diff --git a/SafeCampus.WEB/.env.development b/SafeCampus.WEB/.env.development index 000f01b..20a42a9 100644 --- a/SafeCampus.WEB/.env.development +++ b/SafeCampus.WEB/.env.development @@ -23,5 +23,5 @@ VITE_HTTP_PROXY = true # 开发环境跨域代理,支持配置多个 # VITE_PROXY = [["/api","http://192.168.10.186:5566","/Files"]] -VITE_PROXY = [["/api","http://192.168.10.186:8003"],["/Files","artc://rts-pull-live.deepeleph.com"]] +VITE_PROXY = [["/api","http://192.168.10.186:8003"],["/Files","http://192.168.10.186:8003/Files"]] diff --git a/SafeCampus.WEB/src/api/interface/sys/usermanage/dormitory.ts b/SafeCampus.WEB/src/api/interface/sys/usermanage/dormitory.ts index c521a1a..3a42e51 100644 --- a/SafeCampus.WEB/src/api/interface/sys/usermanage/dormitory.ts +++ b/SafeCampus.WEB/src/api/interface/sys/usermanage/dormitory.ts @@ -26,6 +26,8 @@ export namespace SysDormitory { name?: string | undefined; gender?: boolean | undefined; createTime?: string | undefined; + insCameraId?: string | number | undefined; + outCameraId?: string | number | undefined; } // 寝室列表传参 export interface Page extends ReqPage { diff --git a/SafeCampus.WEB/src/components/Form/SSelect/index.vue b/SafeCampus.WEB/src/components/Form/SSelect/index.vue index bb6c5f8..5f30caa 100644 --- a/SafeCampus.WEB/src/components/Form/SSelect/index.vue +++ b/SafeCampus.WEB/src/components/Form/SSelect/index.vue @@ -4,7 +4,7 @@ * @Date: 2023-12-15 15:38:32 !--> <template> - <el-select :placeholder="placeholder" class="w-full" v-bind="$attrs" clearable> + <el-select :placeholder="placeholder" :filterable="filterable" class="w-full" v-bind="$attrs" clearable> <el-option v-for="(item, index) in options" :key="index" :label="item[props.label]" :value="item[props.value]" /> </el-select> </template> @@ -20,7 +20,8 @@ const props = withDefaults(defineProps<SSelectProps>(), { options: [] as any, value: "value", label: "label", - button: false + button: false, + filterable: false //是否可搜索 }); const placeholder = computed(() => { diff --git a/SafeCampus.WEB/src/components/Form/SSelect/interface.ts b/SafeCampus.WEB/src/components/Form/SSelect/interface.ts index cab77e7..e54615f 100644 --- a/SafeCampus.WEB/src/components/Form/SSelect/interface.ts +++ b/SafeCampus.WEB/src/components/Form/SSelect/interface.ts @@ -21,4 +21,5 @@ export interface SSelectProps { label?: string; /** 选项值 */ value?: string; + filterable?: boolean; } diff --git a/SafeCampus.WEB/src/components/ProTable/index.vue b/SafeCampus.WEB/src/components/ProTable/index.vue index d4fed30..822aa8c 100644 --- a/SafeCampus.WEB/src/components/ProTable/index.vue +++ b/SafeCampus.WEB/src/components/ProTable/index.vue @@ -20,7 +20,15 @@ </div> </div> <!-- 表格主体 --> - <el-table ref="tableRef" v-bind="$attrs" :data="processTableData" :border="border" :row-key="rowKey" @selection-change="selectionChange"> + <el-table + ref="tableRef" + v-bind="$attrs" + :data="processTableData" + :border="border" + :max-height="maxHeight" + :row-key="rowKey" + @selection-change="selectionChange" + > <!-- 默认插槽 --> <slot /> <template v-for="item in tableColumns" :key="item"> @@ -113,6 +121,7 @@ export interface ProTableProps { rowKey?: string; // 行数据的 Key,用来优化 Table 的渲染,当表格数据多选时,所指定的 id ==> 非必传(默认为 id) searchCol?: number | Record<BreakPoint, number>; // 表格搜索项 每列占比配置 ==> 非必传 { xs: 1, sm: 2, md: 2, lg: 3, xl: 4 } pagerCount?: number; // 分页组件显示最大页码按钮数 ==> 非必传(默认为7) + maxHeight?: number | string; } // 接受父组件参数,配置默认值 diff --git a/SafeCampus.WEB/src/components/Selectors/ClassUserselector/index.vue b/SafeCampus.WEB/src/components/Selectors/ClassUserselector/index.vue index 3adb10d..84f096b 100644 --- a/SafeCampus.WEB/src/components/Selectors/ClassUserselector/index.vue +++ b/SafeCampus.WEB/src/components/Selectors/ClassUserselector/index.vue @@ -52,7 +52,7 @@ </el-tabs> </el-col> <el-col :span="10"> - <ProTable ref="userTable" :columns="columns" :tool-button="false" :init-param="initParam" :request-api="userSelectorApi"> + <ProTable ref="userTable" :columns="columns" maxHeight="480" :tool-button="false" :init-param="initParam" :request-api="userSelectorApi"> <!-- 表格 header 按钮 --> <template #tableHeader="scope"> <el-button type="primary" @click="addRecords(userTable!.tableData)">添加当前</el-button> @@ -65,7 +65,15 @@ </ProTable> </el-col> <el-col :span="10"> - <ProTable ref="chooseTable" :columns="columns" :tool-button="true" :data="chooseDataTmp" @search="searchRecords" @reset="resetRecords"> + <ProTable + ref="chooseTable" + :columns="columns" + maxHeight="480" + :tool-button="true" + :data="chooseDataTmp" + @search="searchRecords" + @reset="resetRecords" + > <!-- 表格 header 按钮 --> <template #tableHeader="scope"> <el-button type="danger" @click="delRecords(chooseTable!.tableData)">删除当前</el-button> @@ -84,12 +92,18 @@ </el-row> </div> <template #footer> - <div class="mt-20px"> + <div> <el-button @click="onClose"> 取消 </el-button> <el-button type="primary" @click="handleOk"> 确定 </el-button> </div> </template> </form-container> + <!-- 预览头像 --> + <el-dialog v-model="imgVisible" title="查看头像" width="830px" :before-close="handleClose"> + <div style="display: flex; align-items: center; justify-content: center"> + <img style="max-width: 100%; max-height: 600px" class="detailpic" :src="faceUrl" alt="" /> + </div> + </el-dialog> </template> <script setup lang="tsx" name="UserSelector"> @@ -104,7 +118,16 @@ const emit = defineEmits({ successful: null }); // 自定义事件 // console.log(tab, event); // }; const visible = ref(false); //是否显示 - +const imgVisible = ref(false); //是否显示寝室表单 +const faceUrl = ref(''); +const viewHeadImage = (scope: any) => { + faceUrl.value = scope.row.faces[0].faceUrl; + imgVisible.value = true + console.log(faceUrl); +}; +const handleClose = () => { + imgVisible.value = false; +}; // 定义组件props const props = withDefaults(defineProps<UserSelectProps>(), { multiple: false, @@ -112,7 +135,7 @@ const props = withDefaults(defineProps<UserSelectProps>(), { }); // 根据是否业务显示不同名称 -const userName = props.biz ? "人员" : "用户"; +const userName = props.biz ? "用户" : "人员"; const positionName = props.biz ? "职位" : "岗位"; const orgName = props.biz ? "机构" : "班级"; @@ -132,7 +155,7 @@ const columns: ColumnProps<SysUser.SysUserInfo>[] = [ 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=''/> + <img src={scope.row.faces.length > 0 ? scope.row.faces[0].faceUrl : ''} onClick={() => viewHeadImage(scope)} style='width:30px;height:30px;' alt=''/> ); } }, @@ -162,6 +185,10 @@ function onClose() { /** 提交数据 */ function handleOk() { + if (chooseData.value.length == 0) { + ElMessage.warning("请选择" + userName); + return; + } visible.value = false; console.log(chooseData.value,'提交得数据') emit("successful", chooseData.value); diff --git a/SafeCampus.WEB/src/views/home/index.vue b/SafeCampus.WEB/src/views/home/index.vue index 83e372a..d8e655f 100644 --- a/SafeCampus.WEB/src/views/home/index.vue +++ b/SafeCampus.WEB/src/views/home/index.vue @@ -158,7 +158,7 @@ function getDataChart() { }); }); } -function getCharts1(data) { +function getCharts1(data: any) { const chart = echarts.init(chart1.value); const option = { tooltip: { @@ -208,7 +208,7 @@ function getCharts1(data) { chart.resize(); }); } -function getCharts2(data) { +function getCharts2(data: any) { const chartstation = echarts.init(chart2.value); const option = { tooltip: { @@ -261,22 +261,22 @@ function getCharts2(data) { function getWeekData() { setTimeout(async () => { - await statistionApi.weekstatistion({}).then(res => { + await statistionApi.weekstatistion({}).then((res: any) => { let { code, data } = res; if (code == 200) { // let chartData = data; let time = data.dataX; - let chartData = data.dataY.map(item => { + let chartData = data.dataY.map((item: any) => { return { data: item.data, name: item.name, type: "bar", barWidth: "12px", // 设置柱子粗细 itemStyle: { - normal: { - barBorderRadius: [30, 30, 0, 0] - } + // normal: { + borderRadius: [30, 30, 0, 0] + // } } }; }); @@ -285,7 +285,7 @@ function getWeekData() { }); }); } -function getCharts3(time, data) { +function getCharts3(time: any, data: any) { const chartstation3 = echarts.init(chart3.value); const option = { tooltip: { diff --git a/SafeCampus.WEB/src/views/userManage/dormitory/components/formDormitory/index.vue b/SafeCampus.WEB/src/views/userManage/dormitory/components/formDormitory/index.vue index 7776442..09350d7 100644 --- a/SafeCampus.WEB/src/views/userManage/dormitory/components/formDormitory/index.vue +++ b/SafeCampus.WEB/src/views/userManage/dormitory/components/formDormitory/index.vue @@ -27,6 +27,28 @@ <s-radio-group v-model="sysDormitoryProps.record.gender" :options="genderOptions" /> </s-form-item> </el-col> + <el-col :span="22"> + <s-form-item label="进楼摄像头" prop="insCameraId"> + <s-select + v-model="sysDormitoryProps.record.insCameraId" + :filterable="true" + :options="creamaData" + label="sensorName" + value="sensorId" + ></s-select> + </s-form-item> + </el-col> + <el-col :span="22"> + <s-form-item label="出楼摄像头" prop="outCameraId"> + <s-select + v-model="sysDormitoryProps.record.outCameraId" + :filterable="true" + :options="creamaData" + label="sensorName" + value="sensorId" + ></s-select> + </s-form-item> + </el-col> </el-row> </div> </el-form> @@ -40,12 +62,13 @@ <script setup lang="ts" name="SysDormitoryformClass"> import { ref } from "vue"; -import { SysDormitory, userManageDormitoryApi } from "@/api"; +import { SysDormitory, userManageDormitoryApi, monitorLIVEApi } from "@/api"; import { FormOptEnum } from "@/enums"; import { required } from "@/utils/formRules"; import { FormInstance } from "element-plus"; const visibleDormitory = ref(false); //是否显示表单 +const creamaData = ref<any>([]); const genderOptions = [ { label: "男", @@ -65,7 +88,9 @@ const sysDormitoryProps = reactive<FormProps.Base<SysDormitory.DormitoryInfo>>({ // 表单验证规则 const rules = reactive({ name: [required("请输入宿舍楼名称")], - gender: [required("请选择性别")] + gender: [required("请选择性别")], + insCameraId: [required("请选择进楼摄像头")], + outCameraId: [required("请选择出楼摄像头")] }); /** @@ -113,7 +138,14 @@ async function handleSubmit() { function onClose() { visibleDormitory.value = false; } - +onMounted(() => { + getCreamaList(); +}); +const getCreamaList = () => { + monitorLIVEApi.list({ pageNum: 1, pageSize: 1000 }).then(res => { + creamaData.value = res.data.list; + }); +}; // 暴露给父组件的方法 defineExpose({ onOpen diff --git a/SafeCampus.WEB/src/views/userManage/dormitory/index.vue b/SafeCampus.WEB/src/views/userManage/dormitory/index.vue index 200bfd0..631dff3 100644 --- a/SafeCampus.WEB/src/views/userManage/dormitory/index.vue +++ b/SafeCampus.WEB/src/views/userManage/dormitory/index.vue @@ -1,7 +1,7 @@ <!-- * @Description: 寝室管理 - * @Author: syy - * @Date: 2024-7-15 + * @Author: wwp + * @Date: 2024-7-25 --> <template> <div class="main-box"> @@ -17,6 +17,7 @@ > <template v-slot:header> <s-button suffix="宿舍楼" @click="addDormitory(FormOptEnum.ADD)" style="margin-bottom: 15px" /> + <el-button @click="settingTime" style="margin-bottom: 15px">归寝时间设置</el-button> </template> <template v-slot:label="{ row }"> <span class="custom-tree-node"> @@ -65,28 +66,59 @@ </el-space> </template> </ProTable> + <ClassUserselector + ref="userSelectorRef" + :org-tree-api="userManageClassManageApi.page" + :user-selector-api="userManagePersonnelApi.page" + multiple + @successful="handleChooseUser" + > + </ClassUserselector> </div> <!-- 寝室新增/编辑表单 --> <Form ref="formRef"></Form> <!-- 宿舍楼新增/编辑表单 --> <FormDormitory ref="formRefD" /> - <!-- 班主任绑定/修改 --> - <!-- :user-selector-params="{ orgId: orgId }" --> - <ClassUserselector - ref="userSelectorRef" - :org-tree-api="userManageClassManageApi.page" - :org-tree-props="{ label: 'name', children: 'children' }" - :user-selector-api="userManagePersonnelApi.page" - multiple - @successful="handleChooseUser" - > - </ClassUserselector> - <!-- <formUser ref="formRefU" /> --> <!-- 预览头像 --> - <el-dialog v-model="visible" title="查看头像" width="830px" :before-close="handleClose"> - <div style="display: flex; align-items: center; justify-content: center"> - <img style="max-width: 100%; max-height: 600px" class="detailpic" :src="faceUrl" alt="" /> - </div> + <el-dialog v-model="timeVisible" title="归寝时间设置" :before-close="closeTime"> + <el-form :model="timeForm" :rules="timeRules" ref="timeFormRef" label-width="100px"> + <el-row> + <el-col :span="16"> + <el-form-item label="功能有效期:" prop="dateArr"> + <el-date-picker + v-model="timeForm.dateArr" + type="daterange" + format="YYYY-MM-DD" + value-format="YYYY-MM-DD" + range-separator="-" + start-placeholder="开始日期" + end-placeholder="结束日期" + :size="size" + /> + </el-form-item> + </el-col> + <el-col :span="16"> + <el-form-item label="布防时间:" prop="timeArr"> + <el-time-picker + v-model="timeForm.timeArr" + format="HH:mm:ss" + value-format="HH:mm:ss" + is-range + range-separator="-" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + + <template #footer> + <div class="dialog-footer"> + <el-button type="primary" @click="onTimeSubmit">提交</el-button> + <el-button @click="closeTime">取消</el-button> + </div> + </template> </el-dialog> </div> </template> @@ -105,8 +137,7 @@ import { TokenEnum } from "@/enums"; import type { UploadProps } from "element-plus"; import { UserSelectorInstance } from "@/components/Selectors/UserSelector/interface"; // 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) -const faceUrl = ref(''); -const visible = ref(false); //是否显示寝室表单 + const proTable = ref<ProTableInstance>(); const treeFilter = ref<InstanceType<typeof TreeFilter> | null>(null); const userStore = useUserStore(); @@ -128,17 +159,63 @@ const columns: ColumnProps<SysDormitory.ChamberInfo>[] = [ }, { 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 size = ref<'default' | 'large' | 'small'>('default') +const timeVisible = ref(false); //是否显示时间设置 +const timeForm = reactive({ + dateArr: [], + timeArr: [], + +}); + +const timeRules = ref({ + dateArr: [{ required: true, message: "请选择功能有效期", trigger: "change" }], + timeArr: [{ required: true, message: "请选择布防时间", trigger: "change" }], +}); +const timeFormRef = ref<any>(null); +const settingTime = () => { + timeVisible.value = true; + getTimeDetail() }; -const handleClose = () => { - visible.value = false; +const getTimeDetail = () => { + userManageDormitoryApi.getReturnTime().then((res:any) => { + timeForm.dateArr = [res.data.funcStart,res.data.funcEnd]; + timeForm.timeArr = [res.data.timeBegin,res.data.timeEnd]; + }); +} +const closeTime = () => { + timeForm.dateArr = []; + timeForm.timeArr = []; + + timeVisible.value = false; +}; +// 提交分组 +const onTimeSubmit = () => { + timeFormRef.value.validate((valid: any) => { + if (valid) { + let params: any = reactive({ + funcStart: timeForm.dateArr[0], + funcEnd: timeForm.dateArr[1], + timeBegin: timeForm.timeArr[0], + timeEnd: timeForm.timeArr[1] + }); + userManageDormitoryApi.setReturnTime(params).then((res:any) => { + if (res.code == 200) { + // getGroupList(); + ElMessage({ + message: res.msg, + type: 'success' + }); + closeTime(); + } + }); + + } else { + return false; + } + }); }; +// 确定人员 function handleChooseUser(data: SysUser.SysUserInfo[]) { - console.log(data) - //组装参数 const grantUser: SysRole.GrantUserReq = { // id: roleId.value, @@ -146,7 +223,13 @@ const handleClose = () => { dormitoryId: chamberId.value, personIds: data.map(item => item.personId) as number[] | string[], }; - userManageDormitoryApi.setAssignPerson(grantUser); + userManageDormitoryApi.setAssignPerson(grantUser).then(res => { + ElMessage({ + message: res.msg, + type: 'success' + }); + RefreshTable(); + }) } // 寝室表单引用 const formRef = ref<InstanceType<typeof Form> | null>(null); @@ -248,9 +331,11 @@ const chamberId = ref<number | string>(); //寝室id function handleCommand(command: Command) { switch (command.command) { case cmdEnum.AddPerson: - console.log(111) // addPerson(FormOptEnum.add, command.row) - userSelectorRef.value?.showSelector(); //显示用户选择器 + userManageDormitoryApi.detail({ id: command.row.id }).then(res => { + console.log(res) + userSelectorRef.value?.showSelector(res.data.personInfos); //显示用户选择器 + }); chamberId.value = command.row.id; //获取寝室id break; } diff --git a/SafeCampus.WEB/src/views/warn/statistion/index.vue b/SafeCampus.WEB/src/views/warn/statistion/index.vue index 6187535..3eb3016 100644 --- a/SafeCampus.WEB/src/views/warn/statistion/index.vue +++ b/SafeCampus.WEB/src/views/warn/statistion/index.vue @@ -36,17 +36,17 @@ onMounted(() => { }); function getDataChart() { setTimeout(async () => { - await statistionApi.warnstatistion({}).then(res => { + await statistionApi.warnstatistion({}).then((res: any) => { let { code, data } = res; if (code == 200) { - let chartData1 = data.alarm.map(item => { + let chartData1 = data.alarm.map((item: any) => { return { value: item.count, name: item.name }; }); - let chartData2 = data.hand.map(item => { + let chartData2 = data.hand.map((item: any) => { return { value: item.count, name: item.name @@ -68,7 +68,7 @@ function getDataChart() { }); }); } -function getCharts1(data) { +function getCharts1(data: any) { const chart = echarts.init(chart1.value); const option = { title: { @@ -105,7 +105,7 @@ function getCharts1(data) { chart.resize(); }); } -function getCharts2(data) { +function getCharts2(data: any) { const chartstation = echarts.init(chart2.value); const option = { title: { @@ -142,39 +142,23 @@ function getCharts2(data) { chartstation.resize(); }); } -function flattenArray(arr) { - const result = []; - arr.forEach(item => { - if (Array.isArray(item)) { - result.push(...flattenArray(item)); - } else { - result.push(item); - } - }); - return result; -} -function unique(arr) { - return arr.filter((item, index, arr) => arr.indexOf(item, 0) === index); -} function getWeekData() { setTimeout(async () => { - await statistionApi.weekstatistion({}).then(res => { + await statistionApi.weekstatistion({}).then((res: any) => { let { code, data } = res; if (code == 200) { // let chartData = data; let time = data.dataX; - let chartData = data.dataY.map(item => { + let chartData = data.dataY.map((item: any) => { return { data: item.data, name: item.name, type: "bar", barWidth: "12px", // 设置柱子粗细 itemStyle: { - normal: { - barBorderRadius: [30, 30, 0, 0] - } + borderRadius: [30, 30, 0, 0] } }; }); @@ -183,7 +167,7 @@ function getWeekData() { }); }); } -function getCharts3(time, data) { +function getCharts3(time: any, data: any) { const chartstation3 = echarts.init(chart3.value); const option = { title: { @@ -228,21 +212,20 @@ function getCharts3(time, data) { height: 50px; line-height: 50px; } - .collapse-title { - flex: 1 0 90%; - order: 1; display: flex; + flex: 1 0 90%; align-items: center; justify-content: space-between; - // padding: 30px 0; + order: 1; + // padding: 30px 0; .titlemodel { + margin-right: 40px; + // display: inline-block; font-size: 18px; - margin-right: 40px; } - .btns { margin-left: 40px; } @@ -250,19 +233,22 @@ function getCharts3(time, data) { .collapse-content { padding: 20px; .contentinfo { - margin-top: 20px; + box-sizing: border-box; + // display: flex; // justify-content: space-between; // align-items: center; - padding: 20px 20px; - box-sizing: border-box; + padding: 20px; + margin-top: 20px; + // border-bottom: 1px solid #dcdfe6; // background: red; border-radius: 10px; + // box-shadow: 3px 3px 3px #00000014, 3px -3px 3px #00000014, -3px 3px 3px #00000014, -3px -3px 3px #00000014; // box-shadow: 0 1px 1px hsl(0deg 0% 0% / 0.075), 0 2px 2px hsl(0deg 0% 0% / 0.075), 0 4px 4px hsl(0deg 0% 0% / 0.075), // 0 8px 8px hsl(0deg 0% 0% / 0.075), 0 16px 16px hsl(0deg 0% 0% / 0.075); - box-shadow: 0px 2px 1px rgba(0, 0, 0, 0.1), 0 0px 8px rgba(0, 0, 0, 0.1), 0 -1px 1px #fff, 0px 0 0px #fff, 0 0 16px #fff; + box-shadow: 0 2px 1px rgb(0 0 0 / 10%), 0 0 8px rgb(0 0 0 / 10%), 0 -1px 1px #ffffff, 0 0 0 #ffffff, 0 0 16px #ffffff; .modellabel { font-size: 16px; }