feat(svcitem): 事项库+办事大厅 R2 前端三页,并复用富文本组件消除双份实现
build / build (push) Successful in 3m14s

落地(依据《事项库与办事大厅详细设计 v1》§7)
- 路由:办事事项 modId=21 / 服务字典 modId=22 + 子站镜像(/sch/{code}/site/{siteCode}/svc/*)
  + 3 条 legacyRedirect 旧链兼容;SchoolLayout 菜单图标兜底
- ServiceItemList:三维筛选/关键字/分页/发布下架删除/跳转编辑
- ServiceItemEdit:三段富文本 + 封面 + 指南附件上传回显(attList)+「我要办理外链」提示
  + 部门选择器不可达时提示"可留空保存"
- ServiceDictManage:object/category 双 Tab,被引用键编辑锁定 + 删除引用守护提示
- api/类型:SvcItemApi/SvcDictApi 与 types/cms.ts 契约补齐;站点设置补 svc_hall_base 键

审计修复(docs/18)
- D3 接线:列表页新增 ServiceItemSortModal 拖拽排序(顺序源 selList,保存按下标重排 sort_no)
  与「同步部门名」按钮,此前后端 sort/syncDeptName 已备但前端无入口
- 附件场景拆分:封面与三个富文本编辑器改传 scene=svc_item_asset,指南附件保持 svc_item
  (内容资产由后端按内容派生归属,不再依赖前端收集上传 id——删除只写不读的 uploadedIds 记账)
- 部门组树:SvcDeptVo 增 children,前端 flattenDepts 缩进扁平化(后端改嵌套下发,交互不变)
- RichTextEditor 补 articleId/slateMinHeight prop 并去掉死状态 editorLoading;
  ArticleEdit 改为复用该组件(正文区最小高度按原口径传入,观感不变),消除双份 wangEditor 实现

测试与 mock
- mock 补 /api/svc/** 全量桩(事项分页/字典/部门树/排序/同步部门名/附件回显 + 站点 1、2 示例数据),
  dev:mock 下三页可用(实测 curl 各项响应正确)
- cms.spec 补 save/syncDeptName/selList/dict save+delete 契约;siteRouter.spec 补事项三条路由
  modId 与子站镜像 resolve 断言;新增 RichTextEditor.spec 5 例(上传参数三键/成功 emit/失败不 emit/工具栏排除项)
- vitest 127 用例全绿 + vite build 通过
This commit is contained in:
chenxing
2026-09-11 14:14:02 +08:00
parent 34733ec280
commit a05b0ded55
18 changed files with 2102 additions and 78 deletions
+153
View File
@@ -227,6 +227,159 @@ export interface LinkVo {
status: number;
}
/* ===== 事项库(svc,事项库详细设计 §7.4)===== */
/** 事项分页行(SvcItemPageItem) */
export interface SvcItemPageItem {
id: number;
siteId: number;
itemCode: string;
title: string;
summary?: string;
objectKey?: string;
objectName?: string;
categoryKey?: string;
categoryName?: string;
deptGroupId?: number;
deptName?: string;
/** 1=线上 2=线下 3=线上线下 */
handleMode: number;
/** 1/0("可在线办理"筛选维度) */
onlineFlag: number;
/** 0=草稿 1=已发布 2=已下架 */
status: number;
sortNo: number;
publishTime?: string;
viewCount: number;
createTime?: string;
createBy?: string;
}
/** 事项编辑回显(SvcItemEditVo) */
export interface SvcItemEditVo {
id: number;
siteId: number;
itemCode: string;
title: string;
summary?: string;
objectKey?: string;
categoryKey?: string;
deptGroupId?: number;
deptName?: string;
handleMode: number;
onlineFlag: number;
handlePlace?: string;
handleTimeLimit?: string;
promiseTimeLimit?: string;
contactPhone?: string;
supervisePhone?: string;
processHtml?: string;
materialHtml?: string;
noticeHtml?: string;
faqCategoryId?: number;
noticeCategoryId?: number;
ruleCategoryId?: number;
coverImage?: string;
sortNo: number;
status: number;
publishTime?: string;
offlineTime?: string;
viewCount: number;
/** ext_json.apply_url(我要办理手填外链,可空) */
applyUrl?: string;
}
/** 事项保存入参(SvcItemSaveRequest;applyUrl 服务端写入 ext_json) */
export interface SvcItemSaveRequest {
id?: number;
siteId: number;
itemCode: string;
title: string;
summary?: string;
objectKey?: string;
categoryKey?: string;
deptGroupId?: number;
handleMode?: number;
onlineFlag?: number;
handlePlace?: string;
handleTimeLimit?: string;
promiseTimeLimit?: string;
contactPhone?: string;
supervisePhone?: string;
processHtml?: string;
materialHtml?: string;
noticeHtml?: string;
faqCategoryId?: number;
noticeCategoryId?: number;
ruleCategoryId?: number;
coverImage?: string;
sortNo?: number;
applyUrl?: string;
/** 指南页附件 id(保存时全量重绑) */
attachmentIds?: number[];
}
/** 事项分页查询(SvcItemPageQuery) */
export interface SvcItemPageQuery {
siteId: number;
status?: number;
keyword?: string;
objectKey?: string;
categoryKey?: string;
deptGroupId?: number;
page?: number;
pageSize?: number;
}
/** 事项选择器精简行(SvcItemSimpleVo) */
export interface SvcItemSimpleVo {
id: number;
itemCode: string;
title: string;
status: number;
}
/** 事项指南附件(SvcItemAttachmentVo) */
export interface SvcItemAttachmentVo {
id: number;
fileName: string;
webUrl: string;
fileSize?: number;
}
/** 服务部门选项(SvcDeptVo:UserBase 组树节点,嵌套下发) */
export interface SvcDeptVo {
id: number;
name: string;
/** 子部门(后端返回嵌套组树;选择器按层级缩进展示) */
children?: SvcDeptVo[];
}
/** 事项字典(SvcDictVo;referenced=被事项引用条数) */
export interface SvcDictVo {
id: number;
siteId: number;
/** object=服务对象 category=事项类别 */
dictType: string;
dictKey: string;
dictName: string;
sortNo: number;
/** 0=停用 1=启用 */
status: number;
referenced: number;
}
/** 事项字典保存入参(SvcDictSaveRequest) */
export interface SvcDictSaveRequest {
id?: number;
siteId: number;
dictType: string;
dictKey: string;
dictName: string;
sortNo?: number;
status?: number;
}
/* ===== 通用 ===== */
/** 删除入参(DeleteRequest) */