吉安感知网项目-前端
张含笑
2026-01-12 43099d8b6600dee658ab83882843d81f44a886b9
Merge remote-tracking branch 'origin/master'
4 files modified
3 files added
2008 ■■■■■ changed files
uniapps/work-wx/src/pages/equipmentManagement/index.vue 138 ●●●● patch | view | raw | blame | history
uniapps/work-wx/src/pages/legalPolicy/index.vue 146 ●●●● patch | view | raw | blame | history
uniapps/work-wx/src/pages/page/index.vue 168 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/add.svg 24 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/deviceRegistration/add.vue 465 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/flightApplication/add.vue 810 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/flightApplication/index.vue 257 ●●●● patch | view | raw | blame | history
uniapps/work-wx/src/pages/equipmentManagement/index.vue
@@ -1,62 +1,130 @@
<template>
  <view class="equipmentManagement">
    <u-search :show-action="true" actionText="搜索" :animation="true"></u-search>
    <view class="card" v-for="(item, index) in list" :key="index">
      <view class="left">
        <u-image :src="item.src" mode="aspectFill" :width="100" :height="100"></u-image>
    <u-search :bgColor="'white'" v-model="noticeTitle" :show-action="true" actionText="搜索" :animation="true" @custom="getEquipmentList"></u-search>
    <view class="content">
      <view class="title">飞行设备</view>
      <view class="card" v-for="(item, index) in equipmentList" :key="index">
        <view class="left">
          <u-image :src="droneSvg" mode="aspectFill" :width="70" :height="90"></u-image>
        </view>
        <view class="right">
          <view class="name">设备名称:{{ item.name }}</view>
          <view class="txt">设备类型:{{ item.type }}</view>
          <view class="txt">设备型号:{{ item.type }}</view>
        <view class="txt">设备sn:{{ item.sn }}</view>
        </view>
      </view>
      <view class="right">
        <view class="grid-text">设备名称:{{ item.name }}</view>
        <view class="grid-text">设备类型:{{ item.type }}</view>
        <view class="grid-text">设备型号:{{ item.xh }}</view>
       <view class="grid-text">设备sn:{{ item.sn }}</view>
      </view>
    </view>
    <view class="add-btn" @click="addEquipment">
      <u-image :src="addSvg" mode="aspectFill" :width="60" :height="68"></u-image>
    </view>
  </view>
</template>
<script setup>
   import { reactive, ref } from 'vue'
  import lbPng from '@/static/images/lb.png'
const list = reactive([
  {
    src: lbPng,
    name: '设备1',
    type: '类型1',
    xh: '型号1',
    sn: 'SN123456',
  },
  {
    src: lbPng,
    name: '设备2',
    type: '类型2',
    xh: '型号2',
    sn: 'SN654321',
  },
])
import { reactive, ref } from 'vue'
import lbPng from '@/static/images/lb.png'
import addSvg from '@/static/images/add.svg'
import droneSvg from '@/static/images/drone.svg'
import { myDevicePageInfoApi, aircraftInfoPageInfoOfMyApi } from '@/api/index.js'
const equipmentList = ref([])
const noticeTitle = ref('')
// 设备列表
const getEquipmentList = async () => {
  try {
    const res = await aircraftInfoPageInfoOfMyApi({
      current: 1,
      size: 10,
      model:'',
      name: '',
    })
    console.log(8888888,res.data.data.records)
    equipmentList.value = res.data.data.records || []
  } catch (error) {
    console.error('获取设备列表失败:', error)
  }
}
// 我的设备详情
const getMyDeviceDetail = async (id) => {
  try {
    const res = await myDevicePageInfoApi({ id })
    if (res.code === 200) {
      // 处理设备详情数据
    }
  } catch (error) {
    console.error('获取我的设备详情失败:', error)
  }
}
// 新增设备
const addEquipment = () => {
  uni.navigateTo({
    url: '/subPackages/deviceRegistration/add',
  })
}
onMounted(() => {
  getEquipmentList()
})
</script>
<style scoped lang="scss">
.equipmentManagement {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  .u-search {
    padding: 10px 20px;
    height: 68rpx;
    flex: 0;
  }
  .content {
    font-family: Source Han Sans CN, Source Han Sans CN;
    height: 0;
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    background: #FFFFFF;
    padding: 0 40rpx 40rpx 40rpx;
    overflow-y: auto;
    box-sizing: border-box;
    border-radius: 12px 12px 6px 6px;
  }
  .title {
    font-weight: bold;
    font-size: 32rpx;
    color: #222324;
    padding: 40rpx 0;
  }
  .card {
    display: flex;
    margin-top: 20rpx;
    background-color: #f5f5f5;
    padding: 20rpx;
    border-radius: 10rpx;
    border-bottom: 1px solid #EBEEF3;
    .left {
      width: 100px;
      height: 100px;
      width: 70px;
      height: 90px;
      margin-right: 16rpx;
    }
    .right {
      flex: 1;
      height: 100px;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      .name {
        font-weight: 500;
        font-size: 28rpx;
        color: #1D2129;
      }
      .txt {
        font-weight: 400;
        font-size: 24rpx;
        color: #86909C;
      }
    }
  }
  .add-btn {
    position: absolute;
    bottom: 40rpx;
    right: 40rpx;
  }
}
</style>
uniapps/work-wx/src/pages/legalPolicy/index.vue
@@ -1,20 +1,33 @@
<template>
  <view class="legalPolicy">
    <u-search :show-action="true" actionText="搜索" :animation="true"></u-search>
    <u-tabs :list="list1" @click="click"></u-tabs>
    <!-- <u-navbar title="法律政策" @rightClick="rightClick" :autoBack="true"></u-navbar> -->
    <u-search :bgColor="'white'" v-model="noticeTitle" :show-action="true" actionText="搜索" :animation="true" @custom="getSysNoticeList"></u-search>
    <view class="tabs-container">
      <u-tabs :list="tabs" @click="tabClick"></u-tabs>
    </view>
    <view class="content">
      <view v-for="(item, index) in list2" :key="index">
        <view>{{ item.name }}</view>
        <view>{{ item.item }}</view>
      <view class="card" v-for="(item, index) in announcementList" :key="index">
        <view class="left">
          <u-image :src="docSvg" mode="aspectFill" :width="30" :height="36"></u-image>
        </view>
        <view class="right">
          <view class="r-top">{{ item.title }}</view>
          <view class="r-middle">{{ item.description || '暂无描述' }}</view>
          <view class="r-bottom">{{ item.time || '暂无' }}</view>
        </view>
      </view>
    </view>
  </view>
</template>
<script setup>
import { ref } from 'vue'
  import { sysNoticePageInfoApi } from '@/api/index'
  import docSvg from '@/static/images/doc.png'
import { ref, onMounted } from 'vue'
const list1 = ref([
const noticeTitle = ref('')
const tabs = ref([
  {
    name: '法律法规',
  },
@@ -23,25 +36,120 @@
  },
])
const click = (index) => {
  console.log(index)
const currentTab = ref(2)
const tabClick = (val) => {
  if (val.index === 0) {
     currentTab.value = 2
    getSysNoticeList()
  } else {
    currentTab.value = 1
    getSysNoticeList()
  }
}
const list2 = ref([
  {
    name: '法律法规1',
    item: '法律法规1的内容',
  },
  {
    name: '法律法规2',
    item: '法律法规2的内容',
  },
])
const announcementList = ref()
// 获取通知公告列表
async function getSysNoticeList() {
  try {
    const res = await sysNoticePageInfoApi({
      current: 1,
      size: 10,
      noticeType: currentTab.value,
      noticeTitle: noticeTitle.value,
    })
    announcementList.value = res.data.data.records.map(item => ({
      ...item,
      title: item.noticeTitle,
      description: item.remark,
      time: item.pubDate,
      num: item.num,
      like: item.like,
    }))
  } catch (error) {
    uni.showToast({
      title: error.message,
      icon: 'none',
      duration: 2000,
    })
  }
}
onMounted(() => {
  getSysNoticeList()
})
</script>
<style scoped lang="scss">
.legalPolicy {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
   .u-search {
    padding: 10px 20px;
    height: 68rpx;
    flex: 0;
  }
  .tabs-container {
    display: flex;
    justify-content: center;
    font-family: Source Han Sans CN, Source Han Sans CN;
    font-weight: 400;
    font-size: 14px;
    color: #4E5969;
    background: #FFFFFF;
    border-radius: 12px 12px 6px 6px;
    margin-top: 10px;
  }
  .tabs-container >>> .u-tabs__nav {
    width: auto !important;
  }
  .content {
    width: 100%;
    height: 0;
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    background: #FFFFFF;
    padding: 0 40rpx 40rpx 40rpx;
    overflow-y: auto;
    box-sizing: border-box;
    .card {
      font-family: Source Han Sans CN, Source Han Sans CN;
      display: flex;
      justify-content: space-between;
      border-bottom: 1px solid #EBEEF3;
      padding: 40rpx 0 30rpx 0;
      width: 100%;
      box-sizing: border-box;
      .left {
        .u-image {
          width: 60rpx;
          height: 72rpx;
        }
      }
      .right {
        width: calc(100% - 80rpx);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .r-middle {
        font-weight: 400;
        font-size: 13px;
        color: #86909C;
      }
      .r-bottom {
        font-weight: 400;
        font-size: 13px;
        color: #86909C;
        margin-top: 10rpx;
      }
    }
  }
}
</style>
uniapps/work-wx/src/pages/page/index.vue
@@ -13,27 +13,31 @@
            <text class="grid-text">{{baseListItem.title}}</text>
        </u-grid-item>
    </u-grid>
    <u-tabs :list="tabs" class="tabs">
      <template #right>
            <view
                style="padding-left: 4px;"
                @tap="$u.toast('插槽被点击')"
            >
                更多
            </view>
        </template>
    </u-tabs>
    <view class="card" v-for="(item,index) in announcementList" :key="index">
      <view class="left">
        <u-image :src="lbPng" :width="20" :height="20"></u-image>
      </view>
      <view class="right">
        <view class="c-top">{{ item.airspaceName }}</view>
        <view class="c-middle">{{ item.remarks || '暂无' }}</view>
        <view class="c-bottom">
          <view>{{ item.createTime }}</view>
          <view>{{ item.num || 0 }}</view>
          <view>{{ item.like || 0 }}</view>
    <view class="tabs-container">
      <u-tabs :list="tabs" @click="tabClick">
        <template #right>
              <view
                  style="padding-left: 4px;"
                  @tap="$u.toast('插槽被点击')"
              >
                  更多
              </view>
          </template>
      </u-tabs>
    </view>
    <view class="content">
      <view class="card" v-for="(item,index) in announcementList" :key="index">
        <view class="left">
          <u-image :src="docSvg" :width="30" :height="36"></u-image>
        </view>
        <view class="right">
          <view class="r-top">{{ item.title }}</view>
          <view class="r-middle">{{ item.description || '暂无' }}</view>
          <view class="r-bottom">
            <view>{{ item.time }}</view>
            <!-- <view>{{ item.num || 0 }}</view>
            <view>{{ item.like || 0 }}</view> -->
          </view>
        </view>
      </view>
    </view>
@@ -47,6 +51,7 @@
  import fxsqPng from '@/static/images/fxsq.svg'
  import flfgPng from '@/static/images/flfg.svg'
  import zczdPng from '@/static/images/zczd.svg'
  import docSvg from '@/static/images/doc.png'
  import { sysNoticePageInfoApi, flightAirspacePageInfoApi } from '@/api/index'
const lbList = reactive([]);
// lbPng 轮播图 5次
@@ -127,7 +132,14 @@
      current: 1,
      size: 10,
    })
    announcementList.value = res.data.data.records
    announcementList.value = res.data.data.records.map(item => ({
      ...item,
      title: item.airspaceName,
      description: item.remark,
      time: item.createTime,
      num: item.num,
      like: item.like,
    }))
  } catch (error) {
    uni.showToast({
      title: error.message,
@@ -137,23 +149,39 @@
  }
}
// 获取通知公告列表
async function getSysNoticeList() {
  try {
    const res = await sysNoticePageInfoApi({
      current: 1,
      size: 10,
      noticeType: 2,
    })
    if (res.code === 200) {
      announcementList.value = res.data.records
  // 获取通知公告列表
  async function getSysNoticeList(val) {
    try {
      const res = await sysNoticePageInfoApi({
        current: 1,
        size: 10,
        noticeType: val,
      })
      announcementList.value = res.data.data.records.map(item => ({
        ...item,
        title: item.noticeTitle,
        description: item.remark,
        time: item.pubDate,
        num: item.num,
        like: item.like,
      }))
    } catch (error) {
      uni.showToast({
        title: error.message,
        icon: 'none',
        duration: 2000,
      })
    }
  } catch (error) {
    uni.showToast({
      title: error.message,
      icon: 'none',
      duration: 2000,
    })
  }
function tabClick(value) {
  announcementList.value = []
  if (value.index === 0) {
    getFlightAirspaceList()
  } else if (value.index === 1) {
    getSysNoticeList(2)
  } else if (value.index === 2) {
    getSysNoticeList(1)
  }
}
@@ -166,6 +194,8 @@
.page {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  .u-grid {
    margin-top: 20px;
    .grid-text {
@@ -173,30 +203,66 @@
      font-weight: 500;
      font-size: 14px;
      color: #222324;
      margin-top: 10px;
    }
  }
  .tabs {
    background-color: white;
    border-radius: 10px;
    padding: 0 10px;
    margin-top: 20px;
  .tabs-container {
    font-family: Source Han Sans CN, Source Han Sans CN;
    font-weight: 400;
    font-size: 14px;
    color: #4E5969;
    background: #FFFFFF;
    border-radius: 12px 12px 6px 6px;
    padding: 0 20rpx;
    margin-top: 10px;
  }
  .content {
    width: 100%;
    height: 0;
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    background: #FFFFFF;
    padding: 0 40rpx 40rpx 40rpx;
    overflow-y: auto;
    box-sizing: border-box;
  }
  .card {
    background-color: white;
    padding: 0 10px;
    padding-top: 10px;
    font-family: Source Han Sans CN, Source Han Sans CN;
    display: flex;
    justify-content: space-between;
    border-bottom: 1px solid #EBEEF3;
    padding: 40rpx 0 30rpx 0;
    width: 100%;
    box-sizing: border-box;
    .left {
      width: 20px;
      height: 20px;
      .u-image {
          width: 60rpx;
          height: 72rpx;
        }
    }
    .right {
      flex: 1;
      margin-left: 10px;
      .c-bottom {
      width: calc(100% - 80rpx);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      .r-top {
        font-weight: 500;
        font-size: 14px;
        color: #1D2129;
      }
      .r-middle {
        font-weight: 400;
        font-size: 13px;
        color: #86909C;
      }
      .r-bottom {
        display: flex;
        justify-content: space-between;
        font-weight: 400;
        font-size: 13px;
        color: #86909C;
        margin-top: 10rpx;
      }
    }
  }
uniapps/work-wx/src/static/images/add.svg
New file
@@ -0,0 +1,24 @@
<svg width="68" height="68" viewBox="0 0 68 68" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 1321316305" filter="url(#filter0_d_88_1711)">
<g id="&#229;&#155;&#190;&#230;&#160;&#135;">
<circle id="bg" cx="34" cy="30" r="30" fill="#1D6FE9"/>
</g>
<g id="Group 1321316267">
<g id="Frame">
<path id="Vector" d="M35.002 15.8025C35.1865 15.8025 35.3635 15.8758 35.494 16.0063C35.6245 16.1368 35.6978 16.3138 35.6978 16.4983V27.6314H46.8309C47.0154 27.6314 47.1924 27.7047 47.3229 27.8352C47.4534 27.9656 47.5267 28.1426 47.5267 28.3272V29.7188C47.5267 29.9033 47.4534 30.0803 47.3229 30.2108C47.1924 30.3413 47.0154 30.4146 46.8309 30.4146H35.6978V41.5477C35.6978 41.7322 35.6245 41.9092 35.494 42.0397C35.3635 42.1702 35.1865 42.2435 35.002 42.2435H33.6104C33.4258 42.2435 33.2489 42.1702 33.1184 42.0397C32.9879 41.9092 32.9146 41.7322 32.9146 41.5477V30.4146H21.7815C21.597 30.4146 21.42 30.3413 21.2895 30.2108C21.159 30.0803 21.0857 29.9033 21.0857 29.7188V28.3272C21.0857 28.1426 21.159 27.9656 21.2895 27.8352C21.42 27.7047 21.597 27.6314 21.7815 27.6314H32.9146V16.4983C32.9146 16.3138 32.9879 16.1368 33.1184 16.0063C33.2489 15.8758 33.4258 15.8025 33.6104 15.8025H35.002Z" fill="white" stroke="white" stroke-width="0.4"/>
</g>
</g>
</g>
<defs>
<filter id="filter0_d_88_1711" x="0" y="0" width="68" height="68" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_88_1711"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_88_1711" result="shape"/>
</filter>
</defs>
</svg>
uniapps/work-wx/src/subPackages/deviceRegistration/add.vue
New file
@@ -0,0 +1,465 @@
<template>
<view class="deviceRegistration">
    <u-form labelPosition="top" :model="formParams" :rules="rules" ref="formRef">
        <u-form-item
                label="飞行器名称"
                labelWidth="200rpx"
                prop="name"
                :borderBottom="true"
                ref="item1"
                required
        >
            <u-input v-model="formParams.name" border="none" placeholder="请输入"></u-input>
        </u-form-item>
        <u-form-item
                label="SN(出厂序列号)"
                labelWidth="230rpx"
                prop="sn"
                :borderBottom="true"
                ref="item2"
                required
        >
            <u-input v-model="formParams.sn" border="none" placeholder="请输入"></u-input>
        </u-form-item>
        <u-form-item
                label="飞行器厂商"
                labelWidth="230rpx"
                prop="manufacturer"
                :borderBottom="true"
                ref="item2"
                required
                @click="showManufacturer = true"
        >
            <u-input
                v-model="formParams.manufacturerText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择飞行器厂商"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
        <u-form-item
                label="飞行器型号"
                labelWidth="200rpx"
                prop="model"
                :borderBottom="true"
                ref="item1"
                required
        >
            <u-input v-model="formParams.model" border="none" placeholder="请输入"></u-input>
        </u-form-item>
        <u-form-item
                label="是否改装"
                labelWidth="200rpx"
                prop="isModifiedText"
                :borderBottom="true"
                ref="item1"
                @click="showIsModified = true"
                required
        >
            <u-input
                v-model="formParams.isModifiedText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择是否改装"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
        <u-form-item
                label="飞行器类型"
                labelWidth="200rpx"
                prop="type"
                :borderBottom="true"
                ref="item1"
                required
                @click="showType = true"
        >
            <u-input
                v-model="formParams.typeText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择飞行器类型"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
         <u-form-item
                label="持有人"
                labelWidth="200rpx"
                prop="aircraftName"
                :borderBottom="true"
                ref="item1"
        >
            <u-input
                    v-model="formParams.aircraftName"
                    border="none"
                    placeholder="请输入"
            ></u-input>
        </u-form-item>
         <u-form-item
                label="购买日期"
                labelWidth="200rpx"
                prop="purchaseDate"
                :borderBottom="true"
                ref="item1"
                @click="showPurchaseDate = true"
        >
            <u-input v-model="formParams.purchaseDate" border="none" placeholder="请选择日期" suffixIcon="calendar"></u-input>
        </u-form-item>
        <u-form-item
                label="有无保险"
                labelWidth="230rpx"
                prop="hasInsurance"
                :borderBottom="true"
                ref="item2"
                @click="showHasInsurance = true"
        >
            <u-input
                v-model="formParams.hasInsuranceText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择有无保险"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
        <u-form-item
                label="所属区域"
                labelWidth="230rpx"
                prop="serialNumber"
                :borderBottom="true"
                ref="item2"
        >
            <view class="select-wrapper">
                <u-input
                        v-model="formParams.serialNumber"
                        border="none"
                        placeholder="请选择"
                        readonly
                ></u-input>
                <view class="select-icon">▼</view>
            </view>
        </u-form-item>
        <u-form-item
                label="民用航空器登记证书"
                labelWidth="300rpx"
                prop="aircraftName"
                :borderBottom="true"
                ref="item1"
        >
            <u-input
                    v-model="formParams.aircraftName"
                    border="none"
                    placeholder="请输入"
            ></u-input>
        </u-form-item>
        <u-form-item
                label="飞行器照片"
                labelWidth="200rpx"
                prop="aircraftName"
                :borderBottom="true"
                ref="item1"
        >
            <u-input
                    v-model="formParams.aircraftName"
                    border="none"
                    placeholder="请输入"
            ></u-input>
        </u-form-item>
        <u-form-item
                label="备注"
                labelWidth="200rpx"
                prop="remarks"
                :borderBottom="true"
                ref="item1"
        >
            <u-input
                    v-model="formParams.remarks"
                    border="none"
                    placeholder="请输入"
            ></u-input>
        </u-form-item>
        <u-button
                type="primary"
                size="small"
                @click="submitForm"
            >
                提交
            </u-button>
    </u-form>
    <!-- 飞行器型号 -->
    <u-picker
        :show="showType"
        :columns="[typeList]"
        keyName="label"
        @confirm="onPickerConfirmType"
        @cancel="showType = false"
    />
    <!-- 飞行器厂商 -->
    <u-picker
        :show="showManufacturer"
        :columns="[manufacturerList]"
        keyName="label"
        @confirm="onPickerConfirmManufacturer"
        @cancel="showManufacturer = false"
    />
    <u-picker
        :show="showIsModified"
        :columns="[actionsModified]"
        keyName="label"
        @confirm="onPickerConfirm"
        @cancel="showIsModified = false"
    />
    <u-picker
        :show="showHasInsurance"
        :columns="[actionsHasInsurance]"
        keyName="label"
        @confirm="onPickerConfirmHasInsurance"
        @cancel="showHasInsurance = false"
    />
    <u-datetime-picker
      :show="showPurchaseDate"
      v-model="birthdayValue"
      mode="date"
      @confirm="onPurchaseDate"
      @cancel="showPurchaseDate = false"
    />
</view>
</template>
<script setup>
import { aircraftInfoSaveApi } from '@/api/index'
import { ref, computed } from 'vue'
import dayjs from 'dayjs'
const formRef = ref(null);
const formParams = ref({
    name: '',
    manufacturer: '', // 制造商
    manufacturerText: '', // 制造商文本
    model: '', // 型号
    sn: '', // sn编号
    type: '', // 航空器类型
    typeText: '', // 航空器类型文本
    holder: '', // 持有人
    pilotId: '', // 飞行员id
    status: '', // 状态 飞行器状态:0-未激活,1-正常,2-维修中,3-报废:
    purchaseDate: '', // 购买日期
    isModified: '', // 是否改装 0否 1是:
    isModifiedText: '', // 是否改装文本
    hasInsurance: '', // 是否有保险
    hasInsuranceText: '', // 是否有保险文本
    region: '', // 所属区域
    caacRegistrationCode: '', // 民用航空器登记证书
    deviceImage: '', // 飞行器照片
    remarks: '', // 备注
})
const rules = ref({
    name: [
        { required: true, message: '请输入飞行器名称', trigger: 'blur' }
    ],
    manufacturer: [
        { required: true, message: '请选择飞行器厂商', trigger: 'change' }
    ],
    model: [
        { required: true, message: '请输入飞行器型号', trigger: 'blur' }
    ],
    sn: [
        { required: true, message: '请选择SN(出厂序列号)', trigger: 'change' }
    ],
    isModifiedText: [
        { required: true, message: '请选择是否改装', trigger: 'change' }
    ],
})
// 是否改装
const actionsModified = ref([
    {
        label: '否',
        value: 0
    },
    {
        label: '是',
        value: 1
    }
])
const showIsModified = ref(false);
const onPickerConfirm = (e) => {
  const selected = e.value[0]
  formParams.value.isModified = selected.value
  formParams.value.isModifiedText = selected.label
  showIsModified.value = false
}
const showPurchaseDate = ref(false);
const birthdayValue = ref(Date.now()); // 设置默认值为当前时间戳
// 购买日期
const onPurchaseDate = (e) => {
    formParams.value.purchaseDate = dayjs(e.value).format('YYYY-MM-DD')
    showPurchaseDate.value = false
}
// 是否有保险
const actionsHasInsurance = ref([
    {
        label: '无',
        value: '0'
    },
    {
        label: '有',
        value: '1'
    }
])
const showHasInsurance = ref(false);
const onPickerConfirmHasInsurance = (e) => {
  const selected = e.value[0]
  formParams.value.hasInsurance = selected.value
  formParams.value.hasInsuranceText = selected.label
  showHasInsurance.value = false
}
// 飞行器厂商
const showManufacturer = ref(false);
const manufacturerList = ref([
    {
        label: 'A厂商',
        value: 'A厂商'
    },
    {
        label: 'B厂商',
        value: 'B厂商'
    },
])
// 选择飞行器厂商
const onPickerConfirmManufacturer = (e) => {
  const selected = e.value[0]
  formParams.value.manufacturer = selected.value
  formParams.value.manufacturerText = selected.label
  showManufacturer.value = false
}
// 飞行器型号
const showType = ref(false);
const typeList = ref([
    {
        label: 'A型号',
        value: 'A型号'
    },
    {
        label: 'B型号',
        value: 'B型号'
    },
])
// 选择飞行器型号
const onPickerConfirmType = (e) => {
  const selected = e.value[0]
  formParams.value.type = selected.value
  formParams.value.typeText = selected.label
  showType.value = false
}
// 提交表单
const submitForm = async () => {
    try {
        if (await formRef.value.validate()) {
            const res = await aircraftInfoSaveApi(formParams.value)
            if (res.data.code === 200) {
                uni.showToast({
                    title: '航空器注册成功',
                    icon: 'success'
                })
                // 跳转设备列表页
                uni.switchTab({
                    url: '/pages/equipmentManagement/index',
                })
            } else {
                uni.showToast({
                    title: res.msg || '航空器注册失败',
                    icon: 'error'
                })
            }
        }
    } catch (error) {
        console.log('表单验证失败:', error)
        // 验证失败时,u-form组件会自动显示错误提示
        // 这里可以添加额外的失败处理逻辑
    }
}
</script>
<style scoped lang="scss">
.deviceRegistration {
    padding: 24rpx;
    .select-wrapper {
        position: relative;
        width: 100%;
        .select-icon {
            position: absolute;
            right: 20rpx;
            top: 50%;
            transform: translateY(-50%);
            color: #999;
            font-size: 24rpx;
            pointer-events: none;
        }
    }
    :deep(.u-form-item) {
        margin-bottom: 40rpx;
        padding: 16rpx 24rpx 18rpx 24rpx;
        border-radius: 6px 6px 6px 6px;
        background: white;
        :deep(.u-line) {
            border-bottom: 1px solid #EFEFEF;
        }
        :deep(.u-input) {
            width: 100%;
            height: 80rpx;
            border-radius: 8rpx;
            padding: 0 20rpx;
            background-color: #f5f5f5;
            &::placeholder {
                font-family: Source Han Sans CN, Source Han Sans CN;
                font-weight: 400;
                font-size: 30rpx;
                color: #D2D2D2;
            }
        }
        .clickable-input {
            width: 100%;
            cursor: pointer;
        }
        :deep(.u-form-item__label) {
            margin-bottom: 20rpx;
            // font-weight: bold;
            // color: #333;
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: 400;
            font-size: 30rpx;
            color: #222324;
        }
        :deep(.u-form-item__required) {
            color: #FF2600;
            margin-right: 8rpx;
        }
    }
}
</style>
uniapps/work-wx/src/subPackages/flightApplication/add.vue
New file
@@ -0,0 +1,810 @@
<template>
<view class="flightApplication-add">
    <view class="title">
        基本信息
    </view>
    <u-form labelPosition="top" :model="formParams" :rules="rules" ref="formRef">
        <u-form-item
                label="飞行计划"
                labelWidth="200rpx"
                prop="flightPlanName"
                :borderBottom="true"
                ref="item1"
                required
        >
            <u-input v-model="formParams.flightPlanName" border="none" placeholder="请输入飞行计划名称"></u-input>
        </u-form-item>
        <u-form-item
                label="任务类型"
                labelWidth="230rpx"
                prop="flightTaskType"
                :borderBottom="true"
                ref="item2"
                required
                @click="isShowFlightTaskType = true"
        >
            <u-input
                v-model="formParams.flightTaskTypeText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择任务类型"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
        <u-form-item
                label="飞行规则"
                labelWidth="230rpx"
                prop="flightRule"
                :borderBottom="true"
                ref="item2"
                required
                @click="isShowFlightRule = true"
        >
            <u-input
                v-model="formParams.flightRuleText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择飞行规则"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
        <u-form-item
                label="飞行方式"
                labelWidth="200rpx"
                prop="flightMode"
                :borderBottom="true"
                ref="item1"
                @click="isShowFlightMode = true"
                required
        >
            <u-input
                v-model="formParams.flightModeText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择飞行方式"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
        <u-form-item
                label="飞行活动日期"
                labelWidth="200rpx"
                prop="timeRange"
                :borderBottom="true"
                ref="item1"
                @click="isShowTimeRange = true"
                required
        >
            <u-input v-model="formParams.timeRange" border="none" placeholder="请选择日期" suffixIcon="calendar"></u-input>
        </u-form-item>
        <u-form-item
                label="计划类型"
                labelWidth="200rpx"
                prop="planType"
                :borderBottom="true"
                ref="item1"
                required
                @click="isShowPlanType = true"
        >
            <u-input
                v-model="formParams.planTypeText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择计划类型"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
         <u-form-item
                label="联系人"
                labelWidth="200rpx"
                prop="contactPerson"
                :borderBottom="true"
                required
                ref="item1"
        >
            <u-input v-model="formParams.contactPerson" border="none" placeholder="请输入"></u-input>
        </u-form-item>
        <u-form-item
                label="联系电话"
                labelWidth="200rpx"
                prop="contactPhone"
                :borderBottom="true"
                required
                ref="item1"
        >
            <u-input v-model="formParams.contactPhone" border="none" placeholder="请输入"></u-input>
        </u-form-item>
        <u-form-item
                label="承办人"
                labelWidth="200rpx"
                prop="undertaker"
                :borderBottom="true"
                required
                ref="item1"
        >
            <u-input v-model="formParams.undertaker" border="none" placeholder="请输入"></u-input>
        </u-form-item>
        <u-form-item
                label="承办人联系电话"
                labelWidth="300rpx"
                prop="undertakerPhone"
                :borderBottom="true"
                required
                ref="item1"
        >
            <u-input v-model="formParams.undertakerPhone" border="none" placeholder="请输入"></u-input>
        </u-form-item>
        <u-form-item
                label="临时空域批件"
                labelWidth="200rpx"
                prop="aircraftName"
                :borderBottom="true"
                ref="item1"
        >
            <u-input v-model="formParams.tempAirspaceApproval" border="none" readonly placeholder="(建议文件大小100M内,仅支持pdf、jpg、jpeg、png等格式)"></u-input>
            <template #right>
                <u-upload
                    @afterRead="afterRead"
                    @delete="deletePic"
                    name="6"
                    multiple
                    :maxCount="1"
                    width="250"
                    height="150"
                >
                    <view class="upload">上传文件</view>
                </u-upload>
            </template>
        </u-form-item>
        <u-form-item
                label="气象条件"
                labelWidth="200rpx"
                prop="weatherCondition"
                :borderBottom="true"
                ref="item1"
        >
            <u-input
                    v-model="formParams.weatherCondition"
                    border="none"
                    placeholder="请输入"
            ></u-input>
        </u-form-item>
         <view>飞行器/飞手</view>
        <u-form-item
                label="飞行器"
                labelWidth="230rpx"
                prop="aircraftId"
                :borderBottom="true"
                required
                ref="item2"
                @click="isShowAircraftInfo = true"
        >
            <u-input
                v-model="formParams.aircraftText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择飞行器"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
        <u-form-item
                label="飞手"
                labelWidth="230rpx"
                prop="pilotId"
                :borderBottom="true"
                ref="item2"
                required
                @click="isShowPilotInfo = true"
        >
            <u-input
                v-model="formParams.pilotText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择飞手"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
        <view>空域/航线/场点</view>
        <u-form-item
                label="空域"
                labelWidth="230rpx"
                prop="airspaceId"
                :borderBottom="true"
                ref="item2"
                required
                @click="isShowAirspaceInfo = true"
        >
            <u-input
                v-model="formParams.airspaceText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择空域"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
        <u-form-item
                label="航线"
                labelWidth="230rpx"
                prop="routeId"
                :borderBottom="true"
                ref="item2"
                required
                @click="isShowRouteInfo = true"
        >
            <u-input
                v-model="formParams.routeText"
                disabled
                disabledColor="#ffffff"
                placeholder="请选择航线"
                border="none"
            ></u-input>
            <template #right>
                <up-icon
                    name="arrow-down"
                ></up-icon>
            </template>
        </u-form-item>
        <u-button
                type="primary"
                size="small"
                @click="submitForm"
            >
                提交
            </u-button>
    </u-form>
    <!-- 飞任务类型 -->
    <u-picker
        :show="isShowFlightTaskType"
        :columns="[actionsFlightTaskType]"
        keyName="label"
        @confirm="onPickerFlightTaskType"
        @cancel="isShowFlightTaskType = false"
    />
    <!-- 飞行规则 -->
    <u-picker
        :show="isShowFlightRule"
        :columns="[actionsFlightRule]"
        keyName="label"
        @confirm="onPickerFlightRule"
        @cancel="isShowFlightRule = false"
    />
    <!-- 飞行方式 -->
    <u-picker
        :show="isShowFlightMode"
        :columns="[actionsFlightMode]"
        keyName="label"
        @confirm="onPickerFlightMode"
        @cancel="isShowFlightMode = false"
    />
    <!-- 计划类型 -->
    <u-picker
        :show="isShowPlanType"
        :columns="[actionsPlanType]"
        keyName="label"
        @confirm="onPickerPlanType"
        @cancel="isShowPlanType = false"
    />
    <u-calendar :show="isShowTimeRange" mode="range" @confirm="onConfirmTimeRange" @close="isShowTimeRange = false" :close-on-click-overlay="true"></u-calendar>
    <!-- 飞行器 -->
     <u-picker
        :show="isShowAircraftInfo"
        :columns="[aircraftInfoList]"
        keyName="label"
        @confirm="onPickerAircraftInfo"
        @cancel="isShowAircraftInfo = false"
    />
    <!-- 飞手 -->
    <u-picker
        :show="isShowPilotInfo"
        :columns="[pilotInfoList]"
        keyName="label"
        @confirm="onPickerPilotInfo"
        @cancel="isShowPilotInfo = false"
    />
    <!-- 空域 -->
    <u-picker
        :show="isShowAirspaceInfo"
        :columns="[airspaceInfoList]"
        keyName="label"
        @confirm="onPickerAirspaceInfo"
        @cancel="isShowAirspaceInfo = false"
    />
    <!-- 航线 -->
    <u-picker
        :show="isShowFlightRouteInfo"
        :columns="[flightRouteInfoList]"
        keyName="label"
        @confirm="onPickerFlightRouteInfo"
        @cancel="isShowFlightRouteInfo = false"
    />
</view>
</template>
<script setup>
import { flightPlanSaveApi, flightRoutePageInfoApi, aircraftInfoPageInfoOfMyApi, pilotInfoPageInfoOfMyApi, flightAirspacePageInfoApi, uploadFileApi } from '@/api/index'
import { ref, computed, onMounted } from 'vue'
import dayjs from 'dayjs'
const formRef = ref(null);
const formParams = ref({
    flightPlanNo: '', //飞行计划编号
    flightPlanName: '', // 飞行计划名称
    flightTaskType: '', // 飞行任务类型
    flightTaskTypeText: '', // 飞行任务类型文本
    flightRule: '', // 飞行规则
    flightRuleText: '', // 飞行规则文本
    flightMode: '', // 飞行方式
    flightModeText: '', // 飞行方式文本
    tempAirspaceApproval: '', // 临时空域批件
    planType: '', // 计划类型
    planTypeText: '', // 计划类型文本
    contactPerson: '', // 联系人
    contactPhon: '', // 联系人电话
    undertaker: '', // 承办人
    undertakerPhone: '', // 承办人电话
    timeRange: '', // 时间范围
    flightStartTime: '', // 飞行活动开始时间
    flightEndTime: '', // 飞行活动结束时间
    weatherCondition: '', // 气象条件
    spacecraftId: '', // 航天器id
    spacecraftText: '', // 航天器文本
    pilotId: '', // 飞手id
    pilotText: '', // 飞手文本
    airspaceId: '', // 空域id
    airspaceText: '', // 空域文本
    routeId: '', // 航线id
    routeText: '', // 航线文本
})
const rules = ref({
    flightPlanName: [
        { required: true, message: '请输入飞行计划名称', trigger: 'blur' }
    ],
    flightTaskType: [
        { required: true, message: '请选择飞行任务类型', trigger: 'change' }
    ],
    flightRule: [
        { required: true, message: '请选择飞行规则', trigger: 'change' }
    ],
    flightMode: [
        { required: true, message: '请选择飞行方式', trigger: 'change' }
    ],
    contactPerson: [
        { required: true, message: '请输入联系人', trigger: 'blur' }
    ],
    contactPhon: [
        { required: true, message: '请输入联系人电话', trigger: 'blur' }
    ],
    undertaker: [
        { required: true, message: '请输入承办人', trigger: 'blur' }
    ],
    undertakerPhone: [
        { required: true, message: '请输入承办人联系电话', trigger: 'blur' }
    ],
    timeRange: [
        { required: true, message: '请选择时间范围', trigger: 'change' }
    ],
    spacecraftId: [
        { required: true, message: '请选择飞行器', trigger: 'change' }
    ],
    pilotId: [
        { required: true, message: '请选择飞手', trigger: 'change' }
    ],
    airspaceId: [
        { required: true, message: '请选择空域', trigger: 'change' }
    ],
    routeId: [
        { required: true, message: '请选择航线', trigger: 'change' }
    ],
})
// 任务类型
const isShowFlightTaskType = ref(false)
const actionsFlightTaskType = [
    {
        label: '警务',
        value: '警务',
    },
    {
        label: '文旅',
        value: '文旅',
    },
    {
        label: '航拍',
        value: '航拍',
    },
    {
        label: '物流',
        value: '物流',
    },
    {
        label: '巡检',
        value: '巡检',
    },
    {
        label: '植保',
        value: '植保',
    },
]
const onPickerFlightTaskType = (e) => {
  const selected = e.value[0]
  formParams.value.flightTaskType = selected.value
  formParams.value.flightTaskTypeText = selected.label
  isShowFlightTaskType.value = false
}
// 飞行规则
const isShowFlightRule = ref(false)
const actionsFlightRule = [
    {
        label: '目视餡相飞行规则(VFR)',
        value: '目视餡相飞行规则(VFR)',
    },
    {
        label: '仪表飞行规则(IFR)',
        value: '仪表飞行规则(IFR)',
    },
]
const onPickerFlightRule = (e) => {
  const selected = e.value[0]
  formParams.value.flightRule = selected.value
  formParams.value.flightRuleText = selected.label
  isShowFlightRule.value = false
}
// 飞行方式
const isShowFlightMode = ref(false)
const actionsFlightMode = [
    {
        label: '视距内飞行 (VLOS)',
        value: '视距内飞行 (VLOS)',
    },
    {
        label: '超视距飞行(BVLOS)',
        value: '超视距飞行(BVLOS)',
    },
]
const onPickerFlightMode = (e) => {
  const selected = e.value[0]
  formParams.value.flightMode = selected.value
  formParams.value.flightModeText = selected.label
  isShowFlightMode.value = false
}
// 计划类型
const isShowPlanType = ref(false)
const actionsPlanType = [
    {
        label: '一般',
        value: '0',
    },
    {
        label: '紧急',
        value: '1',
    }
]
const onPickerPlanType = (e) => {
  const selected = e.value[0]
  formParams.value.planType = selected.value
  formParams.value.planTypeText = selected.label
  isShowPlanType.value = false
}
// 是否显示日期
const isShowTimeRange = ref(false)
// 确认时间范围
const onConfirmTimeRange = (e) => {
    // 尝试各种可能的 u-calendar range 模式返回格式
    let startDate, endDate
    // 模式1:uView Plus 1.0+ u-calendar range 模式返回 { startDate, endDate }
    if (e && e.startDate && e.endDate) {
        startDate = e.startDate
        endDate = e.endDate
        console.log('Using format 1: { startDate, endDate }')
    }
    // 模式2:uView 2.x u-calendar range 模式返回 { value: [start, end] }
    else if (e && e.value && Array.isArray(e.value) && e.value.length >= 2) {
        startDate = e.value[0]
        endDate = e.value[1]
        console.log('Using format 2: { value: [start, end] }')
    }
    // 模式3:直接返回数组 [start, end]
    else if (Array.isArray(e) && e.length >= 2) {
        startDate = e[0]
        endDate = e[1]
        console.log('Using format 3: [start, end]')
    }
    // 模式4:其他可能的嵌套格式
    else if (e && e.start && e.end) {
        startDate = e.start
        endDate = e.end
        console.log('Using format 4: { start, end }')
    }
    // 模式5:检查是否有其他可能的日期字段
    else if (e) {
        console.log('Trying to find date fields in e:', e)
        // 尝试提取任何可能的日期字段
        const dateFields = ['start', 'end', 'startTime', 'endTime', 'begin', 'finish']
        for (const field of dateFields) {
            if (e[field]) {
                console.log(`Found date field ${field}:`, e[field])
            }
        }
    }
    if (startDate && endDate) {
        // 格式化显示时间范围
        formParams.value.timeRange = `${startDate} 至 ${endDate}`
        formParams.value.flightStartTime = startDate
        formParams.value.flightEndTime = endDate
    } else {
        console.error('Unable to extract valid date range from:', e)
    }
    isShowTimeRange.value = false
}
// 获取飞行器信息
const isShowAircraftInfo = ref(false)
const aircraftInfoList = ref([])
function getAircraftInfo() {
    aircraftInfoPageInfoOfMyApi({
        current: 1,
        size: 1000,
    }).then(res => {
        aircraftInfoList.value = res.data.data.records.map(item => ({
            label: item.name || '暂无',
            value: item.id,
        }))
    })
}
const onPickerAircraftInfo = (e) => {
  const selected = e.value[0]
  formParams.value.aircraftId = selected.value
  formParams.value.aircraftText = selected.label
  isShowAircraftInfo.value = false
}
// 获取飞手信息
const isShowPilotInfo = ref(false)
const pilotInfoList = ref([])
function getPilotInfo() {
    pilotInfoPageInfoOfMyApi({
        current: 1,
        size: 1000,
    }).then(res => {
        pilotInfoList.value = res.data.data.records.map(item => ({
            label: item.name || '暂无',
            value: item.id,
        }))
    })
}
const onPickerPilotInfo = (e) => {
  const selected = e.value[0]
  formParams.value.pilotId = selected.value
  formParams.value.pilotText = selected.label
  isShowPilotInfo.value = false
}
// 获取空域信息
const isShowAirspaceInfo = ref(false)
const airspaceInfoList = ref([])
function getAirspaceInfo() {
    flightAirspacePageInfoApi({
        current: 1,
        size: 1000,
    }).then(res => {
        airspaceInfoList.value = res.data.data.records.map(item => ({
            label: item.airspaceName || '暂无',
            value: item.id,
        }))
    })
}
const onPickerAirspaceInfo = (e) => {
  const selected = e.value[0]
  formParams.value.airspaceId = selected.value
  formParams.value.airspaceText = selected.label
  isShowAirspaceInfo.value = false
}
// 获取航线信息
const isShowFlightRouteInfo = ref(false)
const flightRouteInfoList = ref([])
function getFlightRouteInfo() {
    flightRoutePageInfoApi({
        current: 1,
        size: 1000,
    }).then(res => {
        flightRouteInfoList.value = res.data.data.records.map(item => ({
            label: item.name,
            value: item.id,
        }))
    })
}
const onPickerFlightRouteInfo = (e) => {
  const selected = e.value[0]
  formParams.value.routeIdouteId = selected.value
  formParams.value.routeText = selected.label
  isShowFlightRouteInfo.value = false
}
// 文件上传处理
const afterRead = (event) => {
    // 获取上传的文件对象
    const file = event.file;
    console.log('上传的文件:', file);
    // 显示加载提示
    uni.showLoading({
        title: '上传中...'
    });
    // 调用上传文件接口
    uploadFileApi({
        file: file, // 传入文件对象
        // 可以根据接口需要添加其他参数
        type: 'tempAirspaceApproval' // 示例参数,表示上传的是临时空域批件
    }).then(res => {
        uni.hideLoading();
        console.log('上传成功结果:', res);
        // 根据接口返回的数据结构处理结果
        if (res.data && res.data.code === 200) {
            // 假设接口返回的数据结构是 { url, fileName } 等
            const uploadResult = res.data.data;
            // 更新表单数据,将上传结果展示在input内
            formParams.value.tempAirspaceApproval = uploadResult.fileName || uploadResult.url || '文件上传成功';
            // 可以将完整的上传信息保存到表单中,以便提交时使用
            formParams.value.tempAirspaceApprovalFile = uploadResult;
            uni.showToast({
                title: '上传成功',
                icon: 'success'
            });
        } else {
            uni.showToast({
                title: res.msg || '上传失败',
                icon: 'none'
            });
        }
    }).catch(err => {
        uni.hideLoading();
        console.error('上传失败:', err);
        uni.showToast({
            title: '上传失败',
            icon: 'none'
        });
    });
};
// 提交表单
const submitForm = async () => {
  await formRef.value.validate()
  if (!formRef.value.isValid) {
    return
  }
  flightPlanSaveApi(formParams.value).then(res => {
    if (res.data.code === 200) {
      uni.showToast({
        title: '提交成功',
        icon: 'success',
        duration: 2000
      })
      uni.navigateBack({
        delta: 1
      })
    } else {
      uni.showToast({
        title: res.msg || '提交失败',
        icon: 'none',
        duration: 2000
      })
    }
  })
}
onMounted(() => {
    getAircraftInfo()
    getPilotInfo()
    getAirspaceInfo()
    getFlightRouteInfo()
})
</script>
<style scoped lang="scss">
.flightApplication-add {
    padding: 24rpx;
    .select-wrapper {
        position: relative;
        width: 100%;
        .select-icon {
            position: absolute;
            right: 20rpx;
            top: 50%;
            transform: translateY(-50%);
            color: #999;
            font-size: 24rpx;
            pointer-events: none;
        }
    }
    .upload {
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 15px;
        color: #1D6FE9;
    }
    :deep(.u-form-item) {
        margin-bottom: 40rpx;
        padding: 16rpx 24rpx 18rpx 24rpx;
        border-radius: 6px 6px 6px 6px;
        background: white;
        :deep(.u-line) {
            border-bottom: 1px solid #EFEFEF;
        }
        :deep(.u-input) {
            width: 100%;
            height: 80rpx;
            border-radius: 8rpx;
            padding: 0 20rpx;
            background-color: #f5f5f5;
            &::placeholder {
                font-family: Source Han Sans CN, Source Han Sans CN;
                font-weight: 400;
                font-size: 30rpx;
                color: #D2D2D2;
            }
        }
        .clickable-input {
            width: 100%;
            cursor: pointer;
        }
        :deep(.u-form-item__label) {
            margin-bottom: 20rpx;
            // font-weight: bold;
            // color: #333;
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: 400;
            font-size: 30rpx;
            color: #222324;
        }
        :deep(.u-form-item__required) {
            color: #FF2600;
            margin-right: 8rpx;
        }
    }
}
</style>
uniapps/work-wx/src/subPackages/flightApplication/index.vue
@@ -1,40 +1,44 @@
<template>
<view class="flightApplication">
    <u-grid :col="2" :border="true" class="grid" @click="gridClick">
        <u-grid-item v-for="(baseListItem,baseListIndex) in baseList" :key="baseListIndex">
            <u-image :src="baseListItem.src" :width="26" :height="26"></u-image>
            <text class="grid-text">{{baseListItem.title}}</text>
        </u-grid-item>
    </u-grid>
    <u-search :show-action="true" actionText="搜索" :animation="true"></u-search>
    <view class="title">
        审批记录
    </view>
    <view class="approvalRecord" v-for="(approvalRecord,approvalRecordIndex) in approvalRecords" :key="approvalRecordIndex">
        <view class="name-status">
            <view>{{approvalRecord.name}}</view>
            <view>{{approvalRecord.status}}</view>
    <view class="header-top">
        <view class="ht-content">
            <view class="item" @click="gridClick(0)">
                <image :src="fxsqSvg" class="icon"></image>
                <view class="txt">飞行申请</view>
            </view>
            <view class="item" @click="gridClick(1)">
                <image :src="mysbSvg" class="icon"></image>
                <view class="txt">我的设备</view>
            </view>
        </view>
        <view>飞行设备:{{approvalRecord.device}}</view>
        <view>行政区划:{{approvalRecord.area}}</view>
        <view>飞行时间:{{approvalRecord.time}}</view>
    </view>
    <u-search :bgColor="'white'" :show-action="true" actionText="搜索" :animation="true"></u-search>
    <view class="content">
        <view class="sp-title">
            审批记录
        </view>
        <view class="approvalRecord" v-for="(approvalRecord,approvalRecordIndex) in approvalRecords" :key="approvalRecordIndex">
            <view class="name-status">
                <view class="name-image">
                    <u-image :src="spSvg" class="icon" width="16" height="16"></u-image>
                    <view class="name">{{approvalRecord.flightPlanName}}</view>
                </view>
                <view class="status">{{approvalRecord.planStatus || '无状态'}}</view>
            </view>
            <view class="txt">飞行设备:{{approvalRecord.device || '无设备'}}</view>
            <view class="txt">行政区划:{{approvalRecord.area || '无行政区划'}}</view>
            <view class="txt">飞行时间:{{approvalRecord.time || '无飞行时间'}}</view>
        </view>
    </view>
</view>
</template>
<script setup>
    import lbPng from '@/static/images/lb.png'
    import spSvg from '@/static/images/sp.svg'
    import { flightPlanPageInfoApi } from '@/api/index.js'
    import fxsqSvg from '@/static/images/fly-apply.svg'
    import mysbSvg from '@/static/images/my-sb.svg'
import { ref } from 'vue'
const baseList = ref([
    {
        src: lbPng,
        title: '飞行申请',
    },
    {
        src: lbPng,
        title: '我的设备',
    },
])
function gridClick(index) {
    // 跳转设备管理 /pages/equipmentManagement/index
@@ -42,56 +46,205 @@
        uni.switchTab({
            url: '/pages/equipmentManagement/index',
        })
        return
    } else {
        uni.navigateTo({
            url: '/subPackages/flightApplication/add',
        })
    }
}
// 审批记录是很多条
const approvalRecords = ref([
    {
        name: '飞行需求名称',
        status: '申请中',
        flightPlanName: '飞行需求名称',
        planStatus: '申请中',
        device: '大疆无人机',
        area: '吉州区',
        time: '2026/01/07至2026/01/08',
    },
    {
        name: '飞行需求名称',
        status: '申请中',
        flightPlanName: '飞行需求名称',
        planStatus: '申请中',
        device: '大疆无人机',
        area: '吉州区',
        time: '2026/01/07至2026/01/08',
    },
    {
        name: '飞行需求名称',
        status: '申请中',
        flightPlanName: '飞行需求名称',
        planStatus: '申请中',
        device: '大疆无人机',
        area: '吉州区',
        time: '2026/01/07至2026/01/08',
    },
    {
        name: '飞行需求名称',
        status: '申请中',
        flightPlanName: '飞行需求名称',
        planStatus: '申请中',
        device: '大疆无人机',
        area: '吉州区',
        time: '2026/01/07至2026/01/08',
    },
    {
        flightPlanName: '飞行需求名称',
        planStatus: '申请中',
        device: '大疆无人机',
        area: '吉州区',
        time: '2026/01/07至2026/01/08',
    },
    {
        flightPlanName: '飞行需求名称',
        planStatus: '申请中',
        device: '大疆无人机',
        area: '吉州区',
        time: '2026/01/07至2026/01/08',
    },
    {
        flightPlanName: '飞行需求名称',
        planStatus: '申请中',
        device: '大疆无人机',
        area: '吉州区',
        time: '2026/01/07至2026/01/08',
    },
])
// 申请审批列表
const getApprovalRecords = async () => {
    try {
        const res = await flightPlanPageInfoApi({
            current: 1,
            size: 10,
        })
        approvalRecords.value = res.data.data.records || []
    } catch (error) {
        uni.showToast({
            title: error.message,
            icon: 'none',
            duration: 2000,
        })
    }
}
onMounted(() => {
    getApprovalRecords()
})
</script>
<style scoped>
.title {
    font-size: 32rpx;
    font-weight: bold;
    color: #1D6FE9;
    margin: 32rpx 0 24rpx 0;
}
.approvalRecord {
    font-size: 28rpx;
    color: #333333;
    margin-bottom: 24rpx;
}
.name-status {
    display: flex;
    justify-content: space-between;
<style scoped lang="scss">
.flightApplication {
    .header-top {
        width: 100%;
        height: 350rpx;
        background: url('@/static/images/fxsq-bg.png') no-repeat center center;
        background-size: 100% 100%;
        position: fixed;
        top: 0;
        .ht-content {
            position: absolute;
            bottom: -40rpx;
            width: 100%;
            height: 166rpx;
            padding: 0 40rpx;
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 60rpx;
            box-sizing: border-box;
            .item {
                flex: 1;
                max-width: 350rpx;
                height: 166rpx;
                background: rgba(251,253,255,0.39);
                box-shadow: inset 0px 0px 7px 0px rgba(64,156,230,0.14), 0px 1px 3px 0px rgba(35,49,96,0.11);
                border-radius: 8px 8px 8px 8px;
                border: 1px solid #fff;
                display: flex;
                justify-content: center;
                align-items: center;
                box-sizing: border-box;
                .icon {
                    width: 128rpx;
                    height: 128rpx;
                }
                .txt {
                    font-family: Source Han Sans CN, Source Han Sans CN;
                    font-weight: bold;
                    font-size: 16px;
                    color: #222324;
                }
            }
        }
    }
     .u-search {
        position: absolute;
        width: 90%;
        left: 50%;
        transform: translateX(-50%);
        top: 340rpx !important;
        height: 68rpx;
        flex: 0;
    }
    .content {
        position: absolute;
        top: 450rpx !important;
        bottom: 0;
        background: white;
        width: 100%;
        display: flex;
        flex-direction: column;
        background: #FFFFFF;
        padding: 0 40rpx 40rpx 40rpx;
        overflow-y: auto;
        box-sizing: border-box;
        border-radius: 12px 12px 6px 6px;
        .sp-title {
            font-weight: bold;
            font-size: 32rpx;
            color: #222324;
            padding: 40rpx 0 0rpx 0;
        }
    }
    .approvalRecord {
        font-family: Source Han Sans CN, Source Han Sans CN;
        // display: flex;
        // justify-content: space-between;
        border-bottom: 1px solid #EBEEF3;
        padding: 40rpx 0 20rpx 0;
        // margin-bottom: 20rpx;
        width: 100%;
        box-sizing: border-box;
    }
    .name-status {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 20rpx;
        .name-image {
            display: flex;
            justify-content: center;
            align-items: center;
            .u-image {
                width: 32rpx;
                height: 32rpx;
            }
            .name {
                font-weight: bold;
                font-size: 32rpx;
                color: #1D2129;
                margin-left: 6rpx;
            }
        }
        .status {
            width: 100rpx;
            text-align: center;
            line-height: 40rpx;
            background: #FF9604;
            border-radius: 2px 2px 2px 2px;
            font-weight: 500;
            font-size: 24rpx;
            color: #FFFFFF;
        }
    }
    .txt {
        font-weight: 400;
        font-size: 12px;
        color: #86909C;
        margin-bottom: 14rpx;
    }
}
</style>