fix: 统一系统化待办日期显示格式 (#686)
## 目标 统一系统化待办在 Mac、Windows 和不同浏览器中的日期展示,避免原生日期控件格式不一致。 ## 实际改动 - 筛选区和编辑弹窗改用现有跨浏览器日期选择器组件。 - 日期文本固定显示为 YYYY-MM-DD,日历按钮负责选择日期。 - 保留开始时间、完成时间、待定和原备注逻辑。 - 待定时禁用日历和清除按钮,取消待定后恢复。 ## 验证 - docker exec jiangling_app php artisan test --filter=SystemizationTodosTest --stop-on-failure:14 passed,244 assertions。 - 页面已不再使用原生 type=date 输入框。 - Blade 视图缓存与 git diff --check 通过。 ## 风险 仅调整日期控件展示和交互,不修改日期存储格式、金额口径、权限或数据库结构。 Reviewed-on: #686
This commit is contained in:
parent
2cf75ac10b
commit
4519a0e627
@ -1,4 +1,5 @@
|
||||
<section class="biz-card mt-6 sys-todo-page" aria-label="系统化待办">
|
||||
@include('business.pages.partials.date-range-picker')
|
||||
<style>
|
||||
.sys-todo-page { --sys-gold:#856632; --sys-gold-soft:#f7f0de; --sys-border:#d8d2c7; --sys-muted:#666; }
|
||||
.sys-todo-page .biz-card-head { align-items:flex-start; gap:1rem; }
|
||||
@ -128,8 +129,14 @@
|
||||
.sys-todo-field input, .sys-todo-field select { min-height:2.15rem; }
|
||||
.sys-todo-field textarea { min-height:5.5rem; resize:vertical; line-height:1.55; overflow:hidden; }
|
||||
.sys-todo-date-control { display:flex; align-items:center; gap:.45rem; min-width:0; }
|
||||
.sys-todo-date-control input[type="date"] { flex:1 1 auto; min-width:0; }
|
||||
.sys-todo-date-control.is-pending input[type="date"] { background:#f7f0de; color:#777; }
|
||||
.sys-todo-date-picker { flex:1 1 auto; min-width:0; }
|
||||
.sys-todo-date-picker input { padding-right:3.35rem; cursor:pointer; }
|
||||
.sys-todo-date-control.is-pending .sys-todo-date-picker input { background:#f7f0de; color:#777; cursor:not-allowed; }
|
||||
.sys-todo-date-control button:disabled { opacity:.5; cursor:not-allowed; }
|
||||
.sys-todo-filter-date { position:relative; display:flex; flex:1 1 auto; min-width:0; }
|
||||
.sys-todo-filter-date input { padding-right:3.35rem; cursor:pointer; }
|
||||
.sys-todo-filter-date .upstream-data-calendar,
|
||||
.sys-todo-date-picker .upstream-data-calendar { width:min(16.5rem,calc(100vw - 3rem)); }
|
||||
.sys-todo-date-pending { display:inline-flex; flex:0 0 auto; align-items:center; gap:.3rem; min-height:2.15rem; padding:0 .55rem; border:1px solid var(--sys-border); border-radius:.45rem; background:#fcfaf5; color:#51483c; font-size:.75rem; white-space:nowrap; cursor:pointer; }
|
||||
.sys-todo-date-pending input[type="checkbox"] { width:1rem; height:1rem; min-height:0; padding:0; accent-color:var(--sys-gold); }
|
||||
.sys-todo-date-note { color:#856632; font-size:.68rem; line-height:1.4; }
|
||||
@ -305,8 +312,30 @@
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<label>开始时间<input type="date" name="start_date" value="{{ $todoFilters['start_date'] }}"></label>
|
||||
<label>完成时间<input type="date" name="due_date" value="{{ $todoFilters['due_date'] }}"></label>
|
||||
<label>开始时间
|
||||
<span class="upstream-data-date sys-todo-filter-date" data-date-picker>
|
||||
<input type="text" name="start_date" value="{{ $todoFilters['start_date'] }}" readonly autocomplete="off" placeholder="YYYY-MM-DD" aria-label="筛选开始时间" data-date-input>
|
||||
<button type="button" class="upstream-data-date__clear" data-date-clear hidden aria-label="清除筛选开始时间">
|
||||
<span class="material-icons-outlined" aria-hidden="true">close</span>
|
||||
</button>
|
||||
<button type="button" class="upstream-data-date__pick" data-date-toggle aria-label="选择筛选开始时间">
|
||||
<span class="material-icons-outlined" aria-hidden="true">calendar_today</span>
|
||||
</button>
|
||||
<div class="upstream-data-calendar" role="dialog" aria-label="筛选开始时间日历" data-date-calendar hidden></div>
|
||||
</span>
|
||||
</label>
|
||||
<label>完成时间
|
||||
<span class="upstream-data-date sys-todo-filter-date" data-date-picker>
|
||||
<input type="text" name="due_date" value="{{ $todoFilters['due_date'] }}" readonly autocomplete="off" placeholder="YYYY-MM-DD" aria-label="筛选完成时间" data-date-input>
|
||||
<button type="button" class="upstream-data-date__clear" data-date-clear hidden aria-label="清除筛选完成时间">
|
||||
<span class="material-icons-outlined" aria-hidden="true">close</span>
|
||||
</button>
|
||||
<button type="button" class="upstream-data-date__pick" data-date-toggle aria-label="选择筛选完成时间">
|
||||
<span class="material-icons-outlined" aria-hidden="true">calendar_today</span>
|
||||
</button>
|
||||
<div class="upstream-data-calendar" role="dialog" aria-label="筛选完成时间日历" data-date-calendar hidden></div>
|
||||
</span>
|
||||
</label>
|
||||
<label class="sys-todo-filter__keyword">关键词<input type="search" name="keyword" value="{{ $todoFilters['keyword'] }}" placeholder="事项、内容、责任人、进展或备注"></label>
|
||||
<div class="sys-todo-filter__actions">
|
||||
<button type="submit" class="sys-todo-page__button sys-todo-page__button--primary">筛选</button>
|
||||
@ -624,7 +653,16 @@
|
||||
<div class="sys-todo-field sys-todo-field--3">
|
||||
<label for="sysTodoStartDate">开始时间</label>
|
||||
<div class="sys-todo-date-control" data-sys-todo-date-control="start">
|
||||
<input id="sysTodoStartDate" type="date" name="start_date">
|
||||
<span class="upstream-data-date sys-todo-date-picker" data-date-picker>
|
||||
<input id="sysTodoStartDate" type="text" name="start_date" readonly autocomplete="off" placeholder="YYYY-MM-DD" aria-label="开始时间" data-date-input>
|
||||
<button type="button" class="upstream-data-date__clear" data-date-clear data-sys-todo-date-clear="start" hidden aria-label="清除开始时间">
|
||||
<span class="material-icons-outlined" aria-hidden="true">close</span>
|
||||
</button>
|
||||
<button type="button" class="upstream-data-date__pick" data-date-toggle data-sys-todo-date-toggle="start" aria-label="选择开始时间">
|
||||
<span class="material-icons-outlined" aria-hidden="true">calendar_today</span>
|
||||
</button>
|
||||
<div class="upstream-data-calendar" role="dialog" aria-label="开始时间日历" data-date-calendar hidden></div>
|
||||
</span>
|
||||
<label class="sys-todo-date-pending">
|
||||
<input type="checkbox" name="start_pending" value="1" data-sys-todo-date-pending="start">
|
||||
<span>待定</span>
|
||||
@ -636,7 +674,16 @@
|
||||
<div class="sys-todo-field sys-todo-field--3">
|
||||
<label for="sysTodoDueDate">完成时间</label>
|
||||
<div class="sys-todo-date-control" data-sys-todo-date-control="due">
|
||||
<input id="sysTodoDueDate" type="date" name="due_date">
|
||||
<span class="upstream-data-date sys-todo-date-picker" data-date-picker>
|
||||
<input id="sysTodoDueDate" type="text" name="due_date" readonly autocomplete="off" placeholder="YYYY-MM-DD" aria-label="完成时间" data-date-input>
|
||||
<button type="button" class="upstream-data-date__clear" data-date-clear data-sys-todo-date-clear="due" hidden aria-label="清除完成时间">
|
||||
<span class="material-icons-outlined" aria-hidden="true">close</span>
|
||||
</button>
|
||||
<button type="button" class="upstream-data-date__pick" data-date-toggle data-sys-todo-date-toggle="due" aria-label="选择完成时间">
|
||||
<span class="material-icons-outlined" aria-hidden="true">calendar_today</span>
|
||||
</button>
|
||||
<div class="upstream-data-calendar" role="dialog" aria-label="完成时间日历" data-date-calendar hidden></div>
|
||||
</span>
|
||||
<label class="sys-todo-date-pending">
|
||||
<input type="checkbox" name="due_pending" value="1" data-sys-todo-date-pending="due">
|
||||
<span>待定</span>
|
||||
@ -735,6 +782,8 @@
|
||||
(function () {
|
||||
var dialog = document.getElementById('sysTodoDialog');
|
||||
var form = dialog.querySelector('[data-sys-todo-form]');
|
||||
var pageRoot = dialog.closest('.sys-todo-page');
|
||||
if (window.CaiWuDatePicker) window.CaiWuDatePicker.setup(pageRoot || document);
|
||||
var methodInput = dialog.querySelector('[data-sys-todo-method]');
|
||||
var title = document.getElementById('sysTodoDialogTitle');
|
||||
var existing = dialog.querySelector('[data-sys-todo-existing]');
|
||||
@ -763,6 +812,8 @@
|
||||
note: form.querySelector('[data-sys-todo-date-note="start"]'),
|
||||
caption: dialog.querySelector('[data-sys-todo-date-note-caption="start"]'),
|
||||
wrap: dialog.querySelector('[data-sys-todo-date-control="start"]'),
|
||||
toggle: dialog.querySelector('[data-sys-todo-date-toggle="start"]'),
|
||||
clear: dialog.querySelector('[data-sys-todo-date-clear="start"]'),
|
||||
};
|
||||
var dueDateControl = {
|
||||
input: form.querySelector('[name="due_date"]'),
|
||||
@ -770,6 +821,8 @@
|
||||
note: form.querySelector('[data-sys-todo-date-note="due"]'),
|
||||
caption: dialog.querySelector('[data-sys-todo-date-note-caption="due"]'),
|
||||
wrap: dialog.querySelector('[data-sys-todo-date-control="due"]'),
|
||||
toggle: dialog.querySelector('[data-sys-todo-date-toggle="due"]'),
|
||||
clear: dialog.querySelector('[data-sys-todo-date-clear="due"]'),
|
||||
};
|
||||
var positionField = dialog.querySelector('[data-sys-todo-position-field]');
|
||||
var positionSelect = dialog.querySelector('[data-sys-todo-position]');
|
||||
@ -837,6 +890,11 @@
|
||||
}
|
||||
|
||||
function syncDateControl(control, fromToggle) {
|
||||
if (control.toggle) control.toggle.disabled = control.pending.checked;
|
||||
if (control.clear) {
|
||||
control.clear.disabled = control.pending.checked;
|
||||
control.clear.hidden = control.pending.checked || control.input.value === '';
|
||||
}
|
||||
control.wrap.classList.toggle('is-pending', control.pending.checked);
|
||||
if (control.pending.checked) {
|
||||
control.input.value = '';
|
||||
|
||||
@ -41,6 +41,13 @@ class SystemizationTodosTest extends FeatureTestCase
|
||||
->assertSee('data-sys-todo-reset-columns', false)
|
||||
->assertSee('data-sys-todo-date-pending="start"', false)
|
||||
->assertSee('data-sys-todo-date-pending="due"', false)
|
||||
->assertSee('data-sys-todo-date-toggle="start"', false)
|
||||
->assertSee('data-sys-todo-date-clear="due"', false)
|
||||
->assertSee('data-date-picker', false)
|
||||
->assertSee('window.CaiWuDatePicker', false)
|
||||
->assertSee('placeholder="YYYY-MM-DD"', false)
|
||||
->assertDontSee('id="sysTodoStartDate" type="date"', false)
|
||||
->assertDontSee('id="sysTodoDueDate" type="date"', false)
|
||||
->assertSee('name="start_pending"', false)
|
||||
->assertSee('name="due_pending"', false)
|
||||
->assertSee('data-sys-todo-owner-filter', false)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user