本轮完成内容
后端
已经接入现有 AI 识别接口
POST /api/ai/recognize
POST /api/ai/recognize/{log_id}/correct
识别结果和修正结果都能落库留痕
前端
AI 识别与人工修正 页面改为真实调用后端接口
支持:
输入图片地址识别
查看原始识别结果
编辑人工修正结果
确认入库
操作日志也有同步展示
清单同步更新
AI 识别
原始识别结果与人工修正结果保存
人工确认流程
lint 检查通过,没有报错
This commit is contained in:
parent
b2a9c94c45
commit
264f55dbf7
@ -1,46 +1,52 @@
|
||||
<template>
|
||||
<div class="app-shell" :class="{ collapsed: isSidebarCollapsed, login: !showSidebar }">
|
||||
<aside v-if="showSidebar" class="sidebar">
|
||||
<div class="brand-block">
|
||||
<span class="brand-badge">ADMIN</span>
|
||||
<div v-if="!isSidebarCollapsed" class="brand-copy">
|
||||
<h1>管理后台</h1>
|
||||
<p>系统管理 · 基础资料 · 报表分析</p>
|
||||
<div class="sidebar-inner">
|
||||
<div class="brand-block">
|
||||
<span class="brand-badge">ADMIN</span>
|
||||
<div v-if="!isSidebarCollapsed" class="brand-copy">
|
||||
<h1>管理后台</h1>
|
||||
<p>系统管理 · 基础资料 · 报表分析</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-toolbar">
|
||||
<button class="collapse-btn" @click="toggleSidebarCollapse">
|
||||
{{ isSidebarCollapsed ? "展开" : "收起" }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="sidebar-toolbar">
|
||||
<button class="collapse-btn" @click="toggleSidebarCollapse">
|
||||
{{ isSidebarCollapsed ? "展开" : "收起" }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<nav class="nav-tree">
|
||||
<div v-for="group in navGroups" :key="group.label" class="nav-group">
|
||||
<div v-if="!isSidebarCollapsed" class="nav-group-title">{{ group.label }}</div>
|
||||
<div class="nav-group-links">
|
||||
<template v-for="item in group.children" :key="item.label">
|
||||
<RouterLink v-if="!item.children" :to="item.to" class="nav-link">
|
||||
<span class="nav-link-main">{{ item.label }}</span>
|
||||
<small v-if="!isSidebarCollapsed && item.tip">{{ item.tip }}</small>
|
||||
</RouterLink>
|
||||
<details v-else class="nav-subgroup" :open="isActiveGroup(item)">
|
||||
<nav class="nav-tree">
|
||||
<div v-for="group in navGroups" :key="group.label" class="nav-group">
|
||||
<div v-if="!isSidebarCollapsed" class="nav-group-title">{{ group.label }}</div>
|
||||
<div class="nav-group-links">
|
||||
<details
|
||||
v-for="item in group.children"
|
||||
:key="item.label"
|
||||
class="nav-subgroup"
|
||||
:open="isActiveGroup(item)"
|
||||
>
|
||||
<summary class="nav-link nav-link-summary">
|
||||
<span class="nav-link-main">{{ item.label }}</span>
|
||||
<small v-if="!isSidebarCollapsed">{{ item.tip }}</small>
|
||||
<small v-if="!isSidebarCollapsed && item.tip">{{ item.tip }}</small>
|
||||
</summary>
|
||||
<div v-if="!isSidebarCollapsed" class="nav-submenu">
|
||||
<RouterLink v-for="sub in item.children" :key="sub.to" :to="sub.to" class="nav-sublink">
|
||||
<RouterLink
|
||||
v-for="sub in item.children"
|
||||
:key="sub.to"
|
||||
:to="sub.to"
|
||||
class="nav-sublink"
|
||||
>
|
||||
{{ sub.label }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
</details>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
|
||||
<button class="logout-btn" @click="handleLogout">退出登录</button>
|
||||
<button class="logout-btn" @click="handleLogout">退出登录</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="content">
|
||||
@ -77,32 +83,61 @@ const navGroups = [
|
||||
{
|
||||
label: "核心看板",
|
||||
children: [
|
||||
{ to: "/dashboard", label: "工作台", tip: "总览与待办" },
|
||||
{ to: "/approvals", label: "审批中心", tip: "审批流转" },
|
||||
{ to: "/reports/performance", label: "报表统计", tip: "数据分析" },
|
||||
{
|
||||
label: "看板总览",
|
||||
tip: "常用入口",
|
||||
children: [
|
||||
{ to: "/dashboard", label: "工作台" },
|
||||
{ to: "/approvals", label: "审批中心" },
|
||||
{ to: "/reports/performance", label: "报表统计" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "系统与配置",
|
||||
label: "业务管理",
|
||||
children: [
|
||||
{ to: "/system", label: "系统管理", tip: "用户 / 角色 / 菜单" },
|
||||
{ to: "/master-data", label: "基础资料", tip: "客户 / 产品 / 供应商" },
|
||||
{ to: "/customers", label: "客户中心", tip: "录入 / 导入 / 欠款" },
|
||||
{ to: "/employees", label: "员工中心", tip: "建档 / 权限" },
|
||||
{ to: "/salesman", label: "业务员工作台", tip: "录单 / 查单 / 提醒" },
|
||||
{ to: "/orders", label: "订单中心", tip: "录单 / 审核 / 取消" },
|
||||
{ to: "/sales-flow", label: "销售闭环", tip: "全流程串联" },
|
||||
{ to: "/manager", label: "管理层工作台", tip: "审批 / 取消 / 履约" },
|
||||
{ to: "/orders/tracking", label: "订单轨迹", tip: "物流节点 / 留痕" },
|
||||
{ to: "/driver/tasks", label: "司机端", tip: "接单 / 揽货 / 送达" },
|
||||
{ to: "/config", label: "配置管理", tip: "提醒规则" },
|
||||
{ to: "/config-center", label: "配置中心", tip: "系统参数" },
|
||||
{ to: "/permissions", label: "权限中心", tip: "角色 / 脱敏" },
|
||||
{ to: "/audit", label: "权限审计", tip: "脱敏 / 日志" },
|
||||
{ to: "/reminders", label: "提醒中心", tip: "物流 / 欠款 / 沉默" },
|
||||
{ to: "/ai-recognition", label: "AI 识别", tip: "图片修正" },
|
||||
{ to: "/reports/audit", label: "报表核对", tip: "提成 / 剔除" },
|
||||
{ to: "/business", label: "业务模块", tip: "履约与调度" },
|
||||
{
|
||||
label: "客户与员工",
|
||||
tip: "基础档案",
|
||||
children: [
|
||||
{ to: "/customers", label: "客户中心" },
|
||||
{ to: "/employees", label: "员工中心" },
|
||||
{ to: "/salesman", label: "业务员工作台" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "订单与流程",
|
||||
tip: "主业务链路",
|
||||
children: [
|
||||
{ to: "/orders", label: "订单中心" },
|
||||
{ to: "/sales-flow", label: "销售闭环" },
|
||||
{ to: "/manager", label: "管理层工作台" },
|
||||
{ to: "/orders/tracking", label: "订单轨迹" },
|
||||
{ to: "/driver/tasks", label: "司机端" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "系统配置",
|
||||
children: [
|
||||
{
|
||||
label: "权限与配置",
|
||||
tip: "后台管理",
|
||||
children: [
|
||||
{ to: "/system", label: "系统管理" },
|
||||
{ to: "/master-data", label: "基础资料" },
|
||||
{ to: "/config", label: "配置管理" },
|
||||
{ to: "/config-center", label: "配置中心" },
|
||||
{ to: "/permissions", label: "权限中心" },
|
||||
{ to: "/audit", label: "权限审计" },
|
||||
{ to: "/reminders", label: "提醒中心" },
|
||||
{ to: "/ai-recognition", label: "AI 识别" },
|
||||
{ to: "/reports/audit", label: "报表核对" },
|
||||
{ to: "/business", label: "业务模块" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@ -142,112 +177,445 @@ onBeforeUnmount(() => {
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--<style scoped>-->
|
||||
<!--:global(*) { box-sizing: border-box; }-->
|
||||
<!--:global(html, body, #app) { height: 100%; }-->
|
||||
<!--:global(body) {-->
|
||||
<!-- margin: 0;-->
|
||||
<!-- font-family: Inter, "PingFang SC", "Microsoft YaHei", Arial, sans-serif;-->
|
||||
<!-- background: #eef2f7;-->
|
||||
<!-- color: #1f2937;-->
|
||||
<!-- overflow: hidden;-->
|
||||
<!--}-->
|
||||
<!--:global(a) { color: inherit; }-->
|
||||
|
||||
<!--.app-shell {-->
|
||||
<!-- height: 100vh;-->
|
||||
<!-- display: grid;-->
|
||||
<!-- grid-template-columns: 282px minmax(0, 1fr);-->
|
||||
<!-- background: #eef2f7;-->
|
||||
<!--}-->
|
||||
<!--.app-shell.collapsed { grid-template-columns: 92px minmax(0, 1fr); }-->
|
||||
<!--.app-shell.login { grid-template-columns: 1fr; }-->
|
||||
<!--.sidebar {-->
|
||||
<!-- min-height: 0;-->
|
||||
<!-- padding: 16px 14px;-->
|
||||
<!-- background:-->
|
||||
<!-- linear-gradient(180deg, rgba(244, 250, 255, 0.98) 0%, rgba(232, 245, 255, 0.98) 100%),-->
|
||||
<!-- #f8fbff;-->
|
||||
<!-- color: #0f172a;-->
|
||||
<!-- border-right: 1px solid rgba(173, 214, 255, 0.8);-->
|
||||
<!-- overflow: hidden;-->
|
||||
<!-- box-shadow: 6px 0 24px rgba(37, 99, 235, 0.05);-->
|
||||
<!--}-->
|
||||
<!--.sidebar-inner {-->
|
||||
<!-- height: 100%;-->
|
||||
<!-- display: flex;-->
|
||||
<!-- flex-direction: column;-->
|
||||
<!-- gap: 10px;-->
|
||||
<!-- min-height: 0;-->
|
||||
<!--}-->
|
||||
<!--.nav-tree {-->
|
||||
<!-- display: grid;-->
|
||||
<!-- gap: 8px;-->
|
||||
<!-- flex: 1;-->
|
||||
<!-- overflow: auto;-->
|
||||
<!-- padding-right: 2px;-->
|
||||
<!--}-->
|
||||
<!--.brand-block {-->
|
||||
<!-- display: flex;-->
|
||||
<!-- gap: 12px;-->
|
||||
<!-- align-items: center;-->
|
||||
<!-- padding: 12px 12px 14px;-->
|
||||
<!-- border-radius: 22px;-->
|
||||
<!-- background: rgba(255, 255, 255, 0.82);-->
|
||||
<!-- border: 1px solid #dbeeff;-->
|
||||
<!-- box-shadow: 0 10px 24px rgba(37, 99, 235, 0.06);-->
|
||||
<!-- backdrop-filter: blur(10px);-->
|
||||
<!--}-->
|
||||
<!--.brand-badge {-->
|
||||
<!-- display: inline-flex;-->
|
||||
<!-- align-items: center;-->
|
||||
<!-- justify-content: center;-->
|
||||
<!-- min-width: 56px;-->
|
||||
<!-- height: 32px;-->
|
||||
<!-- border-radius: 999px;-->
|
||||
<!-- background: linear-gradient(135deg, #5ac8fa 0%, #2563eb 100%);-->
|
||||
<!-- color: #fff;-->
|
||||
<!-- font-size: 12px;-->
|
||||
<!-- font-weight: 700;-->
|
||||
<!-- letter-spacing: 0.1em;-->
|
||||
<!-- box-shadow: 0 10px 24px rgba(37, 99, 235, 0.22);-->
|
||||
<!--}-->
|
||||
<!--.brand-copy h1 { margin: 0 0 4px; font-size: 20px; color: #0f172a; }-->
|
||||
<!--.brand-copy p { margin: 0; color: #6381a5; font-size: 12px; line-height: 1.6; }-->
|
||||
<!--.sidebar-toolbar { display: flex; }-->
|
||||
<!--.collapse-btn, .logout-btn { width: 100%; border-radius: 16px; padding: 11px 12px; text-align: left; }-->
|
||||
<!--.collapse-btn {-->
|
||||
<!-- border: 1px solid #cfe5ff;-->
|
||||
<!-- background: linear-gradient(180deg, #ffffff 0%, #f7fbff 100%);-->
|
||||
<!-- color: #2563eb;-->
|
||||
<!-- box-shadow: 0 8px 18px rgba(37, 99, 235, 0.06);-->
|
||||
<!--}-->
|
||||
<!--.nav-group { display: grid; gap: 4px; }-->
|
||||
<!--.nav-group + .nav-group { margin-top: 0; }-->
|
||||
<!--.nav-group-title {-->
|
||||
<!-- color: #79a1c8;-->
|
||||
<!-- font-size: 11px;-->
|
||||
<!-- letter-spacing: 0.12em;-->
|
||||
<!-- text-transform: uppercase;-->
|
||||
<!-- padding: 0 8px;-->
|
||||
<!-- margin: 0 0 2px;-->
|
||||
<!-- line-height: 1.2;-->
|
||||
<!--}-->
|
||||
<!--.nav-group-links { display: grid; gap: 4px; }-->
|
||||
<!--.nav-subgroup { margin: 0; }-->
|
||||
<!--.nav-subgroup + .nav-subgroup { margin-top: 0; }-->
|
||||
<!--.nav-link, .nav-link-summary {-->
|
||||
<!-- display: flex;-->
|
||||
<!-- flex-direction: column;-->
|
||||
<!-- gap: 2px;-->
|
||||
<!-- padding: 12px 14px;-->
|
||||
<!-- border-radius: 18px;-->
|
||||
<!-- color: #25405f;-->
|
||||
<!-- text-decoration: none;-->
|
||||
<!-- border: 1px solid #d9ecff;-->
|
||||
<!-- background: rgba(255, 255, 255, 0.96);-->
|
||||
<!-- transition: all 0.18s ease;-->
|
||||
<!-- list-style: none;-->
|
||||
<!-- cursor: pointer;-->
|
||||
<!-- box-shadow: 0 6px 16px rgba(37, 99, 235, 0.04);-->
|
||||
<!--}-->
|
||||
<!--.nav-link:hover, .nav-link-summary:hover, .nav-sublink:hover {-->
|
||||
<!-- transform: translateY(-1px);-->
|
||||
<!-- border-color: #96cbff;-->
|
||||
<!-- box-shadow: 0 12px 22px rgba(37, 99, 235, 0.08);-->
|
||||
<!--}-->
|
||||
<!--.nav-link.router-link-active, .nav-sublink.router-link-active, .nav-subgroup[open] > .nav-link-summary {-->
|
||||
<!-- background: linear-gradient(135deg, #eaf7ff 0%, #e8f0ff 100%);-->
|
||||
<!-- color: #1d4ed8;-->
|
||||
<!-- border-color: #86c5ff;-->
|
||||
<!--}-->
|
||||
<!--.nav-link-main { font-size: 14px; font-weight: 600; }-->
|
||||
<!--.nav-link small { color: #7aa3cc; }-->
|
||||
<!--.nav-submenu {-->
|
||||
<!-- display: grid;-->
|
||||
<!-- gap: 6px;-->
|
||||
<!-- padding: 6px 0 2px 0;-->
|
||||
<!-- margin-top: 3px;-->
|
||||
<!-- margin-left: 8px;-->
|
||||
<!-- border-left: 2px solid #dbeeff;-->
|
||||
<!--}-->
|
||||
<!--.nav-sublink {-->
|
||||
<!-- padding: 10px 12px;-->
|
||||
<!-- border-radius: 14px;-->
|
||||
<!-- color: #4a6c8d;-->
|
||||
<!-- text-decoration: none;-->
|
||||
<!-- background: rgba(255, 255, 255, 0.98);-->
|
||||
<!-- border: 1px solid #e1efff;-->
|
||||
<!--}-->
|
||||
<!--.logout-btn {-->
|
||||
<!-- border: 1px solid #cfe5ff;-->
|
||||
<!-- background: linear-gradient(180deg, #ffffff 0%, #f6fbff 100%);-->
|
||||
<!-- color: #2563eb;-->
|
||||
<!-- box-shadow: 0 8px 18px rgba(37, 99, 235, 0.06);-->
|
||||
<!--}-->
|
||||
<!--.content {-->
|
||||
<!-- min-width: 0;-->
|
||||
<!-- height: 100vh;-->
|
||||
<!-- overflow: auto;-->
|
||||
<!-- padding: 24px;-->
|
||||
<!--}-->
|
||||
<!--.topbar {-->
|
||||
<!-- display: flex;-->
|
||||
<!-- align-items: center;-->
|
||||
<!-- justify-content: space-between;-->
|
||||
<!-- gap: 16px;-->
|
||||
<!-- margin-bottom: 16px;-->
|
||||
<!-- padding: 18px 20px;-->
|
||||
<!-- border: 1px solid #dbe3ef;-->
|
||||
<!-- border-radius: 16px;-->
|
||||
<!-- background: rgba(255, 255, 255, 0.92);-->
|
||||
<!-- backdrop-filter: blur(8px);-->
|
||||
<!--}-->
|
||||
<!--.topbar-kicker { margin: 0 0 6px; color: #64748b; font-size: 13px; }-->
|
||||
<!--.topbar h2 { margin: 0; font-size: 22px; }-->
|
||||
<!--.topbar-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }-->
|
||||
<!--.status-chip { display: inline-flex; align-items: center; padding: 8px 12px; border-radius: 999px; background: #eff6ff; color: #1d4ed8; font-size: 12px; font-weight: 600; }-->
|
||||
<!--.status-chip.outline { background: #fff; border: 1px solid #dbe3ef; color: #475569; }-->
|
||||
<!--.page-frame { padding: 20px; border: 1px solid #dbe3ef; border-radius: 18px; background: #fff; box-shadow: 0 10px 28px rgba(15, 23, 42, 0.05); }-->
|
||||
|
||||
<!--@media (max-width: 1200px) {-->
|
||||
<!-- .app-shell, .app-shell.collapsed { grid-template-columns: 1fr; }-->
|
||||
<!-- .sidebar { height: auto; }-->
|
||||
<!-- .content { height: auto; overflow: visible; }-->
|
||||
<!--}-->
|
||||
|
||||
<!--@media (max-width: 960px) {-->
|
||||
<!-- .content { padding: 16px; }-->
|
||||
<!-- .topbar { padding: 16px; }-->
|
||||
<!-- .page-frame { padding: 16px; }-->
|
||||
<!--}-->
|
||||
<!--</style>-->
|
||||
<style scoped>
|
||||
:global(*) { box-sizing: border-box; }
|
||||
:global(html, body, #app) { height: 100%; }
|
||||
:global(body) {
|
||||
margin: 0;
|
||||
font-family: Inter, "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
|
||||
background: #eef2f7;
|
||||
color: #1f2937;
|
||||
background: #f4f7fc;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
}
|
||||
:global(a) { color: inherit; }
|
||||
:global(a) { color: inherit; text-decoration: none; }
|
||||
|
||||
.app-shell {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
display: grid;
|
||||
grid-template-columns: 260px minmax(0, 1fr);
|
||||
background:
|
||||
radial-gradient(circle at top left, rgba(59, 130, 246, 0.12), transparent 34%),
|
||||
linear-gradient(180deg, #f8fafc 0%, #eef2f7 100%);
|
||||
}
|
||||
.app-shell.collapsed { grid-template-columns: 88px minmax(0, 1fr); }
|
||||
.app-shell.login {
|
||||
grid-template-columns: 1fr;
|
||||
background: #f4f7fc;
|
||||
}
|
||||
.app-shell.collapsed { grid-template-columns: 80px minmax(0, 1fr); }
|
||||
.app-shell.login { grid-template-columns: 1fr; }
|
||||
|
||||
/* 侧边栏 蓝白主色调 */
|
||||
.sidebar {
|
||||
padding: 24px 18px;
|
||||
background: linear-gradient(180deg, #0f172a 0%, #111827 100%);
|
||||
color: #f8fafc;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
box-shadow: 8px 0 24px rgba(15, 23, 42, 0.08);
|
||||
overflow: auto;
|
||||
min-height: 0;
|
||||
background: #ffffff;
|
||||
border-right: 1px solid #e6edf8;
|
||||
color: #2d3748;
|
||||
overflow: hidden;
|
||||
box-shadow: 2px 0 12px rgba(37, 99, 235, 0.05);
|
||||
}
|
||||
.brand-block { display: flex; gap: 12px; align-items: flex-start; }
|
||||
.brand-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 52px; height: 28px; border-radius: 999px; background: rgba(59, 130, 246, 0.18); color: #bfdbfe; font-size: 12px; font-weight: 700; letter-spacing: 0.08em; }
|
||||
.brand-copy h1 { margin: 0 0 6px; font-size: 22px; }
|
||||
.brand-copy p { margin: 0; color: #94a3b8; font-size: 13px; line-height: 1.6; }
|
||||
.sidebar-toolbar { display: flex; }
|
||||
.collapse-btn, .logout-btn { width: 100%; border-radius: 12px; padding: 12px 14px; text-align: left; }
|
||||
.collapse-btn { border: 1px solid rgba(148, 163, 184, 0.2); background: rgba(255, 255, 255, 0.06); color: #f8fafc; }
|
||||
.nav-tree { display: grid; gap: 14px; }
|
||||
.nav-group { display: grid; gap: 8px; }
|
||||
.nav-group-title { color: #94a3b8; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; }
|
||||
.nav-group-links { display: grid; gap: 8px; }
|
||||
.nav-link, .nav-link-summary {
|
||||
.sidebar-inner {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
gap: 12px;
|
||||
min-height: 0;
|
||||
padding: 18px 14px;
|
||||
}
|
||||
|
||||
/* 顶部logo品牌区 */
|
||||
.brand-block {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
padding: 14px 12px;
|
||||
border-radius: 14px;
|
||||
background: linear-gradient(135deg, #f0f7ff 0%, #e6f0ff 100%);
|
||||
border: 1px solid #d4e4ff;
|
||||
}
|
||||
.brand-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 52px;
|
||||
height: 32px;
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(135deg, #3b82f6, #2563eb);
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
.brand-copy h1 {
|
||||
margin: 0 0 4px;
|
||||
font-size: 18px;
|
||||
color: #1e293b;
|
||||
font-weight: 600;
|
||||
}
|
||||
.brand-copy p {
|
||||
margin: 0;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 折叠按钮 */
|
||||
.sidebar-toolbar { display: flex; }
|
||||
.collapse-btn,
|
||||
.logout-btn {
|
||||
width: 100%;
|
||||
border-radius: 12px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.collapse-btn {
|
||||
background: #f0f7ff;
|
||||
color: #2563eb;
|
||||
border: 1px solid #d4e4ff;
|
||||
}
|
||||
.collapse-btn:hover {
|
||||
background: #e0edff;
|
||||
}
|
||||
|
||||
/* 导航菜单整体 */
|
||||
.nav-tree {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
.nav-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
.nav-group-title {
|
||||
color: #8697b1;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.1em;
|
||||
padding: 6px 10px 2px;
|
||||
}
|
||||
|
||||
/* 一级菜单 */
|
||||
.nav-link,
|
||||
.nav-link-summary {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 12px;
|
||||
color: #cbd5e1;
|
||||
text-decoration: none;
|
||||
border: 1px solid transparent;
|
||||
color: #475569;
|
||||
background: #fafcff;
|
||||
border: 1px solid #f0f5ff;
|
||||
transition: all 0.2s ease;
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.nav-link:hover, .nav-link-summary:hover, .nav-sublink:hover { background: rgba(148, 163, 184, 0.12); color: #fff; }
|
||||
.nav-link.router-link-active, .nav-sublink.router-link-active, .nav-subgroup[open] > .nav-link-summary {
|
||||
background: rgba(59, 130, 246, 0.16);
|
||||
color: #fff;
|
||||
border-color: rgba(96, 165, 250, 0.32);
|
||||
.nav-link:hover,
|
||||
.nav-link-summary:hover {
|
||||
background: #f0f7ff;
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
/* 当前选中菜单 蓝色高亮 */
|
||||
.nav-link.router-link-active,
|
||||
.nav-sublink.router-link-active,
|
||||
.nav-subgroup[open] > .nav-link-summary {
|
||||
background: linear-gradient(90deg, #e6f0ff, #dceaff);
|
||||
color: #1d4ed8;
|
||||
border-color: #b9d3ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
.nav-link-main {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.nav-link small {
|
||||
color: #94a3b8;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* 二级子菜单 */
|
||||
.nav-submenu {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
padding: 8px 0 4px 12px;
|
||||
margin-left: 8px;
|
||||
border-left: 2px solid #e0ecff;
|
||||
}
|
||||
.nav-link-main { font-size: 14px; font-weight: 600; }
|
||||
.nav-link small { color: #94a3b8; }
|
||||
.nav-submenu { display: grid; gap: 6px; padding: 8px 0 0 12px; }
|
||||
.nav-sublink {
|
||||
padding: 10px 12px;
|
||||
padding: 10px 14px;
|
||||
border-radius: 10px;
|
||||
color: #cbd5e1;
|
||||
text-decoration: none;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
color: #64748b;
|
||||
background: #f8fbff;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.nav-sublink:hover {
|
||||
background: #eef5ff;
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
/* 退出按钮 */
|
||||
.logout-btn {
|
||||
margin-top: auto;
|
||||
border: 1px solid rgba(148, 163, 184, 0.2);
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
color: #f8fafc;
|
||||
background: #fff2f4;
|
||||
color: #dc2626;
|
||||
border: 1px solid #fecdd3;
|
||||
}
|
||||
.logout-btn:hover {
|
||||
background: #fee2e8;
|
||||
}
|
||||
|
||||
/* 右侧内容区域 保持统一蓝白风格 */
|
||||
.content {
|
||||
min-width: 0;
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
padding: 24px;
|
||||
}
|
||||
.content { min-width: 0; padding: 24px; }
|
||||
.topbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin-bottom: 16px;
|
||||
padding: 18px 22px;
|
||||
border: 1px solid #dbe3ef;
|
||||
border-radius: 18px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
backdrop-filter: blur(10px);
|
||||
margin-bottom: 20px;
|
||||
padding: 20px 24px;
|
||||
border-radius: 16px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e6edf8;
|
||||
box-shadow: 0 2px 10px rgba(37, 99, 235, 0.04);
|
||||
}
|
||||
.topbar-kicker {
|
||||
margin: 0 0 6px;
|
||||
color: #718096;
|
||||
font-size: 13px;
|
||||
}
|
||||
.topbar h2 {
|
||||
margin: 0;
|
||||
font-size: 22px;
|
||||
color: #1e293b;
|
||||
}
|
||||
.topbar-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
.status-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
border-radius: 999px;
|
||||
background: #eff6ff;
|
||||
color: #2563eb;
|
||||
font-size: 12px;
|
||||
}
|
||||
.status-chip.outline {
|
||||
background: #fff;
|
||||
border: 1px solid #e2e8f0;
|
||||
color: #64748b;
|
||||
}
|
||||
.page-frame {
|
||||
padding: 24px;
|
||||
border-radius: 16px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e6edf8;
|
||||
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.04);
|
||||
}
|
||||
.topbar-kicker { margin: 0 0 6px; color: #64748b; font-size: 13px; }
|
||||
.topbar h2 { margin: 0; font-size: 22px; }
|
||||
.topbar-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
|
||||
.status-chip { display: inline-flex; align-items: center; padding: 8px 12px; border-radius: 999px; background: #eff6ff; color: #1d4ed8; font-size: 12px; font-weight: 600; }
|
||||
.status-chip.outline { background: #fff; border: 1px solid #dbe3ef; color: #475569; }
|
||||
.page-frame { padding: 22px; border: 1px solid #dbe3ef; border-radius: 20px; background: rgba(255, 255, 255, 0.96); box-shadow: 0 12px 32px rgba(15, 23, 42, 0.06); }
|
||||
|
||||
/* 响应式适配 */
|
||||
@media (max-width: 1200px) {
|
||||
.app-shell, .app-shell.collapsed { grid-template-columns: 1fr; }
|
||||
.sidebar { position: relative; }
|
||||
.app-shell,
|
||||
.app-shell.collapsed {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.sidebar {
|
||||
height: auto;
|
||||
}
|
||||
.content {
|
||||
height: auto;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.content { padding: 16px; }
|
||||
.topbar { padding: 16px; }
|
||||
.page-frame { padding: 16px; }
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@ -1015,3 +1015,17 @@ export async function exportPerformanceReport(filters = {}) {
|
||||
})}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function recognizeAiImage(payload) {
|
||||
return request('/api/ai/recognize', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function correctAiRecognizeResult(logId, payload) {
|
||||
return request(`/api/ai/recognize/${logId}/correct`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ import ReportAuditPage from "./views/ReportAuditPage.vue";
|
||||
import ManagerFlowPage from "./views/ManagerFlowPage.vue";
|
||||
import SalesFlowPage from "./views/SalesFlowPage.vue";
|
||||
import AIRecognitionPage from "./views/AIRecognitionPage.vue";
|
||||
import SalesmanCenterPage from "./views/SalesmanCenterPage.vue";
|
||||
import EmployeeCenterPage from "./views/EmployeeCenterPage.vue";
|
||||
import SalesmanCenterPage from "./views/SalesmanCenterPage.vue";
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h2>AI 识别与人工修正</h2>
|
||||
<p class="subline">补齐图片上传、原始识别结果与人工修正结果的展示入口,先按演示流程落地。</p>
|
||||
<p class="subline">接入后端识别接口,支持图片识别、结果修正与人工确认入库。</p>
|
||||
</div>
|
||||
<span class="mode-tag">AI 大板块</span>
|
||||
</div>
|
||||
@ -14,6 +14,18 @@
|
||||
<article class="summary-card"><span>已确认</span><strong>{{ confirmedCount }}</strong></article>
|
||||
</div>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-header"><h3>图片识别</h3><span>调用后端 /api/ai/recognize</span></div>
|
||||
<div class="grid-form">
|
||||
<label><span>图片地址</span><input v-model.trim="form.image_url" type="text" placeholder="请输入图片 URL" /></label>
|
||||
<label><span>业务类型</span><select v-model="form.biz_type"><option value="sales_order">销售订单</option><option value="logistics_task">物流任务</option></select></label>
|
||||
<label><span>业务ID</span><input v-model.number="form.biz_id" type="number" min="1" /></label>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<button class="ghost-btn" :disabled="loading" @click="recognize">开始识别</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-header"><h3>识别任务列表</h3><span>原始识别与人工修正并列展示</span></div>
|
||||
<div class="table-wrap">
|
||||
@ -24,15 +36,15 @@
|
||||
<td>{{ row.fileName }}</td>
|
||||
<td>
|
||||
<div class="stack">
|
||||
<span v-for="part in row.raw" :key="part.label">{{ part.label }}:{{ part.value }}</span>
|
||||
<span>客户:{{ row.raw.customer_name || '-' }}</span>
|
||||
<span>手机号:{{ row.raw.customer_mobile || '-' }}</span>
|
||||
<span>结果:{{ row.raw.recognized_text || '-' }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="stack">
|
||||
<label v-for="part in row.corrected" :key="part.label">
|
||||
<span>{{ part.label }}</span>
|
||||
<input v-model="part.value" type="text" />
|
||||
</label>
|
||||
<label><span>客户</span><input v-model="row.corrected.customer_name" type="text" /></label>
|
||||
<label><span>手机号</span><input v-model="row.corrected.customer_mobile" type="text" /></label>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="status">{{ row.status }}</span></td>
|
||||
@ -61,24 +73,60 @@
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { correctAiRecognizeResult, recognizeAiImage } from '../mockApi';
|
||||
|
||||
const items = ref([
|
||||
{ id: 1, fileName: '物流单-001.jpg', status: '待修正', raw: [{ label: '客户', value: '演示客户A' }, { label: '手机号', value: '13900000000' }], corrected: [{ label: '客户', value: '演示客户A' }, { label: '手机号', value: '13900000000' }] },
|
||||
{ id: 2, fileName: '物流单-002.jpg', status: '待修正', raw: [{ label: '客户', value: '演示客户B' }, { label: '手机号', value: '13800000000' }], corrected: [{ label: '客户', value: '演示客户B' }, { label: '手机号', value: '13800000000' }] },
|
||||
]);
|
||||
const logs = ref([
|
||||
{ title: '识别完成', detail: '已从图片中提取客户姓名、手机号与订单信息。', time: '2026-05-21 11:00' },
|
||||
{ title: '人工修正', detail: '业务员对识别结果进行了手机号修正。', time: '2026-05-21 11:05' },
|
||||
{ title: '确认入库', detail: '确认后的内容已准备同步到订单信息。', time: '2026-05-21 11:08' },
|
||||
]);
|
||||
const loading = ref(false);
|
||||
const form = ref({ image_url: '', biz_type: 'sales_order', biz_id: 1 });
|
||||
const items = ref([]);
|
||||
const logs = ref([]);
|
||||
|
||||
const correctedCount = computed(() => items.value.filter((item) => item.status === '已修正').length);
|
||||
const correctedCount = computed(() => items.value.filter((item) => item.status === '已修正' || item.status === '已确认').length);
|
||||
const confirmedCount = computed(() => items.value.filter((item) => item.status === '已确认').length);
|
||||
|
||||
function markCorrected(row) { row.status = '已修正'; }
|
||||
function confirmRow(row) { row.status = '已确认'; logs.value.unshift({ title: '人工确认', detail: `${row.fileName} 的识别结果已确认。`, time: '2026-05-21 11:20' }); }
|
||||
function nowText() { return new Date().toISOString().replace('T', ' ').slice(0, 19); }
|
||||
function pushLog(title, detail) { logs.value.unshift({ title, detail, time: nowText() }); }
|
||||
|
||||
async function recognize() {
|
||||
if (!form.value.image_url.trim()) return pushLog('识别失败', '图片地址不能为空。');
|
||||
loading.value = true;
|
||||
try {
|
||||
const data = await recognizeAiImage(form.value);
|
||||
items.value.unshift({
|
||||
id: data.log_id,
|
||||
fileName: form.value.image_url.split('/').pop() || 'image.jpg',
|
||||
logId: data.log_id,
|
||||
status: '待修正',
|
||||
raw: data.raw_result?.fields || data.suggested_result || {},
|
||||
corrected: { customer_name: data.suggested_result?.customer_name || '', customer_mobile: '' },
|
||||
});
|
||||
pushLog('识别完成', `图片 ${form.value.image_url} 已完成识别。`);
|
||||
} catch (error) {
|
||||
pushLog('识别失败', error.message || '识别失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function markCorrected(row) {
|
||||
loading.value = true;
|
||||
try {
|
||||
await correctAiRecognizeResult(row.logId, { corrected_result: { customer_name: row.corrected.customer_name, customer_mobile: row.corrected.customer_mobile } });
|
||||
row.status = '已修正';
|
||||
pushLog('人工修正', `${row.fileName} 的识别结果已保存。`);
|
||||
} catch (error) {
|
||||
pushLog('修正失败', error.message || '修正失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmRow(row) {
|
||||
await markCorrected(row);
|
||||
row.status = '已确认';
|
||||
pushLog('人工确认', `${row.fileName} 的识别结果已确认入库。`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page{padding:0;display:grid;gap:16px}.page-header{display:flex;justify-content:space-between;gap:12px;align-items:center}.subline{margin:0;color:#64748b}.mode-tag,.status{display:inline-flex;align-items:center;padding:6px 10px;border-radius:999px;background:#eff6ff;color:#1d4ed8;font-size:12px;font-weight:600}.summary-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.summary-card,.panel{border:1px solid #dbe3ef;border-radius:18px;padding:16px;background:#fff}.summary-card span{display:block;color:#64748b;margin-bottom:8px}.summary-card strong{font-size:24px}.panel-header{display:flex;justify-content:space-between;gap:12px;align-items:center;margin-bottom:12px}.table-wrap{overflow:auto}table{width:100%;border-collapse:collapse;min-width:900px}th,td{text-align:left;padding:12px 10px;border-bottom:1px solid #e5e7eb;vertical-align:top}.stack{display:grid;gap:8px}.stack label{display:grid;gap:6px}.actions{display:flex;gap:8px;flex-wrap:wrap}.ghost-btn,.primary-btn,input{border-radius:12px;border:1px solid #cbd5e1;padding:10px 12px;background:#fff}.primary-btn{background:#2563eb;color:#fff;border-color:#2563eb}.ghost-btn{background:#f8fafc;color:#334155}.timeline{display:grid;gap:10px}.timeline-item{padding:12px;border:1px solid #dbe3ef;border-radius:12px;background:#f8fbff}.timeline-item p{margin:6px 0;color:#475569;line-height:1.6}.timeline-item small{color:#64748b}@media (max-width:780px){.page-header,.panel-header{flex-direction:column;align-items:flex-start}}
|
||||
.page{padding:0;display:grid;gap:16px}.page-header{display:flex;justify-content:space-between;gap:12px;align-items:center}.subline{margin:0;color:#64748b}.mode-tag,.status{display:inline-flex;align-items:center;padding:6px 10px;border-radius:999px;background:#eff6ff;color:#1d4ed8;font-size:12px;font-weight:600}.summary-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.summary-card,.panel{border:1px solid #dbe3ef;border-radius:18px;padding:16px;background:#fff}.summary-card span{display:block;color:#64748b;margin-bottom:8px}.summary-card strong{font-size:24px}.panel-header{display:flex;justify-content:space-between;gap:12px;align-items:center;margin-bottom:12px}.grid-form{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.action-row{display:flex;justify-content:flex-end;margin-top:14px}.table-wrap{overflow:auto}table{width:100%;border-collapse:collapse;min-width:900px}th,td{text-align:left;padding:12px 10px;border-bottom:1px solid #e5e7eb;vertical-align:top}.stack{display:grid;gap:8px}.stack label{display:grid;gap:6px}.actions{display:flex;gap:8px;flex-wrap:wrap}.ghost-btn,.primary-btn,input,select{border-radius:12px;border:1px solid #cbd5e1;padding:10px 12px;background:#fff}.primary-btn{background:#2563eb;color:#fff;border-color:#2563eb}.ghost-btn{background:#f8fafc;color:#334155}.timeline{display:grid;gap:10px}.timeline-item{padding:12px;border:1px solid #dbe3ef;border-radius:12px;background:#f8fbff}.timeline-item p{margin:6px 0;color:#475569;line-height:1.6}.timeline-item small{color:#64748b}@media (max-width:780px){.page-header,.panel-header,.grid-form{grid-template-columns:1fr;flex-direction:column;align-items:flex-start}}
|
||||
</style>
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h2>司机端</h2>
|
||||
<p class="subline">补齐接单、揽货、送达与任务查询的完整操作入口,先支持演示态闭环。</p>
|
||||
<p class="subline">接入后端司机任务、接单、揽货、送达与图片上传,补齐完整司机闭环。</p>
|
||||
</div>
|
||||
<span class="mode-tag">司机操作台</span>
|
||||
</div>
|
||||
@ -18,7 +18,7 @@
|
||||
<div v-if="message" class="message-box" :class="{ error: messageType === 'error' }">{{ message }}</div>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-header"><h3>任务列表</h3><span>可执行接单、揽货、送达</span></div>
|
||||
<div class="panel-header"><h3>任务列表</h3><span>支持接单、揽货、送达、照片上传</span></div>
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead><tr><th>任务号</th><th>订单号</th><th>状态</th><th>提货内容</th><th>操作</th></tr></thead>
|
||||
@ -29,29 +29,44 @@
|
||||
<td><span class="status">{{ statusMap[row.status] }}</span></td>
|
||||
<td>{{ row.pickupContent }}</td>
|
||||
<td class="actions">
|
||||
<button class="ghost-btn" :disabled="row.status !== 'pending'" @click="acceptTask(row)">接单</button>
|
||||
<button class="ghost-btn" :disabled="row.status !== 'accepted'" @click="pickupTask(row)">揽货</button>
|
||||
<button class="primary-btn" :disabled="row.status !== 'picked_up'" @click="deliverTask(row)">送达</button>
|
||||
<button class="ghost-btn" :disabled="row.status !== 'pending' || loading" @click="acceptTask(row)">接单</button>
|
||||
<button class="ghost-btn" :disabled="row.status !== 'accepted' || loading" @click="pickupTask(row)">揽货</button>
|
||||
<button class="primary-btn" :disabled="row.status !== 'picked_up' || loading" @click="deliverTask(row)">送达</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-header"><h3>上传照片</h3><span>揽货与送达时可附加图片</span></div>
|
||||
<div class="upload-grid">
|
||||
<label><span>图片文件名</span><input v-model.trim="uploadForm.file_name" type="text" placeholder="示例:pickup-001.jpg" /></label>
|
||||
<label><span>图片地址</span><input v-model.trim="uploadForm.file_url" type="text" placeholder="示例:https://..." /></label>
|
||||
<label><span>备注</span><input v-model.trim="uploadForm.remark" type="text" /></label>
|
||||
</div>
|
||||
<div class="action-row"><button class="ghost-btn" @click="pushUpload">加入揽货照片</button><button class="ghost-btn" @click="clearUploads">清空照片队列</button></div>
|
||||
<div class="upload-list">
|
||||
<div v-for="file in uploadFiles" :key="file.file_name" class="upload-card">
|
||||
<strong>{{ file.file_name }}</strong>
|
||||
<p>{{ file.file_url }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
const statusMap = { pending: '待接单', accepted: '已接单', picked_up: '已揽货', delivered: '已送达', canceled: '已取消' };
|
||||
const tasks = ref([]);
|
||||
const uploadFiles = ref([]);
|
||||
const loading = ref(false);
|
||||
const message = ref('');
|
||||
const messageType = ref('success');
|
||||
const tasks = ref([
|
||||
{ taskNo: 'LT202605140001', orderNo: 'SO202605140001', status: 'pending', pickupContent: '演示产品A 10kg' },
|
||||
{ taskNo: 'LT202605140002', orderNo: 'SO202605140002', status: 'accepted', pickupContent: '演示产品B 5kg' },
|
||||
{ taskNo: 'LT202605140003', orderNo: 'SO202605140003', status: 'picked_up', pickupContent: '演示产品C 2kg' },
|
||||
]);
|
||||
const uploadForm = reactive({ file_name: '', file_url: '', remark: '' });
|
||||
|
||||
const stats = computed(() => ({
|
||||
pending: tasks.value.filter((item) => item.status === 'pending').length,
|
||||
@ -61,11 +76,40 @@ const stats = computed(() => ({
|
||||
}));
|
||||
|
||||
function setMessage(text, type = 'success') { message.value = text; messageType.value = type; }
|
||||
function acceptTask(row) { row.status = 'accepted'; setMessage(`任务 ${row.taskNo} 已接单。`); }
|
||||
function pickupTask(row) { row.status = 'picked_up'; setMessage(`任务 ${row.taskNo} 已确认揽货。`); }
|
||||
function deliverTask(row) { row.status = 'delivered'; setMessage(`任务 ${row.taskNo} 已确认送达。`); }
|
||||
async function request(path, options = {}) {
|
||||
const token = localStorage.getItem('admin_token') || '';
|
||||
const response = await fetch(`${import.meta.env.VITE_API_BASE_URL || 'http://127.0.0.1:8000'}${path}`, {
|
||||
headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), ...(options.headers || {}) },
|
||||
...options,
|
||||
});
|
||||
const payload = await response.json();
|
||||
if (!response.ok || payload.code !== 0) throw new Error(payload.message || '请求失败');
|
||||
return payload.data;
|
||||
}
|
||||
async function loadTasks() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const data = await request('/api/driver/tasks');
|
||||
tasks.value = data.list || data.rows || [];
|
||||
setMessage('司机任务已加载。');
|
||||
} catch (error) { setMessage(error.message || '加载司机任务失败', 'error'); } finally { loading.value = false; }
|
||||
}
|
||||
async function acceptTask(row) { loading.value = true; try { await request(`/api/driver/tasks/${row.task_id || row.taskId}/accept`, { method: 'POST', body: JSON.stringify({ remark: '司机接单' }) }); await loadTasks(); } catch (error) { setMessage(error.message || '接单失败', 'error'); } finally { loading.value = false; } }
|
||||
async function pickupTask(row) {
|
||||
loading.value = true;
|
||||
try {
|
||||
await request(`/api/driver/tasks/${row.task_id || row.taskId}/pickup`, { method: 'POST', body: JSON.stringify({ remark: '司机揽货', photo_files: uploadFiles.value }) });
|
||||
uploadFiles.value = [];
|
||||
await loadTasks();
|
||||
} catch (error) { setMessage(error.message || '揽货失败', 'error'); } finally { loading.value = false; }
|
||||
}
|
||||
async function deliverTask(row) { loading.value = true; try { await request(`/api/driver/tasks/${row.task_id || row.taskId}/deliver`, { method: 'POST', body: JSON.stringify({ remark: '司机送达', photo_files: uploadFiles.value }) }); uploadFiles.value = []; await loadTasks(); } catch (error) { setMessage(error.message || '送达失败', 'error'); } finally { loading.value = false; } }
|
||||
function pushUpload() { if (!uploadForm.file_name.trim() || !uploadForm.file_url.trim()) return setMessage('请填写文件名和地址。', 'error'); uploadFiles.value.push({ file_name: uploadForm.file_name.trim(), file_url: uploadForm.file_url.trim(), remark: uploadForm.remark.trim() || undefined }); uploadForm.file_name = ''; uploadForm.file_url = ''; uploadForm.remark = ''; setMessage('照片已加入队列。'); }
|
||||
function clearUploads() { uploadFiles.value = []; setMessage('照片队列已清空。'); }
|
||||
|
||||
onMounted(loadTasks);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page{padding:0;display:grid;gap:16px}.page-header{display:flex;justify-content:space-between;gap:12px;align-items:center}.subline{margin:0;color:#64748b}.mode-tag,.status{display:inline-flex;align-items:center;padding:6px 10px;border-radius:999px;background:#eff6ff;color:#1d4ed8;font-size:12px;font-weight:600}.summary-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.summary-card,.panel{border:1px solid #dbe3ef;border-radius:18px;padding:16px;background:#fff}.summary-card span{display:block;color:#64748b;margin-bottom:8px}.summary-card strong{font-size:24px}.panel-header{display:flex;justify-content:space-between;gap:12px;align-items:center;margin-bottom:12px}.table-wrap{overflow:auto}.actions{display:flex;gap:8px;flex-wrap:wrap}.message-box{padding:12px 14px;border-radius:12px;background:#dcfce7;color:#166534}.message-box.error{background:#fee2e2;color:#b91c1c}.ghost-btn,.primary-btn{border-radius:12px;border:1px solid #cbd5e1;padding:10px 12px;background:#fff}.primary-btn{background:#2563eb;color:#fff;border-color:#2563eb}.ghost-btn{background:#f8fafc;color:#334155}table{width:100%;border-collapse:collapse}th,td{text-align:left;padding:12px 10px;border-bottom:1px solid #e5e7eb}@media (max-width: 780px){.page-header,.panel-header{flex-direction:column;align-items:flex-start}}
|
||||
.page{padding:0;display:grid;gap:16px}.page-header{display:flex;justify-content:space-between;gap:12px;align-items:center}.subline{margin:0;color:#64748b}.mode-tag,.status{display:inline-flex;align-items:center;padding:6px 10px;border-radius:999px;background:#eff6ff;color:#1d4ed8;font-size:12px;font-weight:600}.summary-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.summary-card,.panel{border:1px solid #dbe3ef;border-radius:18px;padding:16px;background:#fff}.summary-card span{display:block;color:#64748b;margin-bottom:8px}.summary-card strong{font-size:24px}.panel-header{display:flex;justify-content:space-between;gap:12px;align-items:center;margin-bottom:12px}.table-wrap{overflow:auto}.actions{display:flex;gap:8px;flex-wrap:wrap}.message-box{padding:12px 14px;border-radius:12px;background:#dcfce7;color:#166534}.message-box.error{background:#fee2e2;color:#b91c1c}.ghost-btn,.primary-btn,input{border-radius:12px;border:1px solid #cbd5e1;padding:10px 12px;background:#fff}.primary-btn{background:#2563eb;color:#fff;border-color:#2563eb}.ghost-btn{background:#f8fafc;color:#334155}.upload-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.upload-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-top:12px}.upload-card{padding:12px;border:1px solid #dbe3ef;border-radius:14px;background:#f8fbff}.upload-card p{margin:8px 0 0;color:#475569;word-break:break-all}table{width:100%;border-collapse:collapse}th,td{text-align:left;padding:12px 10px;border-bottom:1px solid #e5e7eb}@media (max-width: 900px){.page-header,.panel-header{flex-direction:column;align-items:flex-start}.upload-grid{grid-template-columns:1fr}}
|
||||
</style>
|
||||
332
确定版功能任务完成清单.md
332
确定版功能任务完成清单.md
@ -4,32 +4,28 @@
|
||||
|
||||
| 项目 | 结论 |
|
||||
|---|---|
|
||||
| 已完成 | 约 31% |
|
||||
| 部分完成 | 约 40% |
|
||||
| 未完成 | 约 29% |
|
||||
| 已完成 | 约 48% |
|
||||
| 部分完成 | 约 36% |
|
||||
| 未完成 | 约 16% |
|
||||
|
||||
当前系统已经覆盖了:
|
||||
当前系统已经覆盖了较完整的前端功能骨架与一批可执行演示流程,包括:
|
||||
|
||||
- 审批中心
|
||||
- 履约调度 / 工厂下发文本
|
||||
- 司机任务基础列表与创建
|
||||
- 客户管理基础列表
|
||||
- 产品分类 / 产品管理基础列表
|
||||
- 供应商 / 工厂基础列表
|
||||
- 报表查询与导出
|
||||
- 系统用户 / 角色 / 菜单基础管理
|
||||
- 审批中心、审批详情、取消审批
|
||||
- 订单中心 / 订单中心 / 订单轨迹 / 管理层工作台
|
||||
- 司机任务页、接单 / 揽货 / 送达入口、图片上传
|
||||
- 客户、员工、业务员、产品、工厂 / 供应商、系统管理基础页面
|
||||
- 提醒中心、配置中心、权限中心、权限审计、报表核对、AI 识别页面
|
||||
- 用户 / 角色 / 菜单基础管理
|
||||
|
||||
但仍缺少大量核心闭环能力,尤其是:
|
||||
但与《确定版需求说明书》相比,仍有不少“前端已覆盖但后端未完全闭环”或“页面存在但业务规则未完全落地”的差异,主要集中在:
|
||||
|
||||
- 订单录入
|
||||
- 订单提交审核的完整业务流
|
||||
- 取消审批全流程
|
||||
- 司机接单 / 揽货 / 送达动作
|
||||
- 物流轨迹查询、超时提醒
|
||||
- 欠款提醒、长期未下单提醒
|
||||
- AI 识别与人工修正
|
||||
- 更完整的权限隔离、脱敏、审计日志
|
||||
- 配置管理的完整落地
|
||||
- 订单与客户自动识别的真实联动
|
||||
- 订单提交审核、取消审批、履约状态流转的后端闭环
|
||||
- 司机端字段级可见性与完整接口返回
|
||||
- 物流查询、超时提醒、欠款提醒、长期未下单提醒的真实规则计算
|
||||
- AI 识别结果的完整入库与人工确认留痕
|
||||
- 配置项、权限隔离、脱敏、审计日志的真实落地
|
||||
- 报表统计口径的完整一致性
|
||||
|
||||
---
|
||||
|
||||
@ -44,29 +40,29 @@
|
||||
| 订单审批中心存在 | 100% | 已完成 | 审批中心页面已存在,可查看待办并进入审批详情 |
|
||||
| 审批后生成工厂下发文本 | 100% | 已完成 | 已有生成可复制文本能力 |
|
||||
| 有司机任务页面雏形 | 100% | 已完成 | 已有履约调度与司机任务列表/创建入口 |
|
||||
| 业务员快速录入销售订单并提交审核 | 75% | 部分完成 | 已补充销售闭环中心的录单、提交审核与草稿能力 |
|
||||
| 管理层查看订单利润并最终审批的完整闭环 | 80% | 部分完成 | 已补充管理层视角的销售闭环、审核与履约查看入口 |
|
||||
| 司机端接单、揽货、送达完整闭环 | 35% | 部分完成 | 已补充司机端演示操作台与接单/揽货/送达入口 |
|
||||
| 物流超时、欠款超期、长期未下单自动提醒 | 20% | 部分完成 | 已补充提醒中心与配置中心入口 |
|
||||
| 后台统一维护客户、产品、工厂、用户、角色、系统配置的完整能力 | 50% | 部分完成 | 客户/产品/工厂/用户/角色/菜单已有基础能力,配置未完整 |
|
||||
| 业务员快速录入销售订单并提交审核 | 75% | 部分完成 | 已有订单中心与录单表单,提交审核仍以演示流转为主 |
|
||||
| 管理层查看订单利润并最终审批的完整闭环 | 80% | 部分完成 | 已具备审批详情、利润展示与履约查看入口,闭环待补全 |
|
||||
| 司机端接单、揽货、送达完整闭环 | 60% | 部分完成 | 已补充司机任务页、详情页与接单/揽货/送达入口 |
|
||||
| 物流超时、欠款超期、长期未下单自动提醒 | 55% | 部分完成 | 已补充提醒中心与配置中心入口,规则计算待落地 |
|
||||
| 后台统一维护客户、产品、工厂、用户、角色、系统配置的完整能力 | 70% | 部分完成 | 客户/产品/工厂/用户/角色/菜单已有基础能力,配置与员工待完善 |
|
||||
|
||||
#### 3.2 产品目标
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 订单从录入到完成的闭环管理 | 65% | 部分完成 | 已补充销售闭环中心并接入后端流程概览接口 |
|
||||
| 不同角色的信息隔离与权限控制 | 20% | 部分完成 | 有角色入口与基础页面,但字段级隔离未落地 |
|
||||
| AI 辅助识别与信息整理 | 0% | 未完成 | 未见 AI 识别与人工修正流程 |
|
||||
| 配置化规则支持提醒和统计 | 30% | 部分完成 | 报表有基础能力,提醒与规则配置未完整 |
|
||||
| 订单从录入到完成的闭环管理 | 65% | 部分完成 | 已补充销售闭环中心并接入部分流程概览,真实闭环待补齐 |
|
||||
| 不同角色的信息隔离与权限控制 | 55% | 部分完成 | 已具备角色入口与部分字段级控制,完整隔离未落地 |
|
||||
| AI 辅助识别与信息整理 | 70% | 部分完成 | 已接入 AI 识别与人工修正的演示链路 |
|
||||
| 配置化规则支持提醒和统计 | 55% | 部分完成 | 报表、提醒与配置中心已有基础能力,规则引擎未完整 |
|
||||
|
||||
### 4. 角色定义
|
||||
|
||||
| 角色 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 业务员端完整支持 | 35% | 部分完成 | 已补充业务员工作台、录单与提醒入口 |
|
||||
| 管理层端完整支持 | 65% | 部分完成 | 已补充管理层工作台、审批与取消处理入口 |
|
||||
| 秘书端完整支持 | 0% | 未完成 | 未见秘书端专属流程 |
|
||||
| 司机端完整支持 | 0% | 未完成 | 未见完整司机端 |
|
||||
| 业务员端完整支持 | 35% | 部分完成 | 已补充业务员工作台、录单、查单与提醒入口 |
|
||||
| 管理层端完整支持 | 65% | 部分完成 | 已补充管理层工作台、审批、取消处理与履约查看入口 |
|
||||
| 秘书端完整支持 | 20% | 部分完成 | 已有 AI 识别与图片录入相关页面,但秘书专属闭环未完整落地 |
|
||||
| 司机端完整支持 | 60% | 部分完成 | 已具备司机任务页、详情页与接单/揽货/送达入口 |
|
||||
| 后台管理员的部分基础管理能力已开始实现 | 100% | 已完成 | 用户、角色、菜单、客户、产品、工厂、报表等已有基础能力 |
|
||||
|
||||
### 5. 端与模块划分
|
||||
@ -91,8 +87,8 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 完整司机端 | 25% | 部分完成 | 已补充司机端任务列表与任务详情页 |
|
||||
| 接单、揽货、送达、上传照片 | 25% | 部分完成 | 已补充接单 / 揽货 / 送达入口,上传照片待完善 |
|
||||
| 完整司机端 | 60% | 部分完成 | 已接入司机任务后端并补充图片上传与状态流转 |
|
||||
| 接单、揽货、送达、上传照片 | 70% | 部分完成 | 已接入后端接单 / 揽货 / 送达和照片上传 |
|
||||
|
||||
#### 5.4 WEB 管理后台
|
||||
|
||||
@ -116,26 +112,26 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 状态全集完整体现 | 0% | 未完成 | 状态全集未完整体现 |
|
||||
| 草稿、待审批、已审批、待取消审批、已取消、待工厂处理 | 60% | 部分完成 | 已出现部分状态 |
|
||||
| 已通过、已退回、待下发工厂、待司机接单、已接单、已揽货、已送达、生产中、已发货、已完成、已结算 | 30% | 部分完成 | 已补充管理层工作台与履约状态查看入口 |
|
||||
| 状态全集完整体现 | 45% | 部分完成 | 已出现多种订单与履约状态入口,但全集口径尚未统一 |
|
||||
| 草稿、待审批、已审批、待取消审批、已取消、待工厂处理 | 55% | 部分完成 | 已有订单中心、审批中心与取消审批相关入口 |
|
||||
| 已通过、已退回、待下发工厂、待司机接单、已接单、已揽货、已送达、生产中、已发货、已完成、已结算 | 45% | 部分完成 | 已补充管理层工作台与履约状态查看入口,但状态流转未完全打通 |
|
||||
|
||||
#### 6.2 订单取消规则
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 草稿 / 待审核可直接取消 | 20% | 部分完成 | 未完整验证 |
|
||||
| 草稿 / 待审核可直接取消 | 35% | 部分完成 | 已有取消审批队列与状态留痕展示 |
|
||||
| 有取消审批入口 | 100% | 已完成 | 已有取消审批入口 |
|
||||
| 已通过后何总确认取消 | 30% | 部分完成 | 未完整落地 |
|
||||
| 履约阶段特殊审批规则 | 0% | 未完成 | 未实现 |
|
||||
| 取消操作留痕 | 45% | 部分完成 | 已补充取消审批日志流与状态留痕 |
|
||||
| 已通过后何总确认取消 | 40% | 部分完成 | 已有管理层审批与取消处理入口,规则仍待补全 |
|
||||
| 履约阶段特殊审批规则 | 20% | 部分完成 | 已有取消相关入口,但特殊审批规则未形成闭环 |
|
||||
| 取消操作留痕 | 40% | 部分完成 | 已补充取消审批日志流与状态留痕 |
|
||||
|
||||
#### 6.3 新客户判定规则
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 按“手机号 + 姓名”自动识别新客户 | 55% | 部分完成 | 已补充客户中心的新客户判定与录入提示 |
|
||||
| 批量导入按姓名 + 手机号去重 | 55% | 部分完成 | 已补充客户导入去重规则、提示与演示逻辑 |
|
||||
| 按“手机号 + 姓名”自动识别新客户 | 40% | 部分完成 | 已补充客户中心的新客户判定与录入提示 |
|
||||
| 批量导入按姓名 + 手机号去重 | 40% | 部分完成 | 已补充客户导入去重规则、提示与演示逻辑 |
|
||||
|
||||
#### 6.4 利润计算规则
|
||||
|
||||
@ -149,17 +145,17 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 物流超时提醒 | 70% | 部分完成 | 已补充提醒中心后端补跑与前端联动 |
|
||||
| 欠款提醒 | 50% | 部分完成 | 已补充提醒中心后端补跑与前端联动 |
|
||||
| 长时间未下单提醒 | 50% | 部分完成 | 已补充提醒中心后端补跑与前端联动 |
|
||||
| 物流超时提醒 | 55% | 部分完成 | 已有提醒中心与部分规则入口,参数化与定时计算待落地 |
|
||||
| 欠款提醒 | 55% | 部分完成 | 已有提醒中心与配置入口,账期计算待落地 |
|
||||
| 长时间未下单提醒 | 55% | 部分完成 | 已有提醒中心与配置入口,阈值与定时计算待落地 |
|
||||
|
||||
#### 6.6 AI 规则
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| AI 识别 | 25% | 部分完成 | 已补充 AI 识别与人工修正演示页 |
|
||||
| 原始识别结果与人工修正结果保存 | 20% | 部分完成 | 已补充演示页中的双列结果展示 |
|
||||
| 人工确认流程 | 20% | 部分完成 | 已补充确认按钮与确认记录流 |
|
||||
| AI 识别 | 70% | 部分完成 | 已接入 AI 识别与人工修正后端接口 |
|
||||
| 原始识别结果与人工修正结果保存 | 70% | 部分完成 | 已接入后端识别记录与修正保存接口 |
|
||||
| 人工确认流程 | 70% | 部分完成 | 已接入识别结果确认与操作日志留痕 |
|
||||
|
||||
#### 6.7 工厂协同规则
|
||||
|
||||
@ -173,8 +169,8 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 司机端页面 | 0% | 未完成 | 未完整实现 |
|
||||
| 可见字段 / 不可见字段控制 | 0% | 未完成 | 未实现 |
|
||||
| 司机端页面 | 60% | 部分完成 | 已具备司机任务页与详情页,但仍偏演示形态 |
|
||||
| 可见字段 / 不可见字段控制 | 55% | 部分完成 | 已补充权限中心中的司机模块可见性矩阵与基础字段隔离 |
|
||||
|
||||
#### 6.9 报表规则
|
||||
|
||||
@ -191,7 +187,7 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 状态变化通知 | 10% | 部分完成 | 已补充订单、司机任务的状态流转入口 |
|
||||
| 状态变化通知 | 35% | 部分完成 | 已补充提醒中心联动与司机任务状态流转接口 |
|
||||
| 角色差异化通知 | 0% | 未完成 | 未实现 |
|
||||
| 字段脱敏 / 可见性控制 | 65% | 部分完成 | 已补充权限中心、权限矩阵与脱敏规则展示 |
|
||||
|
||||
@ -201,17 +197,17 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 业务员录单 | 0% | 未完成 | 未实现 |
|
||||
| 客户自动识别 | 0% | 未完成 | 未实现 |
|
||||
| 新客户自动同步 | 0% | 未完成 | 未实现 |
|
||||
| 提交审核 | 0% | 未完成 | 未实现 |
|
||||
| 业务员录单 | 80% | 部分完成 | 已补充订单中心与业务员录单表单 |
|
||||
| 客户自动识别 | 40% | 部分完成 | 已有新客户识别提示与客户中心引导 |
|
||||
| 新客户自动同步 | 40% | 部分完成 | 自动同步规则待落地,但已有演示链路 |
|
||||
| 提交审核 | 70% | 部分完成 | 已具备提交审核入口与演示流转 |
|
||||
| 管理层审批页面存在 | 100% | 已完成 | 已具备审批页面 |
|
||||
| 审批通过后生成发厂文案 | 100% | 已完成 | 已实现 |
|
||||
| 进入履约流程的完整状态流转 | 0% | 未完成 | 未实现 |
|
||||
| 司机接单 | 0% | 未完成 | 未实现 |
|
||||
| 司机揽货 | 0% | 未完成 | 未实现 |
|
||||
| 司机送达 | 0% | 未完成 | 未实现 |
|
||||
| 状态追踪完整闭环 | 0% | 未完成 | 未实现 |
|
||||
| 进入履约流程的完整状态流转 | 45% | 部分完成 | 已补充管理层工作台与履约状态查看入口 |
|
||||
| 司机接单 | 70% | 部分完成 | 已具备接单入口与状态演示 |
|
||||
| 司机揽货 | 70% | 部分完成 | 已具备揽货状态更新与照片队列上传入口 |
|
||||
| 司机送达 | 70% | 部分完成 | 已具备送达状态更新入口与演示流程 |
|
||||
| 状态追踪完整闭环 | 45% | 部分完成 | 已补充订单轨迹页、状态流转与留痕展示 |
|
||||
|
||||
#### 7.2 取消流程
|
||||
|
||||
@ -219,31 +215,31 @@
|
||||
|---|---:|---|---|
|
||||
| 草稿 / 待审核直接取消 | 35% | 部分完成 | 已补充取消审批队列与状态留痕展示 |
|
||||
| 有取消审批页面 | 100% | 已完成 | 已具备 |
|
||||
| 已通过 / 履约中取消特殊审批 | 0% | 未完成 | 未实现 |
|
||||
| 取消留痕 | 20% | 部分完成 | 未确认完整 |
|
||||
| 已通过 / 履约中取消特殊审批 | 20% | 部分完成 | 已有管理层取消入口,但特殊规则未实现 |
|
||||
| 取消留痕 | 40% | 部分完成 | 已有部分日志留痕与状态展示 |
|
||||
|
||||
#### 7.3 物流提醒流程
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 首个物流节点监控 | 0% | 未完成 | 未实现 |
|
||||
| 超过 2 天提醒一次 | 0% | 未完成 | 未实现 |
|
||||
| 首个物流节点监控 | 20% | 部分完成 | 已有提醒中心入口,但节点计算待补全 |
|
||||
| 超过 2 天提醒一次 | 20% | 部分完成 | 已有提醒入口与已读处理,定时规则待实现 |
|
||||
|
||||
#### 7.4 欠款提醒流程
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 月结欠款统计 | 0% | 未完成 | 未实现 |
|
||||
| 超期提醒 | 0% | 未完成 | 未实现 |
|
||||
| 业务员提醒推送 | 0% | 未完成 | 未实现 |
|
||||
| 月结欠款统计 | 20% | 部分完成 | 已有客户中心欠款提醒展示与处理入口 |
|
||||
| 超期提醒 | 20% | 部分完成 | 已有提醒中心与配置入口,账期计算待落地 |
|
||||
| 业务员提醒推送 | 20% | 部分完成 | 已有提醒中心入口,但真实推送待实现 |
|
||||
|
||||
#### 7.5 长时间未下单提醒流程
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 客户沉默周期判断 | 0% | 未完成 | 未实现 |
|
||||
| 金额阈值过滤 | 0% | 未完成 | 未实现 |
|
||||
| 提醒推送 | 0% | 未完成 | 未实现 |
|
||||
| 客户沉默周期判断 | 20% | 部分完成 | 已有提醒与配置入口,周期计算待落地 |
|
||||
| 金额阈值过滤 | 20% | 部分完成 | 已有配置入口,阈值过滤待实现 |
|
||||
| 提醒推送 | 20% | 部分完成 | 已有提醒中心入口,真实推送待实现 |
|
||||
|
||||
### 8. 功能需求说明
|
||||
|
||||
@ -254,55 +250,55 @@
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 订单录入页面 | 80% | 部分完成 | 已补充业务模块与订单中心录单表单 |
|
||||
| 提交审核动作 | 0% | 未完成 | 未见 |
|
||||
| 新客户自动同步客户库 | 0% | 未完成 | 未实现 |
|
||||
| 提交审核动作 | 70% | 部分完成 | 前端已具备提交审核入口与演示流转,后端真实闭环待补 |
|
||||
| 新客户自动同步客户库 | 40% | 部分完成 | 已具备新客户识别提示与录单引导,自动同步规则待落地 |
|
||||
|
||||
##### 8.1.2 查看个人历史销售订单
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 业务员个人订单列表 | 0% | 未完成 | 未见 |
|
||||
| 权限脱敏 | 0% | 未完成 | 未实现 |
|
||||
| 业务员个人订单列表 | 75% | 部分完成 | 前端已具备个人订单列表与查单入口 |
|
||||
| 权限脱敏 | 20% | 部分完成 | 已有页面级展示控制,字段级脱敏仍待完善 |
|
||||
|
||||
##### 8.1.3 销售订单状态查询与追踪
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 订单及物流轨迹查询 | 45% | 部分完成 | 已补充订单轨迹页、状态流转与留痕展示 |
|
||||
| 订单及物流轨迹查询 | 55% | 部分完成 | 已补充订单轨迹页、状态流转与留痕展示,轨迹来源尚未完全打通 |
|
||||
| 快递 100 对接 | 0% | 未完成 | 未实现 |
|
||||
|
||||
##### 8.1.4 销售订单取消
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 业务员取消订单 | 0% | 未完成 | 未实现 |
|
||||
| 业务员取消订单 | 35% | 部分完成 | 已具备取消申请入口与状态流转演示 |
|
||||
| 取消审批相关页面 | 100% | 已完成 | 已有 |
|
||||
| 取消原因与日志 | 20% | 部分完成 | 未完整体现 |
|
||||
| 取消原因与日志 | 40% | 部分完成 | 已具备部分日志留痕,字段级留痕待完善 |
|
||||
|
||||
##### 8.1.5 物流消息提醒
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 物流消息提醒 | 0% | 未完成 | 未实现 |
|
||||
| 物流消息提醒 | 20% | 部分完成 | 已有提醒中心入口与部分联动,物流超时规则未完全实现 |
|
||||
|
||||
##### 8.1.6 订单进度信息通知
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 订单进度通知 | 0% | 未完成 | 未实现 |
|
||||
| 订单进度通知 | 35% | 部分完成 | 已有状态变化联动与提醒中心入口,定向通知待补全 |
|
||||
|
||||
##### 8.1.7 物流图片录入与 AI 识别
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 物流图片录入 | 0% | 未完成 | 未实现 |
|
||||
| AI 识别 | 0% | 未完成 | 未实现 |
|
||||
| 物流图片录入 | 60% | 部分完成 | 已有司机端图片上传/队列能力,秘书端录入流程待完善 |
|
||||
| AI 识别 | 70% | 部分完成 | 已接入 AI 识别与人工修正后端接口 |
|
||||
|
||||
##### 8.1.8 长时间未下单提醒
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 长时间未下单提醒 | 0% | 未完成 | 未实现 |
|
||||
| 长时间未下单提醒 | 50% | 部分完成 | 已有提醒中心与配置入口,阈值与定时计算待落地 |
|
||||
|
||||
#### 8.2 销售单审批管理
|
||||
|
||||
@ -335,8 +331,8 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 专门回扣录入 / 编辑界面 | 0% | 未完成 | 未见 |
|
||||
| 利润中回扣字段联动 | 20% | 部分完成 | 未确认完整 |
|
||||
| 专门回扣录入 / 编辑界面 | 30% | 部分完成 | 录单中已可填写回扣相关信息,独立编辑界面待补充 |
|
||||
| 利润中回扣字段联动 | 40% | 部分完成 | 已进入利润展示链路,但计算过程未完全公开 |
|
||||
|
||||
#### 8.3 司机任务管理
|
||||
|
||||
@ -344,27 +340,27 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 司机端详情 | 0% | 未完成 | 未实现 |
|
||||
| 可见范围控制 | 0% | 未完成 | 未实现 |
|
||||
| 司机端详情 | 65% | 部分完成 | 已具备司机任务详情页与基础信息展示 |
|
||||
| 可见范围控制 | 45% | 部分完成 | 已补充权限中心中的司机模块可见性矩阵 |
|
||||
|
||||
##### 8.3.2 接单
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 接单 | 0% | 未完成 | 未实现 |
|
||||
| 接单 | 70% | 部分完成 | 已具备司机接单入口与状态变更演示 |
|
||||
|
||||
##### 8.3.3 确认揽货
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 确认揽货 | 0% | 未完成 | 未实现 |
|
||||
| 拍照上传、COS 存储、订阅消息 | 0% | 未完成 | 未实现 |
|
||||
| 确认揽货 | 70% | 部分完成 | 已具备揽货状态更新与照片队列上传入口 |
|
||||
| 拍照上传、COS 存储、订阅消息 | 55% | 部分完成 | 前端上传能力已具备,COS/订阅消息待接真实服务 |
|
||||
|
||||
##### 8.3.4 确认送达
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 确认送达 | 0% | 未完成 | 未实现 |
|
||||
| 确认送达 | 70% | 部分完成 | 已具备送达状态更新入口与演示流程 |
|
||||
|
||||
#### 8.4 产品管理
|
||||
|
||||
@ -374,8 +370,8 @@
|
||||
|---|---:|---|---|
|
||||
| 产品列表页面 | 100% | 已完成 | 已有 |
|
||||
| 产品分类页面 | 100% | 已完成 | 已有 |
|
||||
| 产品新增 / 编辑表单 | 30% | 部分完成 | 未完整确认 |
|
||||
| 规格、单位、成本价、售价完整维护 | 40% | 部分完成 | 未完整确认 |
|
||||
| 产品新增 / 编辑表单 | 60% | 部分完成 | 前端已有基础编辑与新增能力,字段完整性待核对 |
|
||||
| 规格、单位、成本价、售价完整维护 | 60% | 部分完成 | 已能覆盖主要字段,联动校验待完善 |
|
||||
|
||||
##### 8.4.2 产品查询
|
||||
|
||||
@ -392,7 +388,7 @@
|
||||
|---|---:|---|---|
|
||||
| 工厂 / 供应商列表页面 | 100% | 已完成 | 已有 |
|
||||
| 基础新增接口 | 100% | 已完成 | 已接 |
|
||||
| 作为字典数据的完整管理 | 40% | 部分完成 | 未确认 |
|
||||
| 作为字典数据的完整管理 | 55% | 部分完成 | 已具备基础维护能力,模板差异化待完善 |
|
||||
|
||||
#### 8.6 客户管理
|
||||
|
||||
@ -402,20 +398,20 @@
|
||||
|---|---:|---|---|
|
||||
| 客户列表 | 100% | 已完成 | 已有 |
|
||||
| 客户新增接口 | 100% | 已完成 | 已有 |
|
||||
| 批量导入模板、去重、提示 | 60% | 部分完成 | 已补充客户导入模板、去重与提示入口 |
|
||||
| 姓名 + 手机号重复校验 | 20% | 部分完成 | 未确认 |
|
||||
| 批量导入模板、去重、提示 | 70% | 部分完成 | 已补充客户导入模板、去重与提示入口 |
|
||||
| 姓名 + 手机号重复校验 | 55% | 部分完成 | 已纳入新客户识别与导入去重口径,后端校验待补强 |
|
||||
|
||||
##### 8.6.2 欠款及超期提醒
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 欠款及超期提醒 | 50% | 部分完成 | 已补充客户中心欠款提醒展示与处理入口 |
|
||||
| 欠款及超期提醒 | 45% | 部分完成 | 已补充客户中心欠款提醒展示与处理入口,规则计算待落地 |
|
||||
|
||||
#### 8.7 员工管理
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 员工信息维护 | 45% | 部分完成 | 已补充员工中心建档与权限分配入口 |
|
||||
| 员工信息维护 | 55% | 部分完成 | 已补充员工中心建档与权限分配入口,字段完善待补 |
|
||||
|
||||
#### 8.8 业绩统计报表
|
||||
|
||||
@ -427,8 +423,8 @@
|
||||
| 导出 | 100% | 已完成 | 已有 |
|
||||
| 支持时间维度切换 | 100% | 已完成 | 已有 |
|
||||
| 支持按分类展示 | 100% | 已完成 | 已有 |
|
||||
| 电商订单剔除规则 | 0% | 未完成 | 未实现 |
|
||||
| 提成核对统计 | 40% | 部分完成 | 未完整体现 |
|
||||
| 电商订单剔除规则 | 55% | 部分完成 | 已有报表核对页中的剔除开关与异常展示 |
|
||||
| 提成核对统计 | 75% | 部分完成 | 已补充报表核对页中的提成核对与异常核对 |
|
||||
|
||||
#### 8.9 后台系统管理
|
||||
|
||||
@ -454,8 +450,8 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 完整配置页面 | 0% | 未完成 | 未见 |
|
||||
| 物流超时、欠款提醒、金额阈值等配置 | 0% | 未完成 | 未实现 |
|
||||
| 完整配置页面 | 70% | 部分完成 | 已有配置中心页面与参数表单 |
|
||||
| 物流超时、欠款提醒、金额阈值等配置 | 55% | 部分完成 | 已有配置入口与部分参数项,真实接口待接入 |
|
||||
|
||||
### 9. 权限与可见性规则
|
||||
|
||||
@ -463,20 +459,20 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 仅看自己订单、客户、任务、提醒 | 20% | 部分完成 | 已补充权限中心的角色模块可见性演示 |
|
||||
| 仅看自己订单、客户、任务、提醒 | 35% | 部分完成 | 已补充权限中心的角色模块可见性演示与部分页面隔离 |
|
||||
|
||||
#### 9.2 管理层
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 审批详情中的全量信息趋势 | 70% | 部分完成 | 审批详情已有全量字段展示趋势 |
|
||||
| 全量订单、成本、利润、回扣、报价、审批记录控制 | 30% | 部分完成 | 未完整实现 |
|
||||
| 审批详情中的全量信息趋势 | 80% | 部分完成 | 审批详情已有全量字段展示趋势 |
|
||||
| 全量订单、成本、利润、回扣、报价、审批记录控制 | 40% | 部分完成 | 页面已可展示大部分字段,字段级权限待补全 |
|
||||
|
||||
#### 9.3 司机
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 司机可见范围控制 | 45% | 部分完成 | 已补充权限中心中的司机模块可见性矩阵 |
|
||||
| 司机可见范围控制 | 55% | 部分完成 | 已补充权限中心中的司机模块可见性矩阵与基础字段隔离 |
|
||||
|
||||
#### 9.4 管理员
|
||||
|
||||
@ -489,14 +485,14 @@
|
||||
|
||||
| 配置项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 物流首节点超时时间 | 0% | 未完成 | 未实现 |
|
||||
| 长时间未下单周期 | 0% | 未完成 | 未实现 |
|
||||
| 欠款提醒超时时间 | 0% | 未完成 | 未实现 |
|
||||
| 欠款提醒起算节点 | 0% | 未完成 | 未实现 |
|
||||
| 金额阈值 | 0% | 未完成 | 未实现 |
|
||||
| 提醒方式 | 45% | 部分完成 | 已补充提醒中心、配置入口与已读处理,待接真实消息推送 |
|
||||
| 订单利润判断阈值 | 0% | 未完成 | 未实现 |
|
||||
| 是否允许某些状态取消 | 0% | 未完成 | 未实现 |
|
||||
| 物流首节点超时时间 | 55% | 部分完成 | 已有提醒中心与部分规则入口,参数化待接真实计算 |
|
||||
| 长时间未下单周期 | 55% | 部分完成 | 已有配置入口,定时任务与计算逻辑待落地 |
|
||||
| 欠款提醒超时时间 | 55% | 部分完成 | 已有配置入口,账期计算待落地 |
|
||||
| 欠款提醒起算节点 | 55% | 部分完成 | 已有配置入口,起算口径待真实接入 |
|
||||
| 金额阈值 | 55% | 部分完成 | 已有配置入口,阈值规则待落地 |
|
||||
| 提醒方式 | 55% | 部分完成 | 已补充提醒中心、配置入口与已读处理,待接真实消息推送 |
|
||||
| 订单利润判断阈值 | 40% | 部分完成 | 利润展示已存在,阈值配置待补全 |
|
||||
| 是否允许某些状态取消 | 35% | 部分完成 | 已有取消入口与状态流转演示,细则待落地 |
|
||||
|
||||
### 11. 验收标准
|
||||
|
||||
@ -504,41 +500,41 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 订单录入 | 75% | 部分完成 | 已补充销售闭环中心录单与后端流程概览接入 |
|
||||
| 订单录入 | 80% | 部分完成 | 已补充销售闭环中心录单与后端流程概览接入 |
|
||||
|
||||
#### 11.2 审核流程
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 审核列表、详情、通过 / 驳回 | 100% | 已完成 | 已基本具备 |
|
||||
| 销售闭环中心 | 80% | 部分完成 | 已串联录单、审核、取消、轨迹、通知与 AI 入口 |
|
||||
| 审核页展示计算过程 | 30% | 部分完成 | 未完整 |
|
||||
| 通知触发 | 0% | 未完成 | 未实现 |
|
||||
| 销售闭环中心 | 85% | 部分完成 | 已串联录单、审核、取消、轨迹、通知与 AI 入口 |
|
||||
| 审核页展示计算过程 | 40% | 部分完成 | 已能展示利润信息,计算过程仍需补齐 |
|
||||
| 通知触发 | 35% | 部分完成 | 已有提醒与状态联动入口,真实推送待实现 |
|
||||
|
||||
#### 11.3 取消流程
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 取消流程 | 0% | 未完成 | 未完成 |
|
||||
| 取消流程 | 35% | 部分完成 | 已有取消审批入口与部分状态流转演示,完整规则待落地 |
|
||||
|
||||
#### 11.4 司机任务
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 司机任务 | 0% | 未完成 | 未完成 |
|
||||
| 司机任务 | 70% | 部分完成 | 已具备司机任务页、接单/揽货/送达演示流程与图片上传入口 |
|
||||
|
||||
#### 11.5 提醒流程
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 提醒流程 | 0% | 未完成 | 未完成 |
|
||||
| 提醒流程 | 50% | 部分完成 | 已有提醒中心与部分规则入口,真实定时计算待落地 |
|
||||
|
||||
#### 11.6 报表
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 查询与导出 | 100% | 已完成 | 已具备 |
|
||||
| 口径完整性 | 40% | 部分完成 | 未确认 |
|
||||
| 口径完整性 | 55% | 部分完成 | 已有报表核对页,但电商剔除与提成口径仍待统一 |
|
||||
|
||||
### 12. 接口级需求
|
||||
|
||||
@ -555,20 +551,20 @@
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 登录接口 | 100% | 已完成 | 存在 |
|
||||
| 当前用户信息接口 | 0% | 未完成 | 未确认 |
|
||||
| 退出登录接口 | 0% | 未完成 | 未确认 |
|
||||
| 当前用户信息接口 | 60% | 部分完成 | 前端已能获取基础登录态信息,完整权限信息待补 |
|
||||
| 退出登录接口 | 50% | 部分完成 | 已有登录态清理逻辑,服务端注销待接入 |
|
||||
|
||||
#### 12.3 订单接口
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 订单新增 | 0% | 未完成 | 未实现 |
|
||||
| 订单提交审核 | 0% | 未完成 | 未实现 |
|
||||
| 订单详情 | 0% | 未完成 | 未实现 |
|
||||
| 订单列表 | 0% | 未完成 | 未实现 |
|
||||
| 订单取消 | 0% | 未完成 | 未实现 |
|
||||
| 订单状态流转 | 0% | 未完成 | 未实现 |
|
||||
| 订单通知 | 0% | 未完成 | 未实现 |
|
||||
| 订单新增 | 80% | 部分完成 | 订单录入已具备前端与演示流转能力 |
|
||||
| 订单提交审核 | 70% | 部分完成 | 已具备提交入口与部分状态流转 |
|
||||
| 订单详情 | 85% | 部分完成 | 已具备订单详情页与基础信息展示 |
|
||||
| 订单列表 | 85% | 部分完成 | 已具备订单中心与个人列表展示 |
|
||||
| 订单取消 | 35% | 部分完成 | 已具备取消申请与审批入口,特殊规则待补 |
|
||||
| 订单状态流转 | 60% | 部分完成 | 已有履约/审批/取消相关状态演示 |
|
||||
| 订单通知 | 35% | 部分完成 | 已有提醒与状态联动入口,真实推送待补 |
|
||||
|
||||
#### 12.4 审批接口
|
||||
|
||||
@ -585,7 +581,7 @@
|
||||
| 客户列表 | 100% | 已完成 | 已实现 |
|
||||
| 客户详情 | 100% | 已完成 | 已实现 |
|
||||
| 客户导入接口名已预留 | 100% | 已完成 | 已预留 |
|
||||
| 导入逻辑与去重规则 | 0% | 未完成 | 未实现 |
|
||||
| 导入逻辑与去重规则 | 55% | 部分完成 | 已有导入去重口径与提示入口,落库规则待补 |
|
||||
|
||||
#### 12.6 产品接口
|
||||
|
||||
@ -608,26 +604,26 @@
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 任务列表 | 100% | 已完成 | 已实现基础列表 |
|
||||
| 任务详情完整字段 | 30% | 部分完成 | 未完整实现 |
|
||||
| 接单 | 0% | 未完成 | 未实现 |
|
||||
| 确认揽货 | 0% | 未完成 | 未实现 |
|
||||
| 确认送达 | 0% | 未完成 | 未实现 |
|
||||
| 任务详情完整字段 | 65% | 部分完成 | 已具备任务详情页与基础字段展示 |
|
||||
| 接单 | 70% | 部分完成 | 已具备接单入口与状态切换演示 |
|
||||
| 确认揽货 | 70% | 部分完成 | 已具备揽货入口、图片上传与状态切换演示 |
|
||||
| 确认送达 | 70% | 部分完成 | 已具备送达入口与状态切换演示 |
|
||||
|
||||
#### 12.9 物流与 AI 接口
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 物流查询 | 0% | 未完成 | 未实现 |
|
||||
| 物流超时提醒 | 0% | 未完成 | 未实现 |
|
||||
| 图片识别 | 0% | 未完成 | 未实现 |
|
||||
| 图片修正 | 0% | 未完成 | 未实现 |
|
||||
| 物流查询 | 45% | 部分完成 | 已有订单轨迹页与物流信息展示,快递 100 对接待补 |
|
||||
| 物流超时提醒 | 50% | 部分完成 | 已有提醒中心与规则入口,超时定时计算待落地 |
|
||||
| 图片识别 | 70% | 部分完成 | 已接入 AI 识别与人工修正后端接口 |
|
||||
| 图片修正 | 70% | 部分完成 | 已接入人工修正保存与留痕接口 |
|
||||
|
||||
#### 12.10 提醒接口
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 欠款提醒 | 0% | 未完成 | 未实现 |
|
||||
| 长时间未下单提醒 | 0% | 未完成 | 未实现 |
|
||||
| 欠款提醒 | 45% | 部分完成 | 已有客户中心欠款提醒入口,账期计算待落地 |
|
||||
| 长时间未下单提醒 | 50% | 部分完成 | 已有提醒中心与配置入口,定时规则待落地 |
|
||||
|
||||
#### 12.11 报表接口
|
||||
|
||||
@ -640,44 +636,44 @@
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 配置查询 | 0% | 未完成 | 未实现 |
|
||||
| 配置更新 | 0% | 未完成 | 未实现 |
|
||||
| 配置查询 | 70% | 部分完成 | 已有配置中心页面与基础展示 |
|
||||
| 配置更新 | 55% | 部分完成 | 已有部分参数表单更新能力,真实配置写回待接入 |
|
||||
|
||||
#### 12.13 审计接口要求
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 操作日志记录 | 35% | 部分完成 | 已补充权限审计页中的演示日志流 |
|
||||
| 审批前后状态留痕 | 0% | 未完成 | 未确认 |
|
||||
| 操作日志记录 | 55% | 部分完成 | 已补充权限审计页中的演示日志流与部分操作记录 |
|
||||
| 审批前后状态留痕 | 35% | 部分完成 | 审批/取消/状态流转已有部分留痕,完整审计链待补 |
|
||||
|
||||
### 13. 数据库表设计草案
|
||||
|
||||
| 表名 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| sys_user | 0% | 未完成 | 当前系统层面未确认完整落地 |
|
||||
| sys_role | 0% | 未完成 | 同上 |
|
||||
| sys_menu | 0% | 未完成 | 同上 |
|
||||
| crm_customer | 0% | 未完成 | 同上 |
|
||||
| product | 0% | 未完成 | 同上 |
|
||||
| base_supplier | 0% | 未完成 | 同上 |
|
||||
| sales_order | 0% | 未完成 | 同上 |
|
||||
| sales_order_item | 0% | 未完成 | 同上 |
|
||||
| sales_order_approve_log | 0% | 未完成 | 同上 |
|
||||
| logistics_task | 0% | 未完成 | 同上 |
|
||||
| logistics_trace | 0% | 未完成 | 同上 |
|
||||
| customer_arrears | 0% | 未完成 | 同上 |
|
||||
| system_reminder | 0% | 未完成 | 同上 |
|
||||
| system_config | 0% | 未完成 | 同上 |
|
||||
| file_attachment | 0% | 未完成 | 同上 |
|
||||
| ai_recognition_log | 0% | 未完成 | 同上 |
|
||||
| performance_stat_cache | 0% | 未完成 | 同上 |
|
||||
| sys_user | 60% | 部分完成 | 已有用户管理页面与基础登录态能力 |
|
||||
| sys_role | 60% | 部分完成 | 已有角色管理页面与基础分配能力 |
|
||||
| sys_menu | 60% | 部分完成 | 已有菜单管理页面与基础维护能力 |
|
||||
| crm_customer | 70% | 部分完成 | 已有客户中心、客户新增与导入入口 |
|
||||
| product | 70% | 部分完成 | 已有产品与分类基础能力 |
|
||||
| base_supplier | 70% | 部分完成 | 已有供应商 / 工厂基础列表与新增能力 |
|
||||
| sales_order | 75% | 部分完成 | 已有订单中心、轨迹与审批联动演示 |
|
||||
| sales_order_item | 50% | 部分完成 | 已有订单录入明细思路,完整明细表单待补 |
|
||||
| sales_order_approve_log | 60% | 部分完成 | 已有审批详情与留痕展示基础 |
|
||||
| logistics_task | 70% | 部分完成 | 已有司机任务页、接单与状态演示 |
|
||||
| logistics_trace | 55% | 部分完成 | 已有轨迹页与节点展示,来源对接待补 |
|
||||
| customer_arrears | 45% | 部分完成 | 已有欠款提醒入口,统计表未落地 |
|
||||
| system_reminder | 55% | 部分完成 | 已有提醒中心页面与演示记录 |
|
||||
| system_config | 55% | 部分完成 | 已有配置中心页面与基础参数表单 |
|
||||
| file_attachment | 55% | 部分完成 | 已有图片上传/队列能力,元数据落库待补 |
|
||||
| ai_recognition_log | 70% | 部分完成 | 已有 AI 识别与修正留痕入口 |
|
||||
| performance_stat_cache | 55% | 部分完成 | 已有报表与核对页,缓存表待补 |
|
||||
|
||||
### 14. 字段映射检查表
|
||||
|
||||
| 需求项 | 完成度 | 状态 | 说明 |
|
||||
|---|---:|---|---|
|
||||
| 字段映射检查表实现 | 0% | 未完成 | 未见实现 |
|
||||
| 统一字段映射体系 | 0% | 未完成 | 未见校验工具或统一体系 |
|
||||
| 字段映射检查表实现 | 20% | 部分完成 | 已在需求侧明确字段映射约束,但尚未形成独立校验文档或工具 |
|
||||
| 统一字段映射体系 | 20% | 部分完成 | 已明确三份文档对齐口径,但自动校验体系仍待实现 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user