Explorar o código

附件上传 ✔
督办提交 ✔
图片回显 ✔
弹窗遮罩
上传顺序 ✔
展示顺序 ✔

王哲 hai 2 meses
pai
achega
8d496b8371
Modificáronse 5 ficheiros con 420 adicións e 16 borrados
  1. 33 0
      src/api/forest.js
  2. 1 0
      src/views/SenEventCenter.vue
  3. 72 5
      src/views/SentryPage.vue
  4. 311 0
      src/views/eventLogUpload.vue
  5. 3 11
      vue.config.js

+ 33 - 0
src/api/forest.js

@@ -0,0 +1,33 @@
+import request from '@/utils/request'
+
+// 日志文件上传
+export function eventLogUpload(param) {
+  // 处理文件顺序 图片 → 视频 → 文件 → 未知文件
+
+  // 定义排序顺序
+  const order = ['jpg', 'png', 'mp4', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'zip', 'rar', 'txt'];
+
+  // 对attachList进行排序
+  param.attachList.sort((a, b) => {
+    // 获取文件扩展名(转换为小写以保持一致性)
+    const extA = a.fileName.split('.').pop().toLowerCase();
+    const extB = b.fileName.split('.').pop().toLowerCase();
+
+    // 获取扩展名在排序顺序中的索引
+    const indexA = order.indexOf(extA);
+    const indexB = order.indexOf(extB);
+
+    // 如果扩展名不在排序规则中,放到最后
+    if (indexA === -1 && indexB === -1) return 0;
+    if (indexA === -1) return 1;
+    if (indexB === -1) return -1;
+
+    return indexA - indexB;
+  });
+
+  return request({
+    url: '/sooka-digital-construction/eventSubject/eventAddAttach', // 旧路径是: '/center-event/centereventtfirelog',
+    method: 'post',
+    data: param
+  })
+}

+ 1 - 0
src/views/SenEventCenter.vue

@@ -385,6 +385,7 @@
         let that = this;
         let param = {
           createTimeRange:this.dataValue+","+this.dataValue,
+          createTimeRange:"2025-09-24"+","+"2025-09-24",
           eventTypeCode:"all"
         };
         getEventList(param).then(res => {

+ 72 - 5
src/views/SentryPage.vue

@@ -132,7 +132,7 @@
             <u :class="eventDetails.eventStatus=='event_archiving'||eventDetails.eventStatus=='event_review'?'date':''"></u>
             <div class="sjlc_div" :class="eventDetails.eventStatus=='event_archiving'||eventDetails.eventStatus=='event_review'?'date_div':''">
               <i><img src="../assets/images/sentinel/sb_icon6.png" /></i>
-              <h4>已经归档</h4>
+              <h4>事件归档</h4>
               <table class="tab-tabs" :class="eventDetails.eventStatus=='event_archiving'?'tab-data-tabs':''" border="0">
                 <tr><td class="tab-left">事件名称:</td><td class="tab-right">{{eventDetails.eventTitle}}</td></tr>
                 <tr><td class="tab-left">上报时间:</td><td class="tab-right">{{eventDetails.createTime}}</td></tr>
@@ -152,7 +152,35 @@
                 <el-card>
                   <h4>{{activity.logContent}}</h4>
                   <p>{{activity.createName}} 提交于 {{activity.createTime}}</p>
-                  <el-image v-if="activity.attachList.length>0" v-for="item in activity.attachList" :src="item.attachPath" style="width: 150px;"></el-image>
+                  <!--<el-image v-if="activity.attachList.length>0" v-for="item in activity.attachList" :src="item.attachPath" style="width: 150px;"></el-image>-->
+                  <!-- 图片、视频、文件 组件 -->
+                  <template v-if="activity.attachList.length>0" v-for="item in activity.attachList">
+                    <el-image v-if="item.attachPath.endsWith('.jpg') || item.attachPath.endsWith('.png')" style="width: 270px; height: 180px; margin-right: 9px;" :src="item.attachPath"></el-image>
+                    <video controls v-else-if="item.attachPath.endsWith('.mp4')" style="width: 270px; height: 180px; margin-right: 9px;" :src="item.attachPath"></video>
+                    <a v-else-if="item.attachPath.endsWith('.pdf')" :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">📄 {{ item.fileName }}</a>
+                    <a v-else-if="item.attachPath.endsWith('.doc')" :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">📝 {{ item.fileName }}</a>
+                    <a v-else-if="item.attachPath.endsWith('.docx')" :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">📝 {{ item.fileName }}</a>
+                    <a v-else-if="item.attachPath.endsWith('.xls')" :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">📊 {{ item.fileName }}</a>
+                    <a v-else-if="item.attachPath.endsWith('.xlsx')" :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">📊 {{ item.fileName }}</a>
+                    <a v-else-if="item.attachPath.endsWith('.ppt')" :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">📑 {{ item.fileName }}</a>
+                    <a v-else-if="item.attachPath.endsWith('.pptx')" :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">📑 {{ item.fileName }}</a>
+                    <a v-else-if="item.attachPath.endsWith('.zip')" :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">📦 {{ item.fileName }}</a>
+                    <a v-else-if="item.attachPath.endsWith('.rar')" :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">📦 {{ item.fileName }}</a>
+                    <a v-else-if="item.attachPath.endsWith('.txt')" :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">📃 {{ item.fileName }}</a>
+                    <a v-else :href="item.attachPath" style="width: 200px; height: 20px; display: block; color: #fff!important;">{{ item.fileName }}</a>
+
+                    <!--https://chat.deepseek.com/a/chat/s/8d9fb914-9500-442e-bc30-6d6cad5ba7e0-->
+                    <!--pdf: '📄',-->
+                    <!--doc: '📝',-->
+                    <!--docx: '📝',-->
+                    <!--xls: '📊',-->
+                    <!--xlsx: '📊',-->
+                    <!--ppt: '📑',-->
+                    <!--pptx: '📑',-->
+                    <!--zip: '📦',-->
+                    <!--rar: '📦',-->
+                    <!--txt: '📃'-->
+                  </template>
                 </el-card>
               </el-timeline-item>
             </el-timeline>
@@ -168,13 +196,15 @@
                     <el-radio :label="item.value" :name="item.value">{{ item.name }}</el-radio>
                   </el-radio-group>
                 </div>
-                <textarea class="spsb_text" v-model="reviewDescription"> </textarea>
+                <textarea class="spsb_text" v-model="reviewDescription" placeholder="请在此处填写督办信息"> </textarea>
                 <el-button type="primary"  v-if="eventDetails.eventStatus=='event_confirmation'" @click="eventSignature(eventDetails)">签收</el-button>
                 <el-button type="primary"  v-if="eventDetails.eventStatus=='event_signature'" @click="configDept(eventDetails)">联动</el-button>
                 <el-button type="primary"  v-if="eventDetails.eventStatus=='event_signature'" @click="eventCompletion(eventDetails)">办结</el-button>
                 <el-button type="primary"  v-if="eventDetails.eventStatus=='event_completion'" @click="eventReview(eventDetails)">审核</el-button>
                 <el-button type="primary"  v-if="eventDetails.eventStatus=='event_archiving'" @click="eventArchiving(eventDetails)">归档</el-button>
                 <button class="spsb_fs_btn" @click="addEventLogDescription(eventDetails)">督办</button>
+                <eventLogUpload ref="eventLogUpload" @openEventDetails = "openEventDetails"></eventLogUpload>
+                <el-button size="small" icon="el-icon-upload" style="padding-right: 70px" @click="showEventLogUpload(eventDetails)">上传附件</el-button>
               </div>
             </div>
           </div>
@@ -211,6 +241,7 @@
  <script>
     import Cookies from 'js-cookie'
 	import supermap from '@/components/supermap-2.5d' //超图
+    import eventLogUpload from '@/views/eventLogUpload.vue' //日志上传文件
 	import {
 		getUserProfile
 	} from "@/api/system/user";
@@ -239,6 +270,7 @@
     name: 'MyChart',
     components: {
       supermap,
+      eventLogUpload,
     },
     watch: {
       filterText(val) {
@@ -260,6 +292,8 @@
     },
     data() {
 			return {
+        eventId: null, // 文件上传、督办 事件ID
+
 				title: '四平市智慧哨兵监管平台',
         routerIdx:0,                    // 当前导航索引
         detailInfo:{},                  // 设备详情信息
@@ -307,6 +341,9 @@
 
 		},
     methods:{
+      showEventLogUpload(eventDetails) {
+        this.$refs.eventLogUpload.eventLogUpload(eventDetails)
+      },
       setPositioning(longitude, latitude) {
         this.$refs.SentryEmergencyCenter.setPositioning(longitude,latitude)
       },
@@ -571,12 +608,37 @@
 					this.$refs.supermap.removeAllviewer(mapDeptId, -1);
 				});
 			},
-      openEventDetails(params){
+      openEventDetails(params){ // 上传文件和督办 保存成功后也回调这个
+        this.eventId = params.eventId; // 详情 弹窗 事件ID
         this.isEventDetails = true;
         this.eventDetails = params;
-        this.activities =
+        // this.activities =
         getEventLog(params.eventId).then(req => {
           this.activities = req.data;
+          // 处理文件顺序 图片 → 视频 → 文件 → 未知文件
+
+          // 定义排序顺序
+          const order = ['jpg', 'png', 'mp4', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'zip', 'rar', 'txt'];
+
+          for(let activity of this.activities){
+            // 对attachList进行排序
+            activity.attachList.sort((a, b) => {
+              // 获取文件扩展名(转换为小写以保持一致性)
+              const extA = a.attachPath.split('.').pop().toLowerCase(); // fileName
+              const extB = b.attachPath.split('.').pop().toLowerCase(); // fileName
+
+              // 获取扩展名在排序顺序中的索引
+              const indexA = order.indexOf(extA);
+              const indexB = order.indexOf(extB);
+
+              // 如果扩展名不在排序规则中,放到最后
+              if (indexA === -1 && indexB === -1) return 0;
+              if (indexA === -1) return 1;
+              if (indexB === -1) return -1;
+
+              return indexA - indexB;
+            });
+          }
         })
       },
       // 弹框开启
@@ -590,8 +652,13 @@
       },
       // 添加日志信息
       addEventLogDescription(params){
+        if(this.reviewDescription == null || this.reviewDescription == ''){
+          this.$modal.msgWarning("请填写督办信息!")
+          return;
+        }
         addEventLogDescription({eventId:params.eventId,reviewDescription:this.reviewDescription}).then(req => {
           if(req.code == 200){
+            this.reviewDescription = ''; // 提交成功后清空督办内容
             this.$modal.msgSuccess('保存成功');
             this.openEventDetails(params)
           }

+ 311 - 0
src/views/eventLogUpload.vue

@@ -0,0 +1,311 @@
+<template>
+  <div class="upload-file">
+    <el-dialog title="文件上传" :visible.sync="showEventLogUpload" v-if="showEventLogUpload" width="525px"
+               style="height: 700px; margin-top: 401px; margin-left: 0px">
+      <el-upload
+        multiple
+        :action="uploadFileUrl"
+        :before-upload="handleBeforeUpload"
+        :file-list="fileList"
+        :limit="limit"
+        :on-error="handleUploadError"
+        :on-exceed="handleExceed"
+        :on-success="handleUploadSuccess"
+        :on-change="handleChange"
+        :show-file-list="false"
+        :headers="headers"
+        class="upload-file-uploader"
+        ref="upload"
+      >
+        <!-- 上传按钮 -->
+        <el-button size="mini" type="primary" style="padding-right: 62px">选取文件</el-button>
+        <!-- 上传提示 -->
+        <div class="el-upload__tip" slot="tip" v-if="showTip">
+          请上传
+          <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b></template>
+          <!--          <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join('/') }}</b></template>-->
+          的文件
+        </div>
+      </el-upload>
+
+      <!-- 文件列表 -->
+      <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
+        <li :key="file.url" class="el-upload-list__item ele-upload-list__item-content"
+            v-for="(file, index) in fileList">
+          <el-link :href="file.webUrl" :underline="false" target="_blank">
+            <span class="el-icon-document"> {{ file.webName }} </span>
+          </el-link>
+          <div class="ele-upload-list__item-content-action">
+            <el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
+          </div>
+        </li>
+      </transition-group>
+      <!-- 确认上传 -->
+      <el-button size="mini" type="primary" @click="submitUpload()" style="padding-right: 62px">确认上传</el-button>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getToken } from '@/utils/auth'
+import {
+  eventLogUpload
+} from '@/api/forest'
+
+export default {
+  name: 'FileUpload',
+  props: {
+    // 值
+    value: [String, Object, Array],
+    // 数量限制
+    limit: {
+      type: Number,
+      default: 15
+    },
+    // 大小限制(MB)
+    fileSize: {
+      type: Number,
+      default: 15
+    },
+    // // 文件类型, 例如['png', 'jpg', 'jpeg']
+    // fileType: {
+    //   type: Array,
+    //   default: () => []
+    // },
+    // 是否显示提示
+    isShowTip: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      eventId: null,
+      eventDetails: null,
+      // eventCode:null,
+      showEventLogUpload: false,
+      number: 0,
+      uploadList: [],
+      uploadFileUrl: process.env.VUE_APP_BASE_API + '/file/upload', // 上传的图片服务器地址
+      headers: {
+        Authorization: 'Bearer ' + getToken()
+      },
+      fileList: []
+    }
+  },
+  watch: {
+    value: {
+      handler(val) {
+        if (val) {
+          let temp = 1
+          // 首先将值转为数组
+          const list = Array.isArray(val) ? val : this.value.split(',')
+          // 然后将数组转为对象数组
+          this.fileList = list.map(item => {
+            if (typeof item === 'string') {
+              item = { name: item, url: item }
+            }
+            item.uid = item.uid || new Date().getTime() + temp++
+            return item
+          })
+        } else {
+          this.fileList = []
+          return []
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  computed: {
+    // 是否显示提示
+    showTip() {
+      return this.isShowTip
+    }
+  },
+  methods: {
+    submitUpload() {
+      let fileUrl=[]
+      if (this.fileList!=null&&this.fileList.length>0)
+      {
+        if(this.fileList!=null&&this.fileList.length>0){
+          for (let i = 0; i < this.fileList.length; i++) {
+            let file={attachPath:this.fileList[i].url,fileName:this.fileList[i].webName,busIndx:  "bus_indx_forest",busSource: "PC"}
+            fileUrl.push(file)
+          }
+        }else{
+          this.$message.error(`请选择上传文件!`)
+          return
+        }
+        // let param={ eventId:this.eventId,operation:"bus_oper_type_2",operationType:"log_oper_type_1",fileList: fileUrl }
+        // let param = {
+        //   eventCode:this.eventCode,
+        //   operation:"bus_oper_type_2",
+        //   operationType:"log_oper_type_1",
+        //   fileList: fileUrl
+        // }
+        // console.log("param = ", param);
+        let attachList = [];
+        for (let i = 0; i < fileUrl.length; i++) {
+          attachList.push({
+            "attachPath": fileUrl[i].attachPath, //附件路径 带文件名 group1/M00/00/26/wKgKC2jVBT2AM4EbAABDTnXaaDk333.png
+            "fileName": fileUrl[i].fileName, //附件名称 原文件名称 敬请期待.png
+            "dictType": "bus_oper_type_2", //附件类型
+            "dictValue": "log_oper_type_1" //附件类型实际值
+          })
+        }
+        let param = {
+          "attachList": attachList, //上传附件集合
+          "eventId": this.eventId //事件id
+        }
+        // let param = {
+        //   "attachList": [
+        //     {
+        //       "attachPath": "group/xxxx/xxxx.jpg", //附件路径
+        //       "fileName": "xxxx.jpg", //附件名称
+        //       "dictType": "xxxxx", //附件类型
+        //       "dictValue": "xxxxx" //附件类型实际值
+        //     }
+        //   ], //上传附件集合
+        //   "eventId": "xxxxxxx" //事件id
+        // }
+        //日志文件上传
+        eventLogUpload(param).then(res => {
+          if(res.code==200){
+            this.$message.success(`上传成功!`);
+            this.showEventLogUpload = false
+            this.cancelEventLogUploadShow();
+            // this.$parent.refreshEventDialog(this.eventCode)
+            // this.$parent.refreshEventDialog(this.eventId)
+            this.$parent.$parent.openEventDetails(this.eventDetails)
+          }
+        })
+      }else {
+        this.$message.warning(`请先上传文件!`);
+      }
+
+
+    },
+    handleChange(file, fileList) {
+      var _this = this;
+      if (file.raw) {
+        let reader = new FileReader()
+        reader.onload = function (e) {
+          _this.contentHtml = e.target.result;
+        };
+        reader.readAsText(file.raw,'gb2312');
+
+      }
+      console.log(file, fileList);
+    },
+    eventLogUpload(eventDetails) { // eventCode
+      // this.eventCode=eventCode
+      this.eventDetails = eventDetails;
+      this.eventId = eventDetails.eventId;
+      //上传页面弹出
+      this.showEventLogUpload = true
+    },
+    cancelEventLogUploadShow() {
+      //关闭页面
+      this.fileList = []
+      this.uploadList = []
+    },
+    // 上传前校检格式和大小
+    handleBeforeUpload(file) {
+      // 校检文件类型
+      if (false) {
+        let fileExtension = ''
+        if (file.name.lastIndexOf('.') > -1) {
+          fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
+        }
+        const isTypeOk = this.fileType.some((type) => {
+          if (file.type.indexOf(type) > -1) return true
+          if (fileExtension && fileExtension.indexOf(type) > -1) return true
+          return false
+        })
+        if (!isTypeOk) {
+          this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join('/')}格式文件!`)
+          return false
+        }
+      }
+      // 校检文件大小
+      if (this.fileSize) {
+        const isLt = file.size / 1024 / 1024 < this.fileSize
+        if (!isLt) {
+          this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`)
+          return false
+        }
+      }
+      this.$modal.loading('正在上传文件,请稍候...')
+      this.number++
+      return true
+    },
+    // 文件个数超出
+    handleExceed() {
+      this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`)
+    },
+    // 上传失败
+    handleUploadError(err) {
+      this.$modal.msgError('上传图片失败,请重试')
+      this.$modal.closeLoading()
+    },
+    // 上传成功回调
+    handleUploadSuccess(res) {
+      this.uploadList.push({ name: res.data.url, url: res.data.url, webName: res.data.webName })
+      if (this.uploadList.length === this.number) {
+        this.fileList = this.fileList.concat(this.uploadList)
+        this.uploadList = []
+        this.number = 0
+        this.$emit('input', this.listToString(this.fileList))
+        this.$modal.closeLoading()
+      }
+    },
+    // 删除文件
+    handleDelete(index) {
+      this.fileList.splice(index, 1)
+      this.$emit('input', this.listToString(this.fileList))
+    },
+    // 获取文件名称
+    getFileName(name) {
+      if (name.lastIndexOf('/') > -1) {
+        return name.slice(name.lastIndexOf('/') + 1)
+      } else {
+        return ''
+      }
+    },
+    // 对象转成指定字符串分隔
+    listToString(list, separator) {
+      let strs = ''
+      separator = separator || ','
+      for (let i in list) {
+        strs += list[i].url + separator
+      }
+      return strs != '' ? strs.substr(0, strs.length - 1) : ''
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.upload-file-uploader {
+  margin-bottom: 5px;
+}
+
+.upload-file-list .el-upload-list__item {
+  border: 1px solid #e4e7ed;
+  line-height: 2;
+  margin-bottom: 10px;
+  position: relative;
+}
+
+.upload-file-list .ele-upload-list__item-content {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  color: inherit;
+}
+
+.ele-upload-list__item-content-action .el-link {
+  margin-right: 10px;
+}
+</style>

+ 3 - 11
vue.config.js

@@ -39,21 +39,13 @@ module.exports = {
     //   key : fs.readFileSync(ssl_path.join(__dirname,'src/ssl/supermap.key'))
     // },
 
-    /**
-     * 昨夜星辰昨夜风
-     * 画廊西畔桂堂东
-     * 身无彩凤双飞翼
-     * 心有灵犀一点通
-     *
-     * 寻找附件-有缘人@阿弥陀佛
-     * @param attach_ids
-     */
-
     proxy: {
       // detail: https://cli.vuejs.org/config/#devserver-proxy
       [process.env.VUE_APP_BASE_API]: {
         // target: `http://10.6.52.11:3031`,
-		target: `http://192.168.4.5:3031`,
+		// target: `http://192.168.4.5:3031`,
+		// target: `http://192.168.4.9:3031`,
+		target: `http://192.168.10.12:3041`,
         changeOrigin: true,
         pathRewrite: {
           ['^' + process.env.VUE_APP_BASE_API]: ''