增加视点管理
parent
78325d3fbd
commit
96d727c60f
|
@ -1,14 +1,12 @@
|
|||
package com.yanzhu.file.controller;
|
||||
|
||||
import com.yanzhu.common.core.utils.StringUtils;
|
||||
import com.yanzhu.file.utils.ByteArrayMultipartFile;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.yanzhu.common.core.domain.R;
|
||||
import com.yanzhu.common.core.utils.file.FileUtils;
|
||||
|
@ -16,6 +14,8 @@ import com.yanzhu.file.service.ISysFileService;
|
|||
import com.yanzhu.system.api.domain.SysFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 文件请求处理
|
||||
|
@ -52,6 +52,33 @@ public class SysFileController
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64 图片上传请求
|
||||
*/
|
||||
@PostMapping("/uploadBase64Image")
|
||||
public R<SysFile> uploadBase64Image(@RequestBody Map<String,String> data) {
|
||||
try {
|
||||
// 去除 Base64 数据可能包含的前缀,如 "data:image/png;base64,"
|
||||
String base64Image=data.get("base64Image");
|
||||
String base64Data = base64Image;
|
||||
if (base64Image.contains(",")) {
|
||||
base64Data = base64Image.split(",")[1];
|
||||
}
|
||||
// 解码 Base64 数据
|
||||
byte[] imageBytes = Base64.getDecoder().decode(base64Data);
|
||||
// 生成临时文件名,可根据实际需求修改
|
||||
String fileName = "base64_image_" + System.currentTimeMillis() + ".png";
|
||||
// 创建 MultipartFile 对象
|
||||
MultipartFile multipartFile = new ByteArrayMultipartFile(imageBytes, fileName, "application/octet-stream");
|
||||
// 调用上传方法
|
||||
return upload(multipartFile);
|
||||
} catch (Exception e) {
|
||||
log.error("Base64 图片上传失败", e);
|
||||
return R.fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 文件上传请求
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package com.yanzhu.file.utils;
|
||||
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class ByteArrayMultipartFile implements MultipartFile {
|
||||
private final byte[] fileContent;
|
||||
private final String fileName;
|
||||
private final String contentType;
|
||||
|
||||
public ByteArrayMultipartFile(byte[] fileContent, String fileName, String contentType) {
|
||||
this.fileContent = fileContent;
|
||||
this.fileName = fileName;
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return fileContent == null || fileContent.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return fileContent.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() throws IOException {
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(fileContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(File dest) throws IOException, IllegalStateException {
|
||||
try (FileOutputStream fos = new FileOutputStream(dest)) {
|
||||
fos.write(fileContent);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,3 +31,33 @@ export function roamingDeleteById(data) {
|
|||
params: data,
|
||||
});
|
||||
}
|
||||
|
||||
export function viewpointAdd(data) {
|
||||
return request({
|
||||
url: "/manage/api/bim/viewpoint/add",
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
export function viewpointGet(data) {
|
||||
return request({
|
||||
url: "/manage/api/bim/viewpoint/get",
|
||||
method: "get",
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
export function viewpointUpdateByName(data) {
|
||||
return request({
|
||||
url: "/manage/api/bim/viewpoint/updateName",
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
export function viewpointDeleteById(data) {
|
||||
return request({
|
||||
url: "/manage/api/bim/viewpoint/deleteById",
|
||||
method: "get",
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -128,6 +128,7 @@ export default {
|
|||
pagination: {
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
},
|
||||
isRoaming: false,
|
||||
isRoamingHistory: false,
|
||||
|
@ -188,7 +189,6 @@ export default {
|
|||
projectId: this.currentPrjId,
|
||||
}
|
||||
roamingGet(params).then((res) => {
|
||||
console.log(res)
|
||||
this.pagination.total = res.data.pageInfo.totalCount
|
||||
let datas = res.data.rows
|
||||
if (datas.length > 0) datas.forEach((x) => (x.play = 0))
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
<template>
|
||||
<div class="bim-setting-viewpoint">
|
||||
<el-button class="btn-create" type="primary" @click="CreateViewpoint" @keyup.prevent @keydown.enter.prevent>创建视点</el-button>
|
||||
|
||||
<div style="margin-top: 10px;">
|
||||
<el-card class="viewpoint-list scroll-box" v-if="viewpointList.length > 0">
|
||||
<div v-for="(item, index) in viewpointList" :key="index" class="viewpoint-item" @click="ZoomViewpoint(item)">
|
||||
<div class="viewpoint-content">
|
||||
<el-image :src="item.imgPath" alt class="viewpoint-image" :preview-src-list="[item.imgPath]" />
|
||||
<el-tooltip :content="item.remark" v-if="item.remark">
|
||||
<span class="viewpoint-title">{{ item.name }}</span>
|
||||
</el-tooltip>
|
||||
<span class="viewpoint-title" v-else>{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="viewpoint-actions">
|
||||
<el-tooltip content="默认视点" v-if="1==2">
|
||||
<el-icon @click="DefaultViewpoint(item, index)">
|
||||
<Picture />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="编辑名称">
|
||||
<el-icon @click="editViewPoint(item, index)">
|
||||
<Edit />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除">
|
||||
<el-icon @click="DelViewpoint(item, index)">
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-empty description="暂无视点数据" v-else />
|
||||
</div>
|
||||
<el-dialog
|
||||
title="保存视点"
|
||||
:width="400"
|
||||
v-model="visible"
|
||||
:before-close="handleCancel"
|
||||
class="dialog-bim-setting-viewpoint"
|
||||
:destroy-on-close="true"
|
||||
:close-on-click-modal="false"
|
||||
:modal="false"
|
||||
:class="{ 'mobile-Model':isMobile }"
|
||||
>
|
||||
<el-form :model="form" :rules="formRules" ref="form" label-width="80px">
|
||||
<el-form-item label="视点名称" prop="title">
|
||||
<el-input v-model="form.title" placeholder="请输入视点名称" :rules="[{ required: true, message: '请输入视点名称' }]" />
|
||||
</el-form-item>
|
||||
<el-form-item label="缩略图">
|
||||
<el-image style="width: 100%" :src="previewImage" :preview-src-list="[previewImage]" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input type="textarea" v-model="form.remark" :rows="4" placeholder="备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
<el-button type="primary" @click="SaveViewpoint">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { _isMobile } from '@/utils/public'
|
||||
import { Delete, Picture, Edit } from '@element-plus/icons-vue'
|
||||
import { viewpointGet, viewpointAdd } from '@/api/bim/bim.js'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
export default {
|
||||
components: { Delete, Picture, Edit },
|
||||
props: {
|
||||
me: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
viewpointList: [],
|
||||
visible: false,
|
||||
confirmLoading: false,
|
||||
form: {
|
||||
title: '',
|
||||
remark: '',
|
||||
},
|
||||
formRules: {
|
||||
title: [{ required: true, message: '请输入视点名称', trigger: 'blur' }],
|
||||
},
|
||||
previewImage: '',
|
||||
imgBlobName: '',
|
||||
userName: '',
|
||||
projectMessage: {},
|
||||
isMobile: false,
|
||||
currentPrjId: null,
|
||||
currentComId: null,
|
||||
pagination: {
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.isMobile = _isMobile() ? true : false
|
||||
const userStore = useUserStore()
|
||||
this.currentPrjId = userStore.currentPrjId
|
||||
this.currentComId = userStore.currentComId
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
const that = this
|
||||
viewpointGet({
|
||||
projectId: that.currentPrjId,
|
||||
viewType: 1,
|
||||
pageSize: this.pagination.pageSize,
|
||||
pageNum: this.pagination.current,
|
||||
}).then((d) => {
|
||||
if (d.code != 0) {
|
||||
ElMessage.info('获取视点列表失败!')
|
||||
return false
|
||||
}
|
||||
that.pagination.total = d.data.pageInfo.totalCount
|
||||
that.viewpointList = d.data.rows
|
||||
})
|
||||
},
|
||||
CreateViewpoint() {
|
||||
const that = this
|
||||
api.Public.saveScreenShot((res) => {
|
||||
that.imgBlobName = res
|
||||
that.previewImage = res
|
||||
that.visible = true
|
||||
})
|
||||
},
|
||||
convertBase64UrlToBlob(urlData) {
|
||||
const fd = new FormData()
|
||||
var bytes = window.atob(urlData.split(',')[1]) //去掉url的头,并转换为byte
|
||||
//处理异常,将ascii码小于0的转换为大于0
|
||||
var ab = new ArrayBuffer(bytes.length)
|
||||
var ia = new Uint8Array(ab)
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
ia[i] = bytes.charCodeAt(i)
|
||||
}
|
||||
const blob = new Blob([ab], {
|
||||
type: 'image/png',
|
||||
})
|
||||
fd.append('file', blob, new Date().getTime() + '.png')
|
||||
return fd
|
||||
},
|
||||
ZoomViewpoint(item) {
|
||||
const that = this
|
||||
if (item.viewPosition != null) {
|
||||
api.Camera.setViewPort(JSON.parse(item.viewPosition))
|
||||
}
|
||||
},
|
||||
DefaultViewpoint(item, index) {},
|
||||
DelViewpoint(item, index) {},
|
||||
SaveViewpoint() {
|
||||
const that = this
|
||||
that.$refs.form.validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
const url = '/file/uploadBase64Image'
|
||||
that.$http.post(url, { base64Image: that.previewImage }).then((d) => {
|
||||
if (d.code != 200) {
|
||||
ElMessage.info('上传图片失败!')
|
||||
return false
|
||||
}
|
||||
api.Camera.getViewPort((p) => {
|
||||
let obj = {
|
||||
name: this.form.title,
|
||||
remark: that.form.remark,
|
||||
imgPath: d.data.url,
|
||||
viewPosition: JSON.stringify(p),
|
||||
projectId: that.currentPrjId,
|
||||
comId: that.currentComId,
|
||||
modelId: api.m_model.keys().toArray().join(','),
|
||||
isOvert: 0,
|
||||
level: 0,
|
||||
sort: 0,
|
||||
viewType: 1,
|
||||
processId: 0,
|
||||
parentId: 0,
|
||||
}
|
||||
viewpointAdd({ vo: obj }).then((result) => {
|
||||
if (result.code == 0) {
|
||||
ElMessage.success('已保存!')
|
||||
that.form = {
|
||||
title: [],
|
||||
remark: '',
|
||||
}
|
||||
that.resetScane()
|
||||
that.$refs.form.resetFields()
|
||||
that.visible = false
|
||||
} else {
|
||||
ElMessage.error('保存失败!')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
resetScane() {
|
||||
api.Camera.stopViewPortRoam()
|
||||
api.Model.location(api.m_model.keys().toArray()[0])
|
||||
},
|
||||
handleCancel() {
|
||||
this.visible = false
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.bim-setting-viewpoint {
|
||||
width: 340px;
|
||||
padding: 0px 10px 10px;
|
||||
.btn-create {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 40px;
|
||||
}
|
||||
.viewpoint-list {
|
||||
margin-bottom: 10px;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
|
||||
.viewpoint-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
.viewpoint-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
.viewpoint-image {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
object-fit: cover;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.viewpoint-title {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.viewpoint-actions {
|
||||
.el-icon {
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.dialog-bim-setting-viewpoint {
|
||||
.el-dialog__body {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -31,11 +31,12 @@
|
|||
</div>
|
||||
<div class="bim-setting-tools" v-show="activeMenu>0">
|
||||
<div class="tools-title">{{param.title }}</div>
|
||||
<el-icon @click="doToolsClose" style="color:#fff" class="tools-close">
|
||||
<el-icon @click="doToolsClose" style="color:#000; font-size:20px; cursor:pointer;" class="tools-close">
|
||||
<Close />
|
||||
</el-icon>
|
||||
<person-roaming v-if="activeMenu==1" ref="personRoaming" :me="this"></person-roaming>
|
||||
<custom-viewpoint v-if="activeMenu==2" ref="customViewpoint" :me="this"></custom-viewpoint>
|
||||
<viewpoint v-if="activeMenu==3" ref="viewpoint" :me="this"></viewpoint>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -46,12 +47,13 @@ import { listBimModel } from '@/api/bim/bimModel'
|
|||
import ModelFloorTree from './ModelFloorTree.vue'
|
||||
import PersonRoaming from './PersonRoaming.vue'
|
||||
import CustomViewpoint from './CustomViewpoint.vue'
|
||||
|
||||
import Viewpoint from './Viewpoint.vue'
|
||||
export default {
|
||||
components: {
|
||||
ModelFloorTree,
|
||||
PersonRoaming,
|
||||
CustomViewpoint,
|
||||
Viewpoint,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -112,6 +114,9 @@ export default {
|
|||
if (n == 2) {
|
||||
this.param.title = '自定义视点漫游'
|
||||
}
|
||||
if (n == 3) {
|
||||
this.param.title = '视点管理'
|
||||
}
|
||||
},
|
||||
NotificationPopup(parameter) {
|
||||
this.param = parameter
|
||||
|
@ -133,7 +138,8 @@ export default {
|
|||
// })
|
||||
},
|
||||
doToolsClose() {
|
||||
this.activeMenu = -1
|
||||
this.activeMenu = 0
|
||||
this.resetScene()
|
||||
},
|
||||
notifClose() {
|
||||
this.activeMenu = -1
|
||||
|
@ -196,7 +202,7 @@ export default {
|
|||
}).then((d) => {
|
||||
this.models = d.rows || []
|
||||
if (this.models.length == 0) {
|
||||
this.$model.msgError('暂无模型,请先关联模型')
|
||||
this.$modal.msgError('暂无模型,请先关联模型')
|
||||
} else {
|
||||
this.showTree = true
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue