工具-数据对接

main
ysn 2 days ago
parent ece3b41942
commit f8ef13d049
  1. 2
      .env.development
  2. 2
      .env.production
  3. 2
      .env.staging
  4. 8
      src/api/login.js
  5. 2
      src/permission.js
  6. 365
      src/views/utility/index.vue
  7. 4
      src/views/videoCommunication/index.vue
  8. 6
      vue.config.js

@ -5,7 +5,7 @@ VUE_APP_TITLE = 信联
ENV = 'development'
# 修改为你真实的接口前缀
VUE_APP_BASE_API = '/api_admin/v1'
VUE_APP_BASE_API = '/api/v1'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true

@ -5,4 +5,4 @@ VUE_APP_TITLE = 信联
ENV = 'production'
# 信联/生产环境
VUE_APP_BASE_API = '/prod-api'
VUE_APP_BASE_API = '/api/v1'

@ -9,4 +9,4 @@ NODE_ENV = production
ENV = 'staging'
# 信联/测试环境
VUE_APP_BASE_API = '/stage-api'
VUE_APP_BASE_API = '/api/v1'

@ -58,3 +58,11 @@ export function getCodeImg() {
timeout: 20000
})
}
// 获取网络配置
export function getCommonConfigOptions(data) {
return request({
url: '/common/config/options',
method: 'post',
data: data
})
}

@ -37,12 +37,14 @@ router.beforeEach((to, from, next) => {
isRelogin.show = true
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => {
store.dispatch('GetNetConfig').then(res => {
isRelogin.show = false
store.dispatch('GenerateRoutes').then(accessRoutes => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
})
}).catch(err => {
store.dispatch('LogOut').then(() => {
Message.error(err)

@ -9,179 +9,351 @@
style="float: right; padding: 3px 0"
type="text"
icon="el-icon-delete"
@click="handleClearRecords"
:disabled="groupedRecords.length === 0"
@click="handleClearAll"
>
清空记录
</el-button>
</div>
<div v-for="(dateItem, index) in transferDataList" :key="index">
<div v-loading="loading" class="container">
<template v-if="groupedRecords.length > 0">
<div v-for="(group, index) in groupedRecords" :key="index">
<!-- 日期分割线 -->
<el-divider>
<el-tag type="info">{{ dateItem.date }}</el-tag>
<el-tag type="info">
{{ group.date }} ({{ group.items.length }})
</el-tag>
</el-divider>
<!-- 传输记录表格 -->
<el-table :data="dateItem.list" :show-header="false">
<el-table :data="group.items" :show-header="false">
<el-table-column label="缩略图标" width="80" align="center">
<template slot-scope="scope">
<div class="video-thumb">
<i class="el-icon-video-camera" />
<div class="file-thumb">
<i :class="getFileIconClass(scope.row.file_name)" />
</div>
</template>
</el-table-column>
<el-table-column prop="name" label="文件名" show-overflow-tooltip />
<el-table-column
prop="size"
label="文件大小"
width="120"
align="center"
prop="file_name"
label="文件名"
show-overflow-tooltip
/>
<el-table-column
prop="progress"
label="上传进度"
width="200"
label="文件大小"
width="100"
align="center"
show-overflow-tooltip
>
<template slot-scope="scope">
<el-progress :percentage="scope.row.progress" stroke-width="8" />
{{ formatFileSize(scope.row.file_size) }}
</template>
</el-table-column>
<el-table-column label="进度" width="150" align="center">
<template slot-scope="scope">
<div class="progress-container">
<el-progress :percentage="scope.row.is_success ? 100 : 0" />
</div>
</template>
</el-table-column>
<el-table-column
prop="time"
label="上传时间"
width="100"
width="80"
align="center"
show-overflow-tooltip
/>
<el-table-column
prop="status"
label="上传状态"
width="100"
align="center"
>
<template slot-scope="scope">
{{ formatTime(scope.row.time) }}
</template>
</el-table-column>
<el-table-column label="状态" width="100" align="center">
<template slot-scope="scope">
<el-tag
:type="scope.row.status === '上传成功' ? 'success' : 'warning'"
:type="
getStatusType(
scope.row.transfer_type,
scope.row.is_success
)
"
size="mini"
>
{{ scope.row.status }}
{{
getStatusText(
scope.row.transfer_type,
scope.row.is_success
)
}}
</el-tag>
</template>
</el-table-column>
<!-- 操作按钮 -->
<el-table-column label="操作" width="200" align="center">
<el-table-column label="操作" width="180" align="center">
<template slot-scope="scope">
<el-button
v-if="scope.row.transfer_type === 3 && scope.row.file_url"
type="text"
icon="el-icon-view"
@click="handleOpenFile(scope.row)"
@click="handleDownload(scope.row)"
>
打开
</el-button>
<el-button
v-if="scope.row.transfer_type === 3 && scope.row.file_url"
type="text"
icon="el-icon-folder-opened"
@click="handleOpenFolder(scope.row)"
@click="handleOpenLocation(scope.row)"
>
打开位置
</el-button>
<!-- <el-button
v-if="scope.row.transfer_type === 1"
type="text"
size="mini"
icon="el-icon-upload2"
disabled
>
已上传
</el-button>
<el-button
type="text"
size="mini"
icon="el-icon-delete"
style="color: #f56c6c"
@click="handleDeleteItem(scope.row)"
>
删除
</el-button> -->
</template>
</el-table-column>
</el-table>
</div>
</template>
<el-empty v-else description="暂无文件传输记录" />
</div>
</el-card>
</div>
</template>
<script>
const STORAGE_KEY = "file_transfer_records";
export default {
name: "Utility",
name: "UtilityPage",
data() {
return {
// +
transferDataList: [],
loading: false,
transferRecords: [],
};
},
created() {
this.getList();
computed: {
// Qt DisplayFiletransferinfo
groupedRecords() {
const groups = {};
for (const item of this.transferRecords) {
const date = this.formatDate(item.time);
if (!groups[date]) {
groups[date] = { date, items: [] };
}
groups[date].items.push(item);
}
//
return Object.values(groups).sort((a, b) => {
return new Date(b.date) - new Date(a.date);
});
},
},
mounted() {
this.loadTransferRecords();
},
methods: {
//
getList() {
// localStorage Qt SQLite
loadTransferRecords() {
this.loading = true;
// listUser(this.addDateRange(this.queryParams, this.dateRange)).then(
// (response) => {
this.transferDataList = [
{
date: "2026-05-13",
list: [
{
id: 1,
name: "1633500241136.mp4",
size: "17.92M",
progress: 100,
time: "14:31",
status: "上传成功",
fileUrl: "https://www.w3school.com.cn/i/movie.mp4",
},
{
id: 2,
name: "TG-2023-01-21-215030828.mp4",
size: "11.86M",
progress: 100,
time: "14:31",
status: "上传成功",
fileUrl: "https://www.w3school.com.cn/i/movie.mp4",
},
{
id: 3,
name: "VID_20230121_200603.mp4",
size: "10.02M",
progress: 100,
time: "14:16",
status: "上传成功",
fileUrl: "https://www.w3school.com.cn/i/movie.mp4",
},
],
},
];
// this.total = response.total;
// this.loading = false;
// }
// );
},
//
handleClearRecords() {
this.$modal
.confirm("是否要清除本地传输记录?")
.then(() => {
this.transferDataList = [];
this.$modal.msgSuccess("清空成功");
})
.catch(() => {});
try {
const data = localStorage.getItem(STORAGE_KEY);
if (data) {
this.transferRecords = JSON.parse(data);
}
} catch (e) {
console.error("加载文件传输记录失败", e);
this.transferRecords = [];
} finally {
this.loading = false;
}
},
// localStorage
saveTransferRecords() {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.transferRecords));
} catch (e) {
console.error("保存文件传输记录失败", e);
}
},
// Qt "yyyy-MM-dd"
formatDate(timeStr) {
if (!timeStr) return "";
const date = new Date(timeStr);
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, "0");
const d = String(date.getDate()).padStart(2, "0");
return `${y}-${m}-${d}`;
},
// Qt "hh:mm"
formatTime(timeStr) {
if (!timeStr) return "";
const date = new Date(timeStr);
const h = String(date.getHours()).padStart(2, "0");
const m = String(date.getMinutes()).padStart(2, "0");
return `${h}:${m}`;
},
// Qt getSendFileSize
formatFileSize(size) {
if (!size || size < 0) return "0.00B";
if (size >= 1024 * 1024) {
return (size / (1024.0 * 1024.0)).toFixed(2) + "M";
} else if (size >= 1024) {
return (size / 1024.0).toFixed(2) + "K";
}
return size.toFixed(2) + "B";
},
// Qt getFileIconPath
getFileIconClass(fileName) {
if (!fileName) return "el-icon-document";
const suffix = fileName.split(".").pop().toLowerCase();
const iconMap = {
txt: "el-icon-tickets",
pdf: "el-icon-document-copy",
mp3: "el-icon-headset",
wav: "el-icon-headset",
avi: "el-icon-video-camera",
mp4: "el-icon-video-camera",
wmv: "el-icon-video-camera",
mov: "el-icon-video-camera",
zip: "el-icon-folder-opened",
rar: "el-icon-folder-opened",
ppt: "el-icon-data-board",
pps: "el-icon-data-board",
xls: "el-icon-s-grid",
xlsx: "el-icon-s-grid",
doc: "el-icon-document",
docx: "el-icon-document",
jpg: "el-icon-picture",
jpeg: "el-icon-picture",
jpe: "el-icon-picture",
bmp: "el-icon-picture",
gif: "el-icon-picture",
png: "el-icon-picture",
tif: "el-icon-picture",
tiff: "el-icon-picture",
};
return iconMap[suffix] || "el-icon-document";
},
//
handleOpenFile(row) {
if (!row.fileUrl) {
this.$modal.msgWarning("文件地址无效,无法打开");
return;
// Qt UpdateTransferStatus
// type: 1=upload, 3=download, 9=other
getStatusText(type, isSuccess) {
// Qt switch(type << isSuccess)
const key = type << (isSuccess ? 1 : 0);
const statusMap = {
1: "上传中", // upload=1, is_success=false -> 1 << 0 = 1 ()
2: "上传成功", // upload=1, is_success=true -> 1 << 1 = 2
3: "下载中", // download=3, is_success=false -> 3 << 0 = 3 ()
6: "下载成功", // download=3, is_success=true -> 3 << 1 = 6
9: "其他", // other=9
18: "其他完成", // other=9, is_success=true -> 9 << 1 = 18
};
//
if (!isSuccess && key === 1) return "上传失败";
if (!isSuccess && key === 3) return "下载失败";
return statusMap[key] || "未知";
},
// Element UI
getStatusType(type, isSuccess) {
if (!isSuccess) return "danger";
if (type === 1) return "success";
if (type === 3) return "success";
return "info";
},
//
handleDownload(item) {
if (item.file_url) {
window.open(item.file_url, "_blank");
} else {
this.$message.warning("文件链接不可用");
}
window.open(row.fileUrl, "_blank");
},
//
handleOpenFolder(row) {
//
handleOpenLocation(item) {
if (item.local_path) {
this.$modal.msg("浏览器安全限制:请下载后在下载列表打开文件夹");
const a = document.createElement("a");
a.href = row.fileUrl;
a.download = row.name;
a.href = item.file_url;
a.download = item.file_name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} else {
this.$message.warning("文件路径不可用");
}
},
//
handleDeleteItem(item) {
this.$confirm("确认删除该传输记录?", "提示", { type: "warning" })
.then(() => {
this.transferRecords = this.transferRecords.filter(
(r) => r.id !== item.id
);
this.saveTransferRecords();
this.$message.success("删除成功");
})
.catch(() => {});
},
// Qt on_clearButton_clicked
handleClearAll() {
this.$modal
.confirm("是否要清除本地传输记录?")
.then(() => {
this.transferRecords = [];
this.saveTransferRecords();
this.$message.success("记录已清空");
})
.catch(() => {});
},
// Qt UpdateToolsWidgetSlot
addTransferRecord(record) {
const newRecord = {
id: record.id || Date.now(),
user_id: record.user_id || 0,
file_name: record.file_name || "",
local_path: record.local_path || "",
file_size: record.file_size || 0,
transfer_type: record.transfer_type || 9,
is_success: record.is_success || false,
time: record.time || new Date().toISOString(),
file_url: record.file_url || "",
};
// Qt InsertToolsItemWidget
this.transferRecords.unshift(newRecord);
this.saveTransferRecords();
},
// Qt UpdateFinishedToolsWidgetSlot
updateTransferStatus(id, isSuccess) {
const record = this.transferRecords.find((r) => r.id === id);
if (record) {
record.is_success = isSuccess;
this.saveTransferRecords();
}
},
},
};
</script>
<style lang="scss" scoped>
.video-thumb {
.container {
height: calc(100vh - 230px);
overflow-y: auto;
.file-thumb {
width: 42px;
height: 42px;
border-radius: 6px;
@ -192,5 +364,6 @@ export default {
justify-content: center;
font-size: 20px;
margin: 0 auto;
}
}
</style>

@ -76,7 +76,7 @@
v-show="queryParams.total > 0"
:total="queryParams.total"
:page.sync="queryParams.page"
:limit.sync="queryParams.pageSize"
:limit.sync="queryParams.size"
@pagination="getList"
/>
</el-card>
@ -169,7 +169,7 @@ export default {
loading: false,
queryParams: {
page: 1,
pageSize: 10,
size: 10,
total: 0,
},
meetingModes: [

@ -9,8 +9,10 @@ const CompressionPlugin = require('compression-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '信联' // 网页标题
// const baseUrl = 'http://www.haiteriot.com:13002' // 后端接口
const baseUrl = 'http://47.92.6.51:8005' // 后端接口
const baseUrl = 'http://www.haiteriot.com:13005' // 后端接口
// const baseUrl = 'http://47.92.6.51:8005' // 后端接口
// const baseUrl = 'http://47.92.6.51:8001' // 后端接口

Loading…
Cancel
Save