-

-

-

-

-

-

+
+
+
+
-
-
@@ -722,7 +760,7 @@ function getFileSuffix(name: any) {
style="display: flex;display: -webkit-flex;justify-content: space-between;-webkit-justify-content: space-between; ">

-

@@ -755,14 +793,14 @@ function getFileSuffix(name: any) {
-
-
+
@@ -902,7 +940,7 @@ function getFileSuffix(name: any) {
align-items: center;
justify-content: space-between;
font-size: 14px;
- padding:8px;
+ padding: 8px;
.img_tree {
display: flex;
@@ -946,4 +984,20 @@ function getFileSuffix(name: any) {
padding: 0px !important;
}
}
+.preview-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.file-icon {
+ cursor: pointer;
+ width: 20px;
+ height: 20px;
+ transition: opacity 0.2s;
+}
+
+.file-icon:hover {
+ opacity: 0.8;
+}
diff --git a/web/src/views/special/project/index.vue b/web/src/views/special/project/index.vue
index 4d338e3..d3c975f 100644
--- a/web/src/views/special/project/index.vue
+++ b/web/src/views/special/project/index.vue
@@ -9,6 +9,7 @@ import { onMounted, ref } from "vue";
import { ElMessage, ElMessageBox } from 'element-plus'
import Page from '@/components/Pagination/page.vue'
import { projectPage, addSdproject, updateSdproject, deleteSdprojectById, deleteSdprojectByIds } from "@/api/project";
+import { getDict } from '@/api/dict'
//定义表格数据
const tableData: any = ref([{}, {}]);
// 查询数据
@@ -33,6 +34,13 @@ function getdata() {
total.value = res.data.total
})
}
+//获取字典项目类型
+const dictType = ref([])
+function getDictOne() {
+ getDict({ dictcode: 'zxxmlx' }).then((res: any) => {
+ dictType.value = res.data
+ })
+}
//弹框命名
const title = ref("")
//控制弹框显隐
@@ -80,7 +88,7 @@ function delproject(row: any) {
})
})
-
+
}
//表格多选
const tableIdarr = ref([])
@@ -104,14 +112,14 @@ function delprojectArr() {
)
.then(() => {
deleteSdprojectByIds({ ids: ids.join(',') }).then((res: any) => {
- if(res.code == 0){
+ if (res.code == 0) {
ElMessage({
- type: 'success',
- message: '删除成功',
- })
- getdata()
+ type: 'success',
+ message: '删除成功',
+ })
+ getdata()
}
-
+
})
})
@@ -164,8 +172,18 @@ const moderules = ref({
});
onMounted(() => {
getdata()
+ getDictOne()
});
-
+//项目类型转换
+function typeName(arr:any,itemCode:any){
+ let nameone:any
+ arr.forEach((item:any) => {
+ if(item.itemcode==itemCode){
+ nameone = item.dictname
+ }
+ });
+ return nameone
+}
@@ -176,8 +194,11 @@ onMounted(() => {
-
+
+
+
+
搜索
@@ -195,7 +216,11 @@ onMounted(() => {
-
+
+
+ {{ typeName(dictType,scope.row.projectType) }}
+
+
@@ -223,7 +248,10 @@ onMounted(() => {
-
+
+
+
+
diff --git a/web/src/views/testdata/datamanagement/index.vue b/web/src/views/testdata/datamanagement/index.vue
index 01b1622..05b61bb 100644
--- a/web/src/views/testdata/datamanagement/index.vue
+++ b/web/src/views/testdata/datamanagement/index.vue
@@ -1,6 +1,6 @@
@@ -8,15 +8,29 @@ export default {
import { ref, onMounted, nextTick, defineAsyncComponent } from "vue";
import { Search } from '@element-plus/icons-vue'
import { useAppStore } from '@/store/modules/app';
+import { useUserStore } from '@/store/modules/user';
import { ElMessageBox, ElMessage, ElMain } from "element-plus";
import Page from '@/components/Pagination/page.vue';
import AudioPlayer from '@/components/file/preview/AudioPlayer.vue';
import { batchDeleteReq } from "@/api/file-operator";
-import { tstaskList, getTsNodesTree, addTsNodes, updateTsNodes, deleteTsNodesById, tsFilesPage, addTsFiles, updateTsFiles, deleteTsFilesById, listTsFiles, deleteTsFilesByIds, compress, Decompression, compare, downloadToLocal, uploadToBackup, addTsFile, list, moveFileFolder, copyFileFolder } from "@/api/datamanagement";
+import { tstaskList, getTsNodesTree, addTsNodes, updateTsNodes, deleteTsNodesById, tsFilesPage, addTsFiles, updateTsFiles, deleteTsFilesById, listTsFiles, deleteTsFilesByIds, compress, Decompression, compare, downloadToLocal, uploadToBackup, addTsFile, list, moveFileFolder, copyFileFolder, startSimpleNavi } from "@/api/datamanagement";
import ZUpload from '@/components/file/ZUpload.vue'
import useFileUpload from "@/components/file/file/useFileUpload";
import useHeaderStorageList from "@/components/header/useHeaderStorageList";
import useFileData from "@/components/file/file/useFileData";
+//轨迹图
+import MapChart from '@/components/trajectory/index.vue';
+import Echart from '@/components/trajectory/echarts.vue';
+// 在顶部添加导入
+import PDFImg from '@/assets/fileimg/PDF.png'
+import WordImg from '@/assets/fileimg/word.png'
+import ExcelImg from '@/assets/fileimg/excel.png'
+import PPTImg from '@/assets/fileimg/ppt.png'
+import ZipImg from '@/assets/fileimg/zip.png'
+import Mp3Img from '@/assets/fileimg/mp3.png'
+import Mp4Img from '@/assets/fileimg/mp4.png'
+import ImageImg from '@/assets/fileimg/img.png'
+import TextImg from '@/assets/fileimg/text_line.png'
// 文件预览相关
import Viewfile from '@/views/component/Viewfile.vue'
@@ -30,6 +44,7 @@ const { dialogVideoVisible, dialogTextVisible, dialogPdfVisible, dialogOfficeVis
const { clearALlFinishedUploadFile } = useFileUpload();
const { currentStorageKey } = useHeaderStorageList();
const { openRow } = useFileData();
+const userStore = useUserStore();
onMounted(() => {
getProject()
});
@@ -107,7 +122,9 @@ const projectForme: any = ref({
})
//用户弹窗规则定义
const moderules = ref({
- nodeName: [{ required: true, message: "请输入节点名称", trigger: "blur" }],
+ nodeName: [{ required: true, message: "请输入节点名称", trigger: "blur" },
+ { pattern: /^[^<>:"/\\|?*]*$/, message: "名称不能包含特殊字符 [<>:\"/\\\\|?*]", trigger: "blur" }
+ ],
});
//新增子项目
function addSubItem(row: any) {
@@ -379,7 +396,7 @@ function delfile(row: any) {
}
)
.then(() => {
- deleteTsFilesById({ id: row.id,type:'local' }).then((res: any) => {
+ deleteTsFilesById({ id: row.id, type: 'local' }).then((res: any) => {
if (res.code == 0) {
getdata()
ElMessage({
@@ -414,7 +431,7 @@ function delprojectArr() {
}
)
.then(() => {
- deleteTsFilesByIds({ ids: ids.join(','),type:'local' }).then((res: any) => {
+ deleteTsFilesByIds({ ids: ids.join(','), type: 'local' }).then((res: any) => {
if (res.code == 0) {
ElMessage({
type: 'success',
@@ -973,7 +990,9 @@ const renameobj = ref({
fileName: ''
})
const renameRules = ref({
- fileName: [{ required: true, message: "请输入文件名称", trigger: "blur" }],
+ fileName: [{ required: true, message: "请输入文件名称", trigger: "blur" },
+ { pattern: /^[^<>:"/\\|?*]*$/, message: "名称不能包含特殊字符 [<>:\"/\\\\|?*]", trigger: "blur" }
+ ],
});
const rowarr: any = ref()
function renames(row: any) {
@@ -1047,7 +1066,9 @@ const creatform = ref({
workPath: ''
})
const creatrules = ref({
- fileName: [{ required: true, message: "请输入文件/文件夹名称", trigger: "blur" }],
+ fileName: [{ required: true, message: "请输入文件/文件夹名称", trigger: "blur" },
+ { pattern: /^[^<>:"/\\|?*]*$/, message: "名称不能包含特殊字符 [<>:\"/\\\\|?*]", trigger: "blur" }
+ ],
});
function creatFile() {
creat.value = true
@@ -1086,7 +1107,7 @@ async function submitcreat(formEl: any) {
//路径导航条
const patharr = ref([])
function pathclick(row: any, index: any) {
-
+
patharr.value.splice(index + 1)
creatform.value.parentId = row.id
creatform.value.workPath = convertArrayToPath1(patharr.value)
@@ -1099,9 +1120,16 @@ const visible = ref(false)
const ziprules = ref({
ids: [{ required: true, message: "请选择文件", trigger: "blur" }],
compressedFormat: [{ required: true, message: "请选择压缩格式", trigger: "blur" }],
- compressedName: [{ required: true, message: "请输入压缩文件名", trigger: "blur" }],
+ compressedName: [{ required: true, message: "请输入压缩文件名", trigger: "blur" },
+ { pattern: /^[^<>:"/\\|?*]*$/, message: "名称不能包含特殊字符 [<>:\"/\\\\|?*]", trigger: "blur" }
+ ],
compressedPath: [{ required: true, message: "请输入压缩文件路径", trigger: "blur" }],
})
+const modelarules = ref({
+ fileName: [{ required: true, message: "请输入文件/文件夹名称", trigger: "blur" },
+ { pattern: /^[^<>:"/\\|?*]*$/, message: "名称不能包含特殊字符 [<>:\"/\\\\|?*]", trigger: "blur" }
+ ]
+})
const ziptypearr = ref([])
const zipObj: any = ref({
ids: '',
@@ -1160,7 +1188,7 @@ async function submitzip(formEl: any) {
})
} else {
// loading.value = true
- Decompression({ id: jiezip.value.id, parentId: zipParentid.value, decompressionPath: jieFilearr.value.workPath?jieFilearr.value.workPath : filetsobj.value.path }).then((res: any) => {
+ Decompression({ id: jiezip.value.id, parentId: zipParentid.value, decompressionPath: jieFilearr.value.workPath ? jieFilearr.value.workPath : filetsobj.value.path }).then((res: any) => {
if (res.code == 0) {
ElMessage.success('解压成功')
// // gettreedata()
@@ -1169,7 +1197,7 @@ async function submitzip(formEl: any) {
zipfiles.value = false
tableIdarr.value.length = 0
}
- jieFilearr.value.workPath = ''
+ jieFilearr.value.workPath = ''
})
}
@@ -1183,7 +1211,7 @@ function zipClose() {
}
//查询文件夹
const listFilesarr = ref([])
-const filetsobj:any = ref({
+const filetsobj: any = ref({
id: '',
path: '',
})
@@ -1231,7 +1259,7 @@ function fileSelection(row: any) {
jieFilearr.value = row[0]
}
function pathFile(index: any) {
-
+
jiepatharr.value.splice(index + 1)
filetsobj.value.path = convertArrayToPath(jiepatharr.value)
gettsfiles()
@@ -1284,7 +1312,7 @@ function convertPathToArray(fullPath: string): string[] {
}
// 路径转换方法(数组转路径)
function convertArrayToPath(segments: string[]): string {
-
+
// 处理空数组返回根路径
if (segments.length === 0) return '/'
@@ -1292,13 +1320,13 @@ function convertArrayToPath(segments: string[]): string {
return '/' + segments.filter(Boolean).join('/') + '/'
}
function convertArrayToPath1(segments: string[]): string {
-
+
// 处理空数组返回根路径
if (segments.length === 0) return '/'
// 过滤空值并拼接路径
-
- return '/' + segments.map((item:any) => item.fileName).join('/') + '/'
+
+ return '/' + segments.map((item: any) => item.fileName).join('/') + '/'
}
function removeSuffix(filename: any) {
// 使用正则表达式匹配文件名中的后缀部分
@@ -1315,6 +1343,137 @@ function removeSuffix(filename: any) {
// 如果没有找到后缀,则返回原文件名
return filename;
}
+// 修改映射表
+const FILE_ICONS = {
+ pdf: PDFImg,
+ doc: WordImg,
+ docx: WordImg,
+ xls: ExcelImg,
+ xlsx: ExcelImg,
+ ppt: PPTImg,
+ pptx: PPTImg,
+ zip: ZipImg,
+ rar: ZipImg,
+ gz: ZipImg,
+ bz2: ZipImg,
+ tar: ZipImg,
+ // tar.gz: ZipImg,
+ xz: ZipImg,
+ mp3: Mp3Img,
+ mp4: Mp4Img,
+ avi: Mp4Img,
+ png: ImageImg,
+ jpg: ImageImg,
+ jpeg: ImageImg,
+ gif: ImageImg,
+ txt: TextImg
+};
+// 获取文件图标
+const fileIcon = (row: any) => {
+ const ext = row.fileName.split('.').pop()?.toLowerCase() || 'unknown';
+ return FILE_ICONS[ext as keyof typeof FILE_ICONS] || (row.type == 'ZIP' ? ZipImg : TextImg);
+};
+// 判断是否可预览(基于文件图标映射表)
+const shouldPreview = (rwo: any): boolean => {
+ // 获取文件扩展名并转为小写,兼容无扩展名情况
+ const fileExtension = rwo.fileName.split('.').pop()?.toLowerCase() || '';
+
+ // 通过 keyof 类型保护确保类型安全
+ return Object.keys(FILE_ICONS).includes(fileExtension);
+};
+
+const mapTrajectory = ref(false)
+
+const fredid = ref('')
+function openMap(row: any) {
+ fredid.value = row.id
+ getSSELink()
+ // setInterval(() => {
+ // lineData.value = lineData.value.map(d => ({
+ // x: d.x,
+ // y: Math.random() * 10
+ // }));
+ // }, 2000);
+ mapTrajectory.value = true
+}
+function mapClose() {
+ mapTrajectory.value = false
+ eventSource.value?.close()
+}
+// 1s/10s/30s/1m/2m/5m
+const options = ref([
+ {
+ name: '1秒'
+ , id: 1
+ },
+ {
+ name: '10秒'
+ , id: 10
+ },
+ {
+ name: '30秒'
+ , id: 30
+ },
+ {
+ name: '1分钟'
+ , id: 60
+ },
+ {
+ name: '2分钟'
+ , id: 120
+ },
+ {
+ name: '5分钟'
+ , id: 300
+ },
+])
+const maptime: any = ref(300)
+//频率
+function frequency(row: any) {
+ startSimpleNavi({ samTimes: maptime.value, id: fredid.value, token: userStore.Token }).then((res: any) => {
+ if (res.code == '0' && row) {
+ ElMessage.success("切换成功")
+ }
+ })
+}
+//sse处理
+const eventSource = ref(null)
+const dynamicCoordinates = ref([])
+function getSSELink() {
+ if (eventSource.value) {
+ eventSource.value?.close()
+ }
+ eventSource.value = new EventSource(userStore.webApiBaseUrl + '/sse/connect/' + userStore.Token)
+ eventSource.value.addEventListener('open', () => {
+ frequency(false)
+ console.log('链接成功')
+ });
+ // 监听消息
+ eventSource.value.addEventListener('message', (e: MessageEvent) => {
+ try {
+ const data = JSON.parse(e.data)
+ console.log('SSE消息:', data)
+ if(data){
+ data.forEach((item: any) => {
+ dynamicCoordinates.value.push([item.lon, item.lat])
+ lineData.value.push({x:item.UtcTime,y:item.alt})
+ })
+ }
+
+
+ } catch (err) {
+ console.error('消息解析失败:', err)
+ }
+ })
+ // 错误处理
+ eventSource.value.onerror = (err: any) => {
+ console.error('SSE Error:', err)
+ setTimeout(getSSELink, 5000)
+ }
+}
+// 示例数据格式
+const lineData:any = ref([])
+const tabbas = ref('1')
@@ -1394,7 +1553,7 @@ function removeSuffix(filename: any) {
style="width: 100%; height: calc(66vh);margin-bottom: 20px;" border>
-
+
{{ scope.row.fileName }}
{{ scope.row.fileName }}
@@ -1403,32 +1562,26 @@ function removeSuffix(filename: any) {
-
-
-

-

-

-

-

-

+
+
+

+
-
-
+
-
+
+
-
-
@@ -1466,14 +1617,14 @@ function removeSuffix(filename: any) {
-
-
+
@@ -1576,7 +1727,7 @@ function removeSuffix(filename: any) {
-
+
@@ -1694,6 +1845,30 @@ function removeSuffix(filename: any) {
+
+
+
+
+ 设定采样频率:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1728,7 +1903,6 @@ function removeSuffix(filename: any) {
-