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

View File

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