diff --git a/resources/views/business/pages/systemization-todos.blade.php b/resources/views/business/pages/systemization-todos.blade.php
index 7d4dfdbc..00687d2f 100644
--- a/resources/views/business/pages/systemization-todos.blade.php
+++ b/resources/views/business/pages/systemization-todos.blade.php
@@ -73,12 +73,11 @@
.sys-todo-grid-value:hover { border-color:#ded4c3; background:#fffdf8; }
.sys-todo-grid-value:focus-visible, .sys-todo-grid-value.is-selected { border-color:var(--sys-gold); background:var(--sys-gold-soft); box-shadow:0 0 0 2px rgba(133,102,50,.16); }
.sys-todo-grid-value.is-editing { position:relative; padding:0; border-color:var(--sys-gold); background:#fff; box-shadow:0 0 0 3px rgba(133,102,50,.18); }
+ .sys-todo-grid-value.is-date-anchor { border-color:var(--sys-gold); background:#fff; box-shadow:0 0 0 3px rgba(133,102,50,.18); }
.sys-todo-grid-value.is-dirty { background:#fff8e8; }
.sys-todo-grid-editor { display:block; box-sizing:border-box; width:100%; min-height:1.9rem; padding:.3rem .4rem; border:0; border-radius:.28rem; background:#fff; color:#171717; font:inherit; font-size:.78rem; line-height:1.5; outline:none; resize:vertical; }
textarea.sys-todo-grid-editor { min-height:4rem; }
- .sys-todo-table-wrap.is-date-picking { overflow:visible; }
- .sys-todo-grid-date-editor { position:absolute; top:0; left:0; z-index:45; display:grid; width:18rem; padding:.55rem; border:1px solid var(--sys-border); border-radius:.55rem; background:#fff; box-shadow:0 6px 18px rgba(23,23,23,.16); gap:.45rem; }
- .sys-todo-grid-date-editor.is-align-right { right:0; left:auto; }
+ .sys-todo-grid-date-editor { position:fixed; top:0; left:0; z-index:45; display:grid; box-sizing:border-box; width:min(18rem,calc(100vw - 1rem)); padding:.55rem; border:1px solid var(--sys-border); border-radius:.55rem; background:#fff; box-shadow:0 6px 18px rgba(23,23,23,.16); gap:.45rem; }
.sys-todo-grid-date-editor .upstream-data-date { width:100%; }
.sys-todo-grid-date-editor .upstream-data-date input { height:2rem; font-size:.75rem; }
.sys-todo-grid-date-editor .upstream-data-date__pick { height:2rem; }
@@ -2691,9 +2690,6 @@
var pending = note === '待定';
var wrapper = document.createElement('div');
wrapper.className = 'sys-todo-grid-date-editor';
- if (cell.getBoundingClientRect().left > window.innerWidth * .62) {
- wrapper.classList.add('is-align-right');
- }
wrapper.innerHTML = ''
+ '
'
+ ''
@@ -2719,6 +2715,7 @@
activeEditor = {
cell: cell,
editor: hiddenValue,
+ wrapper: wrapper,
original: original,
scope: scope,
getValue: function () {
@@ -2729,9 +2726,31 @@
return wrapper.contains(element);
}
};
- cell.classList.add('is-editing');
- cell.replaceChildren(wrapper);
- tableWrap.classList.add('is-date-picking');
+ cell.classList.add('is-date-anchor');
+ wrapper.style.visibility = 'hidden';
+ document.body.appendChild(wrapper);
+
+ function positionFloatingEditor() {
+ if (!wrapper.isConnected) return;
+ var anchor = cell.getBoundingClientRect();
+ var viewportWidth = document.documentElement.clientWidth || window.innerWidth;
+ var viewportHeight = document.documentElement.clientHeight || window.innerHeight;
+ var width = wrapper.offsetWidth;
+ var height = wrapper.offsetHeight;
+ var left = Math.max(8, Math.min(
+ anchor.left + anchor.width / 2 - width / 2,
+ viewportWidth - width - 8
+ ));
+ var below = anchor.bottom + 4;
+ var above = anchor.top - height - 4;
+ var top = below + height <= viewportHeight - 8 ? below : above;
+ top = Math.max(8, Math.min(top, viewportHeight - height - 8));
+ wrapper.style.left = Math.round(left) + 'px';
+ wrapper.style.top = Math.round(top) + 'px';
+ }
+ activeEditor.reposition = positionFloatingEditor;
+ window.addEventListener('scroll', positionFloatingEditor, true);
+ window.addEventListener('resize', positionFloatingEditor);
if (window.CaiWuDatePicker) window.CaiWuDatePicker.setup(wrapper);
function closeAfterChoice() {
@@ -2797,6 +2816,10 @@
window.setTimeout(function () {
dateInput.focus({ preventScroll: true });
dateToggle.click();
+ window.requestAnimationFrame(function () {
+ positionFloatingEditor();
+ wrapper.style.visibility = '';
+ });
}, 0);
}
@@ -2805,8 +2828,14 @@
var current = activeEditor;
activeEditor = null;
var value = current.getValue ? current.getValue() : current.editor.value;
- current.cell.classList.remove('is-editing');
- tableWrap.classList.remove('is-date-picking');
+ current.cell.classList.remove('is-editing', 'is-date-anchor');
+ if (current.reposition) {
+ window.removeEventListener('scroll', current.reposition, true);
+ window.removeEventListener('resize', current.reposition);
+ }
+ if (current.wrapper) {
+ current.wrapper.remove();
+ }
if (!commit || !commitCellValue(current.cell, value, current.scope)) {
renderCell(current.cell, current.original);
return commit === false;
diff --git a/tests/Feature/Business/SystemizationTodosTest.php b/tests/Feature/Business/SystemizationTodosTest.php
index 290e48b9..671f7123 100644
--- a/tests/Feature/Business/SystemizationTodosTest.php
+++ b/tests/Feature/Business/SystemizationTodosTest.php
@@ -89,6 +89,9 @@ class SystemizationTodosTest extends FeatureTestCase
->assertSee("if (field === 'start_date' || field === 'due_date')", false)
->assertSee('sys-todo-grid-date-editor__pending', false)
->assertSee('window.CaiWuDatePicker.setup(wrapper)', false)
+ ->assertSee('document.body.appendChild(wrapper)', false)
+ ->assertSee('anchor.left + anchor.width / 2 - width / 2', false)
+ ->assertDontSee('cell.replaceChildren(wrapper)', false)
->assertSee("if (pendingInput.checked) return '待定'", false)
->assertSee('data-sys-todo-image-prev', false)
->assertSee('data-sys-todo-image-next', false)