| @@ -24,7 +24,6 @@ declare module 'vue' { | |||
| ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] | |||
| ElButton: typeof import('element-plus/es')['ElButton'] | |||
| ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] | |||
| ElCol: typeof import('element-plus/es')['ElCol'] | |||
| ElColorPicker: typeof import('element-plus/es')['ElColorPicker'] | |||
| ElContainer: typeof import('element-plus/es')['ElContainer'] | |||
| ElDialog: typeof import('element-plus/es')['ElDialog'] | |||
| @@ -43,13 +42,10 @@ declare module 'vue' { | |||
| ElMain: typeof import('element-plus/es')['ElMain'] | |||
| ElMenu: typeof import('element-plus/es')['ElMenu'] | |||
| ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] | |||
| ElOption: typeof import('element-plus/es')['ElOption'] | |||
| ElPagination: typeof import('element-plus/es')['ElPagination'] | |||
| ElPopover: typeof import('element-plus/es')['ElPopover'] | |||
| ElRadio: typeof import('element-plus/es')['ElRadio'] | |||
| ElRow: typeof import('element-plus/es')['ElRow'] | |||
| ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] | |||
| ElSelect: typeof import('element-plus/es')['ElSelect'] | |||
| ElSpace: typeof import('element-plus/es')['ElSpace'] | |||
| ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] | |||
| ElSwitch: typeof import('element-plus/es')['ElSwitch'] | |||
| @@ -59,6 +55,8 @@ declare module 'vue' { | |||
| ElTabs: typeof import('element-plus/es')['ElTabs'] | |||
| ElTag: typeof import('element-plus/es')['ElTag'] | |||
| ElTooltip: typeof import('element-plus/es')['ElTooltip'] | |||
| ElTree: typeof import('element-plus/es')['ElTree'] | |||
| ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] | |||
| ESign: typeof import('./src/components/ESign/index.vue')['default'] | |||
| FormContainer: typeof import('./src/components/Form/FormContainer/index.vue')['default'] | |||
| Grid: typeof import('./src/components/Grid/index.vue')['default'] | |||
| @@ -2,7 +2,7 @@ | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="UTF-8" /> | |||
| <link rel="icon" href="/qjkj.ico" /> | |||
| <link rel="icon" href="/api/sys/ico" /> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||
| <title><%- title %></title> | |||
| <!-- <script src="https://unpkg.com/aliyun-rts-sdk@1.2.1/dist/aliyun-rts-sdk.js"></script> --> | |||
| @@ -36,5 +36,22 @@ const monitorLIVEApi = { | |||
| }, | |||
| }; | |||
| /** | |||
| * @Description: 监控管理按钮权限码 | |||
| * @Author: huguodong | |||
| * @Date: 2024-02-20 09:51:15 | |||
| */ | |||
| const monitorLiveButtonCode = { | |||
| /** 新增监控 */ | |||
| add: "monitorLiveAdd", | |||
| /** 编辑监控 */ | |||
| edit: "monitorLiveEdit", | |||
| /** 删除监控 */ | |||
| delete: "monitorLiveDelete", | |||
| /** 批量删除监控 */ | |||
| batchDelete: "monitorLiveBatchDelete", | |||
| /** 复制监控 */ | |||
| copy: "monitorLiveCopy" | |||
| }; | |||
| export { monitorLIVEApi }; | |||
| export { monitorLIVEApi, monitorLiveButtonCode }; | |||
| @@ -1,7 +1,7 @@ | |||
| <template> | |||
| <div class="footer flx-center"> | |||
| <!-- <a :href="props.sysCopyrightUrl" target="_blank"> {{ props.sysCopyright }} </a> | |||
| <a v-for="link in props.footerLinks" :key="link.name" :href="link.url" target="_blank" class="mx-1"> | {{ link.name }}</a> --> | |||
| <a :href="props.sysCopyrightUrl" target="_blank"> {{ props.sysCopyright }} </a> | |||
| <a v-for="link in props.footerLinks" :key="link.name" :href="link.url" target="_blank" class="mx-1"> | {{ link.name }}</a> | |||
| </div> | |||
| </template> | |||
| <script setup lang="ts"> | |||
| @@ -1,12 +1,60 @@ | |||
| .home { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| width: 100%; | |||
| height: 100%; | |||
| .home-bg { | |||
| width: 70%; | |||
| max-width: 1200px; | |||
| margin-bottom: 20px; | |||
| margin-bottom: 15px; | |||
| height: 390px; | |||
| // height: 424px; | |||
| .home-bg-title { | |||
| display: flex; | |||
| height: 50px; | |||
| align-items: center; | |||
| div:first-child { | |||
| height: 15px; | |||
| width: 4px; | |||
| background: #3a84ff; | |||
| margin-right: 10px; | |||
| } | |||
| div:nth-child(2) { | |||
| font-size: 20px; | |||
| font-weight: 600; | |||
| margin-left: 10px; | |||
| } | |||
| } | |||
| .home-bg-content { | |||
| height: calc(100% - 50px); | |||
| .home-bg-content-item { | |||
| margin-left: 15px; | |||
| margin-top: 60px; | |||
| display: flex; | |||
| align-items: center; | |||
| .home-bg-content-item-icon { | |||
| margin-right: 15px; | |||
| width: 70px; | |||
| height: 70px; | |||
| img { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| } | |||
| .home-bg-content-item-content { | |||
| .home-bg-content-item-title { | |||
| } | |||
| .home-bg-content-item-value { | |||
| margin-top: 10px; | |||
| font-size: 20px; | |||
| font-weight: 600; | |||
| // color: #3a84ff; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .handleBox ::v-deep(.card) { | |||
| padding:0; | |||
| } | |||
| } | |||
| .topCard { | |||
| height: 355px; | |||
| } | |||
| } | |||
| @@ -1,10 +1,387 @@ | |||
| <template> | |||
| <div class="home card"> | |||
| <img class="home-bg" src="@/assets/images/welcome.png" alt="welcome" /> | |||
| <div class="home"> | |||
| <el-row :gutter="20"> | |||
| <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8"> | |||
| <div class="home-bg card"> | |||
| <div class="home-bg-title"> | |||
| <div></div> | |||
| <div>基础数据</div> | |||
| </div> | |||
| <div class="home-bg-content"> | |||
| <el-row :gutter="20"> | |||
| <el-col :span="12" | |||
| ><div class="home-bg-content-item"> | |||
| <div class="home-bg-content-item-icon"> | |||
| <img src="@/assets/images/home/carame.png" alt="" /> | |||
| </div> | |||
| <div class="home-bg-content-item-content"> | |||
| <div class="home-bg-content-item-title">摄像头数量</div> | |||
| <div class="home-bg-content-item-value">3</div> | |||
| </div> | |||
| </div></el-col | |||
| > | |||
| <el-col :span="12" | |||
| ><div class="home-bg-content-item"> | |||
| <div class="home-bg-content-item-icon"> | |||
| <img src="@/assets/images/home/warn.png" alt="" /> | |||
| </div> | |||
| <div class="home-bg-content-item-content"> | |||
| <div class="home-bg-content-item-title">告警信息总量</div> | |||
| <div class="home-bg-content-item-value">197218</div> | |||
| </div> | |||
| </div></el-col | |||
| > | |||
| <el-col :span="12" | |||
| ><div class="home-bg-content-item"> | |||
| <div class="home-bg-content-item-icon"> | |||
| <img src="@/assets/images/home/handle.png" alt="" /> | |||
| </div> | |||
| <div class="home-bg-content-item-content"> | |||
| <div class="home-bg-content-item-title">处理意见提交</div> | |||
| <div class="home-bg-content-item-value">40</div> | |||
| </div> | |||
| </div></el-col | |||
| > | |||
| <el-col :span="12" | |||
| ><div class="home-bg-content-item"> | |||
| <div class="home-bg-content-item-icon"> | |||
| <img src="@/assets/images/home/participation.png" alt="" /> | |||
| </div> | |||
| <div class="home-bg-content-item-content"> | |||
| <div class="home-bg-content-item-title">参与安防教师</div> | |||
| <div class="home-bg-content-item-value">22</div> | |||
| </div> | |||
| </div></el-col | |||
| > | |||
| </el-row> | |||
| </div> | |||
| </div> | |||
| </el-col> | |||
| <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8"> | |||
| <div class="home-bg card"> | |||
| <div class="home-bg-title"> | |||
| <div></div> | |||
| <div>今日告警情况</div> | |||
| </div> | |||
| <div class="home-bg-content"> | |||
| <div ref="chart1" style="width: 100%; height: 100%"></div> | |||
| </div> | |||
| </div> | |||
| </el-col> | |||
| <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8"> | |||
| <div class="home-bg card"> | |||
| <div class="home-bg-title"> | |||
| <div></div> | |||
| <div>今日处理情况</div> | |||
| </div> | |||
| <div class="home-bg-content"> | |||
| <div ref="chart2" style="width: 100%; height: 100%"></div> | |||
| </div> | |||
| </div> | |||
| </el-col> | |||
| <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8"> | |||
| <div class="home-bg card"> | |||
| <div class="home-bg-title"> | |||
| <div></div> | |||
| <div>高危预警信息统计</div> | |||
| </div> | |||
| <div class="home-bg-content handleBox"> | |||
| <ProTable ref="proTable" title="视频列表" :toolButton="false" :pagination="false" :columns="columns" :data="tableData"> </ProTable> | |||
| </div> | |||
| </div> | |||
| </el-col> | |||
| <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="16"> | |||
| <div class="home-bg card"> | |||
| <div class="home-bg-title"> | |||
| <div></div> | |||
| <div>统计分析</div> | |||
| </div> | |||
| <div class="home-bg-content handleBox"> | |||
| <div ref="chart3" style="width: 100%; height: 100%"></div> | |||
| </div> | |||
| </div> | |||
| </el-col> | |||
| </el-row> | |||
| </div> | |||
| </template> | |||
| <script setup lang="ts" name="home"></script> | |||
| <script setup lang="ts" name="home"> | |||
| import { ref, watch, provide, onMounted, unref, computed, reactive } from "vue"; | |||
| import { ElMessage } from "element-plus"; | |||
| import { monitorLIVEApi } from "@/api"; | |||
| import { ZJRQ } from "@/api/interface"; | |||
| import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | |||
| import { useDictStore } from "@/stores/modules"; | |||
| import { statistionApi } from "@/api"; | |||
| import * as echarts from "echarts"; | |||
| const value = ref(true); | |||
| const chart1 = ref(null); | |||
| const chart2 = ref(null); | |||
| const chart3 = ref(null); | |||
| onMounted(() => { | |||
| getDataChart(); | |||
| getWeekData(); | |||
| }); | |||
| function getDataChart() { | |||
| setTimeout(async () => { | |||
| await statistionApi.warnstatistion({}).then(res => { | |||
| let { code, data } = res; | |||
| if (code == 200) { | |||
| let chartData1 = data.alarm.map(item => { | |||
| return { | |||
| value: item.count, | |||
| name: item.name | |||
| }; | |||
| }); | |||
| let chartData2 = data.hand.map(item => { | |||
| return { | |||
| value: item.count, | |||
| name: item.name | |||
| }; | |||
| }); | |||
| // let chartData = [ | |||
| // { | |||
| // name: "1", | |||
| // value: 100 | |||
| // }, | |||
| // { | |||
| // name: "2", | |||
| // value: 200 | |||
| // } | |||
| // ]; | |||
| getCharts1(chartData1); | |||
| getCharts2(chartData2); | |||
| } | |||
| }); | |||
| }); | |||
| } | |||
| function getCharts1(data) { | |||
| const chart = echarts.init(chart1.value); | |||
| const option = { | |||
| tooltip: { | |||
| trigger: "item" | |||
| }, | |||
| // legend: { | |||
| // top: "5%", | |||
| // left: "center" | |||
| // }, | |||
| legend: { | |||
| orient: "vertical", | |||
| left: "right", | |||
| top: "middle" | |||
| }, | |||
| series: [ | |||
| { | |||
| name: "今日告警情况", | |||
| type: "pie", | |||
| radius: ["60%", "90%"], | |||
| avoidLabelOverlap: false, | |||
| itemStyle: { | |||
| borderRadius: 10, | |||
| borderColor: "#fff", | |||
| borderWidth: 2 | |||
| }, | |||
| label: { | |||
| show: false, | |||
| position: "center" | |||
| }, | |||
| emphasis: { | |||
| label: { | |||
| show: true, | |||
| fontSize: 25, | |||
| fontWeight: "bold" | |||
| } | |||
| }, | |||
| labelLine: { | |||
| show: false | |||
| }, | |||
| data | |||
| } | |||
| ] | |||
| }; | |||
| chart.setOption(option); | |||
| window.addEventListener("resize", function () { | |||
| chart.resize(); | |||
| }); | |||
| } | |||
| function getCharts2(data) { | |||
| const chartstation = echarts.init(chart2.value); | |||
| const option = { | |||
| tooltip: { | |||
| trigger: "item" | |||
| }, | |||
| // legend: { | |||
| // top: "5%", | |||
| // left: "center" | |||
| // }, | |||
| legend: { | |||
| orient: "vertical", | |||
| left: "right", | |||
| top: "middle" | |||
| }, | |||
| series: [ | |||
| { | |||
| name: "今日处理情况", | |||
| type: "pie", | |||
| radius: ["60%", "90%"], | |||
| avoidLabelOverlap: false, | |||
| itemStyle: { | |||
| borderRadius: 10, | |||
| borderColor: "#fff", | |||
| borderWidth: 2 | |||
| }, | |||
| label: { | |||
| show: false, | |||
| position: "center" | |||
| }, | |||
| emphasis: { | |||
| label: { | |||
| show: true, | |||
| fontSize: 25, | |||
| fontWeight: "bold" | |||
| } | |||
| }, | |||
| labelLine: { | |||
| show: false | |||
| }, | |||
| data | |||
| } | |||
| ] | |||
| }; | |||
| chartstation.setOption(option); | |||
| window.addEventListener("resize", function () { | |||
| chartstation.resize(); | |||
| }); | |||
| } | |||
| function getWeekData() { | |||
| setTimeout(async () => { | |||
| await statistionApi.weekstatistion({}).then(res => { | |||
| let { code, data } = res; | |||
| if (code == 200) { | |||
| // let chartData = data; | |||
| let time = data.dataX; | |||
| let chartData = data.dataY.map(item => { | |||
| return { | |||
| data: item.data, | |||
| name: item.name, | |||
| type: "bar", | |||
| barWidth: "12px", // 设置柱子粗细 | |||
| itemStyle: { | |||
| normal: { | |||
| barBorderRadius: [30, 30, 0, 0] | |||
| } | |||
| } | |||
| }; | |||
| }); | |||
| getCharts3(time, chartData); | |||
| } | |||
| }); | |||
| }); | |||
| } | |||
| function getCharts3(time, data) { | |||
| const chartstation3 = echarts.init(chart3.value); | |||
| const option = { | |||
| tooltip: { | |||
| trigger: "axis", | |||
| axisPointer: { | |||
| type: "shadow" | |||
| } | |||
| }, | |||
| legend: {}, | |||
| grid: { | |||
| left: "3%", | |||
| right: "4%", | |||
| bottom: "3%", | |||
| containLabel: true | |||
| }, | |||
| yAxis: { | |||
| type: "value", | |||
| boundaryGap: [0, 0.01] | |||
| }, | |||
| xAxis: { | |||
| type: "category", | |||
| data: time | |||
| }, | |||
| series: data | |||
| }; | |||
| chartstation3.setOption(option); | |||
| window.addEventListener("resize", function () { | |||
| chartstation3.resize(); | |||
| }); | |||
| } | |||
| // 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | |||
| const proTable = ref<ProTableInstance>(); | |||
| const dictStore = useDictStore(); | |||
| // 表格配置项 | |||
| const columns: ColumnProps<ZJRQ.WarnInfo>[] = [ | |||
| { | |||
| prop: "type", | |||
| label: "数据类型" | |||
| // render: () => { | |||
| // return "楼道"; | |||
| // } | |||
| }, | |||
| { | |||
| prop: "warntotal", | |||
| label: "告警总量" | |||
| // render: () => { | |||
| // return "楼道"; | |||
| // } | |||
| }, | |||
| { | |||
| prop: "lowrisk", | |||
| label: "低危信息 " | |||
| }, | |||
| { | |||
| prop: "highrisk", | |||
| label: "高危信息" | |||
| } | |||
| ]; | |||
| const tableData = ref([ | |||
| { | |||
| type: "今日", | |||
| warntotal: "828", | |||
| lowrisk: "675", | |||
| highrisk: "153" | |||
| }, | |||
| { | |||
| type: "本周", | |||
| warntotal: "828", | |||
| lowrisk: "675", | |||
| highrisk: "153" | |||
| }, | |||
| { | |||
| type: "本月", | |||
| warntotal: "19813", | |||
| lowrisk: "17671", | |||
| highrisk: "2129" | |||
| }, | |||
| { | |||
| type: "上月", | |||
| warntotal: "21789", | |||
| lowrisk: "0", | |||
| highrisk: "0" | |||
| }, | |||
| { | |||
| type: "环比", | |||
| warntotal: "-9.07%", | |||
| lowrisk: "0%", | |||
| highrisk: "0%" | |||
| } | |||
| ]); | |||
| const tableLoading = ref(false); | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| @import "./index.scss"; | |||
| @@ -0,0 +1,118 @@ | |||
| <!-- | |||
| * @Description: 表单 | |||
| * @Author: huguodong | |||
| * @Date: 2023-12-15 15:45:28 | |||
| !--> | |||
| <template> | |||
| <div> | |||
| <form-container v-model="visible" :title="`${orgProps.opt}监控`" form-size="600px"> | |||
| <el-form | |||
| ref="liveFormRef" | |||
| :rules="rules" | |||
| :disabled="orgProps.disabled" | |||
| :model="orgProps.record" | |||
| :hide-required-asterisk="orgProps.disabled" | |||
| label-width="auto" | |||
| label-suffix=" :" | |||
| > | |||
| <s-form-item label="摄像头名称" prop="name"> | |||
| <s-input v-model="orgProps.record.name"></s-input> | |||
| </s-form-item> | |||
| <s-form-item label="所属学校" prop="parentId"> | |||
| <org-selector v-model:org-value="orgProps.record.parentId" :org-tree-api="bizOrgApi.tree" :show-all="false" /> | |||
| </s-form-item> | |||
| <s-form-item label="设备IP" prop="codeip"> | |||
| <s-input v-model="orgProps.record.codeip" clearable></s-input> | |||
| </s-form-item> | |||
| <s-form-item label="分辨率" prop="status"> | |||
| <s-input v-model="orgProps.record.status" clearable></s-input> | |||
| </s-form-item> | |||
| </el-form> | |||
| <template #footer> | |||
| <el-button @click="onClose"> 取消 </el-button> | |||
| <el-button v-show="!orgProps.disabled" type="primary" @click="handleSubmit"> 确定 </el-button> | |||
| </template> | |||
| </form-container> | |||
| </div> | |||
| </template> | |||
| <script setup lang="ts"> | |||
| import { SysOrg, SysUser, bizOrgApi, bizPositionApi, sysRoleApi, bizUserApi } from "@/api"; | |||
| import { FormOptEnum, SysDictEnum } from "@/enums"; | |||
| import { required } from "@/utils/formRules"; | |||
| import { FormInstance } from "element-plus"; | |||
| import { useDictStore } from "@/stores/modules"; | |||
| const visible = ref(false); //是否显示表单 | |||
| const dictStore = useDictStore(); //字典仓库 | |||
| // 通用状态选项 | |||
| const statusOptions = dictStore.getDictList(SysDictEnum.COMMON_STATUS); | |||
| // 表单参数 | |||
| const orgProps = reactive<FormProps.Base<SysOrg.SysOrgInfo>>({ | |||
| opt: FormOptEnum.ADD, | |||
| record: {}, | |||
| disabled: false | |||
| }); | |||
| // 表单验证规则 | |||
| const rules = reactive({ | |||
| name: [required("请输入摄像头名称")], | |||
| parentId: [required("请选择所属学校")], | |||
| codeip: [required("请选择设备IP")], | |||
| status: [required("请输入分辨率")] | |||
| }); | |||
| /** | |||
| * 打开表单 | |||
| * @param props 表单参数 | |||
| */ | |||
| function onOpen(props: FormProps.Base<SysOrg.SysOrgInfo>) { | |||
| Object.assign(orgProps, props); //合并参数 | |||
| if (props.opt == FormOptEnum.ADD) { | |||
| //如果是新增,设置默认值 | |||
| orgProps.record.sortCode = 99; | |||
| // orgProps.record.status = statusOptions[0].value; | |||
| } | |||
| visible.value = true; //显示表单 | |||
| if (props.record.id) { | |||
| //如果传了id,就去请求api获取record | |||
| bizOrgApi.detail({ id: props.record.id }).then(res => { | |||
| orgProps.record = res.data; | |||
| }); | |||
| } | |||
| } | |||
| // 提交数据(新增/编辑) | |||
| const liveFormRef = ref<FormInstance>(); | |||
| /** 提交表单 */ | |||
| async function handleSubmit() { | |||
| liveFormRef.value?.validate(async valid => { | |||
| if (!valid) return; //表单验证失败 | |||
| console.log(orgProps); | |||
| return; | |||
| //提交表单 | |||
| await bizOrgApi | |||
| .submitForm(orgProps.record, orgProps.record.id != undefined) | |||
| .then(() => { | |||
| orgProps.successful!(); //调用父组件的successful方法 | |||
| }) | |||
| .finally(() => { | |||
| onClose(); | |||
| }); | |||
| }); | |||
| } | |||
| /** 关闭表单*/ | |||
| function onClose() { | |||
| visible.value = false; | |||
| } | |||
| // 暴露给父组件的方法 | |||
| defineExpose({ | |||
| onOpen | |||
| }); | |||
| </script> | |||
| <style lang="scss" scoped></style> | |||
| @@ -0,0 +1,38 @@ | |||
| .filter { | |||
| box-sizing: border-box; | |||
| width: 280px; | |||
| height: 100%; | |||
| padding: 18px; | |||
| margin-right: 10px; | |||
| .title { | |||
| margin: 0 0 15px; | |||
| font-size: 18px; | |||
| font-weight: bold; | |||
| color: var(--el-color-info-dark-2); | |||
| letter-spacing: 0.5px; | |||
| } | |||
| .el-input { | |||
| margin: 0 0 15px; | |||
| } | |||
| .el-scrollbar { | |||
| :deep(.el-tree) { | |||
| height: 80%; | |||
| overflow: auto; | |||
| .el-tree-node__content { | |||
| height: 33px; | |||
| } | |||
| } | |||
| :deep(.el-tree--highlight-current) { | |||
| .el-tree-node.is-current > .el-tree-node__content { | |||
| background-color: var(--el-color-primary); | |||
| .el-tree-node__label, | |||
| .el-tree-node__expand-icon { | |||
| color: white; | |||
| } | |||
| .is-leaf { | |||
| color: transparent; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -4,66 +4,135 @@ | |||
| * @Date: 2023-12-15 15:44:05 | |||
| !--> | |||
| <template> | |||
| <div class="table-box"> | |||
| <ProTable ref="proTable" title="视频列表" :columns="columns" :request-api="monitorLIVEApi.page"> | |||
| <!-- 表格 header 按钮 --> | |||
| <!-- 表格 菜单类型 按钮 --> | |||
| <template #menuType="scope"> | |||
| <el-space wrap> | |||
| <el-tag v-if="scope.row.menuType === MenuTypeDictEnum.MENU" type="success">{{ | |||
| dictStore.dictTranslation(SysDictEnum.MENU_TYPE, MenuTypeDictEnum.MENU) | |||
| }}</el-tag> | |||
| <el-tag v-else-if="scope.row.menuType === MenuTypeDictEnum.LINK" type="warning">{{ | |||
| dictStore.dictTranslation(SysDictEnum.MENU_TYPE, MenuTypeDictEnum.LINK) | |||
| }}</el-tag> | |||
| <el-tag v-else type="info">{{ dictStore.dictTranslation(SysDictEnum.MENU_TYPE, scope.row.menuType) }}</el-tag> | |||
| <el-tag v-if="scope.row.isHome === true" type="danger">首页</el-tag> | |||
| </el-space> | |||
| </template> | |||
| <!-- 操作 --> | |||
| <template #operation="scope"> | |||
| <s-button link :opt="FormOptEnum.VIEW" @click="onDetail(scope.row)"> 查看 </s-button> | |||
| <!-- <s-button link :opt="FormOptEnum.EDIT" @click="onOpen(FormOptEnum.EDIT, scope.row)">处理</s-button> | |||
| <s-button link :opt="FormOptEnum.DELETE" @click="onDelete([scope.row.id], `确定删除该预警吗?`)" /> --> | |||
| </template> | |||
| </ProTable> | |||
| <el-dialog v-model="visible" :title="detailData.title" width="830px" :before-close="handleClose"> | |||
| <div> | |||
| <div class="dialogHeader"> | |||
| <div></div> | |||
| <div class="dialogBtn" @click="refreshUrl"> | |||
| <el-icon color="#409efc" :size="20"> | |||
| <Refresh /> | |||
| </el-icon> | |||
| <div>刷新视频</div> | |||
| <div class="main-box"> | |||
| <div class="custom-tree-container card filter"> | |||
| <p>摄像头分组管理</p> | |||
| <el-tree style="max-width: 600px" :data="dataSource" node-key="id" default-expand-all :expand-on-click-node="false"> | |||
| <template #default="{ node, data }"> | |||
| <span class="custom-tree-node"> | |||
| <span>{{ node.label }}</span> | |||
| <span> | |||
| <a @click="append(data)"> Append </a> | |||
| <a style="margin-left: 8px" @click="remove(node, data)"> Delete </a> | |||
| </span> | |||
| </span> | |||
| </template> | |||
| </el-tree> | |||
| </div> | |||
| <div class="table-box"> | |||
| <ProTable ref="proTable" title="视频列表" :columns="columns" :request-api="monitorLIVEApi.page"> | |||
| <!-- 表格 header 按钮 --> | |||
| <template #tableHeader="scope"> | |||
| <s-button v-auth="monitorLiveButtonCode.add" suffix="摄像头" @click="onOpen(FormOptEnum.ADD)" /> | |||
| <s-button | |||
| type="danger" | |||
| plain | |||
| suffix="摄像头" | |||
| :opt="FormOptEnum.DELETE" | |||
| :disabled="!scope.isSelected" | |||
| @click="onDelete(scope.selectedListIds, '删除所选数据')" | |||
| /> | |||
| </template> | |||
| <!-- 表格 菜单类型 按钮 --> | |||
| <template #menuType="scope"> | |||
| <el-space wrap> | |||
| <el-tag v-if="scope.row.menuType === MenuTypeDictEnum.MENU" type="success">{{ | |||
| dictStore.dictTranslation(SysDictEnum.MENU_TYPE, MenuTypeDictEnum.MENU) | |||
| }}</el-tag> | |||
| <el-tag v-else-if="scope.row.menuType === MenuTypeDictEnum.LINK" type="warning">{{ | |||
| dictStore.dictTranslation(SysDictEnum.MENU_TYPE, MenuTypeDictEnum.LINK) | |||
| }}</el-tag> | |||
| <el-tag v-else type="info">{{ dictStore.dictTranslation(SysDictEnum.MENU_TYPE, scope.row.menuType) }}</el-tag> | |||
| <el-tag v-if="scope.row.isHome === true" type="danger">首页</el-tag> | |||
| </el-space> | |||
| </template> | |||
| <!-- 操作 --> | |||
| <template #operation="scope"> | |||
| <s-button link :opt="FormOptEnum.VIEW" @click="onDetail(scope.row)"> 查看 </s-button> | |||
| <s-button link :opt="FormOptEnum.EDIT" @click="onOpen(FormOptEnum.EDIT, scope.row)">编辑</s-button> | |||
| <s-button link :opt="FormOptEnum.DELETE" @click="onDelete([scope.row.id], `确定删除该摄像头吗?`)" /> | |||
| </template> | |||
| </ProTable> | |||
| <!-- 新增/编辑表单 --> | |||
| <Form ref="formRef" /> | |||
| <el-dialog v-model="visible" :title="detailData.title" width="830px" :before-close="handleClose"> | |||
| <div> | |||
| <div class="dialogHeader"> | |||
| <div></div> | |||
| <div class="dialogBtn" @click="refreshUrl"> | |||
| <el-icon color="#409efc" :size="20"> | |||
| <Refresh /> | |||
| </el-icon> | |||
| <div>刷新视频</div> | |||
| </div> | |||
| </div> | |||
| <div v-if="visible || showVideo" class="prism-player" id="player-con"></div> | |||
| <!-- <VideoPlay :videoUrl="detailData.videoUrl" :videoType="detailData.videoType" /> --> | |||
| <!-- <video style="width: 100%; height: 500px" id="video" controls muted="false"></video> --> | |||
| <!-- <iframe src="/static/artcvideo.html" width="100%" height="600px" ref="iframeDom"></iframe> --> | |||
| </div> | |||
| <div v-if="visible || showVideo" class="prism-player" id="player-con"></div> | |||
| <!-- <VideoPlay :videoUrl="detailData.videoUrl" :videoType="detailData.videoType" /> --> | |||
| <!-- <video style="width: 100%; height: 500px" id="video" controls muted="false"></video> --> | |||
| <!-- <iframe src="/static/artcvideo.html" width="100%" height="600px" ref="iframeDom"></iframe> --> | |||
| </div> | |||
| <template #footer> | |||
| <div class="dialog-footer"> | |||
| <el-button @click="handleClose">关闭</el-button> | |||
| </div> | |||
| </template> | |||
| </el-dialog> | |||
| <template #footer> | |||
| <div class="dialog-footer"> | |||
| <el-button @click="handleClose">关闭</el-button> | |||
| </div> | |||
| </template> | |||
| </el-dialog> | |||
| </div> | |||
| </div> | |||
| </template> | |||
| <script setup lang="tsx" name="sysSpa"> | |||
| import VideoPlay from "@/components/VideoPlay/videoplay.vue"; | |||
| import { ElMessage } from "element-plus"; | |||
| import { monitorLIVEApi } from "@/api"; | |||
| import type Node from 'element-plus/es/components/tree/src/model/node' | |||
| import { monitorLIVEApi, monitorLiveButtonCode } from "@/api"; | |||
| import { ZJRQ } from "@/api/interface"; | |||
| import { useHandleData } from "@/hooks/useHandleData"; | |||
| import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | |||
| import { useDictStore } from "@/stores/modules"; | |||
| import Form from "./components/form.vue"; | |||
| import { FormOptEnum, SysDictEnum, MenuTypeDictEnum } from "@/enums"; | |||
| import './aliyun-rts-sdk.js' | |||
| import './ali.js' | |||
| interface Tree { | |||
| id: number | |||
| label: string | |||
| children?: Tree[] | |||
| } | |||
| let id = 1000 | |||
| const append = (data: Tree) => { | |||
| const newChild = { id: id++, label: 'testtest', children: [] } | |||
| if (!data.children) { | |||
| data.children = [] | |||
| } | |||
| data.children.push(newChild) | |||
| dataSource.value = [...dataSource.value] | |||
| } | |||
| const remove = (node: Node, data: Tree) => { | |||
| const parent = node.parent | |||
| const children: Tree[] = parent.data.children || parent.data | |||
| const index = children.findIndex((d) => d.id === data.id) | |||
| children.splice(index, 1) | |||
| dataSource.value = [...dataSource.value] | |||
| } | |||
| const dataSource = ref<Tree[]>([ | |||
| { | |||
| id: 1, | |||
| label: 'Level one 1', | |||
| }, | |||
| { | |||
| id: 2, | |||
| label: 'Level one 2', | |||
| }, | |||
| { | |||
| id: 3, | |||
| label: 'Level one 3', | |||
| }, | |||
| ]) | |||
| const visible = ref(false); //是否显示表单 | |||
| // 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | |||
| @@ -72,7 +141,7 @@ | |||
| // 表格配置项 | |||
| const columns: ColumnProps<ZJRQ.WarnInfo>[] = [ | |||
| // { type: "selection", fixed: "left", width: 80 }, | |||
| { type: "selection", fixed: "left", width: 80 }, | |||
| // { prop: "searchKey", label: "关键字", search: { el: "input" }, isShow: false }, | |||
| // { | |||
| // prop: "poiId", | |||
| @@ -107,7 +176,6 @@ | |||
| prop: "resWidth", | |||
| label: "分辨率", | |||
| render: (row) => { | |||
| console.log(row,88) | |||
| return row.row.resWidth + '*' + row.row.resHeight; | |||
| } | |||
| }, | |||
| @@ -119,6 +187,7 @@ | |||
| * @param ids id数组 | |||
| */ | |||
| async function onDelete(ids: string[], msg: string) { | |||
| return | |||
| // 二次确认 => 请求api => 刷新表格 | |||
| await useHandleData(monitorLIVEApi.delete, { ids }, msg); | |||
| RefreshTable(); | |||
| @@ -130,6 +199,16 @@ | |||
| function RefreshTable() { | |||
| proTable.value?.refresh(); | |||
| } | |||
| // 表单引用 | |||
| const formRef = ref<InstanceType<typeof Form> | null>(null); | |||
| /** | |||
| * 打开表单 | |||
| * @param opt 操作类型 | |||
| * @param record 记录 | |||
| */ | |||
| function onOpen(opt: FormOptEnum, record: {} | SysOrg.SysOrgInfo = {}) { | |||
| formRef.value?.onOpen({ opt: opt, record: record, successful: RefreshTable }); | |||
| } | |||
| // 详情数据 | |||
| // let detailData: globalThis.Ref<{}> | |||
| let detailData = reactive({ | |||
| @@ -305,6 +384,7 @@ | |||
| <style lang="scss" scoped> | |||
| @import url("https://g.alicdn.com/apsara-media-box/imp-web-player/2.16.3/skins/default/aliplayer-min.css"); | |||
| @import "./index.scss"; | |||
| .detailpic { | |||
| width: 800px; | |||
| object-fit: cover; | |||
| @@ -7,13 +7,13 @@ | |||
| <div class="card content-main"> | |||
| <el-row :gutter="20"> | |||
| <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12"> | |||
| <div ref="chart1" style="width: 600px; height: 400px"></div> | |||
| <div ref="chart1" style="width: 600px; height: 378px"></div> | |||
| </el-col> | |||
| <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12"> | |||
| <div ref="chart2" style="width: 600px; height: 400px"></div> | |||
| <div ref="chart2" style="width: 600px; height: 378px"></div> | |||
| </el-col> | |||
| <el-col :span="24"> | |||
| <div ref="chart3" style="width: 100%; height: 400px"></div> | |||
| <div ref="chart3" style="width: 100%; height: 378px"></div> | |||
| </el-col> | |||
| </el-row> | |||
| </div> | |||