【招生用户端】 新增# 子账号管理:1、对接编辑、删除接口;2、组织状态设为停用时不可新增账号

main
kaeery 2025-02-27 00:27:52 +08:00
parent ebbe48d31c
commit 314c71a520
5 changed files with 108 additions and 30 deletions

View File

@ -16,3 +16,11 @@ export function subAccountList(params: Record<string, any>) {
export function subAccountNumber() {
return request.get({ url: '/user/validUserCount' })
}
// 子账号详情
export function subAccountDetail(params: Record<string, any>) {
return request.get({ url: '/user/detail', params })
}
// 删除子账号
export function subAccountDelete(params: Record<string, any>) {
return request.post({ url: '/user/sonDel', params })
}

View File

@ -66,9 +66,9 @@
<script setup lang="ts">
import { organzationLists } from '@/api/account_center/organization'
import { postLists } from '@/api/account_center/postion'
import { subAccountAdd } from '@/api/account_center/sub_account'
import { subAccountAdd, subAccountDetail, subAccountEdit } from '@/api/account_center/sub_account'
import ProDialog, { type IParams } from '@/components/ProDialog/index.vue'
import { DataFlowEnum } from '@/enums'
import { DataFlowEnum, StatusEnum } from '@/enums'
import { validateContact } from '@/utils/validate'
import type { FormInstance, FormRules } from 'element-plus'
@ -83,7 +83,7 @@ export interface IAccount {
}
const proDialogRef = ref<InstanceType<typeof ProDialog>>()
const emit = defineEmits(['fetchTableList'])
const emit = defineEmits(['confirmAfter'])
const data = ref([])
const defaultProps = {
label: 'name', //
@ -102,6 +102,7 @@ const accountStatusOptions = ref([
])
const channelTooltips = ['选择默认组织则数据流向到所属组织下的所有招生老师;', '选择组织指定则可选择将数据流向到所属组织下的指定招生老师;']
const form = ref({
id: '',
organizationId: '',
username: '',
mobile: '',
@ -110,17 +111,23 @@ const form = ref({
status: 1,
teacher: ''
})
const fetchPostionData = async () => {
const fetchPostionData = async (callback?: (params: []) => void) => {
try {
const result = await postLists()
positionOptions.value = result.lists
callback && callback(result.lists)
} catch (error) {}
}
const fetchOrganizationData = async () => {
const fetchOrganizationData = async (organizationId: number) => {
try {
const result = await organzationLists()
setDsiabled(result)
data.value = result
const targetNode = findNodeById(data.value, organizationId)
if (targetNode) {
const { id, disabled } = targetNode
form.value.organizationId = !disabled ? id : ''
}
} catch (error) {}
}
//
@ -128,15 +135,48 @@ const setDsiabled = (nodes: any[]) => {
nodes.forEach(node => {
const ancestorArray = node.ancestors ? node.ancestors.split(',') : []
const level = ancestorArray.length - 1
node.disabled = level < 2
node.disabled = level < 2 || node.status == StatusEnum.Stop
if (node.children && node.children.length > 0) {
setDsiabled(node.children)
}
})
}
const openDialog = (params: IParams) => {
const fetchDetail = async (data: any) => {
const { id } = data
try {
const result = await subAccountDetail({ id })
setFormData(result)
} catch (error) {}
}
const setFormData = result => {
for (const key in result) {
if (Object.prototype.hasOwnProperty.call(form.value, key)) {
form.value[key] = result[key]
}
if (key == 'postIds') {
form.value.postIds = result[key].split(',').map((item: string) => Number(item))
}
}
}
// id
const findNodeById = (nodes: any[], id: number): any | undefined => {
for (const node of nodes) {
if (node.id === id) {
return node
}
if (node.children && node.children.length > 0) {
const foundNode = findNodeById(node.children, id)
if (foundNode) {
return foundNode
}
}
}
return undefined
}
const openDialog = async (params: IParams) => {
fetchPostionData()
fetchOrganizationData()
fetchOrganizationData(params.data.organizationId)
if (params.data.id) fetchDetail(params.data)
proDialogRef.value?.openDialog(params)
}
const handleCancel = (callback: () => void) => {
@ -161,9 +201,10 @@ const handleConfirm = (callback: () => void) => {
...form.value,
postIds: form.value.postIds.join(',')
}
await subAccountAdd(data)
const api = form.value.id ? subAccountEdit : subAccountAdd
await api(data)
callback()
emit('fetchTableList')
emit('confirmAfter')
resetForm()
} catch (error) {}
})
@ -172,7 +213,8 @@ const resetForm = () => {
formRef.value?.resetFields()
}
defineExpose({
openDialog
openDialog,
fetchPostionData
})
</script>

View File

@ -3,7 +3,7 @@
<account-number :accoutnInfo="accoutnInfo" />
<div class="flex flex-1 bg-white overflow-x-auto">
<organization @set-selected-node="setSelectedNode" :curSelectedNode="selectedNode" @fetch-table-list="fetchTableList" />
<account-list ref="accountListRef" :curOrganization="selectedNode" />
<account-list ref="accountListRef" :curOrganization="selectedNode" @refresh-sub-account-number="fetchSubAccountNumber" />
</div>
</div>
</template>
@ -14,6 +14,8 @@ import organization from './modules/organization.vue'
import accountList from './modules/account-list.vue'
import type { Tree } from './components/organization/organization-tree.vue'
import { subAccountNumber } from '@/api/account_center/sub_account'
import { StatusEnum } from '@/enums'
import feedback from '@/utils/feedback'
const selectedNode = ref()
const setSelectedNode = (data: Tree) => {
@ -23,6 +25,7 @@ watch(
() => selectedNode.value,
val => {
if (val) {
if (val.status == StatusEnum.Stop) feedback.msgError('当前组织状态为停用,请先启用')
fetchTableList()
}
}

View File

@ -5,7 +5,7 @@
</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="primary" :icon="Plus" :disabled="isDisabledAdd" @click="showAccountDialog"></el-button>
<el-button type="danger" plain :icon="Delete" :disabled="isDisabled" @click="handleBatchDelete"></el-button>
</el-space>
<el-space>
@ -16,7 +16,10 @@
</el-select>
</template>
</el-input>
<el-select placeholder="请选择账号状态" v-model="searchForm.accountStatus" clearable @change="handleSelectChange">
<el-select placeholder="请选择岗位名称" v-model="searchForm.postId" clearable @change="handleSelectChange">
<el-option v-for="option in positionOptions" :key="option.id" :label="option.name" :value="option.id" />
</el-select>
<el-select placeholder="请选择账号状态" v-model="searchForm.status" clearable @change="handleSelectChange">
<el-option v-for="option in accountStatusOptions" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</el-space>
@ -44,7 +47,7 @@
</template>
</ProTable>
</div>
<account-dialog ref="accountDialogRef" @fetch-table-list="fetchTableList" />
<account-dialog ref="accountDialogRef" @confirm-after="confirmAfter" />
</template>
<script setup lang="ts">
@ -53,7 +56,8 @@ import feedback from '@/utils/feedback'
import { Plus, Delete } from '@element-plus/icons-vue'
import accountDialog from '../components/account-list/account-dialog.vue'
import { useDebounceFn } from '@vueuse/core'
import { subAccountList } from '@/api/account_center/sub_account'
import { subAccountDelete, subAccountList } from '@/api/account_center/sub_account'
import { StatusEnum } from '@/enums'
const props = defineProps({
curOrganization: {
@ -61,16 +65,17 @@ const props = defineProps({
default: () => ({})
}
})
const selectKey = ref('accountName')
const emit = defineEmits(['refreshSubAccountNumber'])
const selectKey = ref('username')
const searchOptions = shallowRef([
{ field: 'accountName', label: '账号名称' },
{ field: 'mobile', label: '联系电话' },
{ field: 'positionName', label: '岗位名称' }
{ field: 'username', label: '账号名称' },
{ field: 'mobile', label: '联系电话' }
])
const placeholder = computed(() => searchOptions.value.find(item => item.field == selectKey.value)?.label)
const accountStatusOptions = ref([
{ label: '启用', value: 1 },
{ label: '停用', value: 2 }
{ label: '启用', value: StatusEnum.Normal },
{ label: '停用', value: StatusEnum.Stop }
])
const loading = ref(false)
const proTableRef = ref()
@ -87,6 +92,7 @@ const columns = reactive([
const isGroupLeader = computed(() => (groupLeader: number) => groupLeader == 1)
const btnText = computed(() => (groupLeader: number) => isGroupLeader.value(groupLeader) ? '取消设为组长' : '设置组长')
const isDisabledAdd = computed(() => props.curOrganization.status == StatusEnum.Stop)
const fetchTableList = async (nodeId?: number) => {
loading.value = true
try {
@ -121,13 +127,22 @@ const handleDelete = async row => {
const deleteCommon = async (row?: any) => {
if (row) proTableRef.value.tableRef.toggleRowSelection(row, true)
const ids = proTableRef.value.selectedListIds
const message = '是否要删除选中的员工?'
const message = '是否要删除选中的账号?'
const flag = await useHandleData(message)
if (flag) {
console.log(ids)
try {
await subAccountDelete({ ids })
feedback.msgSuccess('删除成功')
fetchTableList()
emit('refreshSubAccountNumber')
} catch (error) {}
}
proTableRef.value.tableRef.clearSelection()
}
const confirmAfter = () => {
fetchTableList()
emit('refreshSubAccountNumber')
}
const handleEdit = row => {
showAccountDialog(row)
}
@ -139,24 +154,34 @@ const showAccountDialog = (row?: any) => {
accountDialogRef.value?.openDialog({
title: row?.id ? '编辑账号' : '新建账号',
width: 400,
data: {}
data: {
id: row?.id ?? '',
organizationId: props.curOrganization.id
}
})
}
const searchForm = ref({
keyword: '',
accountStatus: ''
postId: '',
status: ''
})
const handleInputChange = useDebounceFn(() => {
const formMap: Record<string, string> = {
accountName: '',
mobile: '',
position: ''
username: '',
mobile: ''
}
formMap[selectKey.value] = searchForm.value.keyword
}, 500)
const handleSelectChange = () => {
console.log('handleSelectChange')
}
const positionOptions = ref<any[]>([])
onMounted(() => {
accountDialogRef.value?.fetchPostionData(lists => {
positionOptions.value = lists ?? []
})
})
watch(
() => selectKey.value,
(newVal, oldVal) => {

View File

@ -23,6 +23,6 @@ const props = defineProps({
default: () => ({})
}
})
const parseUnuseNumber = computed(() => props.accoutnInfo.quota - props.accoutnInfo.quantity)
const parseUnuseNumber = computed(() => props.accoutnInfo?.quota - props.accoutnInfo?.quantity)
</script>
<style scoped></style>