【账号中心】 新增# 子账号管理
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) {
|
||||||
|
nextTick(() => {
|
||||||
treeRef.value?.setCurrentKey(val)
|
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>
|
||||||
|
<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>
|
||||||
|
<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