设备二维码查看导出,导出组件

This commit is contained in:
zzyuan 2024-08-05 14:21:14 +08:00
parent 7ce1da4eca
commit 55bfa3a3f5
6 changed files with 351 additions and 250 deletions

View File

@ -42,14 +42,17 @@
"core-js": "3.25.3",
"echarts": "5.4.0",
"element-ui": "2.15.14",
"file-saver": "2.0.5",
"file-saver": "^2.0.5",
"fuse.js": "6.4.3",
"highlight.js": "9.18.5",
"html2canvas": "^1.4.1",
"js-beautify": "1.13.0",
"js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1",
"jszip": "^3.10.1",
"nprogress": "0.2.0",
"qrcode": "^1.5.3",
"qrcodejs2": "^0.0.2",
"quill": "1.3.7",
"screenfull": "5.0.2",
"sortablejs": "1.10.2",

View File

@ -41,7 +41,7 @@ service.interceptors.request.use(config => {
config.params = {};
config.url = url;
}
console.log(config)
// console.log(config)
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
@ -72,7 +72,7 @@ service.interceptors.request.use(config => {
}
}
}
console.log(config)
// console.log(config)
if( config.headers['Content-Type']=='application/json;charset=utf-8'){
if(typeof (config.data)=='object'){
@ -82,10 +82,10 @@ service.interceptors.request.use(config => {
}
//对下载请求进行数据参数拦截加密
if(config.headers['Content-Type']=='application/x-www-form-urlencoded'){
console.log(config)
console.log(config.data)
// console.log(config)
// console.log(config.data)
if(typeof (config.data)=='object'){
console.log(config.data)
// console.log(config.data)
let formData=tansParams(config.data);
if(formData){
formData = formData.slice(0, -1);

View File

@ -1,7 +1,7 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item prop="devcieType">
<el-form-item prop="deviceType">
<el-select v-model="queryParams.deviceType" placeholder="设备类型" clearable style="width: 100%;">
<el-option
v-for="dict in dict.type.sys_device_type"
@ -29,7 +29,7 @@
/>
</el-form-item>
<el-form-item prop="deviceStatus">
<el-select v-model="queryParams.deviceStatus" placeholder="状态" clearable style="width: 100%;">
<el-select v-model="queryParams.deviceStatus" placeholder="设备状态" clearable style="width: 100%;">
<el-option
v-for="dict in dict.type.sys_device_status"
:key="dict.value"
@ -67,14 +67,21 @@
v-hasPermi="['basic:device:export']"
>导出数据</el-button>
</el-col>
<el-col :span="1.5">
<!-- 二维码导出组件按钮在内部传选中数组 currentSelection:选中数组 clearCheck:清空选中状态-->
<qrCodeUpload :checkboxModel.sync="currentSelection" @clearCheck="clearCheck"/>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="deviceList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table v-loading="loading" :data="tableData" ref="multipleTable" row-key="deviceId" @selection-change="handleSelectionChange" @select="handlerSelect" @select-all="handlerSelectAll">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true" />
<el-table-column label="设备id" align="center" prop="deviceId" v-if="false" />
<el-table-column label="设备类型" align="center" prop="deviceType" />
<el-table-column label="设备类型" align="center" prop="deviceType">
<template slot-scope="scope">
<div>{{ dict.type.sys_device_type[Number(scope.row.deviceType)].label }}</div>
</template>
</el-table-column>
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="设备编号" align="center" prop="deviceCode" />
<el-table-column label="二维码" align="center" class-name="small-padding fixed-width">
@ -83,17 +90,17 @@
size="mini"
type="text"
icon="el-icon-edit"
@click="handleQuertPage(scope.row)"
@click="labelUploadCode(scope.row)"
v-hasPermi="['basic:device:query']"
>查看</el-button>
</template>
</el-table-column>
<el-table-column label="设备状态" align="center" prop="deviceStatus" >
<template slot-scope="scope">
<div v-if="scope.row.deviceStatus==0" style="color: green;">{{ stateList[Number(scope.row.deviceStatus)] }}</div>
<div v-if="scope.row.deviceStatus==1" style="color: red;">{{ stateList[Number(scope.row.deviceStatus)] }}</div>
</template>
</el-table-column>
<template slot-scope="scope">
<div v-if="scope.row.deviceStatus==0" style="color: green;">{{ dict.type.sys_device_status[Number(scope.row.deviceStatus).label] }}</div>
<div v-if="scope.row.deviceStatus==1" style="color: red;">{{ dict.type.sys_device_status[Number(scope.row.deviceStatus)].label }}</div>
</template>
</el-table-column>
<el-table-column label="领用人" align="center" prop="lyName" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
@ -122,124 +129,12 @@
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 杆塔弹窗 -->
<el-dialog :title="title" :visible.sync="showGt" width="1000px" height="1000px" append-to-body>
<el-form :model="queryKeyword" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item prop="keyword">
<el-input
v-model="queryKeyword.keyword"
placeholder="请输入关键词"
clearable
@keyup.enter.native="handleQueryTemp"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQueryTemp">查询</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAddDevice"
v-hasPermi="['basic:sideband:add']"
>绑定设备</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getListTemp"></right-toolbar>
</el-row>
<el-table v-loading="loadingTwo" :data="bindList" width="600px" height = "600px" >
<el-table-column label="设备id" align="center" prop="deviceId" v-if="false" />
<el-table-column label="设备类型" align="center" prop="deviceType" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="设备编号" align="center" prop="deviceCode" />
<el-table-column label="设备状态" align="center" prop="deviceStatus" >
<template slot-scope="scope">
<div v-if="scope.row.deviceStatus==0" style="color: green;">{{ stateList[Number(scope.row.deviceStatus)] }}</div>
<div v-if="scope.row.deviceStatus==1" style="color: red;">{{ stateList[Number(scope.row.deviceStatus)] }}</div>
</template>
</el-table-column>
<el-table-column label="领用人" align="center" prop="lyName" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleDelDevice(scope.row)"
v-hasPermi="['basic:sideband:edit']"
>解除绑定</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="totalTwo>0"
:total="totalTwo"
:page.sync="queryKeyword.pageNum"
:limit.sync="queryKeyword.pageSize"
@pagination="getListTemp"
/>
</el-dialog>
<!-- 选择设备弹窗 -->
<el-dialog :title="title" :visible.sync="showDevice" width="800px" height="800px" append-to-body>
<el-form :model="queryKeywordTemp" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item prop="keyword">
<el-input
v-model="queryKeywordTemp.keyword"
placeholder="请输入关键词"
clearable
@keyup.enter.native="handleQueryDevice"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQueryDevice">查询</el-button>
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleBindDevice"
v-hasPermi="['basic:sideband:add']"
>绑定</el-button>
</el-form-item>
</el-form>
<!--
<el-row :gutter="10" class="mb8">
<right-toolbar :showSearch.sync="showSearch" @queryTable="getListDevice"></right-toolbar>
</el-row> -->
<el-table v-loading="loadingThree" :data="bindNoList" width="600px" height = "600px" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="设备id" align="center" prop="deviceId" v-if="false" />
<el-table-column label="设备类型" align="center" prop="deviceType" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="设备编号" align="center" prop="deviceCode" />
</el-table>
<pagination
v-show="totalThree>0"
:total="totalThree"
:page.sync="queryKeywordTemp.pageNum"
:limit.sync="queryKeywordTemp.pageSize"
@pagination="getListDevice"
/>
</el-dialog>
<!-- 添加或修改设备对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px" >
<el-form-item label="设备类型" prop="devcieType">
<el-select v-model="form.deviceType" placeholder="请输入设备类型" clearable style="width: 100%;">
<el-select v-model="form.deviceType" placeholder="请选择设备类型" clearable style="width: 100%;">
<el-option
v-for="dict in dict.type.sys_device_type"
:key="dict.value"
@ -249,10 +144,10 @@
</el-select>
</el-form-item>
<el-form-item label="设备编码" prop="deviceCode">
<el-input v-model="form.deviceCode" placeholder="请输入设备编码" />
<el-input v-model="form.deviceCode" placeholder="请输入设备编码" maxlength="20"/>
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="form.deviceName" placeholder="请输入设备名称" />
<el-input v-model="form.deviceName" placeholder="请输入设备名称" maxlength="20"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
@ -260,30 +155,51 @@
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<!-- 标签下载对话框 -->
<el-dialog
:title="title"
:visible.sync="uploadOpen"
width="450px"
append-to-body
:close-on-click-modal="false"
>
<div style="text-align: center" ref="codeBox">
<div class="uploadImg">
<div id="qrcode" class="qrcode" ref="codeItem"></div>
<!-- <img src="" alt="">-->
</div>
<div class="deviceCode">设备编号{{ rowObj.deviceCode }}</div>
</div>
<div slot="footer" class="dialog-footer" style="text-align: center">
<el-button type="primary" @click="downloadCode"
> </el-button
>
</div>
</el-dialog>
</div>
</template>
<script>
import { listDevcie, addDevice, editDevice, getDeviceInfo,delDevice,listDeviceNoBind,bindDevice, exportDevice} from "@/api/base/device";
import { listDevcie, addDevice, editDevice, getDeviceInfo,delDevice, exportDevice} from "@/api/base/device";
import { downloadFile } from '@/utils/download'
import { getToken } from '@/utils/auth'
import uploadFile from '../../components/uploadFile.vue'
import qrCodeUpload from '../../components/qrCodeUpload.vue'
import html2canvas from 'html2canvas'
import QRCode from 'qrcodejs2'
import JSZip from 'jszip'
import FileSaver from 'file-saver'
import C from "highlight.js/lib/languages/1c";
export default {
name: "Post",
dicts: ['sys_normal_disable','sys_user_sex','sys_device_type','sys_device_status'],
dicts: ['sys_normal_disable','sys_device_type','sys_device_status'],
components: {
uploadFile
uploadFile,qrCodeUpload
},
data() {
return {
//
loading: true,
// 2
loadingTwo:true,
// 3
loadingThree:true,
//
ids: [],
//
@ -299,11 +215,7 @@
//
totalThree:0,
//
deviceList: [],
//
bindList: [],
//
bindNoList: [],
tableData: [],
//
title: "",
//
@ -322,49 +234,10 @@
deviceCode: undefined,
devcieStatus: undefined,
},
queryKeyword:{
pageNum: 1,
pageSize: 10,
sidebandId: undefined,
keyword: undefined,
},
queryKeywordTemp:{
pageNum: 1,
pageSize: 10,
sidebandId: undefined,
keyword: undefined,
},
showGt:false,
showDevice:false,
stateList:['在用','未用'],
accept:'.png, .jpg, .jpeg, .pdf, .doc, .docx',
highImgList: [],
electricianImgList: [],
elseImgList: [],
maxLength:100,//
currentSelection:[],//
//
form: {},
//
fileList: [],
//
dialogImageUrl: '',
dialogVisible: false,
//
upload: {
//
open: false,
//
title: "",
//
isUploading: false,
//
updateSupport: 0,
//
headers: { Authorization: "Bearer " + getToken() },
//
url: process.env.VUE_APP_BASE_API + "/bracelet/person/excelUpload"
},
//
rules: {
deviceType: [
@ -376,17 +249,22 @@
deviceName: [
{ required: true, message: "设备名称不能为空", trigger: "blur" }
]
}
},
//
rowObj:{},
uploadOpen:false,
deviceCode:'',
};
},
computed: {
//1
uploadDisabled() {
return this.fileList.length > 0
},
},
created() {
this.getList();
},
mounted(){
console.log(this.dict.type.sys_device_type)
},
methods: {
@ -394,16 +272,28 @@
getList() {
this.loading = true;
listDevcie(this.queryParams).then(response => {
this.deviceList = response.rows;
this.tableData = response.rows;
this.total = response.total;
this.loading = false;
if (this.currentSelection.length) {
this.$nextTick(() => {
this.currentSelection.forEach(row => {
this.tableData.forEach(item => {
if (item.deviceId === row) {
this.$refs.multipleTable?.toggleRowSelection(item, true)
}
})
})
})
} else {
this.$refs.multipleTable?.clearSelection()
}
});
},
//
cancel() {
this.open = false;
this.fileList=[];
this.reset();
},
//
@ -416,33 +306,99 @@
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.currentSelection = []//
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.deviceId)
this.single = selection.length!=1
this.multiple = !selection.length
},
//-
handlerSelect(val, row) {
this.currentSelection.indexOf(row.deviceId) === -1
? this.currentSelection.push(row.deviceId)
: this.currentSelection.splice(this.currentSelection.indexOf(row.deviceId), 1)
},
//-
handlerSelectAll(val) {
if (val.length) {
// :
// 1 2
//
// tableDatavalcurrentSelection
// tableDatavalcurrentSelection
const isAllSelect = this.tableData.every(item =>
val.some(valItem => valItem.deviceId === item.deviceId)
)
if (isAllSelect) {
//
const diff = val.filter(
item => !this.currentSelection.some(deviceId => deviceId === item.deviceId)
)
if (this.currentSelection.length + diff.length > this.maxLength) {
this.currentSelection = this.currentSelection.concat(
diff.splice(0, this.maxLength - this.currentSelection.length)
.map(item => item.deviceId))
diff.forEach(item => this.$refs.multipleTable.toggleRowSelection(item, false))
} else {
this.currentSelection = this.currentSelection.concat(diff.map(item => item.deviceId))
}
} else {
this.currentSelection = this.currentSelection.filter(
deviceId => !this.tableData.some(item => item.deviceId === deviceId)
)
}
} else {
// :
//
this.currentSelection = []
}
},
clearCheck(){
console.log("clearCheck")
this.currentSelection = []
this.getList()
},
//
labelUploadCode(row) {
this.rowObj = row
this.uploadOpen = true
this.title = '二维码查看'
this.deviceCode = row.deviceCode
let str = row.deviceCode
this.$nextTick(() => {
// this.selectionList.forEach((item, index) => {
this.$refs.codeItem.innerHTML = ''
var qrcode = new QRCode(this.$refs.codeItem, {
text: str, //
width: 256,
height: 256,
colorDark: '#000000',
colorLight: '#ffffff',
correctLevel: QRCode.CorrectLevel.H,
})
handleQuertPage(row){
const qrCodeData = {
"设备类型": row.deviceType,
"设备名称": row.deviceName,
"设备编号": row.deviceCode,
"设备状态": row.deviceStatus,
};
const qrCodeString = JSON.stringify(qrCodeData, null, 2);
console.log(qrCodeString);
//
// Qrcode = "";
// //
// Qrcode.qrcode(utf16to8(qrCodeString));
this.open = true;
// });
}, 500)
},
downloadCode(e) {
if (document.getElementById('qrcode').childNodes[0]) {
let element = this.$refs.codeBox
html2canvas(element).then((canvas) => {
// canvasURL
const image = canvas.toDataURL('image/png')
const alink = document.createElement('a')
alink.href = image
alink.download = this.deviceCode
alink.click()
})
}
},
/** 新增按钮操作 */
handleAdd() {
@ -512,21 +468,6 @@
downloadFile({ fileName: `设备_${new Date().getTime()}.xlsx`, fileData: res, fileType: 'application/vnd.ms-excel;charset=utf-8' })
})
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "人员导入";
this.upload.open = true;
},
//
openGt(row){
this.sidebandId = row.sidebandId;
this.title = "杆塔"
this.showGt = true;
this.getListTemp();
},
//
openDevice(row){
this.sidebandId = row.sidebandId;
@ -534,31 +475,24 @@
this.showDevice = true;
this.getListDevice();
},
//
cancelGt(){
this.highImgList = []
this.electricianImgList = []
this.elseImgList = []
this.showGt = false;
},
//
submitCertificate(){
console.log(this.highImgList)
console.log(this.electricianImgList)
console.log(this.elseImgList)
// this.highImgList = []
// this.electricianImgList = []
// this.elseImgList = []
this.showGt = false;
},
}
};
</script>
<style lang="scss" scoped>
.uploadImg {
padding-top: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.deviceCode {
margin-top: 10px;
padding-bottom: 20px;
font-size: 18px;
}
::v-deep.el-table .fixed-width .el-button--mini {
width: 60px !important;
margin-bottom: 10px;

View File

@ -172,7 +172,7 @@
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="人员姓名" prop="name">
<el-input v-model="form.name" placeholder="请输入人员名称" />
<el-input v-model="form.name" placeholder="请输入人员名称" maxlength="20"/>
</el-form-item>
<el-form-item label="人员性别" prop="sex">
<el-select v-model="form.sex" placeholder="请选择人员性别" clearable style="width: 100%;">
@ -185,16 +185,16 @@
</el-select>
</el-form-item>
<el-form-item label="身份证号" prop="idCard">
<el-input v-model="form.idCard" placeholder="请输入人员身份证号" />
<el-input v-model="form.idCard" placeholder="请输入人员身份证号" maxlength="20"/>
</el-form-item>
<el-form-item label="手机号" prop="phone">
<el-input v-model="form.phone" placeholder="请输入人员手机号" />
<el-input v-model="form.phone" placeholder="请输入人员手机号" maxlength="11"/>
</el-form-item>
<el-form-item label="安全帽编号" prop="aqmCode">
<el-input v-model="form.aqmCode" placeholder="请输入安全帽编号" />
<el-input v-model="form.aqmCode" placeholder="请输入安全帽编号" maxlength="20"/>
</el-form-item>
<el-form-item label="马甲编号" prop="mjCode">
<el-input v-model="form.mjCode" placeholder="请输入马甲编号" />
<el-input v-model="form.mjCode" placeholder="请输入马甲编号" maxlength="20"/>
</el-form-item>
<el-form-item label="人脸照片" prop="fileName">
<el-upload

View File

@ -228,7 +228,7 @@
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="班组名称" prop="teamName">
<el-input v-model="form.teamName" placeholder="请输入班组名称" />
<el-input v-model="form.teamName" placeholder="请输入班组名称" maxlength="20"/>
</el-form-item>
</el-col>

View File

@ -0,0 +1,164 @@
<template>
<div>
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleQrCodeExport"
v-hasPermi="['basic:device:export']"
>导出二维码</el-button>
<div style="background-color: transparent" ref="qrCodeAll">
<div
id="qrCode"
v-for="(codeItem, codeIndex) in checkboxModel"
:key="codeIndex"
class="captureId"
v-show="codeId"
ref="QrcodePage"
style="
z-index: -1111111;
position: absolute;
top: 10px;
left: -99999;
width: 450px;
height: 475px;
background-size: cover;
"
></div>
</div>
</div>
</template>
<script>
import html2canvas from 'html2canvas'
import QRCode from 'qrcodejs2'
import JSZip from 'jszip'
import FileSaver from 'file-saver'
export default {
name: "qrCodeUpload",
data() {
return {
codeId: true,
qrcodeArr:[]
}
},
props: {
checkboxModel: {
type: Array,
default: function() {
return []
}
},
},
computed: {
},
methods: {
// this.$emit('update:uploadList',this.fileList)
// this.$emit('picturePreview', file)
//
async handleQrCodeExport() {
this.codeId = true;
console.log('checkboxModel', this.checkboxModel)
const msg = this.$modal.loading('批量生成中,请稍候...')
let that = this
try {
let captureId = document.getElementsByClassName('captureId')
for (let i = 0; i < this.checkboxModel.length; i++) {
const element = this.checkboxModel[i]
captureId[i].innerHTML = ''
let shareContent = that.$refs['QrcodePage'][i],
width = shareContent.offsetWidth,
height = shareContent.offsetHeight
const maCodeText = document.createElement('div')
maCodeText.innerHTML = '设备编码:' + element
maCodeText.style =
'font-size=18px; width:100%;text-align:center;margin:10px;'
shareContent.appendChild(maCodeText)
new QRCode(captureId[i], {
width: width,
height: height,
text: element,
colorDark: '#000',
colorLight: '#fff',
})
let canvas = document.createElement('canvas'),
scale = 1
canvas.width = width * scale
canvas.height = height * scale
canvas.style.width =
(shareContent.clientWidth * scale) / 100 + 'rem'
canvas.style.height =
(shareContent.clientHeight * scale) / 100 + 'rem'
canvas.getContext('2d').scale(scale, scale)
let opts = {
scale: scale,
canvas: canvas,
logging: false,
width: width,
height: height,
useCORS: true,
}
await html2canvas(shareContent, opts)
.then(function (canvas) {
const qrContentImage = canvas.toDataURL(
'image/jpeg',
1.0,
)
if (i <= that.checkboxModel.length - 1) {
that.qrcodeArr.push({
url: qrContentImage,
name: element,
})
}
})
.catch(function (reason) {
console.log(reason)
this.$emit('clearCheck')
that.$modal.closeLoading()
})
}
await new Promise((resolve) => setTimeout(resolve, 1000))
that.packageImages()
setTimeout(msg, 1000)
that.$modal.closeLoading()
} catch (error) {
setTimeout(msg, 1000)
// that.getList()
this.$emit('clearCheck')
that.$modal.closeLoading()
}
},
//
packageImages() {
let that = this
const zip = new JSZip()
const cache = {}
let arr = that.qrcodeArr
arr.forEach((item, index) => {
let fileName = item.name
zip.file(fileName + '.png', item.url.substring(22), {
base64: true,
})
cache[fileName] = item.url
})
zip.generateAsync({ type: 'blob' }).then((content) => {
FileSaver.saveAs(content, '二维码.zip')
})
// that.getList()
this.$emit('clearCheck')
that.qrcodeArr = []
that.codeId = false;
},
},
}
</script>
<style lang="scss" scoped>
</style>