Merge remote-tracking branch 'origin/master'
18 files modified
6 files added
| | |
| | | }, |
| | | }); |
| | | }; |
| | | export const getOperationLogPage = params => { |
| | | return request({ |
| | | url: '/blade-log/log/operationLog/page', |
| | | method: 'get', |
| | | params: { descs: 'create_time', ...params }, |
| | | }); |
| | | }; |
| | | // 历史轨迹记录 |
| | | export const getHistoryTrack = (params) => { |
| | | return request({ |
| | |
| | | * @Author : yuan |
| | | * @Date : 2026-01-06 09:47:09 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2026-01-07 15:01:16 |
| | | * @LastEditTime : 2026-01-22 15:00:07 |
| | | * @FilePath : \applications\drone-command\src\page\index\sidebar\sidebarItem.vue |
| | | * @Description : |
| | | * Copyright 2026 OBKoro1, All Rights Reserved. |
| | |
| | | import { mapGetters } from 'vuex'; |
| | | import { validatenull } from 'utils/validate'; |
| | | import website from '@/config/website'; |
| | | import {saveOperationLog} from '@ztzf/apis' |
| | | |
| | | export default { |
| | | name: 'sidebarItem', |
| | |
| | | return item.meta.roles ? item.meta.roles.includes(this.roles) : true; |
| | | }, |
| | | open(item) { |
| | | saveOperationLog({ |
| | | requestUri: item[this.pathKey], |
| | | title: item.name, |
| | | type: 0 |
| | | }) |
| | | |
| | | this.$router.push({ |
| | | path: item[this.pathKey], |
| | | query: item[this.queryKey], |
| | |
| | | color: #fff !important; |
| | | |
| | | .el-date-range-picker__time-header { |
| | | .el-time-panel { |
| | | background: #1A1A2A !important; |
| | | border-radius: 0px 0px 8px 8px; |
| | | border: none !important; |
| | | |
| | | // 将 time-picker-popper 的样式移到这里 |
| | | .el-time-panel__header { |
| | | background: #161B2C !important; |
| | | color: #ffffff !important; |
| | | border-bottom: 1px solid rgba(71, 157, 255, 0.3) !important; |
| | | } |
| | | |
| | | .el-time-panel__content { |
| | | .el-time-spinner__item { |
| | | &:hover { |
| | | background: transparent !important; |
| | | } |
| | | |
| | | &.active { |
| | | color: #479dff !important; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-time-panel__footer { |
| | | .el-time-panel__btn { |
| | | color: #fff; |
| | | } |
| | | |
| | | .el-time-panel__btn:first-child { |
| | | color: #86909C; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-input__wrapper { |
| | | box-shadow: none; |
| | | background: #2E2E48 !important; |
| | |
| | | td.in-range div:hover, |
| | | &.is-week-mode .el-date-table__row.current div, |
| | | &.is-week-mode .el-date-table__row:hover div { |
| | | background-color: #284FE3 !important; |
| | | background-color: #4160D5 !important; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | ## 信号干扰,诱导驱离 |
| | | ## 分页 |
| | | |
| | | |
| | | **接口地址**:`/drone-fw/cockpit/dataCockpit/interferenceAndExpulsion` |
| | | **接口地址**:`/blade-log/log/operationLog/page` |
| | | |
| | | |
| | | **请求方式**:`POST` |
| | | **请求方式**:`GET` |
| | | |
| | | |
| | | **请求数据类型**:`application/json` |
| | | **请求数据类型**:`application/x-www-form-urlencoded` |
| | | |
| | | |
| | | **响应数据类型**:`*/*` |
| | | |
| | | |
| | | **接口描述**:<p>传入fwEffectEval</p> |
| | | **接口描述**:<p>分页</p> |
| | | |
| | | |
| | | |
| | | **请求示例**: |
| | | |
| | | |
| | | ```javascript |
| | | { |
| | | "alarmRecordId": 0, |
| | | "counterWay": "" |
| | | } |
| | | ``` |
| | | |
| | | |
| | | **请求参数**: |
| | |
| | | |
| | | | 参数名称 | 参数说明 | 请求类型 | 是否必须 | 数据类型 | schema | |
| | | | -------- | -------- | ----- | -------- | -------- | ------ | |
| | | |fwEffectEvalParam|fwEffectEvalParam|body|true|FwEffectEvalParam|FwEffectEvalParam| |
| | | |  alarmRecordId|告警记录ID(ja_fw_drone_alarm_record.id)||false|integer(int64)|| |
| | | |  counterWay|反制方式:1.信号干扰/2.诱导驱离/无||false|string|| |
| | | |createBy|操作人|query|false|string|| |
| | | |current|当前页|query|false|integer(int32)|| |
| | | |endTime|结束时间|query|false|string|| |
| | | |size|每页的数量|query|false|integer(int32)|| |
| | | |startTime|开始时间|query|false|string|| |
| | | |title|日志类型(0菜单/1按钮)|query|false|string|| |
| | | |
| | | |
| | | **响应状态**: |
| | |
| | | |
| | | | 状态码 | 说明 | schema | |
| | | | -------- | -------- | ----- | |
| | | |200|OK|R| |
| | | |201|Created|| |
| | | |200|OK|R«IPage«OperationLogVO»»| |
| | | |401|Unauthorized|| |
| | | |403|Forbidden|| |
| | | |404|Not Found|| |
| | |
| | | | 参数名称 | 参数说明 | 类型 | schema | |
| | | | -------- | -------- | ----- |----- | |
| | | |code|状态码|integer(int32)|integer(int32)| |
| | | |data|承载数据|object|| |
| | | |data|承载数据|IPage«OperationLogVO»|IPage«OperationLogVO»| |
| | | |  current||integer(int64)|| |
| | | |  pages||integer(int64)|| |
| | | |  records||array|OperationLogVO| |
| | | |    createBy|操作人|string|| |
| | | |    remoteIp|客户端IP|string|| |
| | | |    requestUri|请求地址|string|| |
| | | |    title|日志标题|string|| |
| | | |    type|日志类型(0菜单/1按钮)|string|| |
| | | |    userAgent|客户端|string|| |
| | | |  size||integer(int64)|| |
| | | |  total||integer(int64)|| |
| | | |msg|返回消息|string|| |
| | | |success|是否成功|boolean|| |
| | | |
| | |
| | | ```javascript |
| | | { |
| | | "code": 0, |
| | | "data": {}, |
| | | "data": { |
| | | "current": 0, |
| | | "pages": 0, |
| | | "records": [ |
| | | { |
| | | "createBy": "", |
| | | "remoteIp": "", |
| | | "requestUri": "", |
| | | "title": "", |
| | | "type": "", |
| | | "userAgent": "" |
| | | } |
| | | ], |
| | | "size": 0, |
| | | "total": 0 |
| | | }, |
| | | "msg": "", |
| | | "success": true |
| | | } |
| | |
| | | <el-date-picker class="command-date-picker" |
| | | popper-class="command-date-picker-popper" v-model="flyDateRange" |
| | | type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" |
| | | :disabled-date="disabledFlyDate" :disabled-time="disabledFlyTime" |
| | | value-format="YYYY-MM-DD HH:mm:ss" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="关联派出所" prop="policeStationId"> |
| | |
| | | deviceIds: fieldRules(false), |
| | | } |
| | | |
| | | function isSameDay (left, right) { |
| | | return ( |
| | | left.getFullYear() === right.getFullYear() && |
| | | left.getMonth() === right.getMonth() && |
| | | left.getDate() === right.getDate() |
| | | ) |
| | | } |
| | | |
| | | const disabledFlyDate = time => { |
| | | const startOfToday = new Date() |
| | | startOfToday.setHours(0, 0, 0, 0) |
| | | return time.getTime() < startOfToday.getTime() |
| | | } |
| | | |
| | | const disabledFlyTime = date => { |
| | | if (!date) return {} |
| | | const now = new Date() |
| | | if (!isSameDay(date, now)) return {} |
| | | const currentHour = now.getHours() |
| | | const currentMinute = now.getMinutes() |
| | | const currentSecond = now.getSeconds() |
| | | return { |
| | | disabledHours: () => Array.from({ length: currentHour }, (_, index) => index), |
| | | disabledMinutes: hour => |
| | | hour === currentHour ? Array.from({ length: currentMinute }, (_, index) => index) : [], |
| | | disabledSeconds: (hour, minute) => |
| | | hour === currentHour && minute === currentMinute |
| | | ? Array.from({ length: currentSecond }, (_, index) => index) |
| | | : [], |
| | | } |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel () { |
| | | visible.value = false |
| New file |
| | |
| | | <template> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search"> |
| | | <el-form-item label="操作名称" prop="title"> |
| | | <el-input |
| | | class="command-input" |
| | | v-model="searchParams.title" |
| | | placeholder="请输入" |
| | | clearable |
| | | @clear="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="操作人" prop="createBy"> |
| | | <el-input |
| | | class="command-input" |
| | | v-model="searchParams.createBy" |
| | | placeholder="请输入" |
| | | clearable |
| | | @clear="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="操作类型" prop="type"> |
| | | <el-select |
| | | class="command-select" |
| | | popper-class="command-select-popper" |
| | | v-model="searchParams.type" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="handleSearch" |
| | | > |
| | | <el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="操作时间"> |
| | | <el-date-picker |
| | | popper-class="command-date-picker-popper" |
| | | class="command-date-picker" |
| | | v-model="dateRange" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | @change="handleSearch" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item class="history-search-actions"> |
| | | <el-button :icon="RefreshRight" @click="resetForm"></el-button> |
| | | <el-button class="search-btn" :icon="Search" @click="handleSearch"></el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)"> |
| | | <div class="command-table-content command-table-content-bg"> |
| | | <el-table class="command-table" :data="list"> |
| | | <el-table-column type="index" show-overflow-tooltip width="64" label="序号" /> |
| | | <el-table-column prop="title" show-overflow-tooltip label="操作名称" /> |
| | | <el-table-column prop="createBy" show-overflow-tooltip label="操作人" /> |
| | | <el-table-column prop="type" show-overflow-tooltip label="操作类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getTypeLabel(row.type) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="remoteIp" show-overflow-tooltip label="客户端IP" /> |
| | | <el-table-column prop="requestUri" show-overflow-tooltip label="请求地址" /> |
| | | <el-table-column prop="userAgent" show-overflow-tooltip label="客户端信息" /> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <div class="command-table-pagination"> |
| | | <el-pagination |
| | | popper-class="command-select-popper" |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | layout="total, prev, pager, next, sizes" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </basic-container> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search, RefreshRight } from '@element-plus/icons-vue' |
| | | import { onMounted, ref } from 'vue' |
| | | import { dateRangeFormat } from '@ztzf/utils' |
| | | import { getOperationLogPage } from '@/api/logs' |
| | | |
| | | const initSearchParams = () => ({ |
| | | title: '', |
| | | createBy: '', |
| | | type: '', |
| | | current: 1, |
| | | size: 10, |
| | | }) |
| | | |
| | | const searchParams = ref(initSearchParams()) |
| | | const total = ref(0) |
| | | const loading = ref(true) |
| | | const list = ref([]) |
| | | const dateRange = ref([]) |
| | | const queryParamsRef = ref(null) |
| | | const typeOptions = [ |
| | | { label: '菜单', value: '1' }, |
| | | { label: '按钮', value: '2' }, |
| | | ] |
| | | |
| | | async function getList() { |
| | | const range = dateRangeFormat(dateRange.value) |
| | | loading.value = true |
| | | try { |
| | | const params = { ...searchParams.value, startTime: range[0], endTime: range[1] } |
| | | const res = await getOperationLogPage(params) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | function handleSearch() { |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | function resetForm() { |
| | | dateRange.value = [] |
| | | queryParamsRef.value?.resetFields() |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | function getTypeLabel(value) { |
| | | const key = value === null || value === undefined ? '' : String(value) |
| | | const match = typeOptions.find(item => item.value === key) |
| | | return match?.label || value || '-' |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| | |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div class="detail-container" v-if="dialogReadonly"> |
| | | <el-row> |
| | | <el-row class="detail-row-view"> |
| | | <el-col :span="12"> |
| | | <div class="label">案例名称</div> |
| | | <div class="val">{{ formData.caseName }}</div> |
| | |
| | | if (!formData.value.id) return |
| | | const res = await gdDataObjectionDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? {} |
| | | if (formData.value.attachIds) { |
| | | getAttachDetail(formData.value.attachIds) |
| | | } |
| | | } |
| | | // 获取附件详情 |
| | | async function getAttachDetail() { |
| | | if (!formData.value.id) return |
| | | const res = await getAttachDetailApi({ id: formData.value.id }) |
| | | console.log('附件详情',res.data.data) |
| | | attachmentDetailsList.value=res.data.data |
| | | async function getAttachDetail(attachIds) { |
| | | // 如果 attachIds 是字符串,尝试分割成数组 |
| | | const ids = typeof attachIds === 'string' ? attachIds.split(',') : Array.isArray(attachIds) ? attachIds : [attachIds] |
| | | const detailPromises = ids.map(id => getAttachDetailApi({ id })) |
| | | const results = await Promise.all(detailPromises) |
| | | attachmentDetailsList.value = results.map(res => res.data.data).filter(Boolean) |
| | | console.log('附件详情', attachmentDetailsList.value) |
| | | } |
| | | // 处理附件下载 |
| | | async function handleDownloadAttach() { |
| | | console.log('附件'); |
| | | |
| | | |
| | | if (attachmentDetailsList.value.length === 0) { |
| | | ElMessage.warning('没有可下载的附件') |
| | | return |
| | | } |
| | | |
| | | // 遍历所有附件并下载 |
| | | attachmentDetailsList.value.forEach(attach => { |
| | | if (attach.link) { |
| | | const link = document.createElement('a') |
| | | link.href = attach.link |
| | | link.download = attach.originalName || attach.name |
| | | link.style.display = 'none' |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | document.body.removeChild(link) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | |
| | |
| | | feedbackFormData.value = initFeedbackForm() |
| | | if (dialogMode.value !== 'add') { |
| | | await loadDetail() |
| | | await getAttachDetail() |
| | | } |
| | | } |
| | | |
| | |
| | | </el-form> |
| | | |
| | | <div class="gd-table-toolbar"> |
| | | <el-button color="#F2F3F5" @click="requester = !requester">我是{{ requester ? '需求方' : '服务方' }}</el-button> |
| | | |
| | | <!-- <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>--> |
| | | </div> |
| | |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import { gdPatrolTaskPageApi, gdPatrolTaskRemoveApi } from './inspectionRequestApi' |
| | | import ViewDiaLog from '@/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue' |
| | | import { useStore } from 'vuex' |
| | | |
| | | const store = useStore() |
| | | const requester = computed(() => store.state.user.userInfo?.role_id === '2014158512610869250') |
| | | // 初始化查询参数 |
| | | const initSearchParams = () => ({ |
| | | patrolTaskName: '', // 任务名称 |
| | |
| | | const viewDiaLogRef = ref(null) |
| | | const dialogVisible = ref(false) |
| | | const viewDiaLogVisible = ref(false) |
| | | const requester = ref(true) |
| | | const dictObj = ref({ |
| | | patrolTaskType: [], // 巡查任务类型 |
| | | workOrderType: [], // 工单类型 |
| | |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div class="content" style="display: flex"> |
| | | <div class="processBox" v-if="dialogMode !== 'add'"> |
| | | <div class="processBox" v-if="dialogMode !== 'add' && processList.length"> |
| | | <el-steps direction="vertical" :active="processList.length"> |
| | | <el-step v-for="item in processList" :title="item.flowName" :description="item.flowDesc" /> |
| | | </el-steps> |
| | |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | |
| | | </div> |
| | | <el-form |
| | | class="gd-dialog-form" |
| | |
| | | v-model="formData.deviceLoadDemand" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="loadDemandChange" |
| | | > |
| | | <el-option |
| | | v-for="item in dictObj.deviceLoadDemand" |
| | |
| | | </div> |
| | | <div class="rightBox" v-if="!dialogReadonly"> |
| | | <div class="detail-title">推荐设备</div> |
| | | <el-table ref="deviceTableRef" :data="deviceList" row-key="id" @selection-change="handleDeviceSelectionChange"> |
| | | <el-table-column type="selection" width="55" :reserve-selection="true" /> |
| | | <el-table-column prop="nickname" label="设备名称" /> |
| | | <el-table-column prop="deviceName" label="设备型号" /> |
| | | <el-table-column prop="devicePayload" label="设备负载" /> |
| | | </el-table> |
| | | <template v-if="formData.deviceLoadDemand && pointList.length"> |
| | | <el-table |
| | | ref="deviceTableRef" |
| | | :data="deviceList" |
| | | row-key="id" |
| | | @selection-change="handleDeviceSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55" :reserve-selection="true" /> |
| | | <el-table-column prop="nickname" label="设备名称" /> |
| | | <el-table-column prop="deviceName" label="设备型号" /> |
| | | <el-table-column prop="devicePayload" label="设备负载" /> |
| | | </el-table> |
| | | </template> |
| | | <div v-else>请先选择设备需求并绘制范围</div> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | > |
| | | 发布 |
| | | </el-button> |
| | | <el-button color="#F2F3F5" v-if="gdStatus === '11'">拒单原因</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="#4C34FF" @click="requestModification" v-if="gdStatus === '20'" class="save-btn"> |
| | | 申请修改 |
| | | </el-button> |
| | | </template> |
| | | <template v-else> |
| | | <el-button color="#F2F3F5" v-if="gdStatus === '10'" @click="rejectOrders">拒绝接单</el-button> |
| | | <el-button color="#F2F3F5" v-if="gdStatus === '10'" @click="addDescription(2)">拒绝接单</el-button> |
| | | <el-button color="#4C34FF" v-if="gdStatus === '10'" @click="statusChange(1)" class="save-btn">接单</el-button> |
| | | <el-button color="#F2F3F5" v-if="gdStatus === '22'" @click="statusChange(7)">同意修改</el-button> |
| | | <el-button color="#4C34FF" v-if="gdStatus === '22'" @click="statusChange(8)" class="save-btn"> |
| | |
| | | <el-button color="#4C34FF" v-if="gdStatus === '21'" @click="statusChange(6)" class="save-btn"> |
| | | 不同意取消 |
| | | </el-button> |
| | | <el-button color="#F2F3F5" v-if="gdStatus === '30'" @click="addDescription(9)">协商修改</el-button> |
| | | </template> |
| | | </template> |
| | | </template> |
| | |
| | | const refuseOrderDialogRef = ref(null) |
| | | let viewer |
| | | let drawPolygonExample |
| | | let pointList = [] |
| | | let pointList = ref([]) |
| | | const requester = inject('requester') |
| | | const editStatus = inject('editStatus') |
| | | const suddenlyEdit = ref(false) |
| | | const processList = ref([]) |
| | | let viewPlane |
| | | const hasPatrolTaskList = computed(() => ['30', '40', '50', '60'].includes(String(formData.value.workOrderStatus))) |
| | | |
| | | // 工单状态:0草稿、10发布中_接单中、11发布中_拒绝接单、20响应中_待拆分、21响应中_申请取消、22响应中_申请修改、23响应中_已取消、 |
| | | // 24响应中_拒绝取消、25响应中_拒绝修改 30执行中_待全部完成、31执行中_协商修改、40完成待验_待全部验收、50验收通过_待结算、60结算完成_已结算 |
| | |
| | | executeStartTime: fieldRules(true), |
| | | deviceLoadDemand: fieldRules(true), |
| | | } |
| | | // 操作类型:1接单,2拒接接单,3申请取消,4申请修改, 5同意取消 6不同意取消 7.同意修改 7.不同意修改 |
| | | // 操作类型:1接单,2拒接接单,3申请取消,4申请修改, 5同意取消 6不同意取消 7.同意修改 8.不同意修改 9.协商修改 |
| | | function statusChange(operationType) { |
| | | gdWorkOrderHandleStatusApi({ operationType: operationType, workOrderId: formData.value.id }).then(res => { |
| | | visible.value = false |
| | |
| | | }) |
| | | } |
| | | |
| | | const suddenlyEdit = ref(false) |
| | | function requestModification() { |
| | | suddenlyEdit.value = true |
| | | dialogMode.value = 'edit' |
| | |
| | | emit('success') |
| | | } |
| | | |
| | | function rejectOrders() { |
| | | // 填写说明 |
| | | function addDescription(type, mode = 'add') { |
| | | let formLabel = '' |
| | | switch (type) { |
| | | case 2: |
| | | formLabel = '拒绝原因' |
| | | break |
| | | case 9: |
| | | formLabel = '修改原因' |
| | | break |
| | | } |
| | | rejectVisible.value = true |
| | | nextTick(() => { |
| | | refuseOrderDialogRef.value.open({ |
| | | mode: 'add', |
| | | row: { workOrderId: formData.value.id }, |
| | | mode, |
| | | row: formData.value, |
| | | type, |
| | | formLabel, |
| | | }) |
| | | }) |
| | | } |
| | |
| | | // 获取推荐设备列表 |
| | | async function getDeviceList() { |
| | | try { |
| | | const res = await gdManageDeviceListApi({ current: 1, size: 1000, ids: formData.value.recommendDeviceIds }) |
| | | const str = [...pointList.value, pointList.value[0]].map(item => `${item.longitude} ${item.latitude}`).join(',') |
| | | let geom = `POLYGON((${str}))` |
| | | const res = await gdManageDeviceListApi({ |
| | | ids: formData.value.recommendDeviceIds, |
| | | devicePayload: dialogMode.value === 'add' ? formData.value.deviceLoadDemand : '', |
| | | geom: dialogMode.value === 'add' ? geom : '', |
| | | }) |
| | | deviceList.value = res?.data?.data ?? [] |
| | | } catch (error) { |
| | | console.error('获取设备列表失败:', error) |
| | | } |
| | | } |
| | | |
| | | function loadDemandChange() { |
| | | formData.value.recommendDeviceIds = '' |
| | | getDeviceList() |
| | | syncSelection() |
| | | } |
| | | |
| | | // 设备选择变化 |
| | |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | if (!pointList.length) { |
| | | if (!pointList.value.length) { |
| | | ElMessage.warning('请绘制范围') |
| | | return |
| | | } |
| | | submitting.value = true |
| | | try { |
| | | const str = [...pointList, pointList[0]].map(item => `${item.longitude} ${item.latitude}`).join(',') |
| | | const str = [...pointList.value, pointList.value[0]].map(item => `${item.longitude} ${item.latitude}`).join(',') |
| | | formData.value.geom = `POLYGON((${str}))` |
| | | if (!formData.value.id) { |
| | | formData.value.workOrderStatus = '10' |
| | |
| | | } |
| | | ) |
| | | |
| | | const processList = ref([]) |
| | | function loadList() { |
| | | gdWorkOrderFlowListApi({ workOrderId: formData.value.id }).then(res => { |
| | | processList.value = res.data.data |
| | |
| | | |
| | | // 绘制完成回调 |
| | | const drawFinished = async data => { |
| | | pointList = _.cloneDeep(data).map(item => { |
| | | pointList.value = _.cloneDeep(data).map(item => { |
| | | const val = cartesian3Convert(item, viewer) |
| | | return { ...val, lng: val.longitude, lat: val.latitude } |
| | | }) |
| | | await getDeviceList() |
| | | syncSelection() |
| | | } |
| | | |
| | | // 编辑面 |
| | | function editPolygon() { |
| | | if (!formData.value?.geom) return |
| | | pointList = geomAnalysis(formData.value.geom) |
| | | pointList.value = geomAnalysis(formData.value.geom) |
| | | drawPolygonExample?.destroy() |
| | | drawPolygonExample = new DrawPolygon(viewer) |
| | | let noClosedList = _.cloneDeep(pointList) |
| | | let noClosedList = _.cloneDeep(pointList.value) |
| | | noClosedList.pop() |
| | | drawPolygonExample.initPolygon( |
| | | viewer, |
| | |
| | | drawPolygonExample.subscribe('getPolygonPositions', drawFinished) |
| | | } |
| | | |
| | | let viewPlane |
| | | // 查看面 |
| | | function viewPolygon() { |
| | | if (!formData.value?.geom) return |
| | | pointList = geomAnalysis(formData.value.geom) |
| | | const result = pointList.map(item => [item.longitude, item.latitude]).flat() |
| | | pointList.value = geomAnalysis(formData.value.geom) |
| | | const result = pointList.value.map(item => [item.longitude, item.latitude]).flat() |
| | | viewPlane = viewer.entities?.add({ |
| | | customType: 'control_group', |
| | | position: Cesium.Cartesian3.fromDegrees(result[0], result[1]), |
| | |
| | | }, |
| | | }) |
| | | flyVisual({ |
| | | positionsData: pointList.map(i => [i.longitude, i.latitude, i.height || 0]), |
| | | positionsData: pointList.value.map(i => [i.longitude, i.latitude, i.height || 0]), |
| | | viewer, |
| | | }) |
| | | } |
| | |
| | | }) |
| | | } |
| | | |
| | | const hasPatrolTaskList = computed(() => ['30','40','50','60'].includes(String(formData.value.workOrderStatus))) |
| | | |
| | | // 获取巡检任务 |
| | | function gdPatrolTaskPage() { |
| | | gdPatrolTaskPageApi({ current: 1, size: 1000, workOrderId: formData.value.id }).then(res => { |
| | | patrolTaskList.value = res.data.data.records || [] |
| | | }) |
| | | } |
| | | |
| | | function setMapDevice() { |
| | | gdManageDeviceListApi().then(res => { |
| | | renderingDevice(res?.data?.data || []) |
| | | }) |
| | | } |
| | | |
| | | 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) |
| | | viewer.entities.add({ |
| | | position: position, |
| | | billboard: { |
| | | image: droneIcon, |
| | | width: 40, |
| | | height: 40, |
| | | verticalOrigin: Cesium.VerticalOrigin.CENTER, |
| | | }, |
| | | }) |
| | | }) |
| | | } |
| | | |
| | |
| | | dialogMode.value === 'edit' ? editPolygon() : viewPolygon() |
| | | } |
| | | await getDeviceList() |
| | | // setMapDevice() |
| | | await nextTick() |
| | | syncSelection() |
| | | } |
| | |
| | | <el-dialog |
| | | class="gd-dialog" |
| | | v-model="visible" |
| | | :title="titleEnum[dialogMode]" |
| | | title="编辑" |
| | | @closed="visible = false" |
| | | destroy-on-close |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div v-if="dialogReadonly"> |
| | | <el-row class="detail-row-view"> |
| | | <el-col :span="24"> |
| | | <div class="label">{{formLabelStr}}:</div> |
| | | <div class="val">{{ formData.rejectReason || '' }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <el-form |
| | | v-else |
| | | class="gd-dialog-form" |
| | | ref="formRef" |
| | | :model="formData" |
| | |
| | | > |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="拒绝原因" prop="rejectReason"> |
| | | <el-form-item :label="formLabelStr" prop="rejectReason"> |
| | | <el-input |
| | | class="gd-input" |
| | | v-model="formData.rejectReason" |
| | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | import { fieldRules, getDictLabel } from '@ztzf/utils' |
| | | import { gdWorkOrderHandleStatusApi } from '@/views/orderView/orderManage/orderManage/orderManageApi' |
| | | import { pxToRem } from '@/utils/rem' |
| | | import dayjs from 'dayjs' |
| | | |
| | | // 初始化表单数据 |
| | | const initForm = () => ({ |
| | | operationType: 2, |
| | | operationType: null, |
| | | rejectReason: '', |
| | | workOrderId: null, |
| | | }) |
| | |
| | | submitting.value = true |
| | | gdWorkOrderHandleStatusApi(formData.value) |
| | | .then(res => { |
| | | ElMessage.success('拒绝接单成功') |
| | | ElMessage.success('提交成功') |
| | | visible.value = false |
| | | emit('success') |
| | | }) |
| | |
| | | }) |
| | | } |
| | | |
| | | let formLabelStr = ref('原因') |
| | | // 打开弹框 |
| | | async function open({ mode = 'add', row } = {}) { |
| | | async function open({ mode = 'add', row, formLabel, type } = {}) { |
| | | dialogMode.value = mode |
| | | formData.value = {...formData.value,...row} |
| | | formLabelStr.value = formLabel |
| | | formData.value = { workOrderId: row.id, operationType: type, rejectReason: row.rejectReason } |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | |
| | | <template> |
| | | <basic-container> |
| | | <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick"> |
| | | <el-tabs class="gd-tabs" v-model="activeName" @tab-click="tabsClick"> |
| | | <el-tab-pane label="全部 " name="all"></el-tab-pane> |
| | | <el-tab-pane label="我的任务工单" name="my"></el-tab-pane> |
| | | </el-tabs> |
| | |
| | | |
| | | <div class="gd-table-toolbar"> |
| | | <!-- <el-button color="#F2F3F5" @click="requester = !requester">我是{{ requester ? '需求方' : '服务方' }}</el-button>--> |
| | | <el-button color="#F2F3F5" @click="previewVisible = true">预览</el-button> |
| | | <!-- <el-button color="#F2F3F5" @click="previewVisible = true">预览</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 :icon="Plus" color="#4C34FF" type="primary" @click="openForm('add')" v-if="requester">新增</el-button> |
| | | <el-button :icon="Delete" color="#4C34FF" :disabled="!selectedIds.length" @click="handleDelete()" v-if="requester">删除</el-button> |
| | | </div> |
| | | |
| | | <div class="gd-table-container" v-loading="loading"> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="serviceParty" show-overflow-tooltip label="服务方名称" /> |
| | | <el-table-column prop="createDeptName" show-overflow-tooltip label="需求方名称" /> |
| | | <el-table-column prop="createUserName" 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 }"> |
| | | <el-link @click="openFormChange(row)">查看</el-link> |
| | | <!--<el-link @click="openForm('edit', row)">编辑</el-link>--> |
| | | <el-link @click="handleDelete(row)">删除</el-link> |
| | | <el-link @click="handleDelete(row)" v-if="requester">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | ...searchParams.value, |
| | | startTime: range[0], |
| | | endTime: range[1], |
| | | createUser: activeName.value === 'user' ? store.state.user.userInfo.user_id : '', |
| | | createUser: activeName.value === 'my' ? store.state.user.userInfo.user_id : '', |
| | | }) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | |
| | | getList() |
| | | } |
| | | |
| | | function handleClick(tab,event) { |
| | | function tabsClick(tab, event) { |
| | | activeName.value = tab.props.name |
| | | resetForm() |
| | | handleSearch() |
| | | } |
| | | |
| | |
| | | export * from './job'; |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2026-01-07 11:04:47 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2026-01-22 14:50:34 |
| | | * @FilePath : \packages\apis\index.js |
| | | * @Description : |
| | | * Copyright 2026 OBKoro1, All Rights Reserved. |
| | | * 2026-01-07 11:04:47 |
| | | */ |
| | | export * from './job' |
| | | export * from './system' |
| New file |
| | |
| | | export const saveOperationLog = (data) => { |
| | | return window._request({ |
| | | url: `/blade-log/log/operationLog/save`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | |
| | | changeOrigin: true, |
| | | rewrite: path => path.replace(new RegExp(`^${VITE_API_PREFIX}`), ''), |
| | | }, |
| | | [VITE_API_PREFIX_GD]: { |
| | | target: configEnv?.[envName || VITE_APP_ENV]?.VITE_API_BASE_URL_GD, |
| | | changeOrigin: true, |
| | | rewrite: path => path.replace(new RegExp(`^${VITE_API_PREFIX_GD}`), ''), |
| | | }, |
| | | } |
| | | return proxy |
| | | } |
| | |
| | | |
| | | # API代理前缀 |
| | | VITE_API_PREFIX=/api |
| | | VITE_API_PREFIX_GD=/api-gd |
| | | |
| | | # 删除console |
| | | VITE_DROP_CONSOLE=false |
| New file |
| | |
| | | import { request } from "@/utils/requestGd/index.js" |
| | | import website from '@/config/website' |
| | | |
| | | // 获取工单列表 |
| | | export const getGdList = data => { |
| | | return request({ |
| | | url: '/system/user/profile/update', |
| | | method: 'post', |
| | | data, |
| | | }); |
| | | }; |
| | | // 工单用户登录接口 |
| | | export const ticketLoginInterfaceApi = (tenantId, deptId, roleId, username, password, type, key, code) => { |
| | | return request({ |
| | | url: '/blade-auth/oauth/token', |
| | | method: 'post', |
| | | header: { |
| | | 'Tenant-Id': tenantId, |
| | | 'Dept-Id': website.switchMode ? deptId : '', |
| | | 'Role-Id': website.switchMode ? roleId : '', |
| | | 'Captcha-Key': key, |
| | | 'Captcha-Code': code, |
| | | }, |
| | | params: { |
| | | tenantId, |
| | | username, |
| | | password, |
| | | grant_type: 'password', |
| | | scope: 'all', |
| | | type, |
| | | }, |
| | | }) |
| | | } |
| | |
| | | VITE_APP_WEBVIEW_URL: 'https://wrj.shuixiongit.com/drone-app-web-view/#/webViewWrapper', |
| | | // VITE_APP_WEBVIEW_URL: 'https://192.168.1.157:5176/mobile-web-view/#/webViewWrapper', |
| | | VITE_API_BASE_URL: 'http://218.202.104.82:8200', |
| | | VITE_API_BASE_URL_GD: 'https://wrj.shuixiongit.com/api', |
| | | // VITE_API_BASE_URL: 'https://aisky.org.cn/api', |
| | | VITE_APP_WS_API_URL:'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws', |
| | | |
| | |
| | | |
| | | // 消息处理 |
| | | function messageHandler(payload) { |
| | | console.log('🌐 全局WebSocket收到消息111111111111111111111:', payload) |
| | | // console.log('🌐 全局WebSocket收到消息111111111111111111111:', payload) |
| | | // 先尝试直接处理消息(适用于mobile-web-view的voiceCallDetail页面的消息格式) |
| | | const t = (payload.type || '').toString() |
| | | // const bizCode = payload.biz_code || '' |
| | |
| | | |
| | | <script setup> |
| | | import { getAssetsImage } from "@/utils/index.js"; |
| | | import {ticketLoginInterfaceApi} from '@/api/work/index1.js' |
| | | import md5 from "js-md5"; |
| | | import { loginByUsername } from "@/api/user/index.js"; |
| | | import { useUserStore, useLocationStore } from "@/store/index.js"; |
| | |
| | | url: '/subPackages/userDetail/password/index' |
| | | }); |
| | | } |
| | | |
| | | const loginFormGd = ref({ |
| | | username: "zhx", |
| | | password: "123456", |
| | | }); |
| | | async function submit() { |
| | | // 调用工单登录接口 |
| | | await gdLogin(); |
| | | if (!loginForm.value.username.trim()) { |
| | | uni.showToast({ |
| | | title: "请输入用户名", |
| | |
| | | userInfo.key, |
| | | userInfo.code |
| | | ); |
| | | userStore.setUserInfo(res.data.data); |
| | | userStore.setUserInfo(res.data.data); |
| | | // 请求位置权限并初始化位置服务 |
| | | try { |
| | | // 请求位置权限 |
| | |
| | | } catch (error) { |
| | | console.error('处理位置服务失败:', error); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | uni.reLaunch({ |
| | | url: "/pages/work/index", |
| | | }); |
| | |
| | | icon: "none", |
| | | duration: 2000, |
| | | }); |
| | | // 即使原始登录失败,也尝试调用工单登录接口 |
| | | await gdLogin(); |
| | | } |
| | | } |
| | | |
| | | // 工单登录 |
| | | async function gdLogin() { |
| | | let userInfo = { |
| | | tenantId: "000000", |
| | | deptId: "", |
| | | roleId: "", |
| | | username: loginFormGd.value.username, |
| | | password: loginFormGd.value.password, |
| | | type: "account", |
| | | code: "", |
| | | key: "", |
| | | }; |
| | | try { |
| | | const res = await ticketLoginInterfaceApi( |
| | | userInfo.tenantId, |
| | | userInfo.deptId, |
| | | userInfo.roleId, |
| | | userInfo.username, |
| | | md5(userInfo.password), |
| | | userInfo.type, |
| | | userInfo.key, |
| | | userInfo.code |
| | | ); |
| | | console.log('工单登录',res) |
| | | // 存储工单token到用户信息中 |
| | | if (res.data?.access_token) { |
| | | const currentUserInfo = userStore.$state.userInfo; |
| | | userStore.setUserInfo({ |
| | | ...currentUserInfo, |
| | | gd_access_token: res.data.access_token |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | const errorMsg = |
| | | error.data?.error_description !== "Bad credentials" |
| | | ? error.data?.error_description |
| | | : "登录失败,请重试"; |
| | | console.error('工单登录失败:', errorMsg); |
| | | } |
| | | } |
| | | // 从本地存储加载记住的密码 |
| | | onMounted(() => { |
| | | const savedUserInfo = uni.getStorageSync("rememberedUser"); |
| New file |
| | |
| | | <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="interactive-button/reply" clip-path="url(#clip0_67_2892)"> |
| | | <path id="Vector" fill-rule="evenodd" clip-rule="evenodd" d="M12.0021 2.91712C11.4337 2.31088 10.4167 2.71307 10.4167 3.54407L10.4167 6.25C5.58418 6.25 1.66667 10.1675 1.66667 15C1.66667 15.069 1.66747 15.1378 1.66906 15.2063C1.68601 15.9378 2.5645 16.2952 3.0882 15.7893C4.66313 14.268 6.80489 13.3333 9.16667 13.3333C9.59145 13.3333 10.0088 13.3635 10.4167 13.4218V16.4559C10.4167 17.2869 11.4337 17.6891 12.0021 17.0829L17.8408 10.8549C18.2916 10.3741 18.2916 9.6259 17.8408 9.14507L12.0021 2.91712ZM12.0833 5.44065L16.3577 10L12.0833 14.5594V12.0583L11.4304 11.9135C10.7008 11.7518 9.94319 11.6667 9.16667 11.6667C7.09177 11.6667 5.15777 12.2739 3.53383 13.3197C4.28823 10.2188 7.08361 7.91667 10.4167 7.91667C10.6691 7.91667 10.9182 7.92984 11.1633 7.95548L12.0833 8.05173V5.44065Z" fill="#4E5969"/> |
| | | </g> |
| | | <defs> |
| | | <clipPath id="clip0_67_2892"> |
| | | <rect width="20" height="20" fill="white" transform="matrix(-1 0 0 1 20 0)"/> |
| | | </clipPath> |
| | | </defs> |
| | | </svg> |
| | |
| | | <!-- 自定义导航栏 --> |
| | | <u-navbar title="工单详情" :is-back="true" back-text="" :back-icon-size="40" @left-click="onBackClick"> |
| | | <template #right> |
| | | <div class="share-btn" @click="onShareClick">分享</div> |
| | | <div class="share-btn" @click="onShareClick"><img src="@/static/images/work/share.svg" alt=""></div> |
| | | </template> |
| | | </u-navbar> |
| | | |
| | |
| | | font-weight: 400; |
| | | font-size: 28rpx; |
| | | color: #1d6fe9; |
| | | text-decoration: underline; |
| | | text-align: right; |
| | | //white-space: nowrap; |
| | | ///* 禁止换行 */ |
| | | //overflow: hidden; |
| New file |
| | |
| | | import Request from "uview-plus/libs/luch-request/index" |
| | | import configEnv from "@/config/env.js"; |
| | | import {getEnvObj} from "@/utils/index.js"; |
| | | import { useUserStore } from "@/store/index.js"; |
| | | import website from '@/config/website' |
| | | import { Base64} from 'js-base64' |
| | | |
| | | const http = new Request() |
| | | |
| | | export function request (config) { |
| | | return new Promise((resolve, reject) => { |
| | | http |
| | | .request(config) |
| | | .then(res => { |
| | | resolve(res) |
| | | }) |
| | | .catch(err => { |
| | | reject(err) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | |
| | | // 请求拦截器 |
| | | function requestInterceptors(http) { |
| | | |
| | | http.interceptors.request.use((config) => { |
| | | const {detail} = useUserStore().$state?.userInfo || {} |
| | | // 假设有token值需要在头部需要携带 |
| | | let accessToken = useUserStore()?.$state?.userInfo?.gd_access_token; |
| | | if (accessToken) { |
| | | config.header['Blade-Auth'] = 'bearer ' + accessToken; |
| | | } |
| | | if (detail?.areaCode) { |
| | | config.header['areaCode'] = detail.areaCode |
| | | } |
| | | // 安全请求header |
| | | config.header['Blade-Requested-With'] = 'BladeHttpRequest'; |
| | | // 客户端认证参数 |
| | | config.header['Authorization'] = 'Basic ' + Base64.encode(website.clientId + ':' + website.clientSecret); |
| | | return config |
| | | }, config => { // 可使用async await 做异步操作 |
| | | return Promise.reject(config) |
| | | }) |
| | | } |
| | | |
| | | function responseInterceptors(http) { |
| | | http.interceptors.response.use((response) => { |
| | | let res = response |
| | | const status = res.data.error_code || res.data.code || res.statusCode |
| | | const message = res?.data?.msg || res?.data?.error_description || res?.data?.message || '系统错误' |
| | | if (status !== 200) { |
| | | uni.showToast({title: message, icon: 'none'}); |
| | | return Promise.reject(response); |
| | | } |
| | | return response; |
| | | }, (response) => { |
| | | let res = response |
| | | const message = res?.data?.msg || res?.data?.error_description || res?.data?.message || '系统错误' |
| | | /* 对响应错误做点什么 (statusCode !== 200)*/ |
| | | uni.showToast({title: message, icon: 'none'}); |
| | | if (response.statusCode === 401) { |
| | | const pages = getCurrentPages() |
| | | const currentPage = pages[pages.length - 1] |
| | | uni.reLaunch({ |
| | | url: `/pages/login/index?redirect=/${currentPage.route}` |
| | | }) |
| | | } |
| | | return Promise.reject(response) |
| | | }) |
| | | } |
| | | |
| | | // 引入拦截器配置 |
| | | export function setupRequest () { |
| | | http.setConfig(defaultConfig => { |
| | | /* defaultConfig 为默认全局配置 */ |
| | | defaultConfig.baseURL = getEnvObj().VITE_API_BASE_URL_GD |
| | | // #ifdef H5 |
| | | if (import.meta.env.VITE_APP_PROXY === "true") { |
| | | defaultConfig.baseURL = import.meta.env.VITE_API_PREFIX_GD |
| | | } |
| | | // #endif |
| | | return defaultConfig |
| | | }) |
| | | requestInterceptors(http) |
| | | responseInterceptors(http) |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | export function get (url, config) { |
| | | return request({ ...config, url, method: "GET" }) |
| | | } |
| | | |
| | | export function post (url, config) { |
| | | return request({ ...config, url, method: "POST" }) |
| | | } |
| | | |
| | | export function upload (url, config) { |
| | | return request({ ...config, url, method: "UPLOAD" }) |
| | | } |
| | | |
| | | export function download (url, config) { |
| | | return request({ ...config, url, method: "DOWNLOAD" }) |
| | | } |
| | | |
| | | export default setupRequest |