吉安感知网项目-前端
shuishen
2026-01-26 38e3bb79544ed4a18fb61b892d4832cafc83c211
Merge branch 'master' of http://139.196.74.78:10010/r/jagzwxm/ja_web
14 files modified
1 files added
269 ■■■■■ changed files
applications/mobile-web-view/src/appComponents/workMap/index.vue 7 ●●●●● patch | view | raw | blame | history
applications/mobile-web-view/src/appPages/work/workDetail/mapWork/index.vue 38 ●●●●● patch | view | raw | blame | history
applications/task-work-order/env/.env 3 ●●●●● patch | view | raw | blame | history
applications/task-work-order/env/.env.development 2 ●●● patch | view | raw | blame | history
applications/task-work-order/src/api/zkxt/index.js 20 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/styles/common/cockpit.scss 16 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/flyingHand/index.vue 7 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/ApplyViewDialog.vue 4 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/auditRecord.vue 67 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/FormDiaLog.vue 9 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue 54 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/index.vue 15 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue 22 ●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderManage/orderManage/index.vue 2 ●●● patch | view | raw | blame | history
uniapps/work-app/src/subPackages/workDetail/index.vue 3 ●●●● patch | view | raw | blame | history
applications/mobile-web-view/src/appComponents/workMap/index.vue
@@ -291,10 +291,11 @@
watch(
    () => mapCurrentDetail,
    newVal => {
const newDataMap=newVal
        // 只有 workNavigationShow 为 true 且有经纬度时才添加标记
        if (workNavigationShow && newVal?.longitude && newVal?.latitude) {
            addIncidentMarker(newVal)
            mapCurrentDetailData.value = newVal
        if (workNavigationShow && newDataMap?.longitude && newDataMap?.latitude) {
            addIncidentMarker(newDataMap)
            mapCurrentDetailData.value = newDataMap
        } else if (!workNavigationShow && incidentMarker) {
            // 当 workNavigationShow 变为 false 时,移除已添加的标记
            markersLayer.removeLayer(incidentMarker)
applications/mobile-web-view/src/appPages/work/workDetail/mapWork/index.vue
@@ -7,56 +7,22 @@
            :workNavigationShow="true"
            :mapCurrentDetail="mapCurrentDetail"
        >
<!--            <template #eventNav>-->
<!--                <EventNavigation :mapCurrentDetail="mapCurrentDetail"></EventNavigation>-->
<!--            </template>-->
        </WorkMap>
    </div>
</template>
<script setup>
import { getDeviceRegion } from '@/api/home/aggregation'
import WorkMap from '@/appComponents/workMap/index.vue'
import EventNavigation from '@/appPages/work/workDetail/mapWork/eventNavigation.vue'
import { useRoute } from 'vue-router'
import { showToast } from 'vant'
import { getList } from '/src/api/work/index.js'
import { useStore } from 'vuex'
const store = useStore()
const userInfo = computed(() => store?.state?.user?.userInfo)
const route = useRoute()
const mapCurrentDetail = ref({})
const eventNum = ref('')
// 机巢数据
let machineData = ref([]);
// 机巢数据
const handleNodeClick = async data => {
  const droneList = await getDeviceRegion({ areaCode: userInfo.value.detail.areaCode });
  machineData.value = droneList?.data?.data;
};
const getDataList = async val => {
    const params = {
        current: 1,
        size: 9999,
        source: 1,
        event_name: val,
    }
    const res = await getList(params)
    const response = res.data.data.records
  const matchedMachine = machineData.value.find(m => m.device_sn === response[0].device_sn);
  const deviceNickname = matchedMachine?.nickname || ''
    mapCurrentDetail.value = {
        ...response[0],
        processingDetail: response[0].processing_details,
        update_photo_url: response[0].update_photo_url,
        aiType: response[0].ai_type_key_list?.join(',') || '',
    device_names:deviceNickname ? deviceNickname :''
    }
}
onMounted(async () => {
  // handleNodeClick()
    eventNum.value = route.query.currentItem
    // await getDataList(eventNum.value)
mapCurrentDetail.value = JSON.parse(decodeURIComponent(route.query.currentItem))
})
</script>
applications/task-work-order/env/.env
@@ -15,3 +15,6 @@
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS=gzip
# xt接口地址
VITE_APP_URL_XT=http://218.202.104.82:8200
applications/task-work-order/env/.env.development
@@ -17,7 +17,7 @@
# VITE_APP_URL = https://wrj.shuixiongit.com/api
VITE_APP_URL= http://192.168.1.204
VITE_APP_URL_XT=http://218.202.104.82:8200
#新大屏地址
VITE_APP_DASHBOARD_URL = 'https://wrj.shuixiongit.com/command-center-dashboard/'
applications/task-work-order/src/api/zkxt/index.js
@@ -18,3 +18,23 @@
        data:{"size":100,"current":1},
    })
}
// 获取飞手信息
export const deviceFlyerApi = (data) => {
    return request({
        url: `/deviceFlyer/deviceFlyer/queryList`,
        method: 'post',
        data: data,
    })
}
// 获取航线列表
export const airlineListApi = (data) => {
    return request({
        url: `/webservice/webservice/airline/queryList`,
        method: 'post',
        data: data,
    })
}
applications/task-work-order/src/styles/common/cockpit.scss
@@ -5,22 +5,28 @@
$form-tips-gray: #A1A3D4;
.gd-input {
  --el-input-bg-color: #{$form-bg};
  --el-input-placeholder-color: #{$form-tips};
  --bg: #{$form-bg};
  --tips: #{$form-tips};
  &.gray {
    --el-input-bg-color: #{$form-bg-gray};
    --el-input-placeholder-color: #{$form-tips-gray};
    --bg: #{$form-bg-gray};
    --tips: #{$form-tips-gray};
  }
  .el-input__wrapper, .el-textarea__inner {
    box-shadow: none !important;
    background: var(--bg);
    border: none;
  }
  .el-input__inner, .el-textarea__inner {
    &::placeholder {
      color: var(--tips);
    }
  }
  &.is-disabled {
    .el-input__wrapper {
      background: $form-bg;
      background: var(--bg);
    }
  }
}
applications/task-work-order/src/views/orderView/flyingHand/index.vue
New file
@@ -0,0 +1,7 @@
<template>
    <basic-container>飞手</basic-container>
</template>
<script setup></script>
<style scoped lang="scss"></style>
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/ApplyViewDialog.vue
@@ -428,14 +428,14 @@
/* 左侧步骤条 */
.detail-left {
    width: 25%;
    width: 35%;
    padding-right: 20px;
    border-right: 1px solid #e8e8e8;
}
/* 右侧表单 */
.detail-right {
    width: 75%;
    width: 65%;
    .reject-reason {
        margin-bottom: 20px;
        background: #f2f3f5;
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/auditRecord.vue
@@ -1,14 +1,25 @@
<template>
  <div class="audit-record-container">
    <div class="label">审批记录</div>
    <el-steps direction="vertical" :active="displayedSteps.length">
      <el-step v-for="step in displayedSteps" :key="step.status" :title="step.title" :description="`${step.person || ''}\n${step.time || ''}`" />
    </el-steps>
    <el-timeline class="gd-timeline">
      <el-timeline-item
        v-for="(step, index) in displayedSteps"
        :key="step.status"
        :icon="Check"
        :type="index === displayedSteps.length - 1 ? 'success' : 'info'"
        :timestamp="step.time"
      >
        <div class="item-content">
          <div class="flowName">{{ step.title }}</div>
          <div >{{ step.person }}</div>
        </div>
      </el-timeline-item>
    </el-timeline>
  </div>
</template>
<script setup>
import { ref, watch } from 'vue'
import { Check } from '@element-plus/icons-vue'
import { gdSupplyDemandAuditListApi } from '@/views/orderView/orderDataManage/supplyAdd/supplyAddApi'
const props = defineProps({
@@ -89,32 +100,32 @@
<style scoped lang="scss">
.audit-record-container {
    height: 95%;
  .label {
    font-weight: 500;
    margin-bottom: 8px;
    color: #333;
width:100%;
    // height: 95%;
}
/* 时间线样式 */
:deep(.gd-timeline) {
 padding-left: 90px;
}
:deep(.el-timeline-item) {
  padding-bottom: 20px;
  .item-content {
     position: relative;
            .flowName {
                width: 80px;
                position: absolute;
                left: -120px;
                top: 0px;
            }
  }
}
/* 步骤条样式 */
:deep(.el-steps) {
  align-items: flex-start;
}
:deep(.el-step) {
  // margin-bottom: 20px;
}
:deep(.el-step__title) {
  font-size: 14px;
  font-weight: 500;
}
:deep(.el-step__description) {
  font-size: 13px;
  color: #666;
  white-space: pre-wrap;
  line-height: 1.4;
:deep(.el-timeline-item__timestamp) {
  font-size: 12px;
  color: #999;
  margin-top: 2px;
}
</style>
applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/FormDiaLog.vue
@@ -201,6 +201,7 @@
import { gdWorkOrderPageApi } from '../orderManage/orderManageApi'
import { gdManageDeviceListApi } from '../orderManage/gdManageDeviceApi'
import { pxToRem } from '@/utils/rem'
import { airlineListApi } from '@/api/zkxt'
// 初始化任务行
const initTaskRow = () => ({
@@ -212,7 +213,7 @@
    deviceId: null,
    taskDesc: '',
})
// todo 时间线
const dictObj = inject('dictObj')
const emit = defineEmits(['success'])
@@ -230,11 +231,7 @@
// 下拉选项
const flyerListMap = ref({}) // 飞手列表,按行索引存储
const deviceList = ref([]) // 设备列表
const routeOptions = ref([
    { name: '航线1', id: '1' },
    { name: '航线2', id: '2' },
    { name: '航线3', id: '3' },
]) // 航线假数据
const routeOptions = inject('routeOptions')
// 子任务列表
const taskList = ref([initTaskRow()])
applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue
@@ -8,6 +8,24 @@
        :close-on-click-modal="false"
    >
        <div class="content" style="display: flex">
            <div class="processBox" v-if="dialogMode !== 'add' && processList.length">
                <el-timeline class="gd-timeline">
                    <el-timeline-item
                        v-for="(activity, index) in processList"
                        :key="index"
                        :icon="Check"
                        :type="index === processList.length - 1 ? 'success' : 'info'"
                        :color="activity.color"
                        :hollow="activity.hollow"
                        :timestamp="activity.flowDesc.split(' ')[1]"
                    >
                        <div class="item-content">
                            <div>{{ activity.flowDesc.split(' ')[0] }}</div>
                            <div class="flowName">{{ activity.flowName }}</div>
                        </div>
                    </el-timeline-item>
                </el-timeline>
            </div>
            <div class="leftBox">
                <!-- 查看模式 -->
                <div class="detail-container" v-if="dialogReadonly">
@@ -27,7 +45,7 @@
                        </el-col>
                        <el-col :span="12">
                            <div class="label">巡查任务航线</div>
                            <div class="val">{{ getRouteName(formData.patrolRouteUrl) }}</div>
                            <div class="val">{{ getAirName(formData.patrolRouteUrl) }}</div>
                        </el-col>
                        <el-col :span="12">
                            <div class="label">推荐飞手</div>
@@ -218,13 +236,14 @@
import { ElMessage } from 'element-plus'
import { fieldRules, getDictLabel } from '@ztzf/utils'
import { gdPatrolTaskRepublish, gdFlyerPageApi, gdPatrolTaskAuditApi } from './inspectionRequestApi'
import { gdWorkOrderPageApi } from '../orderManage/orderManageApi'
import { gdWorkOrderFlowListApi, gdWorkOrderPageApi } from '../orderManage/orderManageApi'
import { gdManageDeviceListApi } from '../orderManage/gdManageDeviceApi'
import { pxToRem } from '@/utils/rem'
import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import { gdTaskResultListApi } from '@/views/orderView/orderManage/clueEvents/achievementApi'
import RefuseOrderDialog from '@/views/orderView/orderManage/orderManage/RefuseOrderDialog.vue'
import RefuseOrderDialog1 from '@/views/orderView/orderManage/inspectionRequest/RefuseOrderDialog1.vue'
import { Check } from '@element-plus/icons-vue'
// 初始化表单数据
const initForm = () => ({
@@ -258,11 +277,8 @@
const flyerList = ref([])
const deviceList = ref([])
const workOrderList = ref([])
const routeOptions = ref([
    { name: '航线1', id: '1' },
    { name: '航线2', id: '2' },
    { name: '航线3', id: '3' },
])
const routeOptions = inject('routeOptions')
const getAirName = inject('getAirName')
const gdStatusObj = {
    '0': { reason: '拒绝原因', operationType: '2' },
@@ -366,6 +382,14 @@
    deviceList.value = res?.data?.data ?? []
}
const processList = ref([])
// 加载时间线list
function loadList() {
    gdWorkOrderFlowListApi({ workOrderId: formData.value.id,type: '1' }).then(res => {
        processList.value = res.data.data
    })
}
// 提交编辑
async function handleSubmit() {
    const isValid = await formRef.value?.validate().catch(() => false)
@@ -396,7 +420,9 @@
async function open({ mode = 'view', row } = {}) {
    dialogMode.value = mode
    formData.value = { ...initForm(), ...row }
    console.log(row)
    ;['6', '7', '8'].includes(row.taskStatus) && getList()
    loadList()
    initMap()
}
@@ -427,8 +453,20 @@
            width: 100%;
            height: 423px;
        }
    }
    }
    .processBox {
        width: 312px;
        .item-content {
            position: relative;
            .flowName {
                width: 80px;
                position: absolute;
                left: -120px;
                top: 0px;
            }
        }
    }
    .imgBox {
        display: flex;
        flex-wrap: wrap;
applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/index.vue
@@ -137,6 +137,7 @@
import { gdPatrolTaskPageApi, gdPatrolTaskRemoveApi } from './inspectionRequestApi'
import ViewDiaLog from '@/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue'
import { useStore } from 'vuex'
import { airlineListApi } from '@/api/zkxt'
const store = useStore()
const requester = computed(() => store.state.user.userInfo?.role_id === '2014158512610869250')
@@ -232,6 +233,19 @@
    selectedIds.value = rows.map(item => item.id)
}
const routeOptions = ref([])
const getAirName = id => {
    const item = routeOptions.value.find(item => item.id === id)
    return item ? item.name : id
}
provide('routeOptions', routeOptions)
provide('getAirName', getAirName)
function getAirList() {
    airlineListApi({}).then(res => {
        routeOptions.value = res.data.data || []
    })
}
// 获取字典
function getDictList() {
    getDictionaryByCode('patrolTaskType,workOrderType,deviceLoadDemand,taskStatus').then(res => {
@@ -249,6 +263,7 @@
onMounted(() => {
    getList()
    getDictList()
    getAirList()
})
</script>
<style scoped lang="scss"></style>
applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue
@@ -374,11 +374,12 @@
// 获取推荐设备列表
async function getDeviceList() {
    const all = ['11'].includes(gdStatus.value)
    try {
        const str = [...pointList.value, pointList.value[0]].map(item => `${item.longitude} ${item.latitude}`).join(',')
        let geom = `POLYGON((${str}))`
        const res = await gdManageDeviceListApi({
            deviceIds: formData.value.recommendDeviceIds,
            deviceIds: all ? '' : formData.value.recommendDeviceIds,
            devicePayload: dialogMode.value === 'add' ? formData.value.deviceLoadDemand : '',
            geom: dialogMode.value === 'add' ? geom : '',
        })
@@ -439,7 +440,7 @@
// 加载时间线list
function loadList() {
    gdWorkOrderFlowListApi({ workOrderId: formData.value.id }).then(res => {
    gdWorkOrderFlowListApi({ workOrderId: formData.value.id,type: '0' }).then(res => {
        processList.value = res.data.data
    })
}
@@ -543,10 +544,20 @@
            position: position,
            billboard: {
                image: droneIcon,
                width: 40,
                height: 40,
                width: 20,
                height: 20,
                verticalOrigin: Cesium.VerticalOrigin.CENTER,
            },
            label: {
                text: item.nickname,
                font: '12px/1.5 Microsoft YaHei',
                style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                outlineWidth: 2,
                outlineColor: Cesium.Color.WHITE,
                horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                pixelOffset: new Cesium.Cartesian2(0, -10)
            }
        })
    })
}
@@ -563,8 +574,9 @@
        hasPatrolTaskList.value && gdPatrolTaskPage()
        dialogMode.value === 'edit' ? editPolygon() : viewPolygon()
    }
    // setMapDevice()
    setMapDevice()
    await nextTick()
    await getDeviceList()
    syncSelection()
}
applications/task-work-order/src/views/orderView/orderManage/orderManage/index.vue
@@ -82,7 +82,7 @@
        <div class="gd-table-container" v-loading="loading">
            <div class="gd-table-content gd-table-content-bg">
                <el-table class="gd-table" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="46" />
                    <el-table-column type="selection" width="46" v-if="requester"/>
                    <el-table-column type="index" width="64" label="序号" />
                    <el-table-column prop="workOrderName" show-overflow-tooltip label="工单名称" />
                    <el-table-column prop="workOrderCode" show-overflow-tooltip label="工单编号" />
uniapps/work-app/src/subPackages/workDetail/index.vue
@@ -146,8 +146,9 @@
})
// 跳转地图
const jumpMap = item => {
  const contactStr = encodeURIComponent(JSON.stringify(item))
  uni.navigateTo({
    url: `/subPackages/workDetail/mapWork/index?eventNum=${item.event_num}`,
    url: `/subPackages/workDetail/mapWork/index?eventNum=${contactStr}`,
  })
}
// 退回