feat(form): 表单级流程绑定前端 + 文档 hall 路径修订
build / build (push) Successful in 1m55s

- FormDesigner:表单绑定流程下拉与保存联动(配合后端 effectiveFlowGuid
  回退口径);types/svc.ts 补 flowGuid 字段;ServiceItemEdit 微调
- README:用户面入口 /svc-hall/public → /svc-hall/hall 对齐现状
This commit is contained in:
chenxing
2026-09-21 09:37:58 +08:00
parent c19b12003c
commit 15f9425922
4 changed files with 48 additions and 4 deletions
+2 -2
View File
@@ -4,7 +4,7 @@
Vue 3 + Vite + view-ui-plus + alova。
> **用户面已迁出本前端**(2026-09-16,BP-R4-3):在线办理 / 我的办件 / 办件详情在学生与教师
> 办理入口的独立前端 **`svc-hall/app/public`(部署于 `/svc-hall/public/`)**,本前端只保留后台管理。
> 办理入口的独立前端 **`svc-hall/hall`(部署于 `/svc-hall/hall/`)**,本前端只保留后台管理。
> 两个前端互不引用;管理端的办件详情是「办件记录」里的只读抽屉,不做提交人动作(撤回/重提)。
> 说明:本文件此前误为本仓 Notice(通知公告)前端的副本(描述 `/notice/*` 路由、
@@ -55,7 +55,7 @@ npm run dev # http://localhost:8087
`modId` 是菜单 ↔ 路由的稳定契约(UserBase `app_module` 按本应用 appKey 配置)。用户面路由
(原 `/my`、`/apply`、`/apply-detail`,modId 27)已随用户面迁出,`app_module` 里的对应菜单应删除
或改指 `/svc-hall/public/`。
或改指 `/svc-hall/hall/`。
## 目录要点
+4
View File
@@ -150,6 +150,8 @@ export interface SvcFormVo {
version: number;
status: number;
schemaJson: string;
/** 表单级流程绑定(可空):事项未自身绑流时回退用它 */
flowGuid?: string;
publishTime?: string;
referenced?: boolean;
/** 绑定本表单的事项明细(表单页反查使用位置;sch 级共享,可能跨站点) */
@@ -169,6 +171,8 @@ export interface SvcFormSaveRequest {
code: string;
name: string;
schemaJson: string;
/** 表单级流程绑定(可空) */
flowGuid?: string;
}
// ===== 办件 =====
+41 -1
View File
@@ -8,7 +8,7 @@ import { computed, onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { cloneDeep } from "lodash";
import { Message, Modal } from "view-ui-plus";
import { svcFormApi } from "@/api/module/svc";
import { svcFlowApi, svcFormApi } from "@/api/module/svc";
import { useSite } from "@/utils/site";
import ComponentLibrary from "@/components/designer/ComponentLibrary.vue";
import DesignerCanvas from "@/components/designer/DesignerCanvas.vue";
@@ -35,6 +35,11 @@ const formStatus = ref(0);
const formVersion = ref(1);
const code = ref("");
const name = ref("");
/** 表单级流程绑定(2026-09-20):用本表单的事项未自身绑流时回退用它 */
const flowGuid = ref("");
const flows = ref<{ flowGuid: string; name: string; version: number }[]>([]);
const flowDisabled = ref(false);
const flowDisabledReason = ref("");
const groups = ref<DesignGroup[]>([]);
const selected = ref<{ gi: number; fi: number } | null>(null);
const saving = ref(false);
@@ -176,6 +181,28 @@ function validateBeforeSave(): string | null {
return null;
}
/** 流程图预览(与事项编辑同款:本应用后端换免签 token 出图) */
function openFlowDiagram() {
if (!currentSiteCode.value || !flowGuid.value) {
Message.warning("请先选择流程并确认当前站点");
return;
}
window.open(svcFlowApi.diagramUrl(currentSiteCode.value, flowGuid.value, "dept"), "_blank");
}
async function loadFlows() {
if (!currentSiteCode.value) return;
try {
flows.value = ((await svcFlowApi.list(currentSiteCode.value).send()) as any[]) || [];
} catch (e: any) {
flowDisabled.value = true;
const msg = String(e?.message || e || "");
flowDisabledReason.value = msg.includes("流程中心未接入")
? "流程中心未接入,表单暂不能绑定流程"
: `流程列表获取失败:${msg}`;
}
}
async function save() {
if (!currentSiteCode.value) {
Message.error("站点上下文缺失,请从表单列表进入设计器");
@@ -194,6 +221,7 @@ async function save() {
code: code.value.trim(),
name: name.value.trim(),
schemaJson: buildSchemaJson(),
flowGuid: flowGuid.value || undefined,
})
.send();
Message.success(
@@ -217,6 +245,7 @@ async function load() {
name.value = vo.name;
formStatus.value = vo.status ?? 0;
formVersion.value = vo.version ?? 1;
flowGuid.value = vo.flowGuid || "";
let parsed: any = {};
try {
parsed = JSON.parse(vo.schemaJson);
@@ -235,6 +264,7 @@ async function load() {
onMounted(async () => {
await loadSites();
loadFlows();
const idRaw = route.query.id;
formId.value = idRaw !== undefined && idRaw !== null ? Number(idRaw) : null;
if (formId.value && !Number.isNaN(formId.value)) {
@@ -258,6 +288,16 @@ onMounted(async () => {
placeholder="表单编码(字母/数字/下划线/中划线)"
style="width: 220px"
/>
<Select v-model="flowGuid" clearable filterable :disabled="flowDisabled"
placeholder="绑定流程(可空,事项未绑时回退)" style="width: 240px">
<Option v-for="f in flows" :key="f.flowGuid" :value="f.flowGuid">
{{ f.name }}(v{{ f.version }})
</Option>
</Select>
<Button v-if="flowGuid" size="small" @click="openFlowDiagram">流程图</Button>
<span v-if="flowDisabled" style="color: #999; font-size: 12px">
{{ flowDisabledReason }}
</span>
</div>
<div class="head-right">
<Tag v-if="loadedPublished" color="success">
+1 -1
View File
@@ -252,7 +252,7 @@ onMounted(loadAll);
<Button v-if="form.flowGuid" size="small" @click="openFlowDiagram">流程图</Button>
</div>
<div v-if="flowDisabled" class="tip">{{ flowDisabledReason || "流程中心未接入,暂只能配置线下事项" }}</div>
<div v-else class="tip">可在线办理的事项必须绑定流程</div>
<div v-else class="tip">可在线办理的事项须绑定流程:此处选择,或留空回退所用表单的绑定流程</div>
</FormItem>
</Col>
<Col span="12">