Files
vueadmin/src/pages/system/area/index.vue
2026-01-20 22:54:35 +08:00

390 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<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"
: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 #level="{ text }">
<a-tag color="blue">{{ getLevelText(text) }}</a-tag>
</template>
</sc-table>
</a-card>
<!-- 添加/编辑弹窗 -->
<AreaModal v-model:visible="modalVisible" :is-edit="isEdit" :initial-data="currentData"
@confirm="handleModalConfirm" />
</div>
</template>
<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 { useI18n } from 'vue-i18n'
import systemApi from '@/api/system'
import ScTable from '@/components/scTable/index.vue'
import AreaModal from './components/AreaModal.vue'
// 定义组件名称
defineOptions({
name: 'SystemArea',
})
const { t } = useI18n()
const tableRef = ref(null)
// 数据源
const dataSource = ref([])
const loading = ref(false)
// 分页
const pagination = reactive({
current: 1,
pageSize: 10,
total: 0,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total) => `${total}`,
pageSizeOptions: ['10', '20', '50', '100'],
})
// 选中的行
const selectedRowKeys = ref([])
// 弹窗相关
const modalVisible = ref(false)
const isEdit = ref(false)
const currentData = ref({})
// 行操作配置
const rowActions = ref([])
// 获取级别文本
const getLevelText = (level) => {
const levelMap = {
1: t('common.province'),
2: t('common.city'),
3: t('common.district'),
4: t('common.street'),
}
return levelMap[level] || t('common.unknown')
}
// 列配置
const columns = ref([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 80,
fixed: 'left',
sorter: true,
},
{
title: t('common.areaName'),
dataIndex: 'title',
key: 'title',
width: 200,
},
{
title: t('common.areaCode'),
dataIndex: 'code',
key: 'code',
width: 150,
},
{
title: t('common.areaLevel'),
dataIndex: 'level',
key: 'level',
width: 100,
slot: 'level',
},
{
title: t('common.parentArea'),
dataIndex: 'parent_code',
key: 'parent_code',
width: 150,
},
{
title: t('common.status'),
dataIndex: 'status',
key: 'status',
width: 100,
slot: 'status',
},
{
title: t('common.createTime'),
dataIndex: 'created_at',
key: 'created_at',
width: 180,
},
{
title: t('common.action'),
key: 'action',
width: 150,
fixed: 'right',
},
])
// 加载数据
const loadData = async () => {
try {
loading.value = true
const params = {
page: pagination.current,
pageSize: pagination.pageSize,
}
const res = await systemApi.area.list.get(params)
if (res.code === 1) {
dataSource.value = res.data.list || res.data || []
pagination.total = res.data.total || 0
}
} catch (error) {
message.error(t('common.fetchDataFailed'))
console.error('获取地区列表失败:', error)
} finally {
loading.value = false
}
}
// 表格变化处理
const handleTableChange = (params) => {
const { pagination: pag } = params
pagination.current = pag.current
pagination.pageSize = pag.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 handleEdit = (record) => {
isEdit.value = true
currentData.value = { ...record }
modalVisible.value = true
}
// 删除
const handleDelete = (record) => {
Modal.confirm({
title: t('common.confirmDelete'),
content: `${t('common.deleteConfirm')}: ${record.title}?`,
okText: t('common.confirm'),
cancelText: t('common.cancel'),
onOk: async () => {
try {
// 注意API 中没有删除接口,这里模拟删除成功
// 如果后端有删除接口,请取消注释以下代码
// const res = await systemApi.area.delete.post({ id: record.id })
// if (res.code === 200) {
message.success(t('common.deleteSuccess'))
loadData()
// }
} catch (error) {
message.error(t('common.deleteFailed'))
console.error('删除地区失败:', error)
}
},
})
}
// 初始化行操作配置(必须在 handleEdit 和 handleDelete 定义之后)
rowActions.value = [
{
key: 'edit',
label: t('common.edit'),
handler: handleEdit,
},
{
key: 'delete',
label: t('common.delete'),
danger: true,
handler: handleDelete,
},
]
// 批量删除
const handleBatchDelete = () => {
if (selectedRowKeys.value.length === 0) {
message.warning(t('common.selectDataFirst'))
return
}
Modal.confirm({
title: t('common.confirmBatchDelete'),
content: `${t('common.batchDeleteConfirm')}: ${selectedRowKeys.value.length} ${t('common.items')}?`,
okText: t('common.confirm'),
cancelText: t('common.cancel'),
onOk: async () => {
try {
// 注意API 中没有批量删除接口,这里模拟删除成功
message.success(t('common.deleteSuccess'))
selectedRowKeys.value = []
loadData()
} catch (error) {
message.error(t('common.deleteFailed'))
console.error('批量删除失败:', error)
}
},
})
}
// 弹窗确认
const handleModalConfirm = async (values) => {
try {
let res
if (isEdit.value) {
// 编辑
res = await systemApi.area.edit.post(values)
if (res.code === 1) {
message.success(t('common.editSuccess'))
modalVisible.value = false
loadData()
}
} else {
// 添加
res = await systemApi.area.add.post(values)
if (res.code === 1) {
message.success(t('common.addSuccess'))
modalVisible.value = false
loadData()
}
}
} catch (error) {
if (error.errorFields) {
return // 表单验证错误
}
message.error(isEdit.value ? t('common.editFailed') : t('common.addFailed'))
console.error(isEdit.value ? '编辑地区失败:' : '添加地区失败:', error)
}
}
// 初始化加载数据
onMounted(() => {
loadData()
})
</script>
<style scoped lang="scss">
.system-area {
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;
}
}
}
</style>