src/api/http/type.ts
@@ -17,10 +17,17 @@ pagination: IPage; }; } // 接口返回参数字段 interface Field<T> { code: number data: T, message: string success: boolean } // Workspace export interface IWorkspaceResponse<T> { code: number; data: T; data: Field<T>; message: string; success:boolean; } src/api/project-page/index.ts
@@ -13,7 +13,7 @@ */ export const getPage = async function (params:any): Promise<IWorkspaceResponse<any>> { const url = `api/${HTTP_PREFIX}/project/getPage` const result = await request.get(url, {params}) const result = await request.get(url, { params }) return result.data } @@ -22,17 +22,36 @@ * @param query */ export const edit = async function (query:any): Promise<IWorkspaceResponse<any>> { const url = `api/${HTTP_PREFIX}/project/edit` const result = await request.post(url, query) return result.data const url = `api/${HTTP_PREFIX}/project/edit` const result = await request.post(url, query) return result.data } /** * 删除 * @param id */ export const del = async function (id:any):Promise<IWorkspaceResponse<any>>{ const url = `api/${HTTP_PREFIX}/project/delete` const result = await request.get(url, {params:{id}}) return result.data export const del = async function (id:any):Promise<IWorkspaceResponse<any>> { const url = `api/${HTTP_PREFIX}/project/delete` const result = await request.get(url, { params: { id } }) return result.data } /** * 新增 * */ export const add = async function (params:any):Promise<IWorkspaceResponse<any>> { const url = `api/${HTTP_PREFIX}/project/add` const result = await request.post(url, params) return result.data } /** * 详情 * */ export const detail = async function (id:any):Promise<IWorkspaceResponse<any>> { const url = `api/${HTTP_PREFIX}/project/getDetail` const result = await request.get(url, { params: { id } }) return result.data } src/components/Search/Input.vue
New file @@ -0,0 +1,29 @@ <template> <div> <a-input-search v-model:value="value" :placeholder="placeholder" @search="onSearch" /> </div> </template> <script setup lang="ts"> import { computed, defineProps, defineEmits } from 'vue' import { CaretDownOutlined } from '@ant-design/icons-vue' const emit = defineEmits(['update:modelValue', 'search']) type Option = { label: string, value: any } const props = defineProps({ modelValue: [String, Number], placeholder: { type: String, default: '搜索' } }) const value = computed({ get: () => props.modelValue, set: (val) => emit('update:modelValue', val), }) const onSearch = () => { emit('search') } </script> src/components/cesiumMap/cesium.vue
@@ -1,8 +1,8 @@ <!-- * @Author: 胡思旗 931347610@qq.com * @Date: 2023-08-22 17:50:30 * @LastEditors: 胡思旗 931347610@qq.com * @LastEditTime: 2023-08-25 10:06:16 * @LastEditors: husq 931347610@qq.com * @LastEditTime: 2023-09-01 16:48:42 * @FilePath: \Cloud-API-Demo-Web\src\components\cesiumMap\cesium.vue * @Description: * src/pages/page-web/projects/project_list/add_page/add.vue
@@ -1,9 +1,19 @@ <!-- * @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">创建项目</h2> <h2 class="title point" @click="goBack">{{route.query.id ? '编辑项目' : '创建项目'}}</h2> </div> <div class="border-bottom"></div> </div> @@ -32,8 +42,10 @@ <div class="application flex-display flex-align-center flex-justify-between"> <p>天气阻飞设置</p> <div class="btn"> <a-button type="text" @click="openWeatherDrawer"> <span class="button_name">{{formState.projectBlocking.cloudBlockingConfigEnable == 1 ? '已开启' : '未开启' }}</span> <a-button type="text" @click="openDrawer('weatherDrawer')"> <span class="button_name">{{ formState.projectBlocking.cloudBlockingConfigEnable == 1 ? '已开启' : '未开启' }}</span> <template #icon><right-outlined :style="{ fontSize: '14px', color: '#fff', marginLeft: '8px' }" /></template> </a-button> @@ -44,7 +56,7 @@ <div class="application flex-display flex-align-center flex-justify-between"> <p>项目成员</p> <div> <a-button type="text"> <a-button type="text" @click="openDrawer('userDrawer')"> <span class="button_add">添加成员</span> <template #icon><plus-outlined :style="{ fontSize: '14px', color: '#2d8cf0' }" /></template> </a-button> @@ -145,13 +157,16 @@ <div class="latitude">经纬度:35.6761919°N 139.65031.6°E</div> </a-form-item> </a-form> <WeatherDrawer v-model:show="weatherDrawer" title="以下设置仅在当前项目中生效" > <WeatherDrawer v-model:show="drawerConfig.weatherDrawer" title="以下设置仅在当前项目中生效"> <ComWeather v-model="formState" /> </WeatherDrawer> <WeatherDrawer v-model:show="drawerConfig.userDrawer" title="添加成员"> <ComUser v-model="formState" /> </WeatherDrawer> </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">创建项目</a-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> </div> </div> </template> @@ -162,28 +177,35 @@ import { UnwrapRef } from 'vue' import WeatherDrawer from '/@/components/Drawer/Drawer.vue' 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 { cloneDeep } from 'lodash' import router from '/@/router' import { add, detail, edit as projectEdit } from '/@/api/project-page/index' const router = useRouter() const route = useRoute() const dataSource = ref([]) const deviceSource = ref([]) const weatherDrawer = ref(false) const editableData: UnwrapRef<Record<string, ProjectUser>> = reactive({}) const editDeviceData: UnwrapRef<Record<string, ProjectDevice>> = reactive({}) const formState = ref<FormState>({ [FormProject.PROJECT_NAME]: 'projectName', [FormProject.PROJECT_NAME]: '', [FormProject.PROJECT_STATUS]: '', [FormProject.PROJCECT_INTRO]: '', [FormProject.LONGITUDE]: 0, [FormProject.LATITUDE]: 0, [FormProject.USERLIST]: [], [FormProject.PROJECT_BLOCKING]: { [blocking.CLOUDBLOCKINGCONFIGENABLE]: 1, [blocking.WEATHERREPORTENABLE]: 1, [blocking.CLOUDBLOCKINGCONFIGENABLE]: '1', [blocking.WEATHERREPORTENABLE]: '1', [blocking.WINDSPEED]: 12, [blocking.WINDSPEEDREPORT]: 15, [blocking.RAIN]: 3 } }) const drawerConfig = ref({ userDrawer: false, weatherDrawer: false, }) const projectForm = ref() // 表格操作方法 @@ -213,21 +235,57 @@ const del = (key: string, type: string) => { console.log(key) } // 获取项目详情 const getDetail = async () => { if (!route.query.id) return const id = route.query.id const res = await detail(id) if (res.code !== 5000) return formState.value = res.data } // 编辑项目 const editProject = async () => { const res = await projectEdit(formState.value) if (res.code !== 5000) return message.success('修改成功') router.go(-1) } // 新增项目 const addProject = async () => { const res = await add(formState.value) if (res.code !== 5000) return message.success('保存成功') router.go(-1) } const goBack = () => { router.go(-1) } // 天气组飞侧边栏 const openWeatherDrawer = () => { weatherDrawer.value = true const openDrawer = (name: string) => { for (const key in drawerConfig.value) { console.log(key) if (key === name) { drawerConfig.value[key] = true } else { drawerConfig.value[key] = false } } } // 表单验证提交 const submit = () => { projectForm.value.validate().then(() => { console.log('验证通过', formState) }).catch((error:ValidateErrorEntity<FormState>) => { projectForm.value.validate().then(async () => { if (route.query.id) { editProject() } else { addProject() } }).catch((error: ValidateErrorEntity<FormState>) => { console.log(error) }) } onMounted(() => { getDetail() }) </script> <style scoped lang="scss"> src/pages/page-web/projects/project_list/add_page/components/ComTable.vue
New file @@ -0,0 +1,78 @@ <template> <div class=""> <a-table class="ant-table-project" v-bind="$attrs" :row-selection="rowSelection" :columns="columns" :data-source="model.userList" /> </div> </template> <script setup lang="ts"> import { defineProps, defineEmits } from 'vue' import { useVModel } from '/@/hooks/use-v-model' import { ColumnProps } from 'ant-design-vue/es/table/interface' type Key = ColumnProps['key']; const props = defineProps({ modelValue: { type: [Object, Number, String], required: true }, }) const emit = defineEmits(['update:modelValue']) const model = useVModel(props, 'modelValue', emit) const columns = [ { title: '人员组织名称', dataIndex: 'userTeamName', }, { title: '成员账号', dataIndex: 'member', }, ] const selectedRowKeys = ref<Key[]>([]) const onSelectChange = (changableRowKeys: Key[]) => { console.log('selectedRowKeys changed: ', changableRowKeys) selectedRowKeys.value = changableRowKeys } const rowSelection = computed(() => { return { selectedRowKeys: unref(selectedRowKeys), onChange: onSelectChange, hideDefaultSelections: true, } }) </script> <style scoped lang="scss"> .ant-table-project :deep(.project_dark) td { background-color: #232323; color: #fff; border: none; border-bottom: 1px solid #4f4f4f; padding: 10px; } .ant-table-project :deep(.ant-table-placeholder) { background: #434343; border: none !important; } .ant-table-project :deep(.ant-table-thead) th { background: #3c3c3c; color: #fff; border: 1px solid #4f4f4f; padding: 10px; } .ant-table-project :deep(.ant-table-body) table { border: 1px solid #4f4f4f; border-right: 1px solid #4f4f4f; } .ant-table-project :deep(.ant-table-body) { background: #434343; } .ant-table-project :deep(.ant-empty-description) { color: #fff; } </style> src/pages/page-web/projects/project_list/add_page/components/UserDrawer.vue
New file @@ -0,0 +1,44 @@ <template> <div class="base"> <Input v-model="params.roleName" style="margin-bottom: 16px;" /> <ComTable v-model="model" /> </div> </template> <script setup lang="ts"> import Input from '/@/components/Search/Input.vue' import ComTable from './ComTable.vue' import { defineProps, defineEmits } from 'vue' import { useVModel } from '/@/hooks/use-v-model' const props = defineProps({ modelValue: { type: [Object, Number, String], required: true }, }) const emit = defineEmits(['update:modelValue']) const model = useVModel(props, 'modelValue', emit) const params = ref({ roleName: '' }) </script> <style scoped lang="scss"> .base { padding: 16px; :deep(.ant-input) { border: none !important; } } :deep(.ant-input) { background: #101010; border: 1px solid #444; color: #fff; } :deep(.ant-input-affix-wrapper) { background: #101010; } </style> 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]" /> <div v-if="model.projectBlocking[blocking.CLOUDBLOCKINGCONFIGENABLE]==1"> <p class="mt10 describe">当风速或雨量大于设置值时,将对机场的飞行器进行阻飞。</p> </div> @@ -13,12 +13,12 @@ <p class="mt10 describe">风速 (风速计) ≥12m/s 或 雨量 (雨量计) ≥大雨 </p> </div> </div> <div class="option-item" v-if="model.projectBlocking[blocking.CLOUDBLOCKINGCONFIGENABLE]==1"> <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'" 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"> <div class="option-item-edit" v-if="model.projectBlocking[blocking.CLOUDBLOCKINGCONFIGENABLE]=='1'"> <a-form ref="weatherFormRef" :model="FormWeatherModel" :rules="weatherRules"> <a-form-item :name="FormWeather.WINDSPEED" ref="windDevice"> <div class="edit-item flex-display flex-align-center flex-justify-between"> @@ -32,7 +32,7 @@ </div> </div> </a-form-item> <a-form-item :name="FormWeather.WINDSPEEDREPORT" v-if="model.projectBlocking.weatherReportEnable"> <a-form-item :name="FormWeather.WINDSPEEDREPORT" v-if="model.projectBlocking.weatherReportEnable==1"> <div class="edit-item flex-display flex-align-center flex-justify-between"> <div class="white-color">风速<span class="describe">(天气预报) (1-15m/s)</span></div> <div class="form-option flex-display flex-align-center white-color"> @@ -91,7 +91,11 @@ const model = useVModel(props, 'modelValue', emit) const edit = ref(false) const weatherFormRef = ref() const FormWeatherModel = ref<FormState>(cloneDeep(model.value.projectBlocking)) const FormWeatherModel = ref<FormState>(cloneDeep({ [FormWeather.WINDSPEEDREPORT]: model.value.projectBlocking[FormWeather.WINDSPEEDREPORT], [FormWeather.WINDSPEED]: model.value.projectBlocking[FormWeather.WINDSPEED], [FormWeather.RAIN]: model.value.projectBlocking[FormWeather.RAIN], })) const submit = () => { weatherFormRef.value .validate() src/pages/page-web/projects/project_list/add_page/type.ts
@@ -16,8 +16,8 @@ WEATHERREPORTENABLE = 'weatherReportEnable', } enum weather { '开启' = 1, '关闭' = 2 '开启' = '1', '关闭' = '2' } interface deviceList { nickName: string @@ -26,8 +26,8 @@ [key: string]: any } interface projectBlocking { [blocking.WEATHERREPORTENABLE]?: weather [blocking.CLOUDBLOCKINGCONFIGENABLE]: weather [blocking.WEATHERREPORTENABLE]?: string [blocking.CLOUDBLOCKINGCONFIGENABLE]: string [blocking.WINDSPEED]?: number [blocking.WINDSPEEDREPORT]?: number [blocking.RAIN]?: number src/pages/page-web/projects/project_list/list_page/components/ProjectList.vue
@@ -2,7 +2,7 @@ * @Author: 胡思旗 931347610@qq.com * @Date: 2023-08-28 15:23:47 * @LastEditors: husq 931347610@qq.com * @LastEditTime: 2023-08-30 15:30:19 * @LastEditTime: 2023-09-01 17:29:16 * @FilePath: \Cloud-API-Demo-Web\src\pages\page-web\projects\project_list\list_page\components\ProjectList.vue * @Description:项目列表组件 * @@ -23,7 +23,7 @@ <template #overlay> <a-menu> <a-menu-item> <a href="javascript:;">编辑</a> <a @click="goEdit(item)">编辑</a> </a-menu-item> <a-menu-item> <a @click="editStatus(item)">归档</a> @@ -58,10 +58,11 @@ <script setup lang="ts"> import { DashOutlined, UserOutlined, ExportOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue' import { defineEmits, defineProps, createVNode } from 'vue' import { ERouterName } from '/@/types/index' import { status, projectCard } from './data' import { del, edit } from '/@/api/project-page' import { Modal, message } from 'ant-design-vue' const router = useRouter() const emit = defineEmits(['refreshList']) const props = defineProps({ cardList: { @@ -110,6 +111,14 @@ }) } const goEdit = (item:any) => { console.log(item) router.push({ name: ERouterName.EDIT_PROJECT, query: { id: item.id } }) } </script> <style scoped lang="scss"> src/pages/page-web/projects/project_list/list_page/list.vue
@@ -3,7 +3,7 @@ <div class="side-header"> <div class="side-option flex-display flex-align-center flex-justify-between"> <h2 class="title">项目列表</h2> <PlusCircleOutlined @click="goAdd(11)" :style="{ fontSize: '20px' }" /> <PlusCircleOutlined @click="goAdd" :style="{ fontSize: '20px' }" /> </div> <div class="border-bottom"></div> </div> @@ -66,8 +66,7 @@ const goDetail = () => { router.push({ name: ERouterName.WORKSPACE }) } const goAdd = (number:number) => { console.log(number, 'number') const goAdd = () => { router.push({ name: ERouterName.ADD_PROJECT }) } const cardList = ref<projectCard[]>([]) @@ -84,10 +83,12 @@ } // 页面初始化 const init = async () => { spinning.value = !spinning.value const res = await getProjectPage(params.value) spinning.value = true const res = await getProjectPage(params.value).catch(e => { spinning.value = false }) cardList.value = res.data.records spinning.value = !spinning.value spinning.value = false } onMounted(() => { init() src/router/index.ts
@@ -50,6 +50,11 @@ name: ERouterName.ADD_PROJECT, component: () => import('/@/pages/page-web/projects/project_list/add_page/add.vue') }, { path: '/' + ERouterName.EDIT_PROJECT, name: ERouterName.EDIT_PROJECT, component: () => import('/@/pages/page-web/projects/project_list/add_page/add.vue') }, // workspace { path: '/' + ERouterName.WORKSPACE, src/store/getters.ts
New file @@ -0,0 +1,2 @@ const getters = {} export default getters src/store/index.ts
@@ -5,6 +5,7 @@ import { getLayers } from '/@/api/layer' import { LayerType } from '/@/types/mapLayer' import { WaylineFile } from '/@/types/wayline' import getter from './getters' import { DevicesCmdExecuteInfo } from '/@/types/device-cmd' const initStateFunc = () => ({ @@ -240,7 +241,10 @@ state: initStateFunc, getters, mutations, actions actions, modules: { getter, }, } const rootStore = createStore(storeOptions) src/store/map.ts
New file @@ -0,0 +1,5 @@ const map = { state: { } } src/types/enums.ts
@@ -3,6 +3,7 @@ LOGIN = 'login', PROJECT = 'project', ADD_PROJECT = 'add_project', EDIT_PROJECT = 'edit_project', PROJECT_LIST='project_list', HOME = 'home', TSA = 'tsa', yarn.lock
Diff too large