吉安感知网项目-前端
罗广辉
2026-01-22 eb1fe28cdab2ce1297273f8c2427726f82535f7a
feat: axios使用实例
6 files modified
507 ■■■■ changed files
applications/task-work-order/src/App.vue 3 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/axios.js 464 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/index.vue 4 ●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue 24 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderManage/orderManage/RefuseOrderDialog.vue 8 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderManage/orderManage/index.vue 4 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/App.vue
@@ -2,9 +2,8 @@
  <router-view />
</template>
<script setup>
</script>
<style>
applications/task-work-order/src/axios.js
@@ -6,240 +6,242 @@
 * isToken是否需要token
 */
import axios from 'axios';
import store from '@/store/';
import router from '@/router/';
import { serialize } from '@/utils/util';
import { getToken, removeToken, removeRefreshToken } from '@/utils/auth';
import { isURL, validatenull } from '@/utils/validate';
import { ElMessage } from 'element-plus';
import website from '@/config/website';
import { Base64 } from 'js-base64';
import { baseUrl } from '@/config/env';
import crypto from '@/utils/crypto';
const adminUrl = import.meta.env.VITE_APP_DASHBOARD_URL;
import axios from 'axios'
import store from '@/store/'
import router from '@/router/'
import { serialize } from '@/utils/util'
import { getToken, removeToken, removeRefreshToken } from '@/utils/auth'
import { isURL, validatenull } from '@/utils/validate'
import { ElMessage } from 'element-plus'
import website from '@/config/website'
import { Base64 } from 'js-base64'
import { baseUrl } from '@/config/env'
import crypto from '@/utils/crypto'
const adminUrl = import.meta.env.VITE_APP_DASHBOARD_URL
// 全局未授权错误提示状态,只提示一次
let isErrorShown = false;
let isErrorShown = false
let _retry = false;
// 超时时间设置为10分钟,部分接口上传比较慢,如固件上传
axios.defaults.timeout = 600000;
//返回其他状态码
axios.defaults.validateStatus = function (status) {
  return status >= 200 && status <= 500; // 默认的
};
//跨域请求,允许保存cookie
axios.defaults.withCredentials = true;
let _retry = false
// 创建作用域的 axios 实例
const service = axios.create({
    // 超时时间设置为10分钟,部分接口上传比较慢,如固件上传
    timeout: 600000,
    //返回其他状态码
    validateStatus: function (status) {
        return status >= 200 && status <= 500 // 默认的
    },
    //跨域请求,允许保存cookie
    withCredentials: true,
})
//http request拦截
axios.interceptors.request.use(
  config => {
    // 初始化错误提示状态
    isErrorShown = false;
    //地址为已经配置状态则不添加前缀
    if (!isURL(config.url) && !config.url.startsWith(baseUrl)) {
      config.url = baseUrl + config.url;
    }
    //安全请求header
    config.headers['areaCode'] = config?.params?.areaCode || store?.state?.user?.userInfo?.detail?.areaCode;
    config.headers['Blade-Requested-With'] = 'BladeHttpRequest';
    //headers判断是否需要
    const authorization = config.authorization === false;
    if (!authorization) {
      config.headers['Authorization'] = `Basic ${Base64.encode(
        `${website.clientId}:${website.clientSecret}`
      )}`;
    }
    // 后端的要求
    if (router.currentRoute.value.path === '/job/jobstatistics'){
      const userAreaCode = store?.state?.user?.userInfo?.detail?.areaCode
      const paramsKey = config.method === 'get' ? 'params' : 'data';
      const codeKey = config.method === 'get' ? 'areaCode' : 'area_code';
      const paramCode = config?.params?.areaCode || config?.data?.area_code
      try {
        if (paramCode){
          if (paramCode === userAreaCode) {
            config[paramsKey][codeKey] = config.method === 'get' ? '' : undefined;
          } else {
            if (!Array.isArray(config[paramsKey])){
              config[paramsKey] = {...config[paramsKey],[codeKey]: paramCode}
            }
          }
        }
      }catch (e) {}
    }
service.interceptors.request.use(
    config => {
        // 初始化错误提示状态
        isErrorShown = false
        //地址为已经配置状态则不添加前缀
        if (!isURL(config.url) && !config.url.startsWith(baseUrl)) {
            config.url = baseUrl + config.url
        }
        //安全请求header
        config.headers['areaCode'] = config?.params?.areaCode || store?.state?.user?.userInfo?.detail?.areaCode
        config.headers['Blade-Requested-With'] = 'BladeHttpRequest'
        //headers判断是否需要
        const authorization = config.authorization === false
        if (!authorization) {
            config.headers['Authorization'] = `Basic ${Base64.encode(`${website.clientId}:${website.clientSecret}`)}`
        }
        // 后端的要求
        if (router.currentRoute.value.path === '/job/jobstatistics') {
            const userAreaCode = store?.state?.user?.userInfo?.detail?.areaCode
            const paramsKey = config.method === 'get' ? 'params' : 'data'
            const codeKey = config.method === 'get' ? 'areaCode' : 'area_code'
            const paramCode = config?.params?.areaCode || config?.data?.area_code
            try {
                if (paramCode) {
                    if (paramCode === userAreaCode) {
                        config[paramsKey][codeKey] = config.method === 'get' ? '' : undefined
                    } else {
                        if (!Array.isArray(config[paramsKey])) {
                            config[paramsKey] = { ...config[paramsKey], [codeKey]: paramCode }
                        }
                    }
                }
            } catch (e) {}
        }
    //headers判断请求是否携带token
    const meta = config.meta || {};
    const isToken = meta.isToken === false;
    //headers传递token是否加密
    const cryptoToken = config.cryptoToken === true;
    //判断传递数据是否加密
    const cryptoData = config.cryptoData === true;
    const token = getToken();
    if (token && !isToken) {
      config.headers[website.tokenHeader] = cryptoToken
        ? 'crypto ' + crypto.encryptAES(token, crypto.cryptoKey)
        : 'bearer ' + token;
    }
    // 开启报文加密
    // if (cryptoData) {
    //   if (config.params) {
    //     const data = crypto.encryptAES(JSON.stringify(config.params), crypto.aesKey);
    //     config.params = { data };
    //   }
    //   if (config.data) {
    //     config.text = true;
    //     config.data = crypto.encryptAES(JSON.stringify(config.data), crypto.aesKey);
    //   }
    // }
    //headers中配置text请求
    if (config.text === true) {
      config.headers['Content-Type'] = 'text/plain';
    }
    //headers中配置serialize为true开启序列化
    if (config.method === 'post' && meta.isSerialize === true) {
      config.data = serialize(config.data);
    }
    return config;
  },
  error => {
    return Promise.reject(error);
  }
);
        //headers判断请求是否携带token
        const meta = config.meta || {}
        const isToken = meta.isToken === false
        //headers传递token是否加密
        const cryptoToken = config.cryptoToken === true
        //判断传递数据是否加密
        const cryptoData = config.cryptoData === true
        const token = getToken()
        if (token && !isToken) {
            config.headers[website.tokenHeader] = cryptoToken
                ? 'crypto ' + crypto.encryptAES(token, crypto.cryptoKey)
                : 'bearer ' + token
        }
        // 开启报文加密
        // if (cryptoData) {
        //   if (config.params) {
        //     const data = crypto.encryptAES(JSON.stringify(config.params), crypto.aesKey);
        //     config.params = { data };
        //   }
        //   if (config.data) {
        //     config.text = true;
        //     config.data = crypto.encryptAES(JSON.stringify(config.data), crypto.aesKey);
        //   }
        // }
        //headers中配置text请求
        if (config.text === true) {
            config.headers['Content-Type'] = 'text/plain'
        }
        //headers中配置serialize为true开启序列化
        if (config.method === 'post' && meta.isSerialize === true) {
            config.data = serialize(config.data)
        }
        return config
    },
    error => {
        return Promise.reject(error)
    }
)
//http response拦截
axios.interceptors.response.use(
  res => {
    const status = res.data.error_code || res.data.code || res.status;
    const statusWhiteList = website.statusWhiteList || [];
    const message = res.data.msg || res.data.error_description || res.data.message || '系统错误';
    const config = res.config;
    const cryptoData = config.cryptoData === true;
    if (status === 511) {
      ElMessage({
        message: '请联系运维人员上传密钥证书!',
        type: 'error',
      });
      // 获取当前路由名称
      const currentRouteName = router.currentRoute.value.name;
      // 如果当前路由不是登录页,则跳转到登录页
      if (currentRouteName !== '登录页') {
        store.dispatch('FedLogOut').then(() =>
          router.push({
            path: '/login',
          })
        );
      }
      return Promise.reject(new Error(message));
    }
    //如果在白名单里则自行catch逻辑处理
    if (statusWhiteList.includes(status)) return Promise.reject(res);
    // 如果是401并且没有重试过,尝试刷新token
    if (status === 401 && !_retry) {
      // 标记此请求已尝试刷新token
      _retry = true;
      // 调用RefreshToken action来刷新token
      return store
        .dispatch('RefreshToken')
        .then(() => {
          const meta = config.meta || {};
          const isToken = meta.isToken === false;
          const cryptoToken = config.cryptoToken === true;
          // 获取刷新后的token
          const token = getToken();
          if (token && !isToken) {
            config.headers[website.tokenHeader] = cryptoToken
              ? 'crypto ' + crypto.encryptAES(token, crypto.cryptoKey)
              : 'bearer ' + token;
          }
          // 重新发送原来的请求
          return axios(config);
        })
        .catch(() => {
          // 首次报错时提示
          if (!isErrorShown) {
            isErrorShown = true;
            ElMessage({
              message: message,
              type: 'error',
            });
          }
          // 清除token信息
          removeToken();
          removeRefreshToken();
          const env = import.meta.env.VITE_APP_ENV;
          // 重定向到登录页
          // store.dispatch('FedLogOut').then(() => router.push({
          //     path: '/login'
          // }));
          env === 'development'
            ? store.dispatch('FedLogOut').then(() =>
                router.push({
                  path: '/login',
                })
              )
            : store.dispatch('FedLogOut').then(() => window.location.replace(`${adminUrl}#/login`));
          return Promise.reject(new Error(message));
        });
    }
    // 如果是401并且已经重试过,直接跳转到登录页面
    if (status === 401 && _retry) {
      // 首次报错时提示
      if (!isErrorShown) {
        isErrorShown = true;
        ElMessage({
          message: '用户令牌过期,请重新登录',
          type: 'error',
        });
      }
      // 清除token信息
      removeToken();
      removeRefreshToken();
      // 重定向到登录页
      //   store.dispatch('FedLogOut').then(() => router.push({
      //       path: '/login'
      //   }));
      const env = import.meta.env.VITE_APP_ENV;
      env === 'development'
        ? store.dispatch('FedLogOut').then(() =>
            router.push({
              path: '/login',
            })
          )
        : store.dispatch('FedLogOut').then(() => window.location.replace(`${adminUrl}#/login`));
      return Promise.reject(new Error(message));
    }
    // 如果请求为oauth2错误码则首次报错时提示
    if (status > 2000 && !validatenull(res.data.error_description)) {
      // 首次报错时提示
      if (!isErrorShown) {
        isErrorShown = true;
        ElMessage({
          message: message,
          type: 'error',
        });
      }
      return Promise.reject(new Error(message));
    }
    // 如果请求为非200默认统一处理
    if (status !== 200 && status !== 0) {
      if (!isErrorShown) {
        ElMessage({
          message: message,
          type: 'error',
        });
      }
      return Promise.reject(new Error(message));
    }
    // 解析加密报文
    if (cryptoData) {
      res.data = JSON.parse(crypto.decryptAES(res.data, crypto.aesKey));
    }
    return res;
  },
  error => {
    return Promise.reject(new Error(error));
  }
);
window._request = axios
export default axios;
service.interceptors.response.use(
    res => {
        const status = res.data.error_code || res.data.code || res.status
        const statusWhiteList = website.statusWhiteList || []
        const message = res.data.msg || res.data.error_description || res.data.message || '系统错误'
        const config = res.config
        const cryptoData = config.cryptoData === true
        if (status === 511) {
            ElMessage({
                message: '请联系运维人员上传密钥证书!',
                type: 'error',
            })
            // 获取当前路由名称
            const currentRouteName = router.currentRoute.value.name
            // 如果当前路由不是登录页,则跳转到登录页
            if (currentRouteName !== '登录页') {
                store.dispatch('FedLogOut').then(() =>
                    router.push({
                        path: '/login',
                    })
                )
            }
            return Promise.reject(new Error(message))
        }
        //如果在白名单里则自行catch逻辑处理
        if (statusWhiteList.includes(status)) return Promise.reject(res)
        // 如果是401并且没有重试过,尝试刷新token
        if (status === 401 && !_retry) {
            // 标记此请求已尝试刷新token
            _retry = true
            // 调用RefreshToken action来刷新token
            return store
                .dispatch('RefreshToken')
                .then(() => {
                    const meta = config.meta || {}
                    const isToken = meta.isToken === false
                    const cryptoToken = config.cryptoToken === true
                    // 获取刷新后的token
                    const token = getToken()
                    if (token && !isToken) {
                        config.headers[website.tokenHeader] = cryptoToken
                            ? 'crypto ' + crypto.encryptAES(token, crypto.cryptoKey)
                            : 'bearer ' + token
                    }
                    // 重新发送原来的请求
                    return service(config)
                })
                .catch(() => {
                    // 首次报错时提示
                    if (!isErrorShown) {
                        isErrorShown = true
                        ElMessage({
                            message: message,
                            type: 'error',
                        })
                    }
                    // 清除token信息
                    removeToken()
                    removeRefreshToken()
                    const env = import.meta.env.VITE_APP_ENV
                    // 重定向到登录页
                    // store.dispatch('FedLogOut').then(() => router.push({
                    //     path: '/login'
                    // }));
                    env === 'development'
                        ? store.dispatch('FedLogOut').then(() =>
                                router.push({
                                    path: '/login',
                                })
                          )
                        : store.dispatch('FedLogOut').then(() => window.location.replace(`${adminUrl}#/login`))
                    return Promise.reject(new Error(message))
                })
        }
        // 如果是401并且已经重试过,直接跳转到登录页面
        if (status === 401 && _retry) {
            // 首次报错时提示
            if (!isErrorShown) {
                isErrorShown = true
                ElMessage({
                    message: '用户令牌过期,请重新登录',
                    type: 'error',
                })
            }
            // 清除token信息
            removeToken()
            removeRefreshToken()
            // 重定向到登录页
            //   store.dispatch('FedLogOut').then(() => router.push({
            //       path: '/login'
            //   }));
            const env = import.meta.env.VITE_APP_ENV
            env === 'development'
                ? store.dispatch('FedLogOut').then(() =>
                        router.push({
                            path: '/login',
                        })
                  )
                : store.dispatch('FedLogOut').then(() => window.location.replace(`${adminUrl}#/login`))
            return Promise.reject(new Error(message))
        }
        // 如果请求为oauth2错误码则首次报错时提示
        if (status > 2000 && !validatenull(res.data.error_description)) {
            // 首次报错时提示
            if (!isErrorShown) {
                isErrorShown = true
                ElMessage({
                    message: message,
                    type: 'error',
                })
            }
            return Promise.reject(new Error(message))
        }
        // 如果请求为非200默认统一处理
        if (status !== 200 && status !== 0) {
            if (!isErrorShown) {
                ElMessage({
                    message: message,
                    type: 'error',
                })
            }
            return Promise.reject(new Error(message))
        }
        // 解析加密报文
        if (cryptoData) {
            res.data = JSON.parse(crypto.decryptAES(res.data, crypto.aesKey))
        }
        return res
    },
    error => {
        return Promise.reject(new Error(error))
    }
)
window._request = service
export default service
applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/index.vue
@@ -68,9 +68,7 @@
        </el-form>
        <div class="gd-table-toolbar">
<!--            <el-button color="#F2F3F5" @click="requester = !requester">我是{{ requester ? '需求方' : '服务方' }}</el-button>-->
            <el-button :icon="Plus" color="#4C34FF" type="primary" @click="openForm('add')">新增</el-button>
            <!--            <el-button :icon="Delete" color="#4C34FF" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button>-->
            <el-button v-if="requester" :icon="Plus" color="#4C34FF" type="primary" @click="openForm('add')">新增</el-button>
        </div>
        <div class="gd-table-container" v-loading="loading">
applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue
@@ -202,8 +202,12 @@
                    >
                        发布
                    </el-button>
                    <el-button color="#F2F3F5" v-if="gdStatus === '11'" @click="addDescription(2, 'view')">拒单原因</el-button>
                    <el-button color="#F2F3F5" @click="statusChange(3)" v-if="gdStatus === '20'">申请取消</el-button>
                    <el-button color="#F2F3F5" v-if="['11', '25', '31'].includes(gdStatus)" @click="addDescription(2, 'view')">
                        原因
                    </el-button>
                    <el-button color="#F2F3F5" @click="addDescription(3)" v-if="['20', '24'].includes(gdStatus)">
                        申请取消
                    </el-button>
                    <el-button color="#4C34FF" @click="requestModification" v-if="gdStatus === '20'" class="save-btn">
                        申请修改
                    </el-button>
@@ -332,6 +336,9 @@
        case 2:
            formLabel = '拒绝原因'
            break
        case 3:
            formLabel = '取消原因'
            break
        case 9:
            formLabel = '修改原因'
            break
@@ -365,6 +372,7 @@
function loadDemandChange() {
    formData.value.recommendDeviceIds = ''
    selectedDevices.value = []
    getDeviceList()
    syncSelection()
}
@@ -380,8 +388,10 @@
    const isValid = await formRef.value?.validate().catch(() => false)
    if (!isValid) return
    if (!pointList.value.length) {
        ElMessage.warning('请绘制范围')
        return
        return ElMessage.warning('请绘制范围')
    }
    if (!formData.value.recommendDeviceIds) {
        return ElMessage.warning('请选择设备')
    }
    submitting.value = true
    try {
@@ -436,6 +446,8 @@
        const val = cartesian3Convert(item, viewer)
        return { ...val, lng: val.longitude, lat: val.latitude }
    })
    formData.value.recommendDeviceIds = ''
    selectedDevices.value = []
    await getDeviceList()
    syncSelection()
}
@@ -503,9 +515,9 @@
import droneIcon from '@/assets/images/orderView/orderManage/drone.png'
function renderingDevice(list) {
   // 渲染红点
    // 渲染红点
    list.forEach(item => {
        const position = Cesium.Cartesian3.fromDegrees(item.longitude || 115.00, item.latitude || 27.11)
        const position = Cesium.Cartesian3.fromDegrees(item.longitude || 115.0, item.latitude || 27.11)
        viewer.entities.add({
            position: position,
            billboard: {
applications/task-work-order/src/views/orderView/orderManage/orderManage/RefuseOrderDialog.vue
@@ -104,7 +104,13 @@
async function open({ mode = 'add', row, formLabel, type } = {}) {
    dialogMode.value = mode
    formLabelStr.value = formLabel
    formData.value = { workOrderId: row.id, operationType: type, rejectReason: row.rejectReason }
    formData.value = {
        workOrderId: row.id,
        operationType: type,
    }
    if (dialogMode.value !== 'add'){
        formData.value.rejectReason = row.rejectReason
    }
}
defineExpose({ open })
applications/task-work-order/src/views/orderView/orderManage/orderManage/index.vue
@@ -107,8 +107,8 @@
                            {{ dayjs(row.executeEndTime).format('YYYY-MM-DD') }}
                        </template>
                    </el-table-column>
                    <el-table-column prop="serviceParty" show-overflow-tooltip label="服务方名称" />
                    <el-table-column prop="createUserName" show-overflow-tooltip label="需求方名称" />
                    <el-table-column prop="serviceParty" show-overflow-tooltip label="服务方名称" />
                    <el-table-column prop="createTime" show-overflow-tooltip label="工单创建时间" />
                    <el-table-column label="操作" class-name="operation-btns">
                        <template v-slot="{ row }">
@@ -229,7 +229,7 @@
        dialogRef.value?.open({ mode, row })
    })
}
const editStatus = ['0','11','24','25']
const editStatus = ['0','11','25']
provide('editStatus', editStatus)
// 工单状态:0草稿、10发布中_接单中、11发布中_拒绝接单、20响应中_待拆分、
// 21响应中_申请取消、22响应中_申请修改、23响应中_已取消、24响应中_拒绝取消、