remove in store list

This commit is contained in:
Timi
2026-08-29 00:49:22 +08:00
parent 147808adda
commit 9ec4e1fe35
3 changed files with 281 additions and 123 deletions
+195
View File
@@ -0,0 +1,195 @@
<template>
<t-dialog
class="remove-dialog"
v-model:visible="visible"
title="删除门店"
>
<div class="content">
<div class="warning">删除后将同步处理以下数据:</div>
<ul class="items">
<li>删除该门店下的所有客户</li>
<li>删除客户的登记记录及相关附件</li>
<li>删除积分规则和积分账户</li>
<li>删除登记事件及事件角色关联</li>
<li>删除门店营业日数据</li>
<li>删除门店用户关系</li>
<li>删除门店自有标签</li>
</ul>
<div class="warning">特别说明:</div>
<ul class="items">
<li>已产生的积分流水不会删除,将保留积分撤销记录</li>
<li>关联的系统用户账号不会删除</li>
<li>删除后无法恢复,请谨慎操作</li>
</ul>
<div class="hint">
请输入门店名称
<span class="name red" v-text="storeName" />
以确认删除
</div>
<t-input
class="confirm-input"
v-model.trim="confirmName"
size="small"
borderless
clearable
placeholder="请输入门店名称"
/>
</div>
<template #cancelBtn>
<t-button
theme="default"
content="取消"
block
@click="close"
/>
</template>
<template #confirmBtn>
<t-button
theme="danger"
:content="confirmButtonText"
block
:loading="loading"
:disabled="!canConfirm || loading || 0 < countdown"
@click="confirm"
/>
</template>
</t-dialog>
</template>
<script setup lang="ts">
import type { Store } from "@/types/Store";
defineOptions({
name: "StoreRemoveDialog"
});
interface Props {
visible?: boolean;
store?: Store;
loading?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
visible: false,
loading: false
});
const emit = defineEmits<{
"update:visible": [visible: boolean];
confirm: [store: Store];
}>();
const COUNTDOWN_SECONDS = 30;
const confirmName = ref("");
const countdown = ref(COUNTDOWN_SECONDS);
let countdownTimer: number | undefined;
const visible = computed({
get: () => props.visible,
set: (value: boolean) => emit("update:visible", value)
});
const storeName = computed(() => props.store?.name || "");
const canConfirm = computed(() => !!storeName.value && confirmName.value === storeName.value);
const confirmButtonText = computed(() => countdown.value ? `删除(${countdown.value} 秒)` : "删除");
watch(() => props.visible, () => {
confirmName.value = "";
resetCountdown();
}, { immediate: true });
onUnmounted(clearCountdown);
function resetCountdown(): void {
clearCountdown();
countdown.value = COUNTDOWN_SECONDS;
if (!props.visible) {
return;
}
countdownTimer = window.setInterval(() => {
if (countdown.value < 2) {
countdown.value = 0;
clearCountdown();
return;
}
countdown.value -= 1;
}, 1000);
}
function clearCountdown(): void {
if (countdownTimer === undefined) {
return;
}
window.clearInterval(countdownTimer);
countdownTimer = undefined;
}
function close(): void {
visible.value = false;
}
function confirm(): void {
if (!props.store?.id || !canConfirm.value || props.loading || 0 < countdown.value) {
return;
}
emit("confirm", props.store);
}
</script>
<style scoped lang="less">
.remove-dialog {
:deep(.t-dialog__footer) {
gap: 1rem;
}
.content {
text-align: left;
.warning {
color: #b42318;
font-weight: 700;
}
.items {
margin: .25rem 0 1rem;
max-height: 5rem;
display: flex;
overflow-y: auto;
line-height: 1.2;
padding-left: 1.25rem;
flex-direction: column;
}
.name {
font-weight: 700;
}
.countdown-hint {
color: var(--td-text-color-secondary);
margin-top: .5rem;
font-size: .875rem;
}
.confirm-input {
--td-input-vertical-padding: 10px;
border: 1px solid var(--td-component-border);
margin-top: .5rem;
border-radius: .75rem;
}
}
}
:global(html.theme-dark) {
.remove-dialog {
.warning {
color: #fda29b;
}
.confirm-input {
background: rgba(15, 23, 42, .72);
border-color: rgba(148, 163, 184, .16);
}
}
}
</style>