| src/api/project-page/index.ts | ●●●●● patch | view | raw | blame | history | |
| src/components/cesiumMap/cesium.vue | ●●●●● patch | view | raw | blame | history | |
| src/event-bus/index.ts | ●●●●● patch | view | raw | blame | history | |
| src/pages/page-web/projects/project_list/add_page/add.vue | ●●●●● patch | view | raw | blame | history | |
| src/pages/page-web/projects/project_list/add_page/components/WeatherDrawer.vue | ●●●●● patch | view | raw | blame | history | |
| src/pages/page-web/projects/project_list/add_page/type.ts | ●●●●● patch | view | raw | blame | history | |
| src/pages/page-web/projects/project_list/list_page/components/ProjectList.vue | ●●●●● patch | view | raw | blame | history | |
| src/pages/page-web/projects/project_list/list_page/list.vue | ●●●●● patch | view | raw | blame | history | |
| src/store/index.ts | ●●●●● patch | view | raw | blame | history | |
| src/store/map.ts | ●●●●● patch | view | raw | blame | history | |
| src/styles/flex.style.scss | ●●●●● patch | view | raw | blame | history |
src/api/project-page/index.ts
@@ -55,3 +55,10 @@ const result = await request.get(url, { params: { id } }) return result.data } // 项目阻飞编辑 export const editProjectBlock = async function (params:any): Promise<IWorkspaceResponse<any>> { const url = `api/${HTTP_PREFIX}/projectBlocking/edit` const result = await request.post(url, params) return result.data } src/components/cesiumMap/cesium.vue
@@ -2,20 +2,26 @@ * @Author: 胡思旗 931347610@qq.com * @Date: 2023-08-22 17:50:30 * @LastEditors: husq 931347610@qq.com * @LastEditTime: 2023-09-01 16:48:42 * @LastEditTime: 2023-09-05 14:12:49 * @FilePath: \Cloud-API-Demo-Web\src\components\cesiumMap\cesium.vue * @Description: * * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved. --> <template> <div class="height-100 width-100 cesium" id="cesiumContainer" @click="getCoordinate"></div> <div class="height-100 width-100 cesium" id="cesiumContainer" @click="getCoordinate"></div> <div v-if="centerConfig.type && !centerConfig.latitude" class="pointLongitude">在地图上点击绘制项目中心点</div> </template> <script setup lang="ts"> import * as Cesium from 'cesium' import { onMounted, ref, onUnmounted } from 'vue' import { useMyStore } from '/@/store' const viewer: { value: Cesium.Viewer | null | undefined } = ref() const store = useMyStore() const centerConfig = computed(() => { return store.state.map.centerConfig }) const init = () => { // Cesium Token const cesiumToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhMjdmNGUxZC02YzY3LTQyZWUtOTNmYy1hNTI0MDRkZDY2ZmEiLCJpZCI6MTYxODgyLCJpYXQiOjE2OTI3NTQyNDV9.Pm7xTwPmKowPzFgJ0TsIKOtthigq86BLJX4c8M97Hhw' @@ -42,12 +48,12 @@ const TDT_Token = 'c6eea7dad4fa1e2d1e32ec0e7c9735db' // 天地图地图 const TDT_IMG_C = 'http://{s}.tianditu.gov.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0' + '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' + '&style=default&format=tiles&tk=' + TDT_Token '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' + '&style=default&format=tiles&tk=' + TDT_Token // 天地图注记 const TDT_ZJ = 'http://{s}.tianditu.gov.cn/cia_c/wmts?service=wmts&request=GetTile&version=1.0.0' + '&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' + '&style=default&format=tiles&tk=' + TDT_Token '&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' + '&style=default&format=tiles&tk=' + TDT_Token // 天地图图层加载 const imageryProvider = new Cesium.WebMapTileServiceImageryProvider({ url: TDT_IMG_C, @@ -76,9 +82,10 @@ viewer.value?.imageryLayers.addImageryProvider(annotation) } // 相机设置 const camera = () => {} const camera = () => { } // 获取地图点击坐标 const getCoordinate = () => { if (!centerConfig.value.type) return let longitude: number, latitude: number viewer.value?.screenSpaceEventHandler.setInputAction((e: any) => { const cartesian = viewer.value?.camera.pickEllipsoid(e.position, viewer.value?.scene.globe.ellipsoid) @@ -86,13 +93,17 @@ const cartographic = Cesium.Cartographic.fromCartesian(cartesian) longitude = Cesium.Math.toDegrees(cartographic.longitude) latitude = Cesium.Math.toDegrees(cartographic.latitude) const data = { longitude, latitude, } store.commit('SET_CENTER_CONFIG_LATITUDE', data) console.log(store, '设置成功') } Point(longitude, latitude) return { longitude, latitude } }, Cesium.ScreenSpaceEventType.LEFT_CLICK) } const Point = (longitude:number, latitude:number) => { const Point = (longitude: number, latitude: number) => { const entity = viewer.value?.entities.add({ position: Cesium.Cartesian3.fromDegrees(longitude, latitude), point: { @@ -118,10 +129,22 @@ </script> <style scoped lang="scss"> .cesium{ :deep(.cesium-viewer-bottom){ .cesium { :deep(.cesium-viewer-bottom) { display: none !important; } } .pointLongitude { background-color: rgba(20, 20, 20, 0.792); position: absolute; z-index: 30; bottom: 30px; color: #fff; left: 0; right: 0; margin: 0 80px; padding: 15px 0; text-align: center; font-size: 16px; } </style> src/event-bus/index.ts
@@ -9,5 +9,4 @@ }; const emitter: Emitter<Events> = mitt<Events>() export default emitter src/pages/page-web/projects/project_list/add_page/add.vue
@@ -1,19 +1,9 @@ <!-- * @Author: husq 931347610@qq.com * @Date: 2023-08-30 14:43:37 * @LastEditors: husq 931347610@qq.com * @LastEditTime: 2023-09-04 09:35:15 * @FilePath: \Cloud-API-Demo-Web\src\pages\page-web\projects\project_list\add_page\add.vue * @Description: * * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved. --> <template> <div class="project_add"> <div class="side-header"> <div class="side-option flex-display flex-align-center"> <left-outlined class="point" @click="goBack" :style="{ fontSize: '18px', marginRight: '8px' }" /> <h2 class="title point" @click="goBack">{{route.query.id ? '编辑项目' : '创建项目'}}</h2> <h2 class="title point" @click="goBack">{{ route.query.id ? '编辑项目' : '创建项目' }}</h2> </div> <div class="border-bottom"></div> </div> @@ -43,7 +33,8 @@ <p>天气阻飞设置</p> <div class="btn"> <a-button type="text" @click="openDrawer('weatherDrawer')"> <span class="button_name">{{ formState.projectBlocking.cloudBlockingConfigEnable == 1 ? <span class="button_name">{{ formState.projectBlocking && formState.projectBlocking.cloudBlockingConfigEnable == '1' ? '已开启' : '未开启' }}</span> <template #icon><right-outlined @@ -142,11 +133,11 @@ </template> </a-table> </a-form-item> <a-form-item> <a-form-item :name="FormProject.LATITUDE"> <div class="application flex-display flex-align-center flex-justify-between"> <p>项目作业中心点</p> <div> <a-button type="text"> <a-button type="text" @click="configCenter"> <span class="button_add">设置项目中心点</span> <template #icon> <AimOutlined :style="{ fontSize: '14px', color: '#2d8cf0' }" /> @@ -154,7 +145,8 @@ </a-button> </div> </div> <div class="latitude">经纬度:35.6761919°N 139.65031.6°E</div> <div class="latitude" v-if="latitude && latitude != 0"> 经纬度:{{ latitude }}°N {{ longitude }}°E</div> </a-form-item> </a-form> <WeatherDrawer v-model:show="drawerConfig.weatherDrawer" title="以下设置仅在当前项目中生效"> @@ -166,7 +158,7 @@ </div> <div class="fix-button"> <a-button @click="submit" style="width: 100%;height: 36px;justify-content: center;" class="flex-display flex-align-center" type="primary">{{route.query.id ? '编辑项目' : '创建项目'}}</a-button> class="flex-display flex-align-center" type="primary">{{ route.query.id ? '编辑项目' : '创建项目' }}</a-button> </div> </div> </template> @@ -179,21 +171,29 @@ import ComWeather from './components/WeatherDrawer.vue' import ComUser from './components/UserDrawer.vue' import { ValidateErrorEntity } from 'ant-design-vue/es/form/interface' import { message } from 'ant-design-vue' import { Form, message } from 'ant-design-vue' import { cloneDeep } from 'lodash' import { add, detail, edit as projectEdit } from '/@/api/project-page/index' import { useMyStore } from '/@/store/index' const router = useRouter() const store = useMyStore() const route = useRoute() const dataSource = ref([]) const deviceSource = ref([]) const editableData: UnwrapRef<Record<string, ProjectUser>> = reactive({}) const editDeviceData: UnwrapRef<Record<string, ProjectDevice>> = reactive({}) const longitude = computed(() => { return store.state.map.centerConfig.longitude }) const latitude = computed(() => { return store.state.map.centerConfig.latitude }) const formState = ref<FormState>({ [FormProject.PROJECT_NAME]: '', [FormProject.PROJECT_STATUS]: '', [FormProject.PROJCECT_INTRO]: '', [FormProject.LONGITUDE]: 0, [FormProject.LATITUDE]: 0, [FormProject.LONGITUDE]: null, [FormProject.LATITUDE]: null, [FormProject.USERLIST]: [], [FormProject.PROJECT_BLOCKING]: { [blocking.CLOUDBLOCKINGCONFIGENABLE]: '1', @@ -249,6 +249,8 @@ if (res.code !== 5000) return message.success('修改成功') router.go(-1) store.commit('SET_CENTER_CONFIG_TYPE', false) store.commit('SET_CENTER_CONFIG_LATITUDE', { latitude: null, longitude: null }) } // 新增项目 const addProject = async () => { @@ -256,14 +258,17 @@ if (res.code !== 5000) return message.success('保存成功') router.go(-1) store.commit('SET_CENTER_CONFIG_TYPE', false) store.commit('SET_CENTER_CONFIG_LATITUDE', { latitude: null, longitude: null }) } const goBack = () => { router.go(-1) store.commit('SET_CENTER_CONFIG_TYPE', false) store.commit('SET_CENTER_CONFIG_LATITUDE', { latitude: null, longitude: null }) } // 天气组飞侧边栏 const openDrawer = (name: string) => { for (const key in drawerConfig.value) { console.log(key) if (key === name) { drawerConfig.value[key] = true } else { @@ -273,6 +278,8 @@ } // 表单验证提交 const submit = () => { formState.value[FormProject.LATITUDE] = latitude.value formState.value[FormProject.LONGITUDE] = longitude.value projectForm.value.validate().then(async () => { if (route.query.id) { editProject() @@ -283,6 +290,12 @@ console.log(error) }) } // 设置项目中心点 const configCenter = () => { if (store.state.map.centerConfig.type === true) return store.commit('SET_CENTER_CONFIG_TYPE', true) } onMounted(() => { getDetail() }) src/pages/page-web/projects/project_list/add_page/components/WeatherDrawer.vue
@@ -3,7 +3,7 @@ <div class="option"> <div class="option-item" :style="[model.projectBlocking[blocking.CLOUDBLOCKINGCONFIGENABLE]!==1?'border:none' : '']"> <span class="mr10">云端天气组飞设置</span> <a-switch :checkedValue="'1'" :unCheckedValue="'2'" v-model:checked="model.projectBlocking[blocking.CLOUDBLOCKINGCONFIGENABLE]" /> <a-switch :checkedValue="'1'" :unCheckedValue="'2'" v-model:checked="model.projectBlocking[blocking.CLOUDBLOCKINGCONFIGENABLE]" @change="changeEdit" /> <div v-if="model.projectBlocking[blocking.CLOUDBLOCKINGCONFIGENABLE]==1"> <p class="mt10 describe">当风速或雨量大于设置值时,将对机场的飞行器进行阻飞。</p> </div> @@ -15,7 +15,7 @@ </div> <div class="option-item" v-if="model.projectBlocking[blocking.CLOUDBLOCKINGCONFIGENABLE]=='1'"> <span class="mr10">天气预报</span> <a-switch :checkedValue="'1'" :unCheckedValue="'2'" v-model:checked="model.projectBlocking[blocking.WEATHERREPORTENABLE]" /> <a-switch :checkedValue="'1'" :unCheckedValue="'2'" @change="changeEdit" v-model:checked="model.projectBlocking[blocking.WEATHERREPORTENABLE]" /> <p class="mt10 describe">天气阻飞将使用天气预报,同时也会使用机场风速计和雨量计数据。</p> </div> <div class="option-item-edit" v-if="model.projectBlocking[blocking.CLOUDBLOCKINGCONFIGENABLE]=='1'"> @@ -75,7 +75,9 @@ import { weatherRules, FormWeather, rainSelect, WeatherEnum, } from './type' import { ValidateErrorEntity } from 'ant-design-vue/es/form/interface' import Select from '/@/components/Search/Select.vue' import { editProjectBlock } from '/@/api/project-page/index' import { useVModel } from '/@/hooks/use-v-model' import { message } from 'ant-design-vue' interface FormState { [FormWeather.WINDSPEEDREPORT]: number [FormWeather.WINDSPEED]: number @@ -87,6 +89,7 @@ required: true }, }) const route = useRoute() const emit = defineEmits(['update:modelValue']) const model = useVModel(props, 'modelValue', emit) const edit = ref(false) @@ -99,14 +102,24 @@ const submit = () => { weatherFormRef.value .validate() .then(() => { .then(async () => { edit.value = false model.value.projectBlocking = { ...model.value.projectBlocking, ...FormWeatherModel.value } if (route.query.id) { const res = await editProjectBlock(model.value.projectBlocking) if (res.code !== 5000) return message.error(res.message) } }) .catch((error: ValidateErrorEntity<FormState>) => { console.log('error', error) }) } const changeEdit = async () => { if (!route.query.id) return model.value.projectBlocking = { ...model.value.projectBlocking, ...FormWeatherModel.value } const res = await editProjectBlock(model.value.projectBlocking) if (res.code !== 5000) return message.error(res.message) } const cancel = () => { FormWeatherModel.value = model.value.projectBlocking edit.value = false src/pages/page-web/projects/project_list/add_page/type.ts
@@ -36,8 +36,8 @@ [FormProject.PROJECT_NAME]: string [FormProject.PROJECT_STATUS]: string [FormProject.PROJCECT_INTRO]: string [FormProject.LONGITUDE]: number [FormProject.LATITUDE]: number [FormProject.LONGITUDE]?: number | null [FormProject.LATITUDE]?: number | null [FormProject.DEVICELIST]?: deviceList[] [FormProject.USERLIST]: number[] [FormProject.PROJECT_BLOCKING]: projectBlocking @@ -120,4 +120,7 @@ [FormProject.PROJECT_NAME]: [ { required: true, message: '请输入项目名称', trigger: 'blur' }, ], [FormProject.LATITUDE]: [ { required: true, type: 'number', message: '请设置项目中心点', trigger: 'blur' }, ], } src/pages/page-web/projects/project_list/list_page/components/ProjectList.vue
@@ -2,57 +2,59 @@ * @Author: 胡思旗 931347610@qq.com * @Date: 2023-08-28 15:23:47 * @LastEditors: husq 931347610@qq.com * @LastEditTime: 2023-09-01 17:29:16 * @LastEditTime: 2023-09-05 10:17:17 * @FilePath: \Cloud-API-Demo-Web\src\pages\page-web\projects\project_list\list_page\components\ProjectList.vue * @Description:项目列表组件 * * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved. --> <template> <div class="project-box"> <div class="project-card" v-for="item in cardList" :key="item.id"> <div class="project-left"> <div class="head mb10 flex-display flex-align-center flex-justify-between"> <div class="head-left flex-display flex-align-center"> <a-tag color="#87d068">{{ status[item.projectStatus] }}</a-tag> <span class="head-text">{{ item.projectName }}</span> </div> <div class="head-right"> <a-dropdown> <dash-outlined /> <template #overlay> <a-menu> <a-menu-item> <a @click="goEdit(item)">编辑</a> </a-menu-item> <a-menu-item> <a @click="editStatus(item)">归档</a> </a-menu-item> <a-menu-item> <a @click="deleteItem(item)">删除</a> </a-menu-item> </a-menu> </template> </a-dropdown> </div> </div> <div class="wrapper"> <div class="introduction mb10">{{ item.projectIntro || '暂无简介' }}</div> <div class="time mb5">创建时间: {{ item.createTime }}</div> <div class="manager mb5 flex-display flex-align-center"> <user-outlined /> <!-- {{item.memberList[0].userId}} --> <div class="user_name ml10">测试角色</div> </div> </div> <div class="project-box flex-common"> <a-spin :spinning="model" style="width: 100%;"> <div class="project-card" v-for="item in cardList" :key="item.id"> <div class="project-left"> <div class="head mb10 flex-display flex-align-center flex-justify-between"> <div class="head-left flex-display flex-align-center"> <a-tag color="#87d068">{{ status[item.projectStatus] }}</a-tag> <span class="head-text">{{ item.projectName }}</span> </div> <div> <div class="enter"> <export-outlined /> </div> <div class="head-right"> <a-dropdown> <dash-outlined /> <template #overlay> <a-menu> <a-menu-item> <a @click="goEdit(item)">编辑</a> </a-menu-item> <a-menu-item> <a @click="editStatus(item)">归档</a> </a-menu-item> <a-menu-item> <a @click="deleteItem(item)">删除</a> </a-menu-item> </a-menu> </template> </a-dropdown> </div> </div> <div class="wrapper"> <div class="introduction mb10">{{ item.projectIntro || '暂无简介' }}</div> <div class="time mb5">创建时间: {{ item.createTime }}</div> <div class="manager mb5 flex-display flex-align-center"> <user-outlined /> <!-- {{item.memberList[0].userId}} --> <div class="user_name ml10">测试角色</div> </div> </div> </div> </div> <div> <div class="enter"> <export-outlined /> </div> </div> </div> </a-spin> </div> </template> <script setup lang="ts"> @@ -63,16 +65,25 @@ import { del, edit } from '/@/api/project-page' import { Modal, message } from 'ant-design-vue' const router = useRouter() const emit = defineEmits(['refreshList']) const emit = defineEmits(['refreshList', 'update:modelValue']) const props = defineProps({ cardList: { type: Array as () => projectCard[], required: true, }, modelValue: [String, Number, Boolean] }) const model = computed({ get () { return props.modelValue }, set (val) { emit('update:modelValue', val) } }) const spinning = ref<boolean>(true) // 删除方法 const deleteItem = (item:projectCard) => { const deleteItem = (item: projectCard) => { Modal.confirm({ title: () => '确认删除?', icon: () => createVNode(ExclamationCircleOutlined), @@ -91,7 +102,7 @@ }) } const editStatus = (item:projectCard) => { const editStatus = (item: projectCard) => { Modal.confirm({ title: () => '确认归档?', icon: () => createVNode(ExclamationCircleOutlined), @@ -111,8 +122,7 @@ }) } const goEdit = (item:any) => { console.log(item) const goEdit = (item: any) => { router.push({ name: ERouterName.EDIT_PROJECT, query: { id: item.id } @@ -123,38 +133,46 @@ <style scoped lang="scss"> .project-box { .project-card { cursor: pointer; width: 100%; min-height: 120px; background: #232323; user-select: none; border-bottom: 1px solid #4f4f4f; display: flex; } width: 100%; height: 100%; .project-left { padding: 16px; flex: 1; width: calc(100% - 48px); box-sizing: border-box; :deep(.ant-spin-nested-loading) { width: 100%; height: 100%; } .head { .head-left { font-size: 16px; } } } .project-card { cursor: pointer; width: 100%; min-height: 120px; background: #232323; user-select: none; border-bottom: 1px solid #4f4f4f; display: flex; } .enter { background: #303030; width: 48px; display: flex; align-items: center; justify-content: center; color: #fff; height: 100%; cursor: pointer; .project-left { padding: 16px; flex: 1; width: calc(100% - 48px); box-sizing: border-box; .head { .head-left { font-size: 16px; } } } .enter { background: #303030; width: 48px; display: flex; align-items: center; justify-content: center; color: #fff; height: 100%; cursor: pointer; } } </style> src/pages/page-web/projects/project_list/list_page/list.vue
@@ -24,11 +24,7 @@ </div> </div> <div class="wrap_card"> <a-spin :spinning="spinning" :delay="delayTime"> <List @refreshList="init" :cardList="cardList" /> </a-spin> <List @refreshList="init" v-model="spinning" :cardList="cardList"></List> </div> <!-- <button @click="goDetail">列表详情</button> --> </div> @@ -46,11 +42,11 @@ const sort = ref('createTime') const searchInput = ref(false) interface paramsFaca { projectStatus:string project:string column:string sort:string projectName?:string projectStatus: string project: string column: string sort: string projectName?: string } const params = ref<paramsFaca>({ projectStatus: '', @@ -61,7 +57,6 @@ }) // ant 加载 const spinning = ref<boolean>(false) const delayTime = 500 const goDetail = () => { router.push({ name: ERouterName.WORKSPACE }) @@ -169,4 +164,5 @@ flex: 1; overflow-y: auto; } }</style> } </style> src/store/index.ts
@@ -7,6 +7,7 @@ import { WaylineFile } from '/@/types/wayline' import getter from './getters' import { DevicesCmdExecuteInfo } from '/@/types/device-cmd' import map from './map' const initStateFunc = () => ({ Layers: [ @@ -244,6 +245,7 @@ actions, modules: { getter, map }, } src/store/map.ts
@@ -1,5 +1,32 @@ const map = { state: { import { MutationTree } from 'vuex' const state = () => ({ // 项目中心点设置 centerConfig: { // true为开启在地图中获取坐标 type: false, latitude: null as number | null, longitude: null as number | null, }, // 所有项目中心点 pointList: [], }) interface longitude { longitude:number latitude: number } export type RootStateType = ReturnType<typeof state> const mutations: MutationTree<RootStateType> = { // 开启设置地图坐标标识 SET_CENTER_CONFIG_TYPE (state, type: boolean) { state.centerConfig.type = type }, // 设置经纬度 SET_CENTER_CONFIG_LATITUDE (state, data:longitude) { state.centerConfig.longitude = data.longitude state.centerConfig.latitude = data.latitude } } export default { state, mutations } src/styles/flex.style.scss
@@ -1,7 +1,11 @@ .flex-display { display: flex; } .flex-common { display: flex; align-items: center; justify-content: center; } // .border-bottom { // position: relative; // box-sizing: border-box;