Commit Graph
9 Commits
Author SHA1 Message Date
chenxing d1177a741c t18:前端代录与导入——管理员视图两个新动作接进同一条 submit 管线
- Fill.vue 加代录态:?proxy=1 且该表单在 managed 清单里才画「被记录人」选择器(复用 UserCheckModal +
  GetSchoolAll 本校组织树),提交体带 subjectId。三条口径写在注释里:proxy 只是界面开关、判权在后端
  requireSubject(非 ALL 档带字段即 403);subjectId 是被写入数据的字段而不是操作者身份(V17 不变);
  代录态不取也不显示"我的提交"段(那是本人视角的历史,混进来会让人以为已经给这个人记过)。
- AppContext 管理员视图每行加「添加(代录)」与「导入」;导入弹窗组件 components/admin/ImportPanel.vue:
  下载模板 → 选文件 → 逐行结果表(行号/结果/答卷ID/原因)+ 成功失败计数。整批拒(不是这张表的模板、
  label 重复、超行数上限)与坏行原因一律按后端 msg 原样亮出,前端不复制规则(同 AdminListPanel 口径)。
- api/module/data.ts 加 import(multipart,formUuid 走 query)与 importTemplateBlob(原生 fetch:
  文件流不能过 alova 的 response.json() 拦截器,理由同导出那条)。types/data.ts 加 ImportResult/ImportRowResult。
- api/module/anon.ts 加开发期会话开关:仅 conf.isMock(build 产物恒 false)时,地址带 mockSession=0
  即判"无会话"——否则 mock 的 GetUserInfo 永远返回 code=0,匿名通道在 mock 面演不出来(V67 前半句要实拍)。

门禁:npx vue-tsc --noEmit 0 错(s7/tsc-2.log);npm run build ✓ built in 20.99s(s7/build-1.log)。
2026-10-20 17:40:30 +08:00
chenxing 60083517c7 t15:前端双探针引导——/f/ 页通道选择走匿名面,顺修 F1 未登录引导与 F2 desc 插槽
- 新 api/module/anon.ts:两把探针走原生 fetch(alova 的 302 拦截对全部 /api/* 生效且没有
  per-request 豁免位,用它问"有没有会话"会当场整页跳 CAS,C15 的代码事实);带 yschapirequest
  头让墙内未登录回 JSON 的 code=302 信封而不是 HTML 跳转。提交回落 alova(/anon 面无 302 语义)。
- Fill.vue 引导改双探针:probeSession → 有会话走登录通道并取"我的提交"段;无会话再 probeAnonForm
  → 命中即匿名渲染(匿名人无任何查询能力,编辑/删除段整条不出现);两跳都落空才 guideToLogin。
- F1 顺修(取"改判通道"那一支,不动全局 errorHandle):旧判据 e?.code===4 是死分支——alova 抛的是
  不带 code 的 Error,embed 的 needLogin 从来没发出去过;现在未登录引导只由探针结论触发。
- F2 顺修:slot desc → #desc 两处(Vue 3 下旧写法静默不进 Alert 描述插槽,报名号那行从未渲染)。
- App.vue:/f/ 前缀路由先以原生探针判会话,无会话则裸渲染且一个鉴权请求都不发(P124——否则无会话者
  还没走到填报页的探针就被带去 CAS,"匿名表单 page=直接可填"根本兑现不了);探到会话时结果直接复用,
  登录面不多发一次请求。其余路由引导一字未动。
- upload/image 两个附件控件的上传端点改 inject("fcUploadUrl", 默认 /api/form/upload),由 Fill.vue
  按通道 provide;设计器预览等调用点行为不变。vite.config.ts 代理加 /anon → 8086。

门禁:npx vue-tsc --noEmit exit 0;npm run build ✓ built in 11.61s。
2026-10-20 14:05:05 +08:00
chenxing 4a7db3d22c t13:前端换形——audience 数组多选 + 冻结/匿名窗口开关,fillable 行去 canFill/myTier
- types/form.ts:AUDIENCE 改字符串码闭集(含 ANONYMOUS)+ audienceText();
  FormView/FormConfigRequest 加 audience 数组、frozen、anonCookieMinutes
- types/data.ts:FillableForm 去 canFill/myTier(C2,入集即可填);
  DATA_SCOPE_LABELS 由四枚举改两档(ALL/SELF,§19 作废-1)
- FormConfigModal:面向人群改复选组(多选共集)+ 冻结开关(文案指路"喂外部业务应用的表单请开启")
  + 匿名防重窗口;含 ANONYMOUS 时限次置灰并在提交前挡(与后端同判据)
- Forms.vue 面向列、My.vue「可填写」卡集、fill.ts/routes.ts 注记同步换形
- AppContext.vue:填报 tab 直接吃入集行;数据/统计两档的驱动位改由 T14 的 managed 端点接,
  本批不留"按 myTier 猜"的兼容分支(壳零自有权限逻辑)
- mock:formapi/dataapi 的 audience 数组形态 + 匿名×限次跨字段约束
2026-10-20 12:54:26 +08:00
chenxing e5555efb79 fix(p93): 附件/图片回显 URL 用错挂载点——/static/* 404,应为 {ctx}/upload/*
build / build (push) Successful in 1m47s
- 160 演练实测(honor_student 证书图片上传后):/static/form/** 404(146B)、
  /form-center/upload/form/** 200 且字节数一致——/static 是平台主题通道保留前缀,
  附件实际挂载在 {ctx}/upload/(Caddy 静态路由 + 后端 upload 映射)。
- 修复两处 URL 构建:fields/image/pc.vue 回显 img src → `${serviceHost}/upload/{key}`;
  AnswerValueView.vue fileLinks 前缀 → `${serviceHost}/upload/`(serviceHost 空=dev
  同源相对,vite 代理补 /upload → localhost:8086)。
- 附带发现记 P92:字段级 maxSize 仅前端 beforeUpload 拦截,/api/form/upload 对
  5.7MB 文件返回成功(上传端点不感知表单 schema 的字段约束)——裁决口径见报告。

验证:vue-tsc --noEmit 干净;vite build 通过。160 端回显修复随下次部署生效。
2026-10-16 00:04:02 +08:00
chenxing 79c98e4280 feat(p89+p90): 复制表单链接 + 设计器整表预览
build / build (push) Failing after 32s
P89 复制填报链接(旧系统先例对齐:Cms AttachmentManage 的 copyToClipboard
+ 文案「链接已复制」;svc-hall 同款 execCommand 兜底):
- 新增 utils/fillLink.ts:buildFillLink 从当前地址推导部署根(生产
  /form-center/front/、本地 dev=/),hash 路由 query 进 hash(#/f/{code}?appCode=),
  中心表单不带 appCode;copyToClipboard=navigator.clipboard 优先 +
  临时 textarea+execCommand 兜底,双失败亮链接提示手动复制不静默。
- Forms.vue 行操作「复制链接」文字链(P51 形态,收「更多」逻辑不动);
  FormDesigner 头部「复制链接」按钮(草稿态可复制,发布后链接即生效)。

P90 设计器整表预览:
- 新增 components/designer/PreviewModal.vue:全屏 Modal 按填报视角渲染当前
  画布内容(含未保存改动);控件件与填报页同源(fieldWidget pc),选项解析
  与 DesignerCanvas.resolvedOptions 同规则(inline 直用/字典引用展开,字典
  缺域显式降级);必填红星/占位/约束 tip 同 Fill.vue 位;值容器本地可试填,
  不校验不提交;locked 只读态也可用;空分组/未知类型显式空态。
- FormDesigner 头部「预览」按钮。

验证:vue-tsc --noEmit 干净;vite build 通过。
2026-10-15 23:42:25 +08:00
chenxing 82a9801ac6 fix(p88-fill): 填报页文本类字段把 InputEvent 存进值 + 壳内卡片收缩成窄条
build / build (push) Successful in 1m47s
- [object InputEvent]:text/textarea/phone 三个控件在 view-ui-plus Input 上
  监听 @input——该组件 emits 表里没有 input(源码取证:on-*/update:modelValue),
  监听器穿透到根元素收原生 InputEvent,事件对象被当作字段值写入答卷,
  提交即被后端值类型校验拒(「字段「单行文本」必须是字符串」)。
  值通道改 @update:model-value;其余六类控件走 @on-change 取值本就正确未动。
- 窄卡:base.layout.css 把 .yh-fill 定为纵向 flex 卡片模型,flex 子项水平
  margin:auto 放弃 stretch 收缩到内容宽(~300px)。Fill 卡片改 width:100% +
  max-width:800px + align-self:center,底色/边框/外距交还平台卡片规则;
  同叶删掉 min-height:100vh(壳内双滚动来源),嵌入态 fill-plain 不受影响。
- 验证:view-ui-plus 源码 emits 表逐控件核对;vue-tsc + vite build 双绿。
2026-10-15 21:24:47 +08:00
chenxing d8f1a1fbfa feat(t10-admin): 管理员体系前端——应用设置双 tab+单表单管理员+选人组件移植
build / build (push) Successful in 3m8s
- AppSettings.vue 应用设置页(基础/字典两 tab);修复 P86:Tabs 写 :value 而受控 prop 是 modelValue,致 ?tab=dicts 深链静默失效,改后深链实拍生效
- UserCheckModal.vue 自 notice 移植(view-ui-plus+ztree,sources 注入式数据源);public/libs 收录 jquery+ztree 本地件(index.html 引用)
- api/module/admin.ts + mock/adminapi.ts + types/admin.ts;AdminListPanel/FormAdminModal 组件
- routes/menuNav/menuRoute/modulePerms 适配管理员菜单与权限位;tree-icon 图标资源
2026-10-15 20:25:39 +08:00
chenxing 14d45f7e3c feat(t9): P76 导出锚点判树修正 + P77 应用内详情形态 + 观察项①勾选回填 + 演练桩
build / build (push) Successful in 3m17s
P76(T8 验收遗留):快应用上下文的导出按钮此前恒按中心会话树判"导出"锚点
(Data.vue exportable 读 store.modules),锚点判定不生效(fail-closed 方向,
有授权也不画按钮)。本轮把 AppContext 拉到的**目标应用树**经 modules prop 下传,
Data.vue 的权限判据改为 permsTree(app=应用树 / center=会话树),canExport 纯函数不动。
Stats.vue 未接:本页无锚点判定也无 store.modules 引用,加 prop 是死代码(差异记 T9 报告)。

P77(T8 验收遗留):应用上下文内的"详情"不再跳回中心路由 /admin/data/detail。
形态二选一取**子路由 /app/:appCode/data/detail**(同一个 AnswerDetail.vue):
地址保留 uuid 可深链/刷新、详情页只有一份实现、back() 本就按 app 回应用数据视图,
写 parentPath 反而造假(menuRoute 的 ROUTE_PATHS 只收静态 path,应用段导航在页内轻导航)。
goDetail 按 props.context 分派;back() 改读 route.params.appCode,撤掉 query.app 双轨。

观察项①(T8 验收记档):确认跨触底页勾选**会被清空**——view-ui-plus 的 data 监听器
用 makeObjBaseData 重建 objData,_isChecked 只认行上的 _checked(点选不回写行),
整组替换后勾选视觉与 getSelection 归零而"已选 N 条"仍累计。新增 withSelectionState()
在 reload/loadMore 两条装载路径按 selected 回填 _checked,selected 为唯一事实源。

演练桩(本地件,dev:mock 生效):baseapi 增 fc-drill 快应用模块树(方案 §6.2 五行含
导入/导出两个 path 空锚点),dataapi 增 /api/form/resolve 桩(快应用数据视图唯一的
合规取数路径是 code→resolve→uuid,契约 §1)。其余外指 appCode 仍旧返回空树(P3 口径)。

门禁:npm run build ✓ / npm run type-check 0 错 ✓;
t1~t9 全量复跑:t5 13/0/1、t6 22/0/2、t7 12/0/0、t8 21/0/1、t9 12/0/1
(skip 均为 headless Edge --dump-dom 吐 0 字节的 P73 环境事实,不假通过)。
本提交含 T6~T8 三轮堆在工作区的既有改动(沿 T8 验收 §5 推送分层)。
2026-10-15 12:57:10 +08:00
chenxing fdd9aaaa3b feat(shell): T5 前端·壳与管理端框架——fork notice/front 基线并剥领域
build / build (push) Successful in 3m10s
- A 类主题 loader 原文接入 + env-config 引导 + vite /static 与 /api(8086) 代理(P6/P11)
- GetUserMod 左导航:utils/menuNav.ts 单点实现 path 空锚点跳过、分组收敛、icon 兜底、面包屑基线(对齐 Notice 13afb22 refined 版)
- alova 封装 + api/module/base.ts(getUserMod 可选 appCode,P2 定名;H4 前空树不回落,P3)
- 路由骨架一 SPA 四形态:/admin/{forms,data,stats,dicts}、/f/:code、/app/:appCode/*、/my;self!=top 剥壳(方案 §3.3)
- 规范件落位:tableActions.ts(UserBase 同构源,正文 MD5 不变)、TablePageAlovaNew + useElementHeight、page-wrapper yh-fill 骨架
- view-ui-plus 精确锁 1.3.24;本地零 layout.css/icons.css;avatar 两件由 YschTheme sync 下发
- 剥除:notice 领域 views/api/mock/menu 兜底、alova-vant(mobiapi)、ztree+jquery 与重依赖(按需回补,见 service/docs/T5-report.md 问题单 P52)
2026-10-14 20:35:41 +08:00