地图照片历史路径独立,与后端api对应

main
滕嵩 2 months ago
parent fe28c83566
commit 84ec34c9fd

@ -1,5 +1,18 @@
import { defHttp } from '@/utils/http/axios';
enum Api {
GetWorkspaceList = '/api/Manage/GetWorkspaceList',
// 获取地图图片列表
GetMediaFile = '/api/AirportMaintenance/GetMediaFile',
// 更新地图图片
UpdatePicStatus = '/api/AirportMaintenance/UpdatePicStatus',
// 删除地图图片
deletepic = '/api/AirportMaintenance/deletepic',
// 修改地图图片名称
UpdatePicName = '/api/AirportMaintenance/UpdatePicName',
// 修改地图图片parentkey
UpdatePicParentKey = '/api/AirportMaintenance/UpdatePicParentKey',
// 获取地图标注列表
GetAnnotationList = '/api/Manage/GetAnnotationList',
// 添加地图标注
@ -19,6 +32,50 @@ enum Api {
DeleteWorkArea = '/api/Manage/DeleteWorkArea',
}
// 获取项目列表
export function GetWorkspaceList(params?) {
return defHttp.get({
url: Api.GetWorkspaceList,
params,
});
}
// 获取地图图片列表
export function GetMediaFile(params) {
return defHttp.get({
url: Api.GetMediaFile,
params
});
}
// 更新地图图片
export function UpdatePicStatus(params) {
return defHttp.get({
url: Api.UpdatePicStatus,
params
});
}
// 删除地图图片
export function Deletepic(params) {
return defHttp.get({
url: Api.deletepic,
params
});
}
// 修改地图图片名称
export function UpdatePicName(params) {
return defHttp.get({
url: Api.UpdatePicName,
params
});
}
// 修改地图图片parentkey
export function UpdatePicParentKey(params) {
return defHttp.get({
url: Api.UpdatePicParentKey,
params
});
}
// 获取地图标注列表
export function GetAnnotationList(params) {
return defHttp.get({

File diff suppressed because it is too large Load Diff

@ -4,12 +4,16 @@
<div class="w-4/5 xl:w-5/6">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #toolbar>
<span v-for="f in floders" :key="f" class="floderTitle">
<span v-if="f != '全部文件'" style="margin-right: 10px"> / </span>
<span @click="getChildrenByProp(tableData, f)"> {{ f }}</span>
<span v-for="(f, index) in floders" :key="f.id" class="floderTitle">
<span v-if="f.name != '全部文件'" style="margin-right: 10px"> / </span>
<a-tooltip placement="top">
<template #title>
<span>{{ f.name }}</span>
</template>
<span class="flodersname" @click="getChildrenByProp(f, index)"> {{ f.name }}</span>
</a-tooltip>
</span>
<div class="floderOtherButton">
<!-- <PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn> -->
<a-button :icon="h(BorderHorizontalOutlined)" @click="openComparisonModal">
变化检测
</a-button>
@ -28,45 +32,19 @@
<template #bodyCell="{ column, record }">
<div v-if="tableType == 'table'">
<template v-if="column.key === 'name'">
<FolderOpenOutlined v-if="record.type == 'folder'" style="font-size: 20px" />
<!-- <PlaySquareTwoTone v-if="record.type == 'video'" style="font-size: 20px" /> -->
<img v-if="record.type == 'img'" :src="record.url" :width="30" :height="20" />
<FolderOpenOutlined v-if="!record.objectKey" style="font-size: 20px" />
<FileOutlined
v-if="record.objectKey && !record.objectKey.includes('jpeg')"
style="font-size: 20px"
/>
<img
v-if="record.type == 'video'"
:src="record.gifZoomImage"
v-if="record.objectKey && record.objectKey.includes('jpeg')"
:src="getImgurl(record.objectKey)"
:width="30"
:height="20"
/>
<FileOutlined v-if="record.type.includes('model')" style="font-size: 20px" />
<div
v-if="record.type.includes('2D')"
style="
position: absolute;
top: 20px;
left: 11px;
font-size: 10px;
color: #ffffff;
background: #000000;
pointer-events: none;
"
>
2D
</div>
<div
v-if="record.type.includes('3D')"
style="
position: absolute;
top: 20px;
left: 11px;
font-size: 10px;
color: #ffffff;
pointer-events: none;
background: #000000;
"
>
3D
</div>
<span
v-if="!record.objectKey || (record.objectKey && record.objectKey.includes('jpeg'))"
@click="lookRecord(record)"
@mouseover="record.isHovered = true"
@mouseout="record.isHovered = false"
@ -77,25 +55,51 @@
>
{{ record.name }}
</span>
<span
v-if="record.objectKey && !record.objectKey.includes('jpeg')"
:style="{
marginLeft: '5px',
}"
>
{{ record.name }}
</span>
</template>
<template v-if="column.key === 'createtime'">
{{ record.createtime ? record.createtime : '-' }}
<template v-if="column.key === 'createTime'">
<span
style="width: 100%; display: flex; align-items: center; justify-content: center"
>
{{ record.createTime ? record.createTime : '-' }}
</span>
</template>
<template v-if="column.key === 'size'">
{{ record.size ? record.size : '-' }}
<span
style="width: 100%; display: flex; align-items: center; justify-content: center"
>
{{ record.size ? record.size : '-' }}
</span>
</template>
<template v-if="column.key === 'label'">
<div v-if="record.label && record.label.length > 0">
<a-tag color="success" v-for="la in record.label" :key="la">{{ la }}</a-tag>
<template v-if="column.key === 'fileTags'">
<div v-if="record.fileTags && record.fileTags.length > 0">
<a-tag color="success" v-for="la in record.fileTags" :key="la">{{ la }}</a-tag>
</div>
</template>
<template v-if="column.key === 'action'">
<a-button type="text">
<EditOutlined @click="renameRecord(record)" />
</a-button>
<a-button type="text">
<BorderInnerOutlined @click="openPathModal(record)" />
</a-button>
<a-tooltip placement="top">
<template #title>
<span>重命名</span>
</template>
<a-button type="text">
<EditOutlined @click="renameRecord(record)" />
</a-button>
</a-tooltip>
<a-tooltip placement="top">
<template #title>
<span>查看地图图片历史路径</span>
</template>
<a-button type="text" v-if="record.objectKey">
<BorderInnerOutlined @click="openPathModal(record)" />
</a-button>
</a-tooltip>
</template>
</div>
</template>
@ -118,53 +122,17 @@
<a-checkbox v-model:checked="record.checked" @change="changeStore($event, record)" />
</div>
<FolderOpenOutlined
v-if="record.type == 'folder'"
v-if="!record.objectKey"
style="font-size: 40px"
@click="lookRecord(record)"
/>
<img
v-if="record.type == 'img'"
:src="record.url"
v-if="record.objectKey"
:src="getImgurl(record.objectKey)"
:width="60"
:height="40"
@click="lookRecord(record)"
/>
<img v-if="record.type == 'video'" :src="record.gifZoomImage" :width="60" :height="40" />
<FileOutlined
v-if="record.type.includes('model')"
style="font-size: 40px"
@click="lookRecord(record)"
/>
<div
v-if="record.type.includes('2D')"
style="
position: absolute;
top: 52px;
left: 60px;
font-size: 20px;
color: #ffffff;
pointer-events: none;
background: #000000;
"
@click="lookRecord(record)"
>
2D
</div>
<div
v-if="record.type.includes('3D')"
style="
position: absolute;
top: 52px;
left: 60px;
font-size: 20px;
color: #ffffff;
pointer-events: none;
background: #000000;
"
@click="lookRecord(record)"
>
3D
</div>
<span
:style="{
textDecoration: record.isHovered ? 'underline' : 'none',
@ -187,13 +155,13 @@
</div>
<!-- 新建文件夹弹窗 -->
<AddFolderModal @register="addFolderModal" @success="handleSuccess" />
<AddFolderModal @register="addFolderModal" @handleSuccess="handleSuccess" />
<!-- 移动弹窗 -->
<MoveFileModal @register="moveFileModal" @success="handleSuccess" />
<MoveFileModal @register="moveFileModal" @handleSuccess="handleSuccess" />
<!-- 压缩弹窗 -->
<CompressFileModal @register="compressFileModal" @success="handleSuccess" />
<CompressFileModal @register="compressFileModal" @handleSuccess="handleSuccess" />
<!-- 重命名弹窗 -->
<RenameModal @register="renameModal" @success="handleSuccess" />
<RenameModal @register="renameModal" @handleSuccess="handleSuccess" />
<!-- 预览弹窗 -->
<a-modal
v-model:open="open"
@ -208,12 +176,12 @@
:maskClosable="false"
>
<Preview
v-if="nowPreviewRecord.type == 'img' || nowPreviewRecord.type == 'video'"
v-if="nowPreviewRecord.objectKey"
:nowPreviewRecord="nowPreviewRecord"
:previewRecordList="previewRecordList"
@chooseNowPreviewRecord="chooseNowPreviewRecord"
@closeModal="closeModal"
@reloadTable="reload"
@handleSuccess="handleSuccess"
/>
</a-modal>
<!-- 变化检测弹窗 -->
@ -244,14 +212,19 @@
:mask="false"
:maskClosable="false"
>
<Path :pathRecord="pathRecord" @closePathModal="closePathModal" />
<Path
:allImageDataList="allImageDataList"
:nowShowImageData="nowShowImageData"
:floderName="floderName"
@closePathModal="closePathModal"
@handleSuccessPath="handleSuccessPath"
/>
</a-modal>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive, ref, watch, h } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getOrgList, deleteDept } from '@/api/demo/system';
import { PageWrapper } from '@/components/Page';
import { useModal } from '@/components/Modal';
import { useMessage } from '@/hooks/web/useMessage';
@ -271,6 +244,13 @@
FileOutlined,
BorderInnerOutlined,
} from '@ant-design/icons-vue';
import {
GetMediaFile,
UpdatePicStatus,
Deletepic,
UpdatePicName,
UpdatePicParentKey,
} from '@/api/demo/mediaLibrary';
import LeftTree from './LeftTree.vue';
import Preview from './preview/index.vue';
import Comparison from './comparison/index.vue';
@ -287,208 +267,8 @@
const { createConfirm, createMessage } = useMessage();
// --------------------------------------------------------------------
const tableData = ref([
{
id: '2',
name: '图片',
createtime: '2025-03-24 18:13:17',
type: 'folder',
children: [
{
id: '1-2',
name: '南山风景照.jpg',
createtime: '2020-10-22 17:33:22',
type: 'img',
url: 'https://img2.baidu.com/it/u=257681495,312745373&fm=253&fmt=auto&app=138&f=JPEG?w=750&h=500',
imgtype: '原片',
taskname: '佛山大火救援项目',
airlineName: '火灾救援勘查航线',
width: 889,
height: 500,
size: '6.2M',
photographFeiji: '救援机1007',
photographNumber: 'GD610',
photographMan: 'zachzhou',
photographTime: '2020-10-22 00:00:00',
label: ['人', '车'],
lat: 35.362625,
lng: 118.033886,
},
{
id: '1-3',
name: '风景图.jpg',
createtime: '2020-10-22 17:33:22',
type: 'img',
url: 'https://m.tuniucdn.com/fb2/t1/G5/M00/44/52/Cii-s1soezyIF2UxABn76u-yKl8AAIwBgB34jAAGfwC3020871',
imgtype: '原片2',
taskname: '佛山大火救援项目2',
airlineName: '火灾救援勘查航线2',
width: 2000,
height: 1334,
size: '1.63M',
photographFeiji: '救援机1008',
photographNumber: 'GD610',
photographMan: 'zachzhou',
photographTime: '2020-10-22 00:00:00',
label: ['人', '车'],
lat: 35.362825,
lng: 118.033886,
},
{
id: '1-4',
name: '红外照片.jpg',
createtime: '2020-10-22 17:33:22',
type: 'img',
url: 'https://pic.rmb.bdstatic.com/bjh/gallery/8c885a0e3cf0647b60548535e2e9ca39.jpeg',
imgtype: '红外照片',
taskname: '佛山大火救援项目-红外照片',
airlineName: '火灾救援勘查航线',
width: 640,
height: 480,
size: '6.2M',
photographFeiji: '救援机1007',
photographNumber: 'GD610',
photographMan: 'zachzhou',
photographTime: '2020-10-22 00:00:00',
label: ['人', '车'],
lat: 35.362925,
lng: 118.033886,
},
{
id: '1-5',
name: '广角照片.jpg',
createtime: '2020-10-22 17:33:22',
type: 'img',
url: 'https://img2.baidu.com/it/u=2490853491,3226002419&fm=253&fmt=auto&app=138&f=JPEG?w=749&h=500',
imgtype: '广角照片',
taskname: '佛山大火救援项目-广角照片',
airlineName: '火灾救援勘查航线',
width: 749,
height: 500,
size: '6.2M',
photographFeiji: '救援机1007',
photographNumber: 'GD610',
photographMan: 'zachzhou',
photographTime: '2020-10-22 00:00:00',
label: ['人', '车'],
lat: 35.362625,
lng: 118.033286,
},
{
id: '1-6',
name: '变焦照片.jpg',
createtime: '2020-10-22 17:33:22',
type: 'img',
url: 'https://img2.baidu.com/it/u=3778652155,475195343&fm=253&fmt=auto&app=138&f=PNG?w=500&h=518',
imgtype: '变焦照片',
taskname: '佛山大火救援项目-变焦照片',
airlineName: '火灾救援勘查航线',
width: 500,
height: 518,
size: '6.2M',
photographFeiji: '救援机1007',
photographNumber: 'GD610',
photographMan: 'zachzhou',
photographTime: '2020-10-22 00:00:00',
label: ['人', '车'],
lat: 35.362725,
lng: 118.033086,
},
],
},
{
id: '3',
name: '视频',
createtime: '2025-03-24 18:13:17',
type: 'folder',
children: [
// {
// id: '3-4',
// name: 'XZD153西',
// createtime: '',
// type: 'video',
// url: '74b95e6575d741489b9a9061bb646467',
// manufacturer: '',
// },
{
id: '3-5',
name: '费县马庄镇陈家鱼后村南斜坡后村',
createtime: '',
type: 'video',
url: 'http://111.36.45.20:18000/flv/hls/H-dcb1ea7388588111.flv',
gifZoomImage: 'https://img.soogif.com/mrGHcO3xjFJnJ986TeL9oAr2BYfPIaM7.gif',
manufacturer: '腾讯',
},
{
id: '3-8',
name: 'movie',
createtime: '',
type: 'video',
url: 'https://www.runoob.com/try/demo_source/mov_bbb.mp4',
gifZoomImage: 'https://img.soogif.com/mrGHcO3xjFJnJ986TeL9oAr2BYfPIaM7.gif',
manufacturer: '腾讯',
},
// {
// id: '3-6',
// name: '',
// createtime: '',
// type: 'video',
// url: '8H03AA1PAG8D9BF',
// manufacturer: '',
// },
// {
// id: '3-7',
// name: '',
// createtime: '',
// type: 'video',
// url: '37130100181328000392',
// manufacturer: '',
// },
],
},
// {
// id: '4',
// name: '',
// createtime: '2025-03-24 18:13:17',
// type: 'folder',
// children: [
// {
// id: '4-1',
// name: ' ',
// createtime: '2025-03-24 18:13:17',
// type: 'model2D',
// url: 'https://m.tuniucdn.com/fb2/t1/G5/M00/44/52/Cii-s1soezyIF2UxABn76u-yKl8AAIwBgB34jAAGfwC3020871',
// boundary: {
// end_lat: 22.57965964566081,
// end_lng: 113.93899440765381,
// max_level: 23,
// min_level: 12,
// start_lat: 22.578193485606185,
// start_lng: 113.93697738647461,
// },
// },
// {
// id: '4-2',
// name: ' ',
// createtime: '2025-03-24 18:13:17',
// type: 'model3D',
// url: 'https://m.tuniucdn.com/fb2/t1/G5/M00/44/52/Cii-s1soezyIF2UxABn76u-yKl8AAIwBgB34jAAGfwC3020871',
// boundary: {
// end_lat: 22.57965964566081,
// end_lng: 113.93899440765381,
// max_level: 23,
// min_level: 12,
// start_lat: 22.578193485606185,
// start_lng: 113.93697738647461,
// },
// },
// ],
// },
]);
//
const showTableData = ref(cloneDeep(tableData.value));
//
const floders = ref(['全部文件']);
const showTableData = ref();
//
const tableType = ref('table');
const tableHeight: any = ref(0);
@ -533,55 +313,12 @@
});
} else {
//
// let showTableDataIds = showTableData.value.map((item) => item.id);
let selectRowsIdArray = showTableData.value.filter((item) => item.checked);
// selectRowsIdArray.forEach((item) => {
// if (showTableDataIds.includes(item.id)) {
// let filterTemp = showTableData.value.filter((f) => f.id == item.id);
// console.log(filterTemp);
// // filterTemp.forEach((temp) => {
// // if (temp.children) {
// // temp.children.forEach((t) => {
// // selectRowsIdArray.push(t);
// // });
// // }
// // });
// }
// });
setSelectedRows(selectRowsIdArray);
}
},
);
//
function getChildrenByProp(children, name) {
if (name == '全部文件') {
showTableData.value = cloneDeep(tableData.value);
floders.value = ['全部文件'];
clearSelectedRowKeys();
return;
}
for (const node of children) {
if (node.name === name) {
showTableData.value = cloneDeep(node.children);
const index = floders.value.indexOf(name);
floders.value = index === -1 ? [] : floders.value.slice(0, index + 1);
clearSelectedRowKeys();
return node.children || [];
}
if (node.children && node.children.length > 0) {
const result = getChildrenByProp(node.children, node.name);
if (result) {
const index = floders.value.indexOf(name);
floders.value = index === -1 ? [] : floders.value.slice(0, index + 1);
clearSelectedRowKeys();
return result;
}
}
}
return null;
}
//
const checkNameChecked = ref(false);
// or
@ -610,64 +347,132 @@
}
//
//
const floders = ref([
{
id: '0',
name: '全部文件',
},
]);
const nowParentKey = ref('0');
const searchInfo = reactive<Recordable>({});
const searchParams = ref();
const [registerTable, { reload, getSelectRows, setSelectedRows, clearSelectedRowKeys }] =
useTable({
// api: getOrgList,
// title: '',
dataSource: showTableData,
rowKey: 'id',
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
},
rowSelection: {
type: 'checkbox',
},
isTreeTable: false,
striped: false,
bordered: false,
inset: false,
tableSetting: {
redo: false,
size: false,
setting: false,
},
useSearchForm: true,
showIndexColumn: false,
showTableSetting: true,
handleSearchInfoFn(info) {
console.log(info);
console.log(searchInfo.value);
searchParams.value = info;
return info;
},
beforeFetch: (data) => {
//
var temp = {
startTime: dayjs(data.startTime).startOf('month').format('YYYY-MM-DD'),
endTime: dayjs(data.endTime).endOf('month').format('YYYY-MM-DD HH:mm:ss'),
const [
registerTable,
{ reload, getDataSource, getSelectRows, setSelectedRows, clearSelectedRowKeys },
] = useTable({
api: GetMediaFile,
rowKey: 'id',
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
},
rowSelection: {
type: 'checkbox',
},
isTreeTable: false,
striped: false,
bordered: false,
inset: false,
tableSetting: {
redo: false,
size: false,
setting: false,
},
useSearchForm: true,
showIndexColumn: false,
showTableSetting: true,
beforeFetch: (data) => {
//
let temp = {
...data,
parentKey: nowParentKey.value,
};
return temp;
},
handleSearchInfoFn(info) {
if (info.startTime && info.endTime) {
info = {
...info,
startTime: dayjs(info.startTime).format('YYYY-MM-DD') + ' 00:00:00',
endTime: dayjs(info.endTime).format('YYYY-MM-DD') + ' 23:59:59',
};
return temp;
},
afterFetch: (res) => {
console.log(res);
},
});
}
searchParams.value = info;
return info;
},
afterFetch: (res) => {
res.forEach((arr) => {
if (arr.fileTags) {
arr.fileTags = JSON.parse(arr.fileTags);
} else {
arr.fileTags = [];
}
if (arr.graffitiJson) {
arr.graffitiJson = JSON.parse(arr.graffitiJson);
} else {
arr.graffitiJson = [];
}
});
return res;
},
});
//
function getChildrenByProp(f, index) {
nowParentKey.value = f.id;
floders.value = floders.value.splice(0, index + 1);
clearSelectedRowKeys();
reload();
showTableData.value = getDataSource();
}
//
function getImgurl(url) {
return 'http://175.27.168.120:6014/api/v1/buckets/test/objects/download?prefix=' + url;
}
// ----------------------------------------------------------------------
//
function handleSelect(orgId = '') {
searchInfo.orgId = orgId;
reload();
}
//
const childRef = ref<any>();
function handleSuccess() {
function handleSuccess(record = null) {
clearSelectedRowKeys();
childRef.value.fetch();
reload();
setTimeout(() => {
if (record) {
// -
previewRecordList.value.forEach((item, index) => {
if (record.id == item.id) {
previewRecordList.value.splice(index, 1);
if (previewRecordList.value.length != 0) {
nowPreviewRecord.value = previewRecordList.value[index];
} else {
open.value = false;
}
}
});
} else {
//
GetMediaFile({
...searchParams.value,
parentKey: nowParentKey.value,
page: 1,
limit: 100,
}).then((res) => {
previewRecordList.value = uniqueByKey(res.items, null);
getDataSource().forEach((item) => {
if (item.id == nowPreviewRecord.value.id) {
nowPreviewRecord.value = item;
}
});
});
}
}, 500);
}
//
const [addFolderModal, { openModal: openAddFolderModal }] = useModal();
@ -680,62 +485,29 @@
//
function addFolder() {
let rows = getSelectRows();
let record: any = null;
if (rows.length == 1) {
if (rows[0].type == 'folder') {
record = rows[0];
} else {
record = findParentIdById(tableData.value, rows[0].id);
}
}
openAddFolderModal(true, {
record,
});
// openAddFolderModal(true, {
// record,
// });
}
//
function moveFolderOrFile() {
let rows = getSelectRows();
if (rows.length > 0) {
const record = rows;
const records = rows;
openMoveFileModal(true, {
tableData: tableData.value,
record,
records,
});
} else {
return createMessage.warn('请选择一个或者多个文件/文件夹进行移动');
}
}
//
async function deleteFolderOrFile() {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请选择一个或者多个文件/文件夹进行删除');
}
const query = rows.map((item) => item.id);
createConfirm({
iconType: 'info',
title: '删除',
content: '确定要删除当前部门吗',
onOk: async () => {
// const data = await deleteDept(query);
const data = null;
if (data) {
handleSuccess();
createMessage.success('删除成功');
} else {
createMessage.error('删除失败');
}
},
});
}
//
function compressFolderOrFile() {
let rows = getSelectRows();
if (rows.length > 0) {
const record = rows;
openCompressFileModal(true, {
tableData: tableData.value,
tableData: getDataSource(),
record,
});
} else {
@ -748,46 +520,107 @@
record,
});
}
//
function findParentIdById(tree, targetId) {
function recurse(nodes) {
for (let node of nodes) {
if (node.children) {
for (let child of node.children) {
if (child.id === targetId) {
return node;
}
const found = recurse([child]);
if (found) return found;
}
}
}
return null;
//
async function deleteFolderOrFile() {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请选择一个或者多个文件/文件夹进行删除');
}
return recurse(tree);
createConfirm({
iconType: 'info',
title: '删除',
content: '确定要删除选择的文件/文件夹吗?',
onOk: async () => {
let ids = '';
rows.forEach((row) => {
if (!ids) {
ids = row.id;
} else {
ids = ids + ',' + row.id;
}
});
Deletepic({
ids: ids,
}).then((res) => {
handleSuccess();
createMessage.success(res);
});
},
});
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------------
const open = ref(false);
//
//
//
const nowPreviewRecord: any = ref();
//
//
const previewRecordList: any = ref([]);
//
function lookRecord(record) {
if (record.type == 'folder') {
showTableData.value = record.children;
floders.value.push(record.name);
// -
async function lookRecord(record) {
if (!record.objectKey) {
nowParentKey.value = record.id;
floders.value.push({
id: nowParentKey.value,
name: record.name,
});
reload();
} else {
open.value = true;
nowPreviewRecord.value = record;
previewRecordList.value = findParentIdById(tableData.value, record.id)?.children;
if (!previewRecordList.value) {
previewRecordList.value = tableData.value;
}
GetMediaFile({
...searchParams.value,
parentKey: nowParentKey.value,
page: 1,
limit: 100,
}).then((res) => {
nowPreviewRecord.value = record;
previewRecordList.value = uniqueByKey(res.items, record);
open.value = true;
});
}
}
//
function uniqueByKey(arrlist, record) {
let resultList: any = [];
arrlist.forEach((arr) => {
if (
arr.objectKey &&
!resultList.some((item) => item.objectKey === arr.objectKey) &&
arr.objectKey.includes('jpeg')
) {
//
if (record) {
if (
(arr.objectKey == record.objectKey && record.id == arr.id) ||
arr.objectKey != record.objectKey
) {
if (!arr.fileTags) {
arr.fileTags = [];
} else {
arr.fileTags = JSON.parse(arr.fileTags);
}
if (!arr.graffitiJson) {
arr.graffitiJson = [];
} else {
arr.graffitiJson = JSON.parse(arr.graffitiJson);
}
resultList.push(arr);
}
} else {
if (!arr.fileTags) {
arr.fileTags = [];
} else {
arr.fileTags = JSON.parse(arr.fileTags);
}
if (!arr.graffitiJson) {
arr.graffitiJson = [];
} else {
arr.graffitiJson = JSON.parse(arr.graffitiJson);
}
resultList.push(arr);
}
}
});
return resultList;
}
//
function chooseNowPreviewRecord(value) {
nowPreviewRecord.value = value;
@ -812,17 +645,46 @@
// ----------------------------------------------------------------------
const pathOpen = ref(false);
//
const pathRecord = ref({});
const floderName = ref('');
const nowShowImageData = ref({});
const allImageDataList: any = ref([]);
function openPathModal(record) {
console.log('pathRecord',record)
pathRecord.value = record;
pathOpen.value = true;
GetMediaFile({
parentKey: record.parentKey,
page: 1,
limit: 1000,
}).then((res) => {
allImageDataList.value = res.items.filter(
(item) => item.objectKey && item.objectKey.includes('.jpeg'),
);
allImageDataList.value.forEach((arr) => {
if (arr.fileTags) {
arr.fileTags = JSON.parse(arr.fileTags);
} else {
arr.fileTags = [];
}
if (arr.graffitiJson) {
arr.graffitiJson = JSON.parse(arr.graffitiJson);
} else {
arr.graffitiJson = [];
}
});
nowShowImageData.value = allImageDataList.value.filter((item) => item.id == record.id)[0];
floderName.value = floders.value[floders.value.length - 1].name;
pathOpen.value = true;
});
}
//
function closePathModal() {
pathRecord.value = {};
nowShowImageData.value = {};
pathOpen.value = false;
}
//
function handleSuccessPath() {
setTimeout(() => {
openPathModal(nowShowImageData.value);
}, 500);
}
</script>
<style lang="less" scoped>
.floderTitle {
@ -845,6 +707,12 @@
gap: 10px;
flex-wrap: wrap;
}
.flodersname {
max-width: 120px;
white-space: nowrap; /* 禁止换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出显示省略号 */
}
::v-deep .floderTitle .ant-btn {
padding-left: 0px !important;

@ -8,30 +8,30 @@ export const columns: BasicColumn[] = [
title: '文件名称',
dataIndex: 'name',
align: 'left',
width: 200,
width: 300,
},
{
title: '创建时间',
dataIndex: 'createtime',
align: 'left',
dataIndex: 'createTime',
align: 'center',
width: 150,
},
{
title: '大小',
dataIndex: 'size',
align: 'left',
align: 'center',
width: 75,
},
{
title: '标签',
dataIndex: 'label',
align: 'left',
dataIndex: 'fileTags',
align: 'center',
width: 200,
},
{
title: '设备名称',
dataIndex: 'equipmentName',
align: 'left',
align: 'center',
width: 200,
},
{
@ -43,23 +43,41 @@ export const columns: BasicColumn[] = [
];
export const searchFormSchema: FormSchema[] = [
// {
// field: 'device',
// label: '标签',
// component: 'Select',
// colProps: { span: 6 },
// componentProps: {
// mode: 'multiple',
// options: [
// { label: '标签1', value: '标签1' },
// { label: '标签2', value: '标签2' },
// { label: '标签3', value: '标签3' },
// ],
// },
// },
// {
// field: 'device',
// label: '飞行器枚举',
// component: 'Select',
// colProps: { span: 6 },
// componentProps: {
// mode: 'multiple',
// options: [
// { label: '0-100-1', value: '0-100-1' },
// ],
// },
// },
// {
// field: 'picname',
// label: '设备名称',
// component: 'Input',
// colProps: { span: 6 },
// },
{
field: 'label',
label: '标签',
component: 'Select',
colProps: { span: 6 },
componentProps: {
mode: 'multiple',
options: [
{ label: '标签1', value: '标签1' },
{ label: '标签2', value: '标签2' },
{ label: '标签3', value: '标签3' },
],
},
},
{
field: 'equipmentName',
label: '设备名称',
field: 'picname',
label: '文件名称',
component: 'Input',
colProps: { span: 6 },
},
@ -69,12 +87,6 @@ export const searchFormSchema: FormSchema[] = [
component: 'RangePicker',
colProps: { span: 6},
},
{
field: 'name',
label: '文件名称',
component: 'Input',
colProps: { span: 6 },
},
];
export const formGroupSchema: FormSchema[] = [
{

@ -1,98 +1,200 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="移动文件" @ok="handleSubmit">
<a-tree
:tree-data="treeData"
:field-names="{
key: 'id',
title: 'name',
}"
v-model:selectedKeys="selectedKeys"
default-expand-all
:height="300"
:showIcon="true"
:autoExpandParent="true"
:defaultExpandAll="true"
>
<template #icon="{ children }">
<template v-if="children">
<FolderOutlined />
<!-- <BasicTable @register="registerTable">
<template #toolbar>
<span v-for="(f, index) in floders" :key="f.id" class="floderTitle">
<span v-if="f.name != '全部文件'" style="margin-right: 10px"> / </span>
<a-tooltip placement="top">
<template #title>
<span>{{ f.name }}</span>
</template>
<span class="flodersname" @click="getChildrenByProp(f, index)"> {{ f.name }}</span>
</a-tooltip>
</span>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'name'">
<FolderOpenOutlined v-if="!record.objectKey" style="font-size: 20px" />
<span
v-if="!record.objectKey || (record.objectKey && record.objectKey.includes('jpeg'))"
@click="lookRecord(record)"
@mouseover="record.isHovered = true"
@mouseout="record.isHovered = false"
:style="{
textDecoration: record.isHovered ? 'underline' : 'none',
marginLeft: '5px',
}"
>
{{ record.name }}
</span>
</template>
</template>
</a-tree>
</BasicTable> -->
<a-tree v-model:selectedKeys="selectedKeys" show-line :tree-data="treeData"> </a-tree>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { BasicModal, useModalInner } from '@/components/Modal';
import { FolderOutlined } from '@ant-design/icons-vue';
import { orgPosGroup } from '@/api/demo/system';
import { FolderOutlined, FolderOpenOutlined } from '@ant-design/icons-vue';
import { GetMediaFile, UpdatePicParentKey } from '@/api/demo/mediaLibrary';
import type { TreeProps } from 'ant-design-vue';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const emit = defineEmits(['success']);
const emit = defineEmits(['handleSuccess']);
// id
const moveIds: any = ref([]);
// // id
const moveDataList: any = ref([]);
const selectedKeys: any = ref<string[]>();
const treeData = ref([]);
const treeData: any = ref([
{
title: '全部文件',
key: '0',
children: [],
},
]);
function funGetMediaFile() {}
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
setModalProps({ confirmLoading: false });
//
treeData.value = filterTreeByType(data.tableData);
moveIds.value = data.record.map((item) => item);
moveDataList.value = data.records;
});
const floders = ref([
{
id: '0',
name: '全部文件',
},
]);
const nowParentKey = ref('0');
const [
registerTable,
{ reload, getDataSource, getSelectRows, setSelectedRows, clearSelectedRowKeys },
] = useTable({
api: GetMediaFile,
rowKey: 'id',
columns: [
{
title: '文件名称',
dataIndex: 'name',
align: 'left',
width: 200,
},
],
rowSelection: {
type: 'radio',
},
isTreeTable: false,
striped: false,
bordered: false,
inset: false,
useSearchForm: false,
showIndexColumn: false,
showTableSetting: false,
beforeFetch: (data) => {
//
let temp = {
...data,
parentKey: nowParentKey.value,
};
return temp;
},
afterFetch: (res) => {
let result: any = [];
res.forEach((arr, index) => {
if (!arr.objectKey) {
result.push(arr);
}
});
return result;
},
});
//
function getChildrenByProp(f, index) {
nowParentKey.value = f.id;
floders.value = floders.value.splice(0, index + 1);
clearSelectedRowKeys();
reload();
}
// -
async function lookRecord(record) {
if (!record.objectKey) {
nowParentKey.value = record.id;
floders.value.push({
id: nowParentKey.value,
name: record.name,
});
reload();
}
}
//
async function handleSubmit() {
try {
let ids = moveIds.value.map((item) => item.id);
let key = selectedKeys.value[0];
if (!ids.includes(key)) {
let query = {
moveIds: ids,
key: key,
};
//
const data = await orgPosGroup(query);
if (data) {
setModalProps({ confirmLoading: true });
closeModal();
emit('success');
return createMessage.success('成功');
} else {
return createMessage.error('失败');
}
} else {
return createMessage.warn('目标目录不能包含选择目录');
}
let selectKeys = getSelectRows();
moveDataList.value.forEach((movedata) => {
UpdatePicParentKey({ id: movedata.id, ParentKey: selectKeys[0].id }).then((res) => {
console.log(res);
// return;
});
});
// if (!ids.includes(key)) {
// let query = {
// moveIds: ids,
// key: key,
// };
// //
// const data = await orgPosGroup(query);
// if (data) {
// setModalProps({ confirmLoading: true });
// closeModal();
// emit('handleSuccess');
// return createMessage.success('');
// } else {
// return createMessage.error('');
// }
// } else {
// return createMessage.warn('');
// }
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
//
function filterTreeByType(tree) {
function recurse(nodes) {
const filteredNodes: any = [];
for (let node of nodes) {
// folder
if (node.type === 'folder') {
//
const newNode = { ...node };
// children
if (node.children && node.children.length > 0) {
const children = recurse(node.children);
newNode.children = children;
} else {
newNode.children = []; // children
}
// folder push
filteredNodes.push(newNode);
}
}
return filteredNodes;
}
return recurse(tree);
<style lang="less" scoped>
.floderTitle {
display: flex;
align-items: center;
justify-content: center;
width: fit-content;
cursor: pointer;
}
</script>
::v-deep .vben-basic-table-header__toolbar {
display: flex !important;
justify-content: flex-start !important;
}
.floderOtherButton {
position: absolute;
right: 0px;
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.flodersname {
max-width: 120px;
white-space: nowrap; /* 禁止换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 超出显示省略号 */
}
::v-deep .ant-table-row-expand-icon {
display: none !important;
}
::v-deep .ant-table-row-expand-icon-collapsed {
display: none !important;
}
</style>

@ -1,11 +1,5 @@
<template>
<BasicModal
v-bind="$attrs"
@register="registerModal"
title="重命名"
height="100"
@ok="handleSubmit"
>
<BasicModal v-bind="$attrs" @register="registerModal" title="重命名" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
@ -14,12 +8,11 @@
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, useForm } from '@/components/Form';
import { renameSchema } from '../modal.data';
import { orgPosGroup } from '@/api/demo/system';
import { UpdatePicName } from '@/api/demo/mediaLibrary';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const emit = defineEmits(['success']);
const emits = defineEmits(['handleSuccess']);
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 100,
@ -47,16 +40,12 @@
id: id.value,
name: values.name,
};
//
const data = await orgPosGroup(query);
if (data) {
UpdatePicName(query).then((res) => {
emits('handleSuccess');
setModalProps({ confirmLoading: true });
createMessage.success(res);
closeModal();
emit('success');
return createMessage.success('重命名成功');
} else {
return createMessage.error('重命名失败');
}
});
} finally {
setModalProps({ confirmLoading: false });
}

@ -4,71 +4,29 @@
<div
class="leftMenuDiv"
:style="{
width: leftMenuShow ? '340px' : '64px',
width: leftMenuShow ? '340px' : '0px',
}"
>
<PathLeftMenu
ref="pathLeftMenuRef"
:pathRecord="props.pathRecord"
:leftMenuShow="leftMenuShow"
:allAnnotationDataList="allAnnotationDataList"
:nowShowAnnotationData="nowShowAnnotationData"
:allAreaDataList="allAreaDataList"
:nowShowAreaData="nowShowAreaData"
:floderName="floderName"
:allImageDataList="allImageDataList"
:nowShowImageData="nowShowImageData"
@changeLeftMenuShow="changeLeftMenuShow"
@handlerLocation="handlerLocation"
@closePathModal="closePathModal"
@changeAnnotationInfoShow="changeAnnotationInfoShow"
@setNowShowAnnotationData="setNowShowAnnotationData"
@setNowShowImageData="setNowShowImageData"
@setNowShowAreaData="setNowShowAreaData"
@setAllAnnotationData="setAllAnnotationData"
@setAllAreaData="setAllAreaData"
@deleteAnnotation="deleteAnnotation"
@deleteArea="deleteArea"
@handleSuccessPath="handleSuccessPath"
/>
</div>
<!-- 地图 -->
<div class="mapDiv" :style="{ width: dynamicWidth }">
<PathMap
ref="pathMapRef"
:allAnnotationDataList="allAnnotationDataList"
:nowShowAnnotationData="nowShowAnnotationData"
:allAreaDataList="allAreaDataList"
:nowShowAreaData="nowShowAreaData"
:allImageDataList="allImageDataList"
:nowShowImageData="nowShowImageData"
@setNowShowAnnotationData="setNowShowAnnotationData"
@setNowShowImageData="setNowShowImageData"
@setNowShowAreaData="setNowShowAreaData"
@setAllAnnotationData="setAllAnnotationData"
@setAllImageData="setAllImageData"
@setAllAreaData="setAllAreaData"
@closePathImageInfo="closePathImageInfo"
/>
</div>
<!-- 地图标注 -->
<div class="annotationInfoDiv" v-if="annotationInfoShow">
<PathAnnotationInfo
:allAnnotationDataList="allAnnotationDataList"
:nowShowAnnotationData="nowShowAnnotationData"
@setNowShowAnnotationData="setNowShowAnnotationData"
@closePathAnnotationInfo="closePathAnnotationInfo"
@handlerLocation="handlerLocation"
@deleteAnnotation="deleteAnnotation"
/>
</div>
<!-- 地图作业区域 -->
<div class="areaInfoDiv" v-if="areaInfoShow">
<PathAreaInfo
:allAreaDataList="allAreaDataList"
:nowShowAreaData="nowShowAreaData"
@setNowShowAreaData="setNowShowAreaData"
@closePathAreaInfo="closePathAreaInfo"
@handlerLocation="handlerLocation"
@deleteArea="deleteArea"
/>
</div>
<!-- 地图照片 -->
@ -77,45 +35,27 @@
:allImageDataList="allImageDataList"
:nowShowImageData="nowShowImageData"
@setNowShowImageData="setNowShowImageData"
@closePathImageInfo="closePathImageInfo"
@handlerLocation="handlerLocation"
@handleSuccessPath="handleSuccessPath"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue';
import { PathLeftMenu, PathMap, PathAnnotationInfo, PathAreaInfo, PathImageInfo } from './path';
import { ref, watch, computed, onMounted } from 'vue';
import { PathLeftMenu, PathMap, PathImageInfo } from './path';
import { cloneDeep } from 'lodash-es';
import imageJson from './json/image.json';
import {
GetAnnotationList,
DeleteAnnotation,
GetWorkAreaList,
DeleteWorkArea,
} from '@/api/demo/mediaLibrary';
import { WktToGeojson, GeojsonToWkt } from '@/components/MapboxMaps/src/WktGeojsonTransform';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
const props = defineProps(['pathRecord']);
const emits = defineEmits(['closePathModal']);
const props = defineProps(['allImageDataList', 'nowShowImageData', 'floderName']);
const emits = defineEmits(['closePathModal', 'handleSuccessPath']);
//
const dynamicWidth = computed(() => {
let width = 0;
//
if (leftMenuShow.value) {
width += 340;
} else {
width += 64;
}
//
if (annotationInfoShow.value) {
width += 320;
}
//
if (areaInfoShow.value) {
width += 320;
}
//
if (imageInfoShow.value) {
@ -128,161 +68,37 @@
const pathMapRef = ref();
// ----------------------------------------------------
const pathLeftMenuRef = ref();
const leftMenuShow = ref(true);
const leftMenuShow = ref(false);
function changeLeftMenuShow() {
leftMenuShow.value = !leftMenuShow.value;
}
// ----------------------------------------------------
const annotationInfoShow = ref(false);
function changeAnnotationInfoShow() {
annotationInfoShow.value = !annotationInfoShow.value;
}
//
function closePathAnnotationInfo() {
annotationInfoShow.value = false;
nowShowAnnotationData.value = {};
pathMapRef.value.annotationRestoreDefault();
}
//
const nowShowAnnotationData = ref();
const allAnnotationDataList: any = ref([]);
//
function setNowShowAnnotationData(value, restore = true) {
if (value.id) {
annotationInfoShow.value = true;
} else {
annotationInfoShow.value = false;
}
if (restore) {
pathMapRef.value.annotationRestoreDefault();
}
nowShowAnnotationData.value = value;
}
//
function setAllAnnotationData() {
//
getAnnotationList();
}
//
async function getAnnotationList(showThis = true) {
allAnnotationDataList.value = await GetAnnotationList({ workspaceid: 1 });
if (allAnnotationDataList.value.length > 0) {
allAnnotationDataList.value.forEach((annotation, index) => {
let geomjson = WktToGeojson(annotation.geom);
annotation = {
...annotation,
properties: JSON.parse(annotation.properties),
geomtype: getGeomType(annotation),
coordinates: geomjson.coordinates,
};
allAnnotationDataList.value[index] = annotation;
});
}
if (showThis) {
setTimeout(() => {
pathLeftMenuRef.value.updateShowMenuInfoList('地图标注');
}, 50);
}
}
//
function deleteAnnotation(value) {
if (nowShowAnnotationData.value && nowShowAnnotationData.value.id == value.id) {
annotationInfoShow.value = false;
nowShowAnnotationData.value = {};
}
DeleteAnnotation({
id: value.id,
}).then((result) => {
if (result) {
//
getAnnotationList();
createMessage.success('删除成功');
}
});
}
// ----------------------------------------------------
const areaInfoShow = ref(false);
function changeAreaInfoShow() {
areaInfoShow.value = !areaInfoShow.value;
}
//
function closePathAreaInfo() {
areaInfoShow.value = false;
nowShowAreaData.value = {};
pathMapRef.value.areaRestoreDefault();
}
//
const nowShowAreaData = ref();
const allAreaDataList: any = ref([]);
//
function setNowShowAreaData(value, restore = true) {
if (value.id) {
areaInfoShow.value = true;
} else {
areaInfoShow.value = false;
}
if (restore) {
pathMapRef.value.areaRestoreDefault();
}
nowShowAreaData.value = value;
}
//
function setAllAreaData() {
//
getWorkAreaList();
}
//
async function getWorkAreaList(showThis = true) {
allAreaDataList.value = await GetWorkAreaList({ workspaceid: 1 });
if (allAreaDataList.value.length > 0) {
allAreaDataList.value.forEach((area, index) => {
let geomjson = WktToGeojson(area.geom);
area = {
...area,
properties: JSON.parse(area.properties),
geomtype: getGeomType(area),
coordinates: geomjson.coordinates,
};
allAreaDataList.value[index] = area;
});
}
if (showThis) {
setTimeout(() => {
pathLeftMenuRef.value.updateShowMenuInfoList('地图作业区域');
}, 50);
}
}
//
async function deleteArea(value) {
if (nowShowAreaData.value && nowShowAreaData.value.id == value.id) {
areaInfoShow.value = false;
nowShowAreaData.value = {};
}
DeleteWorkArea({
id: value.id,
}).then((result) => {
if (result) {
//
getWorkAreaList();
createMessage.success('删除成功');
}
});
}
// ----------------------------------------------------
const imageInfoShow = ref(false);
//
function closePathImageInfo() {
imageInfoShow.value = false;
}
//
const nowShowImageData = ref();
const allImageDataList = ref(imageJson);
const allImageDataList = ref();
watch(
() => props.nowShowImageData,
() => {
nowShowImageData.value = props.nowShowImageData;
},
{
deep: true,
immediate: true,
},
);
watch(
() => props.allImageDataList,
() => {
allImageDataList.value = props.allImageDataList;
},
{
deep: true,
immediate: true,
},
);
//
function setNowShowImageData(value) {
@ -305,34 +121,10 @@
function handlerLocation(position) {
pathMapRef.value.handlerLocation([position.lng, position.lat]);
}
// WKT
function getGeomType(area) {
let geom = area.geom;
let radiusFlag = area.properties.indexOf('radius') > -1 ? true : false;
//
if (geom.indexOf('POINT') > -1 && !radiusFlag) {
return 'Point';
}
// 线
if (geom.indexOf('LINESTRING') > -1 && !radiusFlag) {
return 'Polyline';
}
//
if (geom.indexOf('POLYGON') > -1 && !radiusFlag) {
return 'Polygon';
}
//
if (geom.indexOf('POLYGON') > -1 && radiusFlag) {
return 'Circle';
}
//
function handleSuccessPath() {
emits('handleSuccessPath');
}
onMounted(() => {
//
getWorkAreaList(false);
getAnnotationList();
});
</script>
<style lang="less" scoped>
.pathModal {

File diff suppressed because it is too large Load Diff

@ -144,7 +144,6 @@
const { createMessage, createConfirm } = useMessage();
const props = defineProps(['allAreaDataList', 'nowShowAreaData']);
console.log('nowShowAreaData',props.nowShowAreaData)
const emits = defineEmits([
'setNowShowAreaData',
'closePathAreaInfo',

@ -25,30 +25,32 @@
<div class="titleTime">
<ClockCircleOutlined />
{{
dayjs(props.nowShowImageData.create_at).format('YYYY-MM-DD HH:mm:ss (UTCZ)') +
dayjs(props.nowShowImageData.createTime).format('YYYY-MM-DD HH:mm:ss (UTCZ)') +
'&nbsp;&nbsp;&nbsp;' +
(props.nowShowImageData.size / 1024 / 1024).toFixed(2) +
'M' +
'&nbsp;&nbsp;&nbsp;' +
'4032 x 3024'
props.nowShowImageData.width +
' x ' +
props.nowShowImageData.height
}}
</div>
<div class="titleCoordinate">
{{
props.nowShowImageData.photo_position.lng +
props.nowShowImageData.lng +
'° N' +
'&nbsp;&nbsp;&nbsp;&nbsp;' +
props.nowShowImageData.photo_position.lat +
props.nowShowImageData.lat +
'° E'
}}
</div>
</div>
<!-- 标签 -->
<div class="tags">
<a-tag color="success" v-for="tag in props.nowShowImageData.file_tags" :key="tag">
<a-tag color="success" v-for="tag in props.nowShowImageData.fileTags" :key="tag">
{{ tag }}
</a-tag>
<PlusSquareOutlined style="font-size: 20px; color: #07aaed" @click="addLabelChange" />
<PlusSquareOutlined style="font-size: 20px; color: #07aaed" @click="addFileTagsChange" />
</div>
<!-- 关闭按钮 -->
<div class="closeButton">
@ -124,7 +126,9 @@
transition: 'transform 0.2s',
width: `${imageWidth}px`,
height: `${imageHeight}px`,
background: `url(${props.nowShowImageData.original_url ? 'https://m.tuniucdn.com/fb2/t1/G5/M00/44/52/Cii-s1soezyIF2UxABn76u-yKl8AAIwBgB34jAAGfwC3020871' : props.nowShowImageData.original_url}) no-repeat`,
background: `url(${getImgurl(props.nowShowImageData.objectKey)}) no-repeat center center`,
backgroundSize: 'contain',
backgroundPosition: 'center',
}"
>
<!-- 创建的矩形 -->
@ -426,7 +430,7 @@
<div class="button">
<a-tooltip placement="top">
<template #title>
<span>刷新</span>
<span>复位刷新</span>
</template>
<RedoOutlined @click="refresh" />
</a-tooltip>
@ -441,15 +445,15 @@
</a-tooltip>
</div>
<!-- 加载到地图上 -->
<div class="button2" @click="funAddOrRemoveToMap">
<div class="button2" @click="funShowOnMap">
<a-tooltip placement="top">
<template #title>
<span>
{{ props.nowShowImageData.show_on_map ? '在地图上取消加载' : '在地图上加载' }}
{{ props.nowShowImageData.showOnMap == 1 ? '在地图上取消加载' : '在地图上加载' }}
</span>
</template>
<svg
v-if="props.nowShowImageData.show_on_map"
v-if="props.nowShowImageData.showOnMap == 1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 24 24"
@ -462,7 +466,7 @@
></path>
</svg>
<svg
v-if="!props.nowShowImageData.show_on_map"
v-if="props.nowShowImageData.showOnMap != 1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 24 24"
@ -483,8 +487,8 @@
<img
:src="
li.preview_url
? 'https://m.tuniucdn.com/fb2/t1/G5/M00/44/52/Cii-s1soezyIF2UxABn76u-yKl8AAIwBgB34jAAGfwC3020871'
: li.preview_url
? li.preview_url
: 'https://m.tuniucdn.com/fb2/t1/G5/M00/44/52/Cii-s1soezyIF2UxABn76u-yKl8AAIwBgB34jAAGfwC3020871'
"
width="75"
height="50"
@ -497,7 +501,7 @@
<!-- 标签弹窗 -->
<a-modal
title="标签设置"
:open="addLabelFlag"
:open="addFileTagsFlag"
:mask="false"
:maskClosable="false"
:closable="false"
@ -506,21 +510,24 @@
<div style="display: block">
<div
style="display: flex; flex-wrap: wrap; gap: 5px; width: 96%; margin: 10px"
v-if="props.nowShowImageData.file_tags.length > 0"
v-if="props.nowShowImageData.fileTags && props.nowShowImageData.fileTags.length > 0"
>
已添加的标签
<div
v-for="la in props.nowShowImageData.file_tags"
v-for="la in props.nowShowImageData.fileTags"
:key="la"
style="border: 1px solid #595959; border-radius: 3px"
>
<span style="margin-left: 5px">{{ la }}</span>
<CloseOutlined style="margin-left: 5px; margin-right: 5px" @click="deleteLabel(la)" />
<CloseOutlined
style="margin-left: 5px; margin-right: 5px"
@click="deleteFileTags(la)"
/>
</div>
</div>
<div style="display: inline-flex; gap: 5px; width: 96%; margin: 10px">
<a-input v-model:value="newLabelName" size="small" placeholder="请输入标签" />
<a-button type="primary" @click="pressEnterLabelFunction"></a-button>
<a-input v-model:value="newFileTagsName" size="small" placeholder="请输入标签" />
<a-button type="primary" @click="pressEnterFileTagsFunction"></a-button>
</div>
<div
style="
@ -533,8 +540,8 @@
>
<a-button
@click="
addLabelFlag = false;
newLabelName = '';
addFileTagsFlag = false;
newFileTagsName = '';
"
>
关闭
@ -569,16 +576,32 @@
PlusSquareOutlined,
} from '@ant-design/icons-vue';
import dayjs from 'dayjs';
import {
UpdatePicStatus,
Deletepic,
UpdatePicName,
UpdatePicParentKey,
} from '@/api/demo/mediaLibrary';
import { cloneDeep } from 'lodash-es';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
const props = defineProps(['nowShowImageData', 'allImageDataList']);
const emits = defineEmits(['setNowShowImageData', 'closePathImageInfo', 'handlerLocation']);
const emits = defineEmits([
'setNowShowImageData',
'closePathImageInfo',
'handleSuccessPath',
'handlerLocation',
]);
//
function getImgurl(url) {
return 'http://175.27.168.120:6014/api/v1/buckets/test/objects/download?prefix=' + url;
}
// --------------------------------
const editNameFlag = ref(true);
const focusInputRef = ref();
const editNameFlag = ref(true);
const editName = ref(props.nowShowImageData.name.split('.').slice(0, -1).join('.'));
function editNameChange() {
if (props.nowShowImageData.name.split('.').length <= 1) {
@ -601,95 +624,23 @@
}
let query = {
id: props.nowShowImageData.id,
newName: newName,
name: newName,
};
props.nowShowImageData.name = newName;
editNameFlag.value = true;
// emits('reloadTable');
return;
// //
// const data = await orgPosGroup(query);
// if (data) {
// editNameFlag.value = true;
// emit('reloadTable');
// return createMessage.success('');
// } else {
// return createMessage.error('');
// }
UpdatePicName(query).then((res) => {
props.nowShowImageData.name = newName;
editNameFlag.value = true;
createMessage.success(res);
emits('handleSuccessPath');
});
}
function editNameBlur() {
editNameFlag.value = true;
editName.value = props.nowShowImageData.name.split('.').slice(0, -1).join('.');
}
// ---------------------------------------------------------------------
const addLabelFlag = ref(false);
const newLabelName = ref('');
function addLabelChange() {
addLabelFlag.value = true;
}
//
async function pressEnterLabelFunction() {
if (!newLabelName.value) {
return;
}
if (!props.nowShowImageData.file_tags.includes(newLabelName.value)) {
props.nowShowImageData.file_tags.push(newLabelName.value);
let query = {
id: props.nowShowImageData.id,
newLabel: props.nowShowImageData.file_tags,
};
addLabelFlag.value = true;
// choosenowShowImageData({
// ...props.nowShowImageData,
// label: props.nowShowImageData.file_tags,
// });
// emits('reloadTable');
newLabelName.value = '';
return;
// //
// const data = await orgPosGroup(query);
// if (data) {
// addLabelFlag.value = true;
// emit('reloadTable');
// return createMessage.success('');
// } else {
// return createMessage.error('');
// }
} else {
return createMessage.error('此标签已存在!');
}
}
//
function deleteLabel(value) {
createConfirm({
iconType: 'info',
title: '提醒',
content: '删除标签【' + value + '】,同标签名的涂鸦标记都会被删除!',
onOk: () => {
props.nowShowImageData.file_tags = props.nowShowImageData.file_tags.filter(
(item) => item !== value,
);
let json = JSON.parse(props.nowShowImageData.graffitiJson);
if (json.some((item) => item.text == value)) {
json = json.filter((item) => item.text !== value);
props.nowShowImageData.graffitiJson = JSON.stringify(json);
graffitis.value = JSON.parse(JSON.stringify(json));
}
// choosenowShowImageData({
// ...props.nowShowImageData,
// label: props.nowShowImageData.file_tags,
// graffitiJson: JSON.stringify(json),
// });
// emits('reloadTable');
},
onCancel: () => {},
});
}
// --------------------------------------------------------------
function closePathImageInfo() {
emits('closePathImageInfo');
emits('setNowShowImageData', {});
}
// --------------------------------------------------------------
@ -732,7 +683,6 @@
// ----------------------------------------------------------------------
//
const scale = ref(1);
//
function zoomIn() {
if (scale.value < 3) {
@ -747,13 +697,6 @@
scale.value -= 0.1;
}
}
const imageWidth = ref(720);
const imageHeight = ref(540);
// 100%
function setProportion() {
imageWidth.value = 1440;
imageHeight.value = 1080;
}
//
const rotationAngle = ref(0);
//
@ -764,13 +707,50 @@
function rotateCounterClockwise() {
rotationAngle.value -= 90; // -90
}
//
const imageWidth = ref(720);
const imageHeight = ref(553);
//
function getImageWidthAndHeight() {
if (
props.nowShowImageData.width &&
props.nowShowImageData.height &&
props.nowShowImageData.width > 720 &&
props.nowShowImageData.height > 553
) {
imageWidth.value = 720;
imageHeight.value = (720 / props.nowShowImageData.width) * props.nowShowImageData.height;
} else {
imageHeight.value = 553;
imageWidth.value = 720;
}
}
onMounted(() => {
getImageWidthAndHeight();
});
// 100%
function setProportion() {
if (
props.nowShowImageData.width &&
props.nowShowImageData.height &&
props.nowShowImageData.width > 720 &&
props.nowShowImageData.height > 553
) {
imageWidth.value = props.nowShowImageData.width;
imageHeight.value = props.nowShowImageData.height;
} else {
imageWidth.value = 1440;
imageHeight.value = 1106;
}
}
//
function refresh() {
scale.value = 1;
rotationAngle.value = 0;
graffitiFlag.value = false;
imageWidth.value = 720;
imageHeight.value = 540;
getImageWidthAndHeight();
//
const dragDocument: any = document.querySelector('.dragModal');
if (dragDocument) {
@ -780,16 +760,29 @@
}
//
function handlerLocation() {
emits('handlerLocation', props.nowShowImageData.photo_position);
emits('handlerLocation', props.nowShowImageData);
}
//
function funAddOrRemoveToMap() {
props.nowShowImageData.show_on_map = !props.nowShowImageData.show_on_map;
if (props.nowShowImageData.show_on_map) {
createMessage.success('在地图上加载成功');
function funShowOnMap() {
if (props.nowShowImageData.showOnMap == 1) {
props.nowShowImageData.showOnMap = 0;
} else {
createMessage.success('在地图上取消加载成功');
props.nowShowImageData.showOnMap = 1;
}
UpdatePicStatus({
id: props.nowShowImageData.id,
fileTags: JSON.stringify(fileTags.value),
graffitiJson: JSON.stringify(graffitis.value),
display: props.nowShowImageData.display,
showOnMap: props.nowShowImageData.showOnMap,
}).then((res) => {
if (props.nowShowImageData.showOnMap == 1) {
createMessage.success('在地图上加载成功');
} else {
createMessage.success('在地图上取消加载成功');
}
emits('handleSuccessPath');
});
}
// -----------------------------------------------
@ -810,36 +803,123 @@
}
}
// --------------------------------
const addFileTagsFlag = ref(false);
const newFileTagsName = ref('');
const fileTags: any = ref([]);
//
const graffitis: any = ref([]);
const graffitisClone: any = ref([]);
watch(
() => props.nowShowImageData,
() => {
graffitis.value = props.nowShowImageData.graffitiJson
? props.nowShowImageData.graffitiJson
: [];
fileTags.value = props.nowShowImageData.fileTags ? props.nowShowImageData.fileTags : [];
},
{
deep: true,
immediate: true,
},
);
//
function addFileTagsChange() {
addFileTagsFlag.value = true;
}
//
async function pressEnterFileTagsFunction() {
if (!newFileTagsName.value) {
return;
}
if (!fileTags.value.includes(newFileTagsName.value)) {
fileTags.value.push(newFileTagsName.value);
UpdatePicStatus({
id: props.nowShowImageData.id,
fileTags: JSON.stringify(fileTags.value),
graffitiJson: JSON.stringify(graffitis.value),
display: props.nowShowImageData.display ? 1 : 0,
showOnMap: props.nowShowImageData.showOnMap ? 1 : 0,
}).then((res) => {
addFileTagsFlag.value = true;
newFileTagsName.value = '';
emits('handleSuccessPath');
});
} else {
return createMessage.error('此标签已存在!');
}
}
//
function deleteFileTags(value) {
createConfirm({
iconType: 'info',
title: '提醒',
content: '删除标签【' + value + '】,同标签名的涂鸦标记都会被删除!',
onOk: () => {
fileTags.value = fileTags.value.filter((item) => item !== value);
let json = graffitis.value;
if (json.some((item) => item.text == value)) {
json = json.filter((item) => item.text !== value);
graffitis.value = json;
}
UpdatePicStatus({
id: props.nowShowImageData.id,
fileTags: JSON.stringify(fileTags.value),
graffitiJson: JSON.stringify(graffitis.value),
display: props.nowShowImageData.display,
showOnMap: props.nowShowImageData.showOnMap,
}).then((res) => {
emits('handleSuccessPath');
});
},
onCancel: () => {},
});
}
//
// ref
const mouseCanvasRef = ref();
const graffitiColor = ref('#E23C39');
const nowGraffiti = ref(-1);
//
const graffitis: any = ref([]);
const graffitisClone: any = ref([]);
//
function addGraffiti() {
props.nowShowImageData.graffitiJson = JSON.stringify(graffitis.value);
graffitis.value.forEach((item) => {
if (!props.nowShowImageData.file_tags.includes(item.text)) {
if (item.text && !fileTags.value.includes(item.text)) {
if (item.text) {
props.nowShowImageData.file_tags.push(item.text);
fileTags.value.push(item.text);
}
}
});
UpdatePicStatus({
id: props.nowShowImageData.id,
fileTags: JSON.stringify(fileTags.value),
graffitiJson: JSON.stringify(graffitis.value),
display: props.nowShowImageData.display,
showOnMap: props.nowShowImageData.showOnMap,
}).then((res) => {
emits('handleSuccessPath');
});
}
//
function deleteGraffiti(index = undefined, value = undefined) {
graffitis.value.splice(index, 1);
// or
props.nowShowImageData.graffitiJson = JSON.stringify(graffitis.value);
if (!graffitis.value.some((item) => item.text == value)) {
props.nowShowImageData.file_tags = props.nowShowImageData.file_tags.filter(
(la) => la != value,
);
fileTags.value = fileTags.value.filter((la) => la != value);
}
UpdatePicStatus({
id: props.nowShowImageData.id,
fileTags: JSON.stringify(fileTags.value),
graffitiJson: JSON.stringify(graffitis.value),
display: props.nowShowImageData.display,
showOnMap: props.nowShowImageData.showOnMap,
}).then((res) => {
emits('handleSuccessPath');
});
}
//------------------------------------------------------------------------
@ -858,7 +938,7 @@
//
function onMouseDown(event) {
if (graffitiFlag.value) {
if (graffitiFlag.value || graffitis.value.some((item) => item.status != 'success')) {
//
if (nowGraffiti.value != -1) return;
if (graffitis.value.findIndex((item) => item.status == 'mouse') != -1) return;
@ -895,7 +975,7 @@
}
//
function onMouseMove(event) {
if (graffitiFlag.value) {
if (graffitiFlag.value || graffitis.value.some((item) => item.status != 'success')) {
//
const rect = mouseCanvasRef.value.getBoundingClientRect();
if (!isDragging.value) return;
@ -919,7 +999,7 @@
}
//
function onMouseUp(event) {
if (graffitiFlag.value) {
if (graffitiFlag.value || graffitis.value.some((item) => item.status != 'success')) {
//
if (!isDragging.value) return;
const rect = mouseCanvasRef.value.getBoundingClientRect();
@ -1014,15 +1094,15 @@
const mouseEditType = ref('');
function funMouseDownEdit(e, index, type) {
//
graffitisClone.value = cloneDeep(graffitis.value);
const rect = mouseCanvasRef.value.getBoundingClientRect();
startX = e.x - rect.x;
startY = e.y - rect.y;
isDragging.value = true;
nowGraffiti.value = index;
mouseEditType.value = type;
window.addEventListener('mousemove', funMouseMoveEdit);
window.addEventListener('mouseup', funMouseUpEdit);
// graffitisClone.value = cloneDeep(graffitis.value);
// const rect = mouseCanvasRef.value.getBoundingClientRect();
// startX = e.x - rect.x;
// startY = e.y - rect.y;
// isDragging.value = true;
// nowGraffiti.value = index;
// mouseEditType.value = type;
// window.addEventListener('mousemove', funMouseMoveEdit);
// window.addEventListener('mouseup', funMouseUpEdit);
}
//
function funMouseMoveEdit(e) {
@ -1090,20 +1170,6 @@
}
};
watch(
() => props.nowShowImageData.id,
() => {
if (props.nowShowImageData.graffitiJson) {
graffitis.value = JSON.parse(props.nowShowImageData.graffitiJson);
} else {
graffitis.value = [];
}
},
{
deep: true,
immediate: true,
},
);
//
onMounted(() => {
addEventListener();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -232,3 +232,40 @@ viewBox="0 0 512 512">
<path d="M464 464H48a16 16 0 0 1-14.07-23.62l208-384a16 16 0 0 1 28.14 0l208 384A16 16 0 0 1 464 464z" fill="#000000">
</path>
</svg>`;
export const defaultIcon = `<svg width="15px" height="21.25px" viewBox="0 0 20 29" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="监测平台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="林业防火-智览-物资点图层-2.0" transform="translate(-880, -469)" fill="currentColor">
<g id="菱形" transform="translate(880, 469)">
<path d="M9.90588766,0 L20,13.1685517 L12.4843534,23.5505302 L12.4843534,28.0455285 L7.51106516,28.0455285 L7.51106516,23.5505302 L0,13.1685517 L9.90588766,0 Z M9.90588766,6 L5,13.1685517 L9.90588766,20.3166169 L15,13.1685517 L9.90588766,6 Z" id="形状结合"></path>
</g>
</g>
</g>
</svg>`;
export const locateBack = `<svg width="24px" height="28px" viewBox="0 0 24 28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="监测平台" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linejoin="round">
<g id="林业防火-智览-物资点图层-2.0" transform="translate(-914, -469)" fill-rule="nonzero" stroke-width="2.75">
<g id="定位" transform="translate(916, 471)">
<path d="M10,23.8461538 C10,23.8461538 20,17.3107692 20,9.75523077 C20,4.36756923 15.5228462,0 10,0 C4.47715385,0 0,4.36756923 0,9.75523077 C0,17.3107692 10,23.8461538 10,23.8461538 Z" id="路径" stroke="currentColor" fill="currentColor"></path>
<path d="M10,16 C13.31368,16 16,13.31368 16,10 C16,6.68632 13.31368,4 10,4 C6.68632,4 4,6.68632 4,10 C4,13.31368 6.68632,16 10,16 Z" id="路径" stroke="#ffffff" fill="#ffffff"></path>
</g>
</g>
</g>
</svg>`;
export const fireIcon = `<svg width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M19.48 12.35c-1.57-4.08-7.16-4.3-5.81-10.23c.1-.44-.37-.78-.75-.55C9.29 3.71 6.68 8 8.87 13.62c.18.46-.36.89-.75.59c-1.81-1.37-2-3.34-1.84-4.75c.06-.52-.62-.77-.91-.34C4.69 10.16 4 11.84 4 14.37c.38 5.6 5.11 7.32 6.81 7.54c2.43.31 5.06-.14 6.95-1.87c2.08-1.93 2.84-5.01 1.72-7.69zm-9.28 5.03c1.44-.35 2.18-1.39 2.38-2.31c.33-1.43-.96-2.83-.09-5.09c.33 1.87 3.27 3.04 3.27 5.08c.08 2.53-2.66 4.7-5.56 2.32z" fill="currentColor">
</path></svg>`;
export const peopleIcon = `<svg width="24px" height="24px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
<circle cx="12" cy="4" r="2" fill="currentColor"></circle><path d="M15.89 8.11C15.5 7.72 14.83 7 13.53 7h-2.54C8.24 6.99 6 4.75 6 2H4c0 3.16 2.11 5.84 5 6.71V22h2v-6h2v6h2V10.05L18.95 14l1.41-1.41l-4.47-4.48z" fill="currentColor">
</path></svg>`;
export const warnIcon = `<svg width="24px" height="24px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 12 12"><g fill="none"><path d="M5.214 1.459a.903.903 0 0 1 1.572 0l4.092 7.169c.348.61-.089 1.372-.787 1.372H1.91c-.698 0-1.135-.762-.787-1.372l4.092-7.17zM5.5 4.5v1a.5.5 0 0 0 1 0v-1a.5.5 0 0 0-1 0zM6 6.75a.75.75 0 1 0 0 1.5a.75.75 0 0 0 0-1.5z" fill="currentColor">
</path></g></svg>`;
export const carIcon = `<svg width="24px" height="24px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512">
<path d="M447.68 220.78a16 16 0 0 0-1-3.08l-37.78-88.16C400.19 109.17 379 96 354.89 96H157.11c-24.09 0-45.3 13.17-54 33.54L65.29 217.7A15.72 15.72 0 0 0 64 224v176a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16v-16h256v16a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16V224a16.15 16.15 0 0 0-.32-3.22zM144 320a32 32 0 1 1 32-32a32 32 0 0 1-32 32zm224 0a32 32 0 1 1 32-32a32 32 0 0 1-32 32zM104.26 208l28.23-65.85C136.11 133.69 146 128 157.11 128h197.78c11.1 0 21 5.69 24.62 14.15L407.74 208z" fill="currentColor">
</path></svg>`;
export const checkIcon = `<svg width="24px" height="24px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24">
<path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
</path></svg>`;
export const closeIcon = `<svg width="24px" height="24px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32"><path d="M24 9.4L22.6 8L16 14.6L9.4 8L8 9.4l6.6 6.6L8 22.6L9.4 24l6.6-6.6l6.6 6.6l1.4-1.4l-6.6-6.6L24 9.4z" fill="currentColor">
</path></svg>`;

@ -4,7 +4,7 @@
<div class="title-1">{{ props.nowPreviewRecord.name }}</div>
<div class="title-2">
{{
props.nowPreviewRecord.createtime +
props.nowPreviewRecord.createTime +
' ' +
props.nowPreviewRecord.size +
' ' +
@ -18,12 +18,12 @@
<div class="mainBody">
<div class="imgOrVideo">
<!-- 图片 -->
<div class="imageDiv" v-if="props.nowPreviewRecord.type == 'img'">
<div class="imageDiv" v-if="props.nowPreviewRecord.objectKey">
<PreviewImage
:nowPreviewRecord="props.nowPreviewRecord"
:previewRecordList="props.previewRecordList"
@chooseNowPreviewRecord="chooseNowPreviewRecord"
@reloadTable="reloadTable"
@handleSuccess="handleSuccess"
@setHideOrShowTextboxFlag="setHideOrShowTextboxFlag"
/>
</div>
@ -33,17 +33,17 @@
:nowPreviewRecord="props.nowPreviewRecord"
:previewRecordList="props.previewRecordList"
@chooseNowPreviewRecord="chooseNowPreviewRecord"
@reloadTable="reloadTable"
@handleSuccess="handleSuccess"
/>
</div>
</div>
<div class="information">
<PreviewImageInformation
v-if="props.nowPreviewRecord.type == 'img'"
v-if="props.nowPreviewRecord.objectKey"
:nowPreviewRecord="props.nowPreviewRecord"
:previewRecordList="props.previewRecordList"
@chooseNowPreviewRecord="chooseNowPreviewRecord"
@reloadTable="reloadTable"
@handleSuccess="handleSuccess"
:hideOrShowTextboxFlag="hideOrShowTextboxFlag"
/>
<PreviewVideoInformation
@ -51,7 +51,7 @@
:nowPreviewRecord="props.nowPreviewRecord"
:previewRecordList="props.previewRecordList"
@chooseNowPreviewRecord="chooseNowPreviewRecord"
@reloadTable="reloadTable"
@handleSuccess="handleSuccess"
/>
</div>
</div>
@ -68,7 +68,7 @@
} from './preview';
const props = defineProps(['nowPreviewRecord', 'previewRecordList']);
const emit = defineEmits(['closeModal', 'chooseNowPreviewRecord', 'reloadTable']);
const emit = defineEmits(['closeModal', 'chooseNowPreviewRecord', 'handleSuccess']);
const hideOrShowTextboxFlag = ref(true);
function setHideOrShowTextboxFlag(value) {
@ -80,8 +80,8 @@
emit('chooseNowPreviewRecord', value);
}
//
function reloadTable() {
emit('reloadTable');
function handleSuccess(record = null) {
emit('handleSuccess', record);
}
//
function closeModal() {

@ -3,14 +3,18 @@
<div id="imageDiv" class="imageDiv" style="overflow: hidden">
<div
ref="mouseCanvasRef"
class="dragModal"
@mousedown="onMouseDown"
@wheel="onWheel"
:style="{
position: 'relative',
transform: `scale(${scale}) rotate(${rotationAngle}deg)`,
transition: 'transform 0.2s',
width: `${getImageWidthAndHeight[0]}px`,
height: `${getImageWidthAndHeight[1]}px`,
background: `url(${props.nowPreviewRecord.url}) no-repeat`,
width: `${imageWidth}px`,
height: `${imageHeight}px`,
background: `url(${getImgurl(props.nowPreviewRecord.objectKey)}) no-repeat center center`,
backgroundSize: 'contain',
backgroundPosition: 'center',
}"
>
<!-- 创建的矩形 -->
@ -34,7 +38,7 @@
position: 'absolute',
left: '0px',
top: rect.height + 'px',
width: '220px',
width: '235px',
height: 30 + 'px',
background: nowGraffiti == index ? '#ffffff' : '#ffffff00',
}"
@ -50,7 +54,7 @@
"
/>
<CheckOutlined
style="margin-right: 10px; color: green"
style="margin-right: 10px; padding: 3px; color: green"
@click="
nowGraffiti = -1;
rect.status = 'success';
@ -58,7 +62,7 @@
"
/>
<CloseOutlined
style="margin-right: 10px; color: red"
style="margin-right: 10px; padding: 3px; color: red"
@click="
rect.text ? (rect.text = graffitisClone[index].text) : (rect.text = '');
nowGraffiti = -1;
@ -66,7 +70,7 @@
"
/>
<DeleteOutlined
style="margin-right: 10px"
style="margin-right: 10px; padding: 3px"
@click="
deleteGraffiti(index, rect.text);
nowGraffiti = -1;
@ -74,7 +78,7 @@
/>
<a-popover placement="top">
<template #content>
<div style="display: flex; gap: 5px">
<div style="display: flex; gap: 3px">
<div
class="popoverClass"
v-for="color in ['#2D8CF0', '#19BE6B', '#FFBB00', '#E23C39', '#B620E0']"
@ -82,7 +86,10 @@
:style="{ background: color }"
@click="rect.color = color"
>
<CheckOutlined v-if="rect.color == color" style="color: white" />
<CheckOutlined
v-if="rect.color == color"
style="color: white; padding: 3px"
/>
</div>
</div>
</template>
@ -94,7 +101,7 @@
style="
font-size: 20px;
font-weight: bold;
-webkit-text-stroke: 1px white;
-webkit-text-stroke: 0.1px white;
width: fit-content;
"
:style="{
@ -294,18 +301,25 @@
<RotateLeftOutlined @click="rotateCounterClockwise" />
</a-tooltip>
</div>
<!-- 100%比例 -->
<div class="button">
<a-tooltip placement="top">
<template #title>
<span>100%比例</span>
</template>
<OneToOneOutlined @click="setProportion" />
</a-tooltip>
</div>
<!-- 刷新 -->
<div class="button">
<a-tooltip placement="top">
<template #title>
<span>刷新</span>
<span>复位刷新</span>
</template>
<RedoOutlined @click="refresh" />
</a-tooltip>
</div>
<span style="color: #ffffff; margin-left: 5px; margin-right: 5px">|</span>
<!-- 全屏 -->
<!-- <div class="button"> <RedoOutlined @click="refresh" /> </div> -->
<!-- 对比 -->
<div class="button">
<a-tooltip placement="top">
@ -316,15 +330,15 @@
</a-tooltip>
</div>
<!-- 加载到地图上 -->
<div class="button2" @click="funAddOrRemoveToMap">
<div class="button2" @click="funShowOnMap">
<a-tooltip placement="top">
<template #title>
<span>
{{ props.nowPreviewRecord.addOrRemoveToMap ? '在地图上取消加载' : '在地图上加载' }}
{{ props.nowPreviewRecord.showOnMap == 1 ? '在地图上取消加载' : '在地图上加载' }}
</span>
</template>
<svg
v-if="props.nowPreviewRecord.addOrRemoveToMap"
v-if="props.nowPreviewRecord.showOnMap == 1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 24 24"
@ -337,7 +351,7 @@
></path>
</svg>
<svg
v-if="!props.nowPreviewRecord.addOrRemoveToMap"
v-if="props.nowPreviewRecord.showOnMap != 1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 24 24"
@ -357,7 +371,7 @@
<template #title>
<span>图片链接复制到剪贴板</span>
</template>
<ExportOutlined @click="copyToClipboard(props.nowPreviewRecord.url)" />
<ExportOutlined @click="copyToClipboard(props.nowPreviewRecord.objectKey)" />
</a-tooltip>
</div>
<!-- 下载 -->
@ -366,7 +380,7 @@
<template #title>
<span>下载</span>
</template>
<DownloadOutlined @click="fetchAndDownloadImage(props.nowPreviewRecord.url)" />
<DownloadOutlined @click="fetchAndDownloadImage(props.nowPreviewRecord.objectKey)" />
</a-tooltip>
</div>
<!-- 删除 -->
@ -382,10 +396,10 @@
<div class="imageList">
<div v-for="li in props.previewRecordList" :key="li.id" @click="chooseNowPreviewRecord(li)">
<div
v-if="li.objectKey"
:class="li.id == props.nowPreviewRecord.id ? 'bottom_div_choose' : 'bottom_div'"
v-if="li.type == 'img'"
>
<img :src="li.url" :width="60" :height="40" />
<img :src="getImgurl(li.objectKey)" loading="lazy" :width="60" :height="40" />
</div>
</div>
</div>
@ -501,41 +515,38 @@
EditOutlined,
FontColorsOutlined,
RedoOutlined,
OneToOneOutlined,
FileImageOutlined,
BorderHorizontalOutlined,
ExpandOutlined,
CompressOutlined,
} from '@ant-design/icons-vue';
import {
UpdatePicStatus,
Deletepic,
UpdatePicName,
UpdatePicParentKey,
} from '@/api/demo/mediaLibrary';
import { useMessage } from '@/hooks/web/useMessage';
import { cloneDeep } from 'lodash-es';
const { createConfirm, createMessage } = useMessage();
const props = defineProps(['nowPreviewRecord', 'previewRecordList']);
const emit = defineEmits(['chooseNowPreviewRecord', 'reloadTable', 'setHideOrShowTextboxFlag']);
const emits = defineEmits([
'chooseNowPreviewRecord',
'handleSuccess',
'setHideOrShowTextboxFlag',
]);
//
const getImageWidthAndHeight = computed(() => {
let width = 1300;
let height = 800;
if (props.nowPreviewRecord.width > 1300 || props.nowPreviewRecord.height > 800) {
if (props.nowPreviewRecord.width / 1300 > props.nowPreviewRecord.height / 800) {
width = 1300;
height = (props.nowPreviewRecord.height / props.nowPreviewRecord.width) * 1300;
} else {
height = 800;
width = (props.nowPreviewRecord.width / props.nowPreviewRecord.height) * 800;
}
} else {
width = props.nowPreviewRecord.width;
height = props.nowPreviewRecord.height;
}
return [width, height];
});
//
function getImgurl(url) {
return 'http://175.27.168.120:6014/api/v1/buckets/test/objects/download?prefix=' + url;
}
//
function clickLeftOrRightButton(direction) {
const list = props.previewRecordList.filter((item) => item.type == 'img');
const list = props.previewRecordList.filter((item) => item.objectKey);
graffitiFlag.value = false;
for (let index = 0; index < list.length; index++) {
if (list[index].id == props.nowPreviewRecord.id) {
@ -559,35 +570,28 @@
//
function chooseNowPreviewRecord(value) {
emit('chooseNowPreviewRecord', value);
//
scale.value = 1;
rotationAngle.value = 0;
emits('chooseNowPreviewRecord', value);
refresh();
}
//
function reloadTable() {
emit('reloadTable');
function handleSuccess(record = null) {
emits('handleSuccess', record);
}
// -----------------------------------
//
const scale = ref(1);
//
function zoomIn() {
if (scale.value < 3) {
// 3
scale.value += 0.1;
}
}
//
function zoomOut() {
if (scale.value > 0.5) {
// 0.5
scale.value -= 0.1;
}
}
// -----------------------------------
//
const rotationAngle = ref(0);
//
function rotateClockwise() {
@ -598,20 +602,85 @@
rotationAngle.value -= 90; // -90
}
//
const imageWidth = ref(1040);
const imageHeight = ref(800);
//
function getImageWidthAndHeight() {
if (
props.nowPreviewRecord.width &&
props.nowPreviewRecord.height &&
props.nowPreviewRecord.width > 1040 &&
props.nowPreviewRecord.height > 800
) {
imageHeight.value = 800;
imageWidth.value = (800 / props.nowPreviewRecord.height) * props.nowPreviewRecord.width;
} else {
imageHeight.value = 800;
imageWidth.value = 1040;
}
}
onMounted(() => {
getImageWidthAndHeight();
});
// 100%
function setProportion() {
if (
props.nowPreviewRecord.width &&
props.nowPreviewRecord.height &&
props.nowPreviewRecord.width > 1040 &&
props.nowPreviewRecord.height > 800
) {
imageWidth.value = props.nowPreviewRecord.width;
imageHeight.value = props.nowPreviewRecord.height;
} else {
imageWidth.value = 2080;
imageHeight.value = 1600;
}
}
//
function refresh() {
scale.value = 1;
rotationAngle.value = 0;
graffitiFlag.value = false;
getImageWidthAndHeight();
//
const dragDocument: any = document.querySelector('.dragModal');
if (dragDocument) {
dragDocument.style.left = 0 + 'px';
dragDocument.style.top = 0 + 'px';
}
}
//
function deleteImage() {}
function deleteImage() {
let content = '确定要删除选择的文件/文件夹吗?';
if (props.previewRecordList.length == 1) {
content = '下列图片只有一个,删除此图片后将会关闭此弹窗,确定要删除选择的文件吗?';
}
createConfirm({
iconType: 'info',
title: '删除',
content: content,
onOk: async () => {
let ids = props.nowPreviewRecord.id;
Deletepic({
ids: ids,
}).then((res) => {
handleSuccess(props.nowPreviewRecord);
createMessage.success(res);
});
},
});
}
// -----------------------------------
//
const copyToClipboard = async (url) => {
try {
await navigator.clipboard.writeText(url);
await navigator.clipboard.writeText(getImgurl(url));
createMessage.success('图片链接已复制到剪贴板');
} catch (err) {
createMessage.error('无法复制图片链接');
@ -619,19 +688,32 @@
};
//
function funAddOrRemoveToMap() {
props.nowPreviewRecord.addOrRemoveToMap = !props.nowPreviewRecord.addOrRemoveToMap;
if (props.nowPreviewRecord.addOrRemoveToMap) {
createMessage.success('在地图上加载成功');
function funShowOnMap() {
if (props.nowPreviewRecord.showOnMap == 1) {
props.nowPreviewRecord.showOnMap = 0;
} else {
createMessage.success('在地图上取消加载成功');
props.nowPreviewRecord.showOnMap = 1;
}
UpdatePicStatus({
id: props.nowPreviewRecord.id,
fileTags: JSON.stringify(fileTags.value),
graffitiJson: JSON.stringify(graffitis.value),
display: props.nowPreviewRecord.display,
showOnMap: props.nowPreviewRecord.showOnMap,
}).then((res) => {
if (props.nowPreviewRecord.showOnMap == 1) {
createMessage.success('在地图上加载成功');
} else {
createMessage.success('在地图上取消加载成功');
}
emits('handleSuccess');
});
}
//
async function fetchAndDownloadImage(url) {
try {
const response = await fetch(url, {
const response = await fetch(getImgurl(url), {
mode: 'cors',
});
if (!response.ok) {
@ -641,7 +723,7 @@
const urlObject = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = urlObject;
link.download = props.nowPreviewRecord.name;
link.download = props.nowPreviewRecord.name || 'download';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
@ -661,7 +743,7 @@
const hideOrShowTextboxFlag = ref(true);
function hideOrShowTextbox(value) {
hideOrShowTextboxFlag.value = value;
emit('setHideOrShowTextboxFlag', value);
emits('setHideOrShowTextboxFlag', value);
}
// ---------------------------------------------------------------
@ -685,110 +767,172 @@
let startY = 0;
let endX = 0;
let endY = 0;
//
let initialMouseX;
let initialMouseY;
let initialDocumentX;
let initialDocumentY;
//
const graffitis: any = ref([]);
const graffitisClone: any = ref([]);
const fileTags: any = ref([]);
watch(
() => props.nowPreviewRecord.id,
() => props.nowPreviewRecord,
() => {
graffitis.value = props.nowPreviewRecord.graffitiJson
? JSON.parse(props.nowPreviewRecord.graffitiJson)
? props.nowPreviewRecord.graffitiJson
: [];
fileTags.value = props.nowPreviewRecord.fileTags ? props.nowPreviewRecord.fileTags : [];
},
{
deep: true,
immediate: true,
},
);
watch(
() => graffitis.value,
() => {},
{
deep: true,
},
);
//
//
function addGraffiti() {
props.nowPreviewRecord.graffitiJson = JSON.stringify(graffitis.value);
graffitis.value.forEach((item) => {
if (!props.nowPreviewRecord.label.includes(item.text)) {
if (item.text && !fileTags.value.includes(item.text)) {
if (item.text) {
props.nowPreviewRecord.label.push(item.text);
fileTags.value.push(item.text);
}
}
});
UpdatePicStatus({
id: props.nowPreviewRecord.id,
fileTags: JSON.stringify(fileTags.value),
graffitiJson: JSON.stringify(graffitis.value),
display: props.nowPreviewRecord.display0,
showOnMap: props.nowPreviewRecord.showOnMap,
}).then((res) => {
emits('handleSuccess');
});
}
//
//
function deleteGraffiti(index = undefined, value = undefined) {
graffitis.value.splice(index, 1);
// or
props.nowPreviewRecord.graffitiJson = JSON.stringify(graffitis.value);
if (!graffitis.value.some((item) => item.text == value)) {
props.nowPreviewRecord.label = props.nowPreviewRecord.label.filter((la) => la != value);
fileTags.value = fileTags.value.filter((la) => la != value);
}
UpdatePicStatus({
id: props.nowPreviewRecord.id,
fileTags: JSON.stringify(fileTags.value),
graffitiJson: JSON.stringify(graffitis.value),
display: props.nowPreviewRecord.display,
showOnMap: props.nowPreviewRecord.showOnMap,
}).then((res) => {
emits('handleSuccess');
});
}
const mouseCanvasRef = ref();
//
function onMouseDown(e) {
if (!graffitiFlag.value) return;
if (nowGraffiti.value != -1) return;
if (graffitis.value.findIndex((item) => item.status == 'mouse') != -1) return;
//
const rect = mouseCanvasRef.value.getBoundingClientRect();
startX = e.x - rect.x;
startY = e.y - rect.y;
isDragging.value = true;
//
graffitis.value.push({
x: startX,
y: startY,
width: 0,
height: 0,
color: graffitiColor.value,
text: '',
status: 'edit',
});
graffitisClone.value = cloneDeep(graffitis.value);
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', onMouseUp);
function onMouseDown(event) {
if (graffitiFlag.value || graffitis.value.some((item) => item.status != 'success')) {
//
if (nowGraffiti.value != -1) return;
if (graffitis.value.findIndex((item) => item.status == 'mouse') != -1) return;
//
const rect = mouseCanvasRef.value.getBoundingClientRect();
startX = event.x - rect.x;
startY = event.y - rect.y;
isDragging.value = true;
//
graffitis.value.push({
x: startX,
y: startY,
width: 0,
height: 0,
color: graffitiColor.value,
text: '',
status: 'edit',
});
graffitisClone.value = cloneDeep(graffitis.value);
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', onMouseUp);
} else {
//
const dragDocument: any = document.querySelector('.dragModal');
isDragging.value = true;
initialMouseX = event.clientX;
initialMouseY = event.clientY;
initialDocumentX = dragDocument.offsetLeft;
initialDocumentY = dragDocument.offsetTop;
dragDocument.style.cursor = 'grabbing';
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', onMouseUp);
}
}
//
function onMouseMove(e) {
const rect = mouseCanvasRef.value.getBoundingClientRect();
if (!isDragging.value) return;
endX = e.x - rect.x;
endY = e.y - rect.y;
if (endX < 0 && endY < 0) {
endX = startX;
endY = startY;
function onMouseMove(event) {
if (graffitiFlag.value || graffitis.value.some((item) => item.status != 'success')) {
//
const rect = mouseCanvasRef.value.getBoundingClientRect();
if (!isDragging.value) return;
endX = event.x - rect.x;
endY = event.y - rect.y;
if (endX < 0 && endY < 0) {
endX = startX;
endY = startY;
}
setMouseData();
} else {
//
const dragDocument: any = document.querySelector('.dragModal');
if (isDragging.value) {
const deltaX = event.clientX - initialMouseX;
const deltaY = event.clientY - initialMouseY;
dragDocument.style.left = initialDocumentX + deltaX + 'px';
dragDocument.style.top = initialDocumentY + deltaY + 'px';
}
}
setMouseData();
}
//
function onMouseUp(e) {
if (!isDragging.value) return;
const rect = mouseCanvasRef.value.getBoundingClientRect();
endX = e.x - rect.x;
endY = e.y - rect.y;
if (endX < 0 && endY < 0) {
endX = startX;
endY = startY;
}
isDragging.value = false;
if (e.x > rect.right || e.y > rect.bottom) {
graffitis.value.splice(graffitis.value.length - 1, 1);
nowGraffiti.value = -1;
function onMouseUp(event) {
if (graffitiFlag.value || graffitis.value.some((item) => item.status != 'success')) {
//
if (!isDragging.value) return;
const rect = mouseCanvasRef.value.getBoundingClientRect();
endX = event.x - rect.x;
endY = event.y - rect.y;
if (endX < 0 && endY < 0) {
endX = startX;
endY = startY;
}
isDragging.value = false;
if (event.x > rect.right || event.y > rect.bottom) {
graffitis.value.splice(graffitis.value.length - 1, 1);
nowGraffiti.value = -1;
} else {
setMouseData();
nowGraffiti.value = graffitis.value.length - 1;
}
window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp);
} else {
setMouseData();
nowGraffiti.value = graffitis.value.length - 1;
//
const dragDocument: any = document.querySelector('.dragModal');
isDragging.value = false;
dragDocument.style.cursor = 'default';
}
}
//
function onWheel(event) {
if (!graffitiFlag.value) {
const delta = event.deltaY || event.detail || event.wheelDelta;
//
if (delta < 0) {
//
scale.value += 0.1;
} else if (scale.value > 0.5) {
//
scale.value -= 0.1;
}
}
window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp);
}
//
@ -838,15 +982,15 @@
const mouseEditType = ref('');
function funMouseDownEdit(e, index, type) {
//
graffitisClone.value = cloneDeep(graffitis.value);
const rect = mouseCanvasRef.value.getBoundingClientRect();
startX = e.x - rect.x;
startY = e.y - rect.y;
isDragging.value = true;
nowGraffiti.value = index;
mouseEditType.value = type;
window.addEventListener('mousemove', funMouseMoveEdit);
window.addEventListener('mouseup', funMouseUpEdit);
// graffitisClone.value = cloneDeep(graffitis.value);
// const rect = mouseCanvasRef.value.getBoundingClientRect();
// startX = e.x - rect.x;
// startY = e.y - rect.y;
// isDragging.value = true;
// nowGraffiti.value = index;
// mouseEditType.value = type;
// window.addEventListener('mousemove', funMouseMoveEdit);
// window.addEventListener('mouseup', funMouseUpEdit);
}
//
function funMouseMoveEdit(e) {
@ -963,7 +1107,10 @@
width: 100%;
height: 100px;
background: #1c1c1c;
display: block;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
.buttonList {
position: relative;
@ -971,7 +1118,7 @@
align-items: center;
justify-content: center;
width: 100%;
height: 40px;
height: 35px;
.button {
position: relative;
@ -997,10 +1144,13 @@
.imageList {
display: inline-flex;
align-items: center;
justify-content: center;
width: 100%;
height: 60px;
// align-items: center;
// justify-content: center;
width: 900px;
height: 65px;
overflow-x: auto;
white-space: nowrap;
position: relative;
.bottom_div {
padding: 5px;
@ -1015,6 +1165,15 @@
margin-right: 5px;
}
}
.imageList::-webkit-scrollbar {
display: block;
height: 2px;
}
.imageList {
scrollbar-width: auto;
scrollbar-color: #888 #f1f1f100;
}
}
//

@ -13,11 +13,8 @@
</span>
<span class="infovalue_name" v-if="!editNameFlag">
<a-input v-model:value="editName" size="small" />
<CheckOutlined
style="margin-left: 10px; color: green"
@click="pressEnterNameFunction"
/>
<CloseOutlined style="margin-left: 10px; color: red" @click="editNameBlur" />
<CheckOutlined style="margin-left: 5px; color: green" @click="pressEnterNameFunction" />
<CloseOutlined style="margin-left: 5px; color: red" @click="editNameBlur" />
</span>
</a-col>
<a-col :span="7">
@ -43,14 +40,20 @@
</a-col>
<a-col :span="17">
<span class="infovalue">
{{ props.nowPreviewRecord.width + '*' + props.nowPreviewRecord.height }}
{{ props.nowPreviewRecord.width + ' x ' + props.nowPreviewRecord.height }}
</span>
</a-col>
<a-col :span="7">
<span class="infotitle">照片大小</span>
</a-col>
<a-col :span="17">
<span class="infovalue">{{ props.nowPreviewRecord.size }} </span>
<span class="infovalue">
{{
props.nowPreviewRecord.size
? (props.nowPreviewRecord.size / 1024 / 1024).toFixed(2) + 'M'
: 0
}}
</span>
</a-col>
<a-col :span="7">
<span class="infotitle">拍摄飞机</span>
@ -74,21 +77,24 @@
<span class="infotitle">拍摄时间</span>
</a-col>
<a-col :span="17">
<span class="infovalue">{{ props.nowPreviewRecord.photographTime }} </span>
<span class="infovalue">{{ props.nowPreviewRecord.createTime }} </span>
</a-col>
<a-col :span="7">
<span class="infotitle">标签</span>
</a-col>
<a-col :span="17">
<span class="infovalue_graffitiNum">
<a-tag color="success" v-for="la in props.nowPreviewRecord.label" :key="la">
<a-tag color="success" v-for="la in props.nowPreviewRecord.fileTags" :key="la">
{{ la }}
</a-tag>
<PlusSquareOutlined style="font-size: 20px; color: #07aaed" @click="addLabelChange" />
<PlusSquareOutlined
style="font-size: 20px; color: #07aaed"
@click="addFileTagsChange"
/>
</span>
<a-modal
title="标签设置"
:open="addLabelFlag"
:open="addFileTagsFlag"
:mask="false"
:maskClosable="false"
:closable="false"
@ -97,24 +103,24 @@
<div style="display: block">
<div
style="display: flex; flex-wrap: wrap; gap: 5px; width: 96%; margin: 10px"
v-if="props.nowPreviewRecord.label.length > 0"
v-if="props.nowPreviewRecord.fileTags.length > 0"
>
已添加的标签
<div
v-for="la in props.nowPreviewRecord.label"
v-for="la in props.nowPreviewRecord.fileTags"
:key="la"
style="border: 1px solid #595959; border-radius: 3px"
>
<span style="margin-left: 5px">{{ la }}</span>
<CloseOutlined
style="margin-left: 5px; margin-right: 5px"
@click="deleteLabel(la)"
@click="deleteFileTags(la)"
/>
</div>
</div>
<div style="display: inline-flex; gap: 5px; width: 96%; margin: 10px">
<a-input v-model:value="newLabelName" size="small" placeholder="请输入标签" />
<a-button type="primary" @click="pressEnterLabelFunction"></a-button>
<a-input v-model:value="newFileTagsName" size="small" placeholder="请输入标签" />
<a-button type="primary" @click="pressEnterFileTagsFunction"></a-button>
</div>
<div
style="
@ -127,8 +133,8 @@
>
<a-button
@click="
addLabelFlag = false;
newLabelName = '';
addFileTagsFlag = false;
newFileTagsName = '';
"
>
关闭
@ -155,9 +161,7 @@
<EditOutlined style="color: #ffffff" />
<span>
{{
props.nowPreviewRecord.graffitiJson
? JSON.parse(props.nowPreviewRecord.graffitiJson).length
: 0
props.nowPreviewRecord.graffitiJson ? props.nowPreviewRecord.graffitiJson.length : 0
}}
</span>
</div>
@ -186,7 +190,7 @@
<a-col :span="17">
<span class="infobutton">
<EnvironmentOutlined
v-if="props.nowPreviewRecord.addOrRemoveToMap"
v-if="props.nowPreviewRecord.showOnMap == 1"
style="font-size: 20px; color: #07aaed"
@click="flyPoint"
/>
@ -208,7 +212,7 @@
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { ref, watch, computed } from 'vue';
import {
EditOutlined,
PlusSquareOutlined,
@ -216,13 +220,18 @@
CheckOutlined,
CloseOutlined,
} from '@ant-design/icons-vue';
import { orgPosGroup } from '@/api/demo/system';
import {
UpdatePicStatus,
Deletepic,
UpdatePicName,
UpdatePicParentKey,
} from '@/api/demo/mediaLibrary';
import { Map } from './preview';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
const props = defineProps(['nowPreviewRecord', 'previewRecordList', 'hideOrShowTextboxFlag']);
const emit = defineEmits(['chooseNowPreviewRecord', 'reloadTable']);
const emits = defineEmits(['chooseNowPreviewRecord', 'handleSuccess']);
// --------------------------------
const editNameFlag = ref(true);
@ -243,21 +252,14 @@
}
let query = {
id: props.nowPreviewRecord.id,
newName: newName,
name: newName,
};
props.nowPreviewRecord.name = newName;
editNameFlag.value = true;
emit('reloadTable');
return;
//
const data = await orgPosGroup(query);
if (data) {
UpdatePicName(query).then((res) => {
props.nowPreviewRecord.name = newName;
editNameFlag.value = true;
emit('reloadTable');
return createMessage.success('修改名称成功');
} else {
return createMessage.error('修改名称失败');
}
createMessage.success(res);
emits('handleSuccess');
});
}
function editNameBlur() {
editNameFlag.value = true;
@ -265,66 +267,68 @@
}
// --------------------------------
const addLabelFlag = ref(false);
const newLabelName = ref('');
function addLabelChange() {
addLabelFlag.value = true;
const addFileTagsFlag = ref(false);
const newFileTagsName = ref('');
const graffitiJson: any = ref([]);
const fileTags: any = ref([]);
watch(
() => props.nowPreviewRecord,
() => {
graffitiJson.value = props.nowPreviewRecord.graffitiJson
? props.nowPreviewRecord.graffitiJson
: [];
fileTags.value = props.nowPreviewRecord.fileTags ? props.nowPreviewRecord.fileTags : [];
},
{
deep: true,
immediate: true,
},
);
function addFileTagsChange() {
addFileTagsFlag.value = true;
}
//
async function pressEnterLabelFunction() {
if (!newLabelName.value) {
async function pressEnterFileTagsFunction() {
if (!newFileTagsName.value) {
return;
}
if (!props.nowPreviewRecord.label.includes(newLabelName.value)) {
props.nowPreviewRecord.label.push(newLabelName.value);
let query = {
if (!fileTags.value.includes(newFileTagsName.value)) {
fileTags.value.push(newFileTagsName.value);
UpdatePicStatus({
id: props.nowPreviewRecord.id,
newLabel: props.nowPreviewRecord.label,
};
addLabelFlag.value = true;
chooseNowPreviewRecord({
...props.nowPreviewRecord,
label: props.nowPreviewRecord.label,
fileTags: JSON.stringify(fileTags.value),
graffitiJson: JSON.stringify(graffitiJson.value),
}).then((res) => {
addFileTagsFlag.value = true;
newFileTagsName.value = '';
emits('handleSuccess');
});
emit('reloadTable');
newLabelName.value = '';
return;
//
const data = await orgPosGroup(query);
if (data) {
addLabelFlag.value = true;
emit('reloadTable');
return createMessage.success('修改名称成功');
} else {
return createMessage.error('修改名称失败');
}
} else {
return createMessage.error('此标签已存在!');
}
}
//
function deleteLabel(value) {
function deleteFileTags(value) {
createConfirm({
iconType: 'info',
title: '提醒',
content: '删除标签【' + value + '】,同标签名的涂鸦标记都会被删除!',
onOk: () => {
props.nowPreviewRecord.label = props.nowPreviewRecord.label.filter(
(item) => item !== value,
);
let json = JSON.parse(props.nowPreviewRecord.graffitiJson);
fileTags.value = fileTags.value.filter((item) => item !== value);
let json = graffitiJson.value;
if (json.some((item) => item.text == value)) {
json = json.filter((item) => item.text !== value);
props.nowPreviewRecord.graffitiJson = JSON.stringify(json);
graffitiJson.value = json;
}
chooseNowPreviewRecord({
...props.nowPreviewRecord,
label: props.nowPreviewRecord.label,
graffitiJson: JSON.stringify(json),
UpdatePicStatus({
id: props.nowPreviewRecord.id,
fileTags: JSON.stringify(fileTags.value),
graffitiJson: JSON.stringify(graffitiJson.value),
}).then((res) => {
emits('handleSuccess');
});
emit('reloadTable');
},
onCancel: () => {},
});
@ -335,7 +339,7 @@
if (props.nowPreviewRecord.graffitiJson) {
const map = {};
// text
JSON.parse(props.nowPreviewRecord.graffitiJson).forEach((item) => {
props.nowPreviewRecord.graffitiJson.forEach((item) => {
const key = item.text;
if (map[key]) {
map[key].num += 1;
@ -352,7 +356,7 @@
//
function chooseNowPreviewRecord(value) {
emit('chooseNowPreviewRecord', value);
emits('chooseNowPreviewRecord', value);
}
// --------------------------------

@ -9,25 +9,15 @@
>
<PathLeftMenu
ref="pathLeftMenuRef"
:pathRecord="props.pathRecord"
:leftMenuShow="leftMenuShow"
:allWorkspaceDataList="allWorkspaceDataList"
:allAnnotationDataList="allAnnotationDataList"
:nowShowAnnotationData="nowShowAnnotationData"
:allAreaDataList="allAreaDataList"
:nowShowAreaData="nowShowAreaData"
:allImageDataList="allImageDataList"
:nowShowImageData="nowShowImageData"
@changeLeftMenuShow="changeLeftMenuShow"
@handlerLocation="handlerLocation"
@closePathModal="closePathModal"
@changeAnnotationInfoShow="changeAnnotationInfoShow"
@setNowShowAnnotationData="setNowShowAnnotationData"
@setNowShowImageData="setNowShowImageData"
@setNowShowAreaData="setNowShowAreaData"
@setAllAnnotationData="setAllAnnotationData"
@setAllAreaData="setAllAreaData"
@deleteAnnotation="deleteAnnotation"
@deleteArea="deleteArea"
/>
</div>
<!-- 地图 -->
@ -36,17 +26,8 @@
ref="pathMapRef"
:allAnnotationDataList="allAnnotationDataList"
:nowShowAnnotationData="nowShowAnnotationData"
:allAreaDataList="allAreaDataList"
:nowShowAreaData="nowShowAreaData"
:allImageDataList="allImageDataList"
:nowShowImageData="nowShowImageData"
@setNowShowAnnotationData="setNowShowAnnotationData"
@setNowShowImageData="setNowShowImageData"
@setNowShowAreaData="setNowShowAreaData"
@setAllAnnotationData="setAllAnnotationData"
@setAllImageData="setAllImageData"
@setAllAreaData="setAllAreaData"
@closePathImageInfo="closePathImageInfo"
/>
</div>
<!-- 地图标注 -->
@ -60,46 +41,19 @@
@deleteAnnotation="deleteAnnotation"
/>
</div>
<!-- 地图作业区域 -->
<!-- <div class="areaInfoDiv" v-if="areaInfoShow">
<PathAreaInfo
:allAreaDataList="allAreaDataList"
:nowShowAreaData="nowShowAreaData"
@setNowShowAreaData="setNowShowAreaData"
@closePathAreaInfo="closePathAreaInfo"
@handlerLocation="handlerLocation"
@deleteArea="deleteArea"
/>
</div> -->
<!-- 地图照片 -->
<!-- <div class="imageInfoDiv" v-if="imageInfoShow">
<PathImageInfo
:allImageDataList="allImageDataList"
:nowShowImageData="nowShowImageData"
@setNowShowImageData="setNowShowImageData"
@closePathImageInfo="closePathImageInfo"
@handlerLocation="handlerLocation"
/>
</div> -->
</div>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue';
import { PathLeftMenu, PathMap, PathAnnotationInfo, PathAreaInfo, PathImageInfo } from './path';
import { PathLeftMenu, PathMap, PathAnnotationInfo } from './path';
import { cloneDeep } from 'lodash-es';
import imageJson from './json/image.json';
import {
GetAnnotationList,
DeleteAnnotation,
GetWorkAreaList,
DeleteWorkArea,
} from '@/api/demo/mediaLibrary';
import { GetWorkspaceList, GetAnnotationList, DeleteAnnotation } from '@/api/demo/mediaLibrary';
import { WktToGeojson, GeojsonToWkt } from '@/components/MapboxMaps/src/WktGeojsonTransform';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
const props = defineProps(['pathRecord']);
const emits = defineEmits(['closePathModal']);
//
const dynamicWidth = computed(() => {
let width = 0;
@ -113,14 +67,6 @@
if (annotationInfoShow.value) {
width += 320;
}
// //
// if (areaInfoShow.value) {
// width += 320;
// }
// //
// if (imageInfoShow.value) {
// width += 720;
// }
return 'calc(100% - ' + width + 'px)';
});
@ -136,9 +82,6 @@
// ----------------------------------------------------
const annotationInfoShow = ref(false);
function changeAnnotationInfoShow() {
annotationInfoShow.value = !annotationInfoShow.value;
}
//
function closePathAnnotationInfo() {
annotationInfoShow.value = false;
@ -148,6 +91,7 @@
//
const nowShowAnnotationData = ref();
const allAnnotationDataList: any = ref([]);
const allWorkspaceDataList: any = ref([]);
//
function setNowShowAnnotationData(value, restore = true) {
if (value.id) {
@ -166,25 +110,30 @@
getAnnotationList();
}
//
async function getAnnotationList(showThis = true) {
allAnnotationDataList.value = await GetAnnotationList({ workspaceid: 1 });
if (allAnnotationDataList.value.length > 0) {
allAnnotationDataList.value.forEach((annotation, index) => {
let geomjson = WktToGeojson(annotation.geom);
annotation = {
...annotation,
properties: JSON.parse(annotation.properties),
geomtype: getGeomType(annotation),
coordinates: geomjson.coordinates,
};
allAnnotationDataList.value[index] = annotation;
function getAnnotationList(showThis = true) {
GetWorkspaceList().then((result1) => {
GetAnnotationList({}).then((result2) => {
allWorkspaceDataList.value = result1;
allAnnotationDataList.value = result2;
if (allAnnotationDataList.value.length > 0) {
allAnnotationDataList.value.forEach((annotation, index) => {
let geomjson = WktToGeojson(annotation.geom);
annotation = {
...annotation,
properties: JSON.parse(annotation.properties),
geomtype: getGeomType(annotation),
coordinates: geomjson.coordinates,
};
allAnnotationDataList.value[index] = annotation;
});
}
if (showThis) {
setTimeout(() => {
pathLeftMenuRef.value.updateShowMenuInfoList('地图标注');
}, 50);
}
});
}
if (showThis) {
setTimeout(() => {
pathLeftMenuRef.value.updateShowMenuInfoList('地图标注');
}, 50);
}
});
}
//
@ -204,103 +153,6 @@
});
}
// ----------------------------------------------------
const areaInfoShow = ref(false);
function changeAreaInfoShow() {
areaInfoShow.value = !areaInfoShow.value;
}
//
function closePathAreaInfo() {
areaInfoShow.value = false;
nowShowAreaData.value = {};
pathMapRef.value.areaRestoreDefault();
}
//
const nowShowAreaData = ref();
const allAreaDataList: any = ref([]);
//
function setNowShowAreaData(value, restore = true) {
if (value.id) {
areaInfoShow.value = true;
} else {
areaInfoShow.value = false;
}
if (restore) {
pathMapRef.value.areaRestoreDefault();
}
nowShowAreaData.value = value;
}
//
function setAllAreaData() {
//
getWorkAreaList();
}
//
async function getWorkAreaList(showThis = true) {
allAreaDataList.value = await GetWorkAreaList({ workspaceid: 1 });
if (allAreaDataList.value.length > 0) {
allAreaDataList.value.forEach((area, index) => {
let geomjson = WktToGeojson(area.geom);
area = {
...area,
properties: JSON.parse(area.properties),
geomtype: getGeomType(area),
coordinates: geomjson.coordinates,
};
allAreaDataList.value[index] = area;
});
}
if (showThis) {
setTimeout(() => {
pathLeftMenuRef.value.updateShowMenuInfoList('地图作业区域');
}, 50);
}
}
//
async function deleteArea(value) {
if (nowShowAreaData.value && nowShowAreaData.value.id == value.id) {
areaInfoShow.value = false;
nowShowAreaData.value = {};
}
DeleteWorkArea({
id: value.id,
}).then((result) => {
if (result) {
//
getWorkAreaList();
createMessage.success('删除成功');
}
});
}
// ----------------------------------------------------
const imageInfoShow = ref(false);
//
function closePathImageInfo() {
imageInfoShow.value = false;
}
//
const nowShowImageData = ref();
const allImageDataList = ref(imageJson);
//
function setNowShowImageData(value) {
if (value.id) {
imageInfoShow.value = true;
} else {
imageInfoShow.value = false;
}
nowShowImageData.value = value;
pathMapRef.value.setNowShowImageByRight();
}
// -----------------------------------------------------------------
//
function closePathModal() {
emits('closePathModal');
}
//
function handlerLocation(position) {
pathMapRef.value.handlerLocation([position.lng, position.lat]);
@ -329,8 +181,6 @@
}
onMounted(() => {
//
getWorkAreaList(false);
getAnnotationList();
});
</script>

@ -1,5 +1,3 @@
export { default as PathLeftMenu } from './pathLeftMenu.vue';
export { default as PathMap } from './pathMap.vue';
export { default as PathImageInfo } from './pathImageInfo.vue';
export { default as PathAnnotationInfo } from './pathAnnotationInfo.vue';
export { default as PathAreaInfo } from './pathAreaInfo.vue';

@ -1,373 +0,0 @@
<template>
<div class="areaInfo">
<a-row>
<a-col :span="24">
<div class="annotationTitle"> 自定义飞行区 </div>
</a-col>
<a-col :span="24">
<div class="annotationTitle">
<!-- 自定义禁降区 -->
<div
v-if="props.nowShowAreaData.type == 'noland'"
:style="{
width: '15px',
height: '15px',
outline: `2px solid #FF9900`,
'margin-left': '2px',
'margin-right': '12px',
}"
/>
<!-- 自定义作业区 -->
<div
v-if="props.nowShowAreaData.type == 'dfence'"
:style="{
width: '13px',
height: '13px',
outline: `2px solid #00FF00`,
'margin-left': '2px',
'margin-right': '12px',
'border-radius': props.nowShowAreaData.geomtype == 'Circle' ? '6.5px' : '0px',
}"
/>
<!-- 自定义限飞区 -->
<div
v-if="props.nowShowAreaData.type == 'nfz'"
:style="{
width: '13px',
height: '13px',
outline: `2px solid #FF0000`,
background: `#FF000055`,
'margin-left': '2px',
'margin-right': '12px',
'border-radius': props.nowShowAreaData.geomtype == 'Circle' ? '6.5px' : '0px',
}"
/>
<a-input v-model:value="nowAreaData.name" style="width: 65%" size="small"></a-input>
<div class="annotationTitleButton" @click="handlerLocation">
<AimOutlined />
</div>
<div class="annotationTitleButton" @click="deleteArea">
<DeleteOutlined />
</div>
</div>
</a-col>
<a-col :span="24">
<div class="annotationPrompt" v-if="props.nowShowAreaData.type == 'noland'">
自定义作业区绘制后飞行器只能在该区域内飞行
</div>
<div class="annotationPrompt" v-if="props.nowShowAreaData.type == 'dfence'">
自定义禁降区绘制后飞行器不能在绘制区域内自动降落
</div>
<div class="annotationPrompt" v-if="props.nowShowAreaData.type == 'nfz'">
自定义作业区绘制后飞行器只能在该区域内飞行
</div>
</a-col>
<a-col :span="24">
<div class="annotationTitle"> 更多信息 </div>
</a-col>
<!-- 启用状态 -->
<a-col :span="6">
<div class="annotationTitle">启用状态</div>
</a-col>
<a-col :span="18">
<div class="annotationContent">
{{ props.nowShowAreaData.state == 0 ? '已启用' : '已禁用' }}
</div>
</a-col>
<!-- 水平周长 -->
<a-col :span="6">
<div class="annotationTitle">水平周长</div>
</a-col>
<a-col :span="18">
<div class="annotationContent"> {{ length.toFixed(2) }}m</div>
</a-col>
<!-- 水平面积 -->
<a-col :span="6">
<div class="annotationTitle">水平面积</div>
</a-col>
<a-col :span="18">
<div class="annotationContent"> {{ area.toFixed(2) }}</div>
</a-col>
<!-- 半径 -->
<a-col :span="6" v-if="props.nowShowAreaData.geomtype == 'Circle'">
<div class="annotationTitle">半径</div>
</a-col>
<a-col :span="18" v-if="props.nowShowAreaData.geomtype == 'Circle'">
<div class="annotationContent">
<a-input v-model:value="nowAreaData.properties.radius" style="width: 100%" size="small">
<template #addonAfter> <span style="color: white">m</span> </template>
</a-input>
</div>
</a-col>
<!-- 绘制者 -->
<a-col :span="6">
<div class="annotationTitle">绘制者</div>
</a-col>
<a-col :span="18">
<div class="annotationContent"> {{ props.nowShowAreaData.createdUser }}</div>
</a-col>
<a-col :span="24">
<div class="area_buttons">
<div class="cancelDiv" @click="closePathAreaInfo"></div>
<div class="startDiv" :class="{ disabled: props.nowShowAreaData }">确认</div>
</div>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { ref, watch, nextTick } from 'vue';
import * as mars3d from 'mars3d';
import * as Cesium from 'mars3d-cesium';
import {
CloseOutlined,
DeleteOutlined,
CheckOutlined,
AimOutlined,
AlignLeftOutlined,
InfoCircleOutlined,
AntDesignOutlined,
ExpandAltOutlined,
BorderOutlined,
LogoutOutlined,
MinusOutlined,
PlusOutlined,
} from '@ant-design/icons-vue';
import {
GetWorkAreaList,
AddWorkArea,
UpdateWorkArea,
DeleteWorkArea,
} from '@/api/demo/mediaLibrary';
import { cloneDeep } from 'lodash-es';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
const props = defineProps(['allAreaDataList', 'nowShowAreaData']);
const emits = defineEmits([
'setNowShowAreaData',
'closePathAreaInfo',
'handlerLocation',
'deleteArea',
]);
const nowAreaData: any = ref(props.nowShowAreaData);
//
function closePathAreaInfo() {
emits('closePathAreaInfo');
}
//
function handlerLocation() {
emits('handlerLocation', {
lng: props.nowShowAreaData.properties.centerPoint[0],
lat: props.nowShowAreaData.properties.centerPoint[1],
});
}
//
function deleteArea() {
createConfirm({
iconType: 'info',
title: '提示',
content: '将会影响到项目内设备的作业范围,是否删除该区域?',
onOk: async () => {
emits('deleteArea', props.nowShowAreaData);
},
});
}
//
const length: any = ref();
const area: any = ref();
watch(
() => nowAreaData.value,
() => {
emits('setNowShowAreaData', nowAreaData.value, false);
},
{
deep: true,
},
);
watch(
() => props.nowShowAreaData,
() => {
nowAreaData.value = props.nowShowAreaData;
if (props.nowShowAreaData.geomtype == 'Polygon') {
//
length.value = mars3d.MeasureUtil.getDistance(nowAreaData.value.coordinates[0]);
//
area.value = mars3d.MeasureUtil.getArea(nowAreaData.value.coordinates[0]);
}
if (props.nowShowAreaData.geomtype == 'Circle') {
//
length.value = 2 * Math.PI * parseFloat(nowAreaData.value.properties.radius);
//
area.value =
Math.PI *
parseFloat(nowAreaData.value.properties.radius) *
parseFloat(nowAreaData.value.properties.radius);
}
},
{
deep: true,
immediate: true,
},
);
</script>
<style lang="less" scoped>
.areaInfo {
//
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE/Edge */
user-select: none;
position: relative;
width: 100%;
height: 100%;
background: #232323;
padding: 15px;
}
.annotationTitle {
display: flex;
align-items: center;
justify-content: flex-start;
color: #ffffff;
font-size: 14px;
min-height: 45px;
height: auto;
width: 100%;
flex-wrap: wrap;
.annotationTitleButton_right {
height: 20px;
width: 20px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12px;
font-size: 18px;
}
.annotationTitleButton {
height: 20px;
width: 20px;
display: flex;
align-items: center;
justify-content: center;
margin-left: 12px;
font-size: 18px;
}
}
.annotationContent {
display: flex;
align-items: center;
justify-content: flex-start;
min-height: 45px;
height: auto;
width: 100%;
flex-wrap: wrap;
color: #ffffff;
}
.annotationButton {
display: flex;
align-items: center;
justify-content: flex-start;
min-height: 45px;
height: auto;
width: 100%;
flex-wrap: wrap;
}
.annotationPrompt {
display: flex;
align-items: center;
justify-content: flex-start;
min-height: 45px;
height: auto;
width: 100%;
flex-wrap: wrap;
color: #ffffff55;
}
.button {
display: flex;
align-items: center;
justify-content: center;
width: 35px;
height: 35px;
background: #3c3c3c;
border-radius: 2px;
&:hover {
background: #5d5f61;
}
}
.button.disabled {
cursor: not-allowed;
opacity: 0.5;
background-color: #ccc;
}
.numDiv {
width: calc(80% - 70px);
display: flex;
align-items: center;
justify-content: center;
.numSpan {
color: #2d8cf0;
font-size: 26px;
font-weight: bold;
&:hover {
text-decoration: underline;
text-decoration-color: #2d8cf0;
}
}
}
//
.area_buttons {
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid #ffffff55;
width: 100%;
height: 68px;
gap: 20px;
.cancelDiv {
display: flex;
align-items: center;
justify-content: center;
background: #3c3c3c;
color: #ffffff;
width: 40%;
height: 32px;
border-radius: 5px;
&:hover {
background: #5d5f61;
}
}
.startDiv {
display: flex;
align-items: center;
justify-content: center;
background: #0960bd;
color: #ffffff;
width: 40%;
height: 32px;
border-radius: 5px;
&:hover {
background: #2a7dc9;
}
}
}
</style>

@ -1,93 +1,11 @@
<template>
<div class="leftMenu">
<div class="leftMenuContent">
<!-- <div class="leftMenuContent_1">
<div class="leftMenu_closeButton">
<a-tooltip placement="right">
<template #title> 关闭弹窗 </template>
<CloseOutlined
style="font-size: 24px; margin: 8px; color: white"
@click="closePathModal"
/>
</a-tooltip>
</div>
<div class="leftMenu_buttonList">
<div
class="leftMenu_buttonList_annotation"
:style="{
background: showMenuInfoName == '地图标注' ? '#2D8CF0' : '#1a375a',
}"
@click="
showMenuInfoName = '地图标注';
updateShowMenuInfoList(showMenuInfoName);
showMenuInfoList = filterAfterAnnotationDataList;
"
>
<a-tooltip placement="right">
<template #title> 地图标注 </template>
<AntDesignOutlined style="font-size: 24px; margin: 8px; color: white" />
</a-tooltip>
</div>
<div
class="leftMenu_buttonList_image"
:style="{
background: showMenuInfoName == '地图照片' ? '#2D8CF0' : '#1a375a',
}"
@click="
showMenuInfoName = '地图照片';
updateShowMenuInfoList(showMenuInfoName);
"
>
<a-tooltip placement="right">
<template #title> 地图照片 </template>
<EnvironmentOutlined style="font-size: 24px; margin: 8px; color: white" />
</a-tooltip>
</div>
<div
class="leftMenu_buttonList_area"
:style="{
background: showMenuInfoName == '地图作业区域' ? '#2D8CF0' : '#1a375a',
}"
@click="
showMenuInfoName = '地图作业区域';
updateShowMenuInfoList(showMenuInfoName);
showMenuInfoList = filterAfterAreaDataList;
"
>
<a-tooltip placement="right">
<template #title> 地图作业区域 </template>
<CodeSandboxOutlined style="font-size: 24px; margin: 8px; color: white" />
</a-tooltip>
</div>
</div>
</div> -->
<div class="leftMenuContent_2" v-if="leftMenuShow">
<div class="leftMenuContent_title">
{{ showMenuInfoName }}
</div>
<div class="leftMenuContent_list">
<!-- 地图作业区域 -->
<!-- <div v-if="showMenuInfoName == '地图作业区域'" style="margin: 10px">
<a-select
v-model:value="areatype"
style="width: 120px; margin-right: 15px"
@change="handleChangeAreaSelect"
>
<a-select-option value="all">全部类型</a-select-option>
<a-select-option value="dfence">全部作业区</a-select-option>
<a-select-option value="nfz">全部限飞区</a-select-option>
<a-select-option value="noland">全部禁降区</a-select-option>
</a-select>
<a-select
v-model:value="areastate"
style="width: 120px"
@change="handleChangeAreaSelect"
>
<a-select-option value="all">全部状态</a-select-option>
<a-select-option value="0">已启用</a-select-option>
<a-select-option value="1">已禁用</a-select-option>
</a-select>
</div> -->
<!-- 列表 -->
<div v-for="show in showMenuInfoList" :key="show.id">
<!-- 地图标注 -->
@ -154,217 +72,6 @@
</a-tooltip>
</div>
</div>
<!-- 地图照片 -->
<!-- <div
class="showMenuInfo_image"
v-if="showMenuInfoName == '地图照片'"
:style="{
background:
props.nowShowImageData && props.nowShowImageData.id == show.id
? '#274D75'
: show.mouse
? '#393939'
: '',
}"
>
<FileImageOutlined />
<div
class="eye"
@click="show.is_displayed = !show.is_displayed"
:style="{ background: show.is_displayed ? '#2d8cf0' : '#000000' }"
>
<EyeOutlined v-if="show.is_displayed" style="color: #ffffff; font-size: 16px" />
<EyeInvisibleOutlined
v-if="!show.is_displayed"
style="color: #ffffff; font-size: 16px"
/>
</div>
<a-tooltip placement="top">
<template #title>
<span> {{ show.name }}</span>
</template>
<div
:style="{
width: show.mouse ? '160px' : '210px',
'white-space': 'nowrap',
overflow: 'hidden',
'text-overflow': 'ellipsis',
}"
@click="setNowShowImageData(show)"
>
{{ show.name }}
</div>
</a-tooltip>
<div class="buttonRight2" v-if="show.mouse">
<a-tooltip placement="top">
<template #title>
<span>回中</span>
</template>
<AimOutlined @click="handlerLocation(show)" />
</a-tooltip>
</div>
<div class="buttonRight1" v-if="show.mouse">
<a-tooltip placement="top">
<template #title>
<span>
{{ show.show_on_map ? '在地图上取消加载' : '在地图上加载' }}
</span>
</template>
<div style="display: flex; align-items: center">
<svg
v-if="show.show_on_map"
@click="funAddOrRemoveToMap(show)"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 24 24"
width="18"
height="18"
>
<path
d="M19 5v11.17l2 2V5c0-1.1-.9-2-2-2H5.83l2 2H19zM2.81 2.81L1.39 4.22L3 5.83V19c0 1.1.9 2 2 2h13.17l1.61 1.61l1.41-1.41L2.81 2.81zM5 19V7.83l7.07 7.07l-.82 1.1L9 13l-3 4h8.17l2 2H5z"
fill="#ffffff"
></path>
</svg>
<svg
v-if="!show.show_on_map"
@click="funAddOrRemoveToMap(show)"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 24 24"
width="18"
height="18"
>
<path
d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4.86 8.86l-3 3.87L9 13.14L6 17h12l-3.86-5.14z"
fill="#ffffff"
></path>
</svg>
</div>
</a-tooltip>
</div>
</div> -->
<!-- 地图作业区域 -->
<!-- <div
v-if="showMenuInfoName == '地图作业区域'"
class="showMenuInfo_area"
:style="{
outline:
props.nowShowAreaData && props.nowShowAreaData.id == show.id
? '2px solid #2D8CF0'
: '',
background: props.nowShowAreaData && show.state == 0 ? '#3c3c3c' : '#3c3c3c55',
}"
>
<a-tooltip placement="right">
<template #title> {{ show.name }} </template>
<div
class="name"
@click="setNowShowAreaData(show)"
:style="{
color: show.state == 0 ? '#ffffff' : '#ffffff55',
}"
>
{{ show.name }}
</div>
</a-tooltip>
<div
class="type"
@click="setNowShowAreaData(show)"
:style="{
color: show.state == 0 ? '#ffffff' : '#ffffff55',
}"
>
<div
v-if="show.type == 'noland'"
:style="{
width: '13px',
height: '13px',
outline: `2px solid #FF9900`,
'margin-right': '6px',
}"
/>
<div
v-if="show.type == 'dfence'"
:style="{
width: '13px',
height: '13px',
outline: `2px solid #00FF00`,
'margin-right': '6px',
'border-radius': show.geomtype == 'Circle' ? '6.5px' : '0px',
}"
/>
<div
v-if="show.type == 'nfz'"
:style="{
width: '13px',
height: '13px',
outline: `2px solid #FF0000`,
background: `#FF000055`,
'margin-right': '6px',
'border-radius': show.geomtype == 'Circle' ? '6.5px' : '0px',
}"
/>
<span>{{ getType(show.type) }}</span>
</div>
<div class="buttonlist">
<div class="button" v-if="show.state == 1">
<a-popconfirm
title="将会影响到项目内设备的作业范围,是否启用该区域?"
ok-text="启用"
cancel-text="取消"
placement="right"
@confirm="enableThisArea(show)"
>
<a-tooltip placement="top">
<template #title>
<span>可点击启用该区域</span>
</template>
<CheckCircleOutlined />
</a-tooltip>
</a-popconfirm>
</div>
<div class="button" v-if="show.state == 0">
<a-popconfirm
title="将会影响到项目内设备的作业范围,是否禁用该区域?"
ok-text="禁用"
cancel-text="取消"
placement="right"
@confirm="disableThisArea(show)"
>
<a-tooltip placement="top">
<template #title>
<span>可点击禁用该区域</span>
</template>
<StopOutlined />
</a-tooltip>
</a-popconfirm>
</div>
<div class="button">
<a-tooltip placement="top">
<template #title>
<span>回中</span>
</template>
<AimOutlined @click="handlerLocation(show)" />
</a-tooltip>
</div>
<div class="button">
<a-popconfirm
title="将会影响到项目内设备的作业范围,是否删除该区域?"
ok-text="删除"
cancel-text="取消"
placement="right"
@confirm="deleteArea(show)"
>
<a-tooltip placement="top">
<template #title>
<span>删除</span>
</template>
<DeleteOutlined />
</a-tooltip>
</a-popconfirm>
</div>
</div>
</div> -->
</div>
</div>
</div>
@ -379,12 +86,9 @@
<script lang="ts" setup>
import { ref, watch } from 'vue';
import {
CloseOutlined,
AntDesignOutlined,
DoubleLeftOutlined,
DoubleRightOutlined,
EnvironmentOutlined,
CodeSandboxOutlined,
ExpandAltOutlined,
BorderOutlined,
LogoutOutlined,
@ -392,9 +96,6 @@
EyeInvisibleOutlined,
AimOutlined,
DeleteOutlined,
FileImageOutlined,
CheckCircleOutlined,
StopOutlined,
} from '@ant-design/icons-vue';
import { UpdateWorkArea, UpdateAnnotation } from '@/api/demo/mediaLibrary';
import { cloneDeep } from 'lodash-es';
@ -402,27 +103,17 @@
const { createMessage, createConfirm } = useMessage();
const props = defineProps([
'pathRecord',
'leftMenuShow',
'allWorkspaceList',
'allAnnotationDataList',
'nowShowAnnotationData',
'allImageDataList',
'nowShowImageData',
'allAreaDataList',
'nowShowAreaData',
]);
const emits = defineEmits([
'changeLeftMenuShow',
'handlerLocation',
'closePathModal',
'changeAnnotationInfoShow',
'setNowShowAnnotationData',
'setNowShowImageData',
'setNowShowAreaData',
'setAllAreaData',
'setAllAnnotationData',
'deleteAnnotation',
'deleteArea',
]);
const showMenuInfoList = ref(props.allAnnotationDataList);
const showMenuInfoName = ref('地图标注');
@ -430,22 +121,13 @@
if (type == '地图标注') {
handleChangeAnnotationSearch();
}
if (type == '地图照片') {
showMenuInfoList.value = props.allImageDataList;
}
if (type == '地图作业区域') {
handleChangeAreaSelect();
}
}
// -
function changeLeftMenuShow() {
emits('changeLeftMenuShow');
}
// -
function closePathModal() {
emits('closePathModal');
}
// -
function funAddOrRemoveToMap(show) {
show.show_on_map = !show.show_on_map;
@ -503,125 +185,14 @@
});
}
// -------------------------------------------------
// -
const areatype = ref('all');
const areastate = ref('all');
// -
function getType(type) {
let name = '';
switch (type) {
case 'nfz':
name = '自定义限飞区';
break;
case 'dfence':
name = '自定义作业区';
break;
case 'noland':
name = '自定义禁降区';
break;
}
return name;
}
// -
const filterAfterAreaDataList = ref(props.allAreaDataList);
function handleChangeAreaSelect() {
let filterAreaData = props.allAreaDataList;
if (areatype.value !== 'all') {
filterAreaData = filterAreaData.filter((item) => item.type == areatype.value);
}
if (areastate.value !== 'all') {
filterAreaData = filterAreaData.filter((item) => item.state == areastate.value);
}
filterAfterAreaDataList.value = filterAreaData;
showMenuInfoList.value = filterAfterAreaDataList.value;
}
// -
function enableThisArea(value) {
setNowShowAreaData({
...value,
state: 0,
});
UpdateWorkArea({
...value,
properties: JSON.stringify(value.properties),
state: 0,
}).then((res) => {
emits('setAllAreaData');
});
}
// -
function disableThisArea(value) {
setNowShowAreaData({
...value,
state: 1,
});
UpdateWorkArea({
...value,
properties: JSON.stringify(value.properties),
state: 1,
}).then((res) => {
emits('setAllAreaData');
});
}
// -
function deleteArea(show) {
emits('deleteArea', show);
}
//
function setNowShowAnnotationData(value) {
emits('setNowShowAnnotationData', value);
}
//
function setNowShowImageData(value) {
emits('setNowShowImageData', value);
}
//
function setNowShowAreaData(value) {
emits('setNowShowAreaData', value);
}
// ------------------------------------------------------------------
//
function handlerLocation(position) {
// if (showMenuInfoName.value == '') {
// let coordinates = position.coordinates;
// switch (position.type) {
// case 0:
// emits('handlerLocation', {
// lng: coordinates[0],
// lat: coordinates[1],
// });
// break;
// case 1:
// emits('handlerLocation', {
// lng: coordinates[0][0],
// lat: coordinates[0][1],
// });
// break;
// case 2:
// emits('handlerLocation', {
// lng: coordinates[0][0][0],
// lat: coordinates[0][0][1],
// });
// break;
// case 3:
// emits('handlerLocation', {
// lng: coordinates[0],
// lat: coordinates[1],
// });
// break;
// }
// }
// if (showMenuInfoName.value == '') {
// emits('handlerLocation', {
// lng: position.photo_position.lng,
// lat: position.photo_position.lat,
// });
// }
if (showMenuInfoName.value == '地图作业区域') {
if (showMenuInfoName.value == '地图标注') {
if (position.geomtype == 'Circle') {
emits('handlerLocation', {
lng: position.properties.centerPoint[0],

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save