dsh-task-ledger 0.0.56 → 0.0.58
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/client.js +148 -58
- package/dist/client.js.map +1 -1
- package/dist/host/services/home.service.d.ts +4 -2
- package/dist/host/services/home.service.js +13 -3
- package/dist/host/types.d.ts +14 -4
- package/package.json +1 -1
- package/skill/README.md +2 -1
- package/skill/SKILL.md +2 -2
- package/skill/package.json +1 -1
- package/skill/references/state-model.md +6 -5
- package/skill/scripts/progress.py +2 -2
package/dist/client.js
CHANGED
|
@@ -202,11 +202,12 @@ window.__ModuleLoader__.load({
|
|
|
202
202
|
finish: false,
|
|
203
203
|
release: false
|
|
204
204
|
};
|
|
205
|
-
/**
|
|
205
|
+
/** 状态档命中(积压 / 超期 / 停滞由 host 标记,前端不判阈值)——只作用于第二区。 */
|
|
206
206
|
function statusHit(task, status) {
|
|
207
207
|
if (status === "all") return true;
|
|
208
208
|
if (status === "active") return task.status === "doing" || task.status === "blocked";
|
|
209
209
|
if (status === "open") return task.status === "open";
|
|
210
|
+
if (status === "backlog") return task.backlog === true;
|
|
210
211
|
if (status === "overdue") return task.overdue === true;
|
|
211
212
|
return task.stale === true;
|
|
212
213
|
}
|
|
@@ -235,7 +236,8 @@ window.__ModuleLoader__.load({
|
|
|
235
236
|
doing: 0,
|
|
236
237
|
open: 0,
|
|
237
238
|
overdue: 0,
|
|
238
|
-
stale: 0
|
|
239
|
+
stale: 0,
|
|
240
|
+
backlog: 0
|
|
239
241
|
}
|
|
240
242
|
};
|
|
241
243
|
const allTasks = board.tasks;
|
|
@@ -244,7 +246,8 @@ window.__ModuleLoader__.load({
|
|
|
244
246
|
doing: allTasks.filter((task) => task.status === "doing").length,
|
|
245
247
|
open: allTasks.filter((task) => task.status === "open").length,
|
|
246
248
|
overdue: allTasks.filter((task) => task.overdue === true).length,
|
|
247
|
-
stale: allTasks.filter((task) => task.stale === true).length
|
|
249
|
+
stale: allTasks.filter((task) => task.stale === true).length,
|
|
250
|
+
backlog: allTasks.filter((task) => task.backlog === true).length
|
|
248
251
|
};
|
|
249
252
|
const mineRows = board.tasks.filter((task) => isMine(task, board)).filter((task) => query.workspace === "" || task.workspace.id === query.workspace).filter((task) => hitKeyword(query.keyword, [
|
|
250
253
|
task.title,
|
|
@@ -280,6 +283,7 @@ window.__ModuleLoader__.load({
|
|
|
280
283
|
doingCount: entry.rows.filter((row) => row.kind === "task" && row.task.status === "doing").length,
|
|
281
284
|
overdueCount: entry.rows.filter((row) => row.kind === "task" && row.task.overdue === true).length,
|
|
282
285
|
staleCount: entry.rows.filter((row) => row.kind === "task" && row.task.stale === true).length,
|
|
286
|
+
backlogCount: entry.rows.filter((row) => row.kind === "task" && row.task.backlog === true).length,
|
|
283
287
|
openCount: entry.rows.filter((row) => row.kind === "task" && row.task.status === "open").length,
|
|
284
288
|
total: entry.rows.length,
|
|
285
289
|
rows: entry.rows.sort(inGroupOrder)
|
|
@@ -374,6 +378,9 @@ body{
|
|
|
374
378
|
/* ⚠️ 宿主是 state-warn(不是 state-warning,后者无此定义) */
|
|
375
379
|
--dtl-warning:var(--dsw-alias-state-warn-primary,#f59e0b);
|
|
376
380
|
--dtl-danger:var(--dsw-alias-state-error-primary,#ec1313);
|
|
381
|
+
/* 超期橙:在「积压黄」与「停滞红」之间再取一档(语义阶梯 灰→黄→橙→红),
|
|
382
|
+
宿主没有现成的橙 token ⇒ 用 warn + error 两色现算,主题一换自动跟随 */
|
|
383
|
+
--dtl-overdue:color-mix(in srgb,var(--dtl-warning) 55%,var(--dtl-danger));
|
|
377
384
|
--dtl-link:var(--dsw-alias-link,#3b5bdb);
|
|
378
385
|
/* 语义色实面上的字(角标 / 实心提示):红绿黄都是中调 ⇒ 白字两个主题都可读 */
|
|
379
386
|
--dtl-on-signal:#fff;
|
|
@@ -660,11 +667,12 @@ body[data-ds-dark-theme]{
|
|
|
660
667
|
/* 「查看」钮在表格行里也要常驻布局(display:none 会不算宽度 ⇒ hover 一出就又把行撑开) */
|
|
661
668
|
.dtl-orow .dtl-viewbtn{display:inline-flex;visibility:hidden;}
|
|
662
669
|
.dtl-orow:hover .dtl-viewbtn{visibility:visible;}
|
|
663
|
-
/* 行首状态圆点:灰=待认领 / 浅蓝=进行中(比「我的」蓝灰一档)/
|
|
670
|
+
/* 行首状态圆点:灰=待认领 / 浅蓝=进行中(比「我的」蓝灰一档)/ 黄=积压 / 橙=超期 / 红=停滞;
|
|
664
671
|
6px(用户 2026-10-18:8px 太大) */
|
|
665
672
|
.dtl-dot{display:inline-block;width:6px;height:6px;flex:none;border-radius:50%;}
|
|
666
673
|
.dtl-dot--doing{background:var(--dtl-business-dim);}
|
|
667
|
-
.dtl-dot--
|
|
674
|
+
.dtl-dot--backlog{background:var(--dtl-warning);}
|
|
675
|
+
.dtl-dot--overdue{background:var(--dtl-overdue);}
|
|
668
676
|
.dtl-dot--stale{background:var(--dtl-danger);}
|
|
669
677
|
.dtl-dot--open,.dtl-dot--closed{background:var(--dtl-fg-3);}
|
|
670
678
|
|
|
@@ -693,7 +701,8 @@ body[data-ds-dark-theme]{
|
|
|
693
701
|
/* 状态条:贴卡片左缘、与正文两行等高的竖向色条(dispatch StatusRail 同款 6×36) */
|
|
694
702
|
.dtl-rail{display:inline-block;width:6px;height:36px;flex:none;border-radius:var(--dtl-radius-xs);}
|
|
695
703
|
.dtl-rail--doing{background:var(--dtl-business);}
|
|
696
|
-
.dtl-rail--
|
|
704
|
+
.dtl-rail--backlog{background:var(--dtl-warning);}
|
|
705
|
+
.dtl-rail--overdue{background:var(--dtl-overdue);}
|
|
697
706
|
.dtl-rail--stale{background:var(--dtl-danger);}
|
|
698
707
|
.dtl-rail--open,.dtl-rail--closed{background:var(--dtl-fg-3);}
|
|
699
708
|
|
|
@@ -720,11 +729,12 @@ body[data-ds-dark-theme]{
|
|
|
720
729
|
background:var(--dtl-chip-bg);color:var(--dtl-fg-3);font-size:10px;line-height:16px;
|
|
721
730
|
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;}
|
|
722
731
|
/* 状态四色 = **实心色块**(用户 2026-10-18:彩色字看不清 ⇒ 改色块 + 反色字):
|
|
723
|
-
待认领灰 / 进行中蓝 /
|
|
732
|
+
待认领灰 / 进行中蓝 / 积压黄 / 超期橙 / 停滞红(与行首圆点同色系)。
|
|
724
733
|
红黄蓝都是中调 ⇒ 白字两个主题都可读;灰块用「字色底 + 面色字」⇒ 明暗自动反过来 */
|
|
725
734
|
.dtl-tag--open{background:var(--dtl-fg-3);color:var(--dtl-surface-1);font-weight:600;}
|
|
726
735
|
.dtl-tag--doing{background:var(--dtl-business);color:var(--dtl-on-signal);font-weight:600;}
|
|
727
|
-
.dtl-tag--
|
|
736
|
+
.dtl-tag--backlog{background:var(--dtl-warning);color:var(--dtl-on-signal);font-weight:600;}
|
|
737
|
+
.dtl-tag--overdue{background:var(--dtl-overdue);color:var(--dtl-on-signal);font-weight:600;}
|
|
728
738
|
.dtl-tag--stale{background:var(--dtl-danger);color:var(--dtl-on-signal);font-weight:600;}
|
|
729
739
|
/* 执行人:浅蓝底(与状态色区分:状态是「事怎么样」,人是「谁在做」) */
|
|
730
740
|
.dtl-tag--person{background:var(--dtl-open-bg-soft);color:var(--dtl-fg-2);}
|
|
@@ -935,11 +945,11 @@ body[data-ds-dark-theme]{
|
|
|
935
945
|
*/
|
|
936
946
|
function Tag(props) {
|
|
937
947
|
ensureUiBase();
|
|
938
|
-
const { text, tone = "neutral", title } = props;
|
|
948
|
+
const { text, tone = "neutral", title, tip } = props;
|
|
939
949
|
const long = displayWidth(text) > TAG_MAX_WIDTH;
|
|
940
950
|
return (0, react.createElement)("span", {
|
|
941
951
|
className: `dtl-tag dtl-tag--${tone}`,
|
|
942
|
-
title: long ? title ?? text : void 0
|
|
952
|
+
title: tip ?? (long ? title ?? text : void 0)
|
|
943
953
|
}, text);
|
|
944
954
|
}
|
|
945
955
|
/** 空态:`guide` = 真空引导卡(虚线),`filtered` = 筛选空小字。 */
|
|
@@ -1082,44 +1092,96 @@ body[data-ds-dark-theme]{
|
|
|
1082
1092
|
* 行 = 一条淡分隔线格:上下居中的状态圆点 + 任务(标题行 + 标签行;**标签行最前是状态标签**)
|
|
1083
1093
|
* + **执行人列**(原状态位,有执行人才摆 `@名字` 标签)+ 最右「@创建人 创建于 年-月-日 时:分:秒」
|
|
1084
1094
|
* (悬停掉时分秒并让位给操作钮)+ 查看。
|
|
1085
|
-
*
|
|
1086
|
-
* 灰=待认领 / 蓝=进行中 /
|
|
1087
|
-
*
|
|
1095
|
+
* 状态一律**标签型、五色**(用户 2026-10-18:原来是一排素字 / pill,现在与人员**位置互换**):
|
|
1096
|
+
* 灰=待认领 / 蓝=进行中 / 黄=积压 / 橙=超期 / 红=停滞;三个异常标签悬停给**配置出来的**
|
|
1097
|
+
* 阈值解释(staleDays / overdueDays / backlogDays 由 host 下发)。圆点颜色同色系。
|
|
1088
1098
|
*
|
|
1089
1099
|
* 按钮(含查看)**不各判各的**:权限一律问 `resolveActions()`(rows.ts),本文件只按返回值画。
|
|
1090
1100
|
*
|
|
1091
1101
|
* 按钮点击行为(含查看)归「任务按钮与会话交接」任务,本文件只做样子与提示。
|
|
1092
1102
|
*/
|
|
1103
|
+
/**
|
|
1104
|
+
* ⚠️ 调试态(用户 2026-10-19):第二区**第一条**把全部状态标签一次摆出来,看全五枚色块。
|
|
1105
|
+
* 定稿后:删掉本常量与 `debugAllTones` 这一路,标签行回到按 `tone` 取一枚。
|
|
1106
|
+
*/
|
|
1107
|
+
const DEBUG_TONES = [
|
|
1108
|
+
"open",
|
|
1109
|
+
"backlog",
|
|
1110
|
+
"doing",
|
|
1111
|
+
"overdue",
|
|
1112
|
+
"stale"
|
|
1113
|
+
];
|
|
1093
1114
|
/** 行标题:在办 = 任务名(缺则任务号);已结案 = 任务包名(缺则「完成了什么」首句)。 */
|
|
1094
1115
|
function titleOf(row) {
|
|
1095
1116
|
if (row.kind === "task") return row.task.title ?? row.task.id;
|
|
1096
1117
|
const title = row.record.workpackage ?? row.record.summary;
|
|
1097
1118
|
return title !== void 0 && title !== "" ? title : row.record.src ?? "—";
|
|
1098
1119
|
}
|
|
1099
|
-
/**
|
|
1120
|
+
/** 状态语义(异常优先:停滞 > 超期 > 积压;三者都是 host 按时间算出来的,不是状态)。 */
|
|
1100
1121
|
function toneOf(row) {
|
|
1101
1122
|
if (row.kind !== "task") return "closed";
|
|
1102
1123
|
if (row.task.stale === true) return "stale";
|
|
1103
|
-
if (row.task.overdue === true) return "
|
|
1124
|
+
if (row.task.overdue === true) return "overdue";
|
|
1125
|
+
if (row.task.backlog === true) return "backlog";
|
|
1104
1126
|
if (row.task.status === "open") return "open";
|
|
1105
1127
|
return "doing";
|
|
1106
1128
|
}
|
|
1107
1129
|
/** 状态文案(已结案没有在办状态 ⇒ 不给标签)。 */
|
|
1108
1130
|
function statusLabel(tone, t) {
|
|
1109
1131
|
if (tone === "stale") return t("statusStale");
|
|
1110
|
-
if (tone === "
|
|
1132
|
+
if (tone === "overdue") return t("statusOverdue");
|
|
1133
|
+
if (tone === "backlog") return t("statusBacklog");
|
|
1111
1134
|
if (tone === "open") return t("statusOpen");
|
|
1112
1135
|
if (tone === "doing") return t("statusActive");
|
|
1113
1136
|
return null;
|
|
1114
1137
|
}
|
|
1115
1138
|
function TaskRowView(props) {
|
|
1116
|
-
const { t, row, variant,
|
|
1139
|
+
const { t, row, variant, board, debugAllTones } = props;
|
|
1117
1140
|
const tone = toneOf(row);
|
|
1118
1141
|
const isTask = row.kind === "task";
|
|
1119
1142
|
const tags = (row.kind === "task" ? row.task.tags : row.record.tags) ?? [];
|
|
1120
1143
|
const created = row.kind === "task" ? row.task.created ?? null : row.record.created ?? null;
|
|
1121
1144
|
const createdDay = created !== null && created !== void 0 && Date.parse(created) >= 0 ? formatDateTime(created).slice(0, 10) : null;
|
|
1122
|
-
const
|
|
1145
|
+
const stamp = (value) => value === null || value === void 0 ? t("timeUnknown") : formatDateTime(value, { fallback: t("timeUnknown") });
|
|
1146
|
+
const dayText = (n) => n === null || n === void 0 ? t("daysNone") : t("daysValue", { n });
|
|
1147
|
+
const detailTip = (which) => {
|
|
1148
|
+
if (row.kind !== "task") return void 0;
|
|
1149
|
+
const { task } = row;
|
|
1150
|
+
const owner = task.owner ?? "";
|
|
1151
|
+
const who = owner === "" ? t("ownerUnclaimed") : `@${owner}`;
|
|
1152
|
+
const started = stamp(task.started ?? task.created);
|
|
1153
|
+
const updated = stamp(task.updated ?? task.started ?? task.created);
|
|
1154
|
+
if (which === "open") return t("tipOpen", { created: stamp(task.created) });
|
|
1155
|
+
if (which === "backlog") return t("tipBacklog", {
|
|
1156
|
+
created: stamp(task.created),
|
|
1157
|
+
d: dayText(task.waitingDays)
|
|
1158
|
+
});
|
|
1159
|
+
if (which === "doing") return t("tipDoing", {
|
|
1160
|
+
who,
|
|
1161
|
+
started,
|
|
1162
|
+
updated
|
|
1163
|
+
});
|
|
1164
|
+
if (which === "overdue") return t("tipOverdue", {
|
|
1165
|
+
who,
|
|
1166
|
+
started,
|
|
1167
|
+
updated,
|
|
1168
|
+
d: dayText(task.ageDays)
|
|
1169
|
+
});
|
|
1170
|
+
return t("tipStale", {
|
|
1171
|
+
who,
|
|
1172
|
+
started,
|
|
1173
|
+
updated,
|
|
1174
|
+
d: dayText(task.idleDays)
|
|
1175
|
+
});
|
|
1176
|
+
};
|
|
1177
|
+
const thresholdTip = (which) => {
|
|
1178
|
+
const stats = board?.stats;
|
|
1179
|
+
if (stats === void 0) return statusLabel(which, t) ?? "";
|
|
1180
|
+
if (which === "backlog") return t("statBacklogTitle", { n: stats.backlogDays });
|
|
1181
|
+
if (which === "overdue") return t("statOverdueTitle", { n: stats.overdueDays });
|
|
1182
|
+
if (which === "stale") return t("statStaleTitle", { n: stats.staleDays });
|
|
1183
|
+
return statusLabel(which, t) ?? "";
|
|
1184
|
+
};
|
|
1123
1185
|
const actions = isTask ? resolveActions(row.task, board) : CLOSED_ACTIONS;
|
|
1124
1186
|
const viewButton = (0, react.createElement)("button", {
|
|
1125
1187
|
type: "button",
|
|
@@ -1147,17 +1209,17 @@ body[data-ds-dark-theme]{
|
|
|
1147
1209
|
className: "dtl-minibtn",
|
|
1148
1210
|
"data-tip": t("tipRelease")
|
|
1149
1211
|
}, t("actionRelease"));
|
|
1150
|
-
const
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1212
|
+
const tagOf = (which, tip) => {
|
|
1213
|
+
const text = statusLabel(which, t) ?? "";
|
|
1214
|
+
return (0, react.createElement)(Tag, {
|
|
1215
|
+
key: which,
|
|
1216
|
+
text,
|
|
1217
|
+
tone: which,
|
|
1218
|
+
tip: tip ?? detailTip(which)
|
|
1219
|
+
});
|
|
1220
|
+
};
|
|
1221
|
+
const statusTag = tone === "closed" ? null : tagOf(tone);
|
|
1222
|
+
const alarmTag = tone === "backlog" || tone === "overdue" || tone === "stale" ? tagOf(tone) : null;
|
|
1161
1223
|
const titleLine = (0, react.createElement)("div", { className: "dtl-taskrow__l1" }, (0, react.createElement)("span", {
|
|
1162
1224
|
className: "dtl-taskrow__title dtl-ellipsis",
|
|
1163
1225
|
title: titleOf(row)
|
|
@@ -1177,7 +1239,7 @@ body[data-ds-dark-theme]{
|
|
|
1177
1239
|
who: String(owner),
|
|
1178
1240
|
when: startedOk ? formatDateTime(String(row.task.started)) : t("timeUnknown")
|
|
1179
1241
|
});
|
|
1180
|
-
const tagLine = (0, react.createElement)("div", { className: "dtl-orow__tags" }, statusTag, tags.map((tag) => (0, react.createElement)(Tag, {
|
|
1242
|
+
const tagLine = (0, react.createElement)("div", { className: "dtl-orow__tags" }, debugAllTones === true ? DEBUG_TONES.map((which) => tagOf(which, thresholdTip(which))) : statusTag, tags.map((tag) => (0, react.createElement)(Tag, {
|
|
1181
1243
|
key: tag,
|
|
1182
1244
|
text: `#${tag}`
|
|
1183
1245
|
})));
|
|
@@ -1375,13 +1437,18 @@ body[data-ds-dark-theme]{
|
|
|
1375
1437
|
className: "dtl-stats",
|
|
1376
1438
|
style: statsRowStyle
|
|
1377
1439
|
}, (0, react.createElement)("div", { className: "dtl-stats__cards" }, card("statMyActive", stats.myActive, t("statMyActiveHint", { n: stats.myOverdue })), card("statOpen", stats.open, t("statOpenHint", { n: days(stats.oldestOpenDays) })), card("statDoing", stats.doing, t("statDoingHint", { n: stats.doing - stats.myActive })), (0, react.createElement)(StatCard, {
|
|
1378
|
-
label: t("
|
|
1379
|
-
value: stats.overdue + stats.stale,
|
|
1380
|
-
hint: t("
|
|
1381
|
-
|
|
1440
|
+
label: t("statAlarm"),
|
|
1441
|
+
value: stats.backlog + stats.overdue + stats.stale,
|
|
1442
|
+
hint: t("statAlarmSplit", {
|
|
1443
|
+
backlog: stats.backlog,
|
|
1444
|
+
overdue: stats.overdue,
|
|
1382
1445
|
stale: stats.stale
|
|
1383
1446
|
}),
|
|
1384
|
-
title:
|
|
1447
|
+
title: [
|
|
1448
|
+
t("statBacklogTitle", { n: stats.backlogDays }),
|
|
1449
|
+
t("statOverdueTitle", { n: stats.overdueDays }),
|
|
1450
|
+
t("statStaleTitle", { n: stats.staleDays })
|
|
1451
|
+
].join(";"),
|
|
1385
1452
|
interactive: false
|
|
1386
1453
|
}), periodCard("statWeekDone", periods?.thisWeek), periodCard("statLastWeekDone", periods?.lastWeek), periodCard("statMonthDone", periods?.thisMonth), periodCard("statLastMonthDone", periods?.lastMonth)), (0, react.createElement)("div", {
|
|
1387
1454
|
className: "dtl-card",
|
|
@@ -1482,7 +1549,6 @@ body[data-ds-dark-theme]{
|
|
|
1482
1549
|
t,
|
|
1483
1550
|
row,
|
|
1484
1551
|
variant: "mine",
|
|
1485
|
-
staleDays: board?.stats.staleDays ?? null,
|
|
1486
1552
|
board
|
|
1487
1553
|
})), (0, react.createElement)("div", null, (0, react.createElement)("div", { style: regionHeadRowStyle }, (0, react.createElement)("span", { style: {
|
|
1488
1554
|
color: "var(--dtl-fg-3)",
|
|
@@ -1511,9 +1577,14 @@ body[data-ds-dark-theme]{
|
|
|
1511
1577
|
label: t("statusOpen"),
|
|
1512
1578
|
badge: orZero(view.allCounts.open)
|
|
1513
1579
|
},
|
|
1580
|
+
{
|
|
1581
|
+
value: "backlog",
|
|
1582
|
+
label: t("statusBacklog"),
|
|
1583
|
+
badge: orZero(view.allCounts.backlog)
|
|
1584
|
+
},
|
|
1514
1585
|
{
|
|
1515
1586
|
value: "overdue",
|
|
1516
|
-
label: t("
|
|
1587
|
+
label: t("statusOverdue"),
|
|
1517
1588
|
badge: orZero(view.allCounts.overdue)
|
|
1518
1589
|
},
|
|
1519
1590
|
{
|
|
@@ -1550,12 +1621,12 @@ body[data-ds-dark-theme]{
|
|
|
1550
1621
|
variant: "primary",
|
|
1551
1622
|
size: "md",
|
|
1552
1623
|
onClick: onBack
|
|
1553
|
-
}, t("allEmptyAction"))) : (0, react.createElement)("div", { style: { marginTop: "var(--dtl-space-2)" } }, view.groups.map((group) => (0, react.createElement)(WorkspaceGroupView, {
|
|
1624
|
+
}, t("allEmptyAction"))) : (0, react.createElement)("div", { style: { marginTop: "var(--dtl-space-2)" } }, view.groups.map((group, index) => (0, react.createElement)(WorkspaceGroupView, {
|
|
1554
1625
|
key: group.workspaceId,
|
|
1555
1626
|
t,
|
|
1556
1627
|
group,
|
|
1557
|
-
|
|
1558
|
-
|
|
1628
|
+
board,
|
|
1629
|
+
debugFirstRow: index === 0
|
|
1559
1630
|
})))))))));
|
|
1560
1631
|
}
|
|
1561
1632
|
/** 角标:>0 才给数字,0 = undefined(不标)。 */
|
|
@@ -1564,15 +1635,16 @@ body[data-ds-dark-theme]{
|
|
|
1564
1635
|
}
|
|
1565
1636
|
/** 一个工作区分组(全部待办表格段):段头(点+名+统计)→ 列头行 → 任务行。
|
|
1566
1637
|
* 统计口径(用户 2026-10-18):共 N|待办 N|进行中 N 常显(0 也显);
|
|
1567
|
-
*
|
|
1638
|
+
* 积压 / 超期 / 停滞**只在 >0 时出现**。 */
|
|
1568
1639
|
function WorkspaceGroupView(props) {
|
|
1569
|
-
const { t, group,
|
|
1640
|
+
const { t, group, board, debugFirstRow } = props;
|
|
1570
1641
|
const [open, setOpen] = (0, react.useState)(group.rows.length <= GROUP_COLLAPSE_OVER);
|
|
1571
1642
|
const stats = [
|
|
1572
1643
|
t("groupTotal", { n: group.total }),
|
|
1573
1644
|
t("groupOpen", { n: group.openCount }),
|
|
1574
1645
|
t("groupDoing", { n: group.doingCount }),
|
|
1575
|
-
...group.
|
|
1646
|
+
...group.backlogCount > 0 ? [t("groupBacklog", { n: group.backlogCount })] : [],
|
|
1647
|
+
...group.overdueCount > 0 ? [t("groupOverdue", { n: group.overdueCount })] : [],
|
|
1576
1648
|
...group.staleCount > 0 ? [t("groupStale", { n: group.staleCount })] : []
|
|
1577
1649
|
].join(" | ");
|
|
1578
1650
|
return (0, react.createElement)("div", { className: "dtl-group" }, (0, react.createElement)("button", {
|
|
@@ -1587,13 +1659,13 @@ body[data-ds-dark-theme]{
|
|
|
1587
1659
|
display: "inline-flex",
|
|
1588
1660
|
flex: "none",
|
|
1589
1661
|
color: "var(--dtl-fg-3)"
|
|
1590
|
-
} }, (0, react.createElement)(open ? _deepseek_ai_dsh_client_ui_primitives.IconFolderOpenRegular : _deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 14 })), (0, react.createElement)("span", { className: "dtl-group__name dtl-ellipsis" }, group.title), (0, react.createElement)("span", { style: { flex: "1 1 auto" } }), (0, react.createElement)("span", { className: "dtl-group__stats" }, stats)), open ? (0, react.createElement)("div", null, group.rows.map((row) => (0, react.createElement)(TaskRowView, {
|
|
1662
|
+
} }, (0, react.createElement)(open ? _deepseek_ai_dsh_client_ui_primitives.IconFolderOpenRegular : _deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 14 })), (0, react.createElement)("span", { className: "dtl-group__name dtl-ellipsis" }, group.title), (0, react.createElement)("span", { style: { flex: "1 1 auto" } }), (0, react.createElement)("span", { className: "dtl-group__stats" }, stats)), open ? (0, react.createElement)("div", null, group.rows.map((row, index) => (0, react.createElement)(TaskRowView, {
|
|
1591
1663
|
key: row.key,
|
|
1592
1664
|
t,
|
|
1593
1665
|
row,
|
|
1594
1666
|
variant: "others",
|
|
1595
|
-
|
|
1596
|
-
|
|
1667
|
+
board,
|
|
1668
|
+
debugAllTones: debugFirstRow === true && index === 0
|
|
1597
1669
|
}))) : null);
|
|
1598
1670
|
}
|
|
1599
1671
|
//#endregion
|
|
@@ -1613,16 +1685,18 @@ body[data-ds-dark-theme]{
|
|
|
1613
1685
|
degradedItem: "{title}:{message}",
|
|
1614
1686
|
statsPlaceholder: "统计报表尚未开建(另立任务):这里以后放分类分布、按人完成数、时间线。",
|
|
1615
1687
|
statMyActive: "我的待办",
|
|
1616
|
-
statMyActiveHint: "
|
|
1688
|
+
statMyActiveHint: "超期 {n} 条",
|
|
1617
1689
|
statOpen: "待认领",
|
|
1618
1690
|
statOpenHint: "最长未认领 {n}",
|
|
1619
1691
|
statDoing: "进行中",
|
|
1620
1692
|
statDoingHint: "其他成员负责 {n} 条",
|
|
1621
|
-
|
|
1693
|
+
statAlarm: "积压 · 超期 · 停滞",
|
|
1622
1694
|
statStaleWord: "停滞",
|
|
1623
1695
|
statStaleHint: "{n} 条",
|
|
1624
|
-
|
|
1625
|
-
statStaleTitle: "停滞 =
|
|
1696
|
+
statAlarmSplit: "积压 {backlog} | 超期 {overdue} | 停滞 {stale}",
|
|
1697
|
+
statStaleTitle: "停滞 = 进行中满 {n} 天没更新",
|
|
1698
|
+
statOverdueTitle: "超期 = 认领后满 {n} 天还没结案",
|
|
1699
|
+
statBacklogTitle: "积压 = 待认领满 {n} 天没人接",
|
|
1626
1700
|
statWeekDone: "本周完成",
|
|
1627
1701
|
statLastWeekDone: "上周完成",
|
|
1628
1702
|
statMonthDone: "本月完成",
|
|
@@ -1651,8 +1725,14 @@ body[data-ds-dark-theme]{
|
|
|
1651
1725
|
statusAll: "全部",
|
|
1652
1726
|
statusActive: "进行中",
|
|
1653
1727
|
statusOpen: "待认领",
|
|
1654
|
-
|
|
1728
|
+
statusBacklog: "积压",
|
|
1729
|
+
statusOverdue: "超期",
|
|
1655
1730
|
statusStale: "停滞",
|
|
1731
|
+
tipOpen: "任务创建于 {created},尚未有人认领。",
|
|
1732
|
+
tipBacklog: "任务创建于 {created},无人认领已满 {d}。",
|
|
1733
|
+
tipDoing: "{who} 于 {started} 开始执行,最后更新于 {updated}。",
|
|
1734
|
+
tipOverdue: "{who} 于 {started} 开始执行,最后更新于 {updated};任务已开始 {d}。",
|
|
1735
|
+
tipStale: "{who} 于 {started} 开始执行,最后更新于 {updated};已停滞 {d}。",
|
|
1656
1736
|
workspaceLabel: "工作区",
|
|
1657
1737
|
workspaceAll: "全部工作区",
|
|
1658
1738
|
searchPlaceholder: "搜索",
|
|
@@ -1662,7 +1742,8 @@ body[data-ds-dark-theme]{
|
|
|
1662
1742
|
groupTotal: "共 {n} 条",
|
|
1663
1743
|
groupOpen: "待办 {n} 条",
|
|
1664
1744
|
groupDoing: "进行中 {n} 条",
|
|
1665
|
-
|
|
1745
|
+
groupBacklog: "积压 {n} 条",
|
|
1746
|
+
groupOverdue: "超期 {n} 条",
|
|
1666
1747
|
groupStale: "停滞 {n} 条",
|
|
1667
1748
|
colTask: "任务",
|
|
1668
1749
|
colCreator: "创建人",
|
|
@@ -1727,16 +1808,18 @@ body[data-ds-dark-theme]{
|
|
|
1727
1808
|
degradedItem: "{title}: {message}",
|
|
1728
1809
|
statsPlaceholder: "Stats reports are not built yet (separate task): category breakdown, completions by person, timeline.",
|
|
1729
1810
|
statMyActive: "My todos",
|
|
1730
|
-
statMyActiveHint: "
|
|
1811
|
+
statMyActiveHint: "overdue {n}",
|
|
1731
1812
|
statOpen: "Unclaimed",
|
|
1732
1813
|
statOpenHint: "longest unclaimed {n}",
|
|
1733
1814
|
statDoing: "In progress",
|
|
1734
1815
|
statDoingHint: "owned by other members: {n}",
|
|
1735
|
-
|
|
1816
|
+
statAlarm: "Backlog · Overdue · Stale",
|
|
1736
1817
|
statStaleWord: "Stale",
|
|
1737
1818
|
statStaleHint: "{n}",
|
|
1738
|
-
|
|
1739
|
-
statStaleTitle: "stale = active
|
|
1819
|
+
statAlarmSplit: "{backlog} backlog | {overdue} overdue | {stale} stale",
|
|
1820
|
+
statStaleTitle: "stale = active with no update for {n}+ days",
|
|
1821
|
+
statOverdueTitle: "overdue = claimed {n}+ days ago and still open",
|
|
1822
|
+
statBacklogTitle: "backlog = unclaimed for {n}+ days",
|
|
1740
1823
|
statWeekDone: "Done this week",
|
|
1741
1824
|
statLastWeekDone: "Done last week",
|
|
1742
1825
|
statMonthDone: "Done this month",
|
|
@@ -1765,8 +1848,14 @@ body[data-ds-dark-theme]{
|
|
|
1765
1848
|
statusAll: "All",
|
|
1766
1849
|
statusActive: "Active",
|
|
1767
1850
|
statusOpen: "Unclaimed",
|
|
1768
|
-
|
|
1851
|
+
statusBacklog: "Backlog",
|
|
1852
|
+
statusOverdue: "Overdue",
|
|
1769
1853
|
statusStale: "Stale",
|
|
1854
|
+
tipOpen: "Created on {created}; not claimed yet.",
|
|
1855
|
+
tipBacklog: "Created on {created}; unclaimed for {d}.",
|
|
1856
|
+
tipDoing: "{who} started on {started}; last updated {updated}.",
|
|
1857
|
+
tipOverdue: "{who} started on {started}; last updated {updated}; active for {d}.",
|
|
1858
|
+
tipStale: "{who} started on {started}; last updated {updated}; stalled for {d}.",
|
|
1770
1859
|
workspaceLabel: "Workspace",
|
|
1771
1860
|
workspaceAll: "All workspaces",
|
|
1772
1861
|
searchPlaceholder: "Search",
|
|
@@ -1776,7 +1865,8 @@ body[data-ds-dark-theme]{
|
|
|
1776
1865
|
groupTotal: "{n} total",
|
|
1777
1866
|
groupOpen: "{n} open",
|
|
1778
1867
|
groupDoing: "{n} active",
|
|
1779
|
-
|
|
1868
|
+
groupBacklog: "{n} backlog",
|
|
1869
|
+
groupOverdue: "{n} overdue",
|
|
1780
1870
|
groupStale: "{n} stale",
|
|
1781
1871
|
colTask: "Task",
|
|
1782
1872
|
colCreator: "Created by",
|