feat(app): 基石应用删除解禁——MyConfirm 同步 projman 删除模(输名确认+红色确认键),删除一律危险确认;基石模块/推送仍置灰
build / build (push) Successful in 3m47s
build / build (push) Successful in 3m47s
This commit is contained in:
@@ -1,26 +1,36 @@
|
|||||||
<template>
|
<template>
|
||||||
<Modal v-model="isModal" @on-visible-change="showChange" :title="title">
|
<!-- 确认框固定最高层:可能从任意 transfer 弹窗/抽屉(含手动抬层的 3000 抽屉)里唤起,
|
||||||
|
而 Modal 默认层级是全局计数器 1000+N,会被高 z-index 抽屉盖住 -->
|
||||||
|
<Modal v-model="isModal" @on-visible-change="showChange" :title="title" :z-index="4000" transfer>
|
||||||
<Alert type="warning" class="mb-1" show-icon>
|
<Alert type="warning" class="mb-1" show-icon>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<Icon type="ios-bulb-outline" :class="{ 'mt-5': !info }" slot="icon" :size="28"></Icon>
|
<Icon type="ios-bulb-outline" :class="{ 'mt-5': !info }" :size="28"></Icon>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="msg" :class="['message-box', info ? '' : 'mt-10 mb-10 ml-10']">{{ msg }}</div>
|
<div v-if="msg" :class="['message-box', info ? '' : 'mt-10 mb-10 ml-10']">{{ msg }}</div>
|
||||||
<template #desc v-if="info" slot="desc">{{ info }}</template>
|
<template #desc v-if="info">{{ info }}</template>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
<div v-if="confirmName" class="confirm-name-block mb-1">
|
||||||
|
<div class="mb-5">
|
||||||
|
此操作<span style="font-weight: bold">无法</span>被回滚。<br />
|
||||||
|
请输入 <span class="confirm-name-text">{{ confirmName }}</span> 以确认:
|
||||||
|
</div>
|
||||||
|
<Input v-model="inputName" placeholder="请输入名称以确认" @on-enter="onOkClick" />
|
||||||
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<Button type="primary" :loading="okLoading" @click="onOkClick">{{ confirmText }}</Button>
|
<Button :type="danger ? 'error' : 'primary'" :disabled="!nameMatched" :loading="okLoading" @click="onOkClick">{{ confirmText }}</Button>
|
||||||
<Button :loading="cancleLoading" @click="onCancleClick">{{ closeText }}</Button>
|
<Button :loading="cancleLoading" @click="onCancleClick">{{ closeText }}</Button>
|
||||||
</template>
|
</template>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, computed, onMounted } from "vue";
|
||||||
import { Modal, Button, Alert, Icon } from "view-ui-plus";
|
import { Modal, Button, Alert, Icon, Input } from "view-ui-plus";
|
||||||
|
|
||||||
const isModal = ref(false),
|
const isModal = ref(false),
|
||||||
okLoading = ref(false),
|
okLoading = ref(false),
|
||||||
cancleLoading = ref(false);
|
cancleLoading = ref(false),
|
||||||
|
inputName = ref("");
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -30,6 +40,8 @@ const props = withDefaults(
|
|||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
confirmText?: string;
|
confirmText?: string;
|
||||||
closeText?: string;
|
closeText?: string;
|
||||||
|
confirmName?: string;
|
||||||
|
danger?: boolean;
|
||||||
confirmFn: any;
|
confirmFn: any;
|
||||||
closeFn: any;
|
closeFn: any;
|
||||||
destroy: Function;
|
destroy: Function;
|
||||||
@@ -39,9 +51,13 @@ const props = withDefaults(
|
|||||||
isLoading: true,
|
isLoading: true,
|
||||||
confirmText: "确认",
|
confirmText: "确认",
|
||||||
closeText: "取消",
|
closeText: "取消",
|
||||||
|
confirmName: "",
|
||||||
|
danger: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const nameMatched = computed(() => !props.confirmName || inputName.value.trim() === props.confirmName);
|
||||||
|
|
||||||
onMounted(function () {
|
onMounted(function () {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
isModal.value = true;
|
isModal.value = true;
|
||||||
@@ -49,6 +65,7 @@ onMounted(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const onOkClick = async () => {
|
const onOkClick = async () => {
|
||||||
|
if (!nameMatched.value) return;
|
||||||
if (!!props.isLoading) okLoading.value = true;
|
if (!!props.isLoading) okLoading.value = true;
|
||||||
const { onOk, reslove } = props.confirmFn;
|
const { onOk, reslove } = props.confirmFn;
|
||||||
await Promise.resolve(onOk());
|
await Promise.resolve(onOk());
|
||||||
@@ -73,4 +90,15 @@ const showChange = (state: boolean) => {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style lang="scss" scoped>
|
||||||
|
.confirm-name-block {
|
||||||
|
padding: 0 2px;
|
||||||
|
line-height: 1.6;
|
||||||
|
|
||||||
|
.confirm-name-text {
|
||||||
|
color: #ed4014;
|
||||||
|
font-weight: bold;
|
||||||
|
user-select: all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { MyConfirm } from "@/types/Basics";
|
|||||||
import confirm from "./Confirm.vue";
|
import confirm from "./Confirm.vue";
|
||||||
|
|
||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
export default ({ title, msg, info, confirmText, closeText, isLoading, onOk, onCancel }: MyConfirm) => {
|
export default ({ title, msg, info, confirmText, closeText, isLoading, confirmName, danger, onOk, onCancel }: MyConfirm) => {
|
||||||
return new Promise<boolean>((reslove, reject) => {
|
return new Promise<boolean>((reslove, _reject) => {
|
||||||
const instance = createApp(confirm, {
|
const instance = createApp(confirm, {
|
||||||
title,
|
title,
|
||||||
msg,
|
msg,
|
||||||
@@ -11,6 +11,8 @@ export default ({ title, msg, info, confirmText, closeText, isLoading, onOk, onC
|
|||||||
confirmText,
|
confirmText,
|
||||||
closeText,
|
closeText,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
confirmName,
|
||||||
|
danger,
|
||||||
confirmFn: {
|
confirmFn: {
|
||||||
onOk,
|
onOk,
|
||||||
reslove,
|
reslove,
|
||||||
|
|||||||
Vendored
+4
@@ -105,6 +105,10 @@ export interface MyConfirm {
|
|||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
confirmText?: string;
|
confirmText?: string;
|
||||||
closeText?: string;
|
closeText?: string;
|
||||||
|
/** 输名确认:值与 msg 对象名一致才允许点确认键(危险操作删除模,对齐 projman) */
|
||||||
|
confirmName?: string;
|
||||||
|
/** 红色确认键(危险操作) */
|
||||||
|
danger?: boolean;
|
||||||
onOk?: Function;
|
onOk?: Function;
|
||||||
onCancel?: Function;
|
onCancel?: Function;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,13 +181,14 @@ const columns = [
|
|||||||
width: 280,
|
width: 280,
|
||||||
render: (h: any, { row }: any) => {
|
render: (h: any, { row }: any) => {
|
||||||
// SCHOOL 模式:仅编辑(名称/描述/图标,写学校覆盖表);模块管理/推送设置/删除全部隐藏。
|
// SCHOOL 模式:仅编辑(名称/描述/图标,写学校覆盖表);模块管理/推送设置/删除全部隐藏。
|
||||||
// 基石应用(app_nature=BASE)只做身份注册:模块/推送/删除置灰,「编辑」保持可用(密钥轮换入口)
|
// 基石应用(app_nature=BASE)只做身份注册:模块/推送置灰;删除允许——基石也可下线,
|
||||||
|
// 但走「输名确认」删除模(危险确认,与 projman 应用删除同款)。
|
||||||
const base = row.appNature === "BASE";
|
const base = row.appNature === "BASE";
|
||||||
const actions = [$utils.operatingTextHandle(h, '编辑', '', () => handleEdit(row))];
|
const actions = [$utils.operatingTextHandle(h, '编辑', '', () => handleEdit(row))];
|
||||||
if (!isSchoolMode.value) {
|
if (!isSchoolMode.value) {
|
||||||
actions.push($utils.operatingTextHandle(h, '模块管理', '', () => goModuleManage(row), base));
|
actions.push($utils.operatingTextHandle(h, '模块管理', '', () => goModuleManage(row), base));
|
||||||
actions.push($utils.operatingTextHandle(h, '推送设置', '', () => openPushSetting(row), base));
|
actions.push($utils.operatingTextHandle(h, '推送设置', '', () => openPushSetting(row), base));
|
||||||
actions.push($utils.operatingTextHandle(h, '删除', 'text-error', () => handleDelete(row), base));
|
actions.push($utils.operatingTextHandle(h, '删除', 'text-error', () => handleDelete(row)));
|
||||||
}
|
}
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
@@ -239,18 +240,24 @@ function openSortModal() {
|
|||||||
sortModalVisible.value = true;
|
sortModalVisible.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------- 删除应用 ---------------- */
|
/* ---------------- 删除应用(删除模:输名确认 + 红色确认键,对齐 projman;基石应用同样可删) ---------------- */
|
||||||
async function handleDelete(row: any) {
|
async function handleDelete(row: any) {
|
||||||
|
const name = row.name || String(row.id);
|
||||||
await MyConfirm({
|
await MyConfirm({
|
||||||
msg: `确定删除应用「${row.name || row.id}」吗?`,
|
title: "删除应用",
|
||||||
info: "删除后不可恢复!",
|
msg: `确定删除应用「${name}」吗?`,
|
||||||
|
info: "删除后不可恢复,关联就绪资源需手动清理!"
|
||||||
|
+ (row.appNature === "BASE" ? "(基石应用:请先确认无平台组件仍依赖其 appKey 签名身份)" : ""),
|
||||||
|
confirmName: name,
|
||||||
|
danger: true,
|
||||||
|
confirmText: "删除",
|
||||||
async onOk() {
|
async onOk() {
|
||||||
try {
|
try {
|
||||||
await Apis.AppSettings.deleteApp({ pathParams: { id: row.id } });
|
await Apis.AppSettings.deleteApp({ pathParams: { id: row.id } });
|
||||||
Message.success('删除成功!');
|
Message.success('删除成功!');
|
||||||
tableRef.value?.reloadData(OperatorEnum.del);
|
tableRef.value?.reloadData(OperatorEnum.del);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.warn(e?.message || '删除失败');
|
Message.error(e?.message || '删除失败');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user