@@ -13,3 +13,4 @@ | |||||
* @see https://gitee.com/dotnetmoyu/SimpleAdmin | * @see https://gitee.com/dotnetmoyu/SimpleAdmin | ||||
*/ | */ | ||||
export * from "./passenger"; | export * from "./passenger"; | ||||
export * from "./studentsReturn"; |
@@ -14,7 +14,7 @@ | |||||
import { ReqPage } from "@/api"; | import { ReqPage } from "@/api"; | ||||
/** | /** | ||||
* @Description: 客流查询接口 | |||||
* @Description: 客流查询 | |||||
* @Author: yxq | * @Author: yxq | ||||
* @Date: 2023-12-17 15:34:54 | * @Date: 2023-12-17 15:34:54 | ||||
*/ | */ | ||||
@@ -0,0 +1,31 @@ | |||||
/** | |||||
* @description 学生归寝 | |||||
* @license Apache License Version 2.0 | |||||
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛 | |||||
* @remarks | |||||
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款: | |||||
* 1.请不要删除和修改根目录下的LICENSE文件。 | |||||
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。 | |||||
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin | |||||
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。 | |||||
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。 | |||||
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关 | |||||
*/ | |||||
import { ReqPage } from "@/api"; | |||||
/** | |||||
* @Description: 教师点名 | |||||
* @Author: yxq | |||||
* @Date: 2023-12-17 15:34:54 | |||||
*/ | |||||
export namespace AttendanceStudentsReturn { | |||||
export interface Page extends ReqPage {} | |||||
/** 表单 */ | |||||
export interface studentsReturnInfo { | |||||
fenpianleixing:String, | |||||
shijianduan:any, | |||||
shexiangtou:any, | |||||
} | |||||
} |
@@ -24,19 +24,19 @@ const http = moduleRequest("/business/dfieldApi/"); | |||||
const attendanceStudentsReturn = { | const attendanceStudentsReturn = { | ||||
/** 查询底库列表 */ | /** 查询底库列表 */ | ||||
page(params: SysUserPersonnel.ClassPage) { | page(params: SysUserPersonnel.ClassPage) { | ||||
return http.get("page", params); | |||||
return http.get("test", params); | |||||
}, | }, | ||||
/** 删除底库 */ | /** 删除底库 */ | ||||
delete(params: ReqId) { | delete(params: ReqId) { | ||||
return http.delete("deleteDfieldD", params); | |||||
return http.delete("test", params); | |||||
}, | }, | ||||
/** 创建底库 */ | /** 创建底库 */ | ||||
add(params: SysUserPersonnel.ClassPage) { | add(params: SysUserPersonnel.ClassPage) { | ||||
return http.post("createDfieldA", params); | |||||
return http.post("test", params); | |||||
}, | }, | ||||
/** 更新底库 */ | /** 更新底库 */ | ||||
update(params: SysUserPersonnel.ClassPage) { | update(params: SysUserPersonnel.ClassPage) { | ||||
return http.put("updateDfieldU", params); | |||||
return http.put("test", params); | |||||
} | } | ||||
}; | }; | ||||
@@ -0,0 +1,191 @@ | |||||
<!-- | |||||
* @Description: 人员表单 | |||||
* @Author: syy | |||||
* @Date: 2023-12-15 15:45:50 | |||||
--> | |||||
<template> | |||||
<div class="userManageForm"> | |||||
<div> | |||||
<el-row :gutter="16"> | |||||
<el-col :span="12"> | |||||
<s-form-item label="人员姓名" prop="name"> | |||||
<s-input v-model="userInfo.name"></s-input> | |||||
</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> | |||||
</el-col> | |||||
</el-row> | |||||
<el-row :gutter="16"> | |||||
<el-col :span="24"> | |||||
<s-form-item label="上传人脸" prop="faces"> | |||||
<el-upload | |||||
v-model:file-list="fileList" | |||||
action="/api/business/personApi/uploadFile" | |||||
list-type="picture-card" | |||||
:on-success="handleAvatarSuccess" | |||||
:on-error="handleAvatarError" | |||||
:on-preview="handlePictureCardPreview" | |||||
:on-remove="handleRemove" | |||||
accept=".jpg, .jpeg, .png" | |||||
:headers="{ | |||||
Authorization: `${TokenEnum.TOKEN_PREFIX} ${accessToken}` | |||||
}" | |||||
> | |||||
<el-icon><Plus /></el-icon> | |||||
</el-upload> | |||||
<el-dialog v-model="dialogVisible" title="查看图片"> | |||||
<img w-full :src="dialogImageUrl" alt="Preview Image" style="width: 100%" /> | |||||
</el-dialog> | |||||
</s-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
<el-row :gutter="16"> | |||||
<el-col :span="12"> | |||||
<s-form-item label="性别" prop="gender"> | |||||
<s-radio-group v-model="userInfo.gender" :options="genderOptions" /> | |||||
</s-form-item> | |||||
</el-col> | |||||
<el-col :span="12"> | |||||
<s-form-item label="年龄" prop="age"> | |||||
<s-input v-model="userInfo.age"></s-input> | |||||
</s-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
<el-row :gutter="16"> | |||||
<el-col :span="12"> | |||||
<s-form-item label="手机号" prop="phone"> | |||||
<s-input v-model="userInfo.phone"></s-input> | |||||
</s-form-item> | |||||
</el-col> | |||||
<el-col :span="12"> | |||||
<s-form-item label="扩展字段" prop="extData"> | |||||
<s-input v-model="userInfo.extData"></s-input> | |||||
</s-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script setup lang="ts"> | |||||
import { SysUserPersonnel, userManagePersonnelApi, userManageClassManageApi } 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"; | |||||
// props | |||||
interface FormProps { | |||||
modelValue: Partial<SysUserPersonnel.SysUserPerInfo>; | |||||
} | |||||
const emit = defineEmits(["update:modelValue"]); //定义emit | |||||
const props = defineProps<FormProps>(); //定义props | |||||
// 人员信息 | |||||
const userInfo = computed({ | |||||
get: () => props.modelValue, | |||||
set: val => emit("update:modelValue", val) | |||||
}); | |||||
/* */ | |||||
const userStore = useUserStore(); | |||||
const { accessToken } = userStore; | |||||
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) { | |||||
faces.value.splice(index, 1); | |||||
} | |||||
userInfo.value.faces = faces.value; | |||||
if (uploadFile.personId) { | |||||
userManagePersonnelApi.deleteFace({ personId: uploadFile.personId, faceIds: [uploadFile.uid] }).then(res => {}); | |||||
} | |||||
}; | |||||
const handlePictureCardPreview: UploadProps["onPreview"] = uploadFile => { | |||||
dialogImageUrl.value = uploadFile.url!; | |||||
dialogVisible.value = true; | |||||
}; | |||||
const handleAvatarSuccess: UploadProps["onSuccess"] = (response, uploadFile) => { | |||||
if (response.code === 200) { | |||||
faces.value.push({ faceUrl: response.data, uid: uploadFile.uid }); | |||||
userInfo.value.faces = faces.value; | |||||
ElMessage.success(response.msg); | |||||
} else { | |||||
ElMessage.error(response.msg); | |||||
fileList.value = fileList.value.splice(0, fileList.value.length - 1); | |||||
} | |||||
}; | |||||
const handleAvatarError: UploadProps["onError"] = (error, uploadFile, uploadFiles) => { | |||||
console.log(error, uploadFile, uploadFiles, "err"); | |||||
}; | |||||
// 通用状态选项 | |||||
const genderOptions = ref([ | |||||
{ | |||||
label: "未知", | |||||
value: "GENDER_UNKNOWN" | |||||
}, | |||||
{ | |||||
label: "男", | |||||
value: "GENDER_MALE" | |||||
}, | |||||
{ | |||||
label: "女", | |||||
value: "GENDER_FEMALE" | |||||
} | |||||
]); | |||||
const getRequestData = async () => { | |||||
const { data } = await userManageClassManageApi.page(); | |||||
treeData.value = data; | |||||
}; | |||||
onMounted(() => { | |||||
// 初始化 | |||||
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 = [ | |||||
...JSON.parse(JSON.stringify(userInfo.value.faces)).map((item: any) => { | |||||
return { | |||||
url: item.faceUrl, | |||||
uid: item.faceId, | |||||
personId: userInfo.value.personId | |||||
}; | |||||
}) | |||||
]; | |||||
faces.value = [ | |||||
...JSON.parse(JSON.stringify(userInfo.value.faces)).map((item: any) => { | |||||
return { | |||||
faceUrl: item.faceUrl, | |||||
uid: item.faceId, | |||||
personId: userInfo.value.personId | |||||
}; | |||||
}) | |||||
]; | |||||
} | |||||
} | |||||
}); | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
:deep(.el-input__wrapper) { | |||||
width: 100% !important; | |||||
} | |||||
:deep(.el-date-editor.el-input) { | |||||
width: 92% !important; | |||||
} | |||||
:deep(.el-upload-list--picture-card .el-upload-list__item) { | |||||
width: 100px !important; | |||||
height: 100px !important; | |||||
} | |||||
:deep(.el-upload--picture-card) { | |||||
width: 100px !important; | |||||
height: 100px !important; | |||||
} | |||||
</style> |
@@ -0,0 +1,120 @@ | |||||
<!-- | |||||
* @Description: 表单 | |||||
* @Author: syy | |||||
* @Date: 2023-12-15 15:45:59 | |||||
--> | |||||
<template> | |||||
<div> | |||||
<form-container v-model="visible" :title="`${sysUserProps.opt}人员`" form-size="800px" @close="onClose"> | |||||
<el-form | |||||
ref="sysUserFormRef" | |||||
:rules="rules" | |||||
:disabled="sysUserProps.disabled" | |||||
:model="sysUserProps.record" | |||||
:hide-required-asterisk="sysUserProps.disabled" | |||||
label-width="auto" | |||||
label-suffix=" :" | |||||
> | |||||
<el-tabs v-model="activeName"> | |||||
<Basic v-model="sysUserProps.record"></Basic> | |||||
</el-tabs> | |||||
</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 } from "@/api"; | |||||
import { FormOptEnum, SysDictEnum } from "@/enums"; | |||||
import { required } from "@/utils/formRules"; | |||||
import { FormInstance } from "element-plus"; | |||||
import { useDictStore } from "@/stores/modules"; | |||||
import Basic from "./form_basic.vue"; | |||||
const visible = ref(false); //是否显示表单 | |||||
const activeName = ref("basic"); | |||||
// 表单参数 | |||||
const sysUserProps = reactive<FormProps.Base<SysUserPersonnel.SysUserPerInfo>>({ | |||||
opt: FormOptEnum.ADD, | |||||
record: {}, | |||||
disabled: false | |||||
}); | |||||
// 表单验证规则 | |||||
const rules = reactive({ | |||||
// personId: [required("请输入人员ID")], | |||||
name: [required("请输入姓名")], | |||||
gender: [required("请选择性别")], | |||||
faces: [required("请上传人脸图片")], | |||||
phone: [required("请输入手机号")] | |||||
// extData: [required("请输入扩展数据")] | |||||
}); | |||||
/** | |||||
* 打开表单 | |||||
* @param props 表单参数 | |||||
*/ | |||||
function onOpen(props: FormProps.Base<SysUserPersonnel.SysUserPerInfo>) { | |||||
Object.assign(sysUserProps, props); //合并参数 | |||||
if (props.opt == FormOptEnum.ADD) { | |||||
//如果是新增,设置默认值 | |||||
// 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; | |||||
}); | |||||
} | |||||
} | |||||
// 提交数据(新增/编辑) | |||||
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; | |||||
activeName.value = "basic"; | |||||
} | |||||
// 暴露给父组件的方法 | |||||
defineExpose({ | |||||
onOpen | |||||
}); | |||||
</script> | |||||
<style lang="scss" scoped></style> |
@@ -0,0 +1,107 @@ | |||||
<!-- | |||||
* @Description: 表单 | |||||
* @Author: syy | |||||
* @Date: 2023-12-15 15:45:59 | |||||
--> | |||||
<template> | |||||
<div> | |||||
<form-container v-model="visibleClass" :title="`${sysUserProps.opt}班级`" form-size="400px" @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="22"> | |||||
<s-form-item label="班级名称" prop="personSetName"> | |||||
<s-input v-model="sysUserProps.record.personSetName"></s-input> | |||||
</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="SysUserPerformClass"> | |||||
import { ref } from "vue"; | |||||
import { SysUserPersonnel, userManageClassManageApi } from "@/api"; | |||||
import { FormOptEnum } from "@/enums"; | |||||
import { required } from "@/utils/formRules"; | |||||
import { FormInstance } from "element-plus"; | |||||
const visibleClass = ref(false); //是否显示表单 | |||||
// 表单参数 | |||||
const sysUserProps = reactive<FormProps.Base<SysUserPersonnel.ClassPage>>({ | |||||
opt: FormOptEnum.ADD, | |||||
record: {}, | |||||
disabled: false | |||||
}); | |||||
// 表单验证规则 | |||||
const rules = reactive({ | |||||
personSetName: [required("请输入班级名称")] | |||||
}); | |||||
/** | |||||
* 打开表单 | |||||
* @param props 表单参数 | |||||
*/ | |||||
function onOpen(props: FormProps.Base<SysUserPersonnel.ClassPage>) { | |||||
Object.assign(sysUserProps, props); //合并参数 | |||||
visibleClass.value = true; //显示表单 | |||||
sysUserProps.record = props.record; | |||||
} | |||||
// 提交数据(新增/编辑) | |||||
const sysUserFormRef = ref<FormInstance>(); | |||||
/** 提交表单 */ | |||||
async function handleSubmit() { | |||||
sysUserFormRef.value?.validate(async valid => { | |||||
if (!valid) return; //表单验证失败 | |||||
sysUserProps.record.name = sysUserProps.record.personSetName; | |||||
//提交表单 | |||||
if (sysUserProps.record.personSetId) { | |||||
sysUserProps.record.id = sysUserProps.record.personSetId; | |||||
await userManageClassManageApi | |||||
.update(sysUserProps.record) | |||||
.then(() => { | |||||
sysUserProps.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} else { | |||||
await userManageClassManageApi | |||||
.add(sysUserProps.record) | |||||
.then(() => { | |||||
sysUserProps.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} | |||||
}); | |||||
} | |||||
/** 关闭表单*/ | |||||
function onClose() { | |||||
visibleClass.value = false; | |||||
} | |||||
// 暴露给父组件的方法 | |||||
defineExpose({ | |||||
onOpen | |||||
}); | |||||
</script> | |||||
<style lang="scss" scoped></style> |
@@ -0,0 +1,116 @@ | |||||
<!-- | |||||
* @Description: 表单 | |||||
* @Author: syy | |||||
* @Date: 2023-12-15 15:45:59 | |||||
--> | |||||
<template> | |||||
<div> | |||||
<form-container v-model="visibleClass" :title="`${sysUserProps.opt}`" form-size="400px" @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="22"> | |||||
<s-form-item label="班主任" prop="userId"> | |||||
<s-select v-model="sysUserProps.record.userId" :options="teacherData" label="name" value="userId"></s-select> | |||||
</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="SysUserPerformClass"> | |||||
import { ref } from "vue"; | |||||
import { SysUserPersonnel, userManageTeacherApi } from "@/api"; | |||||
import { required } from "@/utils/formRules"; | |||||
import { FormInstance } from "element-plus"; | |||||
const teacherData = ref<any>([]); | |||||
const visibleClass = ref(false); //是否显示表单 | |||||
// 表单参数 | |||||
enum FormOptEnum { | |||||
/** 新增 */ | |||||
AddTeacher = "绑定班主任", | |||||
/** 编辑 */ | |||||
UpdateTeacher = "修改班主任" | |||||
} | |||||
const sysUserProps = reactive<FormProps.Base<SysUserPersonnel.ClassPage>>({ | |||||
opt: FormOptEnum.AddTeacher, | |||||
record: {}, | |||||
disabled: false | |||||
}); | |||||
// 表单验证规则 | |||||
const rules = reactive({ | |||||
userId: [required("请选择班主任名称")] | |||||
}); | |||||
/** | |||||
* 打开表单 | |||||
* @param props 表单参数 | |||||
*/ | |||||
function onOpen(props: FormProps.Base<SysUserPersonnel.ClassPage>) { | |||||
getRequestData(); | |||||
Object.assign(sysUserProps, props); //合并参数 | |||||
visibleClass.value = true; //显示表单 | |||||
sysUserProps.record = props.record; | |||||
} | |||||
const getRequestData = async () => { | |||||
const { data } = await userManageTeacherApi.page(); | |||||
teacherData.value = data; | |||||
}; | |||||
// 提交数据(新增/编辑) | |||||
const sysUserFormRef = ref<FormInstance>(); | |||||
/** 提交表单 */ | |||||
async function handleSubmit() { | |||||
sysUserFormRef.value?.validate(async valid => { | |||||
if (!valid) return; //表单验证失败 | |||||
console.log(sysUserProps); | |||||
//提交表单 | |||||
if (sysUserProps.opt === FormOptEnum.UpdateTeacher) { | |||||
await userManageTeacherApi | |||||
.update(sysUserProps.record) | |||||
.then(() => { | |||||
sysUserProps.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} else { | |||||
await userManageTeacherApi | |||||
.add(sysUserProps.record) | |||||
.then(() => { | |||||
sysUserProps.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} | |||||
}); | |||||
} | |||||
/** 关闭表单*/ | |||||
function onClose() { | |||||
visibleClass.value = false; | |||||
} | |||||
// 暴露给父组件的方法 | |||||
defineExpose({ | |||||
onOpen | |||||
}); | |||||
</script> | |||||
<style lang="scss" scoped></style> |
@@ -0,0 +1,206 @@ | |||||
<!-- | |||||
* @Description: 人脸识别失败表格 | |||||
* @Author: yxq | |||||
* @Date: 2023-12-15 15:45:59 | |||||
--> | |||||
<template> | |||||
<div> | |||||
<form-container v-model="visible" :title="`行为轨迹查看`" form-size="1000px" @close="onClose"> | |||||
<ProTable ref="proTable" title="教师点名" height="600px" :data="tableData" :columns="columns"> | |||||
<!-- 表格 header 按钮 --> | |||||
<template #tableHeader> | |||||
<!-- <s-button type="primary" icon="none" prefix="人工" suffix="确认" @click="handleSubmit" /> --> | |||||
</template> | |||||
<!-- 表格操作栏 --> | |||||
<template #operation="scope"> | |||||
<el-space> | |||||
<s-button link :opt="FormOptEnum.EDIT" prefix="人工" suffix="确认" @click="onOpen(FormOptEnum.VIEW, scope.row)" /> | |||||
</el-space> | |||||
</template> | |||||
</ProTable> | |||||
<template #footer> | |||||
<el-button @click="onClose"> 关闭 </el-button> | |||||
</template> | |||||
</form-container> | |||||
<!-- 预览头像 --> | |||||
<el-dialog v-model="imgVisible" title="查看头像" width="830px"> | |||||
<div style="display: flex; align-items: center; justify-content: center"> | |||||
<img class="detailpic" :src="faceUrl" alt="" /> | |||||
</div> | |||||
</el-dialog> | |||||
</div> | |||||
</template> | |||||
<script setup lang="tsx" name="attendancePassenger"> | |||||
import { AttendancePassenger, attendancePassenger } from "@/api"; | |||||
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | |||||
import { FormOptEnum } from "@/enums"; | |||||
const visible = ref(false); //是否显示 | |||||
// 弹框参数 | |||||
const propsInfo = reactive<FormProps.Base<AttendancePassenger.PassengerInfo>>({ | |||||
opt: FormOptEnum.ADD, //操作类型 | |||||
record: {}, //弹框数据 | |||||
disabled: false | |||||
}); | |||||
/** | |||||
* 打开弹框 | |||||
* @param props 弹框参数 | |||||
*/ | |||||
function onOpen(props: FormProps.Base<AttendancePassenger.PassengerInfo>) { | |||||
Object.assign(propsInfo, props); //合并参数 | |||||
if (props.opt == FormOptEnum.ADD) { | |||||
//如果是新增,设置默认值 | |||||
propsInfo.record.shijianduan = []; | |||||
propsInfo.record.shexiangtou = []; | |||||
} | |||||
visible.value = true; //显示弹框 | |||||
if (props.record.id) { | |||||
//如果传了id,就去请求api获取record | |||||
attendancePassenger.detail({ id: props.record.id }).then(res => { | |||||
propsInfo.record = res.data; | |||||
}); | |||||
} | |||||
} | |||||
const tableData = ref([ | |||||
{ | |||||
faces: [ | |||||
{ | |||||
faceUrl: | |||||
"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721375257&OSSAccessKeyId=STS.NTfeBHwzU7kivsSS2EypREace&Signature=c1aTbDc1hNISq%2BV05o0slEfoCTI%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5fTLvj8mqV0gKmCdFXitzIQdf9%2BqqTIhzz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4x49TRng0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxORK3yyybb5sa3aTR6942p%2F%2FF5VxFNPqOx1rmCMf4znuW4yrvNkAVvNcuIqdR8aLhaLIEbHzoKxuEKRnrfsIeBqAAUB%2FCKIuI1UaCj4LYX8DyIYOI8tUKFsMguPHpPENaK9Lcz5ZhB%2BrX6BcQfNWOLhDx7KyRE28vtEs2uolAhLTRaZsZFjbAZE5Ngt09%2FbSXdD%2FR%2BOlGMpQdp752x5lOlvPsJp1skuFLbramyqY4oj4tVwv1OLWpcsEc3AEosPalpAuIAA%3D" | |||||
}, | |||||
], | |||||
time:'2024-07-16 18:20:12', | |||||
name:'大厅(魔豆)', | |||||
}, | |||||
{ | |||||
faces: [ | |||||
{ | |||||
faceUrl: | |||||
"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721375257&OSSAccessKeyId=STS.NTfeBHwzU7kivsSS2EypREace&Signature=c1aTbDc1hNISq%2BV05o0slEfoCTI%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5fTLvj8mqV0gKmCdFXitzIQdf9%2BqqTIhzz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4x49TRng0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxORK3yyybb5sa3aTR6942p%2F%2FF5VxFNPqOx1rmCMf4znuW4yrvNkAVvNcuIqdR8aLhaLIEbHzoKxuEKRnrfsIeBqAAUB%2FCKIuI1UaCj4LYX8DyIYOI8tUKFsMguPHpPENaK9Lcz5ZhB%2BrX6BcQfNWOLhDx7KyRE28vtEs2uolAhLTRaZsZFjbAZE5Ngt09%2FbSXdD%2FR%2BOlGMpQdp752x5lOlvPsJp1skuFLbramyqY4oj4tVwv1OLWpcsEc3AEosPalpAuIAA%3D" | |||||
}, | |||||
], | |||||
time:'2024-07-16 18:20:12', | |||||
name:'教室(海康)', | |||||
}, | |||||
{ | |||||
faces: [ | |||||
{ | |||||
faceUrl: | |||||
"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721375257&OSSAccessKeyId=STS.NTfeBHwzU7kivsSS2EypREace&Signature=c1aTbDc1hNISq%2BV05o0slEfoCTI%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5fTLvj8mqV0gKmCdFXitzIQdf9%2BqqTIhzz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4x49TRng0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxORK3yyybb5sa3aTR6942p%2F%2FF5VxFNPqOx1rmCMf4znuW4yrvNkAVvNcuIqdR8aLhaLIEbHzoKxuEKRnrfsIeBqAAUB%2FCKIuI1UaCj4LYX8DyIYOI8tUKFsMguPHpPENaK9Lcz5ZhB%2BrX6BcQfNWOLhDx7KyRE28vtEs2uolAhLTRaZsZFjbAZE5Ngt09%2FbSXdD%2FR%2BOlGMpQdp752x5lOlvPsJp1skuFLbramyqY4oj4tVwv1OLWpcsEc3AEosPalpAuIAA%3D" | |||||
}, | |||||
], | |||||
time:'2024-07-16 18:20:12', | |||||
name:'大厅(魔豆)', | |||||
}, | |||||
{ | |||||
faces: [ | |||||
{ | |||||
faceUrl: | |||||
"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721375257&OSSAccessKeyId=STS.NTfeBHwzU7kivsSS2EypREace&Signature=c1aTbDc1hNISq%2BV05o0slEfoCTI%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5fTLvj8mqV0gKmCdFXitzIQdf9%2BqqTIhzz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4x49TRng0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxORK3yyybb5sa3aTR6942p%2F%2FF5VxFNPqOx1rmCMf4znuW4yrvNkAVvNcuIqdR8aLhaLIEbHzoKxuEKRnrfsIeBqAAUB%2FCKIuI1UaCj4LYX8DyIYOI8tUKFsMguPHpPENaK9Lcz5ZhB%2BrX6BcQfNWOLhDx7KyRE28vtEs2uolAhLTRaZsZFjbAZE5Ngt09%2FbSXdD%2FR%2BOlGMpQdp752x5lOlvPsJp1skuFLbramyqY4oj4tVwv1OLWpcsEc3AEosPalpAuIAA%3D" | |||||
}, | |||||
], | |||||
time:'2024-07-16 18:20:12', | |||||
name:'教室(海康)', | |||||
}, | |||||
{ | |||||
faces: [ | |||||
{ | |||||
faceUrl: | |||||
"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721375257&OSSAccessKeyId=STS.NTfeBHwzU7kivsSS2EypREace&Signature=c1aTbDc1hNISq%2BV05o0slEfoCTI%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5fTLvj8mqV0gKmCdFXitzIQdf9%2BqqTIhzz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4x49TRng0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxORK3yyybb5sa3aTR6942p%2F%2FF5VxFNPqOx1rmCMf4znuW4yrvNkAVvNcuIqdR8aLhaLIEbHzoKxuEKRnrfsIeBqAAUB%2FCKIuI1UaCj4LYX8DyIYOI8tUKFsMguPHpPENaK9Lcz5ZhB%2BrX6BcQfNWOLhDx7KyRE28vtEs2uolAhLTRaZsZFjbAZE5Ngt09%2FbSXdD%2FR%2BOlGMpQdp752x5lOlvPsJp1skuFLbramyqY4oj4tVwv1OLWpcsEc3AEosPalpAuIAA%3D" | |||||
}, | |||||
], | |||||
time:'2024-07-16 18:20:12', | |||||
name:'大厅(魔豆)', | |||||
} | |||||
]); | |||||
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | |||||
const proTable = ref<ProTableInstance>(); | |||||
// 表格配置项 | |||||
const columns: ColumnProps[] = [ | |||||
{ | |||||
prop: "time", | |||||
label: "经过摄像头时间" | |||||
}, | |||||
{ | |||||
prop: "name", | |||||
label: "摄像头名称", | |||||
}, | |||||
{ | |||||
prop: "faces", | |||||
label: "快照", | |||||
render: scope => { | |||||
return ( | |||||
<img | |||||
src={scope.row.faces.length > 0 ? scope.row.faces[0].faceUrl : ""} | |||||
onClick={() => viewHeadImage(scope)} | |||||
style="width:50px;height:50px;" | |||||
alt="" | |||||
/> | |||||
); | |||||
} | |||||
} | |||||
// { prop: "operation", label: "操作", width: 250, fixed: "right" } | |||||
]; | |||||
// 图片预览 | |||||
const imgVisible = ref(false); | |||||
const faceUrl = ref(''); | |||||
const viewHeadImage = (scope: any) => { | |||||
faceUrl.value = scope.row.faces[0].faceUrl; | |||||
imgVisible.value = true | |||||
}; | |||||
// 刷新表格 | |||||
const RefreshTable = () => { | |||||
proTable.value?.refresh(); | |||||
}; | |||||
// 提交数据(新增/编辑) | |||||
const formRef = ref<FormInstance>(); | |||||
/** 提交表单 */ | |||||
async function handleSubmit() { | |||||
formRef.value?.validate(async valid => { | |||||
if (!valid) return; //表单验证失败 | |||||
// shijianduan时间段 | |||||
propsInfo.record.startTime = formatDate(propsInfo.record.shijianduan[0]); | |||||
propsInfo.record.endTime = formatDate(propsInfo.record.shijianduan[1]); | |||||
delete propsInfo.record.shijianduan; | |||||
// shexiangtou摄像头 | |||||
propsInfo.record.shexiangtou = propsInfo.record.shexiangtou.toString(); | |||||
//提交表单 | |||||
console.log(propsInfo); | |||||
if (propsInfo.record.id) { | |||||
await attendancePassenger | |||||
.update(propsInfo.record) | |||||
.then(() => { | |||||
propsInfo.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} else { | |||||
console.log(propsInfo.record); | |||||
await attendancePassenger | |||||
.add(propsInfo.record) | |||||
.then(() => { | |||||
propsInfo.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} | |||||
}); | |||||
} | |||||
/** 关闭表单*/ | |||||
function onClose() { | |||||
visible.value = false; | |||||
} | |||||
// 暴露给父组件的方法 | |||||
defineExpose({ | |||||
onOpen | |||||
}); | |||||
</script> | |||||
<style lang="scss" scoped></style> | |||||
@@ -1,34 +1,374 @@ | |||||
<!-- | <!-- | ||||
* @Description: 班级管理 | |||||
* @Author: yxq | |||||
* @Date: 2024-7-16 | |||||
* @Description: 人员管理 | |||||
* @Author: syy | |||||
* @Date: 2024-7-15 | |||||
--> | --> | ||||
<template> | <template> | ||||
<div class="table-box"> | |||||
<ProTable ref="proTable" title="班级管理" :columns="columns" :request-api="userManageClassManageApi.page"> </ProTable> | |||||
<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.delete" | |||||
type="danger" | |||||
:opt="FormOptEnum.DELETE" | |||||
plain | |||||
suffix="人员" | |||||
:disabled="!scope.isSelected" | |||||
@click="onDelete(scope.selectedListIds, '删除所选人员')" | |||||
/> --> | |||||
</template> | |||||
<!-- 表格操作栏 --> | |||||
<template #operation="scope"> | |||||
<el-space> | |||||
<s-button link prefix="轨迹" suffix="查看" :opt="FormOptEnum.VIEW" @click="onOpenDetail(FormOptEnum.VIEW, scope.row)" /> | |||||
<!-- <s-button v-auth="userPerButtonCode.edit" link :opt="FormOptEnum.EDIT" @click="onOpen(FormOptEnum.EDIT, scope.row)" /> | |||||
<s-button v-auth="userPerButtonCode.delete" link :opt="FormOptEnum.DELETE" @click="onDelete([scope.row.personId], `删除人员`)" /> | |||||
<el-dropdown @command="handleCommand"> | |||||
<el-link type="primary" :underline="false" :icon="ArrowDown"> 更多 </el-link> | |||||
<template #dropdown> | |||||
<el-dropdown-menu> | |||||
<el-dropdown-item :command="command(scope.row, cmdEnum.AddFace)" | |||||
><el-upload | |||||
ref="upload" | |||||
class="upload-demo" | |||||
action="/api/business/personApi/uploadFile" | |||||
:show-file-list="false" | |||||
:on-success="handleAvatarSuccess" | |||||
accept=".jpg, .jpeg, .png" | |||||
:headers="{ | |||||
Authorization: `${TokenEnum.TOKEN_PREFIX} ${accessToken}` | |||||
}" | |||||
> | |||||
<template #trigger> | |||||
{{ cmdEnum.AddFace }} | |||||
</template> | |||||
</el-upload> | |||||
</el-dropdown-item> | |||||
<el-dropdown-item :command="command(scope.row, cmdEnum.UnderpantsUnBinding)"> | |||||
{{ cmdEnum.UnderpantsUnBinding }} | |||||
</el-dropdown-item> | |||||
</el-dropdown-menu> | |||||
</template> | |||||
</el-dropdown> --> | |||||
</el-space> | |||||
</template> | |||||
</ProTable> | |||||
</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"> | |||||
<img class="detailpic" :src="faceUrl" alt="" /> | |||||
</div> | |||||
</el-dialog> | |||||
<!-- 轨迹详情 --> | |||||
<TraceDetail ref="detialRef" /> | |||||
</div> | </div> | ||||
</template> | </template> | ||||
<script setup lang="ts"> | |||||
import { userManageClassManageApi } from "@/api"; | |||||
<script setup lang="tsx" name="SysUserPersonnel"> | |||||
import { userManagePersonnelApi,userPerButtonCode,SysUserPersonnel,userManageClassManageApi,userManageTeacherApi } from "@/api"; | |||||
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 { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | 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"; | |||||
import TraceDetail from "./components/nofaceTable/index.vue"; | |||||
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | // 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | ||||
const faceUrl = ref(''); | |||||
const visible = ref(false); //是否显示人员表单 | |||||
const proTable = ref<ProTableInstance>(); | const proTable = ref<ProTableInstance>(); | ||||
const treeFilter = ref<InstanceType<typeof TreeFilter> | null>(null); | |||||
const userStore = useUserStore(); | |||||
const { accessToken } = userStore; | |||||
// 表格配置项 | // 表格配置项 | ||||
const columns: ColumnProps[] = [ | |||||
const columns: ColumnProps<SysUserPersonnel.SysUserPerInfo>[] = [ | |||||
{ type: "selection", fixed: "left", width: 50 }, | |||||
{ | { | ||||
prop: "personSetName", | |||||
label: "班级名称" | |||||
prop: "faceUrl", | |||||
label: "人脸", | |||||
render: scope => { | |||||
return ( | |||||
<img src={scope.row.faces.length > 0 ? scope.row.faces[0].faceUrl : ''} onClick={() => viewHeadImage(scope)} style='width:50px;height:50px;' alt=''/> | |||||
); | |||||
} | |||||
}, | }, | ||||
{ | { | ||||
prop: "personSetId", | |||||
label: "班级ID" | |||||
prop: "name", | |||||
label: "姓名" | |||||
}, | |||||
{ | |||||
prop: "personId", | |||||
label: "人员ID" | |||||
}, | |||||
{ | |||||
prop: "phone", | |||||
label: "手机号" | |||||
}, | |||||
{ | |||||
prop: "personSets", | |||||
label: "所属班级", | |||||
render: scope => { | |||||
return scope.row.personSets.length > 0 ? scope.row.personSets[0].personSetName : '' | |||||
} | |||||
}, | }, | ||||
{ prop: "operation", label: "操作", width: 250, fixed: "right" } | { prop: "operation", label: "操作", width: 250, fixed: "right" } | ||||
]; | ]; | ||||
const viewHeadImage = (scope: any) => { | |||||
faceUrl.value = scope.row.faces[0].faceUrl; | |||||
visible.value = true | |||||
console.log(faceUrl); | |||||
}; | |||||
const handleClose = () => { | |||||
visible.value = false; | |||||
}; | |||||
// 人员表单引用 | |||||
const formRef = ref<InstanceType<typeof Form> | null>(null); | |||||
// 班级表单引用 | |||||
const formRefC = ref<InstanceType<typeof FormClass> | null>(null); | |||||
// 班级表单引用 | |||||
const formRefT = ref<InstanceType<typeof FormTeacher> | null>(null); | |||||
/** | |||||
* 打开表单 | |||||
* @param opt 操作类型 | |||||
* @param record 记录 | |||||
*/ | |||||
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数组 | |||||
*/ | |||||
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(); | |||||
treeFilter.value?.refresh(); //刷新树形筛选器 | |||||
} | |||||
/** 更多下拉菜单命令枚举 */ | |||||
enum cmdEnum { | |||||
AddFace = "添加人脸", | |||||
UnderpantsUnBinding = "底库解绑" | |||||
} | |||||
/** 下拉菜单参数接口 */ | |||||
interface Command { | |||||
row: SysUserPersonnel.SysUserPerInfo; | |||||
command: cmdEnum; | |||||
} | |||||
/**配置command的参数 */ | |||||
function command(row: SysUserPersonnel.SysUserPerInfo, command: cmdEnum): Command { | |||||
return { | |||||
row: row, | |||||
command: command | |||||
}; | |||||
} | |||||
/** | |||||
* 列表更多下拉菜单点击事件 | |||||
* @param command | |||||
*/ | |||||
const personId = ref<number | string>(); //人员id | |||||
function handleCommand(command: Command) { | |||||
switch (command.command) { | |||||
case cmdEnum.AddFace: | |||||
personId.value = command.row.personId; //获取人员id | |||||
break | |||||
case cmdEnum.UnderpantsUnBinding: | |||||
userManagePersonnelApi.personUnBindDfie({ | |||||
personId:command.row.personId, | |||||
personSetId: command.row.personSets[0].personSetId | |||||
}).then(res=>{ | |||||
ElMessage.success('底库解绑成功'); | |||||
RefreshTable() | |||||
}) | |||||
break; | |||||
} | |||||
} | |||||
/** 更多下拉菜单命令枚举 */ | |||||
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({ | |||||
personId: personId.value, | |||||
faceUrl: response.data | |||||
}).then(res=>{ | |||||
RefreshTable() | |||||
}) | |||||
} else { | |||||
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(); | |||||
} | |||||
const detialRef = ref<InstanceType<typeof TraceDetail> | null>(null); | |||||
/** | |||||
* 详情 | |||||
* @param opt 操作类型 | |||||
* @param record 弹框数据 | |||||
*/ | |||||
function onOpenDetail(opt: FormOptEnum, record: {} | AttendanceStudentsReturn.studentsReturnInfo = {}) { | |||||
switch (opt) { | |||||
case FormOptEnum.VIEW: | |||||
detialRef.value?.onOpen({ opt: opt, record: record, successful: RefreshTable }); | |||||
break; | |||||
} | |||||
} | |||||
</script> | </script> | ||||
<style scoped lang="scss"> | <style scoped lang="scss"> | ||||
.table-box { | .table-box { | ||||
width: 100%; | width: 100%; | ||||
height: 100%; | height: 100%; | ||||
} | } | ||||
.custom-tree-node { | |||||
display: flex; | |||||
flex: 1; | |||||
align-items: center; | |||||
justify-content: space-between; | |||||
padding-right: 8px; | |||||
font-size: 14px; | |||||
} | |||||
</style> | </style> |
@@ -5,23 +5,23 @@ | |||||
--> | --> | ||||
<template> | <template> | ||||
<div> | <div> | ||||
<form-container v-model="visible" :title="`${formProps.opt}查询`" form-size="600px" @close="onClose"> | |||||
<form-container v-model="visible" :title="`${propsInfo.opt}查询`" form-size="600px" @close="onClose"> | |||||
<el-form | <el-form | ||||
ref="formRef" | ref="formRef" | ||||
:rules="rules" | :rules="rules" | ||||
:disabled="formProps.disabled" | |||||
:model="formProps.record" | |||||
:hide-required-asterisk="formProps.disabled" | |||||
:disabled="propsInfo.disabled" | |||||
:model="propsInfo.record" | |||||
:hide-required-asterisk="propsInfo.disabled" | |||||
label-width="auto" | label-width="auto" | ||||
label-suffix=" :" | label-suffix=" :" | ||||
> | > | ||||
<el-tabs v-model="activeName"> | <el-tabs v-model="activeName"> | ||||
<Basic v-model="formProps.record"></Basic> | |||||
<Basic v-model="propsInfo.record"></Basic> | |||||
</el-tabs> | </el-tabs> | ||||
</el-form> | </el-form> | ||||
<template #footer> | <template #footer> | ||||
<el-button @click="onClose"> 取消 </el-button> | <el-button @click="onClose"> 取消 </el-button> | ||||
<el-button v-show="!formProps.disabled" type="primary" @click="handleSubmit"> 确定 </el-button> | |||||
<el-button v-show="!propsInfo.disabled" type="primary" @click="handleSubmit"> 确定 </el-button> | |||||
</template> | </template> | ||||
</form-container> | </form-container> | ||||
</div> | </div> | ||||
@@ -37,8 +37,8 @@ import { formatDate } from "@/utils"; | |||||
const visible = ref(false); //是否显示表单 | const visible = ref(false); //是否显示表单 | ||||
const activeName = ref("basic"); | const activeName = ref("basic"); | ||||
// 表单参数 | |||||
const formProps = reactive<FormProps.Base<AttendancePassenger.PassengerInfo>>({ | |||||
// 弹框参数 | |||||
const propsInfo = reactive<FormProps.Base<AttendancePassenger.PassengerInfo>>({ | |||||
opt: FormOptEnum.ADD, | opt: FormOptEnum.ADD, | ||||
record: {}, | record: {}, | ||||
disabled: false | disabled: false | ||||
@@ -68,17 +68,17 @@ const rules = reactive({ | |||||
* @param props 表单参数 | * @param props 表单参数 | ||||
*/ | */ | ||||
function onOpen(props: FormProps.Base<AttendancePassenger.PassengerInfo>) { | function onOpen(props: FormProps.Base<AttendancePassenger.PassengerInfo>) { | ||||
Object.assign(formProps, props); //合并参数 | |||||
Object.assign(propsInfo, props); //合并参数 | |||||
if (props.opt == FormOptEnum.ADD) { | if (props.opt == FormOptEnum.ADD) { | ||||
//如果是新增,设置默认值 | //如果是新增,设置默认值 | ||||
formProps.record.shijianduan = []; | |||||
formProps.record.shexiangtou = []; | |||||
propsInfo.record.shijianduan = []; | |||||
propsInfo.record.shexiangtou = []; | |||||
} | } | ||||
visible.value = true; //显示表单 | visible.value = true; //显示表单 | ||||
if (props.record.id) { | if (props.record.id) { | ||||
//如果传了id,就去请求api获取record | //如果传了id,就去请求api获取record | ||||
attendancePassenger.detail({ id: props.record.id }).then(res => { | attendancePassenger.detail({ id: props.record.id }).then(res => { | ||||
formProps.record = res.data; | |||||
propsInfo.record = res.data; | |||||
}); | }); | ||||
} | } | ||||
} | } | ||||
@@ -87,37 +87,14 @@ function onOpen(props: FormProps.Base<AttendancePassenger.PassengerInfo>) { | |||||
const formRef = ref<FormInstance>(); | const formRef = ref<FormInstance>(); | ||||
/** 提交表单 */ | /** 提交表单 */ | ||||
async function handleSubmit() { | async function handleSubmit() { | ||||
formRef.value?.validate(async valid => { | |||||
if (!valid) return; //表单验证失败 | |||||
// shijianduan时间段 | |||||
formProps.record.startTime = formatDate(formProps.record.shijianduan[0]); | |||||
formProps.record.endTime = formatDate(formProps.record.shijianduan[1]); | |||||
delete formProps.record.shijianduan; | |||||
// shexiangtou摄像头 | |||||
formProps.record.shexiangtou = formProps.record.shexiangtou.toString(); | |||||
//提交表单 | |||||
console.log(formProps); | |||||
if (formProps.record.id) { | |||||
await attendancePassenger | |||||
.update(formProps.record) | |||||
.then(() => { | |||||
formProps.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} else { | |||||
console.log(formProps.record); | |||||
await attendancePassenger | |||||
.add(formProps.record) | |||||
.then(() => { | |||||
formProps.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} | |||||
}); | |||||
await attendancePassenger | |||||
.update(propsInfo.record) | |||||
.then(() => { | |||||
propsInfo.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} | } | ||||
/** 关闭表单*/ | /** 关闭表单*/ | ||||
@@ -5,7 +5,7 @@ | |||||
--> | --> | ||||
<template> | <template> | ||||
<div class="table-box"> | <div class="table-box"> | ||||
<ProTable ref="proTable" title="查询管理" :columns="columns" :data="data" :request-api="attendancePassenger.page"> | |||||
<ProTable ref="proTable" title="查询管理" :columns="columns" :data="data"> | |||||
<!-- 表格 header 按钮 --> | <!-- 表格 header 按钮 --> | ||||
<template #tableHeader> | <template #tableHeader> | ||||
<s-button v-auth="attendancePassengerBtnCode.add" type="primary" suffix="查询" @click="onOpen(FormOptEnum.ADD)" /> | <s-button v-auth="attendancePassengerBtnCode.add" type="primary" suffix="查询" @click="onOpen(FormOptEnum.ADD)" /> | ||||
@@ -0,0 +1,198 @@ | |||||
<!-- | |||||
* @Description: 人脸识别失败表格 | |||||
* @Author: yxq | |||||
* @Date: 2023-12-15 15:45:59 | |||||
--> | |||||
<template> | |||||
<div> | |||||
<form-container v-model="visible" :title="`${propsInfo.record.classname}人脸未识别确认`" form-size="1000px" @close="onClose"> | |||||
<ProTable ref="proTable" title="教师点名" height="600px" :data="tableData" :columns="columns"> | |||||
<!-- 表格 header 按钮 --> | |||||
<template #tableHeader> | |||||
<s-button type="primary" icon="check" prefix="人工" suffix="确认" @click="handleSubmit" /> | |||||
</template> | |||||
<!-- 表格操作栏 --> | |||||
<template #operation="scope"> | |||||
<el-space> | |||||
<s-button link :opt="FormOptEnum.EDIT" prefix="人工" suffix="确认" @click="onOpen(FormOptEnum.VIEW, scope.row)" /> | |||||
</el-space> | |||||
</template> | |||||
</ProTable> | |||||
<template #footer> | |||||
<el-button @click="onClose"> 关闭 </el-button> | |||||
</template> | |||||
</form-container> | |||||
<!-- 预览头像 --> | |||||
<el-dialog v-model="imgVisible" title="查看头像" width="830px"> | |||||
<div style="display: flex; align-items: center; justify-content: center"> | |||||
<img class="detailpic" :src="faceUrl" alt="" /> | |||||
</div> | |||||
</el-dialog> | |||||
</div> | |||||
</template> | |||||
<script setup lang="tsx" name="attendancePassenger"> | |||||
import { AttendancePassenger, attendancePassenger } from "@/api"; | |||||
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | |||||
import { FormOptEnum } from "@/enums"; | |||||
const visible = ref(false); //是否显示 | |||||
// 弹框参数 | |||||
const propsInfo = reactive<FormProps.Base<AttendancePassenger.PassengerInfo>>({ | |||||
opt: FormOptEnum.ADD, //操作类型 | |||||
record: {}, //弹框数据 | |||||
disabled: false | |||||
}); | |||||
/** | |||||
* 打开弹框 | |||||
* @param props 弹框参数 | |||||
*/ | |||||
function onOpen(props: FormProps.Base<AttendancePassenger.PassengerInfo>) { | |||||
Object.assign(propsInfo, props); //合并参数 | |||||
if (props.opt == FormOptEnum.ADD) { | |||||
//如果是新增,设置默认值 | |||||
propsInfo.record.shijianduan = []; | |||||
propsInfo.record.shexiangtou = []; | |||||
} | |||||
visible.value = true; //显示弹框 | |||||
if (props.record.id) { | |||||
//如果传了id,就去请求api获取record | |||||
attendancePassenger.detail({ id: props.record.id }).then(res => { | |||||
propsInfo.record = res.data; | |||||
}); | |||||
} | |||||
} | |||||
const tableData = ref([ | |||||
{ | |||||
studentname: "张三", | |||||
faces: [ | |||||
{ | |||||
faceUrl: | |||||
"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721375257&OSSAccessKeyId=STS.NTfeBHwzU7kivsSS2EypREace&Signature=c1aTbDc1hNISq%2BV05o0slEfoCTI%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5fTLvj8mqV0gKmCdFXitzIQdf9%2BqqTIhzz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4x49TRng0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxORK3yyybb5sa3aTR6942p%2F%2FF5VxFNPqOx1rmCMf4znuW4yrvNkAVvNcuIqdR8aLhaLIEbHzoKxuEKRnrfsIeBqAAUB%2FCKIuI1UaCj4LYX8DyIYOI8tUKFsMguPHpPENaK9Lcz5ZhB%2BrX6BcQfNWOLhDx7KyRE28vtEs2uolAhLTRaZsZFjbAZE5Ngt09%2FbSXdD%2FR%2BOlGMpQdp752x5lOlvPsJp1skuFLbramyqY4oj4tVwv1OLWpcsEc3AEosPalpAuIAA%3D" | |||||
}, | |||||
], | |||||
}, | |||||
{ | |||||
studentname: "李四", | |||||
faces: [ | |||||
{ | |||||
faceUrl: | |||||
"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721375257&OSSAccessKeyId=STS.NTfeBHwzU7kivsSS2EypREace&Signature=c1aTbDc1hNISq%2BV05o0slEfoCTI%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5fTLvj8mqV0gKmCdFXitzIQdf9%2BqqTIhzz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4x49TRng0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxORK3yyybb5sa3aTR6942p%2F%2FF5VxFNPqOx1rmCMf4znuW4yrvNkAVvNcuIqdR8aLhaLIEbHzoKxuEKRnrfsIeBqAAUB%2FCKIuI1UaCj4LYX8DyIYOI8tUKFsMguPHpPENaK9Lcz5ZhB%2BrX6BcQfNWOLhDx7KyRE28vtEs2uolAhLTRaZsZFjbAZE5Ngt09%2FbSXdD%2FR%2BOlGMpQdp752x5lOlvPsJp1skuFLbramyqY4oj4tVwv1OLWpcsEc3AEosPalpAuIAA%3D" | |||||
}, | |||||
], | |||||
}, | |||||
{ | |||||
studentname: "张三", | |||||
faces: [ | |||||
{ | |||||
faceUrl: | |||||
"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721375257&OSSAccessKeyId=STS.NTfeBHwzU7kivsSS2EypREace&Signature=c1aTbDc1hNISq%2BV05o0slEfoCTI%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5fTLvj8mqV0gKmCdFXitzIQdf9%2BqqTIhzz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4x49TRng0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxORK3yyybb5sa3aTR6942p%2F%2FF5VxFNPqOx1rmCMf4znuW4yrvNkAVvNcuIqdR8aLhaLIEbHzoKxuEKRnrfsIeBqAAUB%2FCKIuI1UaCj4LYX8DyIYOI8tUKFsMguPHpPENaK9Lcz5ZhB%2BrX6BcQfNWOLhDx7KyRE28vtEs2uolAhLTRaZsZFjbAZE5Ngt09%2FbSXdD%2FR%2BOlGMpQdp752x5lOlvPsJp1skuFLbramyqY4oj4tVwv1OLWpcsEc3AEosPalpAuIAA%3D" | |||||
}, | |||||
], | |||||
}, | |||||
{ | |||||
studentname: "李四", | |||||
faces: [ | |||||
{ | |||||
faceUrl: | |||||
"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721375257&OSSAccessKeyId=STS.NTfeBHwzU7kivsSS2EypREace&Signature=c1aTbDc1hNISq%2BV05o0slEfoCTI%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5fTLvj8mqV0gKmCdFXitzIQdf9%2BqqTIhzz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4x49TRng0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxORK3yyybb5sa3aTR6942p%2F%2FF5VxFNPqOx1rmCMf4znuW4yrvNkAVvNcuIqdR8aLhaLIEbHzoKxuEKRnrfsIeBqAAUB%2FCKIuI1UaCj4LYX8DyIYOI8tUKFsMguPHpPENaK9Lcz5ZhB%2BrX6BcQfNWOLhDx7KyRE28vtEs2uolAhLTRaZsZFjbAZE5Ngt09%2FbSXdD%2FR%2BOlGMpQdp752x5lOlvPsJp1skuFLbramyqY4oj4tVwv1OLWpcsEc3AEosPalpAuIAA%3D" | |||||
}, | |||||
], | |||||
}, | |||||
{ | |||||
studentname: "张三", | |||||
faces: [ | |||||
{ | |||||
faceUrl: | |||||
"http://deepvision.oss-cn-zhangjiakou.aliyuncs.com/dfield-cruising/online/person-set/quanjiang/DEMO00001/8746a847ecd64c1696b37f4cdf617a18/5dc35e4c7af84b3fb5aab70156574873.jpg?Expires=1721375257&OSSAccessKeyId=STS.NTfeBHwzU7kivsSS2EypREace&Signature=c1aTbDc1hNISq%2BV05o0slEfoCTI%3D&security-token=CAIS0wN1q6Ft5B2yfSjIr5fTLvj8mqV0gKmCdFXitzIQdf9%2BqqTIhzz2IHFMf3huCeodsv8%2BlGxS5%2FgelrpqVpZDR03Na8RHwrly1lv5O9KY4x49TRng0s%2FLI3OaLjKm9hi7AYygPgK0GJqEb1TDiVUto9%2FTfimjWFqIKICAjYUdAP0cQgi%2Fa0gwZrJRPRAwh8IGEnHTOP2xUHvtmXGCNFd0nQB%2BhGhjk7TdpPeR8R3Dllb35%2FYIroDqWPieYtJrIY10XqWBvqx%2FfbGT1zVLuVoYtvV6gaFc5zbcv9abRFVf4hiCP6%2Ff6MBuNw5%2Fae94efZNp%2BOukuZj6K6B1db7xhtVI%2BBOUiPZA4mr2IzdBeqvNNcwc7m8F1no9YjXbsGs9EEGGStLaVgVI4F8dyAhWEd9FWjgR%2FX5qAyQUGCKULOY1aw6651xwmjz8MCCT1r1GOTBindGasVnMxh5Z0JMjDK9aNkKfgFUbVJ8BrGTCIh%2FYx0bsq7yowDIEyp71TRMo%2Bbu%2FDBhIifKpO4VN7AxMup1DPwu2wNCxORK3yyybb5sa3aTR6942p%2F%2FF5VxFNPqOx1rmCMf4znuW4yrvNkAVvNcuIqdR8aLhaLIEbHzoKxuEKRnrfsIeBqAAUB%2FCKIuI1UaCj4LYX8DyIYOI8tUKFsMguPHpPENaK9Lcz5ZhB%2BrX6BcQfNWOLhDx7KyRE28vtEs2uolAhLTRaZsZFjbAZE5Ngt09%2FbSXdD%2FR%2BOlGMpQdp752x5lOlvPsJp1skuFLbramyqY4oj4tVwv1OLWpcsEc3AEosPalpAuIAA%3D" | |||||
}, | |||||
], | |||||
} | |||||
]); | |||||
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | |||||
const proTable = ref<ProTableInstance>(); | |||||
// 表格配置项 | |||||
const columns: ColumnProps[] = [ | |||||
{ type: "selection" }, | |||||
{ | |||||
prop: "studentname", | |||||
label: "学生姓名" | |||||
}, | |||||
{ | |||||
prop: "faces", | |||||
label: "人脸", | |||||
render: scope => { | |||||
return ( | |||||
<img | |||||
src={scope.row.faces.length > 0 ? scope.row.faces[0].faceUrl : ""} | |||||
onClick={() => viewHeadImage(scope)} | |||||
style="width:50px;height:50px;cursor:pointer" | |||||
alt="" | |||||
/> | |||||
); | |||||
} | |||||
} | |||||
// { prop: "operation", label: "操作", width: 250, fixed: "right" } | |||||
]; | |||||
// 图片预览 | |||||
const imgVisible = ref(false); | |||||
const faceUrl = ref(''); | |||||
const viewHeadImage = (scope: any) => { | |||||
faceUrl.value = scope.row.faces[0].faceUrl; | |||||
imgVisible.value = true | |||||
}; | |||||
// 刷新表格 | |||||
const RefreshTable = () => { | |||||
proTable.value?.refresh(); | |||||
}; | |||||
// 提交数据(新增/编辑) | |||||
const formRef = ref<FormInstance>(); | |||||
/** 提交表单 */ | |||||
async function handleSubmit() { | |||||
formRef.value?.validate(async valid => { | |||||
if (!valid) return; //表单验证失败 | |||||
// shijianduan时间段 | |||||
propsInfo.record.startTime = formatDate(propsInfo.record.shijianduan[0]); | |||||
propsInfo.record.endTime = formatDate(propsInfo.record.shijianduan[1]); | |||||
delete propsInfo.record.shijianduan; | |||||
// shexiangtou摄像头 | |||||
propsInfo.record.shexiangtou = propsInfo.record.shexiangtou.toString(); | |||||
//提交表单 | |||||
console.log(propsInfo); | |||||
if (propsInfo.record.id) { | |||||
await attendancePassenger | |||||
.update(propsInfo.record) | |||||
.then(() => { | |||||
propsInfo.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} else { | |||||
console.log(propsInfo.record); | |||||
await attendancePassenger | |||||
.add(propsInfo.record) | |||||
.then(() => { | |||||
propsInfo.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} | |||||
}); | |||||
} | |||||
/** 关闭表单*/ | |||||
function onClose() { | |||||
visible.value = false; | |||||
} | |||||
// 暴露给父组件的方法 | |||||
defineExpose({ | |||||
onOpen | |||||
}); | |||||
</script> | |||||
<style lang="scss" scoped></style> | |||||
@@ -1,30 +1,85 @@ | |||||
<!-- | <!-- | ||||
* @Description: 班级管理 | |||||
* @Description: 教师点名 | |||||
* @Author: yxq | * @Author: yxq | ||||
* @Date: 2024-7-16 | * @Date: 2024-7-16 | ||||
--> | --> | ||||
<template> | <template> | ||||
<div class="table-box"> | <div class="table-box"> | ||||
<ProTable ref="proTable" title="班级管理" :columns="columns" :request-api="userManageClassManageApi.page"> </ProTable> | |||||
<ProTable ref="proTable" title="教师点名" :columns="columns" :data="data"> | |||||
<!-- 表格操作栏 --> | |||||
<template #operation="scope"> | |||||
<el-space> | |||||
<s-button link prefix="人工" :opt="FormOptEnum.EDIT" suffix="确认" @click="onOpen(FormOptEnum.VIEW, scope.row)" /> | |||||
</el-space> | |||||
</template> | |||||
</ProTable> | |||||
<FaceConfirm ref="FaceConfirmRef" /> | |||||
</div> | </div> | ||||
</template> | </template> | ||||
<script setup lang="ts"> | <script setup lang="ts"> | ||||
import { userManageClassManageApi } from "@/api"; | |||||
import { attendanceStudentsReturn, AttendanceStudentsReturn } from "@/api"; | |||||
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | ||||
import { FormOptEnum } from "@/enums"; | |||||
import FaceConfirm from "./components/nofaceTable/index.vue"; | |||||
const data = ref([ | |||||
{ | |||||
classname: "XXXXX班级", | |||||
classId: "544165", | |||||
studentNum: "43", | |||||
guiqinNum: "38", | |||||
noFaceNum: "5" | |||||
}, | |||||
{ | |||||
classname: "XX班级", | |||||
classId: "555333", | |||||
studentNum: "42", | |||||
guiqinNum: "37", | |||||
noFaceNum: "5" | |||||
} | |||||
]); | |||||
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | // 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | ||||
const proTable = ref<ProTableInstance>(); | const proTable = ref<ProTableInstance>(); | ||||
// 表格配置项 | // 表格配置项 | ||||
const columns: ColumnProps[] = [ | const columns: ColumnProps[] = [ | ||||
{ | { | ||||
prop: "personSetName", | |||||
prop: "classname", | |||||
label: "班级名称" | label: "班级名称" | ||||
}, | }, | ||||
{ | { | ||||
prop: "personSetId", | |||||
prop: "classId", | |||||
label: "班级ID" | label: "班级ID" | ||||
}, | }, | ||||
{ | |||||
prop: "studentNum", | |||||
label: "学生人数" | |||||
}, | |||||
{ | |||||
prop: "guiqinNum", | |||||
label: "归寝人数" | |||||
}, | |||||
{ | |||||
prop: "noFaceNum", | |||||
label: "人脸无法识别人数" | |||||
}, | |||||
{ prop: "operation", label: "操作", width: 250, fixed: "right" } | { prop: "operation", label: "操作", width: 250, fixed: "right" } | ||||
]; | ]; | ||||
const FaceConfirmRef = ref<InstanceType<typeof FaceConfirm> | null>(null); | |||||
/** | |||||
* 打开弹框 | |||||
* @param opt 操作类型 | |||||
* @param record 弹框数据 | |||||
*/ | |||||
function onOpen(opt: FormOptEnum, record: {} | AttendanceStudentsReturn.studentsReturnInfo = {}) { | |||||
switch (opt) { | |||||
case FormOptEnum.VIEW: | |||||
FaceConfirmRef.value?.onOpen({ opt: opt, record: record, successful: RefreshTable }); | |||||
break; | |||||
} | |||||
} | |||||
// 刷新表格 | |||||
const RefreshTable = () => { | |||||
proTable.value?.refresh(); | |||||
}; | |||||
</script> | </script> | ||||
<style scoped lang="scss"> | <style scoped lang="scss"> | ||||
.table-box { | .table-box { | ||||