Browse Source

上传速运行李

zhongxiaoyu 2 years ago
parent
commit
7415793c66

+ 7 - 1
public/config.js

@@ -52,6 +52,10 @@ window.DATACONTENT_ID = {
   sysServiceWarnId: 18030, //预警报警场景(按照ID)
   sysServiceStrategyId: 18033, //预警报警策略(按照ID)
   sysServiceStrategyaddId: 8014, //新增预警报警策略
+
+  /***-----速运行李------***/
+  expressTransportation: 1803432, // 速运行李数据查询
+
   /***-----进港管理------***/
   arrivalAirId: 67, //进港管理-机场选择
   arrivalTableId: 38, //进港管理-表格
@@ -194,5 +198,7 @@ window.SERVICE_ID = {
   sysServiceEditBoxId: 4, //系统设置-服务管理-编辑服务-部署机器-多选框
   sysQueryTabId: 5, //系统设置-查询模板-表格-增删改
   sysServiceAddXyId: 10, //系统设置-服务管理-新增服务-新增数据源-提交
-  sysDataTabId: 9 //系统设置-数据结构-数据项-表格-增删改
+  sysDataTabId: 9, //系统设置-数据结构-数据项-表格-增删改
+
+  expressTransportation: 20037, // 速运行李数据查询
 }

+ 3 - 1
public/staticConfig.js

@@ -6,7 +6,9 @@ window.PLATFROM_CONFIG = {
   appId: "q7kdjmmaf0kerwpf", //appid
   baseURLCA: "http://10.211.67.163:16300", // 登录后的http请求地址-测试
   baggageMessageURL: "/openApi/query",
-  getBase64: 'http://10.211.67.163:8083/getBase64'
+  getBase64: 'http://10.211.67.163:8083/getBase64',
+  fileUrl: 'http://10.211.66.23:8082',
+  expressUrl: 'http://10.211.67.177:8043'
 };
 
 /* 轮询间隔 */

+ 31 - 7
src/api/dataIntegration.js

@@ -10,7 +10,7 @@
 import request from '@/utils/request'
 import { Message } from 'element-ui'
 
-export function GeneralDataReception (params) {
+export function GeneralDataReception(params) {
   return request({
     url: '/openApi/generalDataReception',
     method: 'post',
@@ -21,7 +21,7 @@ export function GeneralDataReception (params) {
   })
 }
 
-export function Query (params) {
+export function Query(params) {
   return request({
     url: '/openApi/query',
     method: 'post',
@@ -32,8 +32,8 @@ export function Query (params) {
   })
 }
 
-//服务管理-启动
-export function Start (params) {
+// 服务管理-启动
+export function Start(params) {
   return request({
     url: '/openApi/start',
     method: 'post',
@@ -44,8 +44,8 @@ export function Start (params) {
   })
 }
 
-//服务管理-停止
-export function Stop (params) {
+// 服务管理-停止
+export function Stop(params) {
   return request({
     url: '/openApi/stop',
     method: 'post',
@@ -56,7 +56,7 @@ export function Stop (params) {
   })
 }
 
-export async function myQuery (id, ...dataContent) {
+export async function myQuery(id, ...dataContent) {
   const params = {
     id,
     dataContent
@@ -73,3 +73,27 @@ export async function myQuery (id, ...dataContent) {
     return Promise.reject(error)
   }
 }
+
+// 上传文件
+export function UploadFile(params) {
+  return request({
+    url: `${PLATFROM_CONFIG.fileUrl}/openApi/upload`,
+    method: 'post',
+    headers: {
+      'content-type': 'multipart/form-data'
+    },
+    data: params
+  })
+}
+
+// 不知道什么的查询
+export function WhatQuery(params) {
+  return request({
+    url: `${PLATFROM_CONFIG.expressUrl}/openApi/query`,
+    method: 'post',
+    headers: {
+      'content-type': 'application/json'
+    },
+    data: params
+  })
+}

BIN
src/assets/nav/ic_ex.png


BIN
src/assets/nav/ic_list_nav_upload_check.png


BIN
src/assets/nav/ic_list_nav_upload_check@2x.png


BIN
src/assets/nav/ic_list_nav_upload_default.png


BIN
src/assets/nav/ic_list_nav_upload_default@2x.png


+ 13 - 0
src/layout/components/Sidebar/SidebarItem.vue

@@ -221,6 +221,10 @@ export default {
     background: url("../../../assets/nav/ic_list_nav_screen_check.png")
       no-repeat;
   }
+  .upload {
+    background: url("../../../assets/nav/ic_list_nav_upload_check.png")
+      no-repeat;
+  }
 }
 // ::v-deep .el-menu-item {
 //   transition: border-color 0.3s, background-color 0s, color 0s;
@@ -429,6 +433,15 @@ export default {
   }
 }
 
+.upload {
+  background: url("../../../assets/nav/ic_list_nav_upload_default.png")
+    no-repeat;
+  &:hover {
+    background: url("../../../assets/nav/ic_list_nav_upload_check.png")
+      no-repeat;
+  }
+}
+
 // .el-tooltip__popper.is-dark{
 //   background: #255395;
 // }

+ 3 - 1
src/layout/components/Sidebar/index.vue

@@ -196,7 +196,6 @@ export default {
     .BasicsData {
       background: url("../../../assets/nav/ic_data_collection_check.png") no-repeat;
     }
-
     .systemSettings {
       background: url("../../../assets/nav/ic_setting_nav_check.png") no-repeat;
     }
@@ -206,6 +205,9 @@ export default {
     .statisticalAnalysis {
       background: url("../../../assets/nav/ic_list_nav_screen_check.png") no-repeat;
     }
+    .upload {
+      background: url("../../../assets/nav/ic_list_nav_upload_check.png") no-repeat;
+    }
   }
 }
 </style>

+ 2 - 1
src/router/index.js

@@ -20,6 +20,7 @@ import routesTwo from './routes/routes-file-two'
 import routesFileFour from './routes/routes-file-four'
 import routesFive from './routes/routes-file-five'
 import routesFileSix from './routes/routes-file-six'
+import routesFileSeven from './routes/routes-file-seven'
 
 /**
  * Note: sub-menu only appear when route children.length >= 1
@@ -70,7 +71,7 @@ export const constantRoutes = [
 // 动态路由
 export const asyncRoutes = []
 // 插入路由
-routesPush([...routesOne, ...routesTwo, ...routesFileFour, ...routesFive, ...routesFileSix], asyncRoutes)
+routesPush([...routesOne, ...routesTwo, ...routesFileFour, ...routesFileSeven, ...routesFileSix, ...routesFive], asyncRoutes)
 // asyncRoutes.push({ path: '/', component: () => import('@/views/noPower'), hidden: true })
 asyncRoutes.push({
   path: '*',

+ 31 - 0
src/router/routes/routes-file-seven.js

@@ -0,0 +1,31 @@
+import Layout from '@/layout'
+
+const uploadRoutes = {
+  path: '/upload',
+  component: Layout,
+  children: [
+    {
+      path: '/upload',
+      meta: {
+        title: '速运行李上传',
+        imgstyle: 'ic_list_nav_upload_default.png',
+        imgstyleup: 'ic_list_nav_upload_check.png'
+      },
+      component: {
+        render(c) {
+          return c('router-view')
+        }
+      },
+      children: [
+        {
+          path: '/upload',
+          name: 'UploadView',
+          meta: { title: '速运行李上传' },
+          component: () => import('@/views/upload/index.vue')
+        }
+      ]
+    }
+  ]
+}
+
+export default [uploadRoutes]

+ 2 - 1
src/utils/request.js

@@ -29,7 +29,8 @@ service.interceptors.request.use(
       // ['X-Token'] is a custom headers key
       // please modify it according to the actual situation
       // config.headers['X-Token'] = getToken()
-      config.headers["token"] = getToken();
+      // config.headers["token"] = getToken();
+      config.headers["token"] = config.headers["token"] ?? getToken();
     }
     if (config.data) {
       config.data["OperatorId"] = getUserId();

+ 11 - 6
src/views/advancedQuery/views/advancedHome.vue

@@ -1040,6 +1040,7 @@ export default {
       const top2 = /^([a-zA-Z][0-9])|([0-9][a-zA-Z])|([a-zA-Z]{2})/
       const bagNum = /^[0-9]{10}$/
       const bagNo = /^[a-zA-Z]{2}[0-9]{6}$/
+      const bagNumCA = /^CA[0-9]{6}$/
       // 纯字母则为旅客姓名
       if (az.test(val)) {
         this.form['passengerName'] = val
@@ -1048,7 +1049,7 @@ export default {
         // 字母加数字且前两位为字母则为航班号
         this.form['flightNO'] = val
         this.advancedSubmitHandler(true)
-      } else if (bagNum.test(val) || bagNo.test(val)) {
+      } else if (bagNum.test(val) || bagNo.test(val) || bagNumCA.test(val)) {
         // 纯数字且位数等于10则为行李牌号
         this.form['baggageNO'] = val
         this.advancedSubmitHandler(true)
@@ -1077,6 +1078,13 @@ export default {
           return ''
         }
       }
+      function baggageFormat(baggageNO) {
+        const bagNumCA = /^CA[0-9]{6}$/
+        if (bagNumCA.test(baggageNO)) {
+          return baggageNO.replace('CA', '3999')
+        }
+        return baggageNO
+      }
       this.resetTable()
       /* 参数顺序
       【航班开始日期,航班结束日期,航班号,航班号,行李牌号,行李牌号,起飞站,起飞站,目的站,目的站,特殊行李类型,特殊行李类型,旅客姓名大写拼音,旅客姓名大写拼音,
@@ -1116,7 +1124,7 @@ export default {
       } = this.form
       this.setDataContent(
         flightNO,
-        baggageNO,
+        baggageFormat(baggageNO),
         departureStation,
         destination,
         specialType.map(v => v.replace(',', '/')).join(),
@@ -1244,10 +1252,7 @@ export default {
 }
 </script>
 
-<style
-  lang="scss"
-  scoped
->
+<style lang="scss" scoped>
 .advance {
   padding: 8px;
   &__head {

+ 19 - 4
src/views/advancedQuery/views/advancedNew.vue

@@ -601,6 +601,13 @@ export default {
       }
     },
     advancedQueryHandler(singleJump) {
+      function baggageFormat(baggageNO) {
+        const bagNumCA = /^CA[0-9]{6}$/
+        if (bagNumCA.test(baggageNO)) {
+          return baggageNO.replace('CA', '3999')
+        }
+        return baggageNO
+      }
       try {
         if (this.dialogFlag) {
           this.$refs['paramsForm'].validate(valid => {
@@ -613,6 +620,12 @@ export default {
         const paramsRowNum = this.paramsForm.params.length
         const queryString = this.paramsForm.params.reduce(
           (preString, { leftBrackets, paramKey, comparisonOperator, paramValue, rightBrackets, connector }, index) => {
+            let formattedValue
+            if (paramKey === 'bagSN') {
+              formattedValue = baggageFormat(paramValue)
+            } else {
+              formattedValue = paramValue
+            }
             bracketsDifference += leftBrackets.length - rightBrackets.length
             if (bracketsDifference < 0) {
               throw new Error('左右括号不匹配!')
@@ -620,11 +633,11 @@ export default {
             preString += leftBrackets + paramKey + ` ${comparisonOperator} `
             if (!['is Null', 'is not Null'].includes(comparisonOperator)) {
               if (comparisonOperator === 'like') {
-                preString += `\'%${paramValue}%\'`
+                preString += `\'%${formattedValue}%\'`
               } else if (this.columnSet[paramKey].dataType === 'number') {
-                preString += paramValue
+                preString += formattedValue
               } else {
-                preString += `\'${paramValue}\'`
+                preString += `\'${formattedValue}\'`
               }
             }
             preString += rightBrackets + (index < paramsRowNum - 1 ? ` ${connector} ` : '')
@@ -771,6 +784,7 @@ export default {
               passengerName: row.passengerName
             })
             this.$store.dispatch('app/togglePassengerDialogFlag', true)
+            break
           case 'bagSN':
             this.$router.push({
               path: '/advance/baggageView',
@@ -848,6 +862,7 @@ export default {
       const top2 = /^([a-zA-Z][0-9])|([0-9][a-zA-Z])|([a-zA-Z]{2})/
       const num = /^[0-9]+$/
       const bagNo = /^[a-zA-Z]{2}[0-9]{6}$/
+      const bagNumCA = /^CA[0-9]{6}$/
       if (az.test(val)) {
         // 纯字母则为旅客姓名
         this.paramsForm.params.push({
@@ -868,7 +883,7 @@ export default {
           rightBrackets: '',
           connector: 'and'
         })
-      } else if ((num.test(val) && val.length === 10) || bagNo.test(val)) {
+      } else if ((num.test(val) && val.length === 10) || bagNo.test(val) || bagNumCA.test(val)) {
         // 纯数字且位数等于10则为行李牌号
         this.paramsForm.params.push({
           leftBrackets: '',

+ 430 - 0
src/views/upload/index.vue

@@ -0,0 +1,430 @@
+<template>
+  <div class="upload">
+    <div class="upload-wrapper">
+      <header class="upload-header">
+        <div class="manageTitle">{{ title }}</div>
+        <el-upload
+          ref="upload"
+          action="#"
+          multiple
+          :loading="exceed"
+          :accept="acceptTypesStr"
+          :show-file-list="false"
+          :http-request="uploadHandler"
+          :before-upload="beforeUpload"
+        >
+          <el-button
+            slot="trigger"
+            type="primary"
+            size="small"
+          >
+            上传文件
+          </el-button>
+        </el-upload>
+      </header>
+      <main class="upload-main">
+        <ul
+          v-if="totalProgressList.length"
+          class="upload-list"
+        >
+          <li
+            v-for="(item, index) in totalProgressList"
+            :key="item.key"
+            class="upload-list-item"
+          >
+            <div class="upload-list-item-wrapper">
+              <div class="upload-list-item-image">
+                <img
+                  src="@/assets/nav/ic_ex.png"
+                  :alt="item.fileName"
+                />
+              </div>
+              <div class="upload-list-item-details">
+                <div>
+                  <span class="upload-list-item-name">{{ item.fileName }}</span>
+                  <span
+                    class="upload-list-item-state"
+                    :class="stateClass(item.state)"
+                    >{{ stateFormat(item.state) }}</span
+                  >
+                  <i
+                    v-show="item.state === 2"
+                    class="upload-list-item-retry el-icon-refresh-right"
+                    @click="retry(item)"
+                  />
+                </div>
+                <div>
+                  <span class="upload-list-item-time">{{ item.time }}</span>
+                </div>
+              </div>
+            </div>
+            <el-divider v-if="index !== totalProgressList.length - 1" />
+          </li>
+        </ul>
+        <NoData
+          v-else
+          :image-width="230"
+          :image-height="160"
+        />
+      </main>
+    </div>
+    <div class="upload-wrapper">
+      <header class="upload-header">
+        <div class="manageTitle">{{ title2 }}</div>
+        <el-date-picker
+          v-model="flightDate"
+          size="small"
+          type="daterange"
+          value-format="yyyy-MM-dd"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          :picker-options="dateRangePickerOptions"
+          :clearable="false"
+        />
+      </header>
+      <main
+        v-loading="loading"
+        element-loading-text="拼命加载中"
+        element-loading-spinner="el-icon-loading"
+        element-loading-background="rgba(0, 0, 0, 0.8)"
+        class="upload-main"
+      >
+        <el-table
+          :data="tableData"
+          border
+          stripe
+          fit
+          height="100%"
+          class="upload-table"
+        >
+          <el-table-column
+            v-for="column in tableColumns"
+            :key="column.key"
+            :prop="column.prop"
+            :label="column.prop"
+          />
+          <template #empty>
+            <NoData
+              :image-width="230"
+              :image-height="160"
+            />
+          </template>
+        </el-table>
+      </main>
+    </div>
+  </div>
+</template>
+
+<script>
+import { parseTime } from '@/utils'
+import { UploadFile, WhatQuery } from '@/api/dataIntegration'
+import NoData from '@/components/nodata/index.vue'
+
+const acceptTypes = ['xlsx', 'xls']
+const acceptTypesStr = acceptTypes.reduce((prevStr, currStr) => {
+  return `${prevStr}${prevStr ? ',' : ''}.${currStr}`
+}, '')
+
+const units = ['B', 'KB', 'MB', 'GB']
+const getUnit = (size, callTime = 0) => {
+  if (size < 1024) {
+    return `${size}${units[callTime]}`
+  }
+  return getUnit(size / 1024, callTime + 1)
+}
+const maxSize = 20 * 1024 * 1024
+const short = getUnit(maxSize)
+
+export default {
+  name: 'Upload',
+  components: { NoData },
+  data() {
+    return {
+      title: '速运行李上传',
+      acceptTypesStr: acceptTypesStr,
+      totalProgressList: [],
+      limit: 3,
+      title2: '速运行李数据',
+      flightDate: new Array(2).fill(parseTime(new Date(), '{y}-{m}-{d}')),
+      dateRangePickerOptions: {
+        onPick: this.dateRangePickHandler,
+        disabledDate: this.dateRangeDisabled
+      },
+      tableColumns: [
+        {
+          prop: 'C0'
+        },
+        {
+          prop: 'C1'
+        },
+        {
+          prop: 'C2'
+        },
+        {
+          prop: 'C3'
+        },
+        {
+          prop: 'C4'
+        },
+        {
+          prop: 'C5'
+        },
+        {
+          prop: 'C6'
+        },
+        {
+          prop: 'C7'
+        },
+        {
+          prop: 'C8'
+        },
+        {
+          prop: 'C9'
+        },
+        {
+          prop: 'createtime'
+        }
+      ],
+      tableData: [],
+      loading: false
+    }
+  },
+  computed: {
+    currentProgressNum() {
+      return this.totalProgressList.reduce((prevCount, currentProgress) => {
+        return currentProgress.state > 0 ? prevCount : prevCount + 1
+      }, 0)
+    },
+    exceed() {
+      return this.currentProgressNum >= this.limit
+    }
+  },
+  watch: {
+    flightDate: {
+      handler() {
+        this.getTableData()
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  methods: {
+    beforeUpload(file) {
+      const progress = this.getProgress(file)
+      if (progress && progress.state === 0) {
+        this.$message.warning(`${file.name} 上传中,请勿重复上传`)
+        return
+      }
+      if (this.exceed) {
+        this.$message.warning(`${file.name} 上传出错:超出最大同时上传数量,最多同时上传 ${this.limit} 个文件`)
+      }
+      const extensionName = file.name.split('.').pop()
+      const acceptExtention = acceptTypes.includes(extensionName)
+      if (!acceptExtention) {
+        this.$message.warning(`${file.name} 上传出错:上传文件只能是 ${acceptTypes.join('/')} 格式`)
+        return false
+      }
+      if (file.size > maxSize) {
+        this.$message.warning(`${file.name} 上传出错:上传文件大小不能超过 ${short}`)
+        return false
+      }
+    },
+    uploadHandler({ file }) {
+      if (!this.exceed) {
+        this.uploadFile(file)
+      }
+      const progress = this.getProgress(file)
+      if (progress) {
+        progress.state = this.exceed ? 2 : 0
+        return
+      }
+      const newProgress = {
+        file,
+        key: `${file.name}${file.lastModified}`,
+        fileName: file.name,
+        state: this.exceed ? 2 : 0,
+        time: parseTime(Date.now(), '{y}-{m}-{d} {h}:{i}:{s}')
+      }
+      this.totalProgressList.push(newProgress)
+    },
+    stateClass(state) {
+      const classMap = ['pending', 'success', 'failure']
+      return `upload-list-item-state-${classMap[state]}`
+    },
+    stateFormat(state) {
+      const textMap = ['上传中···', '上传成功', '上传失败']
+      return textMap[state]
+    },
+    setState(file, state) {
+      const progress = this.getProgress(file)
+      if (progress) {
+        progress.state = state
+      }
+    },
+    getProgress(file) {
+      const key = `${file.name}${file.lastModified}`
+      return this.totalProgressList.find(progress => progress.key === key)
+    },
+    retry(progress) {
+      if (this.exceed) {
+        this.$message.warning('已达到最大同时上传数量,请稍后再试')
+        return
+      }
+      this.uploadFile(progress.file)
+      progress.state = 0
+    },
+    async uploadFile(file) {
+      try {
+        const formData = new FormData()
+        formData.append('file', file)
+        formData.append('serviceId', SERVICE_ID.expressTransportation)
+        const { code } = await UploadFile(formData)
+        if (Number(code) !== 0) {
+          throw new Error('失败')
+        }
+        this.$message.success(`${file.name} 上传成功`)
+        this.setState(file, 1)
+      } catch (error) {
+        this.$message.error(`${file.name} 上传失败`)
+        this.setState(file, 2)
+      }
+    },
+    dateRangePickHandler({ maxDate, minDate }) {
+      if (!maxDate) {
+        this.pickedDate = minDate
+      } else {
+        this.pickedDate = null
+      }
+    },
+    dateRangeDisabled(date) {
+      return this.pickedDate ? Math.abs(date - this.pickedDate) > 2 * 24 * 60 * 60 * 1000 : false
+    },
+    async getTableData() {
+      this.loading = true
+      try {
+        const dataContent = [this.flightDate[0], this.flightDate[1]]
+        const {
+          code,
+          returnData: { listValues }
+        } = await WhatQuery({
+          id: DATACONTENT_ID.expressTransportation,
+          dataContent
+        })
+        if (Number(code) !== 0) {
+          throw new Error('失败')
+        }
+        this.tableData = listValues
+      } catch (error) {
+        this.$message.error('查询表格失败')
+      }
+      this.loading = false
+    }
+  }
+}
+</script>
+
+<style
+  lang="scss"
+  scoped
+>
+.upload {
+  width: 100%;
+  height: calc(100vh - 100px);
+  padding: 24px 24px 0;
+  &-wrapper {
+    width: 100%;
+    padding: 24px 24px 0;
+    background-color: #fff;
+    &:nth-child(1) {
+      height: calc(24px + 32px + 30px + 3 * 63px + 26px);
+    }
+    &:nth-child(2) {
+      height: calc(100% - (24px + 32px + 30px + 3 * 63px + 26px));
+    }
+  }
+  &-header {
+    display: flex;
+    justify-content: space-between;
+  }
+  &-main {
+    height: calc(100% - 32px);
+    padding-top: 30px;
+  }
+  &-list {
+    margin: 0;
+    padding: 0;
+    width: 100%;
+    height: 100%;
+    overflow-x: hidden;
+    overflow-y: auto;
+    &-item {
+      &-wrapper {
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+      }
+      &-image {
+        margin-right: 16px;
+      }
+      &-details {
+        font-size: 14px;
+        font-family: Helvetica, 'Microsoft YaHei';
+        > div {
+          height: 16px;
+          line-height: 16px;
+          &:first-child {
+            margin-bottom: 6px;
+          }
+        }
+      }
+      &-name {
+        color: #303133;
+        margin-right: 16px;
+      }
+      &-state {
+        &-success {
+          color: #40a349;
+        }
+        &-failure {
+          color: #d53e3e;
+        }
+      }
+      &-retry {
+        width: 16px;
+        height: 16px;
+        text-align: center;
+        line-height: 16px;
+        border-radius: 50%;
+        margin-left: 16px;
+        font-size: 14px;
+        color: #2d67e3;
+        cursor: pointer;
+        &:hover {
+          background-color: #2d67e3;
+          color: #fff;
+        }
+      }
+      &-time {
+        color: #afb4bf;
+      }
+    }
+  }
+  ::v-deep &-table {
+    width: 100%;
+    .cell {
+      padding: 0;
+      text-align: center;
+      font-size: 14px;
+      font-family: Helvetica, 'Microsoft YaHei';
+      letter-spacing: 0;
+    }
+    .el-table__header-wrapper,
+    .el-table__fixed-header-wrapper {
+      .cell {
+        font-weight: bold;
+        color: #101116;
+      }
+    }
+  }
+}
+</style>