Просмотр исходного кода

Merge branch 'system-assemble' of ssh://172.16.23.188:9022/tian-group/skyeye-admin-fe into system-assemble

zhudie 2 лет назад
Родитель
Сommit
38b9cca19e

+ 1 - 1
.env.production

@@ -1,5 +1,5 @@
 # 是否开启mock
-VITE_USE_MOCK = true
+VITE_USE_MOCK = false
 
 # 网站根目录
 VITE_PUBLIC_PATH = /

Разница между файлами не показана из-за своего большого размера
+ 1048 - 166
pnpm-lock.yaml


+ 27 - 0
src/api/algo/algo.ts

@@ -0,0 +1,27 @@
+import { http } from '@/utils/http/axios';
+
+export function getAlgoInfo(page: number, pageSize: number) {
+  return http.request({
+    url: '/cameraAlgo/getList?pageNumber=' + page + '&pageSize=' + pageSize,
+    method: 'get',
+  });
+}
+
+export function searchAlgoInfo(page: number, keyWord: string) {
+  return http.request({
+    url: '/cameraAlgo/getAlgo?algoInfo=' + keyWord + '&pageNumber=' + page + '&pageSize=12',
+    method: 'get',
+  });
+}
+
+export function algoInfoModify(algoId: number, pushLinkPrompt: string, pushStatement: string) {
+  return http.request({
+    url: '/cameraAlgo/saveAlgoState',
+    method: 'post',
+    data: {
+      algoId,
+      pushLinkPrompt,
+      pushStatement,
+    },
+  });
+}

+ 341 - 0
src/views/cameras/algo-management/algoManagement.vue

@@ -0,0 +1,341 @@
+<template>
+  <PageWrapper>
+    <div class="background">
+      <div class="left">
+        <el-input
+          v-model="searchKey"
+          placeholder="请输入算法信息搜索"
+          style="margin-top: 24px; height: 32px; margin-bottom: 16px"
+          :suffix-icon="Search"
+          @blur="searchItem"
+        />
+        <div class="algo-table">
+          <el-table
+            ref="singleTableRef"
+            :data="algoList"
+            highlight-current-row
+            stripe
+            style="width: 100%"
+            height="100%"
+            :row-style="{ height: '54px' }"
+            :header-row-style="{ height: '54px' }"
+            @row-click="handleRowClick"
+          >
+            <el-table-column property="id" label="序号" width="80" align="center" />
+            <el-table-column property="code" label="算法编号" width="120" align="center" />
+            <el-table-column property="name" label="算法名称" />
+          </el-table>
+        </div>
+        <div style="display: flex; justify-content: flex-end">
+          <el-pagination
+            background
+            layout="prev, pager, next"
+            style="margin-top: 24px; height: 32px; margin-bottom: 34px"
+            :total="20"
+            v-model:current-page="curPage"
+            @current-change="changePage"
+            :page-size="pageSize"
+          />
+        </div>
+      </div>
+      <div class="right">
+        <div class="right_top">
+          <div class="top_left">
+            <el-scrollbar height="100%">
+              <div v-if="currentRow?.name == ''" class="details_title">请在左侧列表中选择算法</div>
+              <div v-else class="details_title">{{ currentRow?.name }}检测算法展示</div>
+              <div v-for="item in arrRemark" :key="item" class="textbox">
+                <div class="item_title">{{ item }}</div>
+                <!-- <div class="item_details">{{ currentRow?.remark }}</div> -->
+              </div>
+            </el-scrollbar>
+          </div>
+          <div class="top_right">
+            <video :src="currentRow?.url" controls autoplay muted style="width: 100%; height: 100%">
+            </video>
+          </div>
+        </div>
+        <div class="right_bottom">
+          <div class="details_title" style="margin-bottom: 16px">报警推送编辑</div>
+          <el-form :model="alarmConfig" size="default" :rules="rules" ref="ruleFormRef">
+            <el-form-item label="语句编辑:" prop="pushStatement">
+              <div class="pushStatement">
+                <div class="remark">时间:(示例:2023.10.23 10:55:28)</div>
+                <div class="remark">地点:(示例:C919总装车间150A工位)</div>
+                <el-input
+                  v-model="alarmConfig.pushStatement"
+                  style="width: 100%; height: 74px; margin-top: 4px"
+                  placeholder="示例:【异常类:未穿反光背心违规】您好,经安全管控平台分析,在该区域发现员工未穿反光背心或穿戴不规范的情况,请及时提醒。"
+                />
+              </div>
+            </el-form-item>
+
+            <el-form-item label="链接提示:" prop="pushLinkPrompt">
+              <el-input
+                v-model="alarmConfig.pushLinkPrompt"
+                style="width: 100%"
+                placeholder="示例:请点击商飞大脑-天眼APP查看。"
+              />
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" :loading="isSending" @click="onSubmit"
+                >保&nbsp;&nbsp;存</el-button
+              >
+            </el-form-item>
+          </el-form>
+        </div>
+      </div>
+      <!-- <video :src="address" controls autoplay muted style="width: 100%; height: 100%"> </video> -->
+    </div>
+  </PageWrapper>
+</template>
+<script lang="ts" setup>
+  import { onMounted, ref, onUnmounted, reactive, watchEffect } from 'vue';
+  import { PageWrapper } from '../../../components/Page';
+  import useAlgo from './useAlgoData';
+  import { Search } from '@element-plus/icons-vue';
+  import type { FormInstance, FormRules } from 'element-plus';
+
+  //调用后端数据
+  const algoDatas = useAlgo();
+  const {
+    algoList,
+    getAlgoDatas,
+    page,
+    pageSize,
+    keyWord,
+    searchAlgoDatas,
+    algoId,
+    pushLinkPrompt,
+    pushStatement,
+    modifyAlgoDatas,
+  } = algoDatas;
+  //将后端拉到的数据存到algoListUse数组中进行使用
+  //刷新时从后端拉一次算法数组
+  onMounted(() => {
+    getAlgoDatas();
+  });
+
+  const changePage = () => {
+    page.value = curPage.value;
+    getAlgoDatas();
+  };
+
+  const searchItem = () => {
+    keyWord.value = searchKey.value;
+    curPage.value = 1;
+    page.value = curPage.value;
+    searchAlgoDatas();
+  };
+
+  const curPage = ref(1);
+  const currentRow = ref({
+    algoCode: '',
+    name: '',
+    remark: '',
+    url: '',
+    id: 0,
+    pushLinkPrompt: '',
+    pushStatement: '',
+  });
+
+  interface User {
+    algoCode: string;
+    name: string;
+    remark: string;
+    url: string;
+    id: number;
+    pushLinkPrompt: string;
+    pushStatement: string;
+  }
+
+  const arrRemark = ref<string[]>([]);
+
+  const handleRowClick = (val: User | undefined) => {
+    // console.log('xxxxxxxxxx', currentRow.value);
+    currentRow.value = val;
+    arrRemark.value = currentRow.value.remark.split('\r\n');
+    // console.log('arrRemark', arrRemark.value);
+  };
+
+  const searchKey = ref('');
+
+  interface SettingConfig {
+    pushLinkPrompt: string;
+    pushStatement: string;
+  }
+
+  const alarmConfig = ref<SettingConfig>({
+    pushLinkPrompt: '',
+    pushStatement: '',
+  });
+  const rules = ref<FormRules>({
+    pushLinkPrompt: [{ required: true, message: '此处不可空缺' }],
+    pushStatement: [{ required: true, message: '此处不可空缺' }],
+  });
+
+  const ruleFormRef = ref<FormInstance>();
+
+  const isSending = ref(false);
+
+  const onSubmit = async () => {
+    if (!ruleFormRef.value) console.log('error submit!');
+    await ruleFormRef.value?.validate((valid, fields) => {
+      if (valid) {
+        isSending.value = true;
+        algoId.value = currentRow.value.id;
+        pushLinkPrompt.value = alarmConfig.value.pushLinkPrompt;
+        pushStatement.value = alarmConfig.value.pushStatement;
+        // console.log('algoId', algoId.value);
+        // console.log('pushStatement', pushStatement.value);
+        // console.log('pushLinkPrompt', pushLinkPrompt.value);
+        modifyAlgoDatas().finally(() => {
+          isSending.value = false;
+        });
+      } else {
+        console.log('error submit!', fields);
+      }
+    });
+  };
+</script>
+<style lang="scss" scoped>
+  .background {
+    position: relative;
+    height: calc(100vh - 64px - 12px);
+    background-color: #ffffff;
+    display: flex;
+    flex-direction: row;
+    .left {
+      position: relative;
+      height: 100%;
+      width: 31%;
+      padding-left: 1.66%;
+      padding-right: 1.33%;
+      // background-color: green;
+      border-right: #dddddd 1px solid;
+      display: flex;
+      flex-direction: column;
+      .algo-table {
+        position: relative;
+        height: calc(100% - 72px - 90px);
+        width: 100%;
+        // background-color: red;
+        // margin-top: 16px;
+      }
+    }
+    .right {
+      position: relative;
+      height: 100%;
+      width: 69%;
+      display: flex;
+      flex-direction: column;
+      // background-color: yellow;
+      .right_top {
+        position: relative;
+        height: 364px;
+        width: 100%;
+        display: flex;
+        flex-direction: row;
+        border-bottom: #dddddd 1px solid;
+        // background-color: rebeccapurple;
+        .top_left {
+          position: relative;
+          margin-top: 90px;
+          margin-left: 4%;
+          height: 234px;
+          width: 42%;
+          display: flex;
+          flex-direction: column;
+          // background-color: rebeccapurple;
+          .details_title {
+            position: relative;
+            height: 22px;
+            width: 100%;
+            font-size: 14px;
+            font-weight: 600;
+            color: rgba(0, 0, 0, 0.85);
+            line-height: 22px;
+          }
+          .textbox {
+            position: relative;
+            margin-top: 14px;
+            width: 100%;
+            display: flex;
+            flex-direction: row;
+            .item_title {
+              position: relative;
+              width: 100%;
+              font-size: 14px;
+              font-weight: 500;
+              color: rgba(0, 0, 0, 0.85);
+              line-height: 22px;
+            }
+            .item_details {
+              position: relative;
+              width: 79.8%;
+              font-size: 14px;
+              font-weight: 400;
+              color: rgba(0, 0, 0, 0.85);
+              line-height: 22px;
+            }
+          }
+        }
+        .top_right {
+          position: relative;
+          margin-top: 90px;
+          margin-left: 4%;
+          height: 234px;
+          width: 45%;
+          display: flex;
+          flex-direction: row;
+          // background-color: rebeccapurple;
+        }
+      }
+      .right_bottom {
+        position: relative;
+        margin-left: 4%;
+        margin-top: 24px;
+        width: 91%;
+        display: flex;
+        flex-direction: column;
+        .details_title {
+          position: relative;
+          height: 22px;
+          width: 100%;
+          font-size: 14px;
+          font-weight: 600;
+          color: rgba(0, 0, 0, 0.85);
+          line-height: 22px;
+        }
+      }
+    }
+  }
+  .pushStatement {
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    height: 155px;
+    width: 100%;
+    // background-color: red;
+    .remark {
+      position: relative;
+      height: 22px;
+      width: 100%;
+      margin-top: 4px;
+      margin-left: 10px;
+      margin-bottom: 12px;
+      font-size: 16px;
+      font-weight: 400;
+      color: rgba(0, 0, 0, 0.42);
+      line-height: 22px;
+    }
+  }
+  :deep() {
+    .el-input__wrapper {
+      align-items: flex-start !important;
+    }
+    .el-form-item__content {
+      justify-content: flex-end;
+    }
+  }
+</style>

+ 54 - 0
src/views/cameras/algo-management/useAlgoData.ts

@@ -0,0 +1,54 @@
+import { getAlgoInfo, searchAlgoInfo, algoInfoModify } from '@/api/algo/algo';
+import { ref } from 'vue';
+import { ElMessage } from 'element-plus';
+
+export function useAlgo() {
+  const algoList = ref([]);
+  const page = ref(1);
+  const pageSize = ref(12);
+  const keyWord = ref('');
+
+  const algoId = ref(0);
+  const pushLinkPrompt = ref('');
+  const pushStatement = ref('');
+
+  const getAlgoDatas = () => {
+    return getAlgoInfo(page.value, pageSize.value).then((res) => {
+      algoList.value = res.records;
+    });
+  };
+
+  const searchAlgoDatas = () => {
+    return searchAlgoInfo(page.value, keyWord.value).then((res) => {
+      algoList.value = res.records;
+    });
+  };
+
+  const modifyAlgoDatas = () => {
+    return algoInfoModify(algoId.value, pushLinkPrompt.value, pushStatement.value)
+      .then(function () {
+        ElMessage({
+          message: '算法数据保存成功',
+          type: 'success',
+        });
+      })
+      .catch(function () {
+        ElMessage.error('算法数据保存失败');
+      });
+  };
+
+  return {
+    algoList,
+    page,
+    pageSize,
+    keyWord,
+    getAlgoDatas,
+    searchAlgoDatas,
+    algoId,
+    pushLinkPrompt,
+    pushStatement,
+    modifyAlgoDatas,
+  };
+}
+
+export default useAlgo;

+ 20 - 0
src/views/system/role/columns.ts

@@ -1,3 +1,4 @@
+import { h } from 'vue';
 import { BasicColumn } from '@/components/Table';
 
 export const columns: BasicColumn[] = [
@@ -5,6 +6,25 @@ export const columns: BasicColumn[] = [
     label: '角色id',
     prop: 'roleId',
   },
+  {
+    label: '角色类型',
+    prop: 'role_type',
+    render(record) {
+      let type = '管理员';
+      if (record.row.role_type === 1) {
+        type = '超级管理员';
+      } else if (record.row.role_type === 3) {
+        type = '用户';
+      }
+      return h(
+        'span',
+        {},
+        {
+          default: () => type,
+        },
+      );
+    },
+  },
   {
     label: '角色编码',
     prop: 'roleCode',

+ 7 - 2
src/views/system/role/role.vue

@@ -154,8 +154,13 @@
     console.log('点击了编辑', record);
     console.log('record.roleType', record.role_type);
     drawerTitle.value = '编辑角色';
-    const { openDrawer } = createUserDrawerRef.value;
-    openDrawer(record.roleId, record.role_type);
+    if (record.role_type === 3) {
+      const { openDrawer } = createUserDrawerRef.value;
+      openDrawer(record.roleId, record.role_type);
+    } else {
+      const { openDrawer } = createDrawerRef.value;
+      openDrawer(record.roleId);
+    }
   }
 
   function handleDelete(record: Recordable) {

+ 7 - 3
src/views/system/user/CreateDrawer.vue

@@ -20,7 +20,7 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="密码" prop="password">
+      <el-form-item v-if="props.title === '添加用户'" label="密码" prop="password">
         <el-input
           type="password"
           show-password-on="mousedown"
@@ -28,7 +28,11 @@
           v-model="formParams.password"
         />
       </el-form-item>
-      <el-form-item label="确认密码" :prop="!formParams.username ? 'passwordRe' : ''">
+      <el-form-item
+        v-if="props.title === '添加用户'"
+        label="确认密码"
+        :prop="!formParams.username ? 'passwordRe' : ''"
+      >
         <el-input
           type="password"
           show-password-on="mousedown"
@@ -221,7 +225,7 @@
       } else {
         const updateData = {
           userId: params.userId,
-          password: formParams.value.password,
+          // password: formParams.value.password,
           deptId: formParams.value.deptId,
           username: formParams.value.username,
           staffNo: formParams.value.staffNo,

+ 1 - 1
src/views/system/user/columns.ts

@@ -112,7 +112,7 @@ export const columns: BasicColumn[] = [
   // },
   {
     label: '组织',
-    prop: 'postName',
+    prop: 'deptName',
   },
   // {
   //   label: '岗位',

+ 15 - 6
src/views/system/user/component/AddUser.vue

@@ -21,6 +21,8 @@
           :on-exceed="handleExceed"
           :before-upload="beforeUpload"
           :on-success="handleUploadSuccess"
+          :on-exceed="handleExceed"
+          :limit="1"
           style="width: 384px; height: 192px; border-radius: 8px"
         >
           <el-icon class="el-icon--upload" style="width: 33px; height: 42px"><Document /></el-icon>
@@ -104,12 +106,8 @@
 <script setup lang="ts">
   import { Close, Document, CircleCheck, Warning } from '@element-plus/icons-vue';
   import { ref } from 'vue';
-  import {
-    genFileId,
-    type UploadInstance,
-    type UploadProps,
-    type UploadRawFile,
-  } from 'element-plus';
+  import { genFileId, ElMessage } from 'element-plus';
+  import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus';
   import { downloadByUrl } from '@/utils/file/download';
   import { useUserStore } from '@/store/modules/user';
   import { onMounted } from 'vue';
@@ -172,6 +170,10 @@
     const isExcel = /\.(xlsx|xls)$/.test(file.name.toLowerCase());
     if (!isExcel) {
       // 提示用户选择正确的文件类型
+      ElMessage({
+        message: '仅支持上传.xlsx .xls格式文件',
+        type: 'error',
+      });
       return false; // 阻止上传
     }
     return true; // 允许上传
@@ -206,6 +208,13 @@
     emits('change');
   };
 
+  const handleExceed: UploadProps['onExceed'] = (files) => {
+    upload.value!.clearFiles();
+    const file = files[0] as UploadRawFile;
+    file.uid = genFileId();
+    upload.value!.handleStart(file);
+  };
+
   //对话框
 </script>