提交“
This commit is contained in:
1 parent
69ee0f505c
commit
9b88581450
614 files changed
+90318
-689022
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -83,8 +83,8 @@
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '1' ? 'success' : 'danger'" size="small">
|
||||
{{ row.status === '1' ? '正常' : '停用' }}
|
||||
<el-tag :type="dictStore.getTagType('sys_status', row.status)" size="small">
|
||||
{{ dictStore.getLabel('sys_status', row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -278,9 +278,12 @@
|
||||
fetchDictDataOptions,
|
||||
fetchUserList
|
||||
} from '@/api/admin'
|
||||
import { buildTreePathLabelFromFlat } from '@/utils/tree-path'
|
||||
import { buildTreePathLabelFromFlat } from '@/utils/tree-path'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
|
||||
defineOptions({ name: 'SystemDept' })
|
||||
defineOptions({ name: 'SystemDept' })
|
||||
|
||||
const dictStore = useDictStore()
|
||||
|
||||
const searchForm = reactive<{ keyword: string }>({ keyword: '' })
|
||||
const tableData = ref<Api.Dept.DeptItem[]>([])
|
||||
|
||||
@@ -224,6 +224,24 @@
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="tagType"
|
||||
label="标签颜色"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
v-if="row.tagType"
|
||||
:type="row.tagType || undefined"
|
||||
size="small"
|
||||
>
|
||||
{{ row.tagType === 'success' ? '成功' : row.tagType === 'warning' ? '警告' : row.tagType === 'danger' ? '危险' : row.tagType === 'info' ? '信息' : row.tagType === 'primary' ? '主要' : '默认' }}
|
||||
</el-tag>
|
||||
<span v-else class="text-gray-400">默认</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="remark"
|
||||
label="备注"
|
||||
@@ -291,6 +309,24 @@
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="tagType"
|
||||
label="标签颜色"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
v-if="row.tagType"
|
||||
:type="row.tagType || undefined"
|
||||
size="small"
|
||||
>
|
||||
{{ row.tagType === 'success' ? '成功' : row.tagType === 'warning' ? '警告' : row.tagType === 'danger' ? '危险' : row.tagType === 'info' ? '信息' : row.tagType === 'primary' ? '主要' : '默认' }}
|
||||
</el-tag>
|
||||
<span v-else class="text-gray-400">默认</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="remark"
|
||||
label="备注"
|
||||
@@ -359,6 +395,28 @@
|
||||
<el-form-item label="数据值" prop="dictValue">
|
||||
<el-input v-model="dictDataFormData.dictValue" placeholder="数据值" />
|
||||
</el-form-item>
|
||||
<el-form-item label="标签颜色" prop="tagType">
|
||||
<el-select v-model="dictDataFormData.tagType" placeholder="请选择" clearable>
|
||||
<el-option label="默认" value="">
|
||||
<el-tag size="small">预览</el-tag>
|
||||
</el-option>
|
||||
<el-option label="成功(绿)" value="success">
|
||||
<el-tag type="success" size="small">成功</el-tag>
|
||||
</el-option>
|
||||
<el-option label="警告(橙)" value="warning">
|
||||
<el-tag type="warning" size="small">警告</el-tag>
|
||||
</el-option>
|
||||
<el-option label="危险(红)" value="danger">
|
||||
<el-tag type="danger" size="small">危险</el-tag>
|
||||
</el-option>
|
||||
<el-option label="信息(灰)" value="info">
|
||||
<el-tag type="info" size="small">信息</el-tag>
|
||||
</el-option>
|
||||
<el-option label="主要(蓝)" value="primary">
|
||||
<el-tag type="primary" size="small">主要</el-tag>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" style="grid-column: 1 / -1">
|
||||
<el-input
|
||||
v-model="dictDataFormData.remark"
|
||||
@@ -617,6 +675,7 @@
|
||||
const dictDataFormData = reactive({
|
||||
dictLabel: '',
|
||||
dictValue: '',
|
||||
tagType: '',
|
||||
orderNum: 0,
|
||||
remark: ''
|
||||
})
|
||||
@@ -652,6 +711,7 @@
|
||||
function resetDictDataForm() {
|
||||
dictDataFormData.dictLabel = ''
|
||||
dictDataFormData.dictValue = ''
|
||||
dictDataFormData.tagType = ''
|
||||
dictDataFormData.orderNum = 0
|
||||
dictDataFormData.remark = ''
|
||||
dictDataEditingId.value = null
|
||||
@@ -671,6 +731,7 @@
|
||||
dictDataEditingId.value = row.id
|
||||
dictDataFormData.dictLabel = row.dictLabel
|
||||
dictDataFormData.dictValue = row.dictValue
|
||||
dictDataFormData.tagType = row.tagType || ''
|
||||
dictDataFormData.orderNum = row.orderNum ?? 0
|
||||
dictDataFormData.remark = row.remark || ''
|
||||
dictDataFormVisible.value = true
|
||||
@@ -684,6 +745,7 @@
|
||||
const payload = {
|
||||
dictLabel: dictDataFormData.dictLabel.trim(),
|
||||
dictValue: dictDataFormData.dictValue.trim(),
|
||||
tagType: dictDataFormData.tagType || undefined,
|
||||
dictType: currentDictType.dictType,
|
||||
orderNum: dictDataFormData.orderNum,
|
||||
remark: dictDataFormData.remark?.trim() || undefined
|
||||
|
||||
@@ -1,388 +0,0 @@
|
||||
<!-- 快递公司管理 -->
|
||||
<!-- eslint-disable vue/no-v-model-argument -->
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<section class="panel">
|
||||
<div class="panel-top">
|
||||
<h2>快递公司列表</h2>
|
||||
</div>
|
||||
|
||||
<div class="filter-block">
|
||||
<el-form :model="searchForm" class="filter-form" @submit.prevent>
|
||||
<div class="filter-grid">
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="searchForm.keyword" placeholder="快递公司名称/编码" clearable />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="filter-actions-row">
|
||||
<span class="filter-hint">按快递公司名称、编码模糊查询。</span>
|
||||
<div class="filter-actions-end">
|
||||
<el-button class="btn-ghost" @click="handleReset"
|
||||
><el-icon><RefreshLeft /></el-icon>重置</el-button
|
||||
>
|
||||
<el-button class="btn-main" type="primary" @click="handleSearch"
|
||||
><el-icon><Search /></el-icon>搜索</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="list-toolbar">
|
||||
<div class="list-toolbar-row">
|
||||
<div class="list-toolbar-selected">
|
||||
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
|
||||
</div>
|
||||
<el-button class="btn-main" type="primary" @click="handleAdd">
|
||||
<el-icon><Plus /></el-icon>
|
||||
新增快递公司
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
:disabled="selectedRows.length === 0"
|
||||
@click="handleBatchDelete"
|
||||
>
|
||||
批量删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-body list-wrap">
|
||||
<el-table
|
||||
class="list-table"
|
||||
:data="tableData"
|
||||
v-loading="loading"
|
||||
stripe
|
||||
row-key="id"
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="expressCode"
|
||||
label="快递编码"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="expressName"
|
||||
label="快递名称"
|
||||
min-width="140"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
label="创建时间"
|
||||
min-width="180"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
min-width="120"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<div style="display: flex; justify-content: center; gap: 8px">
|
||||
<el-button class="btn-op-item" @click="handleView(row)">
|
||||
<el-icon><View /></el-icon>查看
|
||||
</el-button>
|
||||
<el-dropdown trigger="hover" @command="(cmd: string) => handleDropdownCommand(cmd, row)">
|
||||
<el-button class="btn-op-item">
|
||||
<el-icon><More /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination list-pager-bar">
|
||||
<el-pagination
|
||||
:current-page="pagination.page"
|
||||
:page-size="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
|
||||
@current-change="(val) => ((pagination.page = val), loadData())"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="560px"
|
||||
class="dialog-form-layout"
|
||||
align-center
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-position="top"
|
||||
class="express-dialog-form"
|
||||
scroll-to-error
|
||||
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
|
||||
>
|
||||
<div class="form-grid-2">
|
||||
<el-form-item label="快递编码" prop="expressCode">
|
||||
<el-input v-model="formData.expressCode" placeholder="请输入快递编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="快递名称" prop="expressName">
|
||||
<el-input v-model="formData.expressName" placeholder="请输入快递名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="formData.remark" placeholder="可选" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button class="btn-ghost" @click="dialogVisible = false">
|
||||
<el-icon><Close /></el-icon>
|
||||
取消
|
||||
</el-button>
|
||||
<el-button class="btn-main" type="primary" @click="handleSubmit" :loading="submitLoading">
|
||||
<el-icon><Check /></el-icon>
|
||||
确定
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<SystemViewDialog
|
||||
v-model:visible="viewVisible"
|
||||
:title="viewRow?.expressName || '快递公司详情'"
|
||||
:icon="Van"
|
||||
:meta="viewRow?.createTime || ''"
|
||||
:sections="viewSections"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus, Close, Check, View, Van, RefreshLeft, Search, More, Edit, Delete } from '@element-plus/icons-vue'
|
||||
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
|
||||
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
|
||||
import {
|
||||
fetchExpressCompanyList,
|
||||
fetchCreateExpressCompany,
|
||||
fetchUpdateExpressCompany,
|
||||
fetchDeleteExpressCompany
|
||||
} from '@/api/admin'
|
||||
|
||||
defineOptions({ name: 'SystemExpress' })
|
||||
|
||||
const searchForm = reactive<{ keyword: string }>({ keyword: '' })
|
||||
const tableData = ref<Api.ExpressCompany.ExpressCompanyItem[]>([])
|
||||
const selectedRows = ref<Api.ExpressCompany.ExpressCompanyItem[]>([])
|
||||
const loading = ref(false)
|
||||
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('新增快递公司')
|
||||
const isEdit = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const formRef = ref()
|
||||
const editingId = ref<string | null>(null)
|
||||
const viewVisible = ref(false)
|
||||
const viewRow = ref<Api.ExpressCompany.ExpressCompanyItem | null>(null)
|
||||
|
||||
const formData = reactive({
|
||||
expressCode: '',
|
||||
expressName: '',
|
||||
orderNum: 0,
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const formRules = {
|
||||
expressCode: [{ required: true, message: '请输入快递编码', trigger: 'blur' }],
|
||||
expressName: [{ required: true, message: '请输入快递名称', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
const handleSelectionChange = (rows: Api.ExpressCompany.ExpressCompanyItem[]) => {
|
||||
selectedRows.value = rows
|
||||
}
|
||||
|
||||
const viewSections = computed(() => {
|
||||
if (!viewRow.value) return []
|
||||
const row = viewRow.value
|
||||
return [
|
||||
{
|
||||
title: '基本信息',
|
||||
fields: [
|
||||
{ label: '快递编码', value: row.expressCode },
|
||||
{ label: '快递名称', value: row.expressName },
|
||||
{ label: '备注', value: row.remark, span: true }
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await fetchExpressCompanyList({
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
keyword: searchForm.keyword || undefined
|
||||
})
|
||||
tableData.value = res.list || []
|
||||
pagination.total = res.total ?? 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
pagination.page = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
function handleReset() {
|
||||
searchForm.keyword = ''
|
||||
pagination.page = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
formData.expressCode = ''
|
||||
formData.expressName = ''
|
||||
formData.orderNum = 0
|
||||
formData.remark = ''
|
||||
editingId.value = null
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
isEdit.value = false
|
||||
dialogTitle.value = '新增快递公司'
|
||||
resetForm()
|
||||
dialogVisible.value = true
|
||||
formRef.value?.clearValidate?.()
|
||||
}
|
||||
|
||||
function handleEdit(row: Api.ExpressCompany.ExpressCompanyItem) {
|
||||
isEdit.value = true
|
||||
dialogTitle.value = '编辑快递公司'
|
||||
editingId.value = row.id
|
||||
formData.expressCode = row.expressCode || ''
|
||||
formData.expressName = row.expressName || ''
|
||||
formData.orderNum = row.orderNum ?? 0
|
||||
formData.remark = row.remark || ''
|
||||
dialogVisible.value = true
|
||||
formRef.value?.clearValidate?.()
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
await formRef.value?.validate?.()
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const payload = {
|
||||
expressCode: formData.expressCode.trim(),
|
||||
expressName: formData.expressName.trim(),
|
||||
orderNum: formData.orderNum,
|
||||
remark: formData.remark?.trim() || undefined
|
||||
}
|
||||
if (isEdit.value && editingId.value) {
|
||||
await fetchUpdateExpressCompany(editingId.value, payload)
|
||||
} else {
|
||||
await fetchCreateExpressCompany(payload)
|
||||
}
|
||||
ElMessage.success(isEdit.value ? '更新成功' : '创建成功')
|
||||
dialogVisible.value = false
|
||||
await loadData()
|
||||
} catch {
|
||||
/* 校验或接口错误已由全局处理 */
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleView(row: Api.ExpressCompany.ExpressCompanyItem) {
|
||||
viewRow.value = row
|
||||
viewVisible.value = true
|
||||
}
|
||||
|
||||
function handleDropdownCommand(command: string, row: any) {
|
||||
switch (command) {
|
||||
case 'edit':
|
||||
handleEdit(row)
|
||||
break
|
||||
case 'delete':
|
||||
handleDelete(row)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.ExpressCompany.ExpressCompanyItem) {
|
||||
await ElMessageBox.confirm(`确定删除快递公司「${row.expressName}」吗?`, '提示', {
|
||||
type: 'warning'
|
||||
})
|
||||
await fetchDeleteExpressCompany(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
await loadData()
|
||||
}
|
||||
|
||||
async function handleBatchDelete() {
|
||||
const ids = selectedRows.value.map((r) => r.id)
|
||||
if (!ids.length) return
|
||||
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个快递公司吗?`, '提示', {
|
||||
type: 'warning'
|
||||
})
|
||||
await withFullscreenLoading(async () => {
|
||||
for (const id of ids) {
|
||||
await fetchDeleteExpressCompany(id)
|
||||
}
|
||||
ElMessage.success('批量删除成功')
|
||||
selectedRows.value = []
|
||||
await loadData()
|
||||
}, fullscreenLoadingText.batchDelete)
|
||||
}
|
||||
// 输入检索条件时自动搜索(防抖 300ms)
|
||||
watchDebounced(
|
||||
searchForm,
|
||||
() => {
|
||||
pagination.page = 1
|
||||
loadData()
|
||||
},
|
||||
{ debounce: 300, deep: true }
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.express-dialog-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -96,8 +96,8 @@
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="statusTagType(row.status)" size="small">{{
|
||||
statusLabel(row.status)
|
||||
<el-tag :type="dictStore.getTagType('leave_status', row.status)" size="small">{{
|
||||
dictStore.getLabel('leave_status', row.status)
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -236,7 +236,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Close, Check, RefreshLeft, Search } from '@element-plus/icons-vue'
|
||||
import { leaveStatusLabel, leaveStatusTagType } from '@/utils/status-tag-registry'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import {
|
||||
fetchLeaveList,
|
||||
fetchCreateLeave,
|
||||
@@ -247,6 +247,8 @@
|
||||
|
||||
defineOptions({ name: 'LeaveRequest' })
|
||||
|
||||
const dictStore = useDictStore()
|
||||
|
||||
const loading = ref(false)
|
||||
const tableData = ref<Api.Leave.LeaveItem[]>([])
|
||||
const selectedRows = ref<Api.Leave.LeaveItem[]>([])
|
||||
@@ -268,9 +270,6 @@
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const statusLabel = leaveStatusLabel
|
||||
const statusTagType = leaveStatusTagType
|
||||
|
||||
function resetForm() {
|
||||
formData.leaveType = 'personal'
|
||||
formData.startDate = ''
|
||||
|
||||
@@ -71,8 +71,8 @@
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="menuTypeTagMap[row.menuType]?.type || 'info'" size="small">
|
||||
{{ menuTypeTagMap[row.menuType]?.label || row.menuType }}
|
||||
<el-tag :type="dictStore.getTagType('menu_type', row.menuType)" size="small">
|
||||
{{ dictStore.getLabel('menu_type', row.menuType) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -117,8 +117,8 @@
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.visible === '1' ? 'success' : 'info'" size="small">
|
||||
{{ row.visible === '1' ? '显示' : '隐藏' }}
|
||||
<el-tag :type="dictStore.getTagType('sys_visible', row.visible)" size="small">
|
||||
{{ dictStore.getLabel('sys_visible', row.visible) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -130,8 +130,8 @@
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '1' ? 'success' : 'danger'" size="small">
|
||||
{{ row.status === '1' ? '正常' : '停用' }}
|
||||
<el-tag :type="dictStore.getTagType('sys_status', row.status)" size="small">
|
||||
{{ dictStore.getLabel('sys_status', row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -256,7 +256,7 @@
|
||||
v-model:visible="viewVisible"
|
||||
:title="viewRow?.menuName || '菜单详情'"
|
||||
:icon="MenuIcon"
|
||||
:meta="`类型:${menuTypeTagMap[viewRow?.menuType || '']?.label || viewRow?.menuType || ''}${viewRow?.createTime ? ' · ' + viewRow.createTime : ''}`"
|
||||
:meta="`类型:${dictStore.getLabel('menu_type', viewRow?.menuType || '')}${viewRow?.createTime ? ' · ' + viewRow.createTime : ''}`"
|
||||
:sections="viewSections"
|
||||
/>
|
||||
</section>
|
||||
@@ -280,14 +280,11 @@
|
||||
} from '@element-plus/icons-vue'
|
||||
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
|
||||
import { fetchMenuTree, fetchCreateMenu, fetchUpdateMenu, fetchDeleteMenu } from '@/api/admin'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
|
||||
defineOptions({ name: 'SystemMenu' })
|
||||
|
||||
const menuTypeTagMap: Record<string, { label: string; type: string }> = {
|
||||
M: { label: '目录', type: '' },
|
||||
C: { label: '菜单', type: 'success' },
|
||||
F: { label: '按钮', type: 'warning' }
|
||||
}
|
||||
const dictStore = useDictStore()
|
||||
|
||||
const searchForm = reactive<{ keyword: string }>({ keyword: '' })
|
||||
const tableData = ref<Api.Menu.MenuItem[]>([])
|
||||
@@ -347,8 +344,8 @@
|
||||
{ label: '菜单名称', value: viewRow.value?.menuName },
|
||||
{
|
||||
label: '菜单类型',
|
||||
value: menuTypeTagMap[viewRow.value?.menuType || '']?.label || viewRow.value?.menuType,
|
||||
tagType: 'primary'
|
||||
value: dictStore.getLabel('menu_type', viewRow.value?.menuType || ''),
|
||||
tagType: dictStore.getTagType('menu_type', viewRow.value?.menuType || '')
|
||||
},
|
||||
{ label: '路由路径', value: viewRow.value?.path },
|
||||
{ label: '组件路径', value: viewRow.value?.component },
|
||||
@@ -356,13 +353,13 @@
|
||||
{ label: '是否外链', value: viewRow.value?.isFrame === 1 ? '否' : '是' },
|
||||
{
|
||||
label: '显示状态',
|
||||
value: viewRow.value?.visible === '1' ? '显示' : '隐藏',
|
||||
tagType: viewRow.value?.visible === '1' ? 'success' : 'info'
|
||||
value: dictStore.getLabel('sys_visible', viewRow.value?.visible || ''),
|
||||
tagType: dictStore.getTagType('sys_visible', viewRow.value?.visible || '')
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
value: viewRow.value?.status === '1' ? '正常' : '停用',
|
||||
tagType: viewRow.value?.status === '1' ? 'success' : 'info'
|
||||
value: dictStore.getLabel('sys_status', viewRow.value?.status || ''),
|
||||
tagType: dictStore.getTagType('sys_status', viewRow.value?.status || '')
|
||||
},
|
||||
{ label: '备注', value: viewRow.value?.remark, span: true }
|
||||
]
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -89,8 +89,8 @@
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '1' ? 'success' : 'info'" size="small">
|
||||
{{ row.status === '1' ? '正常' : '停用' }}
|
||||
<el-tag :type="dictStore.getTagType('sys_status', row.status)" size="small">
|
||||
{{ dictStore.getLabel('sys_status', row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -335,6 +335,7 @@
|
||||
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
|
||||
import { MAX_ADMIN_LIST_PAGE_SIZE } from '@/utils/fetch-paged-list'
|
||||
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import {
|
||||
fetchPostList,
|
||||
fetchCreatePost,
|
||||
@@ -349,6 +350,8 @@
|
||||
|
||||
defineOptions({ name: 'SystemPost' })
|
||||
|
||||
const dictStore = useDictStore()
|
||||
|
||||
const searchForm = reactive<{ keyword: string }>({ keyword: '' })
|
||||
const tableData = ref<Api.Post.PostItem[]>([])
|
||||
const selectedRows = ref<Api.Post.PostItem[]>([])
|
||||
@@ -391,8 +394,8 @@
|
||||
{ label: '职位编码', value: row.postCode },
|
||||
{
|
||||
label: '状态',
|
||||
value: row.status === '1' ? '正常' : '停用',
|
||||
tagType: row.status === '1' ? 'success' : 'info'
|
||||
value: dictStore.getLabel('sys_status', row.status),
|
||||
tagType: dictStore.getTagType('sys_status', row.status)
|
||||
},
|
||||
{ label: '创建时间', value: row.createTime },
|
||||
{ label: '备注', value: row.remark, span: true }
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -93,8 +93,8 @@
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '1' ? 'success' : 'info'" size="small">
|
||||
{{ row.status === '1' ? '正常' : '停用' }}
|
||||
<el-tag :type="dictStore.getTagType('sys_status', row.status)" size="small">
|
||||
{{ dictStore.getLabel('sys_status', row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -443,7 +443,8 @@
|
||||
import { MAX_ADMIN_LIST_PAGE_SIZE } from '@/utils/fetch-paged-list'
|
||||
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
|
||||
import { buildPathLabelMapFromTreeRoots } from '@/utils/tree-path'
|
||||
import { dataScopeLabel as dataScopeLabelFn, dataScopeTagType } from '@/utils/status-tag-registry'
|
||||
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import {
|
||||
fetchRoleList,
|
||||
fetchCreateRole,
|
||||
@@ -460,7 +461,10 @@
|
||||
|
||||
defineOptions({ name: 'SystemRole' })
|
||||
|
||||
const dataScopeLabel = dataScopeLabelFn
|
||||
const dictStore = useDictStore()
|
||||
|
||||
const dataScopeLabel = (code: string) => dictStore.getLabel('sys_data_scope', code)
|
||||
const dataScopeTagType = (code: string) => dictStore.getTagType('sys_data_scope', code)
|
||||
|
||||
const searchForm = reactive<{ keyword: string }>({ keyword: '' })
|
||||
const tableData = ref<Api.Role.RoleItem[]>([])
|
||||
@@ -949,8 +953,8 @@
|
||||
{ label: '角色名称', value: row.roleName },
|
||||
{
|
||||
label: '状态',
|
||||
value: row.status === '1' ? '正常' : '停用',
|
||||
tagType: row.status === '1' ? ('success' as const) : ('info' as const)
|
||||
value: dictStore.getLabel('sys_status', row.status),
|
||||
tagType: dictStore.getTagType('sys_status', row.status) as 'success' | 'info'
|
||||
},
|
||||
{ label: '创建时间', value: row.createTime },
|
||||
{ label: '备注', value: row.remark, span: true }
|
||||
|
||||
@@ -100,8 +100,8 @@
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '1' ? 'success' : 'info'" size="small">
|
||||
{{ row.status === '1' ? '正常' : '停用' }}
|
||||
<el-tag :type="dictStore.getTagType('sys_status', row.status)" size="small">
|
||||
{{ dictStore.getLabel('sys_status', row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -302,6 +302,7 @@
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus, Close, Check, View, Edit, Delete, More, Location, RefreshLeft, Search } from '@element-plus/icons-vue'
|
||||
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
|
||||
import {
|
||||
fetchSiteList,
|
||||
@@ -314,6 +315,8 @@
|
||||
|
||||
defineOptions({ name: 'SystemSite' })
|
||||
|
||||
const dictStore = useDictStore()
|
||||
|
||||
// ---- 查看弹窗 ----
|
||||
const viewVisible = ref(false)
|
||||
const viewRow = ref<Api.Site.SiteItem | null>(null)
|
||||
@@ -329,8 +332,8 @@
|
||||
{ label: '站点类型', value: getSiteTypeLabel(row.siteType), tagType: 'primary' },
|
||||
{
|
||||
label: '状态',
|
||||
value: row.status === '1' ? '正常' : '停用',
|
||||
tagType: row.status === '1' ? 'success' : 'info'
|
||||
value: dictStore.getLabel('sys_status', row.status),
|
||||
tagType: dictStore.getTagType('sys_status', row.status)
|
||||
},
|
||||
{ label: '地址', value: row.address, span: true }
|
||||
]
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
} from '@/api/admin'
|
||||
|
||||
/** 与后端 `settings.DEFAULT_TENANT_NO` 一致 */
|
||||
const DEFAULT_TENANT_NO = 'zkxw'
|
||||
const DEFAULT_TENANT_NO = 'shanxia2.0'
|
||||
|
||||
defineOptions({ name: 'SystemTenant' })
|
||||
|
||||
|
||||
@@ -1,397 +0,0 @@
|
||||
<!-- 物品单位管理 -->
|
||||
<!-- eslint-disable vue/no-v-model-argument -->
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<section class="panel">
|
||||
<div class="panel-top">
|
||||
<h2>单位列表</h2>
|
||||
</div>
|
||||
|
||||
<div class="filter-block">
|
||||
<el-form :model="searchForm" class="filter-form" @submit.prevent>
|
||||
<div class="filter-grid">
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="searchForm.keyword" placeholder="单位名称/编码" clearable />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="filter-actions-row">
|
||||
<span class="filter-hint">按名称、编码模糊查询。</span>
|
||||
<div class="filter-actions-end">
|
||||
<el-button class="btn-ghost" @click="handleReset"
|
||||
><el-icon><RefreshLeft /></el-icon>重置</el-button
|
||||
>
|
||||
<el-button class="btn-main" type="primary" @click="handleSearch"
|
||||
><el-icon><Search /></el-icon>搜索</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="list-toolbar">
|
||||
<div class="list-toolbar-row">
|
||||
<div class="list-toolbar-selected">
|
||||
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
|
||||
</div>
|
||||
<el-button class="btn-main" type="primary" @click="handleAdd">
|
||||
<el-icon><Plus /></el-icon>
|
||||
新增单位
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
:disabled="selectedRows.length === 0"
|
||||
@click="handleBatchDelete"
|
||||
>
|
||||
批量删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-body list-wrap">
|
||||
<el-table
|
||||
class="list-table"
|
||||
:data="tableData"
|
||||
v-loading="loading"
|
||||
stripe
|
||||
row-key="id"
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="unitName"
|
||||
label="单位名称"
|
||||
min-width="150"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="unitCode"
|
||||
label="单位编码"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
label="创建时间"
|
||||
min-width="180"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
min-width="120"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<div style="display: flex; justify-content: center; gap: 8px">
|
||||
<el-button class="btn-op-item" @click="handleView(row)">
|
||||
<el-icon><View /></el-icon>查看
|
||||
</el-button>
|
||||
<el-dropdown trigger="hover" @command="(cmd: string) => handleDropdownCommand(cmd, row)">
|
||||
<el-button class="btn-op-item">
|
||||
<el-icon><More /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination list-pager-bar">
|
||||
<el-pagination
|
||||
:current-page="pagination.page"
|
||||
:page-size="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
|
||||
@current-change="(val) => ((pagination.page = val), loadData())"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="560px"
|
||||
class="dialog-form-layout"
|
||||
align-center
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-position="top"
|
||||
class="unit-dialog-form"
|
||||
scroll-to-error
|
||||
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
|
||||
>
|
||||
<div class="form-grid-2">
|
||||
<el-form-item label="单位名称" prop="unitName">
|
||||
<el-input v-model="formData.unitName" placeholder="如:斤、kg、个" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单位编码" prop="unitCode">
|
||||
<el-input v-model="formData.unitCode" placeholder="如:jin、kg、ge" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="formData.remark" placeholder="可选" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button class="btn-ghost" @click="dialogVisible = false">
|
||||
<el-icon><Close /></el-icon>
|
||||
取消
|
||||
</el-button>
|
||||
<el-button class="btn-main" type="primary" @click="handleSubmit" :loading="submitLoading">
|
||||
<el-icon><Check /></el-icon>
|
||||
确定
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<SystemViewDialog
|
||||
v-model:visible="viewVisible"
|
||||
:title="viewRow?.unitName || '单位详情'"
|
||||
:icon="ScaleToOriginal"
|
||||
:meta="viewRow?.createTime || ''"
|
||||
:sections="viewSections"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Plus,
|
||||
Close,
|
||||
Check,
|
||||
View,
|
||||
Edit,
|
||||
Delete,
|
||||
More,
|
||||
ScaleToOriginal,
|
||||
RefreshLeft,
|
||||
Search
|
||||
} from '@element-plus/icons-vue'
|
||||
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
|
||||
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
|
||||
import {
|
||||
fetchItemUnitList,
|
||||
fetchCreateItemUnit,
|
||||
fetchUpdateItemUnit,
|
||||
fetchDeleteItemUnit
|
||||
} from '@/api/admin'
|
||||
|
||||
defineOptions({ name: 'SystemItemUnit' })
|
||||
|
||||
const searchForm = reactive<{ keyword: string }>({ keyword: '' })
|
||||
const tableData = ref<Api.ItemUnit.ItemUnitItem[]>([])
|
||||
const selectedRows = ref<Api.ItemUnit.ItemUnitItem[]>([])
|
||||
const loading = ref(false)
|
||||
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('新增单位')
|
||||
const isEdit = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const formRef = ref()
|
||||
const editingId = ref<string | null>(null)
|
||||
const viewVisible = ref(false)
|
||||
const viewRow = ref<Api.ItemUnit.ItemUnitItem | null>(null)
|
||||
|
||||
const formData = reactive({
|
||||
unitName: '',
|
||||
unitCode: '',
|
||||
orderNum: 0,
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const formRules = {
|
||||
unitName: [{ required: true, message: '请输入单位名称', trigger: 'blur' }],
|
||||
unitCode: [{ required: true, message: '请输入单位编码', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
const handleSelectionChange = (rows: Api.ItemUnit.ItemUnitItem[]) => {
|
||||
selectedRows.value = rows
|
||||
}
|
||||
|
||||
const viewSections = computed(() => {
|
||||
if (!viewRow.value) return []
|
||||
const row = viewRow.value
|
||||
return [
|
||||
{
|
||||
title: '基本信息',
|
||||
fields: [
|
||||
{ label: '单位名称', value: row.unitName },
|
||||
{ label: '单位编码', value: row.unitCode },
|
||||
{ label: '备注', value: row.remark, span: true }
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await fetchItemUnitList({
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
keyword: searchForm.keyword || undefined
|
||||
})
|
||||
tableData.value = res.list || []
|
||||
pagination.total = res.total ?? 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
pagination.page = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
function handleReset() {
|
||||
searchForm.keyword = ''
|
||||
pagination.page = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
formData.unitName = ''
|
||||
formData.unitCode = ''
|
||||
formData.orderNum = 0
|
||||
formData.remark = ''
|
||||
editingId.value = null
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
isEdit.value = false
|
||||
dialogTitle.value = '新增单位'
|
||||
resetForm()
|
||||
dialogVisible.value = true
|
||||
formRef.value?.clearValidate?.()
|
||||
}
|
||||
|
||||
function handleEdit(row: Api.ItemUnit.ItemUnitItem) {
|
||||
isEdit.value = true
|
||||
dialogTitle.value = '编辑单位'
|
||||
editingId.value = row.id
|
||||
formData.unitName = row.unitName || ''
|
||||
formData.unitCode = row.unitCode || ''
|
||||
formData.orderNum = row.orderNum ?? 0
|
||||
formData.remark = row.remark || ''
|
||||
dialogVisible.value = true
|
||||
formRef.value?.clearValidate?.()
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
await formRef.value?.validate?.()
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const payload = {
|
||||
unitName: formData.unitName.trim(),
|
||||
unitCode: formData.unitCode.trim(),
|
||||
orderNum: formData.orderNum,
|
||||
remark: formData.remark?.trim() || undefined
|
||||
}
|
||||
if (isEdit.value && editingId.value) {
|
||||
await fetchUpdateItemUnit(editingId.value, payload)
|
||||
} else {
|
||||
await fetchCreateItemUnit(payload)
|
||||
}
|
||||
ElMessage.success(isEdit.value ? '更新成功' : '创建成功')
|
||||
dialogVisible.value = false
|
||||
await loadData()
|
||||
} catch {
|
||||
/* 校验或接口错误已由全局处理 */
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleView(row: Api.ItemUnit.ItemUnitItem) {
|
||||
viewRow.value = row
|
||||
viewVisible.value = true
|
||||
}
|
||||
|
||||
function handleDropdownCommand(command: string, row: any) {
|
||||
switch (command) {
|
||||
case 'edit':
|
||||
handleEdit(row)
|
||||
break
|
||||
case 'delete':
|
||||
handleDelete(row)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.ItemUnit.ItemUnitItem) {
|
||||
await ElMessageBox.confirm('确定要删除该单位吗?', '提示', { type: 'warning' })
|
||||
await fetchDeleteItemUnit(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
await loadData()
|
||||
}
|
||||
|
||||
async function handleBatchDelete() {
|
||||
const ids = selectedRows.value.map((r) => r.id)
|
||||
if (!ids.length) return
|
||||
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个单位吗?`, '提示', {
|
||||
type: 'warning'
|
||||
})
|
||||
await withFullscreenLoading(async () => {
|
||||
for (const id of ids) {
|
||||
await fetchDeleteItemUnit(id)
|
||||
}
|
||||
ElMessage.success('批量删除成功')
|
||||
selectedRows.value = []
|
||||
await loadData()
|
||||
}, fullscreenLoadingText.batchDelete)
|
||||
}
|
||||
// 输入检索条件时自动搜索(防抖 300ms)
|
||||
watchDebounced(
|
||||
searchForm,
|
||||
() => {
|
||||
pagination.page = 1
|
||||
loadData()
|
||||
},
|
||||
{ debounce: 300, deep: true }
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.unit-dialog-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -34,11 +34,11 @@
|
||||
<div class="profile-info">
|
||||
<div class="profile-name">{{ userData.realName }}</div>
|
||||
<div class="profile-tags">
|
||||
<el-tag :type="getRoleTagType(userData.role)" size="small">{{
|
||||
getRoleText(userData.role)
|
||||
<el-tag :type="dictStore.getTagType('user_role', userData.role)" size="small">{{
|
||||
dictStore.getLabel('user_role', userData.role)
|
||||
}}</el-tag>
|
||||
<el-tag :type="userData.isActive ? 'success' : 'danger'" size="small">{{
|
||||
userData.isActive ? '启用' : '禁用'
|
||||
<el-tag :type="dictStore.getTagType('sys_status', userData.isActive ? '1' : '0')" size="small">{{
|
||||
dictStore.getLabel('sys_status', userData.isActive ? '1' : '0')
|
||||
}}</el-tag>
|
||||
<el-tag v-if="userData.regionName" size="small">{{ userData.regionName }}</el-tag>
|
||||
</div>
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div class="info-label">角色</div>
|
||||
<div class="info-value">{{ getRoleText(userData.role) }}</div>
|
||||
<div class="info-value">{{ dictStore.getLabel('user_role', userData.role) }}</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div class="info-label">所属区域</div>
|
||||
@@ -299,13 +299,16 @@
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
|
||||
import { ArrowLeft, Close, Check } from '@element-plus/icons-vue'
|
||||
import { fetchUserDetail, fetchUpdateUser, fetchActiveRegions } from '@/api/admin'
|
||||
import { fetchUserDetail, fetchUpdateUser } from '@/api/admin'
|
||||
import { resolveUserAvatarUrl } from '@/utils/user-avatar'
|
||||
import { formatMoneyDisplay } from '@/utils/money-format'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
|
||||
defineOptions({ name: 'UserDetail' })
|
||||
|
||||
const dictStore = useDictStore()
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
@@ -397,27 +400,6 @@
|
||||
return userData.value.realName?.charAt(0) || '?'
|
||||
})
|
||||
|
||||
// 获取角色相关
|
||||
const getRoleTagType = (role: string) => {
|
||||
const typeMap: Record<string, string> = {
|
||||
admin: 'primary',
|
||||
supplier: 'warning',
|
||||
client: 'success',
|
||||
deliver: 'info'
|
||||
}
|
||||
return typeMap[role] || 'info'
|
||||
}
|
||||
|
||||
const getRoleText = (role: string) => {
|
||||
const textMap: Record<string, string> = {
|
||||
admin: '运营管理员',
|
||||
supplier: '供应商',
|
||||
client: '客户',
|
||||
deliver: '配送员'
|
||||
}
|
||||
return textMap[role] || role
|
||||
}
|
||||
|
||||
// 格式化金额
|
||||
const formatAmount = (amount: number | string) => {
|
||||
if (amount == null || amount === '') return '0.00'
|
||||
@@ -518,8 +500,8 @@
|
||||
// 加载区域
|
||||
const loadRegions = async () => {
|
||||
try {
|
||||
const res = await fetchActiveRegions()
|
||||
regionList.value = res
|
||||
// TODO: 恢复区域加载(需要重新实现 region API)
|
||||
regionList.value = []
|
||||
} catch (error) {
|
||||
console.error('加载区域失败:', error)
|
||||
}
|
||||
|
||||
@@ -165,8 +165,8 @@
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '1' ? 'success' : 'info'" size="small">
|
||||
{{ row.status === '1' ? '正常' : '停用' }}
|
||||
<el-tag :type="dictStore.getTagType('sys_status', row.status)" size="small">
|
||||
{{ dictStore.getLabel('sys_status', row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -318,19 +318,12 @@
|
||||
fetchDeptTree,
|
||||
fetchRoleOptions
|
||||
} from '@/api/admin'
|
||||
import { buildPathLabelMapFromTreeRoots } from '@/utils/tree-path'
|
||||
import { buildPathLabelMapFromTreeRoots } from '@/utils/tree-path'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
|
||||
const roleOptions = ref<Array<{ label: string; value: string }>>([])
|
||||
defineOptions({ name: 'SystemUser' })
|
||||
|
||||
async function loadRoleOptions() {
|
||||
try {
|
||||
roleOptions.value = (await fetchRoleOptions()) || []
|
||||
} catch {
|
||||
roleOptions.value = []
|
||||
}
|
||||
}
|
||||
|
||||
defineOptions({ name: 'SystemUser' })
|
||||
const dictStore = useDictStore()
|
||||
|
||||
const deptKeyword = ref('')
|
||||
const deptTree = ref<Api.Dept.DeptItem[]>([])
|
||||
@@ -624,8 +617,8 @@
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
value: row.status === '1' ? '正常' : '停用',
|
||||
tagType: row.status === '1' ? 'success' : 'info'
|
||||
value: dictStore.getLabel('sys_status', row.status),
|
||||
tagType: dictStore.getTagType('sys_status', row.status)
|
||||
},
|
||||
{ label: '角色', value: formatUserRoleDisplay(row), span: true },
|
||||
{ label: '创建时间', value: row.createTime },
|
||||
|
||||
@@ -4,22 +4,16 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
|
||||
defineOptions({ name: 'ProcessStatusTag' })
|
||||
|
||||
const dictStore = useDictStore()
|
||||
|
||||
const props = defineProps<{
|
||||
status: string
|
||||
}>()
|
||||
|
||||
const statusMap: Record<string, { type: string; label: string }> = {
|
||||
running: { type: 'warning', label: '进行中' },
|
||||
completed: { type: 'success', label: '已完成' },
|
||||
rejected: { type: 'danger', label: '已驳回' },
|
||||
cancelled: { type: 'info', label: '已取消' },
|
||||
pending: { type: 'warning', label: '待处理' },
|
||||
approved: { type: 'success', label: '已通过' },
|
||||
withdrawn: { type: 'info', label: '已撤回' }
|
||||
}
|
||||
|
||||
const tagType = computed(() => statusMap[props.status]?.type ?? 'info')
|
||||
const label = computed(() => statusMap[props.status]?.label ?? props.status)
|
||||
const tagType = computed(() => dictStore.getTagType('wf_process_status', props.status))
|
||||
const label = computed(() => dictStore.getLabel('wf_process_status', props.status))
|
||||
</script>
|
||||
Reference in new issue
Block a user