20260831172912

This commit is contained in:
oneao committed 2026-08-31 17:29:13 +08:00
1 parent d6a56eb17f
commit 4d46ce6c53
61 files changed
+2086 -2979

No files matched your search

@@ -0,0 +1,77 @@
<script setup>
/**
* 未保存修改确认弹窗(通用)。
* 场景:对象(模块/页签等)存在未保存修改时,离开/切换/关闭前询问用户如何处理。
* 纯受控展示组件:父组件持有 open/saving 状态,接收 save/discard 事件自行执行
* 保存与放弃逻辑,完成后自行关闭(update:open)。
*
* 用法:
* <UnsavedChangesModal
* :open="!!pending"
* :name="pending?.name"
* :saving="saving"
* save-text="保存并切换"
* discard-text="放弃修改"
* @save="onSave"
* @discard="onDiscard"
* @update:open="(v) => !v && (pending = null)"
* />
*/
import { Modal, Button } from '@/components/ui'
defineOptions({ inheritAttrs: false })
const props = defineProps({
/** 受控打开状态 */
open: { type: Boolean, default: false },
/** 当前对象名称(用于「「xxx」有未保存的修改」文案) */
name: { type: String, default: '' },
/** 保存进行中:主按钮转圈、锁定弹窗(阻止一切关闭入口) */
saving: { type: Boolean, default: false },
/** 保存按钮文案 */
saveText: { type: String, default: '保存并继续' },
/** 放弃修改按钮文案 */
discardText: { type: String, default: '放弃修改' },
/** 描述文案;缺省按 name 生成 */
description: { type: String, default: '' },
/** 自定义标题 */
title: { type: String, default: '有未保存的修改' },
})
const emit = defineEmits(['update:open', 'save', 'discard'])
function close() {
if (props.saving) return
emit('update:open', false)
}
function onSave() {
emit('save')
}
function onDiscard() {
emit('discard')
}
</script>
<template>
<Modal
:open="open"
:title="title"
:mask-closable="false"
:keyboard="false"
:confirm-loading="saving"
:fullscreen="false"
:resizable="false"
@cancel="close"
>
<p style="margin: 0; line-height: 1.7; color: var(--fms-text)">
{{ description || `「${name || '当前对象'}」有未保存的修改,请选择如何处理:` }}
</p>
<template #footer>
<Button type="outline" :disabled="saving" @click="close">取消</Button>
<Button type="outline" :disabled="saving" @click="onDiscard">{{ discardText }}</Button>
<Button type="primary" :loading="saving" @click="onSave">{{ saveText }}</Button>
</template>
</Modal>
</template>
@@ -40,8 +40,8 @@ const props = defineProps({
validator: (value) => value === 'light' || value === 'dark',
},
// 行高:唯一真源,同时驱动虚拟滚动计算与库注入的 --row-height 等 CSS 变量,外部勿用 CSS 覆盖
rowHeight: { type: Number, default: 34 },
headerRowHeight: { type: Number, default: 40 },
rowHeight: { type: Number, default: 30 },
headerRowHeight: { type: Number, default: 34 },
})
const emit = defineEmits(['update:columns', 'change', 'row-order-change'])