dsh-erpbot 0.1.0 → 0.1.1
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/README.md +50 -29
- package/bot-identity.js +246 -0
- package/client.js +2438 -627
- package/cordis.patch.yml +128 -0
- package/docs/README.md +39 -0
- package/docs/acceptance.md +136 -0
- package/docs/architecture.md +161 -0
- package/docs/bot-agents-spec.md +205 -0
- package/docs/bot-collaboration-spec.md +161 -0
- package/docs/data-contract.md +262 -0
- package/docs/mcp-inventory-analysis.md +58 -0
- package/docs/requirements.md +234 -0
- package/index.js +270 -15
- package/package.json +6 -2
- package/scripts/check-bot-identity.mjs +71 -0
- package/scripts/lint-factories.mjs +315 -0
- package/scripts/lint-scopes.mjs +179 -0
- package/scripts/scaffold-bots.mjs +76 -0
- package/scripts/test-manifest.mjs +72 -0
- package/scripts/verify.mjs +159 -0
- package/spec/README.md +299 -0
- package/spec/base-content-spec.md +129 -0
- package/spec/cai-content-spec.md +257 -0
- package/spec/shui-content-spec.md +252 -0
- package/spec/spec-CORE.md +155 -0
- package/spec/tui-content-spec.md +259 -0
- package/spec/zi-content-spec.md +256 -0
- package/src/assistant/index.js +389 -4
- package/src/bot-data.js +25 -13
- package/src/bundle.json +1 -0
- package/src/cards/index.js +18 -4
- package/src/dashboard/index.js +65 -25
- package/src/entry.js +7 -7
- package/src/i18n/index.js +80 -60
- package/src/mount.js +19 -2
- package/src/nav.js +7 -5
- package/src/pages-data.js +29 -262
- package/src/shell/index.js +57 -33
- package/src/styles.js +396 -78
- package/src/workbench/index.js +1297 -85
package/src/dashboard/index.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* ===================================================================== */
|
|
9
9
|
|
|
10
10
|
function createDashboard(deps) {
|
|
11
|
-
const { React, h, t, L, readLang, setLang, LANGS, SHORT_LOCALE, LANG_BADGE, useChatState, chatTone, drawOverview, CARDS, CARD_AUTO_MS, DONUT_ARCS, EXPENSE_LEGEND, TRANSACTIONS, nextUid, NAV, Icon, Spark, TxTile } = deps
|
|
11
|
+
const { React, h, t, L, readLang, setLang, LANGS, SHORT_LOCALE, LANG_BADGE, useChatState, useChatBusy, chatTone, drawOverview, CARDS, CARD_AUTO_MS, DONUT_ARCS, EXPENSE_LEGEND, TRANSACTIONS, nextUid, NAV, Icon, Spark, TxTile } = deps
|
|
12
12
|
|
|
13
13
|
/* =====================================================================
|
|
14
14
|
* SECTIONS
|
|
@@ -67,46 +67,86 @@
|
|
|
67
67
|
|
|
68
68
|
const RAIL_LABEL = {
|
|
69
69
|
overview: { zh: '总览', en: 'Overview' },
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
finance: { zh: '账房 · 财', en: 'The Ledger · Books' },
|
|
71
|
+
funds: { zh: '司库 · 资', en: 'The Treasurer · Funds' },
|
|
72
|
+
forecast: { zh: '军师 · 推', en: 'The Planner · Forecast' },
|
|
73
|
+
tax: { zh: '税官 · 税', en: 'The Tax Officer · Tax' },
|
|
74
|
+
team: { zh: '团队模式', en: 'Team mode' },
|
|
74
75
|
base: { zh: '底座 · MCP 与数据', en: 'Base · MCP and Data' },
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
/**
|
|
78
|
-
* Rail-top brand
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
79
|
+
* Rail-top brand avatar: the erpBot identity lockup at the head of the
|
|
80
|
+
* nav column. Three nested discs — a gradient ring, a board-coloured gap
|
|
81
|
+
* and the gradient face — so the brand separates from the flat single-
|
|
82
|
+
* layer buttons below it by STRUCTURE rather than by being a second
|
|
83
|
+
* saturated block that competes with the active page.
|
|
84
|
+
*
|
|
85
|
+
* The whole thing is sized off `--erp-rail-btn`, so it stays inside the
|
|
86
|
+
* rail's existing content width and rescales at every breakpoint without
|
|
87
|
+
* a single extra media query. Footprint 46px against the 54px content
|
|
88
|
+
* box: 4px of air on each side.
|
|
89
|
+
*
|
|
90
|
+
* The status dot aggregates the four bots into one boolean via
|
|
91
|
+
* `useChatBusy` (amber while any bot is mid-flight, green else), so the
|
|
92
|
+
* avatar never needs a per-bot hook loop. Decorative for assistive tech —
|
|
93
|
+
* the button label already names the tile.
|
|
82
94
|
*/
|
|
83
|
-
function
|
|
84
|
-
|
|
95
|
+
function BrandAvatar(props) {
|
|
96
|
+
const busy = useChatBusy()
|
|
97
|
+
const tone = busy ? 'busy' : 'on'
|
|
98
|
+
const label = t('brand.name')
|
|
99
|
+
const goHome = L(RAIL_LABEL.overview)
|
|
100
|
+
return h('div', { className: 'rail-brand-slot' },
|
|
101
|
+
h('button', {
|
|
102
|
+
type: 'button',
|
|
103
|
+
className: 'brand-av',
|
|
104
|
+
title: label + ' · ' + goHome,
|
|
105
|
+
'aria-label': label + ' · ' + goHome,
|
|
106
|
+
onClick: () => props.onNav('overview'),
|
|
107
|
+
},
|
|
108
|
+
h('span', { className: 'brand-av-gap' },
|
|
109
|
+
h('span', { className: 'brand-av-face', 'aria-hidden': 'true' }, 'B')),
|
|
110
|
+
h('i', { className: 'brand-dot ' + tone, 'aria-hidden': 'true' })))
|
|
85
111
|
}
|
|
86
112
|
|
|
87
113
|
/**
|
|
88
|
-
* Left rail: the
|
|
114
|
+
* Left rail: the brand avatar at the top-left corner, the grouped page
|
|
89
115
|
* icons, then the bottom lockup — the erpBot wordmark with the 中 / EN
|
|
90
116
|
* switch directly beneath it, so the language lives at the panel's
|
|
91
117
|
* bottom-left corner.
|
|
118
|
+
*
|
|
119
|
+
* The avatar sits OUTSIDE `.rail-group` on purpose. Inside it, the brand
|
|
120
|
+
* was the group's first item: same white card, same rhythm as the page
|
|
121
|
+
* buttons, which made it read as "the 0th navigation item" rather than
|
|
122
|
+
* as the product's identity. Pulling it out is what fixes the semantics;
|
|
123
|
+
* the ring is what makes the two read as different things.
|
|
92
124
|
*/
|
|
93
125
|
function Rail(props) {
|
|
94
126
|
const navActive = props.page
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
127
|
+
/* `base` opens the infrastructure group, so a hairline separates it from
|
|
128
|
+
the business pages above (总览 + 四个 Bot + 团队). Without it the last
|
|
129
|
+
two entries read as one flat list and the difference in kind between
|
|
130
|
+
"a working page" and "the MCP/data foundation" is invisible. */
|
|
131
|
+
const primary = []
|
|
132
|
+
NAV.forEach((item) => {
|
|
133
|
+
if (item.id === 'base') {
|
|
134
|
+
primary.push(h('span', { className: 'rail-sep', key: 'sep-base', 'aria-hidden': 'true' }))
|
|
135
|
+
}
|
|
136
|
+
primary.push(h('button', {
|
|
137
|
+
key: item.id,
|
|
138
|
+
type: 'button',
|
|
139
|
+
className: 'rail-btn' + (navActive === item.id ? ' active' : ''),
|
|
140
|
+
title: L(RAIL_LABEL[item.id] || { zh: item.id, en: item.id }),
|
|
141
|
+
'aria-label': L(RAIL_LABEL[item.id] || { zh: item.id, en: item.id }),
|
|
142
|
+
'aria-current': navActive === item.id ? 'page' : 'false',
|
|
143
|
+
onClick: () => props.onNav(item.id),
|
|
144
|
+
}, h(Icon, { name: item.icon })))
|
|
145
|
+
})
|
|
104
146
|
|
|
105
147
|
return h('aside', { className: 't1-rail' },
|
|
106
|
-
h(
|
|
107
|
-
|
|
108
|
-
h(RailMark)),
|
|
109
|
-
primary),
|
|
148
|
+
h(BrandAvatar, { onNav: props.onNav }),
|
|
149
|
+
h('div', { className: 'rail-group' }, primary),
|
|
110
150
|
h('div', { className: 'rail-spacer' }),
|
|
111
151
|
h('div', { className: 'rail-foot' },
|
|
112
152
|
h('div', { className: 'rail-brand' },
|
package/src/entry.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/* =====================================================================
|
|
2
2
|
* ENTRY — 唯一接线点。按拓扑序实例化 7 个板块工厂,把符号解构到 factory
|
|
3
3
|
* 作用域。bot-data 片段在此之前已声明 BOT_IDS / BOTS / PLATFORM_SKILLS /
|
|
4
|
-
* SKILL_IDS,由 deps 显式注入到需要的工厂。
|
|
4
|
+
* SKILL_IDS / SKILL_DEPS,由 deps 显式注入到需要的工厂。
|
|
5
5
|
* ===================================================================== */
|
|
6
6
|
|
|
7
7
|
const i18n = createI18n()
|
|
8
8
|
const chart = createChart({ SVG_NS, t: i18n.t })
|
|
9
9
|
|
|
10
10
|
const assistant = createAssistant({ React, h, t: i18n.t, readLang: i18n.readLang, chatBots: BOT_IDS })
|
|
11
|
-
const cards = createCards({ React, h, t: i18n.t, metricLabel, metricSub, PAGES, Icon, Spark, drawTrend: chart.drawTrend })
|
|
12
|
-
const dashboard = createDashboard({ React, h, t: i18n.t, L: i18n.L, readLang: i18n.readLang, setLang: i18n.setLang, LANGS: i18n.LANGS, SHORT_LOCALE: i18n.SHORT_LOCALE, LANG_BADGE: i18n.LANG_BADGE, useChatState: assistant.useChatState, chatTone: assistant.chatTone, drawOverview: chart.drawOverview, CARDS, CARD_AUTO_MS, DONUT_ARCS, EXPENSE_LEGEND, TRANSACTIONS, nextUid, NAV, Icon, Spark, TxTile })
|
|
13
|
-
const workbench = createWorkbench({ React, h, t: i18n.t, L: i18n.L, readLang: i18n.readLang, KpiFigure, compactMoney, metricLabel, metricSub, moneyAmount, Icon, Spark, PAGES, BOTS, useChatState: assistant.useChatState, chatTone: assistant.chatTone, ensureChat: assistant.ensureChat, refreshChat: assistant.refreshChat, switchChatSession: assistant.switchChatSession, newChatSession: assistant.newChatSession, prefillChat: assistant.prefillChat, BotChatSurface: assistant.BotChatSurface })
|
|
14
|
-
const shell = createShell({ React, h, readLang: i18n.readLang, subscribeLang: i18n.subscribeLang, useHostTheme, Rail: dashboard.Rail, CardView: cards.CardView, KpiCard: cards.KpiCard, TodoPage: cards.TodoPage, readHashPage: cards.readHashPage, writeHashPage: cards.writeHashPage, SectionShell: workbench.SectionShell, BotShell: workbench.BotShell, MetricDetailModal, PAGES, ICONS })
|
|
11
|
+
const cards = createCards({ React, h, t: i18n.t, readLang: i18n.readLang, compactMoney, metricLabel, metricSub, PAGES, Icon, Spark, drawTrend: chart.drawTrend })
|
|
12
|
+
const dashboard = createDashboard({ React, h, t: i18n.t, L: i18n.L, readLang: i18n.readLang, setLang: i18n.setLang, LANGS: i18n.LANGS, SHORT_LOCALE: i18n.SHORT_LOCALE, LANG_BADGE: i18n.LANG_BADGE, useChatState: assistant.useChatState, useChatBusy: assistant.useChatBusy, chatTone: assistant.chatTone, drawOverview: chart.drawOverview, CARDS, CARD_AUTO_MS, DONUT_ARCS, EXPENSE_LEGEND, TRANSACTIONS, nextUid, NAV, Icon, Spark, TxTile })
|
|
13
|
+
const workbench = createWorkbench({ React, h, t: i18n.t, L: i18n.L, readLang: i18n.readLang, KpiFigure, compactMoney, metricLabel, metricSub, moneyAmount, Icon, Spark, PAGES, BOTS, SKILL_DEPS, useChatState: assistant.useChatState, chatTone: assistant.chatTone, ensureChat: assistant.ensureChat, ensureTeamChat: assistant.ensureTeamChat, useTeamChat: assistant.useTeamChat, refreshChat: assistant.refreshChat, refreshTeamChat: assistant.refreshTeamChat, switchChatSession: assistant.switchChatSession, newChatSession: assistant.newChatSession, newTeamSession: assistant.newTeamSession, switchTeamSession: assistant.switchTeamSession, prefillChat: assistant.prefillChat, prefillTeamChat: assistant.prefillTeamChat, BotChatSurface: assistant.BotChatSurface, BotTeamSurface: assistant.BotTeamSurface })
|
|
14
|
+
const shell = createShell({ React, h, readLang: i18n.readLang, subscribeLang: i18n.subscribeLang, useHostTheme, Rail: dashboard.Rail, CardView: cards.CardView, KpiCard: cards.KpiCard, TodoPage: cards.TodoPage, readHashPage: cards.readHashPage, writeHashPage: cards.writeHashPage, SectionShell: workbench.SectionShell, BotShell: workbench.BotShell, BaseShell: workbench.BaseShell, TeamShell: workbench.TeamShell, MetricDetailModal, PAGES, ICONS })
|
|
15
15
|
|
|
16
16
|
// 摊回 factory 作用域(mount.js 与横切小片仍按顶层符号名引用)
|
|
17
17
|
const { ZH, EN, t, L, setLang, subscribeLang, readLang } = i18n
|
|
18
18
|
const { mk, smooth, INCOME, EXPENSE, HILITE, drawTrend, drawOverview } = chart
|
|
19
19
|
const { ErpPanel, ErpNavIcon } = shell
|
|
20
|
-
const { ensureChat, refreshChat, primeChats, setAssistantCtx, useChatState, chatTone, BotChatSurface, newChatSession, switchChatSession, prefillChat } = assistant
|
|
20
|
+
const { ensureChat, refreshChat, refreshTeamChat, primeChats, setAssistantCtx, setTeamRemote, useChatState, chatTone, BotChatSurface, newChatSession, switchChatSession, prefillChat } = assistant
|
|
21
21
|
const { KpiCard, CardView, TodoPage, readHashPage, writeHashPage } = cards
|
|
22
22
|
const { TopBar, Rail } = dashboard
|
|
23
|
-
const { SectionShell, BotShell } = workbench
|
|
23
|
+
const { SectionShell, BotShell, BaseShell, TeamShell } = workbench
|
package/src/i18n/index.js
CHANGED
|
@@ -110,6 +110,15 @@
|
|
|
110
110
|
'ai.expand': '展开助手',
|
|
111
111
|
'ai.prompt.insights': '总结一下本月账务的关键异常和待办。',
|
|
112
112
|
'ai.prompt.forecast': '按当前数据预测未来 3 个月现金流,并给出风险点。',
|
|
113
|
+
'team.title': '团队协作',
|
|
114
|
+
'team.role': '账房 · 司库 · 军师 · 税官',
|
|
115
|
+
'team.sub': '共享工作区 · 任务板 · 多 Bot 协作',
|
|
116
|
+
'team.avatar': '团队',
|
|
117
|
+
'team.session': '团队会话',
|
|
118
|
+
'team.greeting': '我是财务团队。月末关账、资金对账、税务申报、现金流预测都可以交给团队;先告诉我这次要做什么?',
|
|
119
|
+
'team.chip.close': '做一次月末关账',
|
|
120
|
+
'team.chip.recon': '对一下银行账户',
|
|
121
|
+
'team.chip.tax': '核一下本期要交的税',
|
|
113
122
|
'ai.prompt.reports': '生成本月经营简报:收入、支出、利润和异常项。',
|
|
114
123
|
'aging.title': '应收账款账龄',
|
|
115
124
|
'aging.totalLabel': '应收合计',
|
|
@@ -131,11 +140,12 @@
|
|
|
131
140
|
'metric.recent': '近 10 个时点',
|
|
132
141
|
'metric.empty': '暂无明细',
|
|
133
142
|
'nav.overview': '总览',
|
|
134
|
-
'nav.
|
|
135
|
-
'nav.
|
|
136
|
-
'nav.
|
|
137
|
-
'nav.
|
|
143
|
+
'nav.finance': '财 · 过去',
|
|
144
|
+
'nav.funds': '资 · 现在',
|
|
145
|
+
'nav.forecast': '推 · 未来',
|
|
146
|
+
'nav.tax': '税 · 税务',
|
|
138
147
|
'nav.base': '底座 · MCP 与数据',
|
|
148
|
+
'nav.team': '团队模式',
|
|
139
149
|
'theme.toDark': '切换到深色',
|
|
140
150
|
'theme.toLight': '切换到浅色',
|
|
141
151
|
'list.empty': '暂无数据',
|
|
@@ -165,15 +175,15 @@
|
|
|
165
175
|
'feed.approvalSub': '18 分钟前',
|
|
166
176
|
'feed.alert': '数据源预警',
|
|
167
177
|
'feed.alertSub': '1 小时前',
|
|
168
|
-
'
|
|
169
|
-
'
|
|
170
|
-
'
|
|
171
|
-
'
|
|
172
|
-
'
|
|
173
|
-
'
|
|
174
|
-
'
|
|
175
|
-
'
|
|
176
|
-
'
|
|
178
|
+
'finance.vouchers': '本期凭证数',
|
|
179
|
+
'finance.vouchersSub': '环比 +6.2%',
|
|
180
|
+
'finance.diff': '借贷差异',
|
|
181
|
+
'finance.diffSub': '差 0 笔',
|
|
182
|
+
'finance.pending': '待处理单据',
|
|
183
|
+
'finance.pendingSub': '较昨日 -12',
|
|
184
|
+
'finance.close': '期末进度',
|
|
185
|
+
'finance.closeSub': '已完成 8 / 12',
|
|
186
|
+
'finance.books': '账务',
|
|
177
187
|
'books.period': '期间与关账',
|
|
178
188
|
'books.periodSub': '2026-11 · 未锁账',
|
|
179
189
|
'books.vouchers': '凭证与分录',
|
|
@@ -182,7 +192,7 @@
|
|
|
182
192
|
'books.ledgerSub': '明细账 / 总账',
|
|
183
193
|
'books.snapshot': '期末镜像',
|
|
184
194
|
'books.snapshotSub': 'ERP 关账状态',
|
|
185
|
-
'
|
|
195
|
+
'finance.reports': '报表',
|
|
186
196
|
'reports.statutory': '法定报表',
|
|
187
197
|
'reports.statutorySub': '资产负债表 / 利润表 / 现金流量表',
|
|
188
198
|
'reports.consol': '合并(占位)',
|
|
@@ -191,29 +201,29 @@
|
|
|
191
201
|
'reports.taxSub': '进项 / 销项',
|
|
192
202
|
'reports.workpaper': '底稿与回执',
|
|
193
203
|
'reports.workpaperSub': '取数链 / 凭据',
|
|
194
|
-
'
|
|
204
|
+
'finance.closeMirror': '期末镜像',
|
|
195
205
|
'close.step1': '关账步骤',
|
|
196
206
|
'close.step1Sub': 'ERP 推进中',
|
|
197
207
|
'close.step2': '锁账',
|
|
198
208
|
'close.step2Sub': '未锁定',
|
|
199
209
|
'close.step3': '重跑',
|
|
200
210
|
'close.step3Sub': '本架构不发起',
|
|
201
|
-
'
|
|
211
|
+
'finance.check': '核对异常',
|
|
202
212
|
'check.recon': '勾稽差异',
|
|
203
213
|
'check.reconSub': '本期',
|
|
204
214
|
'check.cross': '跨表差异',
|
|
205
215
|
'check.crossSub': '待处理',
|
|
206
216
|
'check.miss': '漏账断言',
|
|
207
217
|
'check.missSub': '本期',
|
|
208
|
-
'
|
|
218
|
+
'finance.datasets': '数据集目录',
|
|
209
219
|
'ds.voucher': '凭证与分录',
|
|
210
220
|
'ds.voucherSub': '只读',
|
|
211
221
|
'ds.ledger': '账簿',
|
|
212
222
|
'ds.ledgerSub': '只读',
|
|
213
223
|
'ds.docs': '单据(报销 / 发票 / 合同)',
|
|
214
224
|
'ds.docsSub': '只读',
|
|
215
|
-
'
|
|
216
|
-
'
|
|
225
|
+
'finance.reportsDone': '报表完成',
|
|
226
|
+
'finance.reportsDoneSub': '已出 3 / 4 张',
|
|
217
227
|
'progress.done': '已完成',
|
|
218
228
|
'bars.debit': '借方',
|
|
219
229
|
'bars.credit': '贷方',
|
|
@@ -232,17 +242,17 @@
|
|
|
232
242
|
'focus.time.past': '过去 · 已发生',
|
|
233
243
|
'focus.time.now': '现在 · 在途',
|
|
234
244
|
'focus.time.future': '未来 · 假设',
|
|
235
|
-
'focus.
|
|
236
|
-
'focus.
|
|
237
|
-
'focus.
|
|
238
|
-
'focus.
|
|
239
|
-
'
|
|
240
|
-
'
|
|
241
|
-
'
|
|
242
|
-
'
|
|
243
|
-
'
|
|
244
|
-
'
|
|
245
|
-
'
|
|
245
|
+
'focus.finance.sub': '本期凭证与期末进度',
|
|
246
|
+
'focus.funds.sub': '总余额与未达项',
|
|
247
|
+
'focus.forecast.sub': '预算使用与预测',
|
|
248
|
+
'focus.tax.sub': '票税与申报进度',
|
|
249
|
+
'funds.unreconciled': '未达项',
|
|
250
|
+
'funds.plan': '90 天计划',
|
|
251
|
+
'forecast.revenue': '预测收入',
|
|
252
|
+
'forecast.variance': '与上版差异',
|
|
253
|
+
'tax.output': '销项税额',
|
|
254
|
+
'tax.input': '进项税额',
|
|
255
|
+
'tax.filing': '申报进度',
|
|
246
256
|
'blocks.paused': '已暂停',
|
|
247
257
|
'blocks.open': '打开板块',
|
|
248
258
|
'blocks.unit.vouchers': '凭证',
|
|
@@ -363,6 +373,15 @@
|
|
|
363
373
|
'ai.expand': 'Expand assistant',
|
|
364
374
|
'ai.prompt.insights': 'Summarize this month’s key exceptions and open items.',
|
|
365
375
|
'ai.prompt.forecast': 'Forecast the next three months of cash flow from the current data and list the risks.',
|
|
376
|
+
'team.title': 'Team',
|
|
377
|
+
'team.role': 'Ledger · Treasurer · Planner · Tax Officer',
|
|
378
|
+
'team.sub': 'Shared workspace · task board · multi-bot',
|
|
379
|
+
'team.avatar': 'Team',
|
|
380
|
+
'team.session': 'Team session',
|
|
381
|
+
'team.greeting': 'I am the finance team. Month-end close, bank reconciliation, tax filing, cash-flow forecast — tell me what to do first.',
|
|
382
|
+
'team.chip.close': 'Run a month-end close',
|
|
383
|
+
'team.chip.recon': 'Reconcile the bank accounts',
|
|
384
|
+
'team.chip.tax': 'Check the tax due this period',
|
|
366
385
|
'ai.prompt.reports': 'Draft this month’s operating brief: income, expenses, profit, and exceptions.',
|
|
367
386
|
'aging.title': 'AR aging',
|
|
368
387
|
'aging.totalLabel': 'Outstanding',
|
|
@@ -384,11 +403,12 @@
|
|
|
384
403
|
'metric.recent': 'Last 10 points',
|
|
385
404
|
'metric.empty': 'No details yet',
|
|
386
405
|
'nav.overview': 'Overview',
|
|
387
|
-
'nav.
|
|
388
|
-
'nav.
|
|
389
|
-
'nav.
|
|
390
|
-
'nav.
|
|
406
|
+
'nav.finance': 'Books · Past',
|
|
407
|
+
'nav.funds': 'Funds · Now',
|
|
408
|
+
'nav.forecast': 'Forecast · Future',
|
|
409
|
+
'nav.tax': 'Tax · Filing',
|
|
391
410
|
'nav.base': 'Base · MCP and Data',
|
|
411
|
+
'nav.team': 'Team mode',
|
|
392
412
|
'theme.toDark': 'Switch to dark',
|
|
393
413
|
'theme.toLight': 'Switch to light',
|
|
394
414
|
'list.empty': 'No data',
|
|
@@ -418,15 +438,15 @@
|
|
|
418
438
|
'feed.approvalSub': '18 minutes ago',
|
|
419
439
|
'feed.alert': 'Source alert',
|
|
420
440
|
'feed.alertSub': '1 hour ago',
|
|
421
|
-
'
|
|
422
|
-
'
|
|
423
|
-
'
|
|
424
|
-
'
|
|
425
|
-
'
|
|
426
|
-
'
|
|
427
|
-
'
|
|
428
|
-
'
|
|
429
|
-
'
|
|
441
|
+
'finance.vouchers': 'Vouchers',
|
|
442
|
+
'finance.vouchersSub': '+6.2% MoM',
|
|
443
|
+
'finance.diff': 'Debit-credit diff',
|
|
444
|
+
'finance.diffSub': '0 lines off',
|
|
445
|
+
'finance.pending': 'Pending documents',
|
|
446
|
+
'finance.pendingSub': '-12 vs yesterday',
|
|
447
|
+
'finance.close': 'Period close',
|
|
448
|
+
'finance.closeSub': '8 of 12 done',
|
|
449
|
+
'finance.books': 'Books',
|
|
430
450
|
'books.period': 'Period & close',
|
|
431
451
|
'books.periodSub': '2026-11 · open',
|
|
432
452
|
'books.vouchers': 'Vouchers & lines',
|
|
@@ -435,7 +455,7 @@
|
|
|
435
455
|
'books.ledgerSub': 'Detail / general',
|
|
436
456
|
'books.snapshot': 'Close mirror',
|
|
437
457
|
'books.snapshotSub': 'ERP close status',
|
|
438
|
-
'
|
|
458
|
+
'finance.reports': 'Reports',
|
|
439
459
|
'reports.statutory': 'Statutory reports',
|
|
440
460
|
'reports.statutorySub': 'BS / IS / CF',
|
|
441
461
|
'reports.consol': 'Consolidation (placeholder)',
|
|
@@ -444,29 +464,29 @@
|
|
|
444
464
|
'reports.taxSub': 'Input / output VAT',
|
|
445
465
|
'reports.workpaper': 'Workpapers & receipts',
|
|
446
466
|
'reports.workpaperSub': 'Lineage / credentials',
|
|
447
|
-
'
|
|
467
|
+
'finance.closeMirror': 'Close mirror',
|
|
448
468
|
'close.step1': 'Close steps',
|
|
449
469
|
'close.step1Sub': 'ERP in progress',
|
|
450
470
|
'close.step2': 'Lock',
|
|
451
471
|
'close.step2Sub': 'Not locked',
|
|
452
472
|
'close.step3': 'Rerun',
|
|
453
473
|
'close.step3Sub': 'Not initiated here',
|
|
454
|
-
'
|
|
474
|
+
'finance.check': 'Check exceptions',
|
|
455
475
|
'check.recon': 'Reconciliation diff',
|
|
456
476
|
'check.reconSub': 'This period',
|
|
457
477
|
'check.cross': 'Cross-table diff',
|
|
458
478
|
'check.crossSub': 'Open',
|
|
459
479
|
'check.miss': 'Missing-posting assertion',
|
|
460
480
|
'check.missSub': 'This period',
|
|
461
|
-
'
|
|
481
|
+
'finance.datasets': 'Datasets',
|
|
462
482
|
'ds.voucher': 'Vouchers & lines',
|
|
463
483
|
'ds.voucherSub': 'Read-only',
|
|
464
484
|
'ds.ledger': 'Ledgers',
|
|
465
485
|
'ds.ledgerSub': 'Read-only',
|
|
466
486
|
'ds.docs': 'Documents (expense / invoice / contract)',
|
|
467
487
|
'ds.docsSub': 'Read-only',
|
|
468
|
-
'
|
|
469
|
-
'
|
|
488
|
+
'finance.reportsDone': 'Reports done',
|
|
489
|
+
'finance.reportsDoneSub': '3 of 4 issued',
|
|
470
490
|
'progress.done': 'completed',
|
|
471
491
|
'bars.debit': 'Debit',
|
|
472
492
|
'bars.credit': 'Credit',
|
|
@@ -485,17 +505,17 @@
|
|
|
485
505
|
'focus.time.past': 'Past · booked',
|
|
486
506
|
'focus.time.now': 'Now · in flight',
|
|
487
507
|
'focus.time.future': 'Future · assumed',
|
|
488
|
-
'focus.
|
|
489
|
-
'focus.
|
|
490
|
-
'focus.
|
|
491
|
-
'focus.
|
|
492
|
-
'
|
|
493
|
-
'
|
|
494
|
-
'
|
|
495
|
-
'
|
|
496
|
-
'
|
|
497
|
-
'
|
|
498
|
-
'
|
|
508
|
+
'focus.finance.sub': 'Vouchers & close progress',
|
|
509
|
+
'focus.funds.sub': 'Balance & open items',
|
|
510
|
+
'focus.forecast.sub': 'Budget usage & forecast',
|
|
511
|
+
'focus.tax.sub': 'VAT & filing progress',
|
|
512
|
+
'funds.unreconciled': 'Open items',
|
|
513
|
+
'funds.plan': '90-day plan',
|
|
514
|
+
'forecast.revenue': 'Forecast revenue',
|
|
515
|
+
'forecast.variance': 'Variance vs prior',
|
|
516
|
+
'tax.output': 'Output VAT',
|
|
517
|
+
'tax.input': 'Input VAT',
|
|
518
|
+
'tax.filing': 'Filing progress',
|
|
499
519
|
'blocks.paused': 'Paused',
|
|
500
520
|
'blocks.open': 'Open block',
|
|
501
521
|
'blocks.unit.vouchers': 'vouchers',
|
package/src/mount.js
CHANGED
|
@@ -62,7 +62,13 @@
|
|
|
62
62
|
const sessions = scoped.get('sessions')
|
|
63
63
|
const workspaces = scoped.get('workspaces')
|
|
64
64
|
scoped.effect(() => {
|
|
65
|
-
|
|
65
|
+
/* The team page shares the same stores, so its state must ride the
|
|
66
|
+
same refresh: without it `team.blank` kept the value it had when
|
|
67
|
+
the session was created, and the welcome overlay never left. */
|
|
68
|
+
const refreshAll = () => {
|
|
69
|
+
BOT_IDS.forEach((botId) => refreshChat(botId))
|
|
70
|
+
refreshTeamChat()
|
|
71
|
+
}
|
|
66
72
|
const offSessions = sessions.list.subscribe(refreshAll)
|
|
67
73
|
const offWorkspaces = workspaces.list.subscribe(() => {
|
|
68
74
|
primeChats()
|
|
@@ -78,10 +84,21 @@
|
|
|
78
84
|
ctx.inject(['uiSession'], (scoped) => {
|
|
79
85
|
const uiSession = scoped.get('uiSession')
|
|
80
86
|
scoped.effect(() => {
|
|
81
|
-
const off = uiSession.sessionStatus.subscribe(() =>
|
|
87
|
+
const off = uiSession.sessionStatus.subscribe(() => {
|
|
88
|
+
BOT_IDS.forEach((botId) => refreshChat(botId))
|
|
89
|
+
refreshTeamChat()
|
|
90
|
+
})
|
|
82
91
|
return () => off()
|
|
83
92
|
}, 'dsh-erpbot: chat status subscription')
|
|
84
93
|
})
|
|
94
|
+
/* The team page enables Team mode on its root session through the
|
|
95
|
+
official `remote.agentTeams` namespace. erpbot does not inject the
|
|
96
|
+
whole `remote` service, so this narrow injection hands assistant the
|
|
97
|
+
one namespace it needs (same shape DSH's own agent-team UI uses). */
|
|
98
|
+
ctx.inject(['remote', 'remote.agentTeams'], (scoped) => {
|
|
99
|
+
const agentTeams = scoped.remote !== undefined ? scoped.remote.agentTeams : null
|
|
100
|
+
if (agentTeams !== undefined && agentTeams !== null) setTeamRemote(agentTeams)
|
|
101
|
+
})
|
|
85
102
|
} catch (error) {
|
|
86
103
|
console.error('[dsh-erpbot] chat services unavailable', error)
|
|
87
104
|
}
|
package/src/nav.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
/** Side navigation: 总览 + 四个业务 Bot + 底座(MCP 与数据合一)。
|
|
1
|
+
/** Side navigation: 总览 + 四个业务 Bot + 团队模式 + 底座(MCP 与数据合一)。
|
|
2
|
+
团队模式排在底座之前:底座是「基础设施」类条目,放最后收尾更像栏目边界。 */
|
|
2
3
|
const NAV = [
|
|
3
4
|
{ id: 'overview', icon: 'grid', key: 'nav.overview' },
|
|
4
|
-
{ id: '
|
|
5
|
-
{ id: '
|
|
6
|
-
{ id: '
|
|
7
|
-
{ id: '
|
|
5
|
+
{ id: 'finance', icon: 'doc', key: 'nav.finance' },
|
|
6
|
+
{ id: 'funds', icon: 'wallet', key: 'nav.funds' },
|
|
7
|
+
{ id: 'forecast', icon: 'chart', key: 'nav.forecast' },
|
|
8
|
+
{ id: 'tax', icon: 'list', key: 'nav.tax' },
|
|
9
|
+
{ id: 'team', icon: 'users', key: 'nav.team' },
|
|
8
10
|
{ id: 'base', icon: 'layers', key: 'nav.base' },
|
|
9
11
|
]
|