This commit is contained in:
lizhenhua 2025-07-22 09:22:50 +08:00
parent 5fa24ac729
commit 16ed8e8b61
5 changed files with 1189 additions and 570 deletions

View File

@ -8,7 +8,7 @@ export function getModelListApi(query) {
params: query,
})
}
// 新增模型数据
// 新增模型数据
export function addModelApi(data) {
return request({
url: '/model/add',
@ -16,6 +16,13 @@ export function addModelApi(data) {
data,
})
}
export function openView(data) {
return request({
url: '/model/openView',
method: 'post',
data,
})
}
// 删除层级
export function delModelApi(data) {
return request({
@ -24,6 +31,14 @@ export function delModelApi(data) {
data,
})
}
export function addModel(data) {
return request({
url: '/model/addModel',
method: 'post',
data,
})
}
// // 修改层级
// export function editLevelApi(data) {
// return request({

View File

@ -3,7 +3,7 @@ import request from '@/utils/request'
// 查询项目列表
export function listSurvey(query) {
return request({
url: '/basic/survey/list',
url: '/survey/list',
method: 'get',
params: query
})
@ -12,7 +12,7 @@ export function listSurvey(query) {
// 新增项目
export function addSurvey(data) {
return request({
url: '/basic/survey',
url: '/survey',
method: 'post',
data: data
})
@ -21,7 +21,7 @@ export function addSurvey(data) {
// 查询项目详细
export function getSurvey(proId) {
return request({
url: '/basic/survey/' + proId,
url: '/survey/' + proId,
method: 'get'
})
}
@ -30,7 +30,7 @@ export function getSurvey(proId) {
// 修改项目
export function updateSurvey(data) {
return request({
url: '/basic/survey',
url: '/survey',
method: 'put',
data: data
})
@ -39,7 +39,7 @@ export function updateSurvey(data) {
// 删除项目
export function delSurvey(proId) {
return request({
url: '/basic/survey/' + proId,
url: '/survey/' + proId,
method: 'delete'
})
}
@ -47,7 +47,7 @@ export function delSurvey(proId) {
// 查询项目下拉框
export function projectSelect() {
return request({
url: '/basic/project/list',
url: '/project/list',
method: 'get',
})
}

View File

@ -1,149 +1,172 @@
<template>
<!-- 基础管理-设备管理 -->
<div class="app-container">
<el-form size="small" :inline="true" ref="queryForm" :model="queryParams">
<el-form-item label="项目名称" prop="proName">
<el-input
clearable
placeholder="请输入项目名称"
v-model="queryParams.proName"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="所属单位" prop="unit">
<el-input
clearable
placeholder="请输入所属单位"
v-model="queryParams.unit"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="负责人" prop="chargePerson">
<el-input
clearable
placeholder="请输入负责人"
v-model="queryParams.chargePerson"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- <el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
plain
size="mini"
type="primary"
icon="el-icon-plus"
@click="handleAddDevice"
v-hasPermi="['basic:device:add']"
>
新增
</el-button>
</el-col>
</el-row> -->
<el-table
border
row-key="id"
v-loading="loading"
:data="modelList"
:tree-props="{ children: 'nodes' }"
>
<el-table-column label="序号" align="center" type="index" />
<el-table-column label="项目名称">
<template slot-scope="{ row }">
<span>{{ row.name }}</span>
<el-tag style="margin-left: 10px" size="mini" type="primary">节点{{ row.level }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="240">
<template slot-scope="{ row }">
<el-button
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAddChild(row)"
v-if="row.nodeCount !== row.level"
>
新增
</el-button>
<!-- 根据 modelUrl 显示上传或查看 -->
<el-button
size="mini"
type="text"
:icon="row.modelUrl ? 'el-icon-view' : 'el-icon-upload'"
@click="row.modelUrl ? handleViewModel(row) : handleUploadModel(row)"
v-if="row.nodeCount === row.level"
>
{{ row.modelUrl ? '查看模型' : '上传模型' }}
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleEdit(row)"
v-if="row.level != 1"
>
修改
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
style="color: #f56c6c"
@click="handleDelete(row)"
v-if="row.level != 1"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getModelList"
<div class="app-container">
<el-form size="small" :inline="true" ref="queryForm" :model="queryParams">
<el-form-item label="项目名称" prop="proName">
<el-input
clearable
placeholder="请输入项目名称"
v-model="queryParams.proName"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="所属单位" prop="unit">
<el-input
clearable
placeholder="请输入所属单位"
v-model="queryParams.unit"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="负责人" prop="chargePerson">
<el-input
clearable
placeholder="请输入负责人"
v-model="queryParams.chargePerson"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 添加或修改岗位对话框 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>新增</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getModelList"></right-toolbar>
</el-row>
<el-table
border
row-key="id"
v-loading="loading"
:data="modelList"
:tree-props="{ children: 'nodes' }"
>
<el-table-column label="序号" align="center" type="index" />
<el-table-column label="项目名称">
<template slot-scope="{ row }">
<span>{{ row.name }}</span>
<el-tag style="margin-left: 10px" size="mini" type="primary">节点{{ row.level }}</el-tag>
</template>
</el-table-column>
<el-table-column label="层级名称">
<template slot-scope="{ row }">
<!-- 只在项目级(第一级)显示层级名称 -->
<span v-if="row.level === 1">{{ row.levelName }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="340">
<template slot-scope="{ row }">
<el-button
size="mini"
type="text"
icon="el-icon-plus"
@click="handleAddChild(row)"
v-if="row.level < row.nodeCount"
>
新增
</el-button>
<el-button
size="mini"
type="text"
:icon="row.modelUrl ? 'el-icon-view' : 'el-icon-upload'"
@click="row.modelUrl ? handleViewModel(row) : handleUploadModel(row)"
v-if="row.nodeCount === row.level"
>
{{ row.modelUrl ? '查看模型' : '上传模型' }}
</el-button>
<!-- <el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleEdit(row)"
v-if="row.level != 1"
>
修改
</el-button> -->
<el-button
size="mini"
type="text"
icon="el-icon-delete"
style="color: #f56c6c"
@click="handleDelete(row)"
v-if="row.level != 1"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- <pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getModelList"
/> -->
<el-dialog :title="title" :visible.sync="open" width="550px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="项目名称" prop="proName">
<el-input v-model="form.proName" placeholder="请输入项目名称" />
</el-form-item>
<el-form-item label="层级配置" prop="level">
<el-select v-model="form.level" placeholder="请选择层级配置" style="width: 100%">
<el-option
:key="item.configId"
:value="item.configId"
:label="item.configName"
v-for="item in levelList"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<el-dialog width="50%" append-to-body :title="useOrReturnFormTitle" :visible.sync="useOrReturnFormVisible">
<UseOrReturnForm
ref="useOrReturnFormComponentRef"
v-if="useOrReturnFormVisible"
:project-id="currentProjectId"
@closeUseOrReturnFormDialog="useOrReturnFormVisible = false"
@refreshParentList="getModelList"
/>
</el-dialog>
<!-- 添加或修改岗位对话框 -->
<el-dialog width="40%" append-to-body :title="addOrEditFormTitle" :visible.sync="addOrEditFormVisible">
<AddOrEditForm ref="addOrEditComponentRef" @closeAddOrEditFormDialog="closeAddOrEditFormDialog" />
</el-dialog>
<!-- 模型上传对话框 -->
<el-dialog width="50%" append-to-body :title="useOrReturnFormTitle" :visible.sync="useOrReturnFormVisible">
<UseOrReturnForm
ref="useOrReturnFormComponentRef"
v-if="useOrReturnFormVisible"
:project-id="currentProjectId"
@closeUseOrReturnFormDialog="useOrReturnFormVisible = false"
@refreshParentList="getModelList"
/>
</el-dialog>
<el-dialog
title="模型预览"
:visible.sync="viewDialogVisible"
width="60%"
append-to-body
>
<DxfViewer :dxfUrl="dxfPreviewUrl" v-if="viewDialogVisible" />
</el-dialog>
</div>
<el-dialog
title="模型预览"
:visible.sync="viewDialogVisible"
width="60%"
append-to-body
>
<dxf-viewer :entities="dxfPreviewUrl"></dxf-viewer>
</el-dialog>
</div>
</template>
<script>
@ -152,215 +175,369 @@ import UseOrReturnForm from './useOrReturnForm.vue'
import UseRecordTable from './useRecordTable.vue'
import DxfViewer from './DxfViewer.vue'
// API
import { getModelListApi, delModelApi,openView } from '@/api/basic/model'
import { listProject, getProject, delProject, addProject, updateProject } from '@/api/basic/project'
import { getLevelListApi } from '@/api/basic/level-manage.js'
import { getModelListApi, delModelApi } from '@/api/basic/model'
export default {
name: 'DeviceManage',
components: {
AddOrEditForm,
UseOrReturnForm,
UseRecordTable,
name: 'DeviceManage',
components: {
AddOrEditForm,
UseOrReturnForm,
UseRecordTable,
DxfViewer
},
data() {
return {
// /
open: false,
title: '', //
form: {
proId: undefined,
proName: undefined,
proType: undefined,
unit: undefined,
chargePerson: undefined,
location: undefined,
remark: undefined,
level: undefined,
},
rules: {
proName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
level: [{ required: true, message: '请选择层级配置', trigger: 'change' }],
},
levelList: [], //
viewDialogVisible: false,
dxfPreviewUrl: [],
total: 0, //
loading: false, //
addOrEditFormTitle: '新增', // (AddOrEditForm使)
addOrEditFormVisible: false, // (AddOrEditForm使)
useOrReturnFormTitle: '模型上传', //
useOrReturnFormVisible: false, //
useRecordFormVisible: false, // 使
//
modelList: [],
currentProjectId: null,
showSearch: true, //
//
queryParams: {
// pageNum: 1, // API
// pageSize: 10, // API
proName: undefined,
unit: undefined,
chargePerson: undefined,
},
}
},
created() {
this.getModelList()
this.getLevelList() //
},
methods: {
/** 获取层级配置列表 */
async getLevelList() {
try {
const res = await getLevelListApi({
pageNum: 1,
pageSize: 1000,
})
this.levelList = res.rows
} catch (error) {
console.error("获取层级配置失败:", error)
}
},
components: {
AddOrEditForm,
UseOrReturnForm,
UseRecordTable,
DxfViewer
},
data() {
return {
viewDialogVisible: false,
dxfPreviewUrl: '',
total: 0, //
loading: false, //
addOrEditFormTitle: '新增', //
addOrEditFormVisible: false, //
useOrReturnFormTitle: '模型上传', //
useOrReturnFormVisible: false, //
useRecordFormVisible: false, // 使
//
modelList: [],
currentProjectId: null,
//
queryParams: {
// pageNum: 1,
// pageSize: 10,
proName: undefined,
unit: undefined,
chargePerson: undefined,
},
}
//
handleAdd() {
this.reset() //
this.open = true //
this.title = '新增项目' //
},
created() {
// this.getDeviceList()
this.getModelList()
//
handleViewModel(row) {
/* const modelUrl = row.modelUrl
if (!modelUrl || !modelUrl.endsWith('.dxf')) {
this.$modal.msgWarning('模型地址无效或不是DXF文件')
return
} */
/* 新需求 重新做 上面建议不要删除 有需要直接可以查看 */
openView({ id: row.id }).then(response => {
this.dxfPreviewUrl = response.data
this.viewDialogVisible = true
}).catch(error => {
console.error("获取项目详情失败:", error);
});
},
methods: {
//
handleViewModel(row) {
const modelUrl = row.modelUrl
console.log(modelUrl)
if (!modelUrl || !modelUrl.endsWith('.dxf')) {
this.$modal.msgWarning('模型地址无效或不是DXF文件')
return
}
this.dxfPreviewUrl = modelUrl
this.viewDialogVisible = true
},
//
handleQuery() {
this.queryParams.pageNum = 1
this.getModelList()
},
//
handleQuery() {
this.queryParams.pageNum = 1 //
this.getModelList()
},
//
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
//
resetQuery() {
this.resetForm('queryForm')
this.handleQuery()
},
//
handleAddDevice() {
this.addOrEditFormTitle = '新增'
this.editForm = null
this.addOrEditFormVisible = true
},
// (AddOrEditForm.vue)
handleAddDevice() {
this.addOrEditFormTitle = '新增'
this.editForm = null
this.addOrEditFormVisible = true
},
//
handleAddChild(row) {
const { id, proName, level, nodeCount, projectId } = row
this.addOrEditFormTitle = '新增'
this.editForm = null
this.addOrEditFormVisible = true
//
handleAddChild(row) {
const { id, proName, level, nodeCount, projectId } = row
this.addOrEditFormTitle = '新增'
this.editForm = null
this.addOrEditFormVisible = true
const editForm = { deviceName: proName, id, level, nodeCount, projectId }
this.$nextTick(() => {
this.$refs.addOrEditComponentRef.setFormData(editForm)
})
},
const editForm = { deviceName: proName, id, level, nodeCount, projectId }
this.$nextTick(() => {
this.$refs.addOrEditComponentRef.setFormData(editForm)
})
},
//
getModelList() {
this.loading = true
getModelListApi(this.queryParams).then((response) => {
const rawList = response.rows
// nodes
const formatNodes = (nodes = []) => {
return nodes.map(item => ({
...item,
id: item.nodeId, // row-key 使 id
name: item.nodeName, // 使 name
nodes: formatNodes(item.nodes || [])
}))
}
// proName formatNodes
const formatted = rawList.map(project => ({
...project,
id: project.projectId,
name: project.proName,
nodes: formatNodes(project.children || [])
}))
this.modelList = formatted
this.total = response.total
this.loading = false
//
// UUID nodeId
generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = Math.random() * 16 | 0
const v = c === 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})
},
},
//
handleUploadModel(row) {
this.$nextTick(() => {
// projectId
this.currentProjectId = row.projectId || row.id || null
this.useOrReturnFormVisible = true
// resetForm
this.$refs.useOrReturnFormRef?.resetForm()
})
},
//
handleViewRecord(row) {
console.log(row)
this.useRecordFormVisible = true
},
//
handleEdit(row) {
const { id, proName, level, nodeCount } = row
this.addOrEditFormTitle = '编辑'
this.editForm = null
this.addOrEditFormVisible = true
const editForm = { deviceName: proName, id, level, nodeCount }
this.$nextTick(() => {
this.$refs.addOrEditComponentRef.setFormData(editForm)
})
},
/** 修改按钮操作 */
handleUpdate(row) {
this.addOrEditFormTitle = '编辑'
this.addOrEditFormVisible = true
},
//
handleDelete(row) {
this.$modal.confirm('是否确认删除当前节点数据吗?').then(async () => {
const res = await delModelApi({ id: row.id })
if (res.code === 200) {
this.$modal.msgSuccess('删除成功')
this.getModelList()
}
})
},
//
closeAddOrEditFormDialog(isSuccess) {
this.$refs.addOrEditComponentRef.resetForm()
this.addOrEditFormVisible = false
if (isSuccess) {
this.getModelList()
}
},
//
closeUseOrReturnFormDialog() {
//
// -
// -
getModelList() {
this.loading = true;
getModelListApi(this.queryParams).then((response) => {
const rawList = response.rows || [];
//
const formatNodes = (nodes, level = 2) => { //
if (!Array.isArray(nodes)) return [];
return nodes
.filter(item => item && item.nodeId) //
.map(item => ({
...item,
id: item.nodeId,
name: item.nodeName || '未命名节点',
level: level, //
// +1
nodes: formatNodes(item.nodes || item.children || [], level + 1)
}));
};
//
const formatted = rawList.map(project => {
const children = project.children || [];
//
let levelName = '';
let nodeCount = '';
if (this.levelList && this.levelList.length > 0) {
const levelConfig = this.levelList.find(
item => item.configId == project.level //
);
levelName = levelConfig ? levelConfig.configName : '';
}
return {
...project,
id: project.projectId,
name: project.proName || '未命名项目',
level: 1, // 1
levelName: project.levelName, //
nodes: formatNodes(children),
rawData: project,
nodeCount:project.nodeCount
};
});
this.modelList = formatted;
this.total = response.total;
this.loading = false;
}).catch(error => {
console.error("获取模型列表失败:", error);
this.loading = false;
this.$message.error("模型数据加载失败,请重试");
});
},
//
handleUploadModel(row) {
this.$nextTick(() => {
this.currentProjectId = row.id || null
this.useOrReturnFormVisible = true
// resetForm ()
// useOrReturnFormComponentRef resetForm
if (this.$refs.useOrReturnFormComponentRef && typeof this.$refs.useOrReturnFormComponentRef.resetForm === 'function') {
this.$refs.useOrReturnFormComponentRef.resetForm()
this.useOrReturnFormVisible = false
},
//
}
})
},
//
handleViewRecord(row) {
console.log(row)
this.useRecordFormVisible = true
},
// (AddOrEditForm使)
handleEdit(row) {
const { id, proName, level, nodeCount } = row
this.addOrEditFormTitle = '编辑'
this.editForm = null
this.addOrEditFormVisible = true
const editForm = { deviceName: proName, id, level, nodeCount }
this.$nextTick(() => {
// addOrEditComponentRef
if (this.$refs.addOrEditComponentRef) {
this.$refs.addOrEditComponentRef.setFormData(editForm)
}
})
},
/** 修改按钮操作 (使用新的弹窗) */
handleUpdate(row) {
this.reset();
const proId = row.id; // id projectId
getProject(proId).then(response => {
this.form = response.data;
this.open = true;
this.title = '修改项目';
// form.level
// response.data.level configId
// this.form.level = response.data.level;
}).catch(error => {
console.error("获取项目详情失败:", error);
});
},
//
handleDelete(row) {
this.$modal.confirm('是否确认删除当前节点数据吗?').then(async () => {
// row.level
let res;
if (row.level === 1) { // level 1
res = await delProject(row.id); // 使 delProject API
} else {
res = await delModelApi({ id: row.id }); // 使 delModelApi
}
if (res.code === 200) {
this.$modal.msgSuccess('删除成功')
this.getModelList()
} else {
this.$modal.msgError(res.msg || '删除失败');
}
}).catch(() => {
//
})
},
// (AddOrEditForm)
closeAddOrEditFormDialog(isSuccess) {
if (this.$refs.addOrEditComponentRef) {
this.$refs.addOrEditComponentRef.resetForm()
}
this.addOrEditFormVisible = false
if (isSuccess) {
this.getModelList()
}
},
// (UseOrReturnForm)
closeUseOrReturnFormDialog() {
// @closeUseOrReturnFormDialog="useOrReturnFormVisible = false"
// resetForm
// if (this.$refs.useOrReturnFormComponentRef) {
// this.$refs.useOrReturnFormComponentRef.resetForm();
// }
this.useOrReturnFormVisible = false
},
// /
cancel() {
this.open = false
this.reset()
},
// /
reset() {
this.form = {
proId: undefined,
proName: undefined,
proType: undefined,
unit: undefined,
chargePerson: undefined,
location: undefined,
remark: undefined,
level: undefined,
}
this.resetForm('form') // Element UI resetForm
},
/** 提交按钮 (新增/修改项目) */
submitForm: function () {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.form.proId != undefined) {
updateProject(this.form).then((response) => {
this.$modal.msgSuccess('修改成功')
this.open = false
this.getModelList() //
}).catch(error => {
console.error("修改项目失败:", error);
});
} else {
addProject(this.form).then((response) => {
this.$modal.msgSuccess('新增成功')
this.open = false
this.getModelList() //
}).catch(error => {
console.error("新增项目失败:", error);
});
}
}
})
},
},
}
</script>
<style lang="scss" scoped>
/* 修改树形表格的展开图标为 +/- */
::v-deep .el-table .el-table__expand-icon {
transform: rotate(0deg); /* 取消默认的旋转效果 */
transform: rotate(0deg); /* 取消默认的旋转效果 */
}
::v-deep .el-table .el-table__expand-icon .el-icon-arrow-right:before {
content: ''; /* 更大的加号 */
font-size: 16px; /* 调整大小 */
font-weight: bold;
border: 1px solid #409eff;
color: #409eff;
background-color: #f0f7ff;
content: ''; /* 更大的加号 */
font-size: 16px; /* 调整大小 */
font-weight: bold;
border: 1px solid #409eff;
color: #409eff;
background-color: #f0f7ff;
}
::v-deep .el-table .el-table__expand-icon--expanded .el-icon-arrow-right:before {
content: ''; /* 更大的减号 */
font-size: 16px;
font-weight: bold;
border: 1px solid #409eff;
color: #409eff;
background-color: #f0f7ff;
content: ''; /* 更大的减号 */
font-size: 16px;
font-weight: bold;
border: 1px solid #409eff;
color: #409eff;
background-color: #f0f7ff;
}
</style>
</style>

View File

@ -1,69 +1,218 @@
<template>
<div>
<el-form :model="useOrReturnForm" :rules="useOrReturnFormRules" ref="useOrReturnFormRef" label-width="120px">
<el-form-item label="所属项目" prop="projectId" v-show="false">
<el-input v-model="useOrReturnForm.projectId" placeholder="请输入项目ID" />
</el-form-item>
<!-- 可选显示模型URL -->
<el-form-item label="模型URL" prop="modelUrl" v-show="false">
<el-input v-model="useOrReturnForm.modelUrl" placeholder="上传后自动填充" />
</el-form-item>
<div>
<!-- 上传表单 -->
<el-form
:model="useOrReturnForm"
:rules="useOrReturnFormRules"
ref="useOrReturnFormRef"
label-width="120px"
v-show="!showLayerDialog"
>
<el-form-item label="所属项目" prop="projectId" v-show="false">
<el-input v-model="useOrReturnForm.projectId" placeholder="请输入项目ID" />
</el-form-item>
<el-form-item label="模型URL" prop="modelUrl" v-show="false">
<el-input v-model="useOrReturnForm.modelUrl" placeholder="上传后自动填充" />
</el-form-item>
<!-- <el-form-item label="模型名称" prop="modelName">
<el-input v-model="useOrReturnForm.modelName" placeholder="请输入模型名称" />
</el-form-item> -->
<el-form-item label="模型文件" prop="files">
<el-upload
class="upload-demo"
action="/dev-api/common/upload"
:on-success="handleSuccess"
:on-remove="handleRemove"
:before-upload="beforeUpload"
:headers="uploadHeaders"
:file-list="fileList"
:limit="1"
:auto-upload="true"
:show-file-list="true"
:disabled="fileList.length >= 1"
>
<div v-if="fileList.length < 1" class="upload-demo">
<el-button size="small" icon="el-icon-paperclip">上传模型</el-button>
<div class="upload-demo-tip">仅支持上传dxf文件</div>
</div>
</el-upload>
</el-form-item>
<el-form-item>
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="goToNextStep" :disabled="!fileList.length">下一步</el-button>
</el-form-item>
</el-form>
<el-form-item label="模型名称" prop="modelName">
<el-input v-model="useOrReturnForm.modelName" placeholder="请输入模型名称" />
</el-form-item>
<el-form-item label="模型上传类型" prop="modelType">
<el-input v-model="useOrReturnForm.modelType" placeholder="请输入模型名称" />
</el-form-item>
<el-form-item label="模型文件" prop="files">
<el-upload
action="/dev-api/common/upload"
:on-preview="handlePreview"
:headers="uploadHeaders"
:on-remove="handleRemove"
:on-success="handleSuccess"
:before-remove="beforeRemove"
multiple
:limit="3"
:on-exceed="handleExceed"
:file-list="fileList"
:before-upload="beforeUpload"
>
<div class="upload-demo">
<el-button size="small" icon="el-icon-paperclip">上传模型</el-button>
<div class="upload-demo-tip">仅支持上传dxf文件</div>
</div>
</el-upload>
</el-form-item>
<el-form-item label="模型版本" prop="version">
<el-input v-model="useOrReturnForm.version" placeholder="请输入模型版本" />
</el-form-item>
<el-form-item label="设计人员" prop="returnUser">
<el-select v-model="useOrReturnForm.designer" placeholder="请选择设计人员" style="width: 100%">
<el-option label="张工" value="1" />
<el-option label="李工" value="2" />
<el-option label="王工" value="3" />
</el-select>
</el-form-item>
<el-form-item label="版本描述" prop="remark">
<el-input
maxlength="100"
show-word-limit
type="textarea"
placeholder="请输入版本描述"
v-model="useOrReturnForm.user"
:autosize="{ minRows: 3, maxRows: 6 }"
/>
</el-form-item>
</el-form-item>
<!-- 图层和实体预览 -->
<div v-if="showLayerDialog" class="layer-container">
<div class="left-panel">
<h3 class="panel-title">图层列表</h3>
<el-menu
default-active="0"
@select="handleLayerSelect"
:unique-opened="true"
class="layer-menu"
background-color="#f5f7fa"
text-color="#606266"
active-text-color="#409EFF"
>
<el-menu-item
v-for="(layer, index) in layerList"
:key="layer.layerName"
:index="index.toString()"
class="layer-menu-item"
>
{{ layer.layerName }} <span class="entity-count">({{ layer.entities.length }})</span>
</el-menu-item>
</el-menu>
</div>
<el-form-item>
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</el-form-item>
</el-form>
<div class="right-panel">
<h3 class="panel-title">图元列表</h3>
<el-row :gutter="16" class="entity-row">
<el-col
v-for="(entity, i) in selectedLayerEntities"
:key="entity.id || i"
:span="8"
>
<el-card
class="entity-card"
:body-style="{ padding: '10px' }"
:shadow="selectedEntities.includes(entity.id) ? 'hover' : 'never'"
:class="{ active: selectedEntities.includes(entity.id) }"
@click="selectEntity(entity)"
>
<div class="entity-info">
<el-checkbox
v-model="entity.selected"
@click.stop
@change="selectEntity(entity)"
></el-checkbox>
<div><strong>图层名称:</strong> {{ entity.layerName }}</div>
<div><strong>类型:</strong> {{ entity.entityType }}</div>
<div><strong>颜色:</strong> {{ entity.color }}</div>
<div><strong>线宽:</strong> {{ entity.lineweight }}</div>
<div><strong>厚度:</strong> {{ entity.thickness }}</div>
<div><strong>起点:</strong> {{ entity.startPoint || '无' }}</div>
<div><strong>终点:</strong> {{ entity.endPoint || '无' }}</div>
<div><strong>中心点:</strong> {{ entity.centerPoint || '无' }}</div>
<div><strong>半径:</strong> {{ entity.radius === null ? '无' : entity.radius }}</div>
<div><strong>Points:</strong> {{ entity.points || '无' }}</div>
</div>
</el-card>
</el-col>
</el-row>
<!-- 图元预览 -->
<div class="preview-container">
<div class="preview-header">
<h4>图元预览 ({{ previewEntities.length }})</h4>
<div class="zoom-controls">
<el-button size="small" @click="zoomOut" icon="el-icon-minus" circle></el-button>
<span>{{ Math.round(zoomLevel * 100) }}%</span>
<el-button size="small" @click="zoomIn" icon="el-icon-plus" circle></el-button>
<el-button size="small" @click="fitToView">适应视图</el-button>
</div>
</div>
<div class="preview-wrapper" ref="previewWrapper">
<svg
class="preview-svg"
:width="svgSize"
:height="svgSize"
@mousedown="startPan"
@mousemove="pan"
@mouseup="endPan"
@mouseleave="endPan"
@wheel="handleWheel"
>
<!-- 背景网格 -->
<pattern id="grid" width="50" height="50" patternUnits="userSpaceOnUse">
<path d="M 50 0 L 0 0 0 50" fill="none" stroke="#e0e0e0" stroke-width="0.5"/>
</pattern>
<rect width="100%" height="100%" fill="url(#grid)" />
<!-- 坐标轴 -->
<line x1="0" :y1="originY" x2="100%" :y2="originY" stroke="#999" stroke-width="1" stroke-dasharray="5,5" />
<line :x1="originX" y1="0" :x2="originX" y2="100%" stroke="#999" stroke-width="1" stroke-dasharray="5,5" />
<!-- 绘制图元 -->
<g :transform="`scale(${zoomLevel}) translate(${panX}, ${panY})`">
<!-- -->
<circle
v-for="(entity, index) in previewEntities"
v-if="entity.entityType === 'CIRCLE'"
:key="index"
:cx="entity.centerPoint.x"
:cy="entity.centerPoint.y"
:r="entity.radius"
:fill="entity.color || '#409EFF'"
:stroke="entity.color || '#409EFF'"
stroke-width="1"
fill="none"
/>
<!-- 直线 -->
<line
v-for="(entity, index) in previewEntities"
v-if="entity.entityType === 'LINE'"
:key="index"
:x1="entity.startPoint.x"
:y1="entity.startPoint.y"
:x2="entity.endPoint.x"
:y2="entity.endPoint.y"
:stroke="entity.color || '#409EFF'"
:stroke-width="entity.lineweight || 1"
/>
<!-- 多段线 -->
<polyline
v-for="(entity, index) in previewEntities"
v-if="entity.entityType === 'LWPOLYLINE' && entity.points"
:key="index"
:points="getPolylinePoints(entity)"
:stroke="entity.color || '#409EFF'"
:stroke-width="entity.lineweight || 1"
fill="none"
/>
<!-- -->
<circle
v-for="(entity, index) in previewEntities"
v-if="entity.entityType === 'POINT'"
:key="index"
:cx="entity.position.x"
:cy="entity.position.y"
r="2"
:fill="entity.color || '#409EFF'"
/>
</g>
<!-- 原点标记 -->
<circle :cx="originX" :cy="originY" r="3" fill="#f56c6c" />
<text :x="originX + 5" :y="originY - 5" fill="#f56c6c" font-size="12">(0,0)</text>
</svg>
</div>
<!-- 坐标指示器 -->
<div class="coordinate-indicator">
<span>当前视图: X:{{ viewBox.x.toFixed(2) }}, Y:{{ viewBox.y.toFixed(2) }}</span>
<span>缩放: {{ Math.round(zoomLevel * 100) }}%</span>
</div>
</div>
<div class="layer-footer">
<el-button @click="showLayerDialog = false">上一步</el-button>
<el-button
type="primary"
@click="submitForm"
:disabled="!selectedEntities.length"
>
提交 (已选择 {{ selectedEntities.length }} 个图元)
</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
@ -71,162 +220,463 @@ import { getToken } from '@/utils/auth'
import { addModel } from '@/api/basic/model'
export default {
name: 'useOrReturnForm',
data() {
return {
useOrReturnForm: {
modelName: '',
modelType: '',
version: '',
designer: '',
user: '', // remark
files: [],
modelUrl: '', // URL
projectId: '' // ID
},
fileList: []
}
},
props: {
projectId: {
type: String,
default: ''
}
},
mounted() {
this.useOrReturnForm.projectId = this.projectId
},
computed: {
// token
uploadHeaders() {
return {
Authorization: 'Bearer ' + getToken()
}
},
useOrReturnFormRules() {
return {
modelName: [{ required: true, message: '请输入模型名称', trigger: 'blur' }],
modelType: [{ required: true, message: '请输入上传类型', trigger: 'blur' }],
version: [{ required: true, message: '请输入模型版本', trigger: 'blur' }],
designer: [{ required: true, message: '请选择设计人员', trigger: 'change' }],
files: [{ required: true, message: '请上传模型文件', trigger: 'change' }]
}
}
},
methods: {
cancel() {
this.$emit('closeUseOrReturnFormDialog')
},
// async
async submitForm() {
this.$refs.useOrReturnFormRef.validate(async (valid) => {
if (!valid) return;
const formData = {
modelName: this.useOrReturnForm.modelName,
modelType: this.useOrReturnForm.modelType,
version: this.useOrReturnForm.version,
designer: this.useOrReturnForm.designer,
remark: this.useOrReturnForm.user,
modelUrl: this.useOrReturnForm.modelUrl, //
projectId: this.useOrReturnForm.projectId, //
filePaths: this.useOrReturnForm.files.map(file => file.url)
};
try {
const res = await addModel(formData);
if (res.code === 200) {
this.$modal.msgSuccess('模型添加成功');
this.$emit('closeUseOrReturnFormDialog');
this.$emit('refreshParentList');
this.resetForm();
} else {
this.$modal.msgError(res.msg || '提交失败');
}
} catch (error) {
this.$modal.msgError('提交异常: ' + error.message);
}
});
},
resetForm() {
this.$refs.useOrReturnFormRef.resetFields();
this.fileList = [];
this.useOrReturnForm.files = [];
},
handleSuccess(response, file, fileList) {
if (response.code === 200) {
const uploadedUrl = response.fileUrl || response.data || response.url;
this.fileList = fileList;
this.useOrReturnForm.files.push({
name: file.name,
url:uploadedUrl,
uid: file.uid
});
if (!this.useOrReturnForm.modelUrl) {
this.useOrReturnForm.modelUrl = uploadedUrl;
}
this.$refs.useOrReturnFormRef.validateField('files');
} else {
this.$message.error(response.msg || '文件上传失败');
this.handleRemove(file);
}
},
handleRemove(file, fileList) {
this.fileList = fileList;
this.useOrReturnForm.files = this.useOrReturnForm.files.filter(
f => f.uid !== file.uid
);
this.$refs.useOrReturnFormRef.validateField('files');
},
beforeUpload(file) {
const isDxf = file.name.toLowerCase().endsWith('.dxf');
if (!isDxf) {
this.$message.error('只能上传DXF格式的文件!');
}
return isDxf;
},
handlePreview(file) {
this.$message.info('文件预览功能可根据实际需求实现');
},
beforeRemove(file) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleExceed(files, fileList) {
this.$message.warning(
`最多上传3个文件本次选择了 ${files.length} 个文件,总共选择了 ${files.length + fileList.length}`
);
},
//
setFormData(data) {
if (data && data.files) {
this.useOrReturnForm.files = [...data.files];
this.fileList = data.files.map(file => ({
name: file.name,
url: file.url
}));
}
}
name: 'UseOrReturnForm',
props: {
projectId: {
type: String,
default: ''
}
},
data() {
return {
useOrReturnForm: {
modelName: '',
modelType: '',
version: '',
designer: '',
user: '',
files: [],
modelUrl: '',
projectId: ''
},
useOrReturnFormRules: {
files: [{ required: true, message: '请上传模型文件', trigger: 'change' }]
},
fileList: [],
showLayerDialog: false,
layerList: [],
selectedLayerEntities: [],
selectedLayerIndex: 0,
selectedEntities: [],
cadData: [],
svgSize: 400,
zoomLevel: 1,
panning: false,
panStartX: 0,
panStartY: 0,
panX: 0,
panY: 0,
originX: 200,
originY: 200,
viewBox: { x: 0, y: 0 }
}
},
computed: {
uploadHeaders() {
return {
Authorization: 'Bearer ' + getToken()
}
},
previewEntities() {
return this.getAllSelectedEntities();
}
},
mounted() {
this.useOrReturnForm.projectId = this.projectId;
window.addEventListener('resize', this.adjustSVGSize);
this.adjustSVGSize();
},
beforeDestroy() {
window.removeEventListener('resize', this.adjustSVGSize);
},
methods: {
adjustSVGSize() {
if (this.$refs.previewWrapper) {
const width = this.$refs.previewWrapper.clientWidth;
this.svgSize = Math.min(600, Math.max(400, width - 40));
}
},
getAllSelectedEntities() {
const allEntities = [];
this.layerList.forEach(layer => {
layer.entities.forEach(entity => {
if (this.selectedEntities.includes(entity.id)) {
allEntities.push(entity);
}
});
});
return allEntities;
},
getPolylinePoints(entity) {
if (!entity.points || !Array.isArray(entity.points)) return '';
return entity.points.map(point => {
return `${point.x},${point.y}`;
}).join(' ');
},
zoomIn() {
this.zoomLevel = Math.min(5, this.zoomLevel + 0.1);
},
zoomOut() {
this.zoomLevel = Math.max(0.1, this.zoomLevel - 0.1);
},
handleWheel(event) {
event.preventDefault();
const delta = Math.sign(event.deltaY);
if (delta > 0) {
this.zoomOut();
} else {
this.zoomIn();
}
},
fitToView() {
this.zoomLevel = 1;
this.panX = 0;
this.panY = 0;
this.viewBox = { x: 0, y: 0 };
},
startPan(event) {
this.panning = true;
this.panStartX = event.clientX;
this.panStartY = event.clientY;
},
pan(event) {
if (!this.panning) return;
const dx = event.clientX - this.panStartX;
const dy = event.clientY - this.panStartY;
this.panX += dx / this.zoomLevel;
this.panY += dy / this.zoomLevel;
this.panStartX = event.clientX;
this.panStartY = event.clientY;
this.viewBox.x = -this.panX;
this.viewBox.y = -this.panY;
},
endPan() {
this.panning = false;
},
cancel() {
this.$emit('closeUseOrReturnFormDialog')
},
goToNextStep() {
this.showLayerDialog = true
if (!this.cadData || !this.cadData.length) {
this.$message.error('无效的CAD数据无法进入下一步')
return
}
const map = {}
this.cadData.forEach((entity) => {
if (!map[entity.layerName]) {
map[entity.layerName] = { layerName: entity.layerName, entities: [] }
}
if (!entity.id) {
entity.id = entity.layerName + '_' + Math.random().toString(36).substr(2, 9)
}
map[entity.layerName].entities.push(entity)
})
this.layerList = Object.values(map)
this.selectedLayerIndex = 0
this.selectedLayerEntities = this.layerList[0].entities || []
this.selectedEntities = []
},
handleLayerSelect(index) {
this.selectedLayerIndex = parseInt(index)
this.selectedLayerEntities = this.layerList[this.selectedLayerIndex].entities
},
selectEntity(entity) {
entity.selected = !entity.selected;
const idx = this.selectedEntities.indexOf(entity.id)
console.log(JSON.stringify(this.selectedEntities))
if (entity.selected) {
if (idx === -1) this.selectedEntities.push(entity.id)
} else {
if (idx !== -1) this.selectedEntities.splice(idx, 1)
}
},
async submitForm() {
this.$refs.useOrReturnFormRef.validate(async (valid) => {
if (!valid) return
const selectedEntities = [];
this.layerList.forEach(layer => {
layer.entities.forEach(entity => {
if (entity.selected) {
selectedEntities.push({
entityId: entity.entityId || entity.id || '',
entityType: entity.entityType || '',
color: entity.color || '',
lineweight: entity.lineweight || '',
thickness: entity.thickness || '',
startPoint: entity.startPoint || null,
endPoint: entity.endPoint || null,
centerPoint: entity.centerPoint || null,
radius: entity.radius != null ? entity.radius : null,
// points: entity.points || [],
geometry: entity.geometry || {}, // geometry
layerName: layer.layerName || ''
});
}
});
});
const formData = {
projectId: this.useOrReturnForm.projectId,
modelName: this.useOrReturnForm.modelName,
modelUrl: this.useOrReturnForm.modelUrl,
fileName: this.useOrReturnForm.fileName,
version: this.useOrReturnForm.version,
designer: this.useOrReturnForm.designer,
designerName: this.useOrReturnForm.designerName,
remark: this.useOrReturnForm.remark,
modelType: this.useOrReturnForm.modelType,
modelIds: this.useOrReturnForm.modelIds,
createBy: this.useOrReturnForm.createBy,
createTime: this.useOrReturnForm.createTime,
selectedEntities: selectedEntities
};
try {
const res = await addModel(formData)
if (res.code === 200) {
this.$modal.msgSuccess('模型添加成功')
this.$emit('closeUseOrReturnFormDialog')
this.$emit('refreshParentList')
this.resetForm()
} else {
this.$modal.msgError(res.msg || '提交失败')
}
} catch (error) {
this.$modal.msgError('提交异常: ' + error.message)
}
})
},
resetForm() {
this.$refs.useOrReturnFormRef.resetFields()
this.fileList = []
this.useOrReturnForm.files = []
this.selectedEntities = []
this.showLayerDialog = false
this.fitToView()
},
handleSuccess(response, file, fileList) {
if (response.code === 200) {
this.cadData = response.cadData || []
const uploaded = response.data || {
name: file.name,
url: response.fileUrl || response.url,
uid: file.uid
}
this.fileList = fileList
this.useOrReturnForm.files = [uploaded]
this.useOrReturnForm.modelUrl = uploaded.url
this.$refs.useOrReturnFormRef.validateField('files')
} else {
this.$message.error(response.msg || '文件上传失败')
this.handleRemove(file)
}
},
handleRemove(file, fileList) {
this.fileList = fileList
this.useOrReturnForm.files = []
this.useOrReturnForm.modelUrl = ''
this.cadData = []
this.$refs.useOrReturnFormRef.validateField('files')
},
beforeUpload(file) {
const isDxf = file.name.toLowerCase().endsWith('.dxf')
if (!isDxf) this.$message.error('只能上传DXF格式的文件!')
return isDxf
}
}
}
</script>
<style lang="scss" scoped>
<style scoped>
.upload-demo {
display: flex;
align-items: center;
.upload-demo-tip {
margin-left: 10px;
color: #f56c6c;
}
display: flex;
align-items: center;
}
.upload-demo-tip {
margin-left: 10px;
color: #f56c6c;
}
.layer-container {
display: flex;
height: 650px;
border: 1px solid #e4e7ed;
border-radius: 6px;
box-shadow: 0 4px 12px rgb(0 0 0 / 0.1);
background-color: #fff;
}
.left-panel {
width: 260px;
background: #f7f9fc;
border-right: 1px solid #dcdfe6;
padding: 20px 15px;
overflow-y: auto;
}
.panel-title {
font-weight: 600;
font-size: 18px;
margin-bottom: 20px;
color: #303133;
border-bottom: 2px solid #409EFF;
padding-bottom: 6px;
}
.layer-menu {
background: transparent;
border: none;
}
.layer-menu-item {
font-size: 15px;
padding: 8px 15px !important;
display: flex;
justify-content: space-between;
color: #606266;
cursor: pointer;
}
.layer-menu-item:hover {
background-color: #e6f2ff;
color: #409EFF;
}
.el-menu-item.is-active {
background-color: #409EFF !important;
color: #fff !important;
font-weight: 600;
}
.entity-count {
color: #909399;
font-weight: 400;
}
.right-panel {
flex: 1;
padding: 20px 25px;
background: #fff;
overflow-y: auto;
display: flex;
flex-direction: column;
}
.entity-row {
margin-bottom: 15px;
flex-wrap: wrap;
display: flex;
gap: 15px;
}
.entity-card {
cursor: pointer;
border-radius: 6px;
transition: all 0.3s ease;
margin-bottom: 15px;
box-shadow: 0 2px 8px rgb(0 0 0 / 0.05);
width: 30%;
min-width: 200px;
}
.entity-card:hover {
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.entity-card.active {
border: 2px solid #409EFF;
background-color: #f0f7ff;
}
.entity-info {
font-size: 13px;
color: #4a4a4a;
}
.entity-info div {
margin-bottom: 4px;
line-height: 1.3;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.preview-container {
margin-top: 20px;
padding: 15px;
background: #f8fafc;
border: 1px solid #e4e7ed;
border-radius: 6px;
}
.preview-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.zoom-controls {
display: flex;
align-items: center;
gap: 10px;
}
.zoom-controls span {
min-width: 50px;
text-align: center;
font-size: 14px;
}
.preview-wrapper {
height: 300px;
width: 100%;
background: white;
border: 1px solid #dcdfe6;
border-radius: 4px;
overflow: hidden;
position: relative;
}
.preview-svg {
width: 100%;
height: 100%;
background: #f9f9f9;
cursor: move;
}
.coordinate-indicator {
margin-top: 10px;
display: flex;
justify-content: space-between;
font-size: 12px;
color: #666;
}
.layer-footer {
text-align: right;
margin-top: 20px;
padding-top: 10px;
border-top: 1px solid #eee;
}
.layer-footer button {
min-width: 100px;
margin-left: 15px;
font-weight: 600;
}
</style>

View File

@ -17,22 +17,14 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="所属单位" prop="unit">
<el-input
v-model="queryParams.unit"
placeholder="请输入所属单位"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="负责人" prop="chargePerson">
<!-- <el-form-item label="负责人" prop="chargePerson">
<el-input
v-model="queryParams.chargePerson"
placeholder="请输入负责人"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</el-form-item> -->
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@ -68,11 +60,8 @@
<el-table v-loading="loading" :data="proList" @selection-change="handleSelectionChange" border>
<el-table-column label="序号" align="center" type="index" />
<el-table-column label="项目名称" align="center" prop="proName" />
<el-table-column label="项目类型" align="center" prop="proType" />
<el-table-column label="层级配置" align="center" prop="level" />
<el-table-column label="所属单位" align="center" prop="unit" />
<el-table-column label="负责人" align="center" prop="chargePerson" />
<el-table-column label="项目所在地" align="center" prop="location" width="180" />
<el-table-column label="备注" align="center" prop="remark" width="180" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
@ -110,9 +99,6 @@
<el-form-item label="项目名称" prop="proName">
<el-input v-model="form.proName" placeholder="请输入项目名称" />
</el-form-item>
<el-form-item label="项目类型" prop="proType">
<el-input v-model="form.proType" placeholder="请输入项目类型" />
</el-form-item>
<el-form-item label="层级配置" prop="level">
<el-select v-model="form.level" placeholder="请选择层级配置" style="width: 100%">
<el-option
@ -123,15 +109,6 @@
/>
</el-select>
</el-form-item>
<el-form-item label="建设单位" prop="unit">
<el-input v-model="form.unit" placeholder="请输入建设单位" />
</el-form-item>
<el-form-item label="负责人" prop="chargePerson">
<el-input v-model="form.chargePerson" placeholder="请输入负责人" />
</el-form-item>
<el-form-item label="项目所在地" prop="location">
<el-button size="mini" type="text" icon="el-icon-edit" @click="mapAdd">地图选点</el-button>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>