【账号中心】 新增# 子账号管理
							parent
							
								
									6d3cab044e
								
							
						
					
					
						commit
						4221095b2c
					
				
								
									
									
										
											2
										
									
									.env
									
									
									
									
								
								
							
							
										
											2
										
									
									.env
									
									
									
									
								| 
						 | 
					@ -1,2 +1,2 @@
 | 
				
			||||||
VITE_APP_BASE_URL = 'http://192.168.4.117:8082'
 | 
					VITE_APP_BASE_URL = 'http://124.220.209.120:8082'
 | 
				
			||||||
VITE_MAP_KEY = '2SABZ-S4TWH-AMCDO-W742B-SKEOE-UWBKJ'
 | 
					VITE_MAP_KEY = '2SABZ-S4TWH-AMCDO-W742B-SKEOE-UWBKJ'
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,45 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					    <el-dialog v-model="dialogVisible" :title="parameter.title" :width="parameter.width">
 | 
				
			||||||
 | 
					        <slot />
 | 
				
			||||||
 | 
					        <template #footer>
 | 
				
			||||||
 | 
					            <el-button @click="handleCancel">取消</el-button>
 | 
				
			||||||
 | 
					            <el-button type="primary" @click="handleConfirm">确认</el-button>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					    </el-dialog>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					export interface IParams {
 | 
				
			||||||
 | 
					    title: string
 | 
				
			||||||
 | 
					    width?: string | number
 | 
				
			||||||
 | 
					    data: { [key: string]: any }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const emit = defineEmits(['handleCancel', 'handleConfirm'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const dialogVisible = ref(false)
 | 
				
			||||||
 | 
					// 父组件传递过来的参数
 | 
				
			||||||
 | 
					const parameter = ref<IParams>({
 | 
				
			||||||
 | 
					    title: '',
 | 
				
			||||||
 | 
					    width: '50%',
 | 
				
			||||||
 | 
					    data: {}
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					const openDialog = (params: IParams) => {
 | 
				
			||||||
 | 
					    parameter.value = { ...parameter.value, ...params }
 | 
				
			||||||
 | 
					    dialogVisible.value = true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const handleCancel = () => {
 | 
				
			||||||
 | 
					    emit('handleCancel', closeDialog)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const handleConfirm = () => {
 | 
				
			||||||
 | 
					    emit('handleConfirm', closeDialog)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const closeDialog = () => {
 | 
				
			||||||
 | 
					    dialogVisible.value = false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					defineExpose({
 | 
				
			||||||
 | 
					    openDialog,
 | 
				
			||||||
 | 
					    dialogVisible
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					<style scoped></style>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,42 @@
 | 
				
			||||||
 | 
					<script lang="jsx" >
 | 
				
			||||||
 | 
					import { defineComponent, inject, ref } from 'vue';
 | 
				
			||||||
 | 
					import { filterEnum, handleRowAccordToProp, formatValue, handleProp } from '@/utils/util'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default defineComponent({
 | 
				
			||||||
 | 
					    props: {
 | 
				
			||||||
 | 
					        column: {
 | 
				
			||||||
 | 
					            tyep: Object,
 | 
				
			||||||
 | 
					            default: () => ({})
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    setup(props, { emit, slots }) {
 | 
				
			||||||
 | 
					        const enumMap = inject("enumMap", ref(new Map()))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // 渲染表格数据
 | 
				
			||||||
 | 
					        const renderCellData = (item, scope) => {
 | 
				
			||||||
 | 
					            return enumMap.value.get(item.prop) 
 | 
				
			||||||
 | 
					            ? filterEnum(handleRowAccordToProp(scope.row, item.prop), enumMap.value.get(item.prop), item.fieldNames) 
 | 
				
			||||||
 | 
					            : formatValue(handleRowAccordToProp(scope.row, item.prop))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const { column } = props
 | 
				
			||||||
 | 
					        return () => (
 | 
				
			||||||
 | 
					            <>
 | 
				
			||||||
 | 
					                <el-table-column {...column} showOverflowTooltip={column?.showOverflowTooltip ?? false } align={column.align ?? 'left'}>
 | 
				
			||||||
 | 
					                    {{
 | 
				
			||||||
 | 
					                        default: (scope) => {
 | 
				
			||||||
 | 
					                            if (column.render) return column.render(scope); //执行render函数
 | 
				
			||||||
 | 
					                            if(slots[handleProp(column.prop)]) return slots[handleProp(column.prop)](scope) //执行具名插槽
 | 
				
			||||||
 | 
					                            return renderCellData(column, scope)
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
 | 
					                </el-table-column>
 | 
				
			||||||
 | 
					            </>
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style scoped></style>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,105 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					    <el-table
 | 
				
			||||||
 | 
					        class="pro-table"
 | 
				
			||||||
 | 
					        ref="tableRef"
 | 
				
			||||||
 | 
					        v-loading="loading"
 | 
				
			||||||
 | 
					        :data="tableData"
 | 
				
			||||||
 | 
					        :row-key="rowKey"
 | 
				
			||||||
 | 
					        :row-class-name="({ row }) => row[rowKey]"
 | 
				
			||||||
 | 
					        :max-height="maxHeight"
 | 
				
			||||||
 | 
					        @selection-change="selectionChange"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					        <slot />
 | 
				
			||||||
 | 
					        <template v-for="item in tableColumns" :key="item">
 | 
				
			||||||
 | 
					            <el-table-column v-if="item.type && columnTypes.includes(item.type)" v-bind="item"></el-table-column>
 | 
				
			||||||
 | 
					            <TableColumn v-if="!item.type && item.prop" :column="item">
 | 
				
			||||||
 | 
					                <template v-for="slot in Object.keys($slots)" #[slot]="scope">
 | 
				
			||||||
 | 
					                    <slot :name="slot" v-bind="scope" />
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					            </TableColumn>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					    </el-table>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup name="ProTable">
 | 
				
			||||||
 | 
					import { provide, reactive, ref, unref } from 'vue'
 | 
				
			||||||
 | 
					import TableColumn from './components/TableColumn.vue'
 | 
				
			||||||
 | 
					import useSelection from '@/hooks/useSelection'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
					    columns: {
 | 
				
			||||||
 | 
					        type: Array,
 | 
				
			||||||
 | 
					        default: () => []
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    tableData: {
 | 
				
			||||||
 | 
					        type: Array,
 | 
				
			||||||
 | 
					        default: () => []
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    loading: {
 | 
				
			||||||
 | 
					        type: Boolean,
 | 
				
			||||||
 | 
					        default: false
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    maxHeight: {
 | 
				
			||||||
 | 
					        type: [Number, String],
 | 
				
			||||||
 | 
					        default: ''
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    rowKey: {
 | 
				
			||||||
 | 
					        type: String,
 | 
				
			||||||
 | 
					        default: 'id'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { isSelected, selectedList, selectedListIds, selectionChange } = useSelection(props.rowKey)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const columnTypes = ['selection', 'radio', 'index', 'expand', 'sort']
 | 
				
			||||||
 | 
					const tableRef = ref()
 | 
				
			||||||
 | 
					const enumMap = ref(new Map())
 | 
				
			||||||
 | 
					const tableColumns = reactive(props.columns)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 扁平化 columns
 | 
				
			||||||
 | 
					const flatColumnsFunc = columns => {
 | 
				
			||||||
 | 
					    columns.forEach(async column => {
 | 
				
			||||||
 | 
					        // 设置enumMap
 | 
				
			||||||
 | 
					        await setEnumMap(column)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// 定义 enumMap 存储 enum 值
 | 
				
			||||||
 | 
					const setEnumMap = async ({ prop, enum: enumValue }) => {
 | 
				
			||||||
 | 
					    if (!enumValue) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 如果当前 enumMap 存在相同的值 return
 | 
				
			||||||
 | 
					    if (enumMap.value.has(prop) && (typeof enumValue === 'function' || enumMap.value.get(prop) === enumValue)) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 当前 enum 为静态数据,则直接存储到 enumMap
 | 
				
			||||||
 | 
					    if (typeof enumValue !== 'function') return enumMap.value.set(prop, unref(enumValue))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 为了防止接口执行慢,而存储慢,导致重复请求,所以预先存储为[],接口返回后再二次存储
 | 
				
			||||||
 | 
					    enumMap.value.set(prop, [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 当前 enum 为后台数据需要请求数据,则调用该请求接口,并存储到 enumMap
 | 
				
			||||||
 | 
					    const { rows } = await enumValue()
 | 
				
			||||||
 | 
					    enumMap.value.set(prop, rows)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					flatColumnsFunc(tableColumns)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					provide('enumMap', enumMap)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					defineExpose({
 | 
				
			||||||
 | 
					    tableRef,
 | 
				
			||||||
 | 
					    isSelected,
 | 
				
			||||||
 | 
					    selectedList,
 | 
				
			||||||
 | 
					    selectedListIds
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.pro-table {
 | 
				
			||||||
 | 
					    :deep(.el-table__header) {
 | 
				
			||||||
 | 
					        width: 100% !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    :deep(.el-table__body) {
 | 
				
			||||||
 | 
					        width: 100% !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					export type FieldNamesProps = {
 | 
				
			||||||
 | 
					    label: string
 | 
				
			||||||
 | 
					    value: string
 | 
				
			||||||
 | 
					    children?: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					import { ElMessageBox } from 'element-plus'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type messageType = '' | 'success' | 'warning' | 'info' | 'error'
 | 
				
			||||||
 | 
					export default function useHandleData(message: string, messageType: messageType = 'warning'): Promise<boolean> {
 | 
				
			||||||
 | 
					    return new Promise(resolve => {
 | 
				
			||||||
 | 
					        ElMessageBox.confirm(message, '温馨提示', {
 | 
				
			||||||
 | 
					            confirmButtonText: '确定',
 | 
				
			||||||
 | 
					            cancelButtonText: '取消',
 | 
				
			||||||
 | 
					            type: messageType
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					            .then(() => {
 | 
				
			||||||
 | 
					                resolve(true)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .catch(() => {
 | 
				
			||||||
 | 
					                resolve(false)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,24 @@
 | 
				
			||||||
 | 
					import { computed, ref } from 'vue'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function useSelection(rowKey = 'id') {
 | 
				
			||||||
 | 
					    const isSelected = ref(false)
 | 
				
			||||||
 | 
					    const selectedList = ref([])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 当前选中的所有id
 | 
				
			||||||
 | 
					    const selectedListIds = computed(() => {
 | 
				
			||||||
 | 
					        const ids: number | string[] = []
 | 
				
			||||||
 | 
					        selectedList.value.forEach(item => ids.push(item[rowKey]))
 | 
				
			||||||
 | 
					        return ids
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    // 多选操作
 | 
				
			||||||
 | 
					    const selectionChange = (rowArr = []) => {
 | 
				
			||||||
 | 
					        isSelected.value = rowArr.length ? true : false
 | 
				
			||||||
 | 
					        selectedList.value = rowArr
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        isSelected,
 | 
				
			||||||
 | 
					        selectedList,
 | 
				
			||||||
 | 
					        selectedListIds,
 | 
				
			||||||
 | 
					        selectionChange
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,14 @@ import 'virtual:svg-icons-register'
 | 
				
			||||||
import eventBus from 'vue3-eventbus'
 | 
					import eventBus from 'vue3-eventbus'
 | 
				
			||||||
import directives from './directives'
 | 
					import directives from './directives'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 表格组件
 | 
				
			||||||
 | 
					import ProTable from '@/components/ProTable/index.vue'
 | 
				
			||||||
 | 
					import ProDialog from '@/components/ProDialog/index.vue'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const app = createApp(App)
 | 
					const app = createApp(App)
 | 
				
			||||||
app.use(install)
 | 
					app.use(install)
 | 
				
			||||||
app.use(eventBus)
 | 
					app.use(eventBus)
 | 
				
			||||||
app.use(directives)
 | 
					app.use(directives)
 | 
				
			||||||
 | 
					app.component('ProTable', ProTable)
 | 
				
			||||||
 | 
					app.component('ProDialog', ProDialog)
 | 
				
			||||||
app.mount('#app')
 | 
					app.mount('#app')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
    --navbar-height: 50px;
 | 
					    --navbar-height: 50px;
 | 
				
			||||||
    --color-white: #ffffff;
 | 
					    --color-white: #ffffff;
 | 
				
			||||||
    --color-red: #d9001b;
 | 
					    --color-red: #d9001b;
 | 
				
			||||||
 | 
					    --color-green: #00b42a;
 | 
				
			||||||
    --table-header-bg-color: #f8f8f8;
 | 
					    --table-header-bg-color: #f8f8f8;
 | 
				
			||||||
    --el-font-size-extra-large: 18px;
 | 
					    --el-font-size-extra-large: 18px;
 | 
				
			||||||
    --el-menu-base-level-padding: 16px;
 | 
					    --el-menu-base-level-padding: 16px;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					// 判断是否是数组
 | 
				
			||||||
 | 
					export function isArray(value) {
 | 
				
			||||||
 | 
					    return Array.isArray(value)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
import { isObject } from '@vue/shared'
 | 
					import { isObject } from '@vue/shared'
 | 
				
			||||||
import { ElMessage, type messageType } from 'element-plus'
 | 
					import { ElMessage, type messageType } from 'element-plus'
 | 
				
			||||||
import { cloneDeep } from 'lodash'
 | 
					import { cloneDeep } from 'lodash'
 | 
				
			||||||
 | 
					import { isArray } from './is'
 | 
				
			||||||
 | 
					import type { FieldNamesProps } from '@/components/ProTable/interface'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @description 添加单位
 | 
					 * @description 添加单位
 | 
				
			||||||
| 
						 | 
					@ -261,9 +263,9 @@ export function formatFileSize(bytes: number) {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function retain(value: any, n: any): string {
 | 
					export function retain(value: any, n: any): string {
 | 
				
			||||||
    if (n === 'null' || n === 'undefined' || n === 0) return value
 | 
					    if (n === 'null' || n === 'undefined' || n === 0) return value
 | 
				
			||||||
    let tran = Math.round(value * Math.pow(10, n)) / Math.pow(10, n)
 | 
					    const tran = Math.round(value * Math.pow(10, n)) / Math.pow(10, n)
 | 
				
			||||||
    let tranV = tran.toString()
 | 
					    let tranV = tran.toString()
 | 
				
			||||||
    let newVal = tranV.indexOf('.')
 | 
					    const newVal = tranV.indexOf('.')
 | 
				
			||||||
    if (newVal < 0) {
 | 
					    if (newVal < 0) {
 | 
				
			||||||
        tranV += '.'
 | 
					        tranV += '.'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -272,3 +274,55 @@ export function retain(value: any, n: any): string {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return tranV
 | 
					    return tranV
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @description 处理 ProTable 值为数组 || 无数据
 | 
				
			||||||
 | 
					 * @param {*} callValue 需要处理的值
 | 
				
			||||||
 | 
					 * @returns {String}
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
 | 
					export function formatValue(callValue: any) {
 | 
				
			||||||
 | 
					    // 如果当前值为数组,使用 / 拼接(根据需求自定义)
 | 
				
			||||||
 | 
					    if (isArray(callValue)) return callValue.length ? callValue.join(' / ') : '--'
 | 
				
			||||||
 | 
					    return callValue ?? '--'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {*} row 当前行数据
 | 
				
			||||||
 | 
					 * @param {*} prop 当前prop
 | 
				
			||||||
 | 
					 * @returns 返回单元格值
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function handleRowAccordToProp(row: { [key: string]: any }, prop: string) {
 | 
				
			||||||
 | 
					    if (!prop.includes('.')) return row[prop] ?? '--'
 | 
				
			||||||
 | 
					    return row
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 处理prop
 | 
				
			||||||
 | 
					 * @param {*} prop 当前prop
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function handleProp(prop: string) {
 | 
				
			||||||
 | 
					    const propArr = prop.split('.')
 | 
				
			||||||
 | 
					    if (propArr.length == 1) return prop
 | 
				
			||||||
 | 
					    return propArr[propArr.length - 1]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 根据枚举列表查询当需要的数据(如果指定了 label 和 value 的 key值,会自动识别格式化)
 | 
				
			||||||
 | 
					 * @param {*} callValue 当前单元格值
 | 
				
			||||||
 | 
					 * @param {*} enumData 字典列表
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function filterEnum(callValue: any, enumData?: any, fieldNames?: FieldNamesProps) {
 | 
				
			||||||
 | 
					    const value = fieldNames?.value ?? 'value'
 | 
				
			||||||
 | 
					    const label = fieldNames?.label ?? 'label'
 | 
				
			||||||
 | 
					    const children = fieldNames?.children ?? 'children'
 | 
				
			||||||
 | 
					    let filterData: { [key: string]: any } = {}
 | 
				
			||||||
 | 
					    // 判断 enumData 是否为数组
 | 
				
			||||||
 | 
					    if (Array.isArray(enumData)) filterData = findItemNested(enumData, callValue, value, children)
 | 
				
			||||||
 | 
					    return filterData ? filterData[label] : '--'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 递归查找 callValue 对应的 enum 值
 | 
				
			||||||
 | 
					export function findItemNested(enumData: any, callValue: any, value: string, children: string) {
 | 
				
			||||||
 | 
					    return enumData.reduce((accumulator: any, current: any) => {
 | 
				
			||||||
 | 
					        if (accumulator) return accumulator
 | 
				
			||||||
 | 
					        if (current[value] == callValue) return current
 | 
				
			||||||
 | 
					        if (current[children]) return findItemNested(current[children], callValue, value, children)
 | 
				
			||||||
 | 
					    }, null)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,149 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					    <ProDialog ref="proDialogRef" @handle-cancel="handleCancel" @handle-confirm="handleConfirm">
 | 
				
			||||||
 | 
					        <el-form :model="form" label-position="right" label-width="120">
 | 
				
			||||||
 | 
					            <el-form-item label="所属组织">
 | 
				
			||||||
 | 
					                <el-tree-select
 | 
				
			||||||
 | 
					                    v-model="form.organization"
 | 
				
			||||||
 | 
					                    :data="data"
 | 
				
			||||||
 | 
					                    :props="defaultProps"
 | 
				
			||||||
 | 
					                    :render-after-expand="false"
 | 
				
			||||||
 | 
					                    default-expand-all
 | 
				
			||||||
 | 
					                    style="width: 100%"
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            </el-form-item>
 | 
				
			||||||
 | 
					            <el-form-item label="账号名称">
 | 
				
			||||||
 | 
					                <el-input v-model="form.accountName" autocomplete="off" placeholder="请输入" maxlength="20" show-word-limit />
 | 
				
			||||||
 | 
					            </el-form-item>
 | 
				
			||||||
 | 
					            <el-form-item label="联系电话">
 | 
				
			||||||
 | 
					                <el-input v-model="form.mobile" autocomplete="off" placeholder="请输入" maxlength="11" show-word-limit />
 | 
				
			||||||
 | 
					            </el-form-item>
 | 
				
			||||||
 | 
					            <el-form-item label="岗位">
 | 
				
			||||||
 | 
					                <el-checkbox-group v-model="form.position">
 | 
				
			||||||
 | 
					                    <el-checkbox v-for="option in positionOptions" :key="option.value" :value="option.value" name="type">
 | 
				
			||||||
 | 
					                        {{ option.label }}
 | 
				
			||||||
 | 
					                    </el-checkbox>
 | 
				
			||||||
 | 
					                </el-checkbox-group>
 | 
				
			||||||
 | 
					            </el-form-item>
 | 
				
			||||||
 | 
					            <el-form-item>
 | 
				
			||||||
 | 
					                <template #label>
 | 
				
			||||||
 | 
					                    <div class="flex items-center gap-[6px] cursor-pointer">
 | 
				
			||||||
 | 
					                        <span>有效数据流向</span>
 | 
				
			||||||
 | 
					                        <el-tooltip effect="dark" placement="top">
 | 
				
			||||||
 | 
					                            <icon name="el-icon-QuestionFilled" />
 | 
				
			||||||
 | 
					                            <template #content>
 | 
				
			||||||
 | 
					                                <div>电销有效数据流向:</div>
 | 
				
			||||||
 | 
					                                <ul>
 | 
				
			||||||
 | 
					                                    <li v-for="(tooltip, index) in channelTooltips" :key="index" class="flex items-center gap-[4px]">
 | 
				
			||||||
 | 
					                                        <span class="w-[6px] h-[6px] bg-white rounded-[8px]"></span>
 | 
				
			||||||
 | 
					                                        {{ tooltip }}
 | 
				
			||||||
 | 
					                                    </li>
 | 
				
			||||||
 | 
					                                </ul>
 | 
				
			||||||
 | 
					                            </template>
 | 
				
			||||||
 | 
					                        </el-tooltip>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					                <el-radio-group v-model="form.channel">
 | 
				
			||||||
 | 
					                    <el-radio v-for="option in channelOptions" :key="option.value" :label="option.value">{{ option.label }}</el-radio>
 | 
				
			||||||
 | 
					                </el-radio-group>
 | 
				
			||||||
 | 
					                <template v-if="form.channel == 'specific'">
 | 
				
			||||||
 | 
					                    <el-select class="mt-[10px]" v-model="form.teacher" placeholder="请选择指定招生老师">
 | 
				
			||||||
 | 
					                        <el-option label="Zone one" value="shanghai" />
 | 
				
			||||||
 | 
					                        <el-option label="Zone two" value="beijing" />
 | 
				
			||||||
 | 
					                    </el-select>
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					            </el-form-item>
 | 
				
			||||||
 | 
					            <el-form-item label="账号状态">
 | 
				
			||||||
 | 
					                <el-radio-group v-model="form.accountStatus">
 | 
				
			||||||
 | 
					                    <el-radio v-for="option in accountStatusOptions" :key="option.value" :label="option.value">{{ option.label }}</el-radio>
 | 
				
			||||||
 | 
					                </el-radio-group>
 | 
				
			||||||
 | 
					            </el-form-item>
 | 
				
			||||||
 | 
					        </el-form>
 | 
				
			||||||
 | 
					    </ProDialog>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import ProDialog, { type IParams } from '@/components/ProDialog/index.vue'
 | 
				
			||||||
 | 
					const proDialogRef = ref<InstanceType<typeof ProDialog>>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const data = ref([
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        id: 1,
 | 
				
			||||||
 | 
					        label: '合创云公司',
 | 
				
			||||||
 | 
					        disabled: true,
 | 
				
			||||||
 | 
					        children: [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                id: 11,
 | 
				
			||||||
 | 
					                label: '湛江团队',
 | 
				
			||||||
 | 
					                disabled: true,
 | 
				
			||||||
 | 
					                children: [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        id: 111,
 | 
				
			||||||
 | 
					                        label: 'A组'
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        id: 112,
 | 
				
			||||||
 | 
					                        label: 'B组'
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        id: 113,
 | 
				
			||||||
 | 
					                        label: 'C组'
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                id: 12,
 | 
				
			||||||
 | 
					                label: '广州团队',
 | 
				
			||||||
 | 
					                disabled: true,
 | 
				
			||||||
 | 
					                children: [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        id: 121,
 | 
				
			||||||
 | 
					                        label: 'A组'
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					const defaultProps = {
 | 
				
			||||||
 | 
					    label: 'label', // 显示字段
 | 
				
			||||||
 | 
					    value: 'id', // 值字段
 | 
				
			||||||
 | 
					    children: 'children', // 子节点字段
 | 
				
			||||||
 | 
					    disabled: 'disabled'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const positionOptions = ref([
 | 
				
			||||||
 | 
					    { label: '电销老师', value: 1 },
 | 
				
			||||||
 | 
					    { label: '招生老师', value: 2 }
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					const channelOptions = ref([
 | 
				
			||||||
 | 
					    { label: '默认组织', value: 'default' },
 | 
				
			||||||
 | 
					    { label: '组织指定', value: 'specific' }
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					const accountStatusOptions = ref([
 | 
				
			||||||
 | 
					    { label: '启用', value: 1 },
 | 
				
			||||||
 | 
					    { label: '停用', value: 2 }
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					const channelTooltips = ['选择默认组织则数据流向到所属组织下的所有招生老师;', '选择组织指定则可选择将数据流向到所属组织下的指定招生老师;']
 | 
				
			||||||
 | 
					const form = ref({
 | 
				
			||||||
 | 
					    organization: '',
 | 
				
			||||||
 | 
					    accountName: '',
 | 
				
			||||||
 | 
					    mobile: '',
 | 
				
			||||||
 | 
					    position: '',
 | 
				
			||||||
 | 
					    channel: '',
 | 
				
			||||||
 | 
					    accountStatus: '',
 | 
				
			||||||
 | 
					    teacher: ''
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					const openDialog = (params: IParams) => {
 | 
				
			||||||
 | 
					    proDialogRef.value?.openDialog(params)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const handleCancel = (callback: () => void) => {
 | 
				
			||||||
 | 
					    callback()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const handleConfirm = (callback: () => void) => {
 | 
				
			||||||
 | 
					    callback()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					defineExpose({
 | 
				
			||||||
 | 
					    openDialog
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style scoped lang="scss"></style>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,125 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					    <el-dialog v-model="dialogVisible" :title="parameter.title" :width="parameter.width">
 | 
				
			||||||
 | 
					        <el-space direction="vertical" alignment="normal">
 | 
				
			||||||
 | 
					            <el-form :model="searchForm" ref="userFormRef" :inline="true" label-width="auto" @submit.native.prevent>
 | 
				
			||||||
 | 
					                <el-form-item label="账号名称">
 | 
				
			||||||
 | 
					                    <el-input class="ls-input" v-model="searchForm.accountName" placeholder="请输入账号名称" clearable></el-input>
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					                <el-form-item>
 | 
				
			||||||
 | 
					                    <el-button type="primary">搜索</el-button>
 | 
				
			||||||
 | 
					                    <el-button>重置</el-button>
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					            </el-form>
 | 
				
			||||||
 | 
					            <ProTable ref="proTableRef" :columns="columns" :tableData="tableData" :loading="loading" :maxHeight="530">
 | 
				
			||||||
 | 
					                <template #radio="{ row }">
 | 
				
			||||||
 | 
					                    <el-radio v-model="radio" :label="row.id"> </el-radio>
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					                <template #accountName="{ row }">
 | 
				
			||||||
 | 
					                    <el-space>
 | 
				
			||||||
 | 
					                        <span>{{ row.accountName }}</span>
 | 
				
			||||||
 | 
					                        <span
 | 
				
			||||||
 | 
					                            v-if="isGroupLeader(row.groupLeader)"
 | 
				
			||||||
 | 
					                            class="px-[6px] text-green border border-solid border-green rounded-[4px] text-center text-xs"
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                            组长
 | 
				
			||||||
 | 
					                        </span>
 | 
				
			||||||
 | 
					                    </el-space>
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					                <template #accountStatus="{ row }">
 | 
				
			||||||
 | 
					                    <el-switch v-model="row.accountStatus" disabled :active-value="1" :inactive-value="0" />
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					            </ProTable>
 | 
				
			||||||
 | 
					            <!-- <pagination v-model="pager" @change="getLists" layout="total, prev, pager, next, jumper" class="mb-[10px]" /> -->
 | 
				
			||||||
 | 
					        </el-space>
 | 
				
			||||||
 | 
					        <template #footer>
 | 
				
			||||||
 | 
					            <el-button @click="handleCancel">取消</el-button>
 | 
				
			||||||
 | 
					            <el-button type="primary" @click="handleConfirm">确认</el-button>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					    </el-dialog>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					interface IParams {
 | 
				
			||||||
 | 
					    title: string
 | 
				
			||||||
 | 
					    width?: string | number
 | 
				
			||||||
 | 
					    data: { [key: string]: any }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const dialogVisible = ref(false)
 | 
				
			||||||
 | 
					// 父组件传递过来的参数
 | 
				
			||||||
 | 
					const parameter = ref<IParams>({
 | 
				
			||||||
 | 
					    title: '',
 | 
				
			||||||
 | 
					    width: '50%',
 | 
				
			||||||
 | 
					    data: {}
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					const openDialog = (params: IParams) => {
 | 
				
			||||||
 | 
					    parameter.value = { ...parameter.value, ...params }
 | 
				
			||||||
 | 
					    dialogVisible.value = true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const emit = defineEmits(['refreshList'])
 | 
				
			||||||
 | 
					defineExpose({
 | 
				
			||||||
 | 
					    openDialog
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					const searchForm = ref({
 | 
				
			||||||
 | 
					    accountName: ''
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const loading = ref(false)
 | 
				
			||||||
 | 
					const proTableRef = ref()
 | 
				
			||||||
 | 
					const tableData = ref<any[]>([])
 | 
				
			||||||
 | 
					const columns = reactive([
 | 
				
			||||||
 | 
					    { prop: 'radio', label: '单选', width: 70 },
 | 
				
			||||||
 | 
					    { prop: 'accountName', label: '账号名称' },
 | 
				
			||||||
 | 
					    { prop: 'mobile', label: '联系电话' },
 | 
				
			||||||
 | 
					    { prop: 'organization', label: '所属组织' },
 | 
				
			||||||
 | 
					    { prop: 'position', label: '岗位' },
 | 
				
			||||||
 | 
					    { prop: 'accountStatus', label: '账号状态' }
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					const radio = ref()
 | 
				
			||||||
 | 
					const isGroupLeader = computed(() => (groupLeader: number) => groupLeader == 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
					    () => dialogVisible.value,
 | 
				
			||||||
 | 
					    val => {
 | 
				
			||||||
 | 
					        if (val) {
 | 
				
			||||||
 | 
					            loading.value = true
 | 
				
			||||||
 | 
					            setTimeout(() => {
 | 
				
			||||||
 | 
					                tableData.value = [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        id: 1,
 | 
				
			||||||
 | 
					                        accountName: '张三',
 | 
				
			||||||
 | 
					                        mobile: '18138952909',
 | 
				
			||||||
 | 
					                        organization: '广州团队-A组',
 | 
				
			||||||
 | 
					                        position: '电销老师',
 | 
				
			||||||
 | 
					                        accountStatus: 1,
 | 
				
			||||||
 | 
					                        groupLeader: 1
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        id: 2,
 | 
				
			||||||
 | 
					                        accountName: '李四',
 | 
				
			||||||
 | 
					                        mobile: '18138952909',
 | 
				
			||||||
 | 
					                        organization: '广州团队-A组',
 | 
				
			||||||
 | 
					                        position: '电销老师',
 | 
				
			||||||
 | 
					                        accountStatus: 1,
 | 
				
			||||||
 | 
					                        groupLeader: 0
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					                loading.value = false
 | 
				
			||||||
 | 
					                // 如果已设置组长,则需要默认回显
 | 
				
			||||||
 | 
					                if (tableData.value.length > 0) {
 | 
				
			||||||
 | 
					                    radio.value = tableData.value.find(item => item.groupLeader == 1)?.id
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }, 500)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					const handleCancel = () => {
 | 
				
			||||||
 | 
					    dialogVisible.value = false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const handleConfirm = () => {
 | 
				
			||||||
 | 
					    console.log(radio.value)
 | 
				
			||||||
 | 
					    dialogVisible.value = false
 | 
				
			||||||
 | 
					    emit('refreshList')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					<style scoped></style>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,109 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					    <ProDialog ref="proDialogRef" @handle-cancel="handleCancel" @handle-confirm="handleConfirm">
 | 
				
			||||||
 | 
					        <el-space direction="vertical" alignment="normal">
 | 
				
			||||||
 | 
					            <el-form :model="searchForm" ref="userFormRef" :inline="true" label-width="auto" @submit.native.prevent>
 | 
				
			||||||
 | 
					                <el-form-item label="账号名称">
 | 
				
			||||||
 | 
					                    <el-input class="ls-input" v-model="searchForm.accountName" placeholder="请输入账号名称" clearable></el-input>
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					                <el-form-item>
 | 
				
			||||||
 | 
					                    <el-button type="primary">搜索</el-button>
 | 
				
			||||||
 | 
					                    <el-button>重置</el-button>
 | 
				
			||||||
 | 
					                </el-form-item>
 | 
				
			||||||
 | 
					            </el-form>
 | 
				
			||||||
 | 
					            <ProTable ref="proTableRef" :columns="columns" :tableData="tableData" :loading="loading" :maxHeight="530">
 | 
				
			||||||
 | 
					                <template #radio="{ row }">
 | 
				
			||||||
 | 
					                    <el-radio v-model="radio" :label="row.id"> </el-radio>
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					                <template #accountName="{ row }">
 | 
				
			||||||
 | 
					                    <el-space>
 | 
				
			||||||
 | 
					                        <span>{{ row.accountName }}</span>
 | 
				
			||||||
 | 
					                        <span
 | 
				
			||||||
 | 
					                            v-if="isGroupLeader(row.groupLeader)"
 | 
				
			||||||
 | 
					                            class="px-[6px] text-green border border-solid border-green rounded-[4px] text-center text-xs"
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                            组长
 | 
				
			||||||
 | 
					                        </span>
 | 
				
			||||||
 | 
					                    </el-space>
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					                <template #accountStatus="{ row }">
 | 
				
			||||||
 | 
					                    <el-switch v-model="row.accountStatus" disabled :active-value="1" :inactive-value="0" />
 | 
				
			||||||
 | 
					                </template>
 | 
				
			||||||
 | 
					            </ProTable>
 | 
				
			||||||
 | 
					            <!-- <pagination v-model="pager" @change="getLists" layout="total, prev, pager, next, jumper" class="mb-[10px]" /> -->
 | 
				
			||||||
 | 
					        </el-space>
 | 
				
			||||||
 | 
					    </ProDialog>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import ProDialog, { type IParams } from '@/components/ProDialog/index.vue'
 | 
				
			||||||
 | 
					const proDialogRef = ref<InstanceType<typeof ProDialog>>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const emit = defineEmits(['refreshList'])
 | 
				
			||||||
 | 
					const searchForm = ref({
 | 
				
			||||||
 | 
					    accountName: ''
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const loading = ref(false)
 | 
				
			||||||
 | 
					const proTableRef = ref()
 | 
				
			||||||
 | 
					const tableData = ref<any[]>([])
 | 
				
			||||||
 | 
					const columns = reactive([
 | 
				
			||||||
 | 
					    { prop: 'radio', label: '单选', width: 70 },
 | 
				
			||||||
 | 
					    { prop: 'accountName', label: '账号名称' },
 | 
				
			||||||
 | 
					    { prop: 'mobile', label: '联系电话' },
 | 
				
			||||||
 | 
					    { prop: 'organization', label: '所属组织' },
 | 
				
			||||||
 | 
					    { prop: 'position', label: '岗位' },
 | 
				
			||||||
 | 
					    { prop: 'accountStatus', label: '账号状态' }
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					const radio = ref()
 | 
				
			||||||
 | 
					const isGroupLeader = computed(() => (groupLeader: number) => groupLeader == 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
					    () => proDialogRef.value?.dialogVisible,
 | 
				
			||||||
 | 
					    val => {
 | 
				
			||||||
 | 
					        if (val) {
 | 
				
			||||||
 | 
					            loading.value = true
 | 
				
			||||||
 | 
					            setTimeout(() => {
 | 
				
			||||||
 | 
					                tableData.value = [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        id: 1,
 | 
				
			||||||
 | 
					                        accountName: '张三',
 | 
				
			||||||
 | 
					                        mobile: '18138952909',
 | 
				
			||||||
 | 
					                        organization: '广州团队-A组',
 | 
				
			||||||
 | 
					                        position: '电销老师',
 | 
				
			||||||
 | 
					                        accountStatus: 1,
 | 
				
			||||||
 | 
					                        groupLeader: 1
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        id: 2,
 | 
				
			||||||
 | 
					                        accountName: '李四',
 | 
				
			||||||
 | 
					                        mobile: '18138952909',
 | 
				
			||||||
 | 
					                        organization: '广州团队-A组',
 | 
				
			||||||
 | 
					                        position: '电销老师',
 | 
				
			||||||
 | 
					                        accountStatus: 1,
 | 
				
			||||||
 | 
					                        groupLeader: 0
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					                loading.value = false
 | 
				
			||||||
 | 
					                // 如果已设置组长,则需要默认回显
 | 
				
			||||||
 | 
					                if (tableData.value.length > 0) {
 | 
				
			||||||
 | 
					                    radio.value = tableData.value.find(item => item.groupLeader == 1)?.id
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }, 500)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					const openDialog = (params: IParams) => {
 | 
				
			||||||
 | 
					    proDialogRef.value?.openDialog(params)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const handleCancel = (callback: () => void) => {
 | 
				
			||||||
 | 
					    callback()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const handleConfirm = (callback: () => void) => {
 | 
				
			||||||
 | 
					    callback()
 | 
				
			||||||
 | 
					    emit('refreshList')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					defineExpose({
 | 
				
			||||||
 | 
					    openDialog
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					<style scoped></style>
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,6 @@
 | 
				
			||||||
    <div class="flex-1 p-[16px]" v-loading="loading">
 | 
					    <div class="flex-1 p-[16px]" v-loading="loading">
 | 
				
			||||||
        <div class="mb-[10px]">
 | 
					        <div class="mb-[10px]">
 | 
				
			||||||
            <el-input v-model="filterText" placeholder="请输入" :suffix-icon="Search" clearable />
 | 
					            <el-input v-model="filterText" placeholder="请输入" :suffix-icon="Search" clearable />
 | 
				
			||||||
            {{ currentNodeKey }}
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <el-tree
 | 
					        <el-tree
 | 
				
			||||||
            ref="treeRef"
 | 
					            ref="treeRef"
 | 
				
			||||||
| 
						 | 
					@ -12,13 +11,14 @@
 | 
				
			||||||
            highlight-current
 | 
					            highlight-current
 | 
				
			||||||
            :current-node-key="currentNodeKey"
 | 
					            :current-node-key="currentNodeKey"
 | 
				
			||||||
            :default-expanded-keys="[primaryAccountId]"
 | 
					            :default-expanded-keys="[primaryAccountId]"
 | 
				
			||||||
 | 
					            :expand-on-click-node="false"
 | 
				
			||||||
            :filter-node-method="filterNode"
 | 
					            :filter-node-method="filterNode"
 | 
				
			||||||
            @node-click="handleNodeClick"
 | 
					            @node-click="handleNodeClick"
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #default="{ node, data }">
 | 
					            <template #default="{ node, data }">
 | 
				
			||||||
                <span class="flex-1 flex-row-between-center">
 | 
					                <span class="flex-1 flex-row-between-center">
 | 
				
			||||||
                    <span>{{ node.label }}</span>
 | 
					                    <span>{{ node.label }}</span>
 | 
				
			||||||
                    <el-dropdown placement="bottom" @command="handleCommand">
 | 
					                    <el-dropdown placement="bottom" @command="(...args: any[]) => handleCommand(args, data)">
 | 
				
			||||||
                        <span class="more mr-[12px]" v-if="data.id !== 1">
 | 
					                        <span class="more mr-[12px]" v-if="data.id !== 1">
 | 
				
			||||||
                            <icon name="el-icon-MoreFilled" :size="16" color="999" />
 | 
					                            <icon name="el-icon-MoreFilled" :size="16" color="999" />
 | 
				
			||||||
                        </span>
 | 
					                        </span>
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@
 | 
				
			||||||
                            <el-dropdown-menu>
 | 
					                            <el-dropdown-menu>
 | 
				
			||||||
                                <el-dropdown-item command="editOrganization">编辑组织信息</el-dropdown-item>
 | 
					                                <el-dropdown-item command="editOrganization">编辑组织信息</el-dropdown-item>
 | 
				
			||||||
                                <el-dropdown-item command="deleteOrganization">删除组织</el-dropdown-item>
 | 
					                                <el-dropdown-item command="deleteOrganization">删除组织</el-dropdown-item>
 | 
				
			||||||
                                <el-dropdown-item command="setGroupLeader">设置组长</el-dropdown-item>
 | 
					                                <el-dropdown-item command="setGroupLeader" v-if="!data?.children">设置组长</el-dropdown-item>
 | 
				
			||||||
                            </el-dropdown-menu>
 | 
					                            </el-dropdown-menu>
 | 
				
			||||||
                        </template>
 | 
					                        </template>
 | 
				
			||||||
                    </el-dropdown>
 | 
					                    </el-dropdown>
 | 
				
			||||||
| 
						 | 
					@ -60,6 +60,7 @@ const props = defineProps({
 | 
				
			||||||
        type: [String, Number]
 | 
					        type: [String, Number]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					const emit = defineEmits(['setGroupLeader'])
 | 
				
			||||||
const defaultProps = {
 | 
					const defaultProps = {
 | 
				
			||||||
    children: 'children',
 | 
					    children: 'children',
 | 
				
			||||||
    label: 'label',
 | 
					    label: 'label',
 | 
				
			||||||
| 
						 | 
					@ -80,15 +81,19 @@ watch(filterText, val => {
 | 
				
			||||||
const handleNodeClick = (data: Tree) => {
 | 
					const handleNodeClick = (data: Tree) => {
 | 
				
			||||||
    parent?.setSelectedNode(data)
 | 
					    parent?.setSelectedNode(data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					// 默认设置选中节点
 | 
				
			||||||
watch(
 | 
					watch(
 | 
				
			||||||
    () => props.currentNodeKey,
 | 
					    () => props.currentNodeKey,
 | 
				
			||||||
    val => {
 | 
					    val => {
 | 
				
			||||||
        if (val) {
 | 
					        if (val) {
 | 
				
			||||||
            treeRef.value?.setCurrentKey(val)
 | 
					            nextTick(() => {
 | 
				
			||||||
 | 
					                treeRef.value?.setCurrentKey(val)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
const handleCommand = (command: string) => {
 | 
					const handleCommand = (args: any[], data: Tree) => {
 | 
				
			||||||
 | 
					    const command = args[0]
 | 
				
			||||||
    switch (command) {
 | 
					    switch (command) {
 | 
				
			||||||
        case 'editOrganization':
 | 
					        case 'editOrganization':
 | 
				
			||||||
            parent?.fetchOrganizationList()
 | 
					            parent?.fetchOrganizationList()
 | 
				
			||||||
| 
						 | 
					@ -97,6 +102,7 @@ const handleCommand = (command: string) => {
 | 
				
			||||||
            parent?.fetchOrganizationList()
 | 
					            parent?.fetchOrganizationList()
 | 
				
			||||||
            break
 | 
					            break
 | 
				
			||||||
        case 'setGroupLeader':
 | 
					        case 'setGroupLeader':
 | 
				
			||||||
 | 
					            emit('setGroupLeader', data)
 | 
				
			||||||
            break
 | 
					            break
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,9 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div class="flex flex-col h-full">
 | 
					    <div class="flex flex-col h-full">
 | 
				
			||||||
        <account-number />
 | 
					        <account-number />
 | 
				
			||||||
        <div class="flex flex-1 bg-white">
 | 
					        <div class="flex flex-1 bg-white overflow-x-auto">
 | 
				
			||||||
            <organization @set-selected-node="setSelectedNode" :curSelectedNode="selectedNode" />
 | 
					            <organization @set-selected-node="setSelectedNode" :curSelectedNode="selectedNode" @fetch-table-list="fetchTableList" />
 | 
				
			||||||
            <account-list :curOrganization="selectedNode" />
 | 
					            <account-list ref="accountListRef" :curOrganization="selectedNode" />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -18,5 +18,17 @@ const selectedNode = ref()
 | 
				
			||||||
const setSelectedNode = (data: Tree) => {
 | 
					const setSelectedNode = (data: Tree) => {
 | 
				
			||||||
    selectedNode.value = data
 | 
					    selectedNode.value = data
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
					    () => selectedNode.value,
 | 
				
			||||||
 | 
					    val => {
 | 
				
			||||||
 | 
					        if (val) {
 | 
				
			||||||
 | 
					            fetchTableList()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					const accountListRef = ref<InstanceType<typeof accountList>>()
 | 
				
			||||||
 | 
					const fetchTableList = () => {
 | 
				
			||||||
 | 
					    accountListRef.value?.fetchTableList()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
<style scoped></style>
 | 
					<style scoped></style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,162 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div class="flex flex-col flex-1">
 | 
					    <div class="flex flex-col flex-1">
 | 
				
			||||||
        <div class="h-[50px] flex items-center border-b-solid-light2 px-[20px] text-[20px] font-bold">{{ curOrganization.label }}</div>
 | 
					        <div class="h-[50px] flex items-center border-b-solid-light2 px-[20px] text-[20px] font-bold">
 | 
				
			||||||
 | 
					            {{ curOrganization.label }}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="px-[20px] py-[16px] flex justify-between">
 | 
				
			||||||
 | 
					            <el-space>
 | 
				
			||||||
 | 
					                <el-button type="primary" :icon="Plus" @click="showAccountDialog">新建账号</el-button>
 | 
				
			||||||
 | 
					                <el-button type="danger" plain :icon="Delete" :disabled="isDisabled" @click="handleBatchDelete">批量删除</el-button>
 | 
				
			||||||
 | 
					            </el-space>
 | 
				
			||||||
 | 
					            <el-space>
 | 
				
			||||||
 | 
					                <el-input :placeholder="`请输入${placeholder}`">
 | 
				
			||||||
 | 
					                    <template #prepend>
 | 
				
			||||||
 | 
					                        <el-select v-model="selectKey" :placeholder="placeholder" class="w-[100px]">
 | 
				
			||||||
 | 
					                            <el-option v-for="option in searchOptions" :key="option.field" :label="option.label" :value="option.field" />
 | 
				
			||||||
 | 
					                        </el-select>
 | 
				
			||||||
 | 
					                    </template>
 | 
				
			||||||
 | 
					                </el-input>
 | 
				
			||||||
 | 
					                <el-select placeholder="请选择账号状态">
 | 
				
			||||||
 | 
					                    <el-option label="Restaurant" value="1" />
 | 
				
			||||||
 | 
					                </el-select>
 | 
				
			||||||
 | 
					            </el-space>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <ProTable ref="proTableRef" :columns="columns" :tableData="tableData" :loading="loading" :maxHeight="530">
 | 
				
			||||||
 | 
					            <template #accountName="{ row }">
 | 
				
			||||||
 | 
					                <el-space>
 | 
				
			||||||
 | 
					                    <div class="w-[50px] h-[50px] bg-primary rounded-[6px] text-white flex-row-center-center">{{ row.accountName }}</div>
 | 
				
			||||||
 | 
					                    <span>{{ row.accountName }}</span>
 | 
				
			||||||
 | 
					                    <span
 | 
				
			||||||
 | 
					                        v-if="isGroupLeader(row.groupLeader)"
 | 
				
			||||||
 | 
					                        class="px-[6px] text-green border border-solid border-green rounded-[4px] text-center text-xs"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                        组长
 | 
				
			||||||
 | 
					                    </span>
 | 
				
			||||||
 | 
					                </el-space>
 | 
				
			||||||
 | 
					            </template>
 | 
				
			||||||
 | 
					            <template #accountStatus="{ row }">
 | 
				
			||||||
 | 
					                <el-switch v-model="row.accountStatus" :active-value="1" :inactive-value="0" :before-change="() => handleStatusChange(row)" />
 | 
				
			||||||
 | 
					            </template>
 | 
				
			||||||
 | 
					            <template #operation="{ row }">
 | 
				
			||||||
 | 
					                <el-button link type="primary">详情</el-button>
 | 
				
			||||||
 | 
					                <el-button link type="primary" @click="setGroupLeader(row)">{{ btnText(row.groupLeader) }}</el-button>
 | 
				
			||||||
 | 
					                <el-button link type="primary" @click="handleDelete(row)">删除</el-button>
 | 
				
			||||||
 | 
					            </template>
 | 
				
			||||||
 | 
					        </ProTable>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					    <account-dialog ref="accountDialogRef" />
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import useHandleData from '@/hooks/useHandleData'
 | 
				
			||||||
 | 
					import feedback from '@/utils/feedback'
 | 
				
			||||||
 | 
					import { Plus, Delete } from '@element-plus/icons-vue'
 | 
				
			||||||
 | 
					import accountDialog from '../components/account-list/account-dialog.vue'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineProps({
 | 
					defineProps({
 | 
				
			||||||
    curOrganization: {
 | 
					    curOrganization: {
 | 
				
			||||||
        type: Object,
 | 
					        type: Object,
 | 
				
			||||||
        default: () => ({})
 | 
					        default: () => ({})
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					const selectKey = ref('accountName')
 | 
				
			||||||
 | 
					const searchOptions = shallowRef([
 | 
				
			||||||
 | 
					    { field: 'accountName', label: '账号名称' },
 | 
				
			||||||
 | 
					    { field: 'mobile', label: '联系电话' },
 | 
				
			||||||
 | 
					    { field: 'positionName', label: '岗位名称' }
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					const placeholder = computed(() => searchOptions.value.find(item => item.field == selectKey.value)?.label)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const loading = ref(false)
 | 
				
			||||||
 | 
					const proTableRef = ref()
 | 
				
			||||||
 | 
					const tableData = ref<any[]>([])
 | 
				
			||||||
 | 
					const columns = reactive([
 | 
				
			||||||
 | 
					    { type: 'selection', fixed: 'left', width: 70, reserveSelection: true },
 | 
				
			||||||
 | 
					    { prop: 'accountName', label: '账号名称', width: 180 },
 | 
				
			||||||
 | 
					    { prop: 'mobile', label: '联系电话', width: 180 },
 | 
				
			||||||
 | 
					    { prop: 'organization', label: '所属组织', width: 180 },
 | 
				
			||||||
 | 
					    { prop: 'position', label: '岗位', width: 180 },
 | 
				
			||||||
 | 
					    { prop: 'accountStatus', label: '账号状态', width: 180 },
 | 
				
			||||||
 | 
					    { prop: 'operation', label: '操作', fixed: 'right', width: 250 }
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const isGroupLeader = computed(() => (groupLeader: number) => groupLeader == 1)
 | 
				
			||||||
 | 
					const btnText = computed(() => (groupLeader: number) => isGroupLeader.value(groupLeader) ? '取消设为组长' : '设置组长')
 | 
				
			||||||
 | 
					const fetchTableList = () => {
 | 
				
			||||||
 | 
					    loading.value = true
 | 
				
			||||||
 | 
					    setTimeout(() => {
 | 
				
			||||||
 | 
					        tableData.value = [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                id: 1,
 | 
				
			||||||
 | 
					                accountName: '张三',
 | 
				
			||||||
 | 
					                mobile: '18138952909',
 | 
				
			||||||
 | 
					                organization: '广州团队-A组',
 | 
				
			||||||
 | 
					                position: '电销老师',
 | 
				
			||||||
 | 
					                accountStatus: 1,
 | 
				
			||||||
 | 
					                groupLeader: 1
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                id: 2,
 | 
				
			||||||
 | 
					                accountName: '李四',
 | 
				
			||||||
 | 
					                mobile: '18138952909',
 | 
				
			||||||
 | 
					                organization: '广州团队-A组',
 | 
				
			||||||
 | 
					                position: '电销老师',
 | 
				
			||||||
 | 
					                accountStatus: 1,
 | 
				
			||||||
 | 
					                groupLeader: 0
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                id: 3,
 | 
				
			||||||
 | 
					                accountName: '王五',
 | 
				
			||||||
 | 
					                mobile: '18138952909',
 | 
				
			||||||
 | 
					                organization: '广州团队-A组',
 | 
				
			||||||
 | 
					                position: '招生老师',
 | 
				
			||||||
 | 
					                accountStatus: 0,
 | 
				
			||||||
 | 
					                groupLeader: 0
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        loading.value = false
 | 
				
			||||||
 | 
					    }, 500)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const handleStatusChange = row => {
 | 
				
			||||||
 | 
					    console.log(row)
 | 
				
			||||||
 | 
					    return new Promise(resolve => {
 | 
				
			||||||
 | 
					        resolve(true)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const setGroupLeader = async row => {
 | 
				
			||||||
 | 
					    const { accountName, id, groupLeader } = row
 | 
				
			||||||
 | 
					    const message = isGroupLeader.value(groupLeader) ? `确定要取消【${accountName}】的组长身份吗?` : `确定将【${accountName}】设置为组长?`
 | 
				
			||||||
 | 
					    const flag = await useHandleData(message)
 | 
				
			||||||
 | 
					    if (!flag) return
 | 
				
			||||||
 | 
					    feedback.msgSuccess('设置成功')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const isDisabled = computed(() => proTableRef?.value?.selectedListIds?.length == 0)
 | 
				
			||||||
 | 
					const handleBatchDelete = () => {
 | 
				
			||||||
 | 
					    deleteCommon()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const handleDelete = async row => {
 | 
				
			||||||
 | 
					    deleteCommon(row)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const deleteCommon = async (row?: any) => {
 | 
				
			||||||
 | 
					    if (row) proTableRef.value.tableRef.toggleRowSelection(row, true)
 | 
				
			||||||
 | 
					    const ids = proTableRef.value.selectedListIds
 | 
				
			||||||
 | 
					    const message = '是否要删除选中的员工?'
 | 
				
			||||||
 | 
					    const flag = await useHandleData(message)
 | 
				
			||||||
 | 
					    if (flag) {
 | 
				
			||||||
 | 
					        console.log(ids)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    proTableRef.value.tableRef.clearSelection()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					defineExpose({
 | 
				
			||||||
 | 
					    fetchTableList
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					const accountDialogRef = ref<InstanceType<typeof accountDialog>>()
 | 
				
			||||||
 | 
					const showAccountDialog = () => {
 | 
				
			||||||
 | 
					    accountDialogRef.value?.openDialog({
 | 
				
			||||||
 | 
					        title: '新建账号',
 | 
				
			||||||
 | 
					        width: 400,
 | 
				
			||||||
 | 
					        data: {}
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
<style scoped></style>
 | 
					<style scoped></style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,15 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div class="flex flex-col w-[240px] border-r-solid-light2">
 | 
					    <div class="flex flex-col w-[240px] border-r-solid-light2">
 | 
				
			||||||
        <structure />
 | 
					        <structure />
 | 
				
			||||||
        <organization-tree :data="data" :loading="loading" :currentNodeKey="curSelectedNode?.id" />
 | 
					        <organization-tree :data="data" :loading="loading" :currentNodeKey="curSelectedNode?.id" @set-group-leader="setGroupLeader" />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					    <group-leader-dialog ref="groupLeaderDialogRef" @refresh-list="$emit('fetchTableList')" />
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import structure from '../components/organization/structure.vue'
 | 
					import structure from '../components/organization/structure.vue'
 | 
				
			||||||
import organizationTree, { type Tree } from '../components/organization/organization-tree.vue'
 | 
					import organizationTree, { type Tree } from '../components/organization/organization-tree.vue'
 | 
				
			||||||
 | 
					import groupLeaderDialog from '../components/organization/groupLeader-dialog.vue'
 | 
				
			||||||
import { ORGANIZATION_INJECTION_KEY } from '@/config/symbol'
 | 
					import { ORGANIZATION_INJECTION_KEY } from '@/config/symbol'
 | 
				
			||||||
import type { PropType } from 'vue'
 | 
					import type { PropType } from 'vue'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +19,7 @@ defineProps({
 | 
				
			||||||
        default: () => ({})
 | 
					        default: () => ({})
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
const emit = defineEmits(['setSelectedNode'])
 | 
					const emit = defineEmits(['setSelectedNode', 'fetchTableList'])
 | 
				
			||||||
const data = ref<Tree[]>([])
 | 
					const data = ref<Tree[]>([])
 | 
				
			||||||
const loading = ref(false)
 | 
					const loading = ref(false)
 | 
				
			||||||
const setSelectedNode = (data: Tree) => {
 | 
					const setSelectedNode = (data: Tree) => {
 | 
				
			||||||
| 
						 | 
					@ -72,6 +74,14 @@ provide(ORGANIZATION_INJECTION_KEY, {
 | 
				
			||||||
    setSelectedNode
 | 
					    setSelectedNode
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
fetchOrganizationList()
 | 
					fetchOrganizationList()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const groupLeaderDialogRef = ref<InstanceType<typeof groupLeaderDialog>>()
 | 
				
			||||||
 | 
					const setGroupLeader = (data: Tree) => {
 | 
				
			||||||
 | 
					    groupLeaderDialogRef.value?.openDialog({
 | 
				
			||||||
 | 
					        title: '设置组长',
 | 
				
			||||||
 | 
					        data
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style scoped lang="scss"></style>
 | 
					<style scoped lang="scss"></style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,8 @@ module.exports = {
 | 
				
			||||||
            fill: 'var(--el-fill-color)',
 | 
					            fill: 'var(--el-fill-color)',
 | 
				
			||||||
            'fill-light': 'var(--el-fill-color-light)',
 | 
					            'fill-light': 'var(--el-fill-color-light)',
 | 
				
			||||||
            'fill-lighter': 'var(--el-fill-color-lighter)',
 | 
					            'fill-lighter': 'var(--el-fill-color-lighter)',
 | 
				
			||||||
            mask: 'var(--el-mask-color)'
 | 
					            mask: 'var(--el-mask-color)',
 | 
				
			||||||
 | 
					            green: 'var(--color-green)'
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        fontFamily: {
 | 
					        fontFamily: {
 | 
				
			||||||
            sans: ['PingFang SC', 'Arial', 'Hiragino Sans GB', 'Microsoft YaHei', 'sans-serif']
 | 
					            sans: ['PingFang SC', 'Arial', 'Hiragino Sans GB', 'Microsoft YaHei', 'sans-serif']
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue