From 6a2c82c0ef0803be74ffd5b8a29d94ac75d810d1 Mon Sep 17 00:00:00 2001 From: chenxing Date: Mon, 28 Sep 2026 12:44:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(app):=20=E5=BA=94=E7=94=A8=E8=A1=A8?= =?UTF-8?q?=E5=8D=95=E5=8A=A0=E6=80=A7=E8=B4=A8=20Switch+=E6=8A=80?= =?UTF-8?q?=E6=9C=AF=E6=A0=87=E8=AF=86=EF=BC=8C=E5=88=97=E8=A1=A8=E5=8A=A0?= =?UTF-8?q?=E6=80=A7=E8=B4=A8=E5=88=97=E4=B8=94=E5=9F=BA=E7=9F=B3=E8=A1=8C?= =?UTF-8?q?=E6=A8=A1=E5=9D=97/=E6=8E=A8=E9=80=81/=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E7=BD=AE=E7=81=B0=EF=BC=88=E6=B6=88=E6=81=AF=E5=8D=A1=E7=89=87?= =?UTF-8?q?=E6=96=B9=E6=A1=88=20B1=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/globals.d.ts | 6 ++++++ src/views/app/AddAppContainer.vue | 4 +++- src/views/app/AppForm.vue | 34 ++++++++++++++++++++++++++++++ src/views/app/AppList.vue | 16 ++++++++++---- src/views/app/EditAppContainer.vue | 4 +++- 5 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/api/globals.d.ts b/src/api/globals.d.ts index 1b46d84..c58bdeb 100644 --- a/src/api/globals.d.ts +++ b/src/api/globals.d.ts @@ -223,6 +223,8 @@ export interface ApplicationInfoRequest { name: string; categoryId: number; desc?: string; + appCode?: string; + appNature?: string; clients?: number[]; pcUrl?: string; pcIcon?: string; @@ -230,6 +232,7 @@ export interface ApplicationInfoRequest { appIcon?: string; officialAccountUrl?: string; dingtalkUrl?: string; + miniprogramUrl?: string; } export interface SysUserMoveRequest { userId: number; @@ -766,6 +769,8 @@ export interface ApplicationInfoVo { desc?: string; appKey?: number; appSecret?: string; + appCode?: string; + appNature?: string; clients?: number[]; pcUrl?: string; pcIcon?: string; @@ -773,6 +778,7 @@ export interface ApplicationInfoVo { appIcon?: string; officialAccountUrl?: string; dingtalkUrl?: string; + miniprogramUrl?: string; } export interface BasePageResultApplicationInfoVo { total?: number; diff --git a/src/views/app/AddAppContainer.vue b/src/views/app/AddAppContainer.vue index cf97a84..268ee15 100644 --- a/src/views/app/AddAppContainer.vue +++ b/src/views/app/AddAppContainer.vue @@ -22,7 +22,7 @@ let onSuccessCallback: (() => void) | null = null; // useForm 托管提交 const { form, loading: submitting, send: sendForm, onSuccess, onError } = useForm( (dto) => Apis.AppSettings.addApp({ data: dto }), - { initialForm: { name: '', categoryId: undefined, desc: '', clients: [], pcUrl: '', pcIcon: '', appUrl: '', appIcon: '', officialAccountUrl: '', dingtalkUrl: '' }, resetAfterSubmiting: true } + { initialForm: { name: '', categoryId: undefined, desc: '', appCode: '', appNature: 'BUSINESS', clients: [], pcUrl: '', pcIcon: '', appUrl: '', appIcon: '', officialAccountUrl: '', dingtalkUrl: '' }, resetAfterSubmiting: true } ); onSuccess(() => { @@ -50,6 +50,8 @@ async function handleSubmit(formData: Record) { name: formData.name, categoryId: formData.categoryId, desc: formData.desc, + appCode: formData.appCode, + appNature: formData.appNature, clients: formData.clients, pcUrl: formData.pcUrl, pcIcon: formData.pcIcon, diff --git a/src/views/app/AppForm.vue b/src/views/app/AppForm.vue index 757b192..d269655 100644 --- a/src/views/app/AppForm.vue +++ b/src/views/app/AppForm.vue @@ -33,6 +33,21 @@ + + + + + + {{ natureBase ? '基石应用(不进开通/授权/模块管理)' : '业务应用' }} + + + + + + + + + @@ -173,6 +188,8 @@ const defaultForm = (): Record => ({ desc: '', appKey: null, appSecret: '', + appCode: '', + appNature: 'BUSINESS', clients: [] as number[], pcUrl: '', pcIcon: '', @@ -221,12 +238,22 @@ const clientOptions = [ { value: 32, label: '钉钉' }, ]; +/* ---------- 应用性质 Switch(开=BASE 基石 / 关=BUSINESS 业务) ---------- */ +const natureBase = computed({ + get: () => form.appNature === 'BASE', + set: (val: boolean) => { form.appNature = val ? 'BASE' : 'BUSINESS'; }, +}); + /* ---------- 校验规则(学校模式不校验 categoryId——类型字段不展示且不可改) ---------- */ const rules = computed(() => ({ name: [{ required: true, message: '请输入应用名称', trigger: 'blur' }], ...(props.schoolMode ? {} : { categoryId: [{ required: true, type: 'number' as const, message: '请选择应用类型', trigger: 'change' }], }), + // 技术标识仅新增必填(后端 Create 组同口径);编辑留空 = 保持原值(存量孤儿行允许继续观察) + ...((props.schoolMode || props.isEdit) ? {} : { + appCode: [{ required: true, message: '请输入技术标识', trigger: 'blur' }], + }), })); /* ---------- 提交 ---------- */ @@ -348,4 +375,11 @@ function onVisibleChange(val: boolean) { overflow-y: auto; } } + +/* 应用性质说明文字 */ +.nature-hint { + margin-left: 8px; + color: #808695; + font-size: 12px; +} diff --git a/src/views/app/AppList.vue b/src/views/app/AppList.vue index 2b37c4e..31919d2 100644 --- a/src/views/app/AppList.vue +++ b/src/views/app/AppList.vue @@ -168,18 +168,26 @@ const columns = [ return h("span", arr.map((v) => map[v] ?? v).join("、")); }, }, + { + title: "性质", + key: "appNature", + width: 80, + render: (h: any, { row }: any) => h("span", row.appNature === "BASE" ? "基石" : "业务"), + }, { title: "操作", key: "action", align: 'center', width: 280, render: (h: any, { row }: any) => { - // SCHOOL 模式:仅编辑(名称/描述/图标,写学校覆盖表);模块管理/推送设置/删除全部隐藏 + // SCHOOL 模式:仅编辑(名称/描述/图标,写学校覆盖表);模块管理/推送设置/删除全部隐藏。 + // 基石应用(app_nature=BASE)只做身份注册:模块/推送/删除置灰,「编辑」保持可用(密钥轮换入口) + const base = row.appNature === "BASE"; const actions = [$utils.operatingTextHandle(h, '编辑', '', () => handleEdit(row))]; if (!isSchoolMode.value) { - actions.push($utils.operatingTextHandle(h, '模块管理', '', () => goModuleManage(row))); - actions.push($utils.operatingTextHandle(h, '推送设置', '', () => openPushSetting(row))); - actions.push($utils.operatingTextHandle(h, '删除', 'text-error', () => handleDelete(row))); + actions.push($utils.operatingTextHandle(h, '模块管理', '', () => goModuleManage(row), base)); + actions.push($utils.operatingTextHandle(h, '推送设置', '', () => openPushSetting(row), base)); + actions.push($utils.operatingTextHandle(h, '删除', 'text-error', () => handleDelete(row), base)); } return actions; } diff --git a/src/views/app/EditAppContainer.vue b/src/views/app/EditAppContainer.vue index c9227e0..2c9a8e8 100644 --- a/src/views/app/EditAppContainer.vue +++ b/src/views/app/EditAppContainer.vue @@ -34,7 +34,7 @@ const { form, loading: submitting, send: sendForm, onSuccess, onError } = useFor data: dto, params: props.schoolId != null ? { schoolId: props.schoolId } : undefined, }), - { initialForm: { id: null, name: '', categoryId: undefined, desc: '', clients: [], pcUrl: '', pcIcon: '', appUrl: '', appIcon: '', officialAccountUrl: '', dingtalkUrl: '' }, resetAfterSubmiting: true } + { initialForm: { id: null, name: '', categoryId: undefined, desc: '', appCode: '', appNature: 'BUSINESS', clients: [], pcUrl: '', pcIcon: '', appUrl: '', appIcon: '', officialAccountUrl: '', dingtalkUrl: '' }, resetAfterSubmiting: true } ); onSuccess(() => { @@ -80,6 +80,8 @@ async function handleSubmit(formData: Record) { name: formData.name, categoryId: formData.categoryId, desc: formData.desc, + appCode: formData.appCode, + appNature: formData.appNature, clients: formData.clients, pcUrl: formData.pcUrl, pcIcon: formData.pcIcon,