承接上一提交(通知公告的两个控件),把其余模块里同类控件一次搬到位。 新增组件(都照搬对应模块页的实现,只把「数据从哪来」换成后端下发的 pickerSources) · ScopePickerInput.vue ← 校园公告 components/ClassScopeInput.vue (全部班级 / 指定班级 + 只读回显 + 弹窗班级树;v-model 是 scope 对象数组) · RoomPickerInput.vue ← 宿舍通知 views/dorm/NewNotice.vue 的「选择接收宿舍」弹窗 (左楼栋列表 / 右按楼层分组的房间勾选 / 底部已选间数与住宿生人数;v-model 是字符串) · utils/picker-tree.ts:只剥 {code,msg,data} 外壳、**不拍平** (弹窗要的是原始嵌套树;拍平是下拉字典的口径) 改造 · RichTextEditor:后端没下发正文图片上传地址时,把工具栏的「图片」整组摘掉 —— 专业发展的编辑器就是这样(该模块没有 UploadImage) · UserCheckInput:抽出公共 parseTree,三个自绘控件共用一份外壳剥离口径 · FormCard:接入 scopepicker / roompicker(初值、序列化、isWide 独占整行) · types/agent.ts:widget 联合类型补 scopepicker / roompicker
按用户要求,把 NoticeFront 里这两块 UI 原样搬到助手表单(不再自制近似控件): - 正文 → wangEditor v5(@wangeditor/editor + @wangeditor/editor-for-vue)。 提交给后端的是 **HTML 字符串**,与模块页 NoticeRequest.content 一致; 插图上传走 /api/file/UploadImage、预览走 /api/file/Preview?id=(地址由后端下发, 统一由编排层拼模块前缀)。异步 chunk 加载,避免把 800KB 编辑器塞进首屏。 - 通知对象 → 1:1 搬运模块页 components/UserCheckInput.vue + UserCheckModal.vue: radio「全部用户 / 指定用户」+ 只读回显 + +/清空 + 选人弹窗(左 zTree 组织树勾选级联 / 右已选列表 / 全选 / 删除选中 / 按名字搜索回勾);v-model 值是字符串("all" 或 id 逗号串)。 - 全局依赖 jQuery + zTree 按模块页的方式由 index.html 全局加载(public/libs/), 不用 npm 引入 —— 保证加载顺序(zTree 必须在 jQuery 之后)与样式/图标与模块页完全一致。 已确认模块页的 lodash 实际未被使用,故不引入。 FormCard 新增两个 widget 分支,每一处都对齐模块页口径: - richtext:初值取字符串、提交原 HTML,只读摘要用剥标签后的纯文本; - userpicker:初值数组 join / 字符串原样(空则 allToken)、提交字符串; ★ 跳过下拉字典的「拍平 + 取值对齐」—— 那条路会把人员 id 串判成「认不出的值」清掉, 等于把模型/用户已经选好的人悄悄抹掉; - 两者都独占整行(自适应多列会把单选组挤到换行)。 验证:.scratch/verify-notice-publish-widgets.mjs 真机 38/38(含正文真实打字、 两个数据源页签、勾选回显、以及提交体 receiveList 必须是字符串 "101"、content 必须是 <p>…)。 npm run build 通过(RichTextEditor 单独成 chunk)。