You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

880 lines
28 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<a-modal
class="insert-shp-modal"
width="1290px"
:destroyOnClose="true"
v-model:open="props.openModal"
@cancel="closeModal"
>
<template #closeIcon>
<CloseCircleOutlined />
</template>
<div class="container">
<div class="title"></div>
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane :key="1" tab="文件上传创建">
<div class="content">
<a-steps
class="steps"
:current="current"
label-placement="vertical"
:items="[{ title: '选择文件' }, { title: '编辑信息' }, { title: '完成' }]"
></a-steps>
<div class="select-file-div" v-show="current === 0">
<div class="upload-div">
<a-upload-dragger
style="height: 174px; width: 174px"
class="upload-dragger"
v-model:fileList="fileList"
name="file"
:multiple="false"
:maxCount="1"
:before-upload="beforeUpload"
accept=".zip,.xlsx"
>
<p class="ant-upload-drag-icon">
<inbox-outlined></inbox-outlined>
</p>
<div style="opacity: 0.7">
<a-button :icon="h(PlusOutlined)">文件上传</a-button>
</div>
</a-upload-dragger>
</div>
<div class="upload-span">
<div class="upload-span-content">
<div style="opacity: 0.7">将文件拖拽到这里或点击上传按钮</div>
<div style="color: #1e5eff">支持扩展名zip,xlsx</div>
<div style="opacity: 0.7">zip中需要包含 .shp .shx .dbf 文件 且.shp文件大小小于10MB</div>
</div>
</div>
<div class="upload-form">
<a-form
ref="formRef"
:model="uploadFrom"
:label-col="{ style: { width: '75px' } }"
labelAlign="right"
:rules="uploadFormRules"
>
<a-form-item label="服务名称" name="serverName">
<a-input v-model:value="uploadFrom.serverName" placeholder="请输入服务名称" />
</a-form-item>
<!-- 显示条件文件类型为Excel时 -->
<a-form-item label="线索数据" name="hasFeature" v-if="!isShp">
<a-select v-model:value="uploadFrom.hasFeature" placeholder="请选择是否具有线索数据">
<a-select-option value="1">是</a-select-option>
<a-select-option value="0">否</a-select-option>
</a-select>
</a-form-item>
<!-- 显示条件文件类型为shp 或者 类型为Excel时有线索数据 -->
<a-form-item label="空间参考" name="spaceType" v-if="isShp || (!isShp && uploadFrom.hasFeature == '1')">
<a-select v-model:value="uploadFrom.spaceType" placeholder="请选择空间参考">
<a-select-option value="EPSG:4326">EPSG:4326</a-select-option>
<a-select-option value="3857">EPSG:3857</a-select-option>
<a-select-option value="900913">EPSG:900913</a-select-option>
</a-select>
</a-form-item>
<!-- 显示条件文件类型为Excel有线索时 -->
<a-form-item label="数据类型" name="spaceType" v-if="!isShp && uploadFrom.hasFeature == '1'">
<a-select v-model:value="uploadFrom.layerType" placeholder="请选择数据类型">
<a-select-option value="point">点</a-select-option>
<a-select-option value="linestring">线</a-select-option>
<a-select-option value="polygon">面</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="数据表名" name="tableName">
<a-row :gutter="12">
<a-col :span="20">
<a-input v-model:value="uploadFrom.tableName" placeholder="请输入表名" />
</a-col>
<a-col :span="4">
<a-button type="" :icon="h(PlusOutlined)" @click="handlerGetExistsTableList()" />
</a-col>
</a-row>
</a-form-item>
</a-form>
<div class="upload-span-button">
<a-button type="primary" :icon="h(CloudUploadOutlined)" @click="submitShp">上传</a-button>
</div>
</div>
</div>
<div class="edit-info-div" v-show="current === 1">
<a-table
:columns="tablecolumns"
:data-source="dataList"
:pagination="false"
:bordered="true"
:scroll="{ y: 260 }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'type'">
<a-select v-model:value="record.type" style="width: 120px">
<a-select-option value="geometry">geometry</a-select-option>
<a-select-option value="varchar">varchar</a-select-option>
<a-select-option value="text">text</a-select-option>
</a-select>
</template>
<template v-if="column.key === 'length'">
<a-input v-model:value="record.length" />
</template>
<template v-if="column.key === 'refName'">
<a-input v-model:value="record.refName" />
</template>
<template v-if="column.key === 'initName'">
<a-input v-model:value="record.initName" />
</template>
<template v-if="column.key === 'operation'">
<a-button shape="round" :icon="h(DeleteOutlined)" @click="deleteListItem(record)">
删除
</a-button>
</template>
</template>
</a-table>
<div class="insert-list-button" @click="insertListItem">新增一条</div>
<div class="footer-button">
<a-button @click="current--">取消</a-button>
<a-button style="margin-left: 25px" type="primary" @click="submitDataList"
>下一步</a-button
>
</div>
</div>
<div class="submit-success" v-show="current === 2">
<div class="success-content">
<CheckCircleOutlined style="font-size: 100px; color: #1fd286; margin-bottom: 30px" />
<div style="margin-bottom: 19px; font-size: 26px">导入成功</div>
<div><a-button type="primary">查看数据</a-button></div>
</div>
</div>
<!-- 已有数据表 -->
<div class="exist-table-list" v-if="showExistTableList">
</div>
</div>
</a-tab-pane>
<a-tab-pane :key="2" tab="数据库表创建">
<a-row :gutter="50">
<a-col :span="10">
<div class="layer-icon">
<BlockOutlined />
</div>
</a-col>
<a-col :span="2">
</a-col>
<a-col :span="10">
<div class="upload-form-by-database">
<a-form
ref="formRef"
:model="uploadFrom"
:label-col="{ style: { width: '75px' } }"
labelAlign="right"
:rules="uploadFormRules"
>
<a-form-item label="服务名称" name="name">
<a-input v-model:value="uploadFrom.name" placeholder="请输入服务名称" />
</a-form-item>
<a-form-item label="服务描述" name="description">
<a-input v-model:value="uploadFrom.description" placeholder="请输入服务名称" />
</a-form-item>
<!-- 显示条件文件类型为shp 或者 类型为Excel时有线索数据 -->
<a-form-item label="空间参考" name="srid" >
<a-select v-model:value="uploadFrom.srid" placeholder="请选择空间参考">
<a-select-option value="EPSG:4326">EPSG:4326</a-select-option>
<a-select-option value="3857">EPSG:3857</a-select-option>
<a-select-option value="900913">EPSG:900913</a-select-option>
</a-select>
</a-form-item>
<!-- 显示条件文件类型为Excel有线索时 -->
<a-form-item label="数据类型" name="vectorType" >
<a-select v-model:value="uploadFrom.vectorType" placeholder="请选择数据类型">
<a-select-option value="point">点</a-select-option>
<a-select-option value="linestring">线</a-select-option>
<a-select-option value="面">面</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="图层数据" name="relationTable">
<a-input v-model:value="uploadFrom.relationTable">
<template #addonAfter >
<PlusOutlined @click="handlerGetExistsTableList('relationTable')" />
</template>
</a-input>
</a-form-item>
<a-form-item label="属性数据">
<a-input v-model:value="uploadFrom.attributeTable" @change="handlerGetAttributeFields">
<template #addonAfter >
<PlusOutlined @click="handlerGetExistsTableList('attributeTable')" />
</template>
</a-input>
</a-form-item>
<a-form-item label="查询字段" >
<a-select v-model:value="uploadFrom.attributeField" placeholder="请选择数据类型">
<a-select-option v-for="(item,index) in filedOptions" :key="index" :value="item.dbColumnName">{{item.dbColumnName}}({{item.description}})</a-select-option>
</a-select>
</a-form-item>
</a-form>
<div class="upload-span-button">
<a-button type="primary" :icon="h(CloudUploadOutlined)" @click="submitTable">发布服务</a-button>
</div>
</div>
</a-col>
<a-col :span="2"></a-col>
</a-row>
</a-tab-pane>
<!-- 影像图层 -->
<a-tab-pane :key="3" tab="影像图层服务">
<a-row :gutter="50">
<a-col :span="10">
<div class="layer-icon">
<BlockOutlined />
</div>
</a-col>
<a-col :span="2">
</a-col>
<a-col :span="10">
<div class="upload-form-by-database">
<a-form
ref="formRef"
:model="uploadFrom"
:label-col="{ style: { width: '75px' } }"
labelAlign="right"
:rules="uploadFormRules"
>
<a-form-item label="服务名称" name="name">
<a-input v-model:value="uploadFrom.name" placeholder="请输入服务名称" />
</a-form-item>
<a-form-item label="服务描述" name="description">
<a-input v-model:value="uploadFrom.description" placeholder="请输入服务名称" />
</a-form-item>
<a-form-item label="服务地址" >
<a-input v-model:value="imageServerUrl" placeholder="请输入服务名称" />
</a-form-item>
<a-form-item label="服务图片" name="description">
<a-upload
name="files"
list-type="picture-card"
class="avatar-uploader"
:show-upload-list="false"
:before-upload="beforeImageUpload"
@change="handleChange"
:custom-request="handlerCustomRequest"
>
<img style="width:100px;height:100px;" v-if="uploadFrom.image" :src="VITE_GLOB_API_URL_VAR+uploadFrom.image" alt="avatar" />
<div v-else>
<loading-outlined v-if="loading"></loading-outlined>
<plus-outlined v-else></plus-outlined>
<div class="ant-upload-text">上传图片</div>
</div>
</a-upload>
</a-form-item>
</a-form>
<div class="upload-span-button">
<a-button type="primary" :icon="h(CloudUploadOutlined)" @click="handlerGrenerateImageLayer">发布服务</a-button>
</div>
</div>
</a-col>
<a-col :span="2"></a-col>
</a-row>
</a-tab-pane>
</a-tabs>
</div>
<a-modal :open="openSelectTable" title="请选择数据表" @cancel="handlerCancleSelectTable" @ok="handlerSelectTable" width="1000px" :searchInfo="searchInfo">
<BasicTable @register="registerImportTable" />
</a-modal>
</a-modal>
</template>
<script setup lang="ts">
import { defineEmits, defineProps, ref, h, reactive, onUnmounted, toRaw } from 'vue';
import { generateUUID } from '../src/tool'
import {
CloseCircleOutlined,
PlusOutlined,
DeleteOutlined,
CheckCircleOutlined,
BlockOutlined
} from '@ant-design/icons-vue';
import './index.scss';
import { InboxOutlined,CloudUploadOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import type { UploadChangeParam } from 'ant-design-vue';
import type { UploadProps } from 'ant-design-vue';
import { useModal } from '@/components/Modal';
import { BasicTable, useTable } from '@/components/Table';
import { BasicColumn, FormSchema } from '@/components/Table';
import axios from 'axios';
import { v4 as uuidv4 } from 'uuid';
import { FILETYPE } from '../util'
import {ObjectToUrl} from '../src/tool'
import { addLayer } from '@/api/sys/layerManagement'
import { getOutKeyList } from '@/api/formdesign/index';
import { getAppEnvConfig } from '@/utils/env';
const { VITE_GLOB_API_URL } = getAppEnvConfig();
const VITE_GLOB_API_URL_VAR = ref<String>(VITE_GLOB_API_URL+"/");
const imageServerUrl = ref<String>("")
const filedOptions = ref([])
const searchInfo = ref({
code:"hcsystemdb"
})
import {
getDataBaseTableList,
getImportBaseTableList,
importDataBaseTable,
} from '@/api/formdesign/index';
const openSelectTable = ref<boolean>(false);
const openSelectAttributeTable = ref<boolean>(false);
const columns = reactive([
{
title: '数据表名称',
dataIndex: 'tablename',
key: 'tablename',
},{
title: '选择数据表',
dataIndex: 'operation',
key: 'operation',
}
])
function handleBackRows(ModuleId) {
}
function dataBaseClick() {
let rows = getImportSelectRows();
let param = {
dbCode: receiceDbCode.value,
tableList: rows,
};
importDataBaseTable(param).then((res: Recordable) => {
console.log(res);
message.success('导入成功', 2);
closeImportModal();
reload();
});
}
const importColumns: BasicColumn[] = [
{
title: '表名',
dataIndex: 'name',
},
{
title: '说明',
dataIndex: 'description',
},
];
const [
registerImportTable,{ clearSelectedRowKeys: clearImportSelectedRowKeys, getSelectRows: getImportSelectRows },
] = useTable({
title: '',
rowKey: 'name',
api: getImportBaseTableList,
formConfig: {
labelWidth: 80,
schemas:[
{
field:"code",
label:"数据库",
component:"Select",
colProps:{span:6},
},{
field: 'key',
label: '数据表名',
component: 'Input',
colProps: { span: 6 },
}
],
},
useSearchForm: true,
columns: importColumns,
size: 'small',
rowSelection: {
type: 'radio',
},
showTableSetting: false,
canResize: false,
bordered: true,
pagination: {
pageSize: 10,
},
});
const activeKey = ref(1)
const current = ref(0);
const fileList = ref<UploadProps['fileList']>([]);
const props = defineProps(['openModal']);
const emits = defineEmits(['update:openModal']);
const uploadFrom = reactive({
serverName: null,
hasFeature:null,
spaceType: null,
layerType:null,
tableName: null,
});
const formRef = ref();
const dataList = ref([]);
const isShp = ref<Boolean>(true);
const showExistTableList = ref<Boolean>(false)
// todo
const tablecolumns = [
{ title: 'Shp原始字段', dataIndex: 'name', key: 'name' },
{ title: '数据类型', dataIndex: 'type', key: 'type' },
{ title: '数据长度', dataIndex: 'length', key: 'length' },
{ title: '英文名称', dataIndex: 'refName', key: 'refName' },
{ title: '中文名称', dataIndex: 'initName', key: 'initName' },
{ title: '操作', dataIndex: 'operation', key: 'operation' },
];
const uploadFormRules = reactive({
serverName: [{ required: true, message: '请输入服务名称', trigger: 'blur' }],
imageServerAddress: [{ required: true, message: '请输入服务地址', trigger: 'blur' }],
hasFeature: [{ required: true, message: '请选择是否有线索数据', trigger: 'blur' }],
spaceType: [{ required: true, message: '请选择参考系', trigger: 'blur' }],
layerType: [{ required: true, message: '请选数据类型', trigger: 'blur' }],
tableName: [{ required: true, message: '请输入表名', trigger: 'blur' }],
});
const beforeUpload:UploadProps['beforeUpload'] = (file) => {
file.type === FILETYPE.ZIP ? isShp.value = true: isShp.value = false
fileList.value = [file];
return false;
};
const beforeImageUpload = (file: UploadProps['fileList'][number]) => {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJpgOrPng && isLt2M;
};
const handlerCustomRequest = (options)=>{
const formData = new FormData();
formData.append('files', options.file);
// 假设 Token 存储在 localStorage 中
const token = localStorage.getItem('X-Token');
// 设置请求头部,带上 Token
const headers = {
"X-Token": token,
};
axios.post(VITE_GLOB_API_URL+'/api/Files/Upload', formData, { headers }).then(response => {
options.onSuccess(response.data, options.file);
uploadFrom.image = response.data.result[0].filePath;
}).catch(error => {
options.onError(error);
});
}
const handlerUploadFile = ()=>{
let url = ""
const [proxyFile] = fileList.value
let file = proxyFile.originFileObj
let formData = new FormData();
formData.append('files', file)
// formData.append('serverName',uploadFrom.serverName)
// formData.append('spaceType',uploadFrom.spaceType)
// formData.append('tableName',uploadFrom.tableName)
axios.post(url,formData,{headers: {'Content-Type': 'multipart/form-data;charset=UTF-8','X-Token':"95a1a7a8"}}).then(res => {
handlerCreateLayer(res.data.result[0].filePath)
})
}
const handlerCreateLayer =(filePath)=>{
// upload 接口返回路径的反斜杠替换 20240528\\2024052814563161320172.zip → 20240528/2024052814563161320172.zip
filePath = filePath.replace(/\\/,'/');
let addForm = {
filePath:filePath,
tableName:uploadFrom.tableName,
srid:uploadFrom.spaceType
}
let params = ObjectToUrl(addForm);
axios.post("http://192.168.10.102:9500/api/PolygonalShape/CreateGISLayer"+params,{},{headers:{'Content-Type': 'multipart/form-data;charset=UTF-8','X-Token':"95a1a7a8"}}).then(res=>{
console.log("helloworld",res);
})
}
const submitShp = () => {
formRef.value.validate().then(() => {
if(fileList.value?.length < 1){
message.warning('请选择需要上传的文件')
return
}
// 文件上传FormData()
let formData = new FormData();
const [proxyFile] = fileList.value
let file = proxyFile.originFileObj
formData.append('file', file)
formData.append('serverName',uploadFrom.serverName)
formData.append('spaceType',uploadFrom.spaceType)
formData.append('tableName',uploadFrom.tableName)
let url = ""
isShp.value? url = 'http://221.2.83.254:9006/geoserver/uploadFile': url = 'http://221.2.83.254:9006/geoserver/uploadExcelFile'
// isShp.value ? url = "http://192.168.10.102:9500/api/Files/Upload" : url = "http://192.168.10.102:9500/api/Files/Upload"
// let data = [
// {
// "length": 1024,
// "name": "name",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "num",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "type",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "shebeiid",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "forestryty",
// "type": "varchar"
// },
// {
// "length": "",
// "name": "geom",
// "type": "geometry"
// },
// {
// "length": 1024,
// "name": "road",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "checksite",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "lng",
// "type": "varchar"
// },
// {
// "length": 1024,
// "name": "lat",
// "type": "varchar"
// }
// ]
axios.post(url,formData,{headers: {'Content-Type': 'multipart/form-data;charset=UTF-8'}}).then(res => {
let data = res.data.data.heads
let showData = data.map(item => {
return {...item,refName:item.name.toLowerCase(),initName:item.name,key:uuidv4()}
})
dataList.value = showData
current.value++
}).catch(err => {
console.log(err)
})
}).catch(err => {
console.log(err)
})
}
const submitTable = () => {
formRef.value.validate().then(() => {
addLayer(uploadFrom).then(res=>{
console.log("addLyaerAPI",res);
if(res){
closeModal()
message.success('服务创建成功!')
}
})
// axios.post(url,formData,{headers: {'Content-Type': 'multipart/form-data;charset=UTF-8'}}).then(res => {
// let data = res.data.data.heads
// let showData = data.map(item => {
// return {...item,refName:item.name.toLowerCase(),initName:item.name,key:uuidv4()}
// })
// }).catch(err => {
// console.log(err)
// })
}).catch(err => {
console.log(err)
})
}
const handlerGrenerateImageLayer = () => {
let layer = {
id: generateUUID(),
type: "raster",
source: {
type: "raster",
tiles: [imageServerUrl.value],
tileSize: 256,
},
layout: {
visibility: "visible",
},
paint: {},
}
uploadFrom.style = JSON.stringify(layer);
console.log("uploadFrom",uploadFrom);
submitTable();
}
const closeModal = () => {
emits('update:openModal', false)
formRef.value.resetFields()
fileList.value = []
current.value = 0
}
const deleteListItem = (record) => {
dataList.value = dataList.value.filter(item => item.key !== record.key)
}
const insertListItem = () => {
dataList.value.push({
key:uuidv4(),
name:'',
type:'',
length:'',
refName:'',
initName:'',
})
}
const submitDataList = () => {
// let refRelation = {}
// dataList.value.forEach((item,index)=>{
// refRelation[item.refName] = item.initName;
// })
// console.log("refRelation",refRelation);
// let exportForm = {
// "newHeads": dataList.value,
// "refRelation": JSON.stringify(refRelation),
// }
// console.log(dataList.value)
current.value++
}
// 获取现有数据表
const currentTableType = ref<string>();
const handlerGetExistsTableList = (type)=>{
currentTableType.value = type;
openSelectTable.value = true;
}
const handlerGetAttributeFields = (e)=>{
if(uploadFrom.attributeTable){
getOutKeyList({tableNames:uploadFrom.attributeTable,dbCode:"hcsystemdb"}).then(res=>{
filedOptions.value = res[0].db_codecolumnsList
})
}
}
const handlerSelectTable = ()=> {
let table = getImportSelectRows();
uploadFrom[currentTableType.value] = table[0].name
if(currentTableType.value == 'attributeTable'){
if(uploadFrom.attributeTable){
getOutKeyList({tableNames:uploadFrom.attributeTable,dbCode:"hcsystemdb"}).then(res=>{
filedOptions.value = res[0].db_codecolumnsList
})
}
}
openSelectTable.value = false;
}
const handlerCancleSelectTable = ()=>{
openSelectTable.value = false;
}
</script>
<style lang="scss" scoped>
.container{
padding:0px 30px;
}
.insert-shp-modal {
.title {
height: 20px;
display: flex;
align-items: center;
padding-left: 63px;
font-size: 28px;
}
.content {
padding:100px 56px;
}
.steps {
// margin-bottom: 80px;
}
.select-file-div {
padding-left: 52px;
padding-top: 80px;
display: flex;
.upload-div {
width: 200px;
height: 200px;
background: #ffffff;
box-shadow: 0px 52px 103px 0px rgba(192, 199, 218, 0.35);
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
.upload-dragger {
height: 174px;
}
}
.upload-span {
margin-left: 40px;
display: flex;
flex-direction: column;
justify-content: space-between;
.upload-span-content {
font-size: 16px;
margin-top: 8px;
}
}
.upload-form {
flex: 1;
margin-left: 40px;
.upload-span-button {
display: flex;
justify-content: flex-end;
}
}
}
.edit-info-div {
padding-top: 26px;
.footer-button {
margin-top: 20px;
display: flex;
justify-content: flex-end;
}
.insert-list-button {
background-color: #91b0ff;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
user-select: none;
cursor: pointer;
height: 30px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
font-weight: 400;
transition: 1s;
}
.insert-list-button:hover {
font-weight: 900;
color: #000;
}
}
.submit-success {
.success-content {
width: 200px;
align-items: center;
margin: auto;
display: flex;
flex-direction: column;
}
}
.exist-table-list{
width:100%;
height: calc( 100% - 60px);
position:absolute;
top:60px;
left:0px;
background:#fff;
border-radius: 12px;
}
}
.upload-form-by-database{
padding:70px 20px;
}
.layer-icon{
width:200px;
height:200px;
background:#ffffff;
font-size:100px;
text-align: center;
line-height: 200px;
color:#efefef;
border:1px dashed #cfcfcf;
border-radius: 10px;
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
}
</style>