feat(app): 应用表单加性质 Switch+技术标识,列表加性质列且基石行模块/推送/删除置灰(消息卡片方案 B1)

This commit is contained in:
chenxing
2026-09-28 12:44:45 +08:00
parent 0080861482
commit 6a2c82c0ef
5 changed files with 58 additions and 6 deletions
+6
View File
@@ -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;
+3 -1
View File
@@ -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<string, any>) {
name: formData.name,
categoryId: formData.categoryId,
desc: formData.desc,
appCode: formData.appCode,
appNature: formData.appNature,
clients: formData.clients,
pcUrl: formData.pcUrl,
pcIcon: formData.pcIcon,
+34
View File
@@ -33,6 +33,21 @@
</Col>
</Row>
<!-- 应用性质 / 技术标识(学校模式隐藏——性质与技术标识均为平台主数据) -->
<Row v-if="!schoolMode">
<Col span="12">
<FormItem label="应用性质:">
<Switch v-model="natureBase" size="small" />
<span class="nature-hint">{{ natureBase ? '基石应用(不进开通/授权/模块管理)' : '业务应用' }}</span>
</FormItem>
</Col>
<Col span="12">
<FormItem label="技术标识:" prop="appCode">
<Input v-model="form.appCode" placeholder="如 notice(= 部署名称,创建后尽量不改)" />
</FormItem>
</Col>
</Row>
<!-- 第三行:appKey / appSecret(编辑模式且非学校模式才显示) -->
<Row v-if="isEdit && !schoolMode">
<Col span="12">
@@ -173,6 +188,8 @@ const defaultForm = (): Record<string, any> => ({
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;
}
</style>
+12 -4
View File
@@ -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;
}
+3 -1
View File
@@ -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<string, any>) {
name: formData.name,
categoryId: formData.categoryId,
desc: formData.desc,
appCode: formData.appCode,
appNature: formData.appNature,
clients: formData.clients,
pcUrl: formData.pcUrl,
pcIcon: formData.pcIcon,