Merge branch 'master' of http://139.196.74.78:10010/r/jagzwxm/ja_web
18 files modified
9 files renamed
1 files copied
4 files deleted
9 files added
| | |
| | | import dayjs from 'dayjs' |
| | | import 'styles/common.scss' |
| | | import * as Cesium from 'cesium' |
| | | import _ from 'lodash' |
| | | |
| | | // 视频回放 |
| | | import 'video.js/dist/video-js.css' |
| | |
| | | location.reload() |
| | | } else { |
| | | if (localStorage.getItem("isReload")) { |
| | | localStorage.removeItem("isReload") |
| | | localStorage.removeItem('isReload') |
| | | } |
| | | } |
| | | |
| | | |
| | | window.$crudCommon = crudCommon |
| | | window.axios = axios |
| | | window._ = _ |
| | | const app = createApp(App) |
| | | for (const [key, component] of Object.entries(ElementPlusIconsVue)) { |
| | | app.component(key, component) |
| | |
| | | terrainLoadCallback?.() |
| | | }) |
| | | } else { |
| | | // 正则:第一位非0,第二位任意数字,后10位都是0 |
| | | /*// 正则:第一位非0,第二位任意数字,后10位都是0 |
| | | const re = /^[1-9]\d0{10}$/ |
| | | |
| | | let result = null |
| | |
| | | }).then(terrainProvider => { |
| | | this.viewer.terrainProvider = terrainProvider |
| | | terrainLoadCallback?.() |
| | | }) |
| | | })*/ |
| | | } |
| | | } catch (error) { |
| | | console.error('地形加载失败:', error) |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="titleEnum[dialogMode]" @closed="handleClosed" destroy-on-close> |
| | | <el-dialog v-model="visible" :title="titleEnum[dialogMode]" :close-on-click-modal="false"> |
| | | <div v-if="readonly"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | |
| | | const emit = defineEmits(['success']) |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = ref(false) // 弹框显隐 |
| | | const visible = defineModel() // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const userList = ref([]) // 用户列表 |
| | |
| | | formData.value = res?.data?.data ?? {} |
| | | } |
| | | |
| | | // 关闭后重置 |
| | | function handleClosed() { |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | visible.value = true |
| | | formData.value = dialogMode.value === 'add' ? initForm() : row |
| | | dialogMode.value !== 'add' && (await loadDetail()) |
| | | } |
| File was renamed from applications/drone-command/src/views/aICrudTemplate/aICrudTemplate.vue |
| | |
| | | </el-row> |
| | | </el-form> |
| | | <div> |
| | | <el-button type="primary" @click="handleAdd">新增</el-button> |
| | | <el-button type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button type="primary" @click="exportFile" :loading="exportLoading">导出</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | |
| | | <el-table-column prop="deviceSpecification" label="规格" /> |
| | | <el-table-column label="操作"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="handleView(row)" type="primary">查看</el-link> |
| | | <el-link @click="handleEdit(row)" type="warning">编辑</el-link> |
| | | <el-link @click="openForm('view', row)" type="primary">查看</el-link> |
| | | <el-link @click="openForm('edit', row)" type="warning">编辑</el-link> |
| | | <el-link @click="handleDelete(row)" type="danger">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | /> |
| | | </div> |
| | | |
| | | <FormDiaLog ref="dialogRef" @success="getList" /> |
| | | <FormDiaLog v-if="dialogVisible" v-model="dialogVisible" ref="dialogRef" @success="getList" /> |
| | | </basic-container> |
| | | </template> |
| | | |
| | |
| | | const selectedIds = ref([]) // 勾选的设备ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | | const dialogVisible = ref(null) // 弹框实例 |
| | | const dictObj = ref({ |
| | | deviceType: [], //设备类型 |
| | | deviceAtt: [], //设备属性 |
| | |
| | | queryParamsRef.value?.resetFields() |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // 查看 |
| | | function handleView(row) { |
| | | dialogRef.value?.open({ mode: 'view', row: { ...row } }) |
| | | } |
| | | |
| | | // 编辑 |
| | | function handleEdit(row) { |
| | | dialogRef.value?.open({ mode: 'edit', row: { ...row } }) |
| | | } |
| | | |
| | | // 删除 |
| | |
| | | }) |
| | | } |
| | | |
| | | // 新增 |
| | | function handleAdd() { |
| | | dialogRef.value?.open({ mode: 'add' }) |
| | | // 新增/编辑/查看 弹框 |
| | | function openForm(mode, row) { |
| | | dialogVisible.value = true |
| | | nextTick(() => { |
| | | dialogRef.value?.open({ mode, row }) |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| New file |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="titleEnum[dialogMode]"> |
| | | <div v-if="readonly"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <div>派出所名称: {{ formData.stationName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>联系人: {{ formData.contactPerson }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>位置: {{ formData.address }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>联系方式: {{ formData.contactPhone }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <el-form v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="派出所名称" prop="stationName"> |
| | | <el-input v-model="formData.stationName" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="联系人" prop="contactPerson"> |
| | | <el-input v-model="formData.contactPerson" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="联系方式" prop="contactPhone"> |
| | | <el-input v-model="formData.contactPhone" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="位置" prop="longitude"> |
| | | <el-button @click="selectLocation" style="width: 100%"> |
| | | {{ formData.longitude }}, {{ formData.longitude }}, {{ formData.address }} |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button v-if="!readonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit"> |
| | | 确定 |
| | | </el-button> |
| | | </template> |
| | | |
| | | <el-dialog v-model="visible1" title="选择位置" destroy-on-close @closed="positionClosed"> |
| | | <div class="ztzf-cesium" id="mapContainer"></div> |
| | | <template #footer> |
| | | <el-button @click="handleMapCancel">取消</el-button> |
| | | <el-button type="primary" @click="handleMapConfirm">确定</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, nextTick, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fwPoliceStationDetailApi, fwPoliceStationSubmitApi } from './precinctInfoApi' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | import { PublicCesium } from '@/utils/cesium/publicCesium' |
| | | import * as Cesium from 'cesium' |
| | | import axios from 'axios' |
| | | |
| | | const initForm = () => ({ |
| | | address: '', // 位置 |
| | | contactPerson: '', // 联系人 |
| | | contactPhone: '', // 联系方式 |
| | | stationName: '', // 派出所名称 |
| | | longitude: 0, |
| | | latitude: 0, |
| | | }) |
| | | |
| | | const emit = defineEmits(['success']) |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = defineModel() // 弹框显隐 |
| | | const visible1 = ref(false) // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const readonly = computed(() => dialogMode.value === 'view') |
| | | const titleEnum = ref({ edit: '编辑', view: '查看', add: '新增' }) |
| | | const tempLocation = ref({ longitude: null, latitude: null }) |
| | | |
| | | const rules = { |
| | | address: fieldRules(true, 50), |
| | | stationName: fieldRules(true, 50), |
| | | contactPerson: fieldRules(true, 50), |
| | | contactPhone: fieldRules(true, 0), |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | | try { |
| | | await fwPoliceStationSubmitApi(formData.value) |
| | | ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功') |
| | | visible.value = false |
| | | emit('success') |
| | | } finally { |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | if (!formData.value.id) return |
| | | const res = await fwPoliceStationDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? {} |
| | | } |
| | | |
| | | function LeftClickEvent(click) { |
| | | const pos = click.position // Cartesian2 屏幕坐标 |
| | | // 屏幕坐标 -> 椭球面坐标(不考虑地形/模型) |
| | | const cartesian3 = viewer.camera.pickEllipsoid(pos, viewer.scene.globe.ellipsoid) |
| | | if (!cartesian3) { |
| | | return { longitude: 112, latitude: 23 } |
| | | } |
| | | // 椭球面坐标 -> 经纬度 |
| | | const carto = Cesium.Cartographic.fromCartesian(cartesian3) |
| | | const longitude = Cesium.Math.toDegrees(carto.longitude) |
| | | const latitude = Cesium.Math.toDegrees(carto.latitude) |
| | | tempLocation.value = { longitude, latitude } |
| | | // 添加红点(全局仅保留一个)并渲染经纬度标签 |
| | | if (!redPointEntity) { |
| | | redPointEntity = viewer.entities.add({ |
| | | position: Cesium.Cartesian3.fromDegrees(longitude, latitude), |
| | | point: { |
| | | color: Cesium.Color.RED, |
| | | pixelSize: 10, |
| | | }, |
| | | label: { |
| | | text: `${longitude.toFixed(6)}, ${latitude.toFixed(6)}`, |
| | | fillColor: Cesium.Color.WHITE, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | outlineWidth: 2, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, |
| | | pixelOffset: new Cesium.Cartesian2(0, -12), |
| | | }, |
| | | }) |
| | | } else { |
| | | redPointEntity.position = Cesium.Cartesian3.fromDegrees(longitude, latitude) |
| | | redPointEntity.label.text = `${longitude.toFixed(6)}, ${latitude.toFixed(6)}` |
| | | } |
| | | } |
| | | |
| | | function positionClosed() { |
| | | redPointEntity = null |
| | | } |
| | | |
| | | let viewer |
| | | let redPointEntity |
| | | async function selectLocation() { |
| | | visible1.value = true |
| | | await nextTick() |
| | | const publicCesiumInstance = new PublicCesium({ |
| | | dom: 'mapContainer', |
| | | flatMode: false, |
| | | terrain: true, |
| | | layerMode: 4, |
| | | boundary: false, |
| | | }) |
| | | publicCesiumInstance.addLeftClickEvent(null, LeftClickEvent) |
| | | viewer = publicCesiumInstance.getViewer() |
| | | } |
| | | |
| | | function handleMapCancel() { |
| | | tempLocation.value = { longitude: null, latitude: null } |
| | | visible1.value = false |
| | | } |
| | | |
| | | async function getLocationName() { |
| | | const tk = import.meta.env.VITE_APP_TDT_TOKEN |
| | | const { latitude, longitude } = tempLocation.value |
| | | const http = axios.create({ withCredentials: false }) |
| | | const res = await http({ |
| | | url: `https://api.tianditu.gov.cn/geocoder?postStr={'lon':${longitude},'lat':${latitude},'ver':1}&tk=${tk}`, |
| | | method: 'get', |
| | | }) |
| | | formData.value.address = res.data.result.formatted_address |
| | | } |
| | | |
| | | function handleMapConfirm() { |
| | | if (tempLocation.value.longitude != null && tempLocation.value.latitude != null) { |
| | | formData.value.longitude = _.round(tempLocation.value.longitude, 6) |
| | | formData.value.latitude = _.round(tempLocation.value.latitude, 6) |
| | | getLocationName() |
| | | } |
| | | visible1.value = false |
| | | } |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | formData.value = dialogMode.value === 'add' ? initForm() : row |
| | | dialogMode.value !== 'add' && (await loadDetail()) |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | #mapContainer { |
| | | width: 100%; |
| | | height: 500px; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams"> |
| | | <el-row :gutter="16"> |
| | | <el-col :span="4"> |
| | | <el-form-item label="派出所名称" prop="stationName"> |
| | | <el-input v-model="searchParams.stationName" placeholder="请输入" clearable @clear="handleSearch" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-button @click="resetForm">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">新增</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | | <el-table-column prop="stationName" label="派出所名称" /> |
| | | <el-table-column prop="address" label="位置" /> |
| | | <el-table-column prop="longitude" label="经度" /> |
| | | <el-table-column prop="latitude" label="纬度" /> |
| | | <el-table-column prop="contactPerson" label="联系人" /> |
| | | <el-table-column prop="contactPhone" label="联系方式" /> |
| | | <el-table-column label="操作"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="openForm('edit', row)" type="warning">编辑</el-link> |
| | | <el-link @click="handleDelete(row)" type="danger">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div> |
| | | <el-pagination |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | </div> |
| | | |
| | | <FormDiaLog ref="dialogRef" @success="getList" v-if="dialogVisible" v-model="dialogVisible" /> |
| | | </basic-container> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { fwPoliceStationPageApi, fwPoliceStationRemoveApi } from './precinctInfoApi' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | |
| | | const initSearchParams = () => ({ |
| | | stationName: '', // 名称 |
| | | current: 1, // 当前页 |
| | | size: 10, // 每页大小 |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const selectedIds = ref([]) // 勾选的ID列表 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | | const dialogVisible = ref(false) |
| | | |
| | | // 获取列表 |
| | | async function getList() { |
| | | loading.value = true |
| | | try { |
| | | const res = await fwPoliceStationPageApi(searchParams.value) |
| | | 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() { |
| | | queryParamsRef.value?.resetFields() |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // 删除 |
| | | async function handleDelete(row) { |
| | | const tips = row ? '该条' : '选中的项' |
| | | await ElMessageBox.confirm(`确认删除${tips}吗?`, '提示', { type: 'warning' }) |
| | | const ids = row ? row.id : selectedIds.value.join(',') |
| | | await fwPoliceStationRemoveApi({ ids }) |
| | | ElMessage.success('删除成功') |
| | | selectedIds.value = [] |
| | | getList() |
| | | } |
| | | |
| | | // 勾选值设置 |
| | | function handleSelectionChange(rows) { |
| | | selectedIds.value = rows.map(item => item.id) |
| | | } |
| | | |
| | | // 新增 |
| | | function openForm(mode, row) { |
| | | dialogVisible.value = true |
| | | nextTick(() => { |
| | | dialogRef.value?.open({ mode, row }) |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | import request from '@/axios' |
| | | |
| | | // 查list |
| | | export const fwPoliceStationPageApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/area/fwPoliceStation/page`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | // 增加或更新 |
| | | export const fwPoliceStationSubmitApi = data => { |
| | | return request({ |
| | | url: `/drone-fw/area/fwPoliceStation/submit`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | //删除 |
| | | export const fwPoliceStationRemoveApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/area/fwPoliceStation/remove`, |
| | | method: 'post', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | //详情 |
| | | export const fwPoliceStationDetailApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/area/fwPoliceStation/detail`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| New file |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="titleEnum[dialogMode]" @closed="handleClosed" destroy-on-close> |
| | | <div v-if="dialogReadonly"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <div>设备名称: {{ formData.deviceName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>设备类型: {{ getDictLabel(formData.deviceType, dictObj.deviceType) }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>型号 : {{ formData.deviceModel }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>生产厂商 : {{ formData.manufacturer }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>入库时间 : {{ formData.createTime }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>来源 : {{ formData.source }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>所属部门 : {{ formData.belongDeptName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>负责人 : {{ formData.charger }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>报废时间 : {{ formData.scrapTime }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div>报废原因 : {{ formData.scrapReason }}</div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div>处置方式 : {{ formData.disposeWay }}</div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { getDictLabel } from '@ztzf/utils' |
| | | import { fwDeviceScrapDetailApi } from '@/views/basicManage/deviceStock/fwDeviceScrapApi' |
| | | |
| | | const initForm = () => ({}) |
| | | const emit = defineEmits(['success']) |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = ref(false) // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const dictObj = inject('dictObj') |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const titleEnum = ref({ edit: '编辑', view: '查看', add: '维护计划' }) |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | if (!formData.value.id) return |
| | | const res = await fwDeviceScrapDetailApi({ id: formData.value.id }) |
| | | let obj = res?.data?.data || {} |
| | | formData.value = { ...formData.value, ...obj } |
| | | } |
| | | |
| | | // 关闭后重置 |
| | | function handleClosed() { |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | visible.value = true |
| | | if (dialogMode.value === 'add') { |
| | | formData.value = initForm() |
| | | } else { |
| | | formData.value = row |
| | | await loadDetail() |
| | | } |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
copy from applications/drone-command/src/views/basicManage/maintainRecord/maintainRecord.vue
copy to applications/drone-command/src/views/basicManage/deviceScrap/index.vue
| File was copied from applications/drone-command/src/views/basicManage/maintainRecord/maintainRecord.vue |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div> |
| | | <el-button type="primary" @click="handleAdd">维护计划</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | </div> |
| | | <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | |
| | | </el-table-column> |
| | | <el-table-column prop="deviceModel" label="型号" /> |
| | | <el-table-column prop="manufacturer" label="生产厂商" /> |
| | | <el-table-column prop="createTime" label="入库时间" /> |
| | | <el-table-column prop="source" label="来源" /> |
| | | <el-table-column prop="charger" label="负责人" /> |
| | | <el-table-column prop="scrapTime" label="报废时间" /> |
| | | <el-table-column prop="scrapReason" label="报废原因" /> |
| | | <el-table-column prop="disposeWay" label="处置方式" /> |
| | | <el-table-column prop="maintainReminder" label="维护提醒" /> |
| | | <el-table-column prop="planCycleType" label="维护计划"> |
| | | <template v-slot="{ row }"> |
| | | {{ getPlanCycleLabel(row) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="handleView(row)" type="primary">查看</el-link> |
| | | <el-link @click="maintenance(row)" type="warning">维护</el-link> |
| | | <el-link @click="handleDelete(row)" type="danger">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | </template> |
| | | <script setup> |
| | | import { onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { getDictionaryByCode } from '@/api/system/dictbiz' |
| | | import { getDeptTree } from '@/api/system/dept' |
| | | import { getDictLabel } from '@ztzf/utils' |
| | | import { fwDeviceMaintainPlanPageApi, fwDeviceMaintainPlanRemoveApi } from './maintainRecordApi' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import MaintenanceDiaLog from '@/views/basicManage/maintainRecord/MaintenanceDiaLog.vue' |
| | | import { fwDeviceScrapPageApi } from '@/views/basicManage/deviceStock/fwDeviceScrapApi' |
| | | |
| | | const initSearchParams = () => ({ |
| | | deviceName: '', // 设备名称 |
| | |
| | | async function getList() { |
| | | loading.value = true |
| | | try { |
| | | const res = await fwDeviceMaintainPlanPageApi(searchParams.value) |
| | | const res = await fwDeviceScrapPageApi(searchParams.value) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | | } finally { |
| | |
| | | // 查看 |
| | | function handleView(row) { |
| | | dialogRef.value?.open({ mode: 'view', row: { ...row } }) |
| | | } |
| | | |
| | | // 维护 |
| | | function maintenance(row) { |
| | | maintenanceDialogRef.value?.open({ mode: 'edit', row: { ...row } }) |
| | | } |
| | | |
| | | // 删除 |
| | | async function handleDelete(row) { |
| | | const tips = row ? '该条' : '选中的项' |
| | | await ElMessageBox.confirm(`确认删除${tips}吗?`, '提示', { type: 'warning' }) |
| | | const ids = row ? row.id : selectedIds.value.join(',') |
| | | await fwDeviceMaintainPlanRemoveApi({ ids }) |
| | | ElMessage.success('删除成功') |
| | | selectedIds.value = [] |
| | | getList() |
| | | } |
| | | |
| | | // 勾选值设置 |
| New file |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close> |
| | | <el-form ref="formRef" :model="formData" :rules="rules" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="报废原因" prop="scrapReason"> |
| | | <el-input v-model="formData.scrapReason" maxlength="200" type="textarea" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="处置方式" prop="disposeWay"> |
| | | <el-input v-model="formData.disposeWay" maxlength="200" type="textarea" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="报废时间" prop="scrapTime"> |
| | | <el-date-picker |
| | | v-model="formData.scrapTime" |
| | | type="date" |
| | | placeholder="选择日期" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button |
| | | v-if="!dialogReadonly" |
| | | type="primary" |
| | | :loading="submitting" |
| | | :disabled="submitting" |
| | | @click="handleSubmit" |
| | | > |
| | | 确定 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | import { fwDeviceScrapSaveApi } from '@/views/basicManage/deviceStock/fwDeviceScrapApi' |
| | | |
| | | const initForm = () => ({ |
| | | deviceId: '', // 设备ID |
| | | disposeWay: '', //处置方式 |
| | | scrapReason: '', // 报废原因 |
| | | scrapTime: '', // 报废时间 |
| | | }) |
| | | const emit = defineEmits(['success']) |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = ref(false) // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const submitting = ref(false) |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const dialogTitle = computed(() => { |
| | | if (dialogMode.value === 'edit') { |
| | | return '报废' |
| | | } else if (dialogMode.value === 'view') { |
| | | return '查看' |
| | | } else { |
| | | return '新增' |
| | | } |
| | | }) |
| | | |
| | | const rules = { |
| | | scrapReason: fieldRules(true, 200), |
| | | disposeWay: fieldRules(true, 200), |
| | | scrapTime: fieldRules(true, 0), |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | | try { |
| | | await fwDeviceScrapSaveApi(formData.value) |
| | | ElMessage.success(dialogMode.value === 'add' ? '出库成功' : '更新成功') |
| | | visible.value = false |
| | | emit('success') |
| | | } finally { |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | // 关闭后重置 |
| | | function handleClosed() { |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | visible.value = true |
| | | formData.value.deviceId = row.id |
| | | } |
| | | |
| | | onMounted(() => {}) |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fwDeviceDetailApi, fwDeviceSubmitApi } from '@/views/basicManage/deviceStock/fwDevice' |
| | | import { getUserListApi } from '@/api/system/user' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | import { fwDeviceTrackSubmitApi } from '@/views/basicManage/deviceStock/fwDeviceTrackApi' |
| | |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const dialogTitle = computed(() => { |
| | | if (dialogMode.value === 'edit') { |
| | | return '编辑' |
| | | return '出库' |
| | | } else if (dialogMode.value === 'view') { |
| | | return '查看' |
| | | } else { |
| | |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | |
| | | // 关闭后重置 |
| | | function handleClosed() { |
| | |
| | | <div>用途: {{ formData.purpose }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>所属部门: {{ formData.belongDept }}</div> |
| | | <div>所属部门: {{ formData.belongDeptName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>负责人: {{ formData.charger }}</div> |
| | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fwDeviceDetailApi, fwDevicePageApi, fwDeviceSubmitApi } from '@/views/basicManage/deviceStock/fwDevice' |
| | | import { fwDeviceDetailApi, fwDeviceSubmitApi } from '@/views/basicManage/deviceStock/fwDevice' |
| | | import { getUserListApi } from '@/api/system/user' |
| | | import { fieldRules, getDictLabel } from '@ztzf/utils' |
| | | import { fwDeviceTrackPageApi } from '@/views/basicManage/deviceStock/fwDeviceTrackApi' |
| New file |
| | |
| | | import request from '@/axios' |
| | | |
| | | // 新增报废记录 |
| | | export const fwDeviceScrapSaveApi = data => { |
| | | return request({ |
| | | url: `/drone-fw/device/fwDeviceScrap/save`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | // 分页 |
| | | export const fwDeviceScrapPageApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/device/fwDeviceScrap/page`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | // 详情 |
| | | export const fwDeviceScrapDetailApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/device/fwDeviceScrap/detail`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| File was renamed from applications/drone-command/src/views/basicManage/deviceStock/deviceStock.vue |
| | |
| | | <div> |
| | | <el-button type="primary" @click="handleAdd">新增</el-button> |
| | | <el-button type="primary" @click="exportFile" :loading="exportLoading">导出</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button> |
| | | <!-- <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete()">删除</el-button>--> |
| | | </div> |
| | | <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" /> |
| | |
| | | <el-link @click="handleView(row)" type="primary">查看</el-link> |
| | | <el-link @click="handleEdit(row)" type="warning">编辑</el-link> |
| | | <el-link @click="outbound(row)" type="warning">出库</el-link> |
| | | <el-link @click="handleDelete(row)" type="danger">删除</el-link> |
| | | <el-link @click="scrap(row)" type="warning" v-if="row.status !== 3">报废</el-link> |
| | | <!-- <el-link @click="handleDelete(row)" type="danger">删除</el-link>--> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | |
| | | <FormDiaLog ref="dialogRef" @success="getList" /> |
| | | <DeviceTrackDiaLog ref="outboundDialogRef" @success="getList" /> |
| | | <DeviceScrapDiaLog ref="scrapDialogRef" @success="getList" /> |
| | | </basic-container> |
| | | </template> |
| | | |
| | |
| | | import { blobDownload, dateRangeFormat, getDictLabel } from '@ztzf/utils' |
| | | import { DEVICE_STATUS } from '@ztzf/constants' |
| | | import DeviceTrackDiaLog from '@/views/basicManage/deviceStock/DeviceTrackDiaLog.vue' |
| | | import DeviceScrapDiaLog from '@/views/basicManage/deviceStock/DeviceScrapDiaLog.vue' |
| | | |
| | | const initSearchParams = () => ({ |
| | | deviceName: '', // 设备名称 |
| | |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | | const outboundDialogRef = ref(null) // 弹框实例 |
| | | const scrapDialogRef = ref(null) // 弹框实例 |
| | | const dictObj = ref({ |
| | | deviceType: [], //设备类型 |
| | | deviceAtt: [], //设备属性 |
| | |
| | | } |
| | | |
| | | function outbound(row) { |
| | | outboundDialogRef.value?.open({ mode: 'add', row: { ...row } }) |
| | | outboundDialogRef.value?.open({ mode: 'edit', row: { ...row } }) |
| | | } |
| | | |
| | | function scrap(row) { |
| | | scrapDialogRef.value?.open({ mode: 'edit', row: { ...row } }) |
| | | } |
| | | |
| | | // 删除 |
| | |
| | | <div>生产厂商 : {{ formData.manufacturer }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>所属部门 : {{ formData.belongDept }}</div> |
| | | <div>所属部门 : {{ formData.belongDeptName }}</div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div>负责人 : {{ formData.charger }}</div> |
| | |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fieldRules, getDictLabel } from '@ztzf/utils' |
| | | import { fwDeviceMaintainPlanDetailApi, fwDeviceMaintainPlanSubmitApi, fwDevicePageApi } from './maintainRecordApi' |
| | | import { fwDeviceTrackPageApi } from '@/views/basicManage/deviceStock/fwDeviceTrackApi' |
| | | import { fwDeviceMaintainRecordPageApi } from '@/views/basicManage/maintainRecord/fwDeviceMaintainRecord' |
| | | import { |
| | | fwDeviceMaintainPlanDetailApi, |
| | | fwDeviceMaintainPlanSubmitApi, |
| | | fwDevicePageApi, |
| | | } from '@/views/basicManage/maintainRecord/maintainRecordApi' |
| | | |
| | | const initForm = () => ({ |
| | | deviceId: '', |
| | |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="维护内容" prop="maintainContent"> |
| | | <el-input v-model="formData.maintainContent" maxlength="50" placeholder="请输入" clearable /> |
| | | <el-input |
| | | v-model="formData.maintainContent" |
| | | maxlength="200" |
| | | type="textarea" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="更换部件" prop="replacePart"> |
| | | <el-input v-model="formData.replacePart" maxlength="50" placeholder="请输入" clearable /> |
| | | <el-input v-model="formData.replacePart" maxlength="200" type="textarea" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | import { fwDeviceMaintainPlanDetailApi, fwDeviceMaintainPlanSubmitApi, fwDevicePageApi } from './maintainRecordApi' |
| | | import { fwDeviceMaintainRecordSubmitApi } from '@/views/basicManage/maintainRecord/fwDeviceMaintainRecord' |
| | | import { fwDeviceMaintainPlanDetailApi } from '@/views/basicManage/maintainRecord/maintainRecordApi' |
| | | |
| | | const initForm = () => ({ |
| | | deviceId: '', |
| | |
| | | }) |
| | | |
| | | const rules = { |
| | | maintainContent: fieldRules(true, 50), |
| | | replacePart: fieldRules(true, 50), |
| | | maintainContent: fieldRules(true, 200), |
| | | replacePart: fieldRules(true, 200), |
| | | maintainTime: fieldRules(true, 0), |
| | | } |
| | | |
| | |
| | | planId: res?.data?.data?.id, |
| | | deviceId: res?.data?.data.deviceId, |
| | | } |
| | | console.log(formData.value, 66) |
| | | } |
| | | |
| | | // 关闭后重置 |
| File was renamed from applications/drone-command/src/views/basicManage/maintainRecord/maintainRecord.vue |
| | |
| | | import { getDictionaryByCode } from '@/api/system/dictbiz' |
| | | import { getDeptTree } from '@/api/system/dept' |
| | | import { getDictLabel } from '@ztzf/utils' |
| | | import { fwDeviceMaintainPlanPageApi, fwDeviceMaintainPlanRemoveApi } from './maintainRecordApi' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import MaintenanceDiaLog from '@/views/basicManage/maintainRecord/MaintenanceDiaLog.vue' |
| | | import { |
| | | fwDeviceMaintainPlanPageApi, |
| | | fwDeviceMaintainPlanRemoveApi, |
| | | } from '@/views/basicManage/maintainRecord/maintainRecordApi' |
| | | |
| | | const initSearchParams = () => ({ |
| | | deviceName: '', // 设备名称 |
| | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | formData.value = row |
| | | visible.value = true |
| | | if (dialogMode.value === 'add') { |
| | | formData.value = initForm() |
| | | } else { |
| | | formData.value = row |
| | | await loadDetail() |
| | | } |
| | | } |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close> |
| | | <div> |
| | | <div>无人机名称:{{ formData.droneName }}</div> |
| | | <div>序列号: {{ formData.serialNo }}</div> |
| | | <div>告警时间: {{ formData.alarmTime }}</div> |
| | | <div>触发原因: {{ formData.triggerType }}</div> |
| | | <div>停留时长: {{ formData.stayDuration }}</div> |
| | | <div class="bodyBox"> |
| | | <div class="leftMap ztzf-cesium" id="leftMapContainer"></div> |
| | | <div class="rightInfo"> |
| | | <div> |
| | | <div>无人机名称:{{ formData.droneName }}</div> |
| | | <div>序列号: {{ formData.serialNo }}</div> |
| | | <div>告警时间: {{ formData.alarmTime }}</div> |
| | | <div>触发原因: {{ formData.triggerType }}</div> |
| | | <div>停留时长: {{ formData.stayDuration }}</div> |
| | | </div> |
| | | <el-table :data="list"> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | | <el-table-column label="经纬度"> |
| | | <template #default="{ row }">{{ row.longitude }},{{ row.latitude }}</template> |
| | | </el-table-column> |
| | | <el-table-column prop="createTime" label="时间" /> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | <el-table :data="list"> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | | <el-table-column prop="areaCode" label="areaCode" /> |
| | | <el-table-column prop="createTime" label="createTime" /> |
| | | <el-table-column prop="latitude" label="latitude" /> |
| | | <el-table-column prop="longitude" label="longitude" /> |
| | | </el-table> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | </template> |
| | |
| | | import { computed, ref } from 'vue' |
| | | import { fwDroneFlightRecordDetailApi } from '@/views/recordManage/historyTracks/fwDroneFlightRecord' |
| | | import { fwDroneFlightRecordDetailPageApi } from '@/views/recordManage/historyTracks/flyTrajectory' |
| | | import { PublicCesium } from '@/utils/cesium/publicCesium' |
| | | import * as Cesium from 'cesium' |
| | | import { flyVisual } from '@/utils/cesium/mapUtil' |
| | | |
| | | const initForm = () => ({ |
| | | droneName: '', |
| | |
| | | const res = await fwDroneFlightRecordDetailApi({ id: formData.value.id }) |
| | | const res1 = await fwDroneFlightRecordDetailPageApi({ flightRecordId: formData.value.id }) |
| | | list.value = res1.data.data.records ?? [] |
| | | drawFlightPath() |
| | | formData.value = res?.data?.data ?? {} |
| | | } |
| | | |
| | | // 角度转c3 |
| | | function degreesToC3({ longitude, latitude, height = 0 }) { |
| | | return Cesium.Cartesian3.fromDegrees(longitude, latitude, height) |
| | | } |
| | | // 渲染航线 |
| | | function drawFlightPath() { |
| | | const positions = list.value.map(p => degreesToC3(p)) |
| | | droneLineEntity && geometricSource.entities.remove(droneLineEntity) |
| | | const color = Cesium.Color.fromCssColorString('#00D690') |
| | | droneLineEntity = geometricSource.entities.add({ |
| | | polyline: { |
| | | positions: positions, |
| | | width: 3, |
| | | material: new Cesium.PolylineOutlineMaterialProperty({ color }), |
| | | clampToGround: false, |
| | | }, |
| | | }) |
| | | viewer.flyTo(droneLineEntity) |
| | | } |
| | | |
| | | // 关闭后重置 |
| | |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | let viewer, geometricSource, droneLineEntity |
| | | function initMap() { |
| | | const publicCesiumInstance = new PublicCesium({ |
| | | dom: 'leftMapContainer', |
| | | flatMode: false, |
| | | terrain: true, |
| | | layerMode: 4, |
| | | boundary: false, |
| | | }) |
| | | viewer = publicCesiumInstance.getViewer() |
| | | geometricSource = new Cesium.CustomDataSource('geometricSource') |
| | | viewer.dataSources.add(geometricSource) |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | formData.value = row |
| | | visible.value = true |
| | | await nextTick(() => { |
| | | initMap() |
| | | }) |
| | | if (dialogMode.value === 'add') { |
| | | formData.value = initForm() |
| | | } else { |
| | | formData.value = row |
| | | await loadDetail() |
| | | } |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .bodyBox { |
| | | display: flex; |
| | | .rightInfo { |
| | | width: 50%; |
| | | height: 500px; |
| | | } |
| | | .leftMap { |
| | | width: 50%; |
| | | height: 500px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | }); |
| | | }; |
| | | |
| | | /** 发送重置密码验证码 */ |
| | | export const sendResetCode = (phone) => { |
| | | return request({ |
| | | url: `/system/verificationCode/resetCode/${phone}`, |
| | | method: 'get', |
| | | }); |
| | | }; |
| | | |
| | | /** 根据验证码重置密码 */ |
| | | export const resetPassword = (data) => { |
| | | return request({ |
| | | url: '/system/user/retrievePassword', |
| | | method: 'post', |
| | | data: data, |
| | | }); |
| | | }; |
| | | |
| | | // 微信登录接口 |
| | | export const loginByWechat = (code) => { |
| | | return request({ |
| | |
| | | <div class="voiceCallContainer" :style="{ paddingTop: topMargin + 'px' }"> |
| | | <!-- 顶部搜索栏 --> |
| | | <div class="searchBar"> |
| | | <up-search placeholder="请输入关键字搜索" v-model="defaultParam.searchKeyword" :animation="true" :show-action="false"></up-search> |
| | | <up-search placeholder="请输入关键字搜索" v-model="defaultParam.friendNickName" :animation="true" :show-action="false" @confirm="onSearch" @search="onSearch" @clear="handleClear"></up-search> |
| | | </div> |
| | | |
| | | <!-- 联系人列表 --> |
| | |
| | | |
| | | <script setup> |
| | | import { getStatusBarHeight } from '@/utils/common'; |
| | | |
| | | const topMargin = getStatusBarHeight() |
| | | import { getPhoneBookListApi } from '@/api/voiceCall/index.js' |
| | | import { onShow } from '@dcloudio/uni-app' |
| | | import defaultAvatar from '/static/images/defaultAvatar.svg' |
| | | import defaultAvatar from '/static/images/defaultAvatar.svg' |
| | | // 联系人数据 |
| | | const contacts = ref([]) |
| | | const defaultParam =ref( { |
| | | const defaultParam = ref({ |
| | | current: 1, |
| | | size: 10, |
| | | searchKeyword:'' |
| | | friendNickName: '' |
| | | }) |
| | | |
| | | // 加载状态 |
| | |
| | | // 获取通讯录 |
| | | const getPhoneBookList = () => { |
| | | if (loading.value || !hasMore.value) return |
| | | |
| | | loading.value = true |
| | | // 添加分页参数 |
| | | const params = { |
| | | current: defaultParam.value.current, |
| | | size: defaultParam.value.size, |
| | | searchKeyword: defaultParam.value.searchKeyword |
| | | friendNickName: defaultParam.value.friendNickName |
| | | } |
| | | |
| | | getPhoneBookListApi(params).then(res => { |
| | | const response = res.data.data |
| | | console.log('通讯录', response) |
| | | |
| | | if (defaultParam.value.current === 1) { |
| | | contacts.value = response.records |
| | | } else { |
| | |
| | | defaultParam.value.current++ |
| | | getPhoneBookList() |
| | | } |
| | | const onSearch = () => { |
| | | defaultParam.value.current = 1 |
| | | hasMore.value = true |
| | | getPhoneBookList() |
| | | |
| | | } |
| | | const handleClear = () => { |
| | | defaultParam.value.friendNickName = '' |
| | | defaultParam.value.current = 1 |
| | | hasMore.value = true |
| | | getPhoneBookList() |
| | | } |
| | | // 拨打电话方法 |
| | | const makeCall = (contact) => { |
| | | const contactName = contact.friendNickName || '未知联系人' |
| | |
| | | height: 60rpx; |
| | | |
| | | } |
| | | .loadingMore { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 80rpx; |
| | | font-size: 28rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | .loadingMore { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 80rpx; |
| | | font-size: 28rpx; |
| | | color: #999; |
| | | } |
| | | </style> |
| | |
| | | <view class="detailBox"> |
| | | <div class="detailCon"> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">原始密码</div> |
| | | <input type="password" v-model="passwordForm.oldPassword" placeholder="请输入" class="input-item" /> |
| | | <div class="rowTitle">账号</div> |
| | | <input type="text" v-model="passwordForm.username" placeholder="请输入账号" class="input-item" /> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">新密码</div> |
| | | <input type="password" v-model="passwordForm.newPassword" placeholder="请输入" class="input-item" /> |
| | | <div class="rowTitle">密码</div> |
| | | <input type="password" v-model="passwordForm.password" placeholder="请输入" class="input-item" /> |
| | | |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">确认密码</div> |
| | | <input type="password" v-model="passwordForm.newPassword1" placeholder="请输入" class="input-item" /> |
| | | <input type="password" v-model="passwordForm.password2" placeholder="请输入" class="input-item" /> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">验证码</div> |
| | | <div class="code-container"> |
| | | <input type="text" v-model="passwordForm.code" placeholder="请输入验证码" class="input-item code-input" /> |
| | | <u-button :disabled="countDown > 0" @click="sendVerificationCode" class="send-code-btn"> |
| | | {{ countDown > 0 ? `${countDown}s后重发` : '发送验证码' }} |
| | | </u-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </view> |
| | |
| | | useUserStore |
| | | } from "@/store/index.js"; |
| | | import md5 from "js-md5"; |
| | | import { |
| | | getUserInfo, |
| | | updateInfo, |
| | | updatePassword |
| | | } from '@/api/user/index.js'; |
| | | import { getUserInfo, |
| | | updateInfo, |
| | | updatePassword, |
| | | sendResetCode, |
| | | resetPassword |
| | | } from '@/api/user/index.js'; |
| | | const passwordIcon = { |
| | | show: 'fas fa-eye', // 显示密码时的图标 |
| | | hide: 'fas fa-eye-slash' // 隐藏密码时的图标 |
| | | } |
| | | const userStore = useUserStore(); |
| | | const passwordForm = ref({ |
| | | oldPassword: '', |
| | | newPassword: '', |
| | | newPassword1: '', |
| | | }); |
| | | const passwordForm = ref({ |
| | | username: '', |
| | | password: '', |
| | | password2: '', |
| | | code: '' |
| | | }); |
| | | const countDown = ref(0); |
| | | let timer = null; |
| | | // 校验密码不能包含中文 |
| | | const validatePasswordNoChinese = (password) => { |
| | | const chineseRegex = /[\u4e00-\u9fa5]/; |
| | |
| | | }; |
| | | const clearForm = () => { |
| | | passwordForm.value = { |
| | | oldPassword: '', |
| | | newPassword: '', |
| | | newPassword1: '', |
| | | username: '', |
| | | password: '', |
| | | password2: '', |
| | | code: '' |
| | | }; |
| | | countDown.value = 0; |
| | | if (timer) { |
| | | clearInterval(timer); |
| | | timer = null; |
| | | } |
| | | }; |
| | | const reset = () => { |
| | | clearForm(); |
| | | }; |
| | | const submit = () => { |
| | | // 原始密码校验 |
| | | if (!passwordForm.value.oldPassword) { |
| | | |
| | | // 发送验证码 |
| | | const sendVerificationCode = () => { |
| | | const { username } = passwordForm.value; |
| | | if (!username) { |
| | | uni.showToast({ |
| | | title: '请输入原始密码', |
| | | title: '请先输入账号', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | // 中文校验 |
| | | if (!validatePasswordNoChinese(passwordForm.value.newPassword)) return; |
| | | // 新密码校验 |
| | | if (!passwordForm.value.newPassword) { |
| | | |
| | | // 这里假设账号就是手机号,实际项目中可能需要验证格式 |
| | | sendResetCode(username).then(res => { |
| | | if (res.data.code === 200) { |
| | | uni.showToast({ |
| | | title: '验证码发送成功', |
| | | icon: 'success', |
| | | duration: 2000 |
| | | }); |
| | | |
| | | // 开始倒计时 |
| | | countDown.value = 60; |
| | | timer = setInterval(() => { |
| | | countDown.value--; |
| | | if (countDown.value <= 0) { |
| | | clearInterval(timer); |
| | | timer = null; |
| | | } |
| | | }, 1000); |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.data.msg || '验证码发送失败', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | uni.showToast({ |
| | | title: '网络错误,请稍后重试', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | }); |
| | | }; |
| | | const reset = () => { |
| | | clearForm(); |
| | | }; |
| | | |
| | | const submit = () => { |
| | | const { username, password, password2, code } = passwordForm.value; |
| | | |
| | | // 账号校验 |
| | | if (!username) { |
| | | uni.showToast({ |
| | | title: '请输入账号', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 新密码校验 |
| | | if (!password) { |
| | | uni.showToast({ |
| | | title: '请输入新密码', |
| | | icon: 'none', |
| | |
| | | }); |
| | | return; |
| | | } |
| | | // 确认密码校验 |
| | | if (passwordForm.value.newPassword !== passwordForm.value.newPassword1) { |
| | | |
| | | // 中文校验 |
| | | if (!validatePasswordNoChinese(password)) return; |
| | | |
| | | // 确认密码校验 |
| | | if (password !== password2) { |
| | | uni.showToast({ |
| | | title: '两次输入的新密码不一致', |
| | | icon: 'none', |
| | |
| | | return; |
| | | } |
| | | |
| | | // 验证码校验 |
| | | if (!code) { |
| | | uni.showToast({ |
| | | title: '请输入验证码', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 复杂度校验 |
| | | if (!validatePasswordStrength(passwordForm.value.newPassword)) return; |
| | | updatePassword(md5(passwordForm.value.oldPassword), |
| | | md5(passwordForm.value.newPassword), |
| | | md5(passwordForm.value.newPassword1)).then(res => { |
| | | if (!validatePasswordStrength(password)) return; |
| | | |
| | | // 调用重置密码接口 |
| | | const resetData = { |
| | | username, |
| | | // password: md5(password), |
| | | // confirmPassword: md5(password2), |
| | | password: password, |
| | | password2: password2, |
| | | code |
| | | }; |
| | | console.log('canshu',resetData) |
| | | resetPassword(resetData).then(res => { |
| | | if (res.data.code === 200) { |
| | | uni.showToast({ |
| | | title: '修改信息成功', |
| | | title: '密码修改成功', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | clearForm(); |
| | | userStore.setUserInfo(null) |
| | | userStore.setUserInfo(null); |
| | | uni.removeStorageSync('rememberedUser'); |
| | | uni.reLaunch({ |
| | | url: '/pages/login/index' |
| | | }) |
| | | |
| | | }); |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.msg, |
| | | title: res.data.msg || '密码修改失败', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | } |
| | | |
| | | }).catch(err => { |
| | | uni.showToast({ |
| | | title: '网络错误,请稍后重试', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | }); |
| | | |
| | | }; |
| | | onShow(async () => { |
| | | clearForm(); |
| | |
| | | input.input-item::placeholder { |
| | | font-size: 30rpx; |
| | | } |
| | | |
| | | .code-container { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | width: 100%; |
| | | } |
| | | |
| | | .code-input { |
| | | flex: 1; |
| | | max-width: 400rpx; |
| | | margin-right: 20rpx; |
| | | } |
| | | |
| | | .send-code-btn { |
| | | width: 200rpx; |
| | | height: 70rpx; |
| | | line-height: 70rpx; |
| | | font-size: 26rpx; |
| | | background: #f5f5f5; |
| | | color: #666; |
| | | border-radius: 8rpx; |
| | | text-align: center; |
| | | border: none; |
| | | } |
| | | |
| | | .send-code-btn:disabled { |
| | | background: #e0e0e0; |
| | | color: #999; |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | |
| | | { |
| | | "path": "airspaceInformation/index", |
| | | "style": { |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "flightApplication/add", |
| | | "style": { |
| | | "navigationBarTitleText": "飞行申请" |
| | | } |
| | | }, |
| | | { |
| | | "path": "deviceRegistration/add", |
| | | "style": { |
| | | "navigationBarTitleText": "飞行器注册" |
| | | } |
| | | }, |
| | | { |
| | | "path": "regulationsDetail/details", |
| | | "style": { |
| | | "navigationBarTitleText": "法律政策详情" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/mapWork/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图展示", |
| | |
| | | <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> |
| | |
| | | <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" @click="toRegulationsDetail(item)"> |
| | | <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: '法律法规', |
| | | }, |
| | |
| | | }, |
| | | ]) |
| | | |
| | | 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, |
| | | }) |
| | | } |
| | | } |
| | | // 跳转到法律政策详情页 |
| | | function toRegulationsDetail(item) { |
| | | uni.navigateTo({ |
| | | url: '/subPackages/regulationsDetail/details?id=' + item.noticeId+'&type=2', |
| | | }) |
| | | } |
| | | |
| | | |
| | | |
| | | 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> |
| | |
| | | :keyName="'image'" |
| | | :height="200" |
| | | :indicator="true" |
| | | @change="change" |
| | | ></u-swiper> |
| | | <u-grid :col="4" :border="false" class="grid" @click="gridClick"> |
| | | <u-grid-item v-for="(baseListItem,baseListIndex) in baseList" :key="baseListIndex"> |
| | |
| | | <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 class="content"> |
| | | <view> |
| | | <view class="title">空域信息</view> |
| | | <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" @click.stop="airspaceClick(item)"> |
| | | <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> |
| | | </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> |
| | | </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> |
| | | <view class="title">法律法规</view> |
| | | <view class="card" v-for="(item,index) in regulationsList" :key="index"> |
| | | <view class="left"> |
| | | <u-image :src="docSvg" :width="30" :height="36"></u-image> |
| | | </view> |
| | | <view class="right" @click.stop="toRegulationsDetail(item)"> |
| | | <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> |
| | | <view> |
| | | <view class="title">政策制度</view> |
| | | <view class="card" v-for="(item,index) in policyList" :key="index"> |
| | | <view class="left"> |
| | | <u-image :src="docSvg" :width="30" :height="36"></u-image> |
| | | </view> |
| | | <view class="right" @click.stop="policiesClick(item)"> |
| | | <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> |
| | | </view> |
| | |
| | | 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次 |
| | |
| | | }) |
| | | } |
| | | |
| | | const change = (index) => { |
| | | console.log('轮播图切换到第', index + 1, '张'); |
| | | } |
| | | |
| | | const click = (...args) => { |
| | | // 处理轮播图点击事件 |
| | | if (args.length >= 2) { |
| | | const [item, index] = args; |
| | | console.log('点击了轮播图第', index + 1, '张', item); |
| | | } |
| | | // 处理网格组件点击事件 |
| | | else if (args.length === 1 && typeof args[0] === 'object') { |
| | | const { index, item } = args[0]; |
| | | console.log('点击了网格第', index + 1, '项', item); |
| | | } |
| | | } |
| | | // const change = (index) => { |
| | | // console.log('轮播图切换到第', index + 1, '张'); |
| | | // } |
| | | |
| | | const baseList = ref([ |
| | | { |
| | |
| | | }, |
| | | ]); |
| | | |
| | | const tabs = ref([ |
| | | { name: '空域信息' }, |
| | | { name: '法律法规' }, |
| | | { name: '政策制度' }, |
| | | ]); |
| | | |
| | | const announcementList = ref([]); |
| | | function gridClick(index) { |
| | |
| | | current: 1, |
| | | size: 10, |
| | | }) |
| | | announcementList.value = res.data.data.records |
| | | announcementList.value = res.data.data.records.slice(0, 3).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, |
| | |
| | | } |
| | | } |
| | | |
| | | // 获取通知公告列表 |
| | | async function getSysNoticeList() { |
| | | try { |
| | | const res = await sysNoticePageInfoApi({ |
| | | current: 1, |
| | | size: 10, |
| | | noticeType: 2, |
| | | }) |
| | | if (res.code === 200) { |
| | | announcementList.value = res.data.records |
| | | // 获取通知公告列表 |
| | | const policyList = ref([]); // 政策制度 |
| | | const regulationsList = ref([]); // 法律法规 |
| | | async function getSysNoticeList(val) { |
| | | try { |
| | | const res = await sysNoticePageInfoApi({ |
| | | current: 1, |
| | | size: 10, |
| | | noticeType: val, |
| | | }) |
| | | // 只需要取前3条 公告 |
| | | if (val === 1) { |
| | | regulationsList.value = res.data.data.records.slice(0, 3).map(item => ({ |
| | | ...item, |
| | | title: item.noticeTitle, |
| | | description: item.remark, |
| | | time: item.pubDate, |
| | | num: item.num, |
| | | like: item.like, |
| | | })) |
| | | } else if (val === 2) { |
| | | policyList.value = res.data.data.records.slice(0, 3).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 airspaceClick(item) { |
| | | uni.navigateTo({ |
| | | url: '/subPackages/regulationsDetail/details?id=' + item.id, |
| | | }) |
| | | } |
| | | } |
| | | // 跳转到法律政策详情页 |
| | | function toRegulationsDetail(item) { |
| | | uni.navigateTo({ |
| | | url: '/subPackages/regulationsDetail/details?id=' + item.noticeId, |
| | | }) |
| | | } |
| | | // 跳转到政策制度详情页 |
| | | function policiesClick(item) { |
| | | uni.navigateTo({ |
| | | url: '/subPackages/regulationsDetail/details?id=' + item.noticeId, |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getFlightAirspaceList() |
| | | getSysNoticeList(2) |
| | | getSysNoticeList(1) |
| | | }) |
| | | </script> |
| | | |
| | |
| | | .page { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | .u-grid { |
| | | margin-top: 20px; |
| | | .grid-text { |
| | |
| | | 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 { |
| | | margin-top: 10px; |
| | | width: 100%; |
| | | height: 0; |
| | | flex-grow: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | background: #FFFFFF; |
| | | padding: 0 40rpx 40rpx 40rpx; |
| | | border-radius: 12px 12px 6px 6px; |
| | | overflow-y: auto; |
| | | box-sizing: border-box; |
| | | .title { |
| | | padding: 40rpx 40rpx 0rpx 20rpx; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | color: #222324; |
| | | } |
| | | } |
| | | .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; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <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="图标"> |
| | | <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> |
| | |
| | | theme: storage.get(THEME_KEY) || 'light', |
| | | deviceUpdateKey: 0, //设备刷新key |
| | | jobUpdateKey: 0, //任务刷新key |
| | | |
| | | }), |
| | | getters: { |
| | | getSystemInfo (state) { |
| New file |
| | |
| | | <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="caacRegistrationCodeText" |
| | | :borderBottom="true" |
| | | ref="item1" |
| | | > |
| | | <u-input |
| | | v-model="formParams.caacRegistrationCodeText" |
| | | border="none" |
| | | placeholder="请输入" |
| | | ></u-input> |
| | | <template #right> |
| | | <u-upload |
| | | @afterRead="afterReadFile" |
| | | @delete="deletePic" |
| | | name="6" |
| | | multiple |
| | | :maxCount="1" |
| | | > |
| | | <view class="upload">上传文件</view> |
| | | </u-upload> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item |
| | | label="飞行器照片" |
| | | labelWidth="200rpx" |
| | | prop="deviceImageText" |
| | | :borderBottom="true" |
| | | ref="item1" |
| | | > |
| | | <u-input |
| | | v-model="formParams.deviceImageText" |
| | | border="none" |
| | | placeholder="请输入" |
| | | ></u-input> |
| | | <template #right> |
| | | <u-upload |
| | | @afterRead="afterReadImage" |
| | | @delete="deletePic" |
| | | name="6" |
| | | multiple |
| | | :maxCount="1" |
| | | accept="image" |
| | | > |
| | | <view class="upload">上传图片</view> |
| | | </u-upload> |
| | | </template> |
| | | </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 |
| | | class="submit-button-wrapper" |
| | | type="primary" |
| | | size="small" |
| | | @click="submitForm" |
| | | > |
| | | 提交 |
| | | </u-button> |
| | | <!-- 飞行器型号 --> |
| | | <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" |
| | | /> |
| | | </u-form> |
| | | </view> |
| | | </template> |
| | | <script setup> |
| | | import { aircraftInfoSaveApi,uploadFileApi } 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: '', // 民用航空器登记证书 |
| | | caacRegistrationCodeText: '', // 民用航空器登记证书文本 |
| | | deviceImage: '', // 飞行器照片 |
| | | deviceImageText: '', // 飞行器照片文本 |
| | | 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 |
| | | } |
| | | // 提交文件 |
| | | function afterReadFile(event) { |
| | | // 获取上传的文件对象 |
| | | const file = event.file; |
| | | console.log('上传的文件:', file); |
| | | |
| | | // 显示加载提示 |
| | | uni.showLoading({ |
| | | title: '上传中...' |
| | | }); |
| | | |
| | | // 准备上传参数 |
| | | const uploadParams = { |
| | | name: 'file', // 服务器端接收文件的字段名 |
| | | file: file, // 传入文件对象 |
| | | filePath: file.path || file.url, // 文件路径 |
| | | }; |
| | | |
| | | // 调用上传文件接口 |
| | | uploadFileApi(uploadParams).then(res => { |
| | | uni.hideLoading(); |
| | | |
| | | console.log('上传成功结果:', res); |
| | | |
| | | // 根据接口返回的数据结构处理结果 |
| | | if (res.data && res.data.code === 200) { |
| | | // 假设接口返回的数据结构是 { url, fileName } 等 |
| | | const uploadResult = res.data.data; |
| | | |
| | | // 更新表单数据,将上传结果展示在input内 |
| | | formParams.value.caacRegistrationCodeText = uploadResult.fileName || uploadResult.url || '文件上传成功'; |
| | | |
| | | // 可以将完整的上传信息保存到表单中,以便提交时使用 |
| | | formParams.value.caacRegistrationCode= uploadResult.fileUrl || '文件上传成功'; |
| | | |
| | | 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' |
| | | }); |
| | | }); |
| | | } |
| | | // 提交图片 |
| | | function afterReadImage(event) { |
| | | // 获取上传的文件对象 |
| | | const file = event.file; |
| | | console.log('上传的文件:', file); |
| | | |
| | | // 显示加载提示 |
| | | uni.showLoading({ |
| | | title: '上传中...' |
| | | }); |
| | | |
| | | // 准备上传参数 |
| | | const uploadParams = { |
| | | name: 'file', // 服务器端接收文件的字段名 |
| | | file: file, // 传入文件对象 |
| | | filePath: file.path || file.url, // 文件路径 |
| | | }; |
| | | |
| | | // 调用上传文件接口 |
| | | uploadFileApi(uploadParams).then(res => { |
| | | uni.hideLoading(); |
| | | |
| | | console.log('上传成功结果:', res); |
| | | |
| | | // 根据接口返回的数据结构处理结果 |
| | | if (res.data && res.data.code === 200) { |
| | | // 假设接口返回的数据结构是 { url, fileName } 等 |
| | | const uploadResult = res.data.data; |
| | | |
| | | // 更新表单数据,将上传结果展示在input内 |
| | | formParams.value.deviceImageText = uploadResult.fileName || uploadResult.url || '文件上传成功'; |
| | | |
| | | // 可以将完整的上传信息保存到表单中,以便提交时使用 |
| | | formParams.value.deviceImage= uploadResult.fileUrl || '文件上传成功'; |
| | | |
| | | 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 () => { |
| | | 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 { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | // 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) { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | overflow-y: auto; |
| | | box-sizing: border-box; |
| | | padding: 24rpx; |
| | | } |
| | | |
| | | .submit-button-wrapper { |
| | | padding: 28rpx; |
| | | } |
| | | |
| | | :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> |
| New file |
| | |
| | | <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="260rpx" |
| | | prop="flightStartTime" |
| | | :borderBottom="true" |
| | | ref="item1" |
| | | @click="isShowStartTime = true" |
| | | required |
| | | > |
| | | <u-input v-model="formParams.flightStartTime" border="none" placeholder="请选择日期" suffixIcon="calendar"></u-input> |
| | | </u-form-item> |
| | | <u-form-item |
| | | label="飞行活动结束日期" |
| | | labelWidth="260rpx" |
| | | prop="flightEndTime" |
| | | :borderBottom="true" |
| | | ref="item1" |
| | | @click="isShowEndTime = true" |
| | | required |
| | | > |
| | | <u-input v-model="formParams.flightEndTime" 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.tempAirspaceApprovalText" 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 class="title form-title">飞行器/飞手</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 class="title form-title">空域/航线/场点</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="isShowFlightRouteInfo = 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 class="submit-button-wrapper" |
| | | type="primary" |
| | | size="small" |
| | | @click="submitForm" |
| | | > |
| | | 提交 |
| | | </u-button> |
| | | <!-- 飞任务类型 --> |
| | | <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" |
| | | /> |
| | | <up-datetime-picker |
| | | :show="isShowStartTime" |
| | | v-model="startTime" |
| | | mode="datetime" |
| | | @confirm="onConfirmStartTime" |
| | | @cancel="isShowStartTime = false" |
| | | ></up-datetime-picker> |
| | | <up-datetime-picker |
| | | :show="isShowEndTime" |
| | | v-model="endTime" |
| | | mode="datetime" |
| | | @confirm="onConfirmEndTime" |
| | | @cancel="isShowEndTime = false" |
| | | ></up-datetime-picker> |
| | | <!-- <u-calendar :show="isShowTimeRange" mode="date" @confirm="onConfirmTimeRange" @close="isShowTimeRange = false" :close-on-click-overlay="true"></u-calendar> --> |
| | | <!-- <u-calendar :show="isShowTimeRange" mode="range" @confirm="onConfirmTimeRange" @close="isShowTimeRange = false" :close-on-click-overlay="true" :allow-same-day="true" :show-time="true" time-format="HH:mm:ss"></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" |
| | | /> |
| | | </u-form> |
| | | |
| | | </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: '', // 临时空域批件 |
| | | tempAirspaceApprovalText: '', // 临时空域批件文本 |
| | | 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' } |
| | | ], |
| | | startTime: [ |
| | | { required: true, message: '请选择飞行活动开始时间', trigger: 'change' } |
| | | ], |
| | | endTime: [ |
| | | { 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 isShowStartTime = ref(false) |
| | | // 是否显示结束时间选择器 |
| | | const isShowEndTime = ref(false) |
| | | const startTime = ref(Date.now()); // 设置默认值为当前时间戳 |
| | | const endTime = ref(Date.now()); // 设置默认值为当前时间戳 |
| | | |
| | | const onConfirmStartTime = (e) => { |
| | | formParams.value.flightStartTime = dayjs(e.value).format('YYYY-MM-DD HH:mm:ss') |
| | | isShowStartTime.value = false |
| | | } |
| | | const onConfirmEndTime = (e) => { |
| | | formParams.value.flightEndTime = dayjs(e.value).format('YYYY-MM-DD HH:mm:ss') |
| | | isShowEndTime.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 => { |
| | | console.log(res.data.data, '0000') |
| | | flightRouteInfoList.value = res.data.data.records.map(item => ({ |
| | | label: item.name, |
| | | value: item.id, |
| | | })) |
| | | }) |
| | | } |
| | | const onPickerFlightRouteInfo = (e) => { |
| | | const selected = e.value[0] |
| | | formParams.value.routeId = selected.value |
| | | formParams.value.routeText = selected.label |
| | | isShowFlightRouteInfo.value = false |
| | | } |
| | | |
| | | // 文件上传处理 |
| | | const afterRead = (event) => { |
| | | // 获取上传的文件对象 |
| | | const file = event.file; |
| | | console.log('上传的文件:', file); |
| | | |
| | | // 显示加载提示 |
| | | uni.showLoading({ |
| | | title: '上传中...' |
| | | }); |
| | | |
| | | // 准备上传参数 |
| | | const uploadParams = { |
| | | name: 'file', // 服务器端接收文件的字段名 |
| | | file: file, // 传入文件对象 |
| | | filePath: file.path || file.url, // 文件路径 |
| | | }; |
| | | |
| | | // 调用上传文件接口 |
| | | uploadFileApi(uploadParams).then(res => { |
| | | uni.hideLoading(); |
| | | |
| | | console.log('上传成功结果:', res); |
| | | |
| | | // 根据接口返回的数据结构处理结果 |
| | | if (res.data && res.data.code === 200) { |
| | | // 假设接口返回的数据结构是 { url, fileName } 等 |
| | | const uploadResult = res.data.data; |
| | | |
| | | // 更新表单数据,将上传结果展示在input内 |
| | | formParams.value.tempAirspaceApprovalText = uploadResult.fileName || uploadResult.url || '文件上传成功'; |
| | | |
| | | // 可以将完整的上传信息保存到表单中,以便提交时使用 |
| | | formParams.value.tempAirspaceApproval = uploadResult.fileUrl || '文件上传成功'; |
| | | |
| | | 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() |
| | | |
| | | flightPlanSaveApi(formParams.value).then(res => { |
| | | if (res.data.code === 200) { |
| | | uni.showToast({ |
| | | title: '提交成功', |
| | | icon: 'success', |
| | | duration: 2000 |
| | | }) |
| | | // 跳转申请列表页 |
| | | uni.navigateTo({ |
| | | url: '/subPackages/flightApplication/index', |
| | | }) |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.msg || '提交失败', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | onMounted(() => { |
| | | getAircraftInfo() |
| | | getPilotInfo() |
| | | getAirspaceInfo() |
| | | getFlightRouteInfo() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .flightApplication-add { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | .title { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 17px; |
| | | color: #222324; |
| | | padding-left: 24rpx; |
| | | } |
| | | .form-title { |
| | | margin-bottom: 24rpx; |
| | | padding-left: 0rpx !important; |
| | | } |
| | | .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) { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | overflow-y: auto; |
| | | box-sizing: border-box; |
| | | padding: 24rpx; |
| | | } |
| | | .submit-button-wrapper { |
| | | padding: 28rpx; |
| | | } |
| | | :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> |
| | |
| | | <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 |
| | |
| | | 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> |