1.将部门修改为渠道,并且所有dice_表关联渠道表

2.将所有配置表,记录表设置关联渠道
3.优化后台页面设置
This commit is contained in:
2026-05-19 09:49:02 +08:00
parent 085454fb78
commit dd264b1e97
143 changed files with 4741 additions and 1254 deletions

View File

@@ -1,16 +1,24 @@
<template>
<div class="art-full-height">
<div class="box-border flex gap-4 h-full max-md:block max-md:gap-0 max-md:h-auto">
<div class="flex-shrink-0 w-64 h-full max-md:w-full max-md:h-auto max-md:mb-5">
<ElCard class="tree-card art-card-xs flex flex-col h-full mt-0" shadow="never">
<div
v-show="showChannelSidebar"
class="flex-shrink-0 w-64 h-full max-md:w-full max-md:h-auto max-md:mb-5"
>
<ElCard
class="tree-card art-card-xs flex flex-col h-full mt-0"
shadow="never"
v-loading="channelTreeLoading"
>
<template #header>
<b>部门列表</b>
<b>{{ $t('page.ui.channelList') }}</b>
</template>
<ElScrollbar>
<ElTree
:data="treeData"
:props="{ children: 'children', label: 'label' }"
node-key="id"
:current-node-key="currentChannelId"
default-expand-all
highlight-current
@node-click="handleNodeClick"
@@ -136,10 +144,19 @@
import WorkDialog from './modules/work-dialog.vue'
import api from '@/api/system/user'
import deptApi from '@/api/system/dept'
import { isSuperAdminUser } from '@/utils/channelLayout'
const userStore = useUserStore()
const treeData = ref([])
interface ChannelTreeNode {
id: number
label: string
children?: ChannelTreeNode[]
}
const treeData = ref<ChannelTreeNode[]>([])
const channelTreeLoading = ref(false)
const currentChannelId = ref<number | undefined>(undefined)
// 编辑框
const { dialogType, dialogVisible, dialogData, showDialog, handleSelectionChange, deleteRow } =
@@ -228,24 +245,79 @@
const handleReset = () => {
searchForm.value.dept_id = undefined
resetSearchParams()
if (isSuperAdminUser()) {
currentChannelId.value = undefined
} else {
applyDefaultChannelSelection()
}
}
/**
* 切换部门
* @param data
*/
const handleNodeClick = (data: any) => {
const handleNodeClick = (data: ChannelTreeNode) => {
currentChannelId.value = data.id
searchParams.dept_id = data.id
getData()
}
/** 仅超管显示左侧渠道列表;渠道管理员固定本渠道,由后端过滤 */
const showChannelSidebar = computed(() => isSuperAdminUser())
const normalizeChannelTree = (list: unknown[]): ChannelTreeNode[] => {
if (!Array.isArray(list)) {
return []
}
return list
.map((item) => {
const row = item as Record<string, unknown>
const id = Number(row.id ?? row.value ?? 0)
const label = String(row.label ?? row.name ?? '')
return { id, label }
})
.filter((node) => node.id > 0 && node.label !== '')
}
const fallbackChannelTree = (): ChannelTreeNode[] => {
const dept = userStore.info?.department
if (!dept || Number(dept.id) <= 0) {
return []
}
return [
{
id: Number(dept.id),
label: String(dept.name ?? '')
}
]
}
const applyDefaultChannelSelection = () => {
if (treeData.value.length === 0 || isSuperAdminUser()) {
return
}
const first = treeData.value[0]
currentChannelId.value = first.id
searchParams.dept_id = first.id
getData()
}
/**
* 获取部门数据
* 获取可操作渠道(渠道管理员至少展示本渠道)
*/
const getDeptList = () => {
deptApi.accessDept().then((data: any) => {
treeData.value = data
})
const getDeptList = async () => {
channelTreeLoading.value = true
try {
const data = await deptApi.accessDept()
const nodes = normalizeChannelTree(Array.isArray(data) ? data : [])
treeData.value = nodes.length > 0 ? nodes : fallbackChannelTree()
applyDefaultChannelSelection()
} catch {
treeData.value = fallbackChannelTree()
applyDefaultChannelSelection()
} finally {
channelTreeLoading.value = false
}
}
/**
@@ -283,6 +355,10 @@
}
onMounted(() => {
getDeptList()
if (isSuperAdminUser()) {
getDeptList()
} else {
applyDefaultChannelSelection()
}
})
</script>

View File

@@ -52,13 +52,14 @@
<el-row>
<el-col :span="12">
<el-form-item :label="$t('page.form.labelDept')" prop="dept_id">
<el-tree-select
v-model="formData.dept_id"
:data="optionData.deptData"
:render-after-expand="false"
check-strictly
clearable
/>
<el-select v-model="formData.dept_id" clearable filterable>
<el-option
v-for="item in optionData.deptData"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
@@ -206,6 +207,41 @@
/**
* 监听弹窗打开,初始化表单数据
*/
const flattenDeptOptions = (list: any[], result: { id: number; label: string }[] = []) => {
for (const item of list) {
const id = item.id ?? item.value
if (id !== undefined && id !== null) {
result.push({
id,
label: String(item.label ?? item.name ?? id)
})
}
if (item.children?.length) {
flattenDeptOptions(item.children, result)
}
}
return result
}
const loadRoleOptions = async () => {
const deptId = formData.dept_id
const params =
deptId !== undefined && deptId !== null && deptId !== ''
? { dept_id: deptId }
: undefined
const roleData = await roleApi.accessRole(params)
optionData.roleList = Array.isArray(roleData) ? roleData : []
}
watch(
() => formData.dept_id,
() => {
if (props.modelValue) {
void loadRoleOptions()
}
}
)
watch(
() => props.modelValue,
(newVal) => {
@@ -214,26 +250,23 @@
}
}
)
// 初始化页面数据
const initPage = async () => {
// 先重置为初始值
Object.assign(formData, initialFormData)
// 部门数据
const deptData = await deptApi.accessDept()
optionData.deptData = deptData
optionData.deptData = flattenDeptOptions(Array.isArray(deptData) ? deptData : [])
// 角色数据
const roleData = await roleApi.accessRole()
optionData.roleList = roleData
// 如果有数据,则填充数据
if (props.data) {
if (props.data?.id) {
await nextTick()
if (props.data.id) {
let data = await api.read(props.data.id)
const role = (data.roleList as any[])?.map((item: any) => item.id)
data.role_ids = role
data.password = ''
initForm(data)
}
const data = await api.read(props.data.id)
const role = (data.roleList as any[])?.map((item: any) => item.id)
data.role_ids = role
data.password = ''
initForm(data)
await loadRoleOptions()
} else {
await loadRoleOptions()
}
}