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 推送分层)。
117 lines
5.4 KiB
TypeScript
117 lines
5.4 KiB
TypeScript
/**
|
||
* 定义域管理端接口(后端 `FormAdminController`,/api/form/admin/*,CAS 会话 + 定义管理模块行把关)。
|
||
*
|
||
* 写法沿 T5 定稿的 P49:`alovaInstance.Get<T>(url, {params})` / `Post<T>(url, body, {params})`——
|
||
* 同一个 Method 对象、同一套拦截器与信封解包(Notice 的 `new Method<T>` 在 alova 3.5 类型下不合法)。
|
||
*
|
||
* 两条参数分工照后端原样,别自己发挥:
|
||
* - `uuid` 寻址表单(库内 id 从不外露,契约 §1/V5);
|
||
* - `schId` 只是**超管的目标域**选择(含 0=平台级),校级管理员传别的值直接被 FormAdminGuard 拒;
|
||
* 本端默认不传(会话校),只有超管切平台级上下文时才显式带。
|
||
* publish/disable/enable/softDelete 的 uuid 走 query(后端是 @RequestParam,没有请求体)。
|
||
*/
|
||
import { alovaInstance } from "@/utils/alova/alova-iview";
|
||
import type {
|
||
FormConfigRequest,
|
||
FormCopyRequest,
|
||
FormCreateRequest,
|
||
FormSaveRequest,
|
||
FormView,
|
||
StatusDefsRequest,
|
||
VersionView
|
||
} from "@/types/form";
|
||
|
||
const BASE = "/api/form/admin";
|
||
|
||
/** 目标域参数:只在超管显式选择上下文时带(undefined 一律剔除,避免 query 里出现空值) */
|
||
type Scope = { schId?: number };
|
||
|
||
function paramsOf(params: Record<string, unknown>): Record<string, unknown> {
|
||
const out: Record<string, unknown> = {};
|
||
for (const [k, v] of Object.entries(params)) {
|
||
if (v === undefined || v === null || v === "") continue;
|
||
out[k] = v;
|
||
}
|
||
return out;
|
||
}
|
||
|
||
class FormApi {
|
||
/** 表单列表(头表 + 版本指针,不含 schema 正文;无服务端分页,一期按校量级够用) */
|
||
list(scope: Scope = {}, filter: { appCode?: string; status?: number } = {}) {
|
||
return alovaInstance.Get<FormView[]>(`${BASE}/list`, {
|
||
params: paramsOf({ ...scope, ...filter })
|
||
});
|
||
}
|
||
|
||
/** 单个表单头表(状态/版本指针/表单级配置/状态定义都在这里,schema 正文要另查版本行) */
|
||
get(uuid: string, scope: Scope = {}) {
|
||
return alovaInstance.Get<FormView>(`${BASE}/get`, { params: paramsOf({ ...scope, uuid }) });
|
||
}
|
||
|
||
/** 版本行清单(升版流水账:version/published/changeLog/publishTime) */
|
||
versions(uuid: string, scope: Scope = {}) {
|
||
return alovaInstance.Get<VersionView[]>(`${BASE}/versions`, { params: paramsOf({ ...scope, uuid }) });
|
||
}
|
||
|
||
/** 单个版本行的 schema 正文(编辑回显;已发布行内容逐字节冻结,V7) */
|
||
version(uuid: string, version: number, scope: Scope = {}) {
|
||
return alovaInstance.Get<VersionView>(`${BASE}/version`, {
|
||
params: paramsOf({ ...scope, uuid, version })
|
||
});
|
||
}
|
||
|
||
/** 筛选候选列:只出显式 searchable 且当前发布版本里的字段,附件两类已被后端排除(P28) */
|
||
filterFields(uuid: string, scope: Scope = {}) {
|
||
return alovaInstance.Get<string[]>(`${BASE}/filterFields`, { params: paramsOf({ ...scope, uuid }) });
|
||
}
|
||
|
||
/** 新建草稿(建草稿即生成 uuid,跨版本不变;version 从 1 起) */
|
||
create(body: FormCreateRequest, scope: Scope = {}) {
|
||
return alovaInstance.Post<FormView>(`${BASE}/create`, body, { params: paramsOf({ ...scope }) });
|
||
}
|
||
|
||
/** 保存:草稿直改;已发布表单=开草稿行,头表 status/current_version 不动(V7、P20) */
|
||
save(body: FormSaveRequest, scope: Scope = {}) {
|
||
return alovaInstance.Post<FormView>(`${BASE}/save`, body, { params: paramsOf({ ...scope }) });
|
||
}
|
||
|
||
/** 发布:schema 契约校验 + 字段身份稳定 + 字典可解析,三道都过才把草稿行钉成版本并推指针 */
|
||
publish(uuid: string, changeLog?: string, scope: Scope = {}) {
|
||
return alovaInstance.Post<FormView>(`${BASE}/publish`, {}, {
|
||
params: paramsOf({ ...scope, uuid, changeLog })
|
||
});
|
||
}
|
||
|
||
/** 停用:只断填报入口,数据可读可导(方案 §5.4) */
|
||
disable(uuid: string, scope: Scope = {}) {
|
||
return alovaInstance.Post<FormView>(`${BASE}/disable`, {}, { params: paramsOf({ ...scope, uuid }) });
|
||
}
|
||
|
||
/** 停用恢复:重新发布当前版本,不产生新版本行 */
|
||
enable(uuid: string, scope: Scope = {}) {
|
||
return alovaInstance.Post<FormView>(`${BASE}/enable`, {}, { params: paramsOf({ ...scope, uuid }) });
|
||
}
|
||
|
||
/** 软删(唯一删除形态,无物理删除接口) */
|
||
softDelete(uuid: string, scope: Scope = {}) {
|
||
return alovaInstance.Post<void>(`${BASE}/softDelete`, {}, { params: paramsOf({ ...scope, uuid }) });
|
||
}
|
||
|
||
/** 另存为副本(V41):新 code/新 uuid/version 从 1 起/schema 深拷贝,源表单零改动 */
|
||
copy(body: FormCopyRequest, scope: Scope = {}) {
|
||
return alovaInstance.Post<FormView>(`${BASE}/copy`, body, { params: paramsOf({ ...scope }) });
|
||
}
|
||
|
||
/** 表单级配置(不进版本快照,改它不升版):audience/限次/截止/报名号/分组标签 */
|
||
config(body: FormConfigRequest, scope: Scope = {}) {
|
||
return alovaInstance.Post<FormView>(`${BASE}/config`, body, { params: paramsOf({ ...scope }) });
|
||
}
|
||
|
||
/** 状态定义(V12):statusDefs 传 null=回默认「待处理/已处理」 */
|
||
statusDefs(body: StatusDefsRequest, scope: Scope = {}) {
|
||
return alovaInstance.Post<FormView>(`${BASE}/statusDefs`, body, { params: paramsOf({ ...scope }) });
|
||
}
|
||
}
|
||
|
||
export const formApi = new FormApi();
|