Ver código fonte

人员、教室点名、行为轨迹添加专业、系部;新增班级模块整体处理

master
suyanyan 3 meses atrás
pai
commit
01decd6e82
11 arquivos alterados com 566 adições e 218 exclusões
  1. +2
    -2
      SafeCampus.WEB/src/api/modules/usermanage/classManage.ts
  2. +21
    -0
      SafeCampus.WEB/src/mixin/index.ts
  3. +81
    -12
      SafeCampus.WEB/src/views/attendance/behaviorTrace/index.vue
  4. +40
    -21
      SafeCampus.WEB/src/views/attendance/roolcall/components/form/index.vue
  5. +76
    -35
      SafeCampus.WEB/src/views/attendance/roolcall/index.vue
  6. +15
    -2
      SafeCampus.WEB/src/views/userManage/classManage/components/formClass/index.vue
  7. +6
    -4
      SafeCampus.WEB/src/views/userManage/classManage/components/formTeacher/index.vue
  8. +211
    -0
      SafeCampus.WEB/src/views/userManage/classManage/index.vue
  9. +36
    -10
      SafeCampus.WEB/src/views/userManage/personnel/components/form/form_basic.vue
  10. +4
    -3
      SafeCampus.WEB/src/views/userManage/personnel/components/form/index.vue
  11. +74
    -129
      SafeCampus.WEB/src/views/userManage/personnel/index.vue

+ 2
- 2
SafeCampus.WEB/src/api/modules/usermanage/classManage.ts Ver arquivo

@@ -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) {


+ 21
- 0
SafeCampus.WEB/src/mixin/index.ts Ver arquivo

@@ -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 };

+ 81
- 12
SafeCampus.WEB/src/views/attendance/behaviorTrace/index.vue Ver arquivo

@@ -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 {


+ 40
- 21
SafeCampus.WEB/src/views/attendance/roolcall/components/form/index.vue Ver arquivo

@@ -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) => {


+ 76
- 35
SafeCampus.WEB/src/views/attendance/roolcall/index.vue Ver arquivo

@@ -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 {


SafeCampus.WEB/src/views/userManage/personnel/components/formClass/index.vue → SafeCampus.WEB/src/views/userManage/classManage/components/formClass/index.vue Ver arquivo

@@ -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>();
/** 提交表单 */

SafeCampus.WEB/src/views/userManage/personnel/components/formTeacher/index.vue → SafeCampus.WEB/src/views/userManage/classManage/components/formTeacher/index.vue Ver arquivo

@@ -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();
};

// 提交数据(新增/编辑)

+ 211
- 0
SafeCampus.WEB/src/views/userManage/classManage/index.vue Ver arquivo

@@ -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>

+ 36
- 10
SafeCampus.WEB/src/views/userManage/personnel/components/form/form_basic.vue Ver arquivo

@@ -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>



+ 4
- 3
SafeCampus.WEB/src/views/userManage/personnel/components/form/index.vue Ver arquivo

@@ -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("请选择班级")]
});

/**


+ 74
- 129
SafeCampus.WEB/src/views/userManage/personnel/index.vue Ver arquivo

@@ -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 {


Carregando…
Cancelar
Salvar