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