Jelajahi Sumber

feat: 报警推送配置页

wyf 1 tahun lalu
induk
melakukan
7ff486c219

TEMPAT SAMPAH
src/assets/icons/arrow-right.png


TEMPAT SAMPAH
src/assets/images/alarm-example-photo.png


TEMPAT SAMPAH
src/assets/images/alarm-example.png


+ 217 - 0
src/views/message/alarm-config/AlarmConfig.vue

@@ -0,0 +1,217 @@
+<template>
+  <div class="alarm-config-page">
+    <div class="alarm-config-header">
+      <div class="alarm-config-rollback" @click="">
+        <img src="../reportmessage/img/rollback.png" /><span>返回</span>
+      </div>
+      <span>新建报表配置</span>
+    </div>
+    <div class="alarm-config-content">
+      <div class="alarm-config-form">
+        <el-form ref="formRef" :model="alarmConfigForm" :rules="rules" label-width="auto">
+          <el-form-item label="违规类型:">
+            <el-select
+              class="alarm-config-input"
+              v-model="alarmConfigForm.violationType"
+              placeholder="请选择违规类型"
+            >
+              <el-option
+                v-for="item in AlarmTypes"
+                :key="item.id"
+                :label="item.label"
+                :value="item.id"
+            /></el-select>
+          </el-form-item>
+          <el-form-item label="报警等级:">
+            <el-select
+              class="alarm-config-input"
+              v-model="alarmConfigForm.violationLevel"
+              placeholder="请选择报警等级"
+            >
+              <el-option
+                v-for="item in AlarmLevels"
+                :key="item.id"
+                :label="item.label"
+                :value="item.id"
+            /></el-select>
+          </el-form-item>
+          <el-form-item label="推送渠道:">
+            <el-checkbox-group v-model="alarmConfigForm.pushChannel">
+              <el-checkbox
+                v-for="channel in PushChannels"
+                :key="channel.id"
+                :label="channel.label"
+                :value="channel.id"
+              >
+              </el-checkbox>
+            </el-checkbox-group>
+          </el-form-item>
+          <el-form-item label="推送阶段:">
+            <el-checkbox-group
+              class="alarm-config-checkbox-group"
+              v-model="alarmConfigForm.pushOccasions"
+            >
+              <div v-for="occasion in PushOccasions">
+                <el-checkbox :key="occasion.id" :label="occasion.label" :value="occasion.id">
+                </el-checkbox>
+                <div
+                  v-if="alarmConfigForm.pushPhaseVOList.some((it) => it.pushPhase === occasion.id)"
+                >
+                  <PushOccasionsCard
+                    :form="alarmConfigForm.pushPhaseVOList.find((it) => it.pushPhase === occasion.id)!"
+                    :type="AlarmTypes.find((it) => it.id === alarmConfigForm.violationType)?.label!"
+                  />
+                </div>
+              </div>
+            </el-checkbox-group>
+          </el-form-item>
+          <el-form-item label="创建人:">
+            <el-input class="alarm-config-input" v-model="alarmConfigForm.creator" disabled />
+          </el-form-item>
+          <el-form-item> </el-form-item>
+        </el-form>
+        <div style="text-align: right; margin-right: 32px">
+          <el-button> 取 消 </el-button>
+          <el-button type="primary" @click="submitForm(formRef)"> 确 定 </el-button>
+        </div>
+      </div>
+      <div class="alarm-config-example">
+        <AlarmExample />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import PushOccasionsCard from './components/PushOccasionsCard.vue';
+  import AlarmExample from './components/AlarmExample.vue';
+  import {
+    ElForm,
+    ElFormItem,
+    ElSelect,
+    ElCheckboxGroup,
+    ElCheckbox,
+    FormInstance,
+    FormRules,
+  } from 'element-plus';
+  import { AlarmConfigForm } from './types';
+  import { ref, watch } from 'vue';
+  import { useUserStore } from '@/store/modules/user';
+
+  const useUser = useUserStore();
+
+  const alarmConfigForm = ref<AlarmConfigForm>({
+    violationType: undefined,
+    violationLevel: undefined,
+    pushChannel: [],
+    pushOccasions: [],
+    pushPhaseVOList: [],
+    creator: useUser.info.nickname,
+  });
+
+  watch(
+    () => alarmConfigForm.value.pushOccasions,
+    () => {
+      alarmConfigForm.value.pushOccasions.forEach((occasion) => {
+        if (!alarmConfigForm.value.pushPhaseVOList.some((it) => it.pushPhase === occasion)) {
+          alarmConfigForm.value.pushPhaseVOList.push({
+            pushPhase: occasion,
+            recipientType: undefined,
+            content: '',
+          });
+        }
+      });
+      alarmConfigForm.value.pushPhaseVOList.forEach((vo) => {
+        if (!alarmConfigForm.value.pushOccasions.some((occ) => occ === vo.pushPhase)) {
+          alarmConfigForm.value.pushPhaseVOList.splice(
+            alarmConfigForm.value.pushPhaseVOList.findIndex((it) => it.pushPhase === vo.pushPhase),
+            1,
+          );
+        }
+      });
+    },
+  );
+
+  const formRef = ref<FormInstance>();
+
+  const rules = ref<FormRules<AlarmConfigForm>>();
+  // 违规类型
+  const AlarmTypes = [
+    { id: 1, label: '违规类型1' },
+    { id: 2, label: '违规类型2' },
+  ];
+
+  // 报警等级
+  const AlarmLevels = [
+    { id: 1, label: '报警等级1' },
+    { id: 2, label: '报警等级2' },
+  ];
+
+  // 推送渠道
+  const PushChannels = [
+    { id: 1, label: '平台' },
+    { id: 2, label: '蓝信' },
+  ];
+
+  // 推送阶段
+  const PushOccasions = [
+    { id: 1, label: '问题发生时推送', value: {} },
+    { id: 2, label: '问题生效后推送', value: {} },
+    { id: 3, label: '审核通过后推送', value: {} },
+  ];
+
+  const submitForm = async (formEl: FormInstance | undefined) => {
+    if (!formEl) return;
+    await formEl.validate((valid, fields) => {
+      if (valid) {
+        console.log('submit!');
+      } else {
+        console.log('error submit!', fields);
+      }
+    });
+  };
+</script>
+
+<style scoped lang="scss">
+  .alarm-config-page {
+    background-color: rgba(255, 255, 255, 1);
+    .alarm-config-header {
+      display: flex;
+      align-items: center;
+      padding: 16px 0 15px 20px;
+      border-bottom: 1px solid #e9e9e9;
+      .alarm-config-rollback {
+        width: 60px;
+        display: flex;
+        align-items: center;
+        cursor: pointer;
+      }
+    }
+    .alarm-config-content {
+      display: flex;
+      height: calc(100vh - 137px);
+
+      .alarm-config-form {
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        padding: 20px 0 32px 32px;
+        width: 803px;
+        border-right: 1px solid rgba(0, 0, 0, 0.06);
+        overflow-y: auto;
+
+        .alarm-config-input {
+          max-width: 446px;
+        }
+
+        .alarm-config-checkbox-group {
+          max-height: 556px;
+          overflow: auto;
+        }
+      }
+      .alarm-config-example {
+        flex: 1;
+      }
+    }
+  }
+</style>

+ 190 - 0
src/views/message/alarm-config/components/AlarmExample.vue

@@ -0,0 +1,190 @@
+<template>
+  <div>
+    <div class="alarm-example">示例样式</div>
+    <el-tabs v-model="activeName" class="alarm-example-tabs" @tab-click="handleTabClick">
+      <el-tab-pane label="平台侧" :name="0">
+        <div style="width: 450px">
+          <div class="alarm-example-title"> <div class="alarm-example-block"></div>卡片页</div>
+          <div class="alarm-example-card">
+            <div class="alarm-example-card-head">
+              <div class="alarm-example-card-head-title">报警信息</div>
+              <div style="display: flex; justify-content: center">
+                <div class="alarm-example-card-head-btn">去查看</div>
+                <img src="@/assets/icons/arrow-right.png" alt="" />
+              </div>
+            </div>
+            <div class="alarm-example-card-content">
+              <img src="@/assets/images/alarm-example.png" alt="" />
+              <div class="alarm-example-card-content-time">2024年6月25日 16:45:06:342</div>
+              <div class="alarm-example-card-content-tips"
+                >您好,智能检测到该区域发现员工【安全帽违规】的情况,请及时关注!</div
+              >
+            </div>
+          </div>
+          <div class="alarm-example-title"><div class="alarm-example-block"></div>详情页</div>
+          <div class="alarm-example-detail">
+            <table>
+              <tr v-for="it in ExampleData">
+                <th>{{ it.th }}</th>
+                <td>{{ it.td }}</td>
+              </tr>
+              <tr>
+                <th>问题照片</th>
+                <td>
+                  <img src="@/assets/images/alarm-example-photo.png" alt="" />
+                  <img src="@/assets/images/alarm-example-photo.png" alt="" />
+                  <img src="@/assets/images/alarm-example-photo.png" alt="" />
+                </td>
+              </tr>
+            </table>
+          </div>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane label="蓝信侧" :name="1"></el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { ref } from 'vue';
+
+  const activeName = ref<number>(0);
+
+  const handleTabClick = (tab: any) => {
+    console.log(tab);
+  };
+
+  const ExampleData = [
+    {
+      th: '问题分类',
+      td: '安全帽违规',
+    },
+    {
+      th: '问题描述',
+      td: '关于问题类型的描述,大概300字以内',
+    },
+    {
+      th: '地点',
+      td: 'B26胶接车间-固化区',
+    },
+    {
+      th: '危险点负责人',
+      td: '李四',
+    },
+    {
+      th: '上报人',
+      td: '张三三',
+    },
+    {
+      th: '上报时间',
+      td: '20240315 12:00',
+    },
+  ];
+</script>
+
+<style lang="scss" scoped>
+  .alarm-example {
+    padding: 18px 0 0 20px;
+    font-weight: 500;
+    font-size: 14px;
+    color: rgba(0, 0, 0, 0.85);
+    line-height: 22px;
+  }
+
+  :deep(.el-tabs__nav-scroll) {
+    padding: 0 20px 0;
+  }
+  .alarm-example-title {
+    padding-left: 20px;
+    font-size: 14px;
+    color: #303133;
+    line-height: 20px;
+    .alarm-example-block {
+      margin-right: 20px;
+      width: 4px;
+      height: 12px;
+      background: #1777ff;
+      border-radius: 3px;
+      display: inline-block;
+    }
+  }
+
+  .alarm-example-card {
+    padding: 10px 0;
+    margin: 10px 20px;
+    border: 1px solid rgba(0, 0, 0, 0.06);
+    border-radius: 4px;
+
+    .alarm-example-card-head {
+      padding: 0 20px 10px;
+      border-bottom: 1px solid rgba(0, 0, 0, 0.06);
+      display: flex;
+      justify-content: space-between;
+      .alarm-example-card-head-title {
+        display: inline-block;
+        font-weight: 600;
+        font-size: 15px;
+        color: #646566;
+      }
+      .alarm-example-card-head-btn {
+        display: inline-block;
+        font-weight: 400;
+        font-size: 14px;
+        color: #1777ff;
+      }
+      img {
+        display: inline-block;
+        margin-left: 5px;
+        width: 18px;
+      }
+    }
+    .alarm-example-card-content {
+      padding: 3px 20px 10px;
+      .alarm-example-card-content-time {
+        padding: 10px 0;
+        font-weight: 400;
+        font-size: 12px;
+        color: #969799;
+      }
+      .alarm-example-card-content-tips {
+        font-weight: 400;
+        font-size: 13px;
+        color: #646566;
+      }
+    }
+  }
+
+  .alarm-example-detail {
+    table {
+      border-collapse: separate; /* 分开边框 */
+      border-spacing: 0; /* 消除边框间距 */
+
+      th,
+      td {
+        border-top: 1px solid rgba(0, 0, 0, 0.06);
+        border-left: 1px solid rgba(0, 0, 0, 0.06);
+        padding: 8px; /* 内边距 */
+        text-align: left; /* 文字对齐方式 */
+      }
+
+      td {
+        border-right: 1px solid rgba(0, 0, 0, 0.06);
+      }
+
+      tr:first-child th {
+        border-top-left-radius: 8px; /* 左上角圆角 */
+      }
+      tr:first-child td {
+        border-top-right-radius: 8px; /* 右上角圆角 */
+      }
+      tr:last-child th {
+        border-bottom: 1px solid rgba(0, 0, 0, 0.06);
+        border-bottom-left-radius: 8px; /* 左下角圆角 */
+      }
+      tr:last-child td {
+        border-bottom: 1px solid rgba(0, 0, 0, 0.06);
+        border-bottom-right-radius: 8px; /* 右下角圆角 */
+      }
+    }
+  }
+</style>

+ 51 - 0
src/views/message/alarm-config/components/PushOccasionsCard.vue

@@ -0,0 +1,51 @@
+<template>
+  <div class="push-occasions-card">
+    <!-- <el-form-item label="推送对象:">
+      <el-radio-group v-model="form.pushRecipients.type">
+        <el-radio v-for="item in PushRecipientType" :value="item.id">{{ item.label }}</el-radio>
+      </el-radio-group>
+    </el-form-item>
+    <el-form-item v-if="form.pushRecipients.type !== 1">asdad </el-form-item> -->
+    <!-- <el-form-item label="自定义内容:">
+        <el-input
+    v-model="form."
+    style="width: 240px"
+    :autosize="{ minRows: 2, maxRows: 4 }"
+    type="textarea"
+    :placeholder="holder"
+  />
+    </el-form-item> -->
+    <div>{{ '【' + (type || '') + '】' + form.pushPhase }}</div>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { PushRecipients } from '../types';
+  // import {
+  //   ElFormItem,
+  //   ElInput,
+  //   FormInstance,
+  //   FormRules,
+  // } from 'element-plus';
+
+  const props = defineProps<{
+    form: PushRecipients;
+    type?: string | undefined;
+  }>();
+
+  // 推送人员
+  // const PushRecipientType = [
+  //   { id: 1, label: '全员' },
+  //   { id: 2, label: '分组' },
+  //   { id: 3, label: '自定义' },
+  // ];
+</script>
+
+<style scoped lang="scss">
+  .push-occasions-card {
+    width: 541px;
+    height: 248px;
+    background-color: #fafafa;
+    font-size: 16px;
+  }
+</style>

+ 16 - 0
src/views/message/alarm-config/types.ts

@@ -0,0 +1,16 @@
+export interface AlarmConfigForm {
+  violationType: number | undefined;
+  violationLevel: string | undefined;
+  pushChannel: number[];
+  pushOccasions: number[];
+  pushPhaseVOList: PushRecipients[];
+  creator: string;
+}
+
+export interface PushRecipients {
+  content: string;
+  pushPhase: number | undefined;
+  recipientType: number | undefined;
+  userGroupList?: number[];
+  customUserList?: number[];
+}