Kaynağa Gözat

寝室管理

master
wwp 7 ay önce
ebeveyn
işleme
600df7601c
10 değiştirilmiş dosya ile 230 ekleme ve 87 silme
  1. +1
    -1
      SafeCampus.WEB/.env.development
  2. +2
    -0
      SafeCampus.WEB/src/api/interface/sys/usermanage/dormitory.ts
  3. +3
    -2
      SafeCampus.WEB/src/components/Form/SSelect/index.vue
  4. +1
    -0
      SafeCampus.WEB/src/components/Form/SSelect/interface.ts
  5. +10
    -1
      SafeCampus.WEB/src/components/ProTable/index.vue
  6. +33
    -6
      SafeCampus.WEB/src/components/Selectors/ClassUserselector/index.vue
  7. +8
    -8
      SafeCampus.WEB/src/views/home/index.vue
  8. +35
    -3
      SafeCampus.WEB/src/views/userManage/dormitory/components/formDormitory/index.vue
  9. +116
    -31
      SafeCampus.WEB/src/views/userManage/dormitory/index.vue
  10. +21
    -35
      SafeCampus.WEB/src/views/warn/statistion/index.vue

+ 1
- 1
SafeCampus.WEB/.env.development Dosyayı Görüntüle

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


+ 2
- 0
SafeCampus.WEB/src/api/interface/sys/usermanage/dormitory.ts Dosyayı Görüntüle

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


+ 3
- 2
SafeCampus.WEB/src/components/Form/SSelect/index.vue Dosyayı Görüntüle

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


+ 1
- 0
SafeCampus.WEB/src/components/Form/SSelect/interface.ts Dosyayı Görüntüle

@@ -21,4 +21,5 @@ export interface SSelectProps {
label?: string;
/** 选项值 */
value?: string;
filterable?: boolean;
}

+ 10
- 1
SafeCampus.WEB/src/components/ProTable/index.vue Dosyayı Görüntüle

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

// 接受父组件参数,配置默认值


+ 33
- 6
SafeCampus.WEB/src/components/Selectors/ClassUserselector/index.vue Dosyayı Görüntüle

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


+ 8
- 8
SafeCampus.WEB/src/views/home/index.vue Dosyayı Görüntüle

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


+ 35
- 3
SafeCampus.WEB/src/views/userManage/dormitory/components/formDormitory/index.vue Dosyayı Görüntüle

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


+ 116
- 31
SafeCampus.WEB/src/views/userManage/dormitory/index.vue Dosyayı Görüntüle

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


+ 21
- 35
SafeCampus.WEB/src/views/warn/statistion/index.vue Dosyayı Görüntüle

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


Yükleniyor…
İptal
Kaydet