Quellcode durchsuchen

教师点名

master
suyanyan vor 2 Monaten
Ursprung
Commit
2fa3db5726
7 geänderte Dateien mit 490 neuen und 94 gelöschten Zeilen
  1. +24
    -18
      SafeCampus.WEB/src/api/modules/attendance/roolcall.ts
  2. +10
    -1
      SafeCampus.WEB/src/routers/modules/staticRouter.ts
  3. +177
    -0
      SafeCampus.WEB/src/views/attendance/roolcall/components/form/index.vue
  4. +0
    -33
      SafeCampus.WEB/src/views/attendance/roolcall/components/nofaceTable/index.vue
  5. +135
    -0
      SafeCampus.WEB/src/views/attendance/roolcall/detail.vue
  6. +143
    -41
      SafeCampus.WEB/src/views/attendance/roolcall/index.vue
  7. +1
    -1
      SafeCampus.WEB/src/views/userManage/clothing/components/form/index.vue

+ 24
- 18
SafeCampus.WEB/src/api/modules/attendance/roolcall.ts Datei anzeigen

@@ -13,31 +13,37 @@
* @see https://gitee.com/dotnetmoyu/SimpleAdmin
*/
import { moduleRequest } from "@/api/request";
import { ReqId, SysUserPersonnel } from "@/api/interface";
const http = moduleRequest("/business/dfieldApi/");

const http = moduleRequest("/business/classRoomCallApi/");
/**
* @Description: 单页管理
* @Description: 教师点名
* @Author: SYY
* @Date: 2023-12-15 15:34:54
*/
const attendanceRoolcall = {
/** 查询底库列表 */
page(params: SysUserPersonnel.ClassPage) {
return http.get("page", params);
const attendanceRoolcallApi = {
// 获取列表
page(params: any) {
return http.get("getPageList", params);
},
/** 查询点名任务列表 */
getTaskPageList(params: any) {
return http.get("getTaskPageList", params);
},
/** 删除点名任务(删除关联点名数据) */
delete(params: any) {
return http.delete("delete", params);
},
/** 删除底库 */
delete(params: ReqId) {
return http.delete("deleteDfieldD", params);
/** 删除点名任务(只可删除待处理的任务) */
remove(params: any) {
return http.delete("remove", params);
},
/** 创建底库 */
add(params: SysUserPersonnel.ClassPage) {
return http.post("createDfieldA", params);
/** 点名任务下发 */
add(params: any) {
return http.post("taskSubmit", params);
},
/** 更新底库 */
update(params: SysUserPersonnel.ClassPage) {
return http.put("updateDfieldU", params);
/** 修改点名任务 */
update(params: any) {
return http.post("update", params);
}
};

export { attendanceRoolcall };
export { attendanceRoolcallApi };

+ 10
- 1
SafeCampus.WEB/src/routers/modules/staticRouter.ts Datei anzeigen

@@ -37,7 +37,16 @@ export const staticRouter: RouteRecordRaw[] = [
component: () => import("@/layouts/index.vue"),
// component: () => import("@/layouts/indexAsync.vue"),
redirect: HOME_URL,
children: []
children: [
{
meta: {
title: "任务人员列表"
},
name: "任务人员列表",
path: "/roolcall/detail",
component: () => import("@/views/attendance/roolcall/detail.vue")
}
]
}
];



+ 177
- 0
SafeCampus.WEB/src/views/attendance/roolcall/components/form/index.vue Datei anzeigen

@@ -0,0 +1,177 @@
<!--
* @Description: 表单
* @Author: syy
* @Date: 2023-12-15 15:45:59
-->
<template>
<div>
<form-container v-model="visible" :title="`${sysUserProps.opt}点名`" form-size="900px" @close="onClose">
<el-form
ref="sysUserFormRef"
:rules="rules"
:disabled="sysUserProps.disabled"
:model="sysUserProps.record"
:hide-required-asterisk="sysUserProps.disabled"
label-width="auto"
label-suffix=" :"
>
<div>
<el-row :gutter="16">
<el-col :span="12">
<s-form-item label="摄像头分组" prop="cameraGroudId">
<org-selector v-model:org-value="sysUserProps.record.cameraGroudId" :org-tree-api="monitorLIVEApi.groupList" :show-all="false"
/></s-form-item>
</el-col>
<el-col :span="12">
<s-form-item label="摄像头" prop="cameraId">
<s-input v-model="sysUserProps.record.cameraId"></s-input>
</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-form-item>
</el-col>
<el-col :span="12">
<s-form-item label="持续时间" prop="continueTime">
<el-slider v-model="sysUserProps.record.continueTime" />
</s-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<s-form-item label="相似度" prop="similarity">
<el-slider v-model="sysUserProps.record.similarity" :min="0.3" :max="0.8" :step="0.01" />
</s-form-item>
</el-col>
</el-row>
</div>
</el-form>
<template #footer>
<el-button @click="onClose"> 取消 </el-button>
<el-button v-show="!sysUserProps.disabled" type="primary" @click="handleSubmit"> 确定 </el-button>
</template>
</form-container>
</div>
</template>

<script setup lang="ts" name="SysUserPersonnelForm">
import { SysUserPersonnel, userManagePersonnelApi, monitorLIVEApi } from "@/api";
import { SysDictEnum } from "@/enums";
import { required } from "@/utils/formRules";
import { FormInstance } from "element-plus";
import { useDictStore } from "@/stores/modules";
const visible = ref(false); //是否显示表单
const formatTooltip = (val: number) => {
return val / 80;
};
// 表单参数
const sysUserProps = reactive<FormProps.Base<SysUserPersonnel.SysUserPerInfo>>({
opt: FormOptEnums.INITIATE,
record: {},
treeAllData: [],
disabled: false
});
const CameraList = ref([]);
/** 表单操作类型枚举 */
enum FormOptEnums {
/** 发起 */
INITIATE = "发起"
}

// 表单验证规则
const rules = reactive({
cameraGroudId: [required("请选择摄像头分组")],
similarity: [required("请选择相似度")],
cameraId: [required("请选择摄像头")],
continueTime: [required("请选择持续时间")],
personSetId: [required("请选择所属班级")]
});

/**
* 打开表单
* @param props 表单参数
*/
function onOpen(props: FormProps.Base<SysUserPersonnel.SysUserPerInfo>) {
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 => {
sysUserProps.record = res.data;
});
}
}
watch(
sysUserProps.record.cameraGroudId,
(newVal, oldVal) => {
console.log(newVal, "..........");
},
{
deep: true,
immediate: true
}
);

const handleChange = (val: any) => {
console.log(val);

// monitorLIVEApi.list({ groupId: val }).then(res => {
// CameraList.value = res.data;
// });
};
// 提交数据(新增/编辑)
const sysUserFormRef = ref<FormInstance>();
/** 提交表单 */
async function handleSubmit() {
sysUserFormRef.value?.validate(async valid => {
if (!valid) return; //表单验证失败
//提交表单
if (sysUserProps.record.faces.length === 0) {
return ElMessage.error("请上传人脸图片");
}
if (sysUserProps.record.personId) {
await userManagePersonnelApi
.update(sysUserProps.record)
.then(() => {
sysUserProps.successful!(); //调用父组件的successful方法
})
.finally(() => {
onClose();
});
} else {
await userManagePersonnelApi
.add(sysUserProps.record)
.then(() => {
sysUserProps.successful!(); //调用父组件的successful方法
})
.finally(() => {
onClose();
});
}
});
}

/** 关闭表单*/
function onClose() {
visible.value = false;
}

// 暴露给父组件的方法
defineExpose({
onOpen
});
</script>

<style lang="scss" scoped></style>

+ 0
- 33
SafeCampus.WEB/src/views/attendance/roolcall/components/nofaceTable/index.vue Datei anzeigen

@@ -1,33 +0,0 @@
<!--
* @Description: 人脸识别失败表格
* @Author: yxq
* @Date: 2023-12-15 15:45:59
-->
<template>
<div>
<ProTable ref="proTable" title="教师点名" :columns="columns" :data="data" :request-api="userManageClassManageApi.page">
<!-- 表格操作栏 -->
<template #operation="scope">
<el-space>
<s-button link prefix="人工" :opt="FormOptEnum.EDIT" suffix="确认" @click="onOpen(FormOptEnum.VIEW, scope.row)" />
</el-space>
</template>
</ProTable>
</div>
</template>
<script setup lang="ts">
/** 关闭表单*/
function onClose() {
visible.value = false;
activeName.value = "basic";
}

// 暴露给父组件的方法
defineExpose({
onOpen
});
</script>
<style lang="scss" scoped></style>

+ 135
- 0
SafeCampus.WEB/src/views/attendance/roolcall/detail.vue Datei anzeigen

@@ -0,0 +1,135 @@
<template>
<div class="roolcallDetail">
<el-row>
<el-col :xl="4" :lg="4" :md="6" :sm="12" v-for="(item, index) in listData" :key="index"
><div class="grid-content">
<div class="imgBox">
<img
src="http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721376415&OSSAccessKeyId=STS.NUSm6539EVcLhtZCZEHnhRF8t&Signature=2Kmz3s%2FXjUBLfMfXi0GcuV998WY%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5bmJoyB3uZk4aGnalLrp1oQROFEvYOTljz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY42JpORrg0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxATp3htf%2FAxd8uAx9DyyfH1x3TObqd7jjqzaKs3NYdtswV4BUlvK5CGWEjhzQEO8mJtNIDT39awuolxWrfsIeBqAAVOd5Y2r6RQD6ZRZFrkepn9XGhIi2MZGgFU5h4wAMv9fpXFA%2FgTSJhbBoKXkAOvkYLObuS4FAaKYBll7eEMnCpOf%2BVGjABIbd%2BhpQaD8MIuUBVw1SOyjTVaLxMbb7guH7nLPyeZMcRqmZw3WH0leI4eeyeTPTT0DfJMgIezHEGctIAA%3D"
alt=""
/>
</div>
<div class="info">
<div class="desc">
<span class="label">姓名:</span>
{{ item.name }}
</div>
<div class="desc">
<span class="label">所属分组:</span>
{{ item.group }}
</div>
</div>
<div class="btn">
<el-button type="text" :icon="Edit">编辑</el-button>
<el-button type="danger" text :icon="Delete">删除</el-button>
</div>
</div></el-col
>
</el-row>
</div>
</template>
<script setup lang="ts" name="SysUserPersonnel">
import { Delete, Edit } from "@element-plus/icons-vue";
const listData = ref([
{
name: "zhangsan ",
group: "所属fenzu ",
status: "正常",
phone: "1234567890",
email: "1234567890@qq.com"
},
{
name: "zhangsan ",
group: "所属fenzu ",
status: "正常",
phone: "1234567890",
email: "1234567890@qq.com"
},
{
name: "zhangsan ",
group: "所属fenzu ",
status: "正常",
phone: "1234567890",
email: "1234567890@qq.com"
},
{
name: "zhangsan ",
group: "所属fenzu ",
status: "正常",
phone: "1234567890",
email: "1234567890@qq.com"
},
{
name: "zhangsan ",
group: "所属fenzu ",
status: "正常",
phone: "1234567890",
email: "1234567890@qq.com"
},
{
name: "zhangsan ",
group: "所属fenzu ",
status: "正常",
phone: "1234567890",
email: "1234567890@qq.com"
}
]);
</script>
<style lang="scss" scoped>
.roolcallDetail {
.el-row {
width: 100%;
.el-col {
box-sizing: border-box;
height: 310px;
margin-bottom: 20px;
.grid-content {
box-sizing: border-box;
height: 100%;
padding: 15px;
margin: 10px;
background: #ffffff;
.imgBox {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 150px;
background: #f2f2f2;
img {
max-height: 100%;
object-fit: cover;
}
}
.info {
height: 80px;
.label {
margin-right: 8px;
font-size: 14px;
color: #41465f;
opacity: 0.6;
}
.desc {
max-width: 100%;
margin-top: 15px;
overflow: hidden;
font-size: 14px;
color: #41465f;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.btn {
display: flex;
align-items: center;
justify-content: space-between;
height: 40px;
font-size: 14px;
color: #41465f;
border-top: 1px solid #f3f3f3;
}
}
}
}
}
</style>

+ 143
- 41
SafeCampus.WEB/src/views/attendance/roolcall/index.vue Datei anzeigen

@@ -1,70 +1,172 @@
<!--
* @Description: 教师点名
* @Author: yxq
* @Date: 2024-7-16
* @Author: syy
* @Date: 2024-7-15
-->
<template>
<div class="table-box">
<ProTable ref="proTable" title="教师点名" :columns="columns" :data="data" :request-api="userManageClassManageApi.page">
<!-- 表格操作栏 -->
<template #operation="scope">
<el-space>
<s-button link prefix="人工" :opt="FormOptEnum.EDIT" suffix="确认" @click="onOpen(FormOptEnum.VIEW, scope.row)" />
</el-space>
<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>
</ProTable>
</TreeFilter>
<div class="table-box">
<!-- :request-api="attendanceRoolcallApi.page" -->
<ProTable ref="proTable" title="任务列表" :columns="columns" rowKey="personId" :data="tableData">
<!-- 表格 header 按钮 -->
<template #tableHeader="scope">
<s-button :opt="FormOptEnums.INITIATE" @click="onOpen(FormOptEnums.INITIATE, { personSetId: personSetId }, treeFilter.treeAllData)" />
<s-button
type="danger"
:opt="FormOptEnum.DELETE"
plain
suffix="点名任务"
:disabled="!scope.isSelected"
@click="onDelete(scope.selectedListIds, '删除点名任务')"
/>
</template>
<!-- 表格操作栏 -->
<template #operation="scope">
<el-space>
<s-button link :opt="FormOptEnum.VIEW" @click="onView(scope.row)" />
<s-button link :opt="FormOptEnum.DELETE" @click="onDelete([scope.row.personId], `删除点名任务`)" />
</el-space>
</template>
</ProTable>
</div>
<!-- 发起新增/编辑表单 -->
<Form ref="formRef"></Form>
</div>
</template>
<script setup lang="ts">
import { userManageClassManageApi } from "@/api";
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
<script setup lang="tsx" name="SysUserPersonnel">
import { attendanceRoolcallApi,userManagePersonnelApi,userManageClassManageApi} from "@/api";
import { useHandleData } from "@/hooks/useHandleData";
import { FormOptEnum } from "@/enums";
const data = ref([
import Form from "./components/form/index.vue";
import { ArrowDown,More } from "@element-plus/icons-vue";
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
import TreeFilter from "@/components/TreeFilter/index.vue";
import { useRouter } from "vue-router";
const router = useRouter();

/** 表单操作类型枚举 */
enum FormOptEnums {
/** 发起 */
INITIATE = "发起",
/* 查看点名任务 */
VIEWTASK = "查看",
/* 修改点名记录 */
EDITTASK = "修改点名记录"
}

// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数)
const visible = ref(false); //是否显示人员表单
const proTable = ref<ProTableInstance>();
const treeFilter = ref<InstanceType<typeof TreeFilter> | null>(null);

const tableData = ref([
{
classname: "XXXXX班级",
classId: "544165",
studentNum: "43",
guiqinNum: "38",
noFaceNum: "5"
cameraName: "摄像头1",
continueTime: "20",
similarity: "0.7",
},
{
classname: "XX班级",
classId: "555333",
studentNum: "42",
guiqinNum: "37",
noFaceNum: "4"
cameraName: "摄像头2",
continueTime: "30",
similarity: "0.45",
}
]);
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数)
const proTable = ref<ProTableInstance>();
])
// 表格配置项
const columns: ColumnProps[] = [
{ type: "selection", fixed: "left", width: 50 },
{
prop: "classname",
label: "班级名称"
},
{
prop: "classId",
label: "班级ID"
prop: "cameraName",
label: "摄像头名称"
},
{
prop: "studentNum",
label: "学生人数"
prop: "continueTime",
label: "持续时间"
},
{
prop: "guiqinNum",
label: "归寝人数"
},
{
prop: "noFaceNum",
label: "人脸无法识别人数"
prop: "similarity",
label: "相似度"
},
{ prop: "operation", label: "操作", width: 250, fixed: "right" }
];
const handleClose = () => {
visible.value = false;
};

const onView = (row: any) => {
router.push('/roolcall/detail');
};
// 发起任务表单引用
const formRef = ref<InstanceType<typeof Form> | null>(null);

/**
* 打开表单
* @param opt 操作类型
* @param record 记录
*/
function onOpen(opt: FormOptEnum, record: {},treeAllData:any) {
formRef.value?.onOpen({ opt: opt, record: record,treeAllData:treeAllData, successful: RefreshTable });
}



/**
* 任务删除
* @param ids id数组
*/
async function onDelete(ids: string[], msg: string) {
if(ids.length === 0){
ElMessage({
message: '请选择要删除的人员',
type: 'warning'
});
return
}
// 二次确认 => 请求api => 刷新表格
await useHandleData(userManagePersonnelApi.delete, {id: ids.join(",") }, msg);
RefreshTable(); //刷新表格
}

// 刷新表格
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();
}
</script>
<style scoped lang="scss">
.table-box {
width: 100%;
height: 100%;
}
.custom-tree-node {
display: flex;
flex: 1;
align-items: center;
justify-content: space-between;
padding-right: 8px;
font-size: 14px;
}
</style>

+ 1
- 1
SafeCampus.WEB/src/views/userManage/clothing/components/form/index.vue Datei anzeigen

@@ -30,7 +30,7 @@
</el-row>
<el-row :gutter="16">
<el-col :span="24">
<s-form-item label="上传服装" prop="faces">
<s-form-item label="上传服装" prop="clothUrl">
<el-upload
class="avatar-uploader"
action="/api/business/clothApi/uploadFile"


Laden…
Abbrechen
Speichern