@qnote/q-ai-note 1.0.17 → 1.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web/app.js +255 -2
- package/dist/web/index.html +33 -0
- package/dist/web/styles.css +107 -0
- package/package.json +1 -1
package/dist/web/app.js
CHANGED
|
@@ -32,6 +32,7 @@ const state = {
|
|
|
32
32
|
nodeEntityFilter: 'all',
|
|
33
33
|
editingNodeEntityId: null,
|
|
34
34
|
nodeEntityFormExpanded: false,
|
|
35
|
+
drawerWorkItemEditMode: false,
|
|
35
36
|
sandboxChatVisible: false,
|
|
36
37
|
sandboxChatVisibleBeforeFullscreen: false,
|
|
37
38
|
sandboxFullscreenMode: false,
|
|
@@ -804,6 +805,9 @@ function applyReadonlyMode() {
|
|
|
804
805
|
closeQuickChatPopover();
|
|
805
806
|
}
|
|
806
807
|
applySandboxChatVisibility();
|
|
808
|
+
if (state.selectedNodeId) {
|
|
809
|
+
renderDrawerWorkItemQuickEdit(state.selectedNodeId);
|
|
810
|
+
}
|
|
807
811
|
if (aserRuntimeView) {
|
|
808
812
|
aserRuntimeView.setAccessContext({
|
|
809
813
|
readonly: state.readonly,
|
|
@@ -1642,6 +1646,147 @@ function renderQuickDiaryTargetLabel() {
|
|
|
1642
1646
|
el.textContent = `快速日记:${state.currentSandbox.name} / ${getWorkItemNameById(nodeId)}`;
|
|
1643
1647
|
}
|
|
1644
1648
|
|
|
1649
|
+
function setDrawerWorkItemQuickEditMode(editing) {
|
|
1650
|
+
state.drawerWorkItemEditMode = Boolean(editing);
|
|
1651
|
+
const readPanel = document.getElementById('drawer-work-item-quick-read');
|
|
1652
|
+
const editPanel = document.getElementById('drawer-work-item-quick-edit');
|
|
1653
|
+
readPanel?.classList.toggle('hidden', state.drawerWorkItemEditMode);
|
|
1654
|
+
editPanel?.classList.toggle('hidden', !state.drawerWorkItemEditMode);
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
function renderDrawerWorkItemQuickRead(row) {
|
|
1658
|
+
const titleEl = document.getElementById('drawer-work-item-read-title');
|
|
1659
|
+
const metaEl = document.getElementById('drawer-work-item-read-meta');
|
|
1660
|
+
const descriptionEl = document.getElementById('drawer-work-item-read-description');
|
|
1661
|
+
if (!(titleEl instanceof HTMLElement) || !(metaEl instanceof HTMLElement) || !(descriptionEl instanceof HTMLElement)) return;
|
|
1662
|
+
if (!row) {
|
|
1663
|
+
titleEl.textContent = '-';
|
|
1664
|
+
metaEl.innerHTML = '';
|
|
1665
|
+
descriptionEl.innerHTML = '';
|
|
1666
|
+
return;
|
|
1667
|
+
}
|
|
1668
|
+
titleEl.textContent = String(row.name || '-');
|
|
1669
|
+
const assignee = String(row.assignee || '').trim() || '-';
|
|
1670
|
+
const status = String(row.status || 'pending').trim() || 'pending';
|
|
1671
|
+
const priority = String(row.priority || 'medium').trim() || 'medium';
|
|
1672
|
+
metaEl.innerHTML = [
|
|
1673
|
+
`<span class="drawer-work-item-read-meta-item">负责人: ${safeText(assignee)}</span>`,
|
|
1674
|
+
`<span class="drawer-work-item-read-meta-item">状态: ${safeText(status)}</span>`,
|
|
1675
|
+
`<span class="drawer-work-item-read-meta-item">优先级: ${safeText(priority)}</span>`,
|
|
1676
|
+
].join('');
|
|
1677
|
+
const description = String(row.description || '').trim();
|
|
1678
|
+
descriptionEl.innerHTML = description
|
|
1679
|
+
? renderMarkdownSnippet(description)
|
|
1680
|
+
: '<div class="empty-state"><p>暂无描述(双击进入编辑)</p></div>';
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
function renderDrawerWorkItemQuickEdit(nodeId) {
|
|
1684
|
+
const nameInput = document.getElementById('drawer-work-item-name');
|
|
1685
|
+
const assigneeInput = document.getElementById('drawer-work-item-assignee');
|
|
1686
|
+
const statusInput = document.getElementById('drawer-work-item-status');
|
|
1687
|
+
const priorityInput = document.getElementById('drawer-work-item-priority');
|
|
1688
|
+
const descriptionInput = document.getElementById('drawer-work-item-description');
|
|
1689
|
+
const saveBtn = document.getElementById('save-drawer-work-item-btn');
|
|
1690
|
+
const dirtyHint = document.getElementById('drawer-work-item-dirty-hint');
|
|
1691
|
+
if (!nameInput || !assigneeInput || !statusInput || !priorityInput || !descriptionInput || !saveBtn || !dirtyHint) return;
|
|
1692
|
+
const row = getNodeById(nodeId);
|
|
1693
|
+
renderDrawerWorkItemQuickRead(row);
|
|
1694
|
+
setDrawerWorkItemQuickEditMode(state.drawerWorkItemEditMode);
|
|
1695
|
+
const canEdit = !state.readonly && state.currentSandboxWritable;
|
|
1696
|
+
if (!row) {
|
|
1697
|
+
nameInput.value = '';
|
|
1698
|
+
assigneeInput.value = '';
|
|
1699
|
+
statusInput.value = 'pending';
|
|
1700
|
+
priorityInput.value = 'medium';
|
|
1701
|
+
descriptionInput.value = '';
|
|
1702
|
+
[nameInput, assigneeInput, statusInput, priorityInput, descriptionInput, saveBtn].forEach((el) => {
|
|
1703
|
+
el.disabled = true;
|
|
1704
|
+
});
|
|
1705
|
+
saveBtn.dataset.original = '';
|
|
1706
|
+
dirtyHint.textContent = '无修改';
|
|
1707
|
+
dirtyHint.classList.remove('dirty');
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1710
|
+
const baseline = {
|
|
1711
|
+
name: String(row.name || '').trim(),
|
|
1712
|
+
assignee: String(row.assignee || '').trim(),
|
|
1713
|
+
status: String(row.status || 'pending').trim() || 'pending',
|
|
1714
|
+
priority: String(row.priority || 'medium').trim() || 'medium',
|
|
1715
|
+
description: String(row.description || '').trim(),
|
|
1716
|
+
};
|
|
1717
|
+
nameInput.value = baseline.name;
|
|
1718
|
+
assigneeInput.value = baseline.assignee;
|
|
1719
|
+
statusInput.value = baseline.status;
|
|
1720
|
+
priorityInput.value = baseline.priority;
|
|
1721
|
+
descriptionInput.value = baseline.description;
|
|
1722
|
+
saveBtn.dataset.original = JSON.stringify(baseline);
|
|
1723
|
+
[nameInput, assigneeInput, statusInput, priorityInput, descriptionInput, saveBtn].forEach((el) => {
|
|
1724
|
+
el.disabled = !canEdit;
|
|
1725
|
+
});
|
|
1726
|
+
if (canEdit) {
|
|
1727
|
+
saveBtn.disabled = true;
|
|
1728
|
+
dirtyHint.textContent = '无修改';
|
|
1729
|
+
dirtyHint.classList.remove('dirty');
|
|
1730
|
+
} else {
|
|
1731
|
+
dirtyHint.textContent = '只读模式';
|
|
1732
|
+
dirtyHint.classList.remove('dirty');
|
|
1733
|
+
setDrawerWorkItemQuickEditMode(false);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
function refreshDrawerWorkItemSaveButtonState() {
|
|
1738
|
+
const nameInput = document.getElementById('drawer-work-item-name');
|
|
1739
|
+
const assigneeInput = document.getElementById('drawer-work-item-assignee');
|
|
1740
|
+
const statusInput = document.getElementById('drawer-work-item-status');
|
|
1741
|
+
const priorityInput = document.getElementById('drawer-work-item-priority');
|
|
1742
|
+
const descriptionInput = document.getElementById('drawer-work-item-description');
|
|
1743
|
+
const saveBtn = document.getElementById('save-drawer-work-item-btn');
|
|
1744
|
+
const dirtyHint = document.getElementById('drawer-work-item-dirty-hint');
|
|
1745
|
+
if (!nameInput || !assigneeInput || !statusInput || !priorityInput || !descriptionInput || !saveBtn || !dirtyHint) return;
|
|
1746
|
+
if (state.readonly || !state.currentSandboxWritable || !state.selectedNodeId) {
|
|
1747
|
+
saveBtn.disabled = true;
|
|
1748
|
+
dirtyHint.textContent = '只读模式';
|
|
1749
|
+
dirtyHint.classList.remove('dirty');
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
const originalRaw = String(saveBtn.dataset.original || '').trim();
|
|
1753
|
+
if (!originalRaw) {
|
|
1754
|
+
saveBtn.disabled = true;
|
|
1755
|
+
dirtyHint.textContent = '无修改';
|
|
1756
|
+
dirtyHint.classList.remove('dirty');
|
|
1757
|
+
return;
|
|
1758
|
+
}
|
|
1759
|
+
let original = null;
|
|
1760
|
+
try {
|
|
1761
|
+
original = JSON.parse(originalRaw);
|
|
1762
|
+
} catch {
|
|
1763
|
+
original = null;
|
|
1764
|
+
}
|
|
1765
|
+
if (!original || typeof original !== 'object') {
|
|
1766
|
+
saveBtn.disabled = true;
|
|
1767
|
+
dirtyHint.textContent = '无修改';
|
|
1768
|
+
dirtyHint.classList.remove('dirty');
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
const current = {
|
|
1772
|
+
name: String(nameInput.value || '').trim(),
|
|
1773
|
+
assignee: String(assigneeInput.value || '').trim(),
|
|
1774
|
+
status: String(statusInput.value || 'pending').trim() || 'pending',
|
|
1775
|
+
priority: String(priorityInput.value || 'medium').trim() || 'medium',
|
|
1776
|
+
description: String(descriptionInput.value || '').trim(),
|
|
1777
|
+
};
|
|
1778
|
+
if (!current.name) {
|
|
1779
|
+
saveBtn.disabled = true;
|
|
1780
|
+
dirtyHint.textContent = '名称不能为空';
|
|
1781
|
+
dirtyHint.classList.add('dirty');
|
|
1782
|
+
return;
|
|
1783
|
+
}
|
|
1784
|
+
const hasChanged = JSON.stringify(current) !== JSON.stringify(original);
|
|
1785
|
+
saveBtn.disabled = !hasChanged;
|
|
1786
|
+
dirtyHint.textContent = hasChanged ? '有未保存修改' : '无修改';
|
|
1787
|
+
dirtyHint.classList.toggle('dirty', hasChanged);
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1645
1790
|
async function saveDiaryEntry({ content, sandboxId = null, workItemId = null }) {
|
|
1646
1791
|
const payload = {
|
|
1647
1792
|
sandbox_id: sandboxId,
|
|
@@ -1763,9 +1908,35 @@ function closeNodeEntityDrawer() {
|
|
|
1763
1908
|
state.nodeEntityFilter = 'all';
|
|
1764
1909
|
state.editingNodeEntityId = null;
|
|
1765
1910
|
state.nodeEntityFormExpanded = false;
|
|
1911
|
+
state.drawerWorkItemEditMode = false;
|
|
1766
1912
|
renderWorkTree();
|
|
1767
1913
|
}
|
|
1768
1914
|
|
|
1915
|
+
function getVisibleTreeSelectNodeIds() {
|
|
1916
|
+
const tree = document.getElementById('work-tree');
|
|
1917
|
+
if (!(tree instanceof HTMLElement)) return [];
|
|
1918
|
+
const seen = new Set();
|
|
1919
|
+
const ids = [];
|
|
1920
|
+
tree.querySelectorAll('[data-select-id]').forEach((el) => {
|
|
1921
|
+
if (!(el instanceof HTMLElement)) return;
|
|
1922
|
+
if (el.offsetParent === null) return;
|
|
1923
|
+
const id = String(el.getAttribute('data-select-id') || '').trim();
|
|
1924
|
+
if (!id || seen.has(id)) return;
|
|
1925
|
+
seen.add(id);
|
|
1926
|
+
ids.push(id);
|
|
1927
|
+
});
|
|
1928
|
+
return ids;
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
function isTypingElement(target) {
|
|
1932
|
+
if (!(target instanceof HTMLElement)) return false;
|
|
1933
|
+
if (target.isContentEditable) return true;
|
|
1934
|
+
if (target instanceof HTMLInputElement) return true;
|
|
1935
|
+
if (target instanceof HTMLTextAreaElement) return true;
|
|
1936
|
+
if (target instanceof HTMLSelectElement) return true;
|
|
1937
|
+
return false;
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1769
1940
|
function setNodeEntityFormExpanded(expanded) {
|
|
1770
1941
|
state.nodeEntityFormExpanded = expanded;
|
|
1771
1942
|
const form = document.getElementById('drawer-create-form');
|
|
@@ -2089,9 +2260,11 @@ function showNodeEntityDrawer(nodeId, preferredFilter = 'all') {
|
|
|
2089
2260
|
const node = getNodeById(nodeId);
|
|
2090
2261
|
if (!drawer || !title || !node) return;
|
|
2091
2262
|
state.selectedNodeId = nodeId;
|
|
2263
|
+
state.drawerWorkItemEditMode = false;
|
|
2092
2264
|
const filter = ['all', 'todo', 'issue', 'knowledge', 'capability', 'diary'].includes(preferredFilter) ? preferredFilter : 'all';
|
|
2093
2265
|
state.nodeEntityFilter = filter;
|
|
2094
2266
|
title.textContent = node.name || nodeId;
|
|
2267
|
+
renderDrawerWorkItemQuickEdit(nodeId);
|
|
2095
2268
|
renderNodeEntitySummary(nodeId);
|
|
2096
2269
|
renderWorkTree();
|
|
2097
2270
|
renderQuickDiaryTargetLabel();
|
|
@@ -3912,6 +4085,26 @@ async function initApp() {
|
|
|
3912
4085
|
document.getElementById('entity-content-input')?.addEventListener('keydown', entitySubmitByShortcut);
|
|
3913
4086
|
|
|
3914
4087
|
document.addEventListener('keydown', (event) => {
|
|
4088
|
+
const drawer = document.getElementById('node-entity-drawer');
|
|
4089
|
+
const isDrawerOpen = Boolean(drawer && !drawer.classList.contains('hidden'));
|
|
4090
|
+
const isArrowKey = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key);
|
|
4091
|
+
if (isDrawerOpen && isArrowKey && !event.metaKey && !event.ctrlKey && !event.altKey && !isTypingElement(event.target)) {
|
|
4092
|
+
const ids = getVisibleTreeSelectNodeIds();
|
|
4093
|
+
if (ids.length > 0) {
|
|
4094
|
+
const currentId = String(state.selectedNodeId || '');
|
|
4095
|
+
const currentIdx = ids.indexOf(currentId);
|
|
4096
|
+
const baseIdx = currentIdx >= 0 ? currentIdx : 0;
|
|
4097
|
+
const offset = (event.key === 'ArrowUp' || event.key === 'ArrowLeft') ? -1 : 1;
|
|
4098
|
+
const nextIdx = Math.max(0, Math.min(ids.length - 1, baseIdx + offset));
|
|
4099
|
+
const nextId = ids[nextIdx];
|
|
4100
|
+
if (nextId && nextId !== currentId) {
|
|
4101
|
+
event.preventDefault();
|
|
4102
|
+
event.stopPropagation();
|
|
4103
|
+
showNodeEntityDrawer(nextId, state.nodeEntityFilter || 'all');
|
|
4104
|
+
return;
|
|
4105
|
+
}
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
3915
4108
|
if (event.key !== 'Escape') return;
|
|
3916
4109
|
if (quickChatPopover) {
|
|
3917
4110
|
event.preventDefault();
|
|
@@ -3919,8 +4112,7 @@ async function initApp() {
|
|
|
3919
4112
|
closeQuickChatPopover();
|
|
3920
4113
|
return;
|
|
3921
4114
|
}
|
|
3922
|
-
|
|
3923
|
-
if (drawer && !drawer.classList.contains('hidden')) {
|
|
4115
|
+
if (isDrawerOpen) {
|
|
3924
4116
|
event.preventDefault();
|
|
3925
4117
|
event.stopPropagation();
|
|
3926
4118
|
closeNodeEntityDrawer();
|
|
@@ -4004,6 +4196,67 @@ async function initApp() {
|
|
|
4004
4196
|
setButtonState(btn, { disabled: false, text: originalText || '保存' });
|
|
4005
4197
|
}
|
|
4006
4198
|
});
|
|
4199
|
+
|
|
4200
|
+
document.getElementById('save-drawer-work-item-btn')?.addEventListener('click', async () => {
|
|
4201
|
+
if (state.readonly || !state.currentSandboxWritable) return;
|
|
4202
|
+
if (!state.currentSandbox || !state.selectedNodeId) return;
|
|
4203
|
+
const nodeId = String(state.selectedNodeId || '');
|
|
4204
|
+
const current = getNodeById(nodeId);
|
|
4205
|
+
if (!current) return;
|
|
4206
|
+
const name = String(document.getElementById('drawer-work-item-name')?.value || '').trim();
|
|
4207
|
+
if (!name) {
|
|
4208
|
+
alert('请输入任务名称');
|
|
4209
|
+
return;
|
|
4210
|
+
}
|
|
4211
|
+
const payload = {
|
|
4212
|
+
name,
|
|
4213
|
+
description: String(document.getElementById('drawer-work-item-description')?.value || '').trim(),
|
|
4214
|
+
assignee: String(document.getElementById('drawer-work-item-assignee')?.value || '').trim(),
|
|
4215
|
+
status: String(document.getElementById('drawer-work-item-status')?.value || 'pending'),
|
|
4216
|
+
priority: String(document.getElementById('drawer-work-item-priority')?.value || 'medium'),
|
|
4217
|
+
parent_id: current.parent_id || null,
|
|
4218
|
+
extra_data: {
|
|
4219
|
+
...(current.extra_data || {}),
|
|
4220
|
+
},
|
|
4221
|
+
};
|
|
4222
|
+
const saveBtn = document.getElementById('save-drawer-work-item-btn');
|
|
4223
|
+
const originalText = saveBtn?.textContent || '保存工作项';
|
|
4224
|
+
if (saveBtn) setButtonState(saveBtn, { disabled: true, text: '保存中...' });
|
|
4225
|
+
try {
|
|
4226
|
+
await apiRequest(`${API_BASE}/items/${nodeId}`, {
|
|
4227
|
+
method: 'PUT',
|
|
4228
|
+
body: JSON.stringify(payload),
|
|
4229
|
+
});
|
|
4230
|
+
const activeFilter = state.nodeEntityFilter || 'all';
|
|
4231
|
+
await loadSandbox(state.currentSandbox.id);
|
|
4232
|
+
showNodeEntityDrawer(nodeId, activeFilter);
|
|
4233
|
+
} finally {
|
|
4234
|
+
if (saveBtn) setButtonState(saveBtn, { disabled: false, text: originalText });
|
|
4235
|
+
refreshDrawerWorkItemSaveButtonState();
|
|
4236
|
+
}
|
|
4237
|
+
});
|
|
4238
|
+
|
|
4239
|
+
const bindDrawerQuickEditDirtyState = (eventName) => {
|
|
4240
|
+
['drawer-work-item-name', 'drawer-work-item-assignee', 'drawer-work-item-status', 'drawer-work-item-priority', 'drawer-work-item-description']
|
|
4241
|
+
.forEach((id) => {
|
|
4242
|
+
document.getElementById(id)?.addEventListener(eventName, refreshDrawerWorkItemSaveButtonState);
|
|
4243
|
+
});
|
|
4244
|
+
};
|
|
4245
|
+
bindDrawerQuickEditDirtyState('input');
|
|
4246
|
+
bindDrawerQuickEditDirtyState('change');
|
|
4247
|
+
|
|
4248
|
+
document.getElementById('drawer-work-item-quick-read')?.addEventListener('dblclick', () => {
|
|
4249
|
+
if (state.readonly || !state.currentSandboxWritable || !state.selectedNodeId) return;
|
|
4250
|
+
setDrawerWorkItemQuickEditMode(true);
|
|
4251
|
+
const nameInput = document.getElementById('drawer-work-item-name');
|
|
4252
|
+
if (nameInput instanceof HTMLInputElement) nameInput.focus();
|
|
4253
|
+
});
|
|
4254
|
+
|
|
4255
|
+
document.getElementById('cancel-drawer-work-item-edit-btn')?.addEventListener('click', () => {
|
|
4256
|
+
if (!state.selectedNodeId) return;
|
|
4257
|
+
state.drawerWorkItemEditMode = false;
|
|
4258
|
+
renderDrawerWorkItemQuickEdit(state.selectedNodeId);
|
|
4259
|
+
});
|
|
4007
4260
|
|
|
4008
4261
|
document.getElementById('rollback-btn')?.addEventListener('click', async () => {
|
|
4009
4262
|
if (state.readonly) return;
|
package/dist/web/index.html
CHANGED
|
@@ -150,6 +150,39 @@
|
|
|
150
150
|
<button class="btn btn-secondary btn-sm" id="close-node-drawer-btn">关闭</button>
|
|
151
151
|
</div>
|
|
152
152
|
</div>
|
|
153
|
+
<section class="drawer-section">
|
|
154
|
+
<div class="drawer-section-title">工作项快速编辑</div>
|
|
155
|
+
<div class="drawer-work-item-quick" id="drawer-work-item-quick">
|
|
156
|
+
<div class="drawer-work-item-quick-read" id="drawer-work-item-quick-read" title="双击进入编辑">
|
|
157
|
+
<div class="drawer-work-item-read-title" id="drawer-work-item-read-title">-</div>
|
|
158
|
+
<div class="drawer-work-item-read-meta" id="drawer-work-item-read-meta"></div>
|
|
159
|
+
<div class="drawer-work-item-read-description diary-content" id="drawer-work-item-read-description"></div>
|
|
160
|
+
</div>
|
|
161
|
+
<div class="drawer-work-item-quick-edit hidden" id="drawer-work-item-quick-edit">
|
|
162
|
+
<div class="drawer-work-item-quick-edit-grid">
|
|
163
|
+
<input type="text" id="drawer-work-item-name" placeholder="工作项名称">
|
|
164
|
+
<input type="text" id="drawer-work-item-assignee" placeholder="负责人(可选)">
|
|
165
|
+
<select id="drawer-work-item-status">
|
|
166
|
+
<option value="pending">待处理</option>
|
|
167
|
+
<option value="in_progress">进行中</option>
|
|
168
|
+
<option value="done">已完成</option>
|
|
169
|
+
<option value="archived">已归档</option>
|
|
170
|
+
</select>
|
|
171
|
+
<select id="drawer-work-item-priority">
|
|
172
|
+
<option value="low">低优先级</option>
|
|
173
|
+
<option value="medium">中优先级</option>
|
|
174
|
+
<option value="high">高优先级</option>
|
|
175
|
+
</select>
|
|
176
|
+
</div>
|
|
177
|
+
<textarea id="drawer-work-item-description" rows="3" placeholder="描述(可选,支持 Markdown)"></textarea>
|
|
178
|
+
<div class="drawer-work-item-quick-edit-actions">
|
|
179
|
+
<span class="drawer-work-item-dirty-hint" id="drawer-work-item-dirty-hint">无修改</span>
|
|
180
|
+
<button class="btn btn-secondary btn-sm" id="cancel-drawer-work-item-edit-btn" type="button">取消编辑</button>
|
|
181
|
+
<button class="btn btn-primary btn-sm" id="save-drawer-work-item-btn" type="button">保存工作项</button>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
</section>
|
|
153
186
|
<section class="drawer-section">
|
|
154
187
|
<div class="drawer-section-title">节点概览</div>
|
|
155
188
|
<div class="summary-strip compact" id="node-entity-summary"></div>
|
package/dist/web/styles.css
CHANGED
|
@@ -3670,6 +3670,113 @@ dialog::backdrop {
|
|
|
3670
3670
|
margin-bottom: 8px;
|
|
3671
3671
|
}
|
|
3672
3672
|
|
|
3673
|
+
.drawer-work-item-quick {
|
|
3674
|
+
display: grid;
|
|
3675
|
+
gap: 8px;
|
|
3676
|
+
}
|
|
3677
|
+
|
|
3678
|
+
.drawer-work-item-quick-read {
|
|
3679
|
+
display: grid;
|
|
3680
|
+
gap: 8px;
|
|
3681
|
+
padding: 10px;
|
|
3682
|
+
background: #fff;
|
|
3683
|
+
border: 1px dashed var(--border);
|
|
3684
|
+
border-radius: 10px;
|
|
3685
|
+
cursor: default;
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3688
|
+
.drawer-work-item-quick-read:hover {
|
|
3689
|
+
border-color: #c7dafc;
|
|
3690
|
+
background: #f8fbff;
|
|
3691
|
+
}
|
|
3692
|
+
|
|
3693
|
+
.drawer-work-item-read-title {
|
|
3694
|
+
font-size: 13px;
|
|
3695
|
+
font-weight: 600;
|
|
3696
|
+
color: var(--text-primary);
|
|
3697
|
+
}
|
|
3698
|
+
|
|
3699
|
+
.drawer-work-item-read-meta {
|
|
3700
|
+
display: flex;
|
|
3701
|
+
flex-wrap: wrap;
|
|
3702
|
+
gap: 6px;
|
|
3703
|
+
}
|
|
3704
|
+
|
|
3705
|
+
.drawer-work-item-read-meta-item {
|
|
3706
|
+
font-size: 12px;
|
|
3707
|
+
color: var(--text-secondary);
|
|
3708
|
+
background: #f3f4f6;
|
|
3709
|
+
border: 1px solid var(--border);
|
|
3710
|
+
border-radius: 999px;
|
|
3711
|
+
padding: 2px 8px;
|
|
3712
|
+
}
|
|
3713
|
+
|
|
3714
|
+
.drawer-work-item-read-description {
|
|
3715
|
+
font-size: 13px;
|
|
3716
|
+
color: var(--text-primary);
|
|
3717
|
+
}
|
|
3718
|
+
|
|
3719
|
+
.drawer-work-item-read-description .empty-state {
|
|
3720
|
+
padding: 6px 0;
|
|
3721
|
+
text-align: left;
|
|
3722
|
+
color: var(--text-secondary);
|
|
3723
|
+
}
|
|
3724
|
+
|
|
3725
|
+
.drawer-work-item-read-description .empty-state p {
|
|
3726
|
+
margin: 0;
|
|
3727
|
+
}
|
|
3728
|
+
|
|
3729
|
+
.drawer-work-item-quick-edit {
|
|
3730
|
+
display: grid;
|
|
3731
|
+
gap: 8px;
|
|
3732
|
+
padding: 10px;
|
|
3733
|
+
background: #f8f9fb;
|
|
3734
|
+
border: 1px solid var(--border);
|
|
3735
|
+
border-radius: 10px;
|
|
3736
|
+
}
|
|
3737
|
+
|
|
3738
|
+
.drawer-work-item-quick-edit.hidden {
|
|
3739
|
+
display: none;
|
|
3740
|
+
}
|
|
3741
|
+
|
|
3742
|
+
.drawer-work-item-quick-edit-grid {
|
|
3743
|
+
display: grid;
|
|
3744
|
+
grid-template-columns: 1fr 1fr;
|
|
3745
|
+
gap: 8px;
|
|
3746
|
+
}
|
|
3747
|
+
|
|
3748
|
+
.drawer-work-item-quick-edit input,
|
|
3749
|
+
.drawer-work-item-quick-edit select,
|
|
3750
|
+
.drawer-work-item-quick-edit textarea {
|
|
3751
|
+
width: 100%;
|
|
3752
|
+
border: 1px solid var(--border);
|
|
3753
|
+
border-radius: 8px;
|
|
3754
|
+
padding: 8px 10px;
|
|
3755
|
+
font-size: 13px;
|
|
3756
|
+
background: #fff;
|
|
3757
|
+
}
|
|
3758
|
+
|
|
3759
|
+
.drawer-work-item-quick-edit-actions {
|
|
3760
|
+
display: flex;
|
|
3761
|
+
align-items: center;
|
|
3762
|
+
justify-content: flex-end;
|
|
3763
|
+
gap: 8px;
|
|
3764
|
+
}
|
|
3765
|
+
|
|
3766
|
+
.drawer-work-item-dirty-hint {
|
|
3767
|
+
font-size: 12px;
|
|
3768
|
+
color: var(--text-secondary);
|
|
3769
|
+
}
|
|
3770
|
+
|
|
3771
|
+
.drawer-work-item-dirty-hint.dirty {
|
|
3772
|
+
color: #92400e;
|
|
3773
|
+
font-weight: 600;
|
|
3774
|
+
background: #fef3c7;
|
|
3775
|
+
border: 1px solid #f59e0b;
|
|
3776
|
+
border-radius: 999px;
|
|
3777
|
+
padding: 2px 8px;
|
|
3778
|
+
}
|
|
3779
|
+
|
|
3673
3780
|
.drawer-create-form {
|
|
3674
3781
|
display: grid;
|
|
3675
3782
|
gap: 8px;
|