| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- const drafts = new Map();
- const scenarios = {
- customer: [['start', '重新体验换货流程'], ['waiting', '等待审批'], ['unknown', '外部受理结果未知'], ['revision', '方案需要修订'], ['generating', '助手正在回复'], ['unavailable', '助手暂时不可用'], ['disconnect', '连接中断 / 恢复'], ['empty', '无订单 / 无工单']],
- staff: [['human', '客户请求人工协助'], ['unknown', '已提交外部申请'], ['revision', '方案需要修订'], ['empty', '队列为空'], ['expired', '店铺权限已撤销']],
- supervisor: [['waiting', '客户已确认,等待审批'], ['self', '申请人为当前主管'], ['stale', '方案版本发生变化'], ['processed', '审批通过后的进度'], ['completed', '履约已完成']],
- merchant: [['merchant', '商家正常配置'], ['billing-reviewer', '切换费用申请 / 审批员工'], ['stale', '配置版本冲突'], ['expired', '当前权限已撤销']],
- platform: [['platform', '平台正常管理'], ['delivery-done', '投递已确认'], ['stale', '额度版本冲突'], ['expired', '当前权限已撤销']],
- };
- function navigate(role, page) {
- const target = screens[`${role}/${page}`];
- if (!target) throw new Error(`Unknown wireframe page: ${role}/${page}`);
- if (page !== 'login' && ['merchant', 'staff', 'supervisor'].includes(role) && role !== merchantRole) { notify('当前员工没有该功能权限。'); return; }
- currentRole = role; currentPage = page;
- const hash = routeUrl(role, page);
- if (location.hash === hash) render(); else location.hash = hash;
- }
- function saveDrafts() {
- const forms = document.querySelectorAll('#product form');
- forms.forEach(element => {
- const values = {};
- for (const input of element.elements) {
- if (!input.name || input.type === 'password') continue;
- values[input.name] = input.type === 'checkbox' ? input.checked : input.value;
- }
- drafts.set(`${currentRole}/${currentPage}/${element.dataset.submit}`, values);
- });
- }
- function restoreDrafts() {
- document.querySelectorAll('#product form').forEach(element => {
- const values = drafts.get(`${currentRole}/${currentPage}/${element.dataset.submit}`);
- if (!values) return;
- for (const input of element.elements) {
- if (!(input.name in values)) continue;
- if (input.type === 'checkbox') input.checked = values[input.name];
- else input.value = values[input.name];
- }
- });
- }
- function render() {
- const product = adminProduct(currentRole);
- if (product && currentPage !== 'login' && !adminAuth[product]) {
- adminReturn[product] = { role: currentRole, page: currentPage };
- currentRole = product; currentPage = 'login';
- history.replaceState(null, '', routeUrl(product, 'login'));
- }
- const screen = screens[`${currentRole}/${currentPage}`];
- document.title = `${screen.code} ${screen.title} · 智服产品线稿`;
- const productRole = ['staff', 'supervisor'].includes(currentRole) ? 'merchant' : currentRole;
- document.getElementById('role-nav').innerHTML = ['customer', 'merchant', 'platform'].map(role => `<button type="button" data-role-home="${role}" ${role === productRole ? 'aria-current="page"' : ''}>${roleLabels[role]}</button>`).join('');
- document.getElementById('merchant-role-controls').hidden = productRole !== 'merchant';
- document.getElementById('merchant-role-nav').innerHTML = [['merchant', '商家管理员'], ['staff', '客服'], ['supervisor', '主管']].map(([role, label]) => `<button type="button" data-employee-role="${role}" ${merchantRole === role ? 'aria-current="page"' : ''}>${label}</button>`).join('');
- document.getElementById('page-nav').innerHTML = Object.values(screens).filter(item => item.role === currentRole).map(item => `<button type="button" data-page="${item.page}" data-role="${item.role}" ${item.page === currentPage ? 'aria-current="page"' : ''}>${item.code} ${item.title}</button>`).join('');
- const availableScenarios = product ? [...scenarios[currentRole], ['login-error', '登录失败'], ['session-expired', '登录会话过期']] : scenarios[currentRole];
- document.getElementById('scenario-nav').innerHTML = availableScenarios.map(([id, label]) => `<button type="button" data-scenario="${id}">${label}</button>`).join('');
- document.getElementById('page-code').textContent = `${screen.code} / ${roleLabels[currentRole]}`;
- document.getElementById('page-title').textContent = screen.title;
- document.getElementById('screen-scope').textContent = currentRole === 'customer' ? '手机页面 · 可点击线稿' : '桌面页面 · 可点击线稿';
- document.getElementById('notice').textContent = notice;
- document.getElementById('product').innerHTML = `${product && currentPage !== 'login' ? `<div class="admin-session"><span>已登录 · ${roleLabels[currentRole]}</span>${product === 'merchant' && !state.expired ? link(`消息通知(${unreadCount()})`, 'notifications') : ''}${button('退出登录', 'admin-logout')}</div>` : ''}${state.expired && currentPage !== 'login' ? desktop(`${hint('当前店铺权限已失效,内容已停止显示。未提交文字保留。')}${button('演示重新取得有效授权', 'restore-access')}`) : screen.render()}`;
- document.getElementById('notes').innerHTML = `<ul>${screen.notes.map(item => `<li>${item}</li>`).join('')}</ul>`;
- restoreDrafts();
- }
- function notify(message) { notice = message; render(); }
- function checkAccess() {
- if (state.expired) { notify('当前权限已失效,请重新取得授权。'); return false; }
- if (state.stale) { notify('内容已被其他操作更新,请重新读取后检查并提交。'); return false; }
- return true;
- }
- function loginRequired() {
- if (currentRole === 'customer' && !state.loggedIn) {
- state.returnPage = currentPage; notice = '请登录当前商家账户后继续。'; navigate('customer', 'login'); return true;
- }
- return false;
- }
- function createProposal(data) {
- if (loginRequired() || !checkAccess()) return;
- if (currentRole === 'staff' && state.owner !== 'HUMAN') { notify('请先接管会话。'); return; }
- if (!canCreate() && !canRevise()) { notify('当前状态无法修改方案,请查看已有工单。'); return; }
- if (state.blocked || !state.ruleActive) { notify('适用条件已经变化,无法生成方案。请查看规则或申请人工协助。'); return; }
- const reason = data.get('reason').trim();
- if (!reason || Number(data.get('quantity')) !== 1) { notify('请填写故障描述,申请数量必须为 1。'); return; }
- if (state.ticket !== 'NONE') state.version += 1;
- state.reason = reason; state.quantity = 1; state.ticket = 'DRAFT'; state.customerConfirmed = false;
- state.proposalRuleVersion = state.ruleVersion; state.proposalRuleDays = state.ruleDays;
- drafts.delete('customer/proposal/confirm-proposal');
- record(`方案 V${state.version} 已保存,等待客户本人确认。`);
- notice = currentRole === 'staff' ? '已保存待确认方案。通过购物商城入口检查客户确认页面。' : '请检查方案,再确认提交。';
- navigate(currentRole, currentRole === 'staff' ? 'ticket' : 'proposal');
- }
- // 每个表单都在本地演示相应结果;不发送网络请求,不产生业务侧写入。
- const submissions = {
- 'merchant-login'(data) { completeAdminLogin('merchant', data); },
- 'platform-login'(data) { completeAdminLogin('platform', data); },
- login(data) { state.loggedIn = true; notice = '已进入客户 A01 的线稿身份。'; navigate('customer', state.returnPage); },
- 'customer-message'(data) {
- if (loginRequired() || !checkAccess()) return;
- if (!state.connected) { notify('连接中断,消息保留在输入框。'); return; }
- const text = data.get('message').trim();
- if (!text) { notify('请填写消息内容。'); return; }
- state.messages.push({ sender: '客户', text });
- if (state.owner === 'HUMAN') markNotificationNew('staff-message');
- if (state.owner === 'AGENT' && !state.blocked) state.messages.push({ sender: '智能助手 · 设计示例', text: '请通过“选择订单”确认需要处理的商品,并填写故障描述。' });
- drafts.delete('customer/chat/customer-message');
- notify(state.owner === 'HUMAN' ? '消息已显示在客服会话中。' : '消息已加入本次咨询线稿。');
- },
- 'staff-message'(data) {
- if (!checkAccess() || state.owner !== 'HUMAN') { notify('只有当前接管客服可以回复。'); return; }
- const text = data.get('message').trim();
- if (!text) { notify('请填写回复内容。'); return; }
- state.messages.push({ sender: '客服王芳', text }); drafts.delete('staff/conversation/staff-message'); notify('回复已同步到消费者咨询页面。');
- },
- proposal: createProposal,
- 'confirm-proposal'() {
- if (loginRequired() || !checkAccess()) return;
- if (state.ticket !== 'DRAFT') { notify('当前方案已处理,请查看最新进度。'); return; }
- state.customerConfirmed = true; state.ticket = 'WAITING_REVIEW'; record(`客户 A01 确认方案 V${state.version},创建主管审批任务。`);
- markNotificationNew('supervisor-review');
- notice = '方案已提交审批。商家后台具有审批权限的员工可以处理。'; navigate('customer', 'ticket');
- },
- approval(data) {
- if (!checkAccess()) return;
- if (state.selfApproval || state.ticket !== 'WAITING_REVIEW' || !state.customerConfirmed) { notify('当前申请不满足审批条件。'); return; }
- const reason = data.get('reason').trim();
- if (!reason) { notify('请填写审批意见。'); return; }
- const approved = data.get('decision') === '批准';
- confirmAction('确认提交审批决定', `对方案 V${state.version} 作出“${approved ? '批准' : '拒绝'}”决定。意见:${reason}`, () => {
- state.ticket = approved ? 'APPROVED' : 'REJECTED'; state.formValues.approvalReason = reason;
- record(`主管李明${approved ? '批准' : '拒绝'}方案 V${state.version}:${reason}`);
- notice = '决定已记录,可通过消费者入口查看进度。'; navigate('supervisor', 'history');
- });
- },
- memory(data) {
- if (loginRequired() || !checkAccess()) return;
- if (!state.memoryConsent) { notify('请先授权保存沟通习惯。'); return; }
- state.memoryStyle = data.get('style'); state.memoryLanguage = data.get('language'); state.memorySaved = true; record('客户更新沟通习惯。'); notify('沟通习惯已保存,可查看、更正或清空。');
- },
- invite(data) {
- if (!checkAccess()) return;
- const account = data.get('account').trim();
- if (!account) { notify('请填写员工账户。'); return; }
- if (state.invites.some(item => item.account === account)) { notify('该账户已登记,请检查已有邀请。'); return; }
- state.invites.push({ account, permission: data.get('permission') }); record(`登记员工 ${account},授权配件店的${data.get('permission')}职责。`); notify('员工邀请已登记在下方列表中,等待身份接入。');
- },
- 'channel-save'(data) {
- if (!checkAccess()) return;
- const url = new URL(data.get('callback'));
- if (url.protocol !== 'https:') { notify('回调地址必须使用 HTTPS。'); return; }
- state.formValues.channel = data.get('name'); record('保存渠道接入配置,等待接入检查。'); notify('配置已保存到线稿;签名、身份映射和回调接入仍需验证。');
- },
- 'rule-save'(data) {
- if (!checkAccess()) return;
- state.ruleSaved = true; state.formValues.ruleDays = Number(data.get('days'));
- state.formValues.rule = `${data.get('products')} / ${data.get('days')} 天 / ${data.get('citation')}`;
- notify('规则草稿已保存,请检查影响范围后发布。');
- },
- 'knowledge-save'(data) {
- if (!checkAccess()) return;
- if (state.knowledge !== 'DRAFT') state.knowledgeVersion += 1;
- state.knowledgeTitle = data.get('title'); state.formValues.knowledge = data.get('text'); state.knowledge = 'DRAFT'; record('知识资料保存为草稿。'); notify('草稿已保存,发布后才可以被客户检索。');
- },
- release(data) {
- if (!checkAccess()) return;
- if (!state.ruleActive || state.knowledge !== 'PUBLISHED') { notify('请先发布有效规则和知识资料,再检查发布清单。'); return; }
- confirmAction('确认发布配置', '新运行将使用发布版本 R2。原等待任务继续引用原发布版本。', () => { state.release = 'R2 已发布'; record(`发布 R2:${data.get('reason')}`); notify('线稿中的发布状态已更新为 R2。'); });
- },
- budget(data) {
- if (!checkAccess()) return;
- if (state.billingReviewer || state.budgetRequest === 'PENDING') { notify('请由申请员工提交新申请,已有待审批申请请先处理。'); return; }
- state.pendingBudget = Number(data.get('amount')); state.budgetRequest = 'PENDING'; record(`员工甲申请每日预算 ¥${state.pendingBudget}:${data.get('reason')}`); notify('申请已保存,等待另一位费用员工审批;当前预算保持原值。');
- },
- 'budget-decision'(data) {
- if (!checkAccess()) return;
- if (!state.billingReviewer || state.budgetRequest !== 'PENDING') { notify('需要另一位有审批权限的员工处理待审批申请。'); return; }
- const approved = data.get('decision') === '批准';
- confirmAction('确认费用审批决定', approved ? `批准后每日预算变为 ¥${state.pendingBudget}。` : '拒绝后当前预算保持不变。', () => {
- state.budgetRequest = approved ? 'APPROVED' : 'REJECTED'; if (approved) state.budget = state.pendingBudget;
- record(`员工乙${approved ? '批准' : '拒绝'}费用申请:${data.get('reason')}`); notify('费用审批决定已记录。');
- });
- },
- 'tenant-create'(data) {
- if (!checkAccess()) return;
- const name = data.get('name').trim();
- if (!name) { notify('请填写商家名称。'); return; }
- if (state.tenantRegistrations.includes(name)) { notify('该商家已登记。'); return; }
- state.tenantRegistrations.push(name); record(`登记商家 ${name},等待接入。`); notify('商家已登记为待接入,尚未启用业务。');
- },
- capacity(data) {
- if (!checkAccess()) return;
- const interactive = Number(data.get('interactive')); const reserved = Number(data.get('reserved'));
- if (reserved > interactive || reserved + 2 > 4) { notify('预留份额不能超过本商家并发上限;另一个商家已预留 2,交互可分配总量为 4。'); return; }
- state.formValues.interactive = interactive; state.formValues.reserved = reserved;
- record(`调整${data.get('tenant')}交互上限 ${interactive}、预留 ${reserved}:${data.get('reason')}`); notify('额度已保存。已有任务继续执行,预留随执行额度释放生效。');
- },
- };
- const actionHandlers = {
- 'notification-filter'(target) { notificationFilter = target.dataset.filter; render(); },
- 'notification-open'(target) { if (!checkAccess()) return; const item = employeeNotifications().find(entry => entry.id === target.dataset.id); if (!item) { notify('当前员工无权查看该通知。'); return; } selectedNotification = item.id; notificationRead.add(item.id); navigate(currentRole, 'notification-detail'); },
- 'notifications-read-all'() { if (!checkAccess()) return; confirmAction('全部标为已读', '将当前员工的所有通知标为已读,业务任务仍需分别处理。', () => { employeeNotifications().forEach(item => notificationRead.add(item.id)); notify('当前员工通知已全部标为已读。'); }); },
- 'admin-login-help'() { notify(currentRole === 'platform' ? '请联系平台账户管理员核实身份并重置密码。' : '请联系本商家管理员核实账户、商家标识和权限,必要时重置密码。'); },
- 'admin-logout'() { const product = adminProduct(currentRole); confirmAction('退出当前后台', '当前后台登录状态将结束,未提交表单清空。', () => { adminAuth[product] = false; adminReturn[product] = null; for (const key of drafts.keys()) if (adminProduct(key.split('/')[0]) === product) drafts.delete(key); notice = '已退出登录。'; navigate(product, 'login'); }); },
- 'review-toggle'() { const panel = document.querySelector('.review-sidebar'); panel.hidden = !panel.hidden; document.getElementById('review-toggle').setAttribute('aria-expanded', String(!panel.hidden)); },
- 'commerce-scope'() { notify('当前项目提供商品咨询、已购订单查询和换货服务。购物车与支付交易保留产品入口,暂未提供交易功能。'); },
- 'catalog-search'() { notify('商品搜索位置用于确认商城结构。可选择分类查看商品,并通过商品页咨询 AI。'); },
- category(target) { state.category = target.dataset.category; render(); },
- 'order-filter'(target) { state.orderFilter = target.dataset.filter; notice = ''; navigate('customer', 'orders'); },
- reset() { confirmAction('重置全部线稿状态', '本次演示的方案、消息及配置记录将清空。', () => { state = initialState(); drafts.clear(); notice = '演示已重置。'; navigate('customer', 'home'); }); },
- 'request-human'() { if (loginRequired()) return; state.humanRequested = true; markNotificationNew('staff-handoff'); record('客户申请人工协助。'); notify('已登记人工协助请求。客服接管后会显示服务人员。'); },
- takeover() { if (!checkAccess()) return; state.owner = 'HUMAN'; state.humanRequested = false; record('客服王芳接管会话,助手停止后续输出。'); notify('已接管,现在可以回复并整理方案。'); },
- release() { confirmAction('结束人工接管', '下一条客户消息交由助手处理,已有售后申请继续跟踪。', () => { state.owner = 'AGENT'; record('客服王芳结束接管。'); notify('接管已结束。'); }); },
- 'cancel-ticket'() {
- if (loginRequired() || !checkAccess()) return;
- if (!canCancel()) { notify('当前外部操作已登记或工单已结束,无法取消。'); return; }
- confirmAction('确认取消换货申请', '取消后停止当前方案的确认与审批。需要再次申请时重新填写。', () => { state.ticket = 'CANCELLED'; record('客户取消换货申请。'); notice = '申请已取消。'; navigate('customer', 'ticket'); });
- },
- 'refresh-proposal'() { state.stale = false; state.version += 1; state.customerConfirmed = false; state.ticket = 'DRAFT'; drafts.delete('customer/proposal/confirm-proposal'); notify('已读取新方案,等待客户重新确认;旧版本审批失效。'); },
- reconnect() { state.connected = true; notify('连接已恢复,继续显示已有消息。输入内容保留。'); },
- 'stop-answer'() { state.replyActive = false; notify('本次助手输出已停止,售后工单状态保持不变。'); },
- logout() { state.loggedIn = false; notice = '已退出当前客户身份。'; navigate('customer', 'login'); },
- 'memory-consent'() { if (loginRequired()) return; confirmAction('授权保存沟通习惯', '仅用于本商家的回复方式、语言和联系方式。可以随时撤销授权。', () => { state.memoryConsent = true; record('客户授权保存沟通习惯。'); notify('已授权,可以设置沟通习惯。'); }); },
- 'memory-clear'() { confirmAction('清空沟通习惯', '已保存内容清空,授权状态保持不变,历史咨询记录保留。', () => { state.memorySaved = false; record('客户清空沟通习惯。'); notify('已清空已保存内容。'); }); },
- 'memory-revoke'() { confirmAction('撤销沟通习惯授权', '停止保存及使用沟通习惯,历史咨询记录保留。', () => { state.memoryConsent = false; state.memorySaved = false; record('客户撤销沟通习惯授权。'); notify('授权已撤销。'); }); },
- 'identity-verify'() { if (loginRequired()) return; state.identityVerified = true; notify('已展示“目标渠道验证通过”情景,请检查两个身份并确认。'); },
- 'identity-link'() { if (!state.identityVerified) return; confirmAction('确认关联两个身份', '仅共享本商家本人业务进度,各渠道聊天记录保持独立。', () => { state.linked = true; record('客户确认关联已验证的两个渠道身份。'); notify('已关联,可以跨渠道查看同一工单。'); }); },
- 'store-toggle'() { toggle('storeEnabled', '店铺'); },
- 'staff-toggle'() { toggle('staffEnabled', '员工账户'); },
- 'channel-toggle'() { toggle('channelEnabled', 'Webhook 接入'); },
- 'tenant-toggle'() { toggle('tenantEnabled', '商家'); },
- 'rule-revoke'() { confirmAction('撤销当前规则', '使用该规则且尚未执行的方案需要重新修订、确认与审批。', () => { state.ruleActive = false; if (['DRAFT', 'WAITING_REVIEW', 'APPROVED'].includes(state.ticket)) { state.ticket = 'NEEDS_REVISION'; state.customerConfirmed = false; } record('撤销当前换货规则。'); notify('规则已撤销,相关方案显示需要修订。'); }); },
- 'rule-publish'() { if (!checkAccess() || !state.ruleSaved) return; confirmAction('发布新规则版本', '新申请使用新规则,已经确认的有效方案继续使用原规则版本。', () => { state.ruleVersion += 1; state.ruleDays = state.formValues.ruleDays; state.ruleSaved = false; state.ruleActive = true; record(`发布换货规则 V${state.ruleVersion}。`); notify('新规则版本已发布。'); }); },
- 'knowledge-preview'() { notify(`检索内容预览:${state.formValues.knowledge || '键盘清洁前请断开电源。换货条件以当前有效售后规则为准。'}`); },
- 'knowledge-publish'() { if (!checkAccess()) return; confirmAction('发布知识资料', '发布后当前版本可以被本店客户检索和引用。', () => { state.knowledge = 'PUBLISHED'; record(`发布知识 ${state.knowledgeTitle} V${state.knowledgeVersion}。`); notify('当前知识版本已发布。'); }); },
- 'knowledge-revoke'() { confirmAction('撤回知识资料', '停止向客户提供当前版本正文,相关答复需要重新检查资料。', () => { state.knowledge = 'REVOKED'; record('撤回知识资料。'); notify('资料已撤回,客户检索停止引用该版本。'); }); },
- 'delivery-retry'() { if (!checkAccess()) return; confirmAction('重试结果投递', '重试沿用原业务事件,提交后进入等待投递状态。', () => { state.delivery = 'QUEUED'; record('结果投递 DL-001 重新排队。'); notify('投递已排队,尚未收到接收端确认。'); }); },
- 'restore-access'() { state.expired = false; state.stale = false; notify('已进入重新取得有效授权的演示状态。'); },
- 'price-fields'() { notify('价格申请字段:供应商地址、模型名称、地域、生效日期、三类 token 单价、价格来源、申请原因。提交后等待另一位费用员工审批。'); },
- 'reconcile-fields'() { notify('费用核对字段:账本编号、完整核实金额、证据编号、核对原因。提交后等待另一位费用员工审批,批准后保留修改记录。'); },
- };
- function toggle(key, label) {
- if (!checkAccess()) return;
- const verb = state[key] ? '停用' : '启用';
- confirmAction(`${verb}${label}`, `${verb}影响后续访问和调用。已经登记的外部业务继续跟踪。`, () => { state[key] = !state[key]; record(`${verb}${label}。`); notify(`${label}已${verb}。`); });
- }
- function applyScenario(id) {
- saveDrafts(); notice = '已切换评审情景;页面内容为设计示例。';
- if (id === 'login-error' || id === 'session-expired') {
- const product = adminProduct(currentRole);
- if (currentPage !== 'login') adminReturn[product] = { role: currentRole, page: currentPage };
- adminAuth[product] = false;
- notice = id === 'login-error' ? '登录未成功,请检查账户信息或联系管理员。' : '登录已过期,请重新登录后继续。未提交内容保留。';
- navigate(product, 'login'); return;
- }
- state.expired = false; state.stale = false; state.selfApproval = false; state.empty = false;
- if (id === 'start') { state = initialState(); drafts.clear(); navigate('customer', 'home'); return; }
- if (id === 'waiting' || id === 'self' || id === 'stale' && currentRole === 'supervisor') { state.loggedIn = true; state.ticket = 'WAITING_REVIEW'; state.customerConfirmed = true; state.selfApproval = id === 'self'; state.stale = id === 'stale'; navigate(currentRole, currentRole === 'supervisor' ? 'review' : 'ticket'); return; }
- if (id === 'unknown' || id === 'revision' || id === 'completed' || id === 'processed') {
- state.loggedIn = true; state.customerConfirmed = id !== 'revision';
- state.ticket = { unknown: 'RESULT_UNKNOWN', revision: 'NEEDS_REVISION', completed: 'COMPLETED', processed: 'PROCESSING' }[id];
- navigate(currentRole, currentRole === 'supervisor' ? 'history' : 'ticket'); return;
- }
- if (id === 'human') { state.humanRequested = true; state.owner = 'AGENT'; navigate('staff', 'conversation'); return; }
- if (id === 'disconnect') { state.connected = false; navigate('customer', 'chat'); return; }
- if (id === 'generating') { state.loggedIn = true; state.replyActive = true; state.blocked = false; navigate('customer', 'chat'); return; }
- if (id === 'unavailable') { state.loggedIn = true; state.replyActive = false; state.blocked = true; navigate('customer', 'chat'); return; }
- if (id === 'empty') { state.empty = true; state.ticket = 'NONE'; navigate(currentRole, currentRole === 'staff' ? 'queue' : 'orders'); return; }
- if (id === 'expired') state.expired = true;
- if (id === 'stale') { state.stale = true; notice = '演示其他操作者已更新配置。保存时将提示版本冲突。使用正常配置情景重新读取。'; }
- if (id === 'billing-reviewer') { state.billingReviewer = !state.billingReviewer; navigate('merchant', 'billing'); return; }
- if (id === 'delivery-done') { state.delivery = 'SENT'; navigate('platform', 'deliveries'); return; }
- render();
- }
- document.addEventListener('click', event => {
- const target = event.target.closest('button'); if (!target || target.disabled) return;
- if (target.dataset.employeeRole) { saveDrafts(); merchantRole = target.dataset.employeeRole; notice = ''; navigate(merchantRole, roleHomes[merchantRole]); }
- else if (target.dataset.roleHome) { saveDrafts(); notice = ''; const role = target.dataset.roleHome === 'merchant' ? merchantRole : target.dataset.roleHome; navigate(role, roleHomes[role]); }
- else if (target.dataset.page) {
- saveDrafts(); notice = '';
- if (target.dataset.category) state.category = target.dataset.category;
- // 商品与订单入口携带咨询上下文,AI 会话仍保持同一客户身份。
- if (target.dataset.role === 'customer' && target.dataset.page === 'chat') {
- state.aiContext = currentPage === 'product' ? `当前咨询商品:${state.category || '键盘'}` : ['orders', 'order', 'ticket'].includes(currentPage) ? '当前咨询订单:A-20260918-001 · 键盘' : '';
- }
- navigate(target.dataset.role, target.dataset.page);
- }
- else if (target.dataset.scenario) applyScenario(target.dataset.scenario);
- else if (target.dataset.action) { saveDrafts(); const handler = actionHandlers[target.dataset.action]; if (!handler) throw new Error(`Unknown action: ${target.dataset.action}`); handler(target); }
- });
- document.addEventListener('submit', event => {
- const action = event.target.dataset.submit; if (!action) return;
- event.preventDefault(); saveDrafts();
- const handler = submissions[action]; if (!handler) throw new Error(`Unknown form: ${action}`);
- handler(new FormData(event.target));
- });
- document.getElementById('confirm-dialog').addEventListener('close', event => {
- const callback = pendingConfirmation; pendingConfirmation = null;
- if (event.target.returnValue === 'confirm' && callback) callback();
- });
- // 商家页面共用一个入口;页面路径不改变当前员工的权限。
- function routeUrl(role, page) {
- if (role === 'staff') return `#merchant/service/${page}`;
- if (role === 'supervisor') return `#merchant/approval/${page}`;
- return `#${role}/${page}`;
- }
- function readRoute() {
- let key = location.hash.slice(1);
- if (key.startsWith('merchant/service/')) key = 'staff/' + key.slice('merchant/service/'.length);
- else if (key.startsWith('merchant/approval/')) key = 'supervisor/' + key.slice('merchant/approval/'.length);
- const screen = screens[key];
- if (screen && screen.page !== 'login' && ['merchant', 'staff', 'supervisor'].includes(screen.role) && screen.role !== merchantRole) {
- currentRole = merchantRole; currentPage = roleHomes[merchantRole];
- notice = '当前员工没有所请求页面的权限,已进入可访问的商家功能。';
- history.replaceState(null, '', routeUrl(currentRole, currentPage));
- }
- else if (screen) { currentRole = screen.role; currentPage = screen.page; history.replaceState(null, '', routeUrl(currentRole, currentPage)); }
- else { currentRole = 'customer'; currentPage = 'home'; history.replaceState(null, '', '#customer/home'); }
- render();
- }
- window.addEventListener('hashchange', readRoute);
- readRoute();
|