views/water/content 改为参考图列表+手机双栏布局,分离 ContentEditor/ContentPhone/ContentPreviewDialog,接口类型在 api/water/content.ts。搜索状态筛选、8条分页、全量上线统计、选中素材/草稿预览、按身份区域模拟预览均接入后端。server/docs/WATER_CONTENT.md。浏览器仍受既有工具认证故障限制。withdrawal_demo(list/total/amount_cents),待审核区显示4条持久化测试申请,测试卡片合计12360元;名称/状态/说明明确模拟,无真实余额或打款。按月份、all/demo显示,regular隐藏;正式提现权限能力及按钮仍未开通。server/docs/WATER_FINANCE.md;原收款汇总、流水与导出不混入测试提现。/water-finance 使用 api/water/finance.ts 与 views/water/finance/{index.vue,ReceiptDialog.vue,finance.scss},已完成参考图四卡/趋势/月汇总/提现占位/流水布局。月份、测试范围、搜索、8条分页、详情、全量匹配XLSX导出接入真实供水接口。saveWater('finance',{action:'purchase',...}),企业和套餐远程选项、金额权益预览、凭据校验与核对勾选、提交锁和失败保留输入。后端凭据幂等,不重复发放权益。按钮校验 finance:write。server/docs/WATER_FINANCE.md。unsupported Codex auth method: apikey 不能点击或截图验收;接口及后端测试已通过。catalog.ts代理商region使用新region-map字段类型,WaterWorkspace交由WaterRegionField显示只读区域、地图选择、清空;已有值原样保留,选图确认后回填,代理商保存才提交。WaterLocationPicker.vue支持点坐标和行政区名称模式;原DispatchLocationPicker为兼容包装,配送调用不变。findMapRegion使用高德逆地理编码,去重直辖市省/市并兼容空city;没有识别结果或失败时禁止确认。node scripts/test-water-region.mjs覆盖行政区、直辖市、缺区县、空结果和配额错误;原道路规划脚本、ESLint/vue-tsc及Vite构建验证。未修改既有代理商数据和数据库结构,浏览器实际选图验收仍未完成。src/views/index/index.vue 导入同目录 water-layout.scss。此前依赖业务页懒加载,直接刷新独立设备/库存页会显示默认白色,访问总览后才恢复。src/views/water/modules/water.scss 仅保留业务页规则;以后独立页面无需为导航导入该文件。布局仍按原 /water- 路由范围应用品牌主题。FulfillmentDialog.vue(实收/部分签收/拒收、退回核对、关联重送、返仓结算)及 DeliveryHistory.vue 履约记录。任务展示实收数量、异常、父子重送编号和结算时间,新增待退回/已退回筛选;总览同步异常统计。server/docs/WATER_FULFILLMENT.md。当前为后台人工确认,未接入配送员移动端或客户电子签名。本轮浏览器工具运行时启动失败,未做视觉验收。项目:
D:\phpstudy_pro\WWW\saiadmin6.x\saiadmin-artd记录日期:2026-08-25
本文件只记录该前端子项目。父项目
saiadmin6.x的记忆仍单独保存在父目录,不要混用。
这是 SaiAdmin 6.x 配套的管理后台前端,当前与父项目中的 Webman 后端配套使用。项目包含登录、动态菜单权限、系统管理、商户管理、设备、订单、资金、运营管理、小程序和后台维护等页面。
当前重点业务已于 2026-09-09 调整为云泉智配企业供水:企业档案、套餐权益、库存、补货与配送。旧商户管理页面及数据保留。
src/views/water,共享表单/列表 modules/WaterWorkspace.vue,总览单独实现;API src/api/water。src/router/modules/water.ts 根据已授权菜单调整显示顺序并隐藏旧一级导航,不主动补发新业务权限。src/store/modules/menu.ts 优先将已授权 /water-overview 设为首页。.water-layout 和 .water-page,品牌名为“云泉智配”,保留用户其他页面设置。server/docs/WATER_MERGE.md。为验证15条演示预警分页,WaterWorkspace.vue 将补货模块页大小及API的limit统一为10,其他模块保持20。新增10家不同名称企业及东/西/南/北区域、山泉水/纯净水规格供筛选;数据脚本见父项目 server/scripts/seed_water_alert_search_demo.php。
补货搜索实际按企业名称/区域/规格模糊查询。用户反馈无效时已复现名称查询返回1条;搜索“1”会命中全部0910/18.9演示数据。页面已校正提示、增加重置及无匹配文案,并限制120字、去除首尾空格。
搜索调整通过vue-tsc、ESLint及Vite构建;浏览器验证名称查询1条、回车无匹配0条、重置恢复5条。
WaterWorkspace.vue 增加仅预警/全部启用账户切换、数量阈值编辑、预警桶数列及当前页多选;切换查询清空选择,已建单或无可用权益账户不能批量选择。
modules/BatchDeliveryDialog.vue 独立维护逐条配送数量和确认过程,列出地址、权益与现场满桶;未填数量不能提交,错误时保留表单,提交期间阻止重复提交或关闭。
策略保存使用 saveWater('alerts',{action:'policy',id,threshold_qty});批量保存使用 saveWater('dispatch',{action:'batch_create',items:[{account_id,quantity}]})。按钮分别检查已有 alerts/dispatch write 权限。
vue-tsc、相关 ESLint、Prettier 和 Vite production build 通过(3247 modules);4173 浏览器确认入口、列和零数据布局。后端 69 项事务回滚检查通过;未在浏览器创建实际业务数据,非空弹窗仍待实际数据验收。
Vue 3 + TypeScript + Vite 7
Element Plus、Pinia、Vue Router 4、Axios、VueUse、Vue I18n
ECharts 6、Tailwind CSS 4、WangEditor、XLSX、FileSaver
包管理器:pnpm
Node 要求:>=20.19.0;已知本机 Node:v22.21.0
项目依赖目录 node_modules 已存在;如果 pnpm 未加入 PATH,可直接使用 node_modules/.bin 中的工具
常用命令:
pnpm dev # 开发服务器,默认端口 3006
pnpm build # vue-tsc --noEmit 后执行 vite build
pnpm lint # ESLint
pnpm serve # 预览构建结果
已知验证结果:
vue-tsc --noEmit 已通过环境文件:.env、.env.development、.env.production。不要把密钥值写入项目记忆。
关键变量:
VITE_ACCESS_MODE=backend:当前使用后端菜单模式VITE_API_URL:Axios 的 baseURL;开发环境为 /apiVITE_API_PROXY_URL:开发代理目标,当前为 http://127.0.0.1:8787VITE_BASE_URL:当前为 /VITE_PORT:当前开发端口为 3006VITE_WITH_CREDENTIALS:是否携带 CookieVITE_VERSION、VITE_DROP_CONSOLE、VITE_OPEN_ROUTE_INFOVITE_LOCK_ENCRYPT_KEY:锁屏相关密钥,仅使用环境文件中的值,不复制到记忆vite.config.ts 将 /api 代理到 Webman 后端 127.0.0.1:8787,并去除 /api 前缀。生产环境默认直接访问 http://127.0.0.1:8787,部署时需按实际后端地址调整环境配置。
src/main.ts:创建 App,初始化 Pinia、Router、语言、指令和错误处理src/App.vue:Element Plus 配置、主题、存储兼容性和系统升级检查src/api/:按业务拆分的 Axios API 封装(当前约 31 个文件)src/views/:页面组件(当前约 132 个文件)src/components/core/:通用后台布局、表单、表格、图表和基础组件src/components/sai/:项目业务组件,例如 SaSearchBar、SaDict、上传和导入导出组件src/store/:Pinia storesrc/router/:静态路由、动态路由、守卫和路由转换核心src/locales/:多语言资源src/config/:系统名称、主题、布局和头部配置src/types/:API、路由、组件、配置和 store 类型src/assets/:图片、SVG 和样式页面通常按 src/views/<业务>/<页面>/index.vue 组织,复杂页面的子组件放在同级 modules/ 目录。API 按业务放在 src/api/<业务>/,例如 src/api/merchant/merchant.ts。
Vite 别名:@ 指向 src,另有 @views、@imgs、@icons、@utils、@stores、@styles。
src/router/index.ts 使用 createWebHashHistory(),因此访问地址形如 /#/merchant/statistics?id=73src/router/routes/staticRoutes.ts 注册登录、注册、忘记密码、403、404、500 和 iframe 等静态路由src/router/routes/asyncRoutes.ts 汇总前端模块路由src/router/modules/ 保存 dashboard、system、merchant、mini-program、operations 等模块路由src/router/guards/beforeEach.ts 并行获取用户信息、字典和菜单,然后注册动态路由src/router/core/MenuProcessor.ts 根据 VITE_ACCESS_MODE 在前端菜单和后端菜单之间切换;当前是 backend 模式,通过 /core/system/menu 获取菜单RouteRegistry 负责注册/移除动态路由;RouteTransformer 负责 Layout、iframe、全屏页和普通组件转换ComponentLoader 使用 import.meta.glob('../../views/**/*.vue') 按需懒加载页面,组件字段通常写成 /merchant/my-merchant 这类视图路径RoutePermissionValidator 负责路径、动态参数和菜单前缀权限匹配修改后端菜单时要特别注意:后端返回的 path、name、component、children、meta 必须符合 AppRouteRecord 和 RouteValidator 规则;二级及以下菜单不要错误使用 Layout 作为 component。
统一请求封装在 src/utils/http/index.ts:
VITE_API_URLuseUserStore().accessToken 读取令牌,并添加 Authorization: Bearer <token>params 且没有 data,封装层会把 params 转成请求体{ code: 200, message: string, data: T };封装层最终返回 dataHttpError;401 会防抖提示、清理登录状态并跳转登录MAX_RETRIES=0,虽然保留了可配置重试逻辑,但默认不会自动重试responseType: 'blob' 时直接返回二进制响应,用于导出文件认证 API 在 src/api/auth.ts:
GET /core/captchaPOST /core/loginGET /core/system/userGET /core/system/dictAllGET /core/system/menu登录页 src/views/auth/login/index.vue 在挂载和登录失败后刷新验证码,保存 uuid 和 image;验证码接口需要避免浏览器缓存时应在请求层增加时间戳参数或正确的缓存响应头。
src/store/index.ts 创建 Pinia,并通过 pinia-plugin-persistedstate 使用 localStorage 持久化。主要 store:
user:登录状态、用户信息、access/refresh token、语言、锁屏和搜索历史menu:后端菜单、首页路径、动态路由移除函数dict:全局字典缓存setting:菜单布局、主题、工作台、界面开关等worktab:工作台标签和 keep-alive 状态table:表格相关状态持久化 key 由 StorageKeyManager 版本化管理,修改字段或版本时要考虑旧 localStorage 数据兼容。登出逻辑会清理 token、用户信息、动态路由和 iframe 缓存,但按设计保留部分工作台标签,下一次登录会根据用户 ID判断是否清理。
路由定义在 src/router/modules/merchant.ts,当前包括:
/merchant/my-merchant:我的商户/merchant/subordinate-merchant:下级商户,复用 my-merchant/index.vue,通过 subordinate prop 切换查询范围/merchant/add-merchant:新增商户/merchant/statistics:商户数据统计,通常通过 query id 进入API 在 src/api/merchant/merchant.ts,主要接口:
GET /core/merchant/index:商户分页列表;scope 支持 own / subordinate,并支持名称、电话、分配状态、状态、分润方式、设备类别、代理类型等筛选GET /core/merchant/readPOST /core/merchant/savePUT /core/merchant/updateDELETE /core/merchant/destroyPOST /core/merchant/passwordGET /core/merchant/devicesPOST /core/merchant/device/bindPOST /core/merchant/device/unbindGET/PUT /core/merchant/withdrawal-settingGET /core/merchant/statisticsPOST /core/merchant/statistics/export:Blob 导出商户列表返回分页结构 current_page/data/per_page/total,并包含分类统计 summary:all、city-partner、agent、salesperson。统计接口返回商户信息、日期范围、汇总、支付方式和每日数据。
已验证的业务结果:
/merchant/statistics?id=73 可以正常加载统计页面并与后端交互/merchant/subordinate-merchant 可以加载后端列表近期新增/修改的商户相关文件包括:
src/router/modules/merchant.tssrc/router/modules/index.tssrc/router/core/MenuProcessor.tssrc/api/merchant/merchant.tssrc/views/merchant/my-merchant/index.vuesrc/views/merchant/subordinate-merchant/index.vuesrc/views/merchant/statistics/index.vuesrc/api/agent/agent.ts 提供代理分页、导出、当前账号可分配设备、分配、回收和分配流水 API。src/views/agent/components/AgentList.vue 已从静态演示数据切换为真实 API,支持筛选、后端分页、导出,并接入设备分配和分配记录弹窗。DeviceAssignmentDialog.vue 支持库存勾选与手工/扫码 SN 合并,单次最多 100 台,并分别展示成功、已在目标、非当前管理、已铺货和未找到结果。AssignmentRecordsDialog.vue 支持按操作、设备类型和 SN 查询流水,并可从历史分配记录发起回收;后端仍会复核设备当前管理人和铺货状态。/device/assign 是隐藏的去分配页面;“我的设备”勾选未铺货设备后进入该页面会通过 sns query 预填待分配 SN。vue-tsc --noEmit 通过;Vite production build 通过(3173 modules),仅有既有 system menu 动静态导入警告;真实 HTTP 分配、流水查询和回收闭环通过。src/views/agent/edit-agent/index.vue 是真实代理修改页,通过 /agent/edit-agent?id=... 进入;运营产品控制对应分润输入,开通类型只读,重置恢复接口加载快照,页面不修改密码或登录账号。src/api/agent/agent.ts 已增加 AgentProfile / AgentUpdatePayload 类型,以及 GET /core/agent/read、PUT /core/agent/update 封装。/agent/contract?id=... 并接入真实读写,设备绑定和删除代理仍显示未接入提示,不执行危险操作。vue-tsc --noEmit;Vite production build 通过(3177 modules),只有既有 system menu 动静态导入警告;真实 HTTP 修改、读取和恢复闭环通过。src/views/agent/contract/index.vue 使用 SaImageUpload 维护合同照片、身份信息和其他信息,每组最多 20 张;API 为 GET/PUT /core/agent/contract,后端持久化到 sa_agent_contract。vue-tsc --noEmit;Vite production build 通过(3180 modules)。浏览器实际加载 /agent/contract?id=101,代理信息、三组上传区和提交按钮渲染正常。src/views/fund-management/member-activation-records/index.vue 已从占位页切换为真实列表,支持来源、卡类型、设备类型、用户、开通日期筛选,以及汇总、分页、重置和 Excel 导出。src/api/fundManagement/memberActivationRecord.ts,列表和导出接口分别为 GET /core/fund-management/member-activation-records/index、POST /core/fund-management/member-activation-records/export。sa_member_activation_record 保存会员开通/续费业务快照,不从普通租借订单推测历史会员数据;数据按当前管理员及递归下级范围隔离。vue-tsc --noEmit、PHP 语法检查和 Vite production build 通过;本地数据库、API、筛选、重置和 Excel 导出闭环通过,测试数据为 3 条。pnpm build 已通过,但修改路由、API 类型或页面后仍应至少重新执行 pnpm buildhttp://localhost:4173 属于其他预览/开发实例,排查时先确认当前实际启动端口和 Vite 进程/api/core/captcha 的代理、后端 /core/captcha 响应格式、浏览器缓存以及 image 是否为完整 data URL{ code, message, data } 结构、Authorization、动态菜单初始化和路由 component 路径后续修改该子项目后,在本文件追加或更新:变更文件、接口/路由约定、已验证命令、已知问题和未完成事项。只记录已经从代码、接口或实际运行结果确认的信息;敏感环境变量值、token、密码和用户隐私不要写入。
WaterLedgerDrawer.vue,不再限制最近 100 条;默认每页 10 条,可选 20/50/100 条,支持页码跳转、关键词、操作类型、起止日期、重置和空结果提示。WaterLedger 服务统一列表/导出筛选口径:企业名、商品名、关联凭据、说明,日期包含结束日全天;操作类型及中文名称由后端提供。保留原库存/配送九种流水,档案、收款等其他审计不混入。GET /core/water/ledger 返回分页及 kinds,POST /core/water/ledger/export 接收相同筛选,导出当前已查询条件的全部 XLSX(忽略 page/limit),超过 50,000 条明确拒绝。两接口均要求库存读取权限;临时文件位于系统临时目录,响应生成后删除。php tests/water_ledger_test.php 30 项、原 water_business_test.php 69 项通过,测试数据全部回滚。浏览器现有 20 条流水分成两页;第二页搜索星河返回第一页 1 条,下载 XLSX 解析确认 1 条星河数据加表头,空结果禁用导出,重置恢复 20 条。/water-dispatch 已从 WaterWorkspace 普通列表换为独立调度看板:真实片区任务池、日期/关键词/片区筛选、配送员状态、站点地图、路线摘要/完整路线、任务状态分页及当前页 Excel 导出。原企业/库存/预警页面保持共享组件,调度详情跳转带入关键词。WaterDispatch.php:看板、配送员档案、每日排班、车辆容量、待派单任务日期/时限/位置、区域和时限优先合单预览及原子确认。任务、库存、权益仍复用 WaterBusiness;完整路线单独查询,避免关键词/日期过滤漏站。php scripts/migrate_water_dispatch.php --apply:新增 driver/driver_shift/route 三张表,企业经纬度和配送计划/路线字段。旧任务姓名电话关联到 2 位既有测试配送员,未推断排班,当前容量使用可编辑默认 100 桶;3 单 24 桶、待派单 1/配送中 2 的状态未改变。GET /core/water/dispatch/board、GET /core/water/dispatch/route 需要配送读取权限,GET /core/water/dispatch/plan 和 POST dispatch 新 action 需要管理权限。合单按容量及相同片区校验,原始自由文本 HTTP 派单不再使用,单笔派单也生成经校验的路线。server/docs/WATER_DISPATCH.md。src/utils/waterAmap.ts 统一供水地图和选点弹窗的脚本/插件加载,复用既有高德脚本标识与本地 VITE_AMAP_KEY/VITE_AMAP_SECURITY_CODE,配置值不记入文档。DispatchLocationPicker.vue 为配送计划增加地址搜索及地图选点,确认回填后保存才写入配送任务坐标;保存后切换到对应任务组展示。后端沿用已有 schedule 校验,企业地址和库存/权益不受影响。php scripts/seed_water_shenzhen_coordinates.php --apply,仅给任务9/10/11及其对应3个【测试0910】企业更新地址、深圳南山区片区和坐标;任务新增 origin_address/origin_longitude/origin_latitude 记录出发点,结构由原 dispatch 增量迁移扩展。seed_water_device_dashboard_demo.php --apply固定批次12台【测试0911】设备(ID26–37)、四区各3台、298条模拟用水日记录。写入时6在线/2离线/2告警/2未接入,每页8条分两页;版本三种测试版本及未登记。心跳15分钟后自然离线,脚本复跑不覆盖用户修改。原库存、权益、订单和配送未变。src/views/water/devices/index.vue 按用户图片重做,拆分卡片、编辑弹窗、版本弹窗、分析图表、展示函数和 useDeviceDashboard;接口类型在 src/api/water/devices.ts。WaterMetricCards.vue、useWaterOptions.ts、utils/waterDownload.ts;远程选项保留原选择、防旧请求覆盖,导出校验XLSX和错误响应。设备编辑继续走原写入接口/权限。../server/docs/WATER_DEVICE_DASHBOARD.md。src/views/water/inventory/index.vue 替换共享工作台入口,布局按用户参考图:四张卡、左侧规格表/七日趋势、右侧库存构成;新增 InventoryForm.vue 和页面限定 inventory.scss,保留 WaterLedgerDrawer。getWaterInventory / exportWaterInventory 接真实后端读模型;统计全量,表格搜索分页,导出全部匹配规格。路由 keyword 变化同步查询,窗口回焦刷新但避开正在操作的弹窗,失败显示明确错误。../server/docs/WATER_INVENTORY.md。