<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>
|
</div>
|
<div class="border-bottom"></div>
|
</div>
|
<div class="side-form-content">
|
<a-form hideRequiredMark layout="vertical" :model="formState" :rules="rules" ref="projectForm">
|
<a-form-item label="项目名称" :name="FormProject.PROJECT_NAME">
|
<a-input v-model:value="formState[FormProject.PROJECT_NAME]" placeholder="项目名称" />
|
</a-form-item>
|
<a-form-item label="平台名称" :name="FormProject.PLATFORMNAME">
|
<a-input v-model:value="formState[FormProject.PLATFORMNAME]" placeholder="平台名称" />
|
</a-form-item>
|
<a-form-item label="绑定编码" :name="FormProject.BINDCODE">
|
<a-input v-model:value="formState[FormProject.BINDCODE]" placeholder="绑定编码" />
|
</a-form-item>
|
<a-form-item label="项目简介" :name="FormProject.PROJCECT_INTRO">
|
<a-textarea :auto-size="{ minRows: 4, maxRows: 8 }" type="textarea"
|
v-model:value="formState[FormProject.PROJCECT_INTRO]" placeholder="项目简介" />
|
</a-form-item>
|
<!-- <a-form-item>
|
<div class="application flex-display flex-align-center flex-justify-between">
|
<p>申请码加入项目</p>
|
<div class="btn dis_opticy">
|
<a-button type="text" disabled>
|
<span class="button_name">未开启</span>
|
<template #icon><right-outlined
|
:style="{ fontSize: '14px', color: '#fff', marginLeft: '8px' }" /></template>
|
</a-button>
|
</div>
|
</div>
|
</a-form-item>
|
<a-form-item>
|
<div class="application flex-display flex-align-center flex-justify-between">
|
<p>天气阻飞设置</p>
|
<div class="btn">
|
<a-button type="text" @click="openDrawer('weatherDrawer')">
|
<span class="button_name">{{ formState.projectBlocking &&
|
formState.projectBlocking.cloudBlockingConfigEnable == '1' ?
|
'已开启'
|
: '未开启' }}</span>
|
<template #icon><right-outlined
|
:style="{ fontSize: '14px', color: '#fff', marginLeft: '8px' }" /></template>
|
</a-button>
|
</div>
|
</div>
|
</a-form-item>
|
<a-form-item>
|
<div class="application flex-display flex-align-center flex-justify-between">
|
<p>项目成员</p>
|
<div>
|
<a-button type="text" @click="openDrawer('userDrawer')">
|
<span class="button_add">添加成员</span>
|
<template #icon><plus-outlined :style="{ fontSize: '14px', color: '#2d8cf0' }" /></template>
|
</a-button>
|
</div>
|
</div>
|
<a-table class="ant-table-project" :columns="Usercolumns" :data-source="dataSource" bordered
|
:pagination="false" :rowClassName="() => 'project_dark'">
|
<template v-for="col in ['name', 'role', 'edit']" #[col]="{ text, record }" :key="col">
|
<div>
|
<a-input v-if="editableData[record.key]" v-model:value="editableData[record.key][col]"
|
style="margin: -5px 0" />
|
<template v-else>
|
{{ text }}
|
</template>
|
</div>
|
</template>
|
<template #operation="{ record }">
|
<div class="editable-row-operations">
|
<span v-if="editableData[record.key]">
|
<div class="flex-display flex-align-center flex-justify-between">
|
<CheckOutlined :style="{ fontSize: '14px', color: '#28d445' }"
|
@click="save(record.key, 'editableData')" />
|
<a-popconfirm title="确定取消?" ok-text="确定" cancel-text="取消"
|
@confirm="cancel(record.key, 'editableData')">
|
<CloseOutlined :style="{ fontSize: '14px', color: '#e70102' }" />
|
</a-popconfirm>
|
</div>
|
</span>
|
<span v-else>
|
<div class="flex-display flex-align-center flex-justify-between">
|
<EditOutlined :style="{ fontSize: '14px', color: '#1180ff' }"
|
@click="edit(record.key, 'editableData')" />
|
<DeleteOutlined :style="{ fontSize: '14px', color: '#e70102' }"
|
@click="del(record.key, 'editableData')" />
|
</div>
|
</span>
|
</div>
|
</template>
|
</a-table>
|
</a-form-item>
|
<a-form-item>
|
<div class="application flex-display flex-align-center flex-justify-between">
|
<p>项目设备</p>
|
<div>
|
<a-button type="text">
|
<span class="button_add">添加飞行器</span>
|
<template #icon><plus-outlined :style="{ fontSize: '14px', color: '#2d8cf0' }" /></template>
|
</a-button>
|
</div>
|
</div>
|
<a-table class="ant-table-project" :columns="Devicecolumns" :data-source="deviceSource" bordered
|
:pagination="false" :rowClassName="() => 'project_dark'">
|
<template v-for="col in ['name', 'role', 'edit']" #[col]="{ text, record }" :key="col">
|
<div>
|
<a-input v-if="editDeviceData[record.key]" v-model:value="editDeviceData[record.key][col]"
|
style="margin: -5px 0" />
|
<template v-else>
|
{{ text }}
|
</template>
|
</div>
|
</template>
|
<template #operation="{ record }">
|
<div class="editable-row-operations">
|
<span v-if="editDeviceData[record.key]">
|
<div class="flex-display flex-align-center flex-justify-between">
|
<CheckOutlined :style="{ fontSize: '14px', color: '#28d445' }"
|
@click="save(record.key, 'editDeviceData')" />
|
<a-popconfirm title="确定取消?" ok-text="确定" cancel-text="取消"
|
@confirm="cancel(record.key, 'editDeviceData')">
|
<CloseOutlined :style="{ fontSize: '14px', color: '#e70102' }" />
|
</a-popconfirm>
|
</div>
|
</span>
|
<span v-else>
|
<div class="flex-display flex-align-center flex-justify-between">
|
<EditOutlined :style="{ fontSize: '14px', color: '#1180ff' }"
|
@click="edit(record.key, 'editDeviceData')" />
|
<DeleteOutlined :style="{ fontSize: '14px', color: '#e70102' }"
|
@click="del(record.key, 'editDeviceData')" />
|
</div>
|
</span>
|
</div>
|
</template>
|
</a-table>
|
</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" @click="configCenter">
|
<span class="button_add">设置项目中心点</span>
|
<template #icon>
|
<AimOutlined :style="{ fontSize: '14px', color: '#2d8cf0' }" />
|
</template>
|
</a-button>
|
</div>
|
</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="以下设置仅在当前项目中生效">
|
<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">{{ route.query.id ? '编辑项目' : '创建项目' }}</a-button>
|
</div>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import { LeftOutlined, RightOutlined, PlusOutlined, EditOutlined, DeleteOutlined, CheckOutlined, CloseOutlined, AimOutlined } from '@ant-design/icons-vue'
|
import { FormState, FormProject, Usercolumns, ProjectUser, Devicecolumns, ProjectDevice, rules, blocking } from './type'
|
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 { Form, message } from 'ant-design-vue'
|
import { cloneDeep } from 'lodash'
|
import { add, detail, edit as projectEdit } from '/@/api/project-page/index'
|
import { getPlatformInfo, editPlatformInfo, addPlatformInfo } from '/@/api/manage'
|
import { addPoint } from '/@/hooks/use-center-point'
|
import { useMyStore } from '/@/store/index'
|
const { appContext } = getCurrentInstance()
|
const global = appContext.config.globalProperties
|
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.BINDCODE]: '',
|
[FormProject.PROJCECT_INTRO]: '',
|
[FormProject.PLATFORMNAME]: '',
|
})
|
const drawerConfig = ref({
|
userDrawer: false,
|
weatherDrawer: false,
|
})
|
const projectForm = ref()
|
// 表格操作方法
|
const edit = (key: string, type: string) => {
|
if (type === 'editableData') {
|
editableData[key] = cloneDeep(dataSource.value.filter(item => key === item.key)[0])
|
} else {
|
editDeviceData[key] = cloneDeep(deviceSource.value.filter(item => key === item.key)[0])
|
}
|
}
|
const save = (key: string, type: string) => {
|
if (type === 'editableData') {
|
Object.assign(dataSource.value.filter(item => key === item.key)[0], editableData[key])
|
delete editableData[key]
|
} else {
|
Object.assign(deviceSource.value.filter(item => key === item.key)[0], editDeviceData[key])
|
delete editDeviceData[key]
|
}
|
}
|
const cancel = (key: string, type: string) => {
|
if (type === 'editableData') {
|
delete editableData[key]
|
} else {
|
delete editDeviceData[key]
|
}
|
}
|
const del = (key: string, type: string) => {
|
console.log(key)
|
}
|
// 获取项目详情
|
const getDetail = async () => {
|
if (!route.query.id) return
|
const res = await getPlatformInfo()
|
console.log(res, '项目详情')
|
if (res.code !== 0) return
|
formState.value = res.data
|
// addPoint(global.$viewer, res.data.id, res.data.latitude, res.data.latitude)
|
// store.commit('SET_CENTER_CONFIG_LATITUDE', { latitude: formState.value.latitude, longitude: formState.value.longitude })
|
}
|
// 编辑项目
|
const editProject = async () => {
|
const res = await editPlatformInfo(formState.value)
|
if (res.code !== 0) 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 () => {
|
const res = await addPlatformInfo(formState.value)
|
if (res.code !== 0) 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) {
|
if (key === name) {
|
drawerConfig.value[key] = true
|
} else {
|
drawerConfig.value[key] = false
|
}
|
}
|
}
|
// 表单验证提交
|
const submit = () => {
|
projectForm.value.validate().then(async () => {
|
if (route.query.id) {
|
editProject()
|
} else {
|
addProject()
|
}
|
}).catch((error: ValidateErrorEntity<FormState>) => {
|
console.log(error)
|
})
|
}
|
|
// 设置项目中心点
|
const configCenter = () => {
|
if (store.state.map.centerConfig.type === true) return
|
store.commit('SET_CENTER_CONFIG_TYPE', true)
|
}
|
onMounted(() => {
|
getDetail()
|
})
|
</script>
|
|
<style scoped lang="scss">
|
.project_add {
|
display: flex;
|
flex-direction: column;
|
height: 100%;
|
color: #fff;
|
position: relative;
|
background-color: #232323;
|
|
.side-header {
|
height: 60px;
|
font-size: 16px;
|
line-height: 60px;
|
box-sizing: border-box;
|
background-color: #232323;
|
border-bottom: 1px solid #4f4f4f;
|
|
.side-option {
|
padding: 0 16px;
|
|
.title {
|
color: $text-white-basic;
|
font-size: 18px;
|
margin: 0;
|
font-weight: 700;
|
}
|
}
|
}
|
|
.side-form-content {
|
padding: 16px;
|
flex: 1;
|
overflow-y: auto;
|
|
.application {
|
color: #fff;
|
|
>p {
|
margin: 0;
|
}
|
|
.btn {
|
:deep(.ant-btn-text) {
|
display: flex;
|
align-items: center;
|
flex-direction: row-reverse;
|
}
|
|
.button_name {
|
color: #fff;
|
}
|
}
|
|
.button_add {
|
color: $primary;
|
margin: 0;
|
}
|
}
|
|
.latitude {
|
margin-top: 8px;
|
font-size: 12px;
|
line-height: 20px;
|
color: hsla(0, 0%, 100%, .45);
|
}
|
|
.ant-table-project :deep(.project_dark) td {
|
background-color: #232323 !important;
|
color: #fff !important;
|
border: none !important;
|
border-bottom: 1px solid #4f4f4f;
|
padding: 10px;
|
}
|
|
.ant-table-project :deep(.ant-table-placeholder) {
|
background: #434343 !important;
|
border: none !important;
|
}
|
|
.ant-table-project :deep(.ant-table-thead) th {
|
background: #3c3c3c !important;
|
color: #fff !important;
|
border: 1px solid #4f4f4f !important;
|
padding: 10px;
|
}
|
|
.ant-table-project :deep(.ant-table-body) table {
|
border: 1px solid #4f4f4f !important;
|
border-right: 1px solid #4f4f4f !important;
|
}
|
|
.ant-table-project :deep(.ant-table-body) {
|
background: #434343 !important;
|
}
|
|
.ant-table-project :deep(.ant-empty-description) {
|
color: #fff !important;
|
}
|
}
|
|
.fix-button {
|
position: sticky;
|
bottom: 0;
|
width: 100%;
|
padding: 16px;
|
border-top: 1px solid #4f4f4f;
|
}
|
|
:deep(.ant-form-item-label > label) {
|
color: #fff;
|
}
|
|
:deep(.ant-form-item) {
|
margin-bottom: 16px;
|
}
|
|
:deep(.ant-input) {
|
background: #101010;
|
border: 1px solid #444;
|
color: #fff;
|
}
|
|
:deep(.ant-input-affix-wrapper) {
|
background: #101010;
|
}
|
}
|
</style>
|