@@ -23,8 +23,8 @@ const http = moduleRequest("/business/dfieldApi/"); | |||
*/ | |||
const userManageClassManageApi = { | |||
/** 查询底库列表 */ | |||
page() { | |||
return http.get("queryAll"); | |||
page(params: SysUserPersonnel.ClassPage) { | |||
return http.get("queryAll", params); | |||
}, | |||
/** 删除底库 */ | |||
delete(params: ReqId) { | |||
@@ -0,0 +1,21 @@ | |||
import { userManageClassManageApi, userManageMajorApi, userManageDepartmentApi } from "@/api"; | |||
// 获取专业列表 | |||
const getMajorList = async (depId: any) => { | |||
const res: any = await userManageMajorApi.list({ depId }); | |||
return res.data; | |||
}; | |||
/* 获取系部 */ | |||
const getDepartmentList = async () => { | |||
const res: any = await userManageDepartmentApi.list({}); | |||
return res.data; | |||
}; | |||
/* 获取所属班级 */ | |||
const getClassList = async (majorId: any) => { | |||
const res: any = await userManageClassManageApi.page({ majorId }); | |||
return res.data; | |||
}; | |||
export { getMajorList, getDepartmentList, getClassList }; |
@@ -5,7 +5,7 @@ | |||
--> | |||
<template> | |||
<div class="main-box"> | |||
<TreeFilter | |||
<!-- <TreeFilter | |||
ref="treeFilter" | |||
label="personSetName" | |||
id="personSetId" | |||
@@ -22,7 +22,7 @@ | |||
<span>{{ row.node.label }}</span> | |||
</span> | |||
</template> | |||
</TreeFilter> | |||
</TreeFilter> --> | |||
<div class="table-box"> | |||
<ProTable ref="proTable" title="人员管理" :columns="columns" rowKey="personId" :request-api="userManagePersonnelApi.page"> | |||
<!-- 表格操作栏 --> | |||
@@ -44,19 +44,84 @@ | |||
</div> | |||
</template> | |||
<script setup lang="tsx" name="SysUserPersonnel"> | |||
import { userManagePersonnelApi,SysUserPersonnel,userManageClassManageApi,userManageTeacherApi } from "@/api"; | |||
import { userManagePersonnelApi,SysUserPersonnel } from "@/api"; | |||
import { getMajorList, getDepartmentList, getClassList } from "@/mixin"; | |||
import { FormOptEnum } from "@/enums"; | |||
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | |||
import TreeFilter from "@/components/TreeFilter/index.vue"; | |||
import { useUserStore } from "@/stores/modules"; | |||
import TraceShow from "./components/traceShow/index.vue"; | |||
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | |||
const faceUrl = ref(''); | |||
const visible = ref(false); //预览头像 | |||
const proTable = ref<ProTableInstance>(); | |||
const treeFilter = ref<InstanceType<typeof TreeFilter> | null>(null); | |||
const departmentOptions = ref<any>([]) | |||
const majorOptions = ref<any>([]) | |||
const classOptions = ref<any>([]) | |||
//监听depId/majorId变化 | |||
watch( | |||
() => [proTable.value!?.searchParam?.depId,proTable.value!?.searchParam?.majorId], | |||
async ([newDepId,newMajorId],[oldDepId,oldMajorId]) => { | |||
if(newDepId !== oldDepId){ | |||
majorOptions.value =await getMajorList(newDepId) | |||
classOptions.value = []; | |||
proTable.value!.searchParam.majorId = ""; | |||
proTable.value!.searchParam.personSetId = "" | |||
} | |||
if(newMajorId !== oldMajorId){ | |||
classOptions.value = await getClassList(newMajorId) | |||
} | |||
} ,{ deep: true, immediate: false } | |||
); | |||
// 表格配置项 | |||
const columns: ColumnProps<SysUserPersonnel.SysUserPerInfo>[] = [ | |||
{ | |||
prop: "depId", | |||
label: "所属系部", | |||
enum: departmentOptions, | |||
fieldNames: { label: "name", value: "id" }, | |||
search: { | |||
el: "select", | |||
span:1, | |||
props: { | |||
clearable: false, | |||
placeholder: "请选择系部", | |||
}, | |||
}, | |||
isShow: false | |||
}, | |||
{ | |||
prop: "majorId", | |||
label: "所属专业", | |||
enum: majorOptions, | |||
fieldNames: { label: "name", value: "id" }, | |||
search: { | |||
el: "select", | |||
span:1, | |||
props: { | |||
clearable: false, | |||
placeholder: "请选择专业", | |||
}, | |||
}, | |||
isShow: false | |||
}, | |||
{ | |||
prop: "personSetId", | |||
label: "所属班级", | |||
enum: classOptions, | |||
fieldNames: { label: "personSetName", value: "personSetId" }, | |||
search: { | |||
el: "select", | |||
span:1, | |||
props: { | |||
clearable: false, | |||
placeholder: "请选择所属班级", | |||
}, | |||
}, | |||
isShow: false | |||
}, | |||
{ | |||
prop: "faceUrl", | |||
label: "人脸", | |||
@@ -99,26 +164,30 @@ const RefreshTable = () => { | |||
} | |||
/** 部门切换 */ | |||
const personSetId = ref<number | string>() | |||
function changeTreeFilter(val: number | string) { | |||
personSetId.value = val | |||
proTable.value!.pageable.pageNum = 1; | |||
proTable.value!.searchParam.personSetId = val; | |||
proTable.value!.search(); | |||
} | |||
// const personSetId = ref<number | string>() | |||
// function changeTreeFilter(val: number | string) { | |||
// personSetId.value = val | |||
// proTable.value!.pageable.pageNum = 1; | |||
// proTable.value!.searchParam.personSetId = val; | |||
// proTable.value!.search(); | |||
// } | |||
const detialRef = ref<InstanceType<typeof TraceShow> | null>(null); | |||
/** | |||
* 详情 | |||
* @param opt 操作类型 | |||
* @param record 弹框数据 | |||
*/ | |||
function onOpenDetail(opt: FormOptEnum, record: {} | AttendanceStudentsReturn.studentsReturnInfo = {}) { | |||
function onOpenDetail(opt: FormOptEnum, record: {}) { | |||
switch (opt) { | |||
case FormOptEnum.VIEW: | |||
detialRef.value?.onOpen({ opt: opt, record: record, successful: RefreshTable }); | |||
break; | |||
} | |||
} | |||
onMounted(async () => { | |||
// 获取系部下拉数据 | |||
departmentOptions.value = await getDepartmentList() | |||
}); | |||
</script> | |||
<style scoped lang="scss"> | |||
.table-box { | |||
@@ -32,15 +32,22 @@ | |||
</s-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="16"> | |||
<el-col :span="12"> | |||
<s-form-item label="所属系部" prop="depId"> | |||
<s-select v-model="sysUserProps.record.depId" :options="departmentOptions" label="name" value="id"></s-select | |||
></s-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<s-form-item label="所属专业" prop="majorId"> | |||
<s-select v-model="sysUserProps.record.majorId" :options="majorOptions" label="name" value="id"></s-select> | |||
</s-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="16"> | |||
<el-col :span="12"> | |||
<s-form-item label="所属班级" prop="personSetId"> | |||
<s-select | |||
v-model="sysUserProps.record.personSetId" | |||
:options="sysUserProps.treeAllData" | |||
label="personSetName" | |||
value="personSetId" | |||
></s-select> | |||
<s-select v-model="sysUserProps.record.personSetId" :options="classOptions" label="personSetName" value="personSetId"></s-select> | |||
</s-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
@@ -67,10 +74,15 @@ | |||
</template> | |||
<script setup lang="ts" name="SysUserPersonnelForm"> | |||
import { attendanceRoolcallApi, userManagePersonnelApi, monitorLIVEApi } from "@/api"; | |||
import { attendanceRoolcallApi, monitorLIVEApi } from "@/api"; | |||
import { required } from "@/utils/formRules"; | |||
import { FormInstance } from "element-plus"; | |||
import { getMajorList, getDepartmentList, getClassList } from "@/mixin"; | |||
const visible = ref(false); //是否显示表单 | |||
const CameraList = ref<any>([]); | |||
const departmentOptions = ref<any>([]); | |||
const majorOptions = ref<any>([]); | |||
const classOptions = ref<any>([]); | |||
/** 表单操作类型枚举 */ | |||
enum FormOptEnums { | |||
/** 发起 */ | |||
@@ -80,10 +92,8 @@ enum FormOptEnums { | |||
const sysUserProps = reactive<FormProps.Base<any>>({ | |||
opt: FormOptEnums.INITIATE, | |||
record: {}, | |||
treeAllData: [], | |||
disabled: false | |||
}); | |||
const CameraList = ref<any>([]); | |||
// 表单验证规则 | |||
const rules = reactive({ | |||
@@ -91,26 +101,35 @@ const rules = reactive({ | |||
similarity: [required("请选择相似度")], | |||
cameraId: [required("请选择摄像头")], | |||
continueTime: [required("请选择持续时间")], | |||
personSetId: [required("请选择所属班级")] | |||
personSetId: [required("请选择所属班级")], | |||
depId: [required("请选择系部")], | |||
majorId: [required("请选择专业")] | |||
}); | |||
/** | |||
* 打开表单 | |||
* @param props 表单参数 | |||
*/ | |||
function onOpen(props: FormProps.Base<any>) { | |||
async function onOpen(props: FormProps.Base<any>) { | |||
departmentOptions.value = await getDepartmentList(); | |||
Object.assign(sysUserProps, props); //合并参数 | |||
if (props.opt == FormOptEnums.INITIATE) { | |||
//如果是新增,设置默认值 | |||
// sysUserProps.record.sortCode = 99; | |||
} | |||
visible.value = true; //显示表单 | |||
if (props.record.personId) { | |||
//如果传了id,就去请求api获取record | |||
userManagePersonnelApi.detail({ id: props.record.personId }).then((res: any) => { | |||
sysUserProps.record = res.data; | |||
}); | |||
} | |||
/* 监听系部、专业 */ | |||
watch( | |||
() => [sysUserProps.record?.depId, sysUserProps.record?.majorId], | |||
async ([newDepId, newMajorId], [oldDepId, oldMajorId]) => { | |||
if (newDepId != oldDepId) { | |||
majorOptions.value = await getMajorList(newDepId); | |||
classOptions.value = []; | |||
sysUserProps.record.personSetId = ""; | |||
sysUserProps.record.majorId = ""; | |||
} | |||
if (newMajorId && newMajorId != oldMajorId) { | |||
classOptions.value = await getClassList(newMajorId); | |||
} | |||
}, | |||
{ deep: true, immediate: false } | |||
); | |||
} | |||
const handleChange = async (val: any, data: any) => { | |||
@@ -5,27 +5,11 @@ | |||
--> | |||
<template> | |||
<div class="main-box"> | |||
<TreeFilter | |||
ref="treeFilter" | |||
label="personSetName" | |||
id="personSetId" | |||
width="300px" | |||
title="班级管理" | |||
:show-all="true" | |||
:request-api="userManageClassManageApi.page" | |||
@change="changeTreeFilter" | |||
> | |||
<template v-slot:label="{ row }"> | |||
<span class="custom-tree-node"> | |||
<span>{{ row.node.label }} {{ row.node.userName ? `(${row.node.userName})` : "" }}</span> | |||
</span> | |||
</template> | |||
</TreeFilter> | |||
<div class="table-box"> | |||
<ProTable ref="proTable" title="任务列表" :columns="columns" rowKey="id" :request-api="attendanceRoolcallApi.getTaskPageList"> | |||
<!-- 表格 header 按钮 --> | |||
<template #tableHeader="scope"> | |||
<s-button :opt="FormOptEnums.INITIATE" @click="onOpen(FormOptEnums.INITIATE, { personSetId: personSetId }, treeFilter.treeAllData)" /> | |||
<s-button :opt="FormOptEnums.INITIATE" @click="onOpen(FormOptEnums.INITIATE, {})" /> | |||
<s-button | |||
type="danger" | |||
:opt="FormOptEnum.DELETE" | |||
@@ -49,15 +33,36 @@ | |||
</div> | |||
</template> | |||
<script setup lang="tsx" name="SysUserPersonnel"> | |||
import { attendanceRoolcallApi,userManageClassManageApi} from "@/api"; | |||
import { attendanceRoolcallApi} from "@/api"; | |||
import { getMajorList, getDepartmentList, getClassList } from "@/mixin"; | |||
import { useHandleData } from "@/hooks/useHandleData"; | |||
import { FormOptEnum } from "@/enums"; | |||
import Form from "./components/form/index.vue"; | |||
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | |||
import TreeFilter from "@/components/TreeFilter/index.vue"; | |||
import { useRouter } from "vue-router"; | |||
const router = useRouter(); | |||
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | |||
const proTable = ref<ProTableInstance>(); | |||
const departmentOptions = ref<any>([]) | |||
const majorOptions = ref<any>([]) | |||
const classOptions = ref<any>([]) | |||
//监听depId/majorId变化 | |||
watch( | |||
() => [proTable.value!?.searchParam?.depId,proTable.value!?.searchParam?.majorId], | |||
async ([newDepId,newMajorId],[oldDepId,oldMajorId]) => { | |||
if(newDepId !== oldDepId){ | |||
majorOptions.value =await getMajorList(newDepId) | |||
classOptions.value = []; | |||
proTable.value!.searchParam.majorId = ""; | |||
proTable.value!.searchParam.personSetId = "" | |||
} | |||
if(newMajorId !== oldMajorId){ | |||
classOptions.value = await getClassList(newMajorId) | |||
} | |||
} ,{ deep: true, immediate: false } | |||
); | |||
/** 表单操作类型枚举 */ | |||
enum FormOptEnums { | |||
/** 发起 */ | |||
@@ -68,13 +73,54 @@ enum FormOptEnums { | |||
EDITTASK = "修改点名记录" | |||
} | |||
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | |||
const visible = ref(false); //是否显示人员表单 | |||
const proTable = ref<ProTableInstance>(); | |||
const treeFilter = ref<any>(); | |||
// 表格配置项 | |||
const columns: ColumnProps[] = [ | |||
{ type: "selection", fixed: "left", width: 50 }, | |||
{ | |||
prop: "depId", | |||
label: "所属系部", | |||
enum: departmentOptions, | |||
fieldNames: { label: "name", value: "id" }, | |||
search: { | |||
el: "select", | |||
span:1, | |||
props: { | |||
clearable: false, | |||
placeholder: "请选择系部", | |||
}, | |||
}, | |||
isShow: false | |||
}, | |||
{ | |||
prop: "majorId", | |||
label: "所属专业", | |||
enum: majorOptions, | |||
fieldNames: { label: "name", value: "id" }, | |||
search: { | |||
el: "select", | |||
span:1, | |||
props: { | |||
clearable: false, | |||
placeholder: "请选择专业", | |||
}, | |||
}, | |||
isShow: false | |||
}, | |||
{ | |||
prop: "personSetId", | |||
label: "所属班级", | |||
enum: classOptions, | |||
fieldNames: { label: "personSetName", value: "personSetId" }, | |||
search: { | |||
el: "select", | |||
span:1, | |||
props: { | |||
clearable: false, | |||
placeholder: "请选择所属班级", | |||
}, | |||
}, | |||
isShow: false | |||
}, | |||
{ | |||
prop: "cameraName", | |||
label: "摄像头名称" | |||
@@ -106,8 +152,8 @@ const formRef = ref<InstanceType<typeof Form> | null>(null); | |||
* @param opt 操作类型 | |||
* @param record 记录 | |||
*/ | |||
function onOpen(opt: FormOptEnums, record: {},treeAllData:any) { | |||
formRef.value?.onOpen({ opt: opt, record: record,treeAllData:treeAllData, successful: RefreshTable }); | |||
function onOpen(opt: FormOptEnums, record: {}) { | |||
formRef.value?.onOpen({ opt: opt, record: record, successful: RefreshTable }); | |||
} | |||
@@ -133,15 +179,10 @@ const formRef = ref<InstanceType<typeof Form> | null>(null); | |||
const RefreshTable = () => { | |||
proTable.value?.refresh(); | |||
} | |||
/** 班级切换 */ | |||
const personSetId = ref<number | string>() | |||
function changeTreeFilter(val: number | string) { | |||
personSetId.value = val | |||
proTable.value!.pageable.pageNum = 1; | |||
proTable.value!.searchParam.personSetId = val; | |||
proTable.value!.search(); | |||
} | |||
onMounted(async () => { | |||
// 获取系部下拉数据 | |||
departmentOptions.value = await getDepartmentList() | |||
}); | |||
</script> | |||
<style scoped lang="scss"> | |||
.table-box { | |||
@@ -18,6 +18,9 @@ | |||
<div> | |||
<el-row :gutter="16"> | |||
<el-col :span="22"> | |||
<s-form-item label="所属专业" prop="majorId"> | |||
<s-select v-model="sysUserProps.record.majorId" :options="majorIdData" label="name" value="id"></s-select> | |||
</s-form-item> | |||
<s-form-item label="班级名称" prop="personSetName"> | |||
<s-input v-model="sysUserProps.record.personSetName"></s-input> | |||
</s-form-item> | |||
@@ -35,12 +38,13 @@ | |||
<script setup lang="ts" name="SysUserPerformClass"> | |||
import { ref } from "vue"; | |||
import { SysUserPersonnel, userManageClassManageApi } from "@/api"; | |||
import { SysUserPersonnel, userManageClassManageApi, userManageMajorApi } from "@/api"; | |||
import { FormOptEnum } from "@/enums"; | |||
import { required } from "@/utils/formRules"; | |||
import { FormInstance } from "element-plus"; | |||
const visibleClass = ref(false); //是否显示表单 | |||
const majorIdData = ref<any>([]); //专业数据 | |||
// 表单参数 | |||
const sysUserProps = reactive<FormProps.Base<SysUserPersonnel.ClassPage>>({ | |||
opt: FormOptEnum.ADD, | |||
@@ -49,6 +53,7 @@ const sysUserProps = reactive<FormProps.Base<SysUserPersonnel.ClassPage>>({ | |||
}); | |||
// 表单验证规则 | |||
const rules = reactive({ | |||
majorId: [required("请选择专业")], | |||
personSetName: [required("请输入班级名称")] | |||
}); | |||
@@ -59,9 +64,17 @@ const rules = reactive({ | |||
function onOpen(props: FormProps.Base<SysUserPersonnel.ClassPage>) { | |||
Object.assign(sysUserProps, props); //合并参数 | |||
visibleClass.value = true; //显示表单 | |||
sysUserProps.record = props.record; | |||
getRequestData(() => { | |||
sysUserProps.record = props.record; | |||
}); //获取专业数据 | |||
} | |||
/* 获取专业数据 */ | |||
const getRequestData = async (callback: Function | null = null) => { | |||
const { data } = await userManageMajorApi.list({}); | |||
majorIdData.value = data; | |||
if (callback) callback; | |||
}; | |||
// 提交数据(新增/编辑) | |||
const sysUserFormRef = ref<FormInstance>(); | |||
/** 提交表单 */ |
@@ -62,15 +62,17 @@ const rules = reactive({ | |||
* @param props 表单参数 | |||
*/ | |||
function onOpen(props: FormProps.Base<SysUserPersonnel.ClassPage>) { | |||
getRequestData(); | |||
Object.assign(sysUserProps, props); //合并参数 | |||
visibleClass.value = true; //显示表单 | |||
sysUserProps.record = props.record; | |||
getRequestData(() => { | |||
Object.assign(sysUserProps, props); //合并参数 | |||
sysUserProps.record = props.record; | |||
}); | |||
} | |||
const getRequestData = async () => { | |||
const getRequestData = async (callback: Function | null = null) => { | |||
const { data } = await userManageTeacherApi.page(); | |||
teacherData.value = data; | |||
if (callback) callback(); | |||
}; | |||
// 提交数据(新增/编辑) |
@@ -0,0 +1,211 @@ | |||
<!-- | |||
* @Description: 人员管理 | |||
* @Author: syy | |||
* @Date: 2024-7-15 | |||
--> | |||
<template> | |||
<div class="main-box"> | |||
<div class="table-box"> | |||
<ProTable | |||
ref="proTable" | |||
:pagination="false" | |||
title="班级管理" | |||
:columns="columns" | |||
rowKey="personSetId" | |||
:request-api="userManageClassManageApi.page" | |||
> | |||
<!-- 表格 header 按钮 --> | |||
<template #tableHeader="scope"> | |||
<s-button suffix="班级" @click="addClass(FormOptEnum.ADD)" /> | |||
<s-button | |||
type="danger" | |||
:opt="FormOptEnum.DELETE" | |||
plain | |||
suffix="班级" | |||
:disabled="!scope.isSelected" | |||
@click="addDelete(scope.selectedListIds, '删除所选班级')" | |||
/> | |||
</template> | |||
<!-- 表格操作栏 --> | |||
<template #operation="scope"> | |||
<el-space> | |||
<s-button link :opt="FormOptEnum.EDIT" @click="addClass(FormOptEnum.EDIT, scope.row)" /> | |||
<s-button link :opt="FormOptEnum.DELETE" @click="addDelete([scope.row.personSetId], `删除班级`)" /> | |||
<el-dropdown @command="handleCommandTree"> | |||
<el-link type="primary" :underline="false" :icon="ArrowDown"> 更多 </el-link> | |||
<template #dropdown> | |||
<el-dropdown-menu> | |||
<el-dropdown-item v-if="!scope.row.userId" :command="commander(scope.row, cmdEnumTree.AddTeacher)"> | |||
{{ cmdEnumTree.AddTeacher }} | |||
</el-dropdown-item> | |||
<el-dropdown-item v-if="scope.row.userId" :command="commander(scope.row, cmdEnumTree.UpdateTeacher)"> | |||
{{ cmdEnumTree.UpdateTeacher }} | |||
</el-dropdown-item> | |||
<el-dropdown-item v-if="scope.row.userId" :command="commander(scope.row, cmdEnumTree.DeleteTeacher)"> | |||
{{ cmdEnumTree.DeleteTeacher }} | |||
</el-dropdown-item> | |||
</el-dropdown-menu> | |||
</template> | |||
</el-dropdown> | |||
</el-space> | |||
</template> | |||
</ProTable> | |||
</div> | |||
<!-- 班级新增/编辑表单 --> | |||
<FormClass ref="formRefC" /> | |||
<!-- 班主任绑定/修改 --> | |||
<FormTeacher ref="formRefT" /> | |||
</div> | |||
</template> | |||
<script setup lang="tsx" name="SysUserKeyPersonnel"> | |||
import { userManageClassManageApi,userManageTeacherApi,SysUserPersonnel,userManageMajorApi,userManageDepartmentApi } from "@/api"; | |||
import { useHandleData } from "@/hooks/useHandleData"; | |||
import { FormOptEnum } from "@/enums"; | |||
import FormClass from "./components/formClass/index.vue"; | |||
import FormTeacher from "./components/formTeacher/index.vue"; | |||
import { ArrowDown } from "@element-plus/icons-vue"; | |||
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | |||
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | |||
const proTable = ref<ProTableInstance>(); | |||
const majorOptions = ref<any>([]) | |||
// 获取专业列表 | |||
const getMajorList = async () => { | |||
const res:any = await userManageMajorApi.list({}); | |||
if (res.code === 200) { | |||
majorOptions.value = res.data; | |||
} | |||
}; | |||
/* 获取系部 */ | |||
const departmentOptions = ref<any>([]) | |||
const getDepartmentList = async () => { | |||
const res:any = await userManageDepartmentApi.list({}); | |||
if (res.code === 200) { | |||
departmentOptions.value = res.data; | |||
} | |||
}; | |||
// 表格配置项 | |||
const columns: ColumnProps<SysUserPersonnel.ClassPage>[] = [ | |||
{ type: "selection", fixed: "left", width: 50 }, | |||
{ | |||
prop: "majorId", | |||
label: "所属专业", | |||
enum: majorOptions, | |||
fieldNames: { label: "name", value: "id" }, | |||
search: { | |||
el: "select", | |||
span:1, | |||
props: { | |||
clearable: false, | |||
placeholder: "请选择专业", | |||
}, | |||
}, | |||
isShow: false | |||
}, | |||
{ | |||
prop: "personSetName", | |||
label: "班级名称", | |||
search: { el: "input",span:1, } | |||
}, | |||
{ | |||
prop: "majorName", | |||
label: "所属专业", | |||
}, | |||
{ | |||
prop: "departmentName", | |||
label: "所属系部", | |||
}, | |||
{ | |||
prop: "userName", | |||
label: "班主任" | |||
}, | |||
{ prop: "operation", label: "操作", width: 250, fixed: "right" } | |||
]; | |||
// 班级表单引用 | |||
const formRefC = ref<InstanceType<typeof FormClass> | null>(null); | |||
// 班级表单引用 | |||
const formRefT = ref<InstanceType<typeof FormTeacher> | null>(null); | |||
/** | |||
* 打开班级表单 | |||
* @param opt 操作类型 | |||
* @param record 记录 | |||
*/ | |||
function addClass(opt: FormOptEnum, record: {} | SysUserPersonnel.ClassPage = {}) { | |||
formRefC.value?.onOpen({ opt: opt, record: JSON.parse(JSON.stringify(record)), successful: RefreshTable }); | |||
} | |||
/** | |||
* 班级删除 | |||
* @param ids id数组 | |||
*/ | |||
async function addDelete(id: string[],msg: string) { | |||
// 二次确认 => 请求api => 刷新表格 | |||
await useHandleData(userManageClassManageApi.delete, { id:id.join(",") }, msg); | |||
RefreshTable(); //刷新表格 | |||
} | |||
// 刷新表格 | |||
const RefreshTable = () => { | |||
proTable.value?.refresh(); | |||
} | |||
/** 更多下拉菜单命令枚举 */ | |||
enum cmdEnumTree { | |||
AddTeacher = "绑定班主任", | |||
UpdateTeacher = "修改班主任", | |||
DeleteTeacher = "解绑班主任", | |||
} | |||
/** 树下拉菜单参数接口 */ | |||
interface CommandTree { | |||
row: SysUserPersonnel.ClassPage; | |||
commander: cmdEnumTree; | |||
} | |||
/**配置command的参数 */ | |||
function commander(row: SysUserPersonnel.ClassPage, commander: cmdEnumTree): CommandTree { | |||
return { | |||
row: row, | |||
commander: commander, | |||
}; | |||
} | |||
/** | |||
* 树更多下拉菜单点击事件 | |||
* @param commandtree | |||
*/ | |||
async function handleCommandTree(commander: CommandTree) { | |||
switch (commander.commander) { | |||
case cmdEnumTree.AddTeacher: | |||
formRefT.value?.onOpen({ opt: commander.commander, record: commander.row, successful: RefreshTable }); | |||
break | |||
case cmdEnumTree.UpdateTeacher: | |||
formRefT.value?.onOpen({ opt: commander.commander, record: commander.row, successful: RefreshTable }); | |||
break; | |||
case cmdEnumTree.DeleteTeacher: | |||
// 二次确认 => 请求api => 刷新表格 | |||
await useHandleData(userManageTeacherApi.delete, {id: commander.row.userId}, '解绑教师'); | |||
RefreshTable(); //刷新表格 | |||
break; | |||
} | |||
} | |||
onMounted(() => { | |||
// 获取专业下拉数据 | |||
getMajorList(); | |||
}); | |||
</script> | |||
<style scoped lang="scss"> | |||
.table-box { | |||
width: 100%; | |||
height: 100%; | |||
} | |||
</style> |
@@ -13,10 +13,21 @@ | |||
</s-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<s-form-item label="所属班级" prop="personSetId"> | |||
<s-select v-model="userInfo.personSetId" :options="treeData" label="personSetName" value="personSetId"></s-select> | |||
<s-form-item label="所属系部" prop="depId"> | |||
<s-select v-model="userInfo.depId" :options="departmentOptions" label="name" value="id"></s-select | |||
></s-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="16"> | |||
<el-col :span="12"> | |||
<s-form-item label="所属专业" prop="majorId"> | |||
<s-select v-model="userInfo.majorId" :options="majorOptions" label="name" value="id"></s-select> | |||
</s-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<s-form-item label="所属班级" prop="personSetId"> | |||
<s-select v-model="userInfo.personSetId" :options="classOptions" label="personSetName" value="personSetId"></s-select> </s-form-item | |||
></el-col> | |||
</el-row> | |||
<el-row :gutter="16"> | |||
<el-col :span="24"> | |||
@@ -72,12 +83,16 @@ | |||
</template> | |||
<script setup lang="ts"> | |||
import { SysUserPersonnel, userManagePersonnelApi, userManageClassManageApi } from "@/api"; | |||
import { SysUserPersonnel, userManagePersonnelApi } from "@/api"; | |||
import { Plus } from "@element-plus/icons-vue"; | |||
import { useUserStore } from "@/stores/modules"; | |||
import type { UploadProps } from "element-plus"; | |||
import { ElMessage } from "element-plus"; | |||
import { TokenEnum } from "@/enums"; | |||
import { getMajorList, getDepartmentList, getClassList } from "@/mixin"; | |||
const departmentOptions = ref<any>([]); | |||
const majorOptions = ref<any>([]); | |||
const classOptions = ref<any>([]); | |||
// props | |||
interface FormProps { | |||
modelValue: Partial<SysUserPersonnel.SysUserPerInfo>; | |||
@@ -96,7 +111,6 @@ const fileList = ref<any>([]); | |||
const faces = ref<SysUserPersonnel.SysUserAvatar[]>([]); | |||
const dialogImageUrl = ref(""); | |||
const dialogVisible = ref(false); | |||
const treeData = ref<any>([]); | |||
const handleRemove: UploadProps["onRemove"] = (uploadFile: any) => { | |||
const index = faces.value.findIndex(item => item.uid === uploadFile.uid); | |||
if (index > -1) { | |||
@@ -140,14 +154,10 @@ const genderOptions = ref([ | |||
value: "GENDER_FEMALE" | |||
} | |||
]); | |||
const getRequestData = async () => { | |||
const { data } = await userManageClassManageApi.page(); | |||
treeData.value = data; | |||
}; | |||
onMounted(() => { | |||
onMounted(async () => { | |||
departmentOptions.value = await getDepartmentList(); | |||
// 初始化 | |||
userInfo.value.gender = userInfo.value.gender ? userInfo.value.gender : genderOptions.value[0].value; | |||
getRequestData(); | |||
if (userInfo.value.personId) { | |||
if (userInfo.value.faces?.length > 0) { | |||
fileList.value = [ | |||
@@ -170,6 +180,22 @@ onMounted(() => { | |||
]; | |||
} | |||
} | |||
/* 监听系部、专业 */ | |||
watch( | |||
() => [userInfo.value?.depId, userInfo.value?.majorId], | |||
async ([newDepId, newMajorId], [oldDepId, oldMajorId]) => { | |||
if (newDepId != oldDepId) { | |||
majorOptions.value = await getMajorList(newDepId); | |||
classOptions.value = []; | |||
userInfo.value.personSetId = ""; | |||
userInfo.value.majorId = ""; | |||
} | |||
if (newMajorId && newMajorId != oldMajorId) { | |||
classOptions.value = await getClassList(newMajorId); | |||
} | |||
}, | |||
{ deep: true, immediate: false } | |||
); | |||
}); | |||
</script> | |||
@@ -45,12 +45,13 @@ const sysUserProps = reactive<FormProps.Base<SysUserPersonnel.SysUserPerInfo>>({ | |||
// 表单验证规则 | |||
const rules = reactive({ | |||
// personId: [required("请输入人员ID")], | |||
name: [required("请输入姓名")], | |||
gender: [required("请选择性别")], | |||
faces: [required("请上传人脸图片")], | |||
phone: [required("请输入手机号")] | |||
// extData: [required("请输入扩展数据")] | |||
phone: [required("请输入手机号")], | |||
depId: [required("请选择系部")], | |||
majorId: [required("请选择专业")], | |||
personSetId: [required("请选择班级")] | |||
}); | |||
/** | |||
@@ -5,55 +5,11 @@ | |||
--> | |||
<template> | |||
<div class="main-box"> | |||
<TreeFilter | |||
ref="treeFilter" | |||
label="personSetName" | |||
id="personSetId" | |||
width="300px" | |||
:show-all="true" | |||
:request-api="userManageClassManageApi.page" | |||
@change="changeTreeFilter" | |||
> | |||
<template v-slot:header> | |||
<s-button suffix="班级" @click="addClass(FormOptEnum.ADD)" style="margin-bottom: 15px" /> | |||
</template> | |||
<template v-slot:label="{ row }"> | |||
<span class="custom-tree-node"> | |||
<span>{{ row.node.label }}</span> | |||
<span v-if="row.node.label != '全部'"> | |||
<a @click.stop="addClass(FormOptEnum.EDIT, row.node.data)"> | |||
<el-icon><Edit /></el-icon> | |||
</a> | |||
<a style="margin-left: 8px" @click.stop="addDelete(row.node.data.personSetId, '删除班级')"> | |||
<el-icon><Delete /></el-icon> | |||
</a> | |||
<a style="margin-left: 8px" @click.stop> | |||
<el-dropdown @command="handleCommandTree"> | |||
<el-link :underline="false" :icon="More"> </el-link> | |||
<template #dropdown> | |||
<el-dropdown-menu> | |||
<el-dropdown-item v-if="!row.node.data.userId" :command="commander(row.node.data, cmdEnumTree.AddTeacher)"> | |||
{{ cmdEnumTree.AddTeacher }} | |||
</el-dropdown-item> | |||
<el-dropdown-item v-if="row.node.data.userId" :command="commander(row.node.data, cmdEnumTree.UpdateTeacher)"> | |||
{{ cmdEnumTree.UpdateTeacher }} | |||
</el-dropdown-item> | |||
<el-dropdown-item v-if="row.node.data.userId" :command="commander(row.node.data, cmdEnumTree.DeleteTeacher)"> | |||
{{ cmdEnumTree.DeleteTeacher }} | |||
</el-dropdown-item> | |||
</el-dropdown-menu> | |||
</template> | |||
</el-dropdown> | |||
</a> | |||
</span> | |||
</span> | |||
</template> | |||
</TreeFilter> | |||
<div class="table-box"> | |||
<ProTable ref="proTable" title="人员管理" :columns="columns" rowKey="personId" :request-api="userManagePersonnelApi.page"> | |||
<!-- 表格 header 按钮 --> | |||
<template #tableHeader="scope"> | |||
<s-button v-auth="userPerButtonCode.add" suffix="人员" @click="onOpen(FormOptEnum.ADD, { personSetId: personSetId })" /> | |||
<s-button v-auth="userPerButtonCode.add" suffix="人员" @click="onOpen(FormOptEnum.ADD)" /> | |||
<s-button | |||
v-auth="userPerButtonCode.delete" | |||
type="danger" | |||
@@ -102,10 +58,6 @@ | |||
</div> | |||
<!-- 人员新增/编辑表单 --> | |||
<Form ref="formRef"></Form> | |||
<!-- 班级新增/编辑表单 --> | |||
<FormClass ref="formRefC" /> | |||
<!-- 班主任绑定/修改 --> | |||
<FormTeacher ref="formRefT" /> | |||
<!-- 预览头像 --> | |||
<el-dialog v-model="visible" title="查看头像" width="830px" :before-close="handleClose"> | |||
<div style="display: flex; align-items: center; justify-content: center"> | |||
@@ -115,15 +67,13 @@ | |||
</div> | |||
</template> | |||
<script setup lang="tsx" name="SysUserPersonnel"> | |||
import { userManagePersonnelApi,userPerButtonCode,SysUserPersonnel,userManageClassManageApi,userManageTeacherApi } from "@/api"; | |||
import { userManagePersonnelApi,userPerButtonCode,SysUserPersonnel } from "@/api"; | |||
import { getMajorList, getDepartmentList, getClassList } from "@/mixin"; | |||
import { useHandleData } from "@/hooks/useHandleData"; | |||
import { FormOptEnum } from "@/enums"; | |||
import Form from "./components/form/index.vue"; | |||
import FormClass from "./components/formClass/index.vue"; | |||
import FormTeacher from "./components/formTeacher/index.vue"; | |||
import { ArrowDown,More } from "@element-plus/icons-vue"; | |||
import { ArrowDown } from "@element-plus/icons-vue"; | |||
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | |||
import TreeFilter from "@/components/TreeFilter/index.vue"; | |||
import { useUserStore } from "@/stores/modules"; | |||
import { TokenEnum } from "@/enums"; | |||
import type { UploadProps } from "element-plus"; | |||
@@ -131,12 +81,76 @@ import type { UploadProps } from "element-plus"; | |||
const faceUrl = ref(''); | |||
const visible = ref(false); //是否显示人员表单 | |||
const proTable = ref<ProTableInstance>(); | |||
const treeFilter = ref<InstanceType<typeof TreeFilter> | null>(null); | |||
const userStore = useUserStore(); | |||
const { accessToken } = userStore; | |||
const departmentOptions = ref<any>([]) | |||
const majorOptions = ref<any>([]) | |||
const classOptions = ref<any>([]) | |||
//监听depId/majorId变化 | |||
watch( | |||
() => [proTable.value!?.searchParam?.depId,proTable.value!?.searchParam?.majorId], | |||
async ([newDepId,newMajorId],[oldDepId,oldMajorId]) => { | |||
if(newDepId !== oldDepId){ | |||
majorOptions.value =await getMajorList(newDepId) | |||
classOptions.value = []; | |||
proTable.value!.searchParam.majorId = ""; | |||
proTable.value!.searchParam.personSetId = "" | |||
} | |||
if(newMajorId !== oldMajorId){ | |||
classOptions.value = await getClassList(newMajorId) | |||
} | |||
} ,{ deep: true, immediate: false } | |||
); | |||
// 表格配置项 | |||
const columns: ColumnProps<SysUserPersonnel.SysUserPerInfo>[] = [ | |||
{ type: "selection", fixed: "left", width: 50 }, | |||
{ | |||
prop: "depId", | |||
label: "所属系部", | |||
enum: departmentOptions, | |||
fieldNames: { label: "name", value: "id" }, | |||
search: { | |||
el: "select", | |||
span:1, | |||
props: { | |||
clearable: false, | |||
placeholder: "请选择系部", | |||
}, | |||
}, | |||
isShow: false | |||
}, | |||
{ | |||
prop: "majorId", | |||
label: "所属专业", | |||
enum: majorOptions, | |||
fieldNames: { label: "name", value: "id" }, | |||
search: { | |||
el: "select", | |||
span:1, | |||
props: { | |||
clearable: false, | |||
placeholder: "请选择专业", | |||
}, | |||
}, | |||
isShow: false | |||
}, | |||
{ | |||
prop: "personSetId", | |||
label: "所属班级", | |||
enum: classOptions, | |||
fieldNames: { label: "personSetName", value: "personSetId" }, | |||
search: { | |||
el: "select", | |||
span:1, | |||
props: { | |||
clearable: false, | |||
placeholder: "请选择所属班级", | |||
}, | |||
}, | |||
isShow: false | |||
}, | |||
{ | |||
prop: "faceUrl", | |||
label: "人脸", | |||
@@ -176,10 +190,6 @@ const handleClose = () => { | |||
// 人员表单引用 | |||
const formRef = ref<InstanceType<typeof Form> | null>(null); | |||
// 班级表单引用 | |||
const formRefC = ref<InstanceType<typeof FormClass> | null>(null); | |||
// 班级表单引用 | |||
const formRefT = ref<InstanceType<typeof FormTeacher> | null>(null); | |||
/** | |||
* 打开表单 | |||
@@ -190,25 +200,6 @@ function onOpen(opt: FormOptEnum, record: {} | SysUserPersonnel.SysUserPerInfo = | |||
formRef.value?.onOpen({ opt: opt, record: record, successful: RefreshTable }); | |||
} | |||
/** | |||
* 打开班级表单 | |||
* @param opt 操作类型 | |||
* @param record 记录 | |||
*/ | |||
function addClass(opt: FormOptEnum, record: {} | SysUserPersonnel.ClassPage = {}) { | |||
formRefC.value?.onOpen({ opt: opt, record: JSON.parse(JSON.stringify(record)), successful: RefreshTable }); | |||
} | |||
/** | |||
* 班级删除 | |||
* @param ids id数组 | |||
*/ | |||
async function addDelete(id: string[],msg: string) { | |||
// 二次确认 => 请求api => 刷新表格 | |||
await useHandleData(userManageClassManageApi.delete, { id }, msg); | |||
RefreshTable(); //刷新表格 | |||
} | |||
/** | |||
* 人员删除 | |||
* @param ids id数组 | |||
@@ -229,7 +220,7 @@ function onOpen(opt: FormOptEnum, record: {} | SysUserPersonnel.SysUserPerInfo = | |||
// 刷新表格 | |||
const RefreshTable = () => { | |||
proTable.value?.refresh(); | |||
treeFilter.value?.refresh(); //刷新树形筛选器 | |||
// treeFilter.value?.refresh(); //刷新树形筛选器 | |||
} | |||
@@ -275,47 +266,6 @@ function handleCommand(command: Command) { | |||
/** 更多下拉菜单命令枚举 */ | |||
enum cmdEnumTree { | |||
AddTeacher = "绑定班主任", | |||
UpdateTeacher = "修改班主任", | |||
DeleteTeacher = "解绑班主任", | |||
} | |||
/** 树下拉菜单参数接口 */ | |||
interface CommandTree { | |||
row: SysUserPersonnel.ClassPage; | |||
commander: cmdEnumTree; | |||
} | |||
/**配置command的参数 */ | |||
function commander(row: SysUserPersonnel.ClassPage, commander: cmdEnumTree): CommandTree { | |||
return { | |||
row: row, | |||
commander: commander, | |||
}; | |||
} | |||
/** | |||
* 树更多下拉菜单点击事件 | |||
* @param commandtree | |||
*/ | |||
async function handleCommandTree(commander: CommandTree) { | |||
switch (commander.commander) { | |||
case cmdEnumTree.AddTeacher: | |||
formRefT.value?.onOpen({ opt: commander.commander, record: commander.row, successful: RefreshTable }); | |||
break | |||
case cmdEnumTree.UpdateTeacher: | |||
formRefT.value?.onOpen({ opt: commander.commander, record: commander.row, successful: RefreshTable }); | |||
break; | |||
case cmdEnumTree.DeleteTeacher: | |||
// 二次确认 => 请求api => 刷新表格 | |||
await useHandleData(userManageTeacherApi.delete, {id: commander.row.id}, '解绑教师'); | |||
RefreshTable(); //刷新表格 | |||
break; | |||
} | |||
} | |||
const handleAvatarSuccess: UploadProps["onSuccess"] = (response) => { | |||
if (response.code === 200) { | |||
userManagePersonnelApi.addFace({ | |||
@@ -328,15 +278,10 @@ const handleAvatarSuccess: UploadProps["onSuccess"] = (response) => { | |||
ElMessage.error(response.msg); | |||
} | |||
}; | |||
/** 部门切换 */ | |||
const personSetId = ref<number | string>() | |||
function changeTreeFilter(val: number | string) { | |||
personSetId.value = val | |||
proTable.value!.pageable.pageNum = 1; | |||
proTable.value!.searchParam.personSetId = val; | |||
proTable.value!.search(); | |||
} | |||
onMounted(async () => { | |||
// 获取系部下拉数据 | |||
departmentOptions.value = await getDepartmentList() | |||
}); | |||
</script> | |||
<style scoped lang="scss"> | |||
.table-box { | |||