基础管理页面编号下载可视化

This commit is contained in:
zhulongchuan 2025-09-24 18:08:20 +08:00
parent 6b4cb11ead
commit 003ab32ffd
9 changed files with 526 additions and 14 deletions

View File

@ -39,20 +39,20 @@
"jsencrypt": "3.0.0-rc.1",
"minimatch": "^10.0.3",
"nprogress": "0.2.0",
"qrcode": "^1.5.4",
"qrcodejs2-fix": "^0.0.1",
"quill": "2.0.2",
"screenfull": "5.0.2",
"sortablejs": "1.10.2",
"splitpanes": "2.4.1",
"uuid": "^9.0.0",
"vue": "2.6.12",
"vue-count-to": "1.0.13",
"vue-cropper": "0.5.5",
"vue-router": "3.4.9",
"vuedraggable": "2.24.3",
"vuex": "3.6.0",
"uuid": "^9.0.0",
"yarn": "^1.22.22",
"qrcode": "^1.5.3",
"qrcodejs2-fix": "^0.0.1"
"yarn": "^1.22.22"
},
"devDependencies": {
"@vue/cli-plugin-babel": "4.4.6",

15
src/main.ts Normal file
View File

@ -0,0 +1,15 @@
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router/index'
// 导入element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(router);
app.use(ElementPlus);
app.mount('#app')

29
src/router/index.ts Normal file
View File

@ -0,0 +1,29 @@
import { createRouter, createWebHistory } from 'vue-router';
const routerHistory = createWebHistory();
const router = createRouter({
history: routerHistory, //history写法不同
routes: [{
path: '/',
redirect: '/home',
},{
path: '/home',
component: () => import(`@/views/Home.vue`),
},{
path: '/hawkEyeO',
component: () => import(`@/views/MultiView/hawkEyeO.vue`),
},{
path: '/hawkEyeL',
component: () => import(`@/views/MultiView/hawkEyeL.vue`),
},{
path: '/hawkEyeC',
component: () => import(`@/views/MultiView/hawkEyeC.vue`),
}, {
path: '/swipe',
component: () => import(`@/views/MultiView/Swipe.vue`),
},
{
path: '/doubleView',
component: () => import(`@/views/MultiView/DoubleView.vue`),
}]
});
export default router;

82
src/style.css Normal file
View File

@ -0,0 +1,82 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
/* max-width: 1280px; */
/* margin: 0 auto; */
/* padding: 2rem; */
margin: 0;
padding: 0;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

View File

@ -50,7 +50,13 @@
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<!-- <el-table-column label="设备编号" align="center" key="equId" prop="equId" /> -->
<el-table-column label="设备编号" align="center" key="equCode" prop="equCode" />
<!-- <el-table-column label="设备编号" align="center" key="equCode" prop="equCode" /> -->
<el-table-column prop="equCode" label="设备编号" header-align="center" align="center">
<template #default="{ row }">
<span @click="downloadText(row.equCode)"
style="cursor: pointer; color: blue;">{{ row.equCode }}</span>
</template>
</el-table-column>
<el-table-column label="部门" align="center" key="deptName" prop="deptName" />
<el-table-column label="品牌型号" align="center" key="modelId" prop="modelId" />
<el-table-column label="设备分类" align="center" key="classify" prop="classify" >
@ -378,6 +384,54 @@ export default {
return true
})
},
downloadText (text) {
const canvas = document.createElement('canvas');
canvas.width = 1400; //
canvas.height = 600; // 60:35
// 2D
const ctx = canvas.getContext('2d');
if (ctx) {
//
ctx.font = 'bold 128px 楷体';
//
ctx.fillStyle = 'rgb(20, 17, 110)'; //
//
const charSpacing = 35 / 4; // 1/4
const fontSize = 128; //
//
let totalTextWidth = 0;
for (const char of text) {
totalTextWidth += ctx.measureText(char).width + charSpacing;
}
totalTextWidth -= charSpacing; //
//
let currentX = (canvas.width - totalTextWidth) / 2;
//
for (const char of text) {
ctx.fillText(char, currentX, (canvas.height - fontSize) / 2); //
currentX += ctx.measureText(char).width + charSpacing;
}
//
const link = document.createElement('a');
link.href = canvas.toDataURL(); // base64
link.download = '设备编号.png'; //
link.click(); //
//
ctx.clearRect(0, 0, canvas.width, canvas.height);
} else {
console.error('Failed to get 2D context from canvas.');
}
},
//
filterNode(value, data) {
if (!value) return true
@ -571,3 +625,25 @@ export default {
}
}
</script>
<style scoped>
.qrcode-image {
width: 100px;
/* 根据需求调整二维码图片大小 */
height: 100px;
margin-left: 60px;
}
.qrcode-container {
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
}
.zoomed-qrcode-image {
width: 100%;
}
</style>

View File

@ -50,7 +50,14 @@
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<!-- <el-table-column label="设备编号" align="center" key="equId" prop="equId" /> -->
<el-table-column label="设备编号" align="center" key="equCode" prop="equCode" />
<!-- <el-table-column label="设备编号" align="center" key="equCode" prop="equCode" /> -->
<el-table-column prop="equCode" label="设备编号" header-align="center" align="center">
<template #default="{ row }">
<span @click="downloadText(row.equCode)"
style="cursor: pointer; color: blue;">{{ row.equCode }}</span>
</template>
</el-table-column>
<el-table-column label="部门" align="center" key="deptName" prop="deptName" />
<el-table-column label="国标码" align="center" key="gbCode" prop="gbCode" />
<el-table-column label="品牌型号" align="center" key="modelId" prop="modelId" />
@ -70,7 +77,14 @@
<el-table-column label="保险状态" align="center" key="insuranceSts" prop="insuranceSts" />
<el-table-column label="保险期限" align="center" key="mtnDate" prop="mtnDate"/>
<el-table-column label="备注" align="center" key="remark" prop="remark" />
<!-- <el-table-column label="二维码" align="center">
<template #default="{ row }">
<div class="qrcode-container" @click="downloadQRCode(row)"
@dblclick="zoomQRCode(row)">
<img :src="row.qrCode" alt="QR Code" class="qrcode-image" />
</div>
</template>
</el-table-column> -->
<!-- <el-table-column prop="equCode" label="设备编号" header-align="center" align="center">
<template #default="{ row }">
<span @click="downloadText(row.equCode)"
@ -212,7 +226,7 @@ import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
import qrcode from 'qrcode';
export default {
name: "User",
dicts: ['sys_normal_disable', 'sys_user_sex','dev_equ_classify','dev_health_status', 'equ_attribution_sts','equ_model_info'],
@ -257,6 +271,8 @@ export default {
children: "children",
label: "label"
},
zoomedQrCode : '',
isible : false,
//
upload: {
//
@ -349,6 +365,9 @@ export default {
this.queryParams.typeId = 13
listData(this.queryParams).then(response => {
this.userList = response.rows
this.userList?.forEach(row => {
this.generateQRCode(row);
});
this.total = response.total
this.loading = false
}
@ -468,6 +487,119 @@ export default {
this.title = "修改"
})
},
zoomQRCode (row) {
this.zoomedQrCode = qrcode.toDataURL(row.equCode)
this.isiblee = true
},
downloadText (text) {
const canvas = document.createElement('canvas');
canvas.width = 1400; //
canvas.height = 600; // 60:35
// 2D
const ctx = canvas.getContext('2d');
if (ctx) {
//
ctx.font = 'bold 128px 楷体';
//
ctx.fillStyle = 'rgb(20, 17, 110)'; //
//
const charSpacing = 35 / 4; // 1/4
const fontSize = 128; //
//
let totalTextWidth = 0;
for (const char of text) {
totalTextWidth += ctx.measureText(char).width + charSpacing;
}
totalTextWidth -= charSpacing; //
//
let currentX = (canvas.width - totalTextWidth) / 2;
//
for (const char of text) {
ctx.fillText(char, currentX, (canvas.height - fontSize) / 2); //
currentX += ctx.measureText(char).width + charSpacing;
}
//
const link = document.createElement('a');
link.href = canvas.toDataURL(); // base64
link.download = '设备编号.png'; //
link.click(); //
//
ctx.clearRect(0, 0, canvas.width, canvas.height);
} else {
console.error('Failed to get 2D context from canvas.');
}
},
//
generateQRCode(row) {
try {
const str =
"警航编号:" + row.equCode + "\n" +
"设备状态: " + row.equSts + "\n" +
"所属机构:" + row.deptName + "\n" +
"类别: 无人机" + "\n" +
"设备序列号:" + row.equSn + "\n" +
"责任人姓名:" + row.mngName + "\n" +
"责任人警号:" + row.mngCode + "\n" +
"采购日期:" + row.purDate + "\n" +
"保险期限: " + row.mtnDate
console.log("str:",str)
console.log("qrcode:",qrcode)
console.log("qrcode.toDataURL:",qrcode.toDataURL)
const url = this.qrcode.toDataURL(str);
row.qrCode = url;
} catch (err) {
console.error(err);
}
},
//
downloadQRCode (row) {
if (row.equSts = 0) {
row.equSts = "正常"
}
if (row.equSts = 1) {
row.equSts = "故障"
}
if (row.equSts = 2) {
row.equSts = "报废"
}
console.log(row.equSts, "row.equSts");
const str =
"警航编号:" + row.equCode + "\n" +
"设备状态: " + row.equSts + "\n" +
"所属机构:" + row.deptName + "\n" +
"类别: 无人机" + "\n" +
"设备序列号:" + row.equSn + "\n" +
"责任人姓名:" + row.mngName + "\n" +
"责任人警号:" + row.mngCode + "\n" +
"采购日期:" + row.purDate + "\n" +
"保险期限: " + row.mtnDate
const qrCodeCanvas = this.qrcode.toCanvas(str, { errorCorrectionLevel: 'H' })
const link = document.createElement('a')
link.href = this.qrCodeCanvas.toDataURL('image/png')
link.download = `${row.equCode}.png`
link.click()
},
/** 重置密码按钮操作 */
handleResetPwd(row) {
this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
@ -566,3 +698,26 @@ export default {
}
}
</script>
<style scoped>
.qrcode-image {
width: 100px;
/* 根据需求调整二维码图片大小 */
height: 100px;
margin-left: 60px;
}
.qrcode-container {
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
}
.zoomed-qrcode-image {
width: 100%;
}
</style>

View File

@ -55,7 +55,13 @@
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<!-- <el-table-column label="设备编号" align="center" key="equId" prop="equId" /> -->
<el-table-column label="设备编号" align="center" key="equCode" prop="equCode" />
<!-- <el-table-column label="设备编号" align="center" key="equCode" prop="equCode" /> -->
<el-table-column prop="equCode" label="设备编号" header-align="center" align="center">
<template #default="{ row }">
<span @click="downloadText(row.equCode)"
style="cursor: pointer; color: blue;">{{ row.equCode }}</span>
</template>
</el-table-column>
<el-table-column label="所属机构" align="center" key="deptName" prop="deptName" />
<el-table-column label="品牌型号" align="center" key="modelId" prop="modelId" />
<el-table-column label="设备功能 " align="center" prop="equFunction"/>
@ -358,6 +364,55 @@ export default {
}
)
},
downloadText (text) {
const canvas = document.createElement('canvas');
canvas.width = 1400; //
canvas.height = 600; // 60:35
// 2D
const ctx = canvas.getContext('2d');
if (ctx) {
//
ctx.font = 'bold 128px 楷体';
//
ctx.fillStyle = 'rgb(20, 17, 110)'; //
//
const charSpacing = 35 / 4; // 1/4
const fontSize = 128; //
//
let totalTextWidth = 0;
for (const char of text) {
totalTextWidth += ctx.measureText(char).width + charSpacing;
}
totalTextWidth -= charSpacing; //
//
let currentX = (canvas.width - totalTextWidth) / 2;
//
for (const char of text) {
ctx.fillText(char, currentX, (canvas.height - fontSize) / 2); //
currentX += ctx.measureText(char).width + charSpacing;
}
//
const link = document.createElement('a');
link.href = canvas.toDataURL(); // base64
link.download = '设备编号.png'; //
link.click(); //
//
ctx.clearRect(0, 0, canvas.width, canvas.height);
} else {
console.error('Failed to get 2D context from canvas.');
}
},
/** 查询部门下拉树结构 */
getDeptTree() {
deptTreeSelect().then(response => {
@ -570,3 +625,25 @@ export default {
}
}
</script>
<style scoped>
.qrcode-image {
width: 100px;
/* 根据需求调整二维码图片大小 */
height: 100px;
margin-left: 60px;
}
.qrcode-container {
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
}
.zoomed-qrcode-image {
width: 100%;
}
</style>

View File

@ -50,7 +50,13 @@
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<!-- <el-table-column label="设备编号" align="center" key="equId" prop="equId" /> -->
<el-table-column label="设备编号" align="center" key="equCode" prop="equCode" />
<!-- <el-table-column label="设备编号" align="center" key="equCode" prop="equCode" /> -->
<el-table-column prop="equCode" label="设备编号" header-align="center" align="center">
<template #default="{ row }">
<span @click="downloadText(row.equCode)"
style="cursor: pointer; color: blue;">{{ row.equCode }}</span>
</template>
</el-table-column>
<el-table-column label="部门" align="center" key="deptName" prop="deptName" />
<el-table-column label="品牌型号" align="center" key="modelId" prop="modelId" />
<!-- <el-table-column label="设备分类" align="center" key="classify" prop="classify" >
@ -388,6 +394,54 @@ export default {
row.status = row.status === "0" ? "1" : "0"
})
},
downloadText (text) {
const canvas = document.createElement('canvas');
canvas.width = 1400; //
canvas.height = 600; // 60:35
// 2D
const ctx = canvas.getContext('2d');
if (ctx) {
//
ctx.font = 'bold 128px 楷体';
//
ctx.fillStyle = 'rgb(20, 17, 110)'; //
//
const charSpacing = 35 / 4; // 1/4
const fontSize = 128; //
//
let totalTextWidth = 0;
for (const char of text) {
totalTextWidth += ctx.measureText(char).width + charSpacing;
}
totalTextWidth -= charSpacing; //
//
let currentX = (canvas.width - totalTextWidth) / 2;
//
for (const char of text) {
ctx.fillText(char, currentX, (canvas.height - fontSize) / 2); //
currentX += ctx.measureText(char).width + charSpacing;
}
//
const link = document.createElement('a');
link.href = canvas.toDataURL(); // base64
link.download = '设备编号.png'; //
link.click(); //
//
ctx.clearRect(0, 0, canvas.width, canvas.height);
} else {
console.error('Failed to get 2D context from canvas.');
}
},
//
cancel() {
this.open = false
@ -560,3 +614,26 @@ export default {
}
}
</script>
<style scoped>
.qrcode-image {
width: 100px;
/* 根据需求调整二维码图片大小 */
height: 100px;
margin-left: 60px;
}
.qrcode-container {
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
}
.zoomed-qrcode-image {
width: 100%;
}
</style>

1
src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />