<template>
|
<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
|
:close-on-click-modal="false">
|
<div class="detail-container" v-if="dialogReadonly">
|
<el-row>
|
<el-col :span="12">
|
<div class="label">部门名称</div>
|
<div class="val">{{ formData.deptName }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">部门全称</div>
|
<div class="val">{{ formData.fullName }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">上级部门</div>
|
<div class="val">{{ formData.parentName }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">部门类型</div>
|
<div class="val">{{ getDictLabel(formData.deptCategory, dictObj.org_category) }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">部门性质</div>
|
<div class="val">{{ getDictLabel(formData.deptNature, dictObj.org_nature) }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">行政区划</div>
|
<div class="val">{{ formData.areaName || '-' }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">排序</div>
|
<div class="val">{{ formData.sort }}</div>
|
</el-col>
|
<el-col :span="24">
|
<div class="label">备注</div>
|
<div class="val">{{ formData.remark || '-' }}</div>
|
</el-col>
|
</el-row>
|
</div>
|
|
<el-form class="dialog-form" v-else ref="formRef" :model="formData" :rules="rules" label-width="100px">
|
<el-row>
|
<el-col :span="12">
|
<el-form-item label="部门名称" prop="deptName">
|
<el-input class="command-input" v-model="formData.deptName" maxlength="50" placeholder="请输入" clearable />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="部门全称" prop="fullName">
|
<el-input class="command-input" v-model="formData.fullName" maxlength="50" placeholder="请输入" clearable />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="上级部门" prop="parentId">
|
<el-tree-select
|
class="command-select"
|
popper-class="command-tree-select-popper"
|
v-model="formData.parentId"
|
:data="deptTree"
|
:props="treeProps"
|
node-key="id"
|
check-strictly
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="部门类型" prop="deptCategory">
|
<el-select class="command-select" popper-class="command-select-popper" v-model="formData.deptCategory" placeholder="请选择" clearable>
|
<el-option v-for="item in dictObj.org_category" :key="item.dictKey" :label="item.dictValue" :value="Number(item.dictKey)" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="部门性质" prop="deptNature">
|
<el-select class="command-select" popper-class="command-select-popper" v-model="formData.deptNature" placeholder="请选择" clearable>
|
<el-option v-for="item in dictObj.org_nature" :key="item.dictKey" :label="item.dictValue" :value="Number(item.dictKey)" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="排序" prop="sort">
|
<el-input-number class="command-input" v-model="formData.sort" :min="0" :controls="false" placeholder="请输入" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="行政区划" prop="areaCode">
|
<el-cascader
|
class="command-cascader"
|
popper-class="command-cascader-popper"
|
v-model="formData.areaCode"
|
:props="areaProps"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="24">
|
<el-form-item label="备注" prop="remark">
|
<el-input class="command-input" v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入" clearable />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
|
<template #footer>
|
<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
|
<el-button color="#284FE3" v-if="!dialogReadonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit">
|
保存
|
</el-button>
|
</template>
|
</el-dialog>
|
</template>
|
|
<script setup>
|
import { computed, inject, ref } from 'vue'
|
import { ElMessage } from 'element-plus'
|
import { add, getDept, getDeptTree, update } from '@/api/system/dept'
|
import { getLazyTree } from '@/api/base/region'
|
import { fieldRules, getDictLabel } from '@ztzf/utils'
|
import { saveOperationLog } from '@ztzf/apis'
|
import { useRoute } from 'vue-router'
|
|
const initForm = () => ({
|
deptName: '',
|
fullName: '',
|
parentId: '',
|
parentName: '',
|
deptCategory: null,
|
deptNature: null,
|
areaCode: [],
|
areaName: '',
|
sort: 0,
|
remark: '',
|
})
|
|
const treeProps = {
|
label: 'name',
|
children: 'children',
|
}
|
|
const areaProps = {
|
label: 'title',
|
value: 'value',
|
emitPath: true,
|
checkStrictly: true,
|
lazy: true,
|
lazyLoad(node, resolve) {
|
const level = node.level
|
let list = []
|
const callback = () => {
|
resolve(
|
(list || []).map(ele => ({
|
...ele,
|
value: ele.value,
|
leaf: level >= 2,
|
}))
|
)
|
}
|
if (level === 0) {
|
getLazyTree('000000000000').then(res => {
|
list = res.data.data
|
callback()
|
})
|
} else {
|
getLazyTree(node.value).then(res => {
|
list = res.data.data
|
callback()
|
})
|
}
|
},
|
}
|
|
const dictObj = inject('dictObj')
|
const deptTree = inject('deptTree')
|
const emit = defineEmits(['success'])
|
const formRef = ref(null)
|
const formData = ref(initForm())
|
const visible = defineModel()
|
const dialogMode = ref('add')
|
const submitting = ref(false)
|
const isAddChild = ref(false)
|
const dialogReadonly = computed(() => dialogMode.value === 'view')
|
const route = useRoute()
|
const dialogTitle = computed(() => {
|
if (dialogMode.value === 'edit') return '编辑'
|
if (dialogMode.value === 'view') return '查看'
|
return '新增'
|
})
|
|
const rules = {
|
deptName: fieldRules(true, 50),
|
fullName: fieldRules(true, 50),
|
parentId: fieldRules(false),
|
deptCategory: fieldRules(true),
|
deptNature: fieldRules(true),
|
areaCode: fieldRules(true),
|
sort: fieldRules(true),
|
}
|
|
function normalizeAreaCode(value) {
|
if (!value) return ''
|
if (Array.isArray(value)) {
|
return value[value.length - 1]
|
}
|
if (typeof value === 'string' && value.includes(',')) {
|
const codes = value.split(',')
|
return codes[codes.length - 1]
|
}
|
return value
|
}
|
|
function getFullAreaCode(areaCode) {
|
if (!areaCode) return []
|
if (Array.isArray(areaCode)) return areaCode
|
const code = areaCode.toString()
|
if (code.includes(',')) return code.split(',')
|
if (code.endsWith('0000000000')) {
|
return [code]
|
} else if (code.endsWith('00000000') && !code.endsWith('0000000000')) {
|
const provinceCode = code.substring(0, 2) + '0000000000'
|
return [provinceCode, code]
|
} else {
|
const provinceCode = code.substring(0, 2) + '0000000000'
|
const cityCode = code.substring(0, 4) + '00000000'
|
return [provinceCode, cityCode, code]
|
}
|
}
|
|
function normalizeNumber(value) {
|
if (value === '' || value === null || value === undefined) return null
|
const num = Number(value)
|
return Number.isNaN(num) ? null : num
|
}
|
|
function handleCancel() {
|
visible.value = false
|
}
|
|
async function handleSubmit() {
|
const isValid = await formRef.value?.validate().catch(() => false)
|
if (!isValid) return
|
submitting.value = true
|
try {
|
const payload = {
|
...formData.value,
|
areaCode: normalizeAreaCode(formData.value.areaCode),
|
}
|
if (dialogMode.value === 'edit') {
|
await update(payload)
|
} else {
|
await add(payload)
|
}
|
const actionText = dialogMode.value === 'add' ? (isAddChild.value ? '新增子项' : '新增') : '编辑'
|
saveOperationLog({
|
requestUri: route.path,
|
title: `${route.name || '部门管理'}-${actionText}`,
|
type: 1
|
})
|
ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功')
|
visible.value = false
|
emit('success', { parentId: formData.value.parentId || null, mode: dialogMode.value, isAddChild: isAddChild.value })
|
} finally {
|
submitting.value = false
|
}
|
}
|
|
async function loadDetail(id) {
|
if (!id) return
|
const res = await getDept(id)
|
const data = res?.data?.data ?? {}
|
formData.value = {
|
...data,
|
deptCategory: normalizeNumber(data.deptCategory),
|
deptNature: normalizeNumber(data.deptNature),
|
areaCode: getFullAreaCode(data.areaCode),
|
}
|
}
|
|
function handleClosed() {
|
formData.value = initForm()
|
isAddChild.value = false
|
}
|
|
async function open({ mode, row, parent } = {}) {
|
dialogMode.value = mode || 'add'
|
isAddChild.value = mode === 'add' && !!parent?.id
|
await getDeptTree().then(res => {
|
if (deptTree) {
|
deptTree.value = res?.data?.data ?? []
|
}
|
})
|
if (dialogMode.value === 'add') {
|
formData.value = initForm()
|
if (parent?.id) {
|
formData.value.parentId = parent.id
|
formData.value.parentName = parent.deptName
|
}
|
return
|
}
|
formData.value = row
|
await loadDetail(row?.id)
|
}
|
|
defineExpose({ open })
|
</script>
|