This commit is contained in:
2026-01-21 10:35:45 +08:00
parent 8d4290e131
commit 431d2c7071
3 changed files with 506 additions and 645 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -32,8 +32,7 @@
</template>
<script setup>
import { ref, reactive, watch, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { ref, reactive, watch } from 'vue'
import systemApi from '@/api/system'
// 定义组件名称
@@ -41,8 +40,6 @@ defineOptions({
name: 'AreaModal',
})
const { t } = useI18n()
const props = defineProps({
visible: {
type: Boolean,
@@ -78,7 +75,7 @@ const formData = reactive({
const fetchAreaTree = async () => {
try {
const res = await systemApi.area.list.get({ pageSize: 1000 })
if (res.code === 200) {
if (res.code === 200 || res.code === 1) {
const list = res.data.list || res.data || []
areaTreeData.value = buildTree(list)
}
@@ -93,12 +90,12 @@ const buildTree = (list) => {
const roots = []
// 创建映射,以 code 作为键
list.forEach(item => {
list.forEach((item) => {
map[item.code] = { ...item, children: [] }
})
// 构建树,通过 parent_code 关联
list.forEach(item => {
list.forEach((item) => {
if (item.parent_code && map[item.parent_code]) {
map[item.parent_code].children.push(map[item.code])
} else if (item.parent_code === '0' || !item.parent_code) {
@@ -110,36 +107,46 @@ const buildTree = (list) => {
}
// 监听弹窗显示和初始数据变化
watch(() => props.initialData, (newVal) => {
if (props.isEdit && Object.keys(newVal).length > 0) {
formData.id = newVal.id || null
formData.code = newVal.code || ''
formData.title = newVal.title || ''
formData.parent_code = newVal.parent_code || null
formData.status = newVal.status ?? 1
}
}, { immediate: true })
watch(
() => props.initialData,
(newVal) => {
if (props.isEdit && Object.keys(newVal).length > 0) {
formData.id = newVal.id || null
formData.code = newVal.code || ''
formData.title = newVal.title || ''
formData.parent_code = newVal.parent_code || null
formData.status = newVal.status ?? 1
}
},
{ immediate: true },
)
// 监听弹窗打开,加载地区树数据
watch(() => props.visible, (newVal) => {
if (newVal) {
fetchAreaTree()
}
})
watch(
() => props.visible,
(newVal) => {
if (newVal) {
fetchAreaTree()
}
},
)
// 监听弹窗关闭,重置表单
watch(() => props.visible, (newVal) => {
if (!newVal) {
handleClose()
}
})
watch(
() => props.visible,
(newVal) => {
if (!newVal) {
handleClose()
}
},
)
// 确认提交
const handleConfirm = async () => {
try {
const values = await formRef.value.validate()
emit('confirm', values)
} catch (error) {
} catch {
// 表单验证错误,不处理
}
}

View File

@@ -1,45 +1,47 @@
<template>
<div class="system-area">
<a-card :bordered="false">
<template #title>
<div class="page-title">
<EnvironmentOutlined />
<span>{{ $t('common.areaManage') }}</span>
</div>
<sc-table ref="tableRef" :columns="columns" :data-source="dataSource" :loading="loading"
:pagination="pagination" @refresh="loadData" @change="handleTableChange"
@selection-change="handleSelectionChange" :show-action-column="true"
:rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: handleSelectionChange }">
<!-- 工具栏左侧 -->
<template #toolbar-left>
<a-button type="primary" @click="handleAdd">
<template #icon>
<PlusOutlined />
</template>
{{ $t('common.add') }}
</a-button>
<a-button danger @click="handleBatchDelete" :disabled="!selectedRowKeys.length">
<template #icon>
<DeleteOutlined />
</template>
{{ $t('common.batchDelete') }}
</a-button>
</template>
<sc-table ref="tableRef" :columns="columns" :data-source="dataSource" :loading="loading"
:pagination="pagination" :show-row-actions="true" :row-actions="rowActions" :enable-cache="true"
cache-key="system-area-table" @refresh="loadData" @change="handleTableChange" @action="handleAction">
<!-- 工具栏左侧 -->
<template #toolbar-left>
<a-button type="primary" @click="handleAdd">
<template #icon>
<PlusOutlined />
</template>
{{ $t('common.add') }}
</a-button>
<a-button danger @click="handleBatchDelete" :disabled="!selectedRowKeys.length">
<template #icon>
<DeleteOutlined />
</template>
{{ $t('common.batchDelete') }}
</a-button>
</template>
<!-- 状态列自定义 -->
<template #status="{ text }">
<a-tag :color="text === 1 ? 'green' : 'red'">
{{ text === 1 ? $t('common.enabled') : $t('common.disabled') }}
</a-tag>
</template>
<!-- 状态列自定义 -->
<template #status="{ text }">
<a-tag :color="text === 1 ? 'green' : 'red'">
{{ text === 1 ? $t('common.enabled') : $t('common.disabled') }}
</a-tag>
</template>
<!-- 级别列自定义 -->
<template #level="{ text }">
<a-tag color="blue">{{ getLevelText(text) }}</a-tag>
</template>
<!-- 级别列自定义 -->
<template #level="{ text }">
<a-tag color="blue">{{ getLevelText(text) }}</a-tag>
</template>
</sc-table>
</a-card>
<!-- 操作列 -->
<template #action="{ record }">
<a-button size="small" type="link" @click="handleEdit(record)">
{{ $t('common.edit') }}
</a-button>
<a-button size="small" type="link" danger @click="handleDelete(record)">
{{ $t('common.delete') }}
</a-button>
</template>
</sc-table>
<!-- 添加/编辑弹窗 -->
<AreaModal v-model:visible="modalVisible" :is-edit="isEdit" :initial-data="currentData"
@@ -50,7 +52,7 @@
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { message, Modal } from 'ant-design-vue'
import { EnvironmentOutlined, PlusOutlined, DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue'
import { EnvironmentOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { useI18n } from 'vue-i18n'
import systemApi from '@/api/system'
import ScTable from '@/components/scTable/index.vue'
@@ -90,6 +92,13 @@ const currentData = ref({})
// 行操作配置
const rowActions = ref([])
// 添加
const handleAdd = () => {
isEdit.value = false
currentData.value = {}
modalVisible.value = true
}
// 获取级别文本
const getLevelText = (level) => {
const levelMap = {
@@ -149,12 +158,6 @@ const columns = ref([
key: 'created_at',
width: 180,
},
{
title: t('common.action'),
key: 'action',
width: 150,
fixed: 'right',
},
])
// 加载数据
@@ -166,7 +169,7 @@ const loadData = async () => {
pageSize: pagination.pageSize,
}
const res = await systemApi.area.list.get(params)
if (res.code === 1) {
if (res.code === 200 || res.code === 1) {
dataSource.value = res.data.list || res.data || []
pagination.total = res.data.total || 0
}
@@ -180,26 +183,14 @@ const loadData = async () => {
// 表格变化处理
const handleTableChange = (params) => {
const { pagination: pag } = params
pagination.current = pag.current
pagination.pageSize = pag.pageSize
if (params.current) pagination.current = params.current
if (params.pageSize) pagination.pageSize = params.pageSize
loadData()
}
// 行操作处理
const handleAction = (key, record) => {
if (key === 'edit') {
handleEdit(record)
} else if (key === 'delete') {
handleDelete(record)
}
}
// 添加
const handleAdd = () => {
isEdit.value = false
currentData.value = {}
modalVisible.value = true
// 行选择变化处理
const handleSelectionChange = (selectedKeys) => {
selectedRowKeys.value = selectedKeys
}
// 编辑
@@ -221,9 +212,10 @@ const handleDelete = (record) => {
// 注意API 中没有删除接口,这里模拟删除成功
// 如果后端有删除接口,请取消注释以下代码
// const res = await systemApi.area.delete.post({ id: record.id })
// if (res.code === 200) {
// if (res.code === 200 || res.code === 1) {
message.success(t('common.deleteSuccess'))
loadData()
selectedRowKeys.value = [] // 清除选择
// }
} catch (error) {
message.error(t('common.deleteFailed'))
@@ -263,9 +255,13 @@ const handleBatchDelete = () => {
onOk: async () => {
try {
// 注意API 中没有批量删除接口,这里模拟删除成功
// 如果后端有批量删除接口,请取消注释以下代码
// const res = await systemApi.area.batchDelete.post({ ids: selectedRowKeys.value })
// if (res.code === 200 || res.code === 1) {
message.success(t('common.deleteSuccess'))
selectedRowKeys.value = []
loadData()
// }
} catch (error) {
message.error(t('common.deleteFailed'))
console.error('批量删除失败:', error)
@@ -281,7 +277,7 @@ const handleModalConfirm = async (values) => {
if (isEdit.value) {
// 编辑
res = await systemApi.area.edit.post(values)
if (res.code === 1) {
if (res.code === 200 || res.code === 1) {
message.success(t('common.editSuccess'))
modalVisible.value = false
loadData()
@@ -289,7 +285,7 @@ const handleModalConfirm = async (values) => {
} else {
// 添加
res = await systemApi.area.add.post(values)
if (res.code === 1) {
if (res.code === 200 || res.code === 1) {
message.success(t('common.addSuccess'))
modalVisible.value = false
loadData()
@@ -315,75 +311,9 @@ onMounted(() => {
height: 100%;
display: flex;
flex-direction: column;
padding: 16px;
overflow: hidden;
:deep(.ant-card) {
height: 100%;
display: flex;
flex-direction: column;
}
:deep(.ant-card-head) {
flex-shrink: 0;
min-height: auto;
padding: 12px 24px;
}
:deep(.ant-card-head-title) {
padding: 0;
}
:deep(.ant-card-body) {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 16px;
}
:deep(.sc-table) {
flex: 1;
height: 0;
min-height: 0;
:deep(.ant-table-wrapper) {
height: 100%;
display: flex;
flex-direction: column;
}
:deep(.ant-spin-nested-loading) {
height: 100%;
display: flex;
flex-direction: column;
}
:deep(.ant-spin-container) {
height: 100%;
display: flex;
flex-direction: column;
}
:deep(.ant-table) {
flex: 1;
}
:deep(.ant-table-container) {
height: 100%;
display: flex;
flex-direction: column;
}
:deep(.ant-table-body) {
flex: 1;
overflow-y: auto !important;
}
:deep(.ant-pagination) {
flex-shrink: 0;
margin-top: 16px;
}
}
background-color: #ffffff;
padding: 10px;
border-radius: 10px;
}
</style>