报告查询
This commit is contained in:
parent
4fc8bb6606
commit
9f24743e4f
|
|
@ -180,3 +180,31 @@ export function getScrapDetailsListApi(query) {
|
|||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//报表查询
|
||||
export function getReportList(query) {
|
||||
return request({
|
||||
url: '/material/bm_report/reportList',
|
||||
method: 'get',
|
||||
params: query,
|
||||
})
|
||||
}
|
||||
|
||||
export function downloadFileApi(data) {
|
||||
return request({
|
||||
url: '/material/bm_report/downloadSingle',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'arraybuffer'
|
||||
})
|
||||
}
|
||||
|
||||
export function batchDownloadFileApi(data) {
|
||||
return request({
|
||||
url: '/material/bm_report/downloadBulk',
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'arraybuffer'
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,942 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="分公司" prop="impUnitName">
|
||||
<el-select
|
||||
v-model="queryParams.impUnitName"
|
||||
placeholder="请选择分公司"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 240px"
|
||||
@change="handleImpUnitChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in impUnitOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="项目部" prop="departName">
|
||||
<el-select
|
||||
v-model="queryParams.departName"
|
||||
placeholder="请选择项目部"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 240px"
|
||||
@change="handleDepartChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in departOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="工程" prop="proName">
|
||||
<el-select
|
||||
v-model="queryParams.proName"
|
||||
placeholder="请选择工程"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in proOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="物资名称" prop="typeName">
|
||||
<el-select
|
||||
v-model="queryParams.typeName"
|
||||
placeholder="请选择物资名称"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 240px"
|
||||
@change="handleMaModel"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in materialNameList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="规格型号" prop="typeModelName">
|
||||
<el-select
|
||||
v-model="queryParams.typeModelName"
|
||||
placeholder="请选择规格型号"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in materialModelList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="机具类型" prop="jiJuType">
|
||||
<el-select
|
||||
v-model="queryParams.jiJuType"
|
||||
placeholder="请选择机具类型"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option label="施工机具" :value="1" />
|
||||
<el-option label="安全工器具" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
|
||||
<el-button icon="el-icon-download" size="mini" @click="handleBulkDownload">一键下载</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
||||
<el-table v-loading="loading" :data="tableList" ref="multipleTable" row-key="id" @selection-change="handleSelectionChange" border>
|
||||
<el-table-column type="selection" width="55"></el-table-column>
|
||||
<el-table-column label="序号" align="center" width="70" type="index">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="分公司" align="center" prop="impUnitName" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="项目部" align="center" prop="departName" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="工程名称" align="center" prop="proName" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="物资名称" align="center" prop="typeName" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="规格型号" align="center" prop="typeModelName" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="计量单位" align="center" prop="unit" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="数量" align="center" prop="num" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="编码" align="center" prop="maCode" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<span
|
||||
v-if="scope.row.maCode"
|
||||
:style="{
|
||||
color: scope.row.qrCode ? '#3EA7F1' : '#000000',
|
||||
cursor: scope.row.qrCode ? 'pointer' : 'default'
|
||||
}"
|
||||
@click="scope.row.qrCode && handleViewQrCode(scope.row)"
|
||||
>
|
||||
{{ scope.row.maCode }}
|
||||
</span>
|
||||
<span v-else>—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="领用日期" align="center" prop="leaseTime" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="出库检验报告" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<span
|
||||
@click="handleReport(scope.row)"
|
||||
style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
|
||||
>查看</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="合格证" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.qualifiedUrl">无</span>
|
||||
<span
|
||||
v-else
|
||||
@click="handleFileView(scope.row.qualifiedUrl)"
|
||||
style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
|
||||
>查看</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="型式试验报告" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.testReportUrl">无</span>
|
||||
<span
|
||||
v-else
|
||||
@click="handleFileView(scope.row.testReportUrl)"
|
||||
style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
|
||||
>查看</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="第三方检测报告" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.thirdReportUrl">无</span>
|
||||
<span
|
||||
v-else
|
||||
@click="handleFileView(scope.row.thirdReportUrl)"
|
||||
style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
|
||||
>查看</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="出厂检测报告" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.factoryReportUrl">无</span>
|
||||
<span
|
||||
v-else
|
||||
@click="handleFileView(scope.row.factoryReportUrl)"
|
||||
style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
|
||||
>查看</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="其他" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.otherReportUrl">无</span>
|
||||
<span
|
||||
v-else
|
||||
@click="handleFileView(scope.row.otherReportUrl)"
|
||||
style="color: #3EA7F1; text-decoration: none; cursor: pointer;"
|
||||
>查看</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="140">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="primary" @click="handleDownload(scope.row)">下载</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 验收单弹窗 -->
|
||||
<el-dialog :title="title" :visible.sync="openOutReport" width="70%" append-to-body>
|
||||
<div style="height: 600px; overflow-y: scroll; padding: 0 20px">
|
||||
<vue-easy-print tableShow ref="remarksPrintRefCheck" class="print" :printable="'checkId1'">
|
||||
<div id="checkId1">
|
||||
<div class="title" style="text-align: center; font-weight: 600; font-size: 16px">
|
||||
施工机具设备出库检验记录表
|
||||
</div>
|
||||
<div class="info" style="margin-top: 10px; display: flex; flex-wrap: wrap">
|
||||
<div class="item" style="width: 50%; flex-shrink: 0; margin-bottom: 5px; font-size: 14px">
|
||||
<span>领用工程:</span>
|
||||
{{ checkDataInfo.leaseProject }}
|
||||
</div>
|
||||
|
||||
<div class="item" style="width: 50%; flex-shrink: 0; margin-bottom: 5px; font-size: 14px">
|
||||
<span>使用单位:</span>
|
||||
{{ checkDataInfo.leaseUnit }}
|
||||
</div>
|
||||
</div>
|
||||
<table
|
||||
class="print-table"
|
||||
style="margin-top: 20px; width: 100%; border-collapse: collapse"
|
||||
border="1"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center">机具名称</th>
|
||||
<th style="text-align: center">规格型号</th>
|
||||
<th style="text-align: center">单位</th>
|
||||
<th style="text-align: center">数量</th>
|
||||
<th style="text-align: center">设备编码</th>
|
||||
<th style="text-align: center">额定载荷KN</th>
|
||||
<th style="text-align: center">试验载荷KN</th>
|
||||
<th style="text-align: center">持荷时间min</th>
|
||||
<th style="text-align: center; width: 100px">试验日期</th>
|
||||
<th style="text-align: center; width: 100px">下次试验日期</th>
|
||||
<th style="text-align: center">检验结论</th>
|
||||
<th style="text-align: center">备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, index) in printTableData" :key="index">
|
||||
<td style="text-align: center">{{ item.typeName }}</td>
|
||||
<td style="text-align: center">{{ item.typeModelName }}</td>
|
||||
<td style="text-align: center">{{ item.unit }}</td>
|
||||
<td style="text-align: center">{{ item.num }}</td>
|
||||
<td style="text-align: center">{{ item.maCode }}</td>
|
||||
<td style="text-align: center">{{ item.ratedLoad }}</td>
|
||||
<td style="text-align: center">{{ item.testLoad }}</td>
|
||||
<td style="text-align: center">{{ item.holdingTime }}</td>
|
||||
<td style="text-align: center">{{ item.testTime }}</td>
|
||||
<td style="text-align: center">{{ item.nextTestTime }}</td>
|
||||
<td style="text-align: center">{{ item.checkResult }}</td>
|
||||
<td style="text-align: center">{{ item.remark }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div
|
||||
class="fillIn"
|
||||
style="margin-top: 20px; display: flex; align-items: center; justify-content: right"
|
||||
>
|
||||
<div class="item" style="width: 30%; align-items: center; position: relative">
|
||||
<div>
|
||||
<span>检验单位:</span>
|
||||
</div>
|
||||
<div v-if="openOutReport">
|
||||
<canvas
|
||||
id="canvas"
|
||||
width="165"
|
||||
height="165"
|
||||
style="
|
||||
position: absolute;
|
||||
top: 180%;
|
||||
left: 90%;
|
||||
transform: translate(-100%, -50%);
|
||||
z-index: 9999;
|
||||
"
|
||||
></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</vue-easy-print>
|
||||
</div>
|
||||
|
||||
<div slot="footer" class="dialog-footer" style="text-align: center">
|
||||
<!-- <el-button type="primary" @click="handleExportCheck">导出</el-button>-->
|
||||
<el-button type="primary" @click="printCheck">打 印</el-button>
|
||||
<el-button @click="closeDialogAndRefresh">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 二维码下载对话框 -->
|
||||
<el-dialog title="二维码查看" :visible.sync="uploadOpen" width="450px" append-to-body :close-on-click-modal="false">
|
||||
<div style="text-align: center" ref="codeQr" v-if="uploadOpen">
|
||||
<div class="uploadImg">
|
||||
<div id="qrcode" class="qrcode" ref="codeItem"></div>
|
||||
</div>
|
||||
<div class="boxCode">{{ rowObj.maCode }}</div>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer" style="text-align: center">
|
||||
<el-button type="primary" @click="downloadQrCode(rowObj)">下 载</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import vueEasyPrint from "vue-easy-print";
|
||||
import {batchDownloadFileApi, downloadFileApi, getReportList} from "@/api/report/report";
|
||||
import {getDepartListByImpUnitApi, getImpUnitListApi, getProListByDepartApi} from "@/api/materialsStation";
|
||||
import {getDeviceType} from "@/api/ma/device";
|
||||
import {getCheckInfo} from "@/api/lease/apply";
|
||||
import printJS from "print-js";
|
||||
import QRCode from "qrcodejs2";
|
||||
import axios from 'axios'
|
||||
import {downloadFile} from "@/utils/download";
|
||||
export default {
|
||||
name: "PartAccept",
|
||||
dicts: ['part_task_status'],
|
||||
components: { vueEasyPrint },
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
showHouse: false,
|
||||
dateRange:[],
|
||||
ids: [],
|
||||
infos: [],
|
||||
// 总条数
|
||||
total: 0,
|
||||
//表格数据
|
||||
tableList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
keyWord:undefined,
|
||||
taskStatus:undefined,
|
||||
},
|
||||
impUnitOptions: [], // 分公司下拉
|
||||
departOptions: [], // 项目部下拉
|
||||
proOptions: [], // 工程下拉
|
||||
materialNameList: [],
|
||||
materialModelList: [],
|
||||
openOutReport: false,
|
||||
checkDataInfo: {},
|
||||
printTableData: [],
|
||||
uploadOpen: false,
|
||||
rowObj: {},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getImpUnitOptions()
|
||||
this.handleImpUnitChange()
|
||||
this.handleDepartChange()
|
||||
this.getDeviceType()
|
||||
},
|
||||
methods: {
|
||||
/** 获取分公司下拉 */
|
||||
async getImpUnitOptions() {
|
||||
try {
|
||||
const res = await getImpUnitListApi() // 调后台接口
|
||||
this.impUnitOptions = res.data.map(item => ({
|
||||
label: item.impUnitName, // 这里根据实际字段替换
|
||||
value: item.impUnitName
|
||||
}))
|
||||
} catch (e) {
|
||||
console.error('获取分公司下拉失败:', e)
|
||||
}
|
||||
},
|
||||
/** 分公司选择变化,加载项目部 */
|
||||
async handleImpUnitChange() {
|
||||
this.queryParams.departName = null // 清空项目部已选
|
||||
this.departOptions = [] // 清空原有下拉
|
||||
|
||||
try {
|
||||
const params = {
|
||||
impUnitName: this.queryParams.impUnitName, // 分公司名称
|
||||
departName: this.queryParams.departName, // 项目部名称
|
||||
proName: this.queryParams.proName,
|
||||
teamName:this.queryParams.teamName,
|
||||
subUnitName:this.queryParams.subUnitName,
|
||||
}
|
||||
const res = await getDepartListByImpUnitApi(params)
|
||||
this.departOptions = res.data.map(item => ({
|
||||
label: item.departName, // 项目部名称字段
|
||||
value: item.departName
|
||||
}))
|
||||
} catch (e) {
|
||||
console.error('获取项目部下拉失败:', e)
|
||||
}
|
||||
},
|
||||
/** 项目部选择变化,加载工程 */
|
||||
async handleDepartChange() {
|
||||
this.queryParams.proName = null // 清空工程已选
|
||||
this.proOptions = [] // 清空原有下拉
|
||||
|
||||
try {
|
||||
// 同时传入分公司和项目部参数
|
||||
const params = {
|
||||
impUnitName: this.queryParams.impUnitName, // 分公司名称
|
||||
departName: this.queryParams.departName, // 项目部名称
|
||||
proName: this.queryParams.proName,
|
||||
teamName:this.queryParams.teamName,
|
||||
subUnitName:this.queryParams.subUnitName,
|
||||
}
|
||||
const res = await getProListByDepartApi(params)
|
||||
this.proOptions = res.data.map(item => ({
|
||||
label: item.proName, // 工程名称字段
|
||||
value: item.proName
|
||||
}))
|
||||
} catch (e) {
|
||||
console.error('获取工程下拉失败:', e)
|
||||
}
|
||||
},
|
||||
getDeviceType() {
|
||||
getDeviceType({ level: 3, skipPermission: 1 }).then(response => {
|
||||
let matNameRes = response.data
|
||||
this.materialNameList = matNameRes.map((item) => {
|
||||
return {
|
||||
label: item.typeName,
|
||||
value: item.typeId
|
||||
}
|
||||
})
|
||||
})
|
||||
getDeviceType({ level: 4, skipPermission: 1 }).then(response => {
|
||||
let matModelRes = response.data
|
||||
this.materialModelList = matModelRes.map((item) => {
|
||||
return {
|
||||
label: item.typeName,
|
||||
value: item.typeId
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
// change设备类型
|
||||
handleMaModel(e) {
|
||||
this.queryParams.typeModelName=null
|
||||
this.materialModelList = []
|
||||
let typeId = null
|
||||
if (!e) {
|
||||
typeId = null
|
||||
} else {
|
||||
typeId = this.materialNameList.find(item => item.label == e).value
|
||||
}
|
||||
console.log('🚀 ~ handleMaModel ~ typeId:', typeId)
|
||||
getDeviceType({ level: 4, skipPermission: 1, typeId }).then(response => {
|
||||
let matModelRes = response.data
|
||||
this.materialModelList = matModelRes.map((item) => {
|
||||
return {
|
||||
label: item.typeName,
|
||||
value: item.typeId
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
if(this.dateRange.length>0){
|
||||
this.queryParams.startTime=this.dateRange[0]
|
||||
this.queryParams.endTime=this.dateRange[1]
|
||||
}else{
|
||||
this.queryParams.startTime=undefined
|
||||
this.queryParams.endTime=undefined
|
||||
}
|
||||
this.queryParams.taskStage = 3
|
||||
getReportList(this.queryParams).then(response => {
|
||||
this.tableList = response.data.rows;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.dateRange=[]
|
||||
this.queryParams.keyWord=null;
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id)
|
||||
this.infos = selection.map(item => ({ id: item.id }))
|
||||
this.single = selection.length != 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
//查看
|
||||
handleView(row){
|
||||
console.log(row)
|
||||
let query = { Id:row.id,taskId: row.taskId,isView:"true" }
|
||||
this.$tab.closeOpenPage({
|
||||
path: '/part/partAcceptDetail',
|
||||
query,
|
||||
})
|
||||
},
|
||||
// 文件查看逻辑
|
||||
handleFileView(url) {
|
||||
if (!url) return;
|
||||
|
||||
// 获取文件后缀名(忽略大小写)
|
||||
const fileExt = url.split('.').pop().toLowerCase();
|
||||
|
||||
// 定义不同类型的文件后缀
|
||||
const imgExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
|
||||
const pdfExts = ['pdf'];
|
||||
const docExts = ['doc', 'docx', 'xls', 'xlsx'];
|
||||
|
||||
if (imgExts.includes(fileExt)) {
|
||||
// 图片预览
|
||||
this.$viewerApi ? this.$viewerApi({ images: [url] }) : window.open(url);
|
||||
} else if (pdfExts.includes(fileExt)) {
|
||||
// PDF 预览
|
||||
window.open(url);
|
||||
} else if (docExts.includes(fileExt)) {
|
||||
// Word、Excel 文件 → 下载
|
||||
this.downloadFile(url);
|
||||
} else {
|
||||
// 其他文件,默认下载
|
||||
this.downloadFile(url);
|
||||
}
|
||||
},
|
||||
|
||||
// 文件下载逻辑
|
||||
downloadFile(url) {
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
const fileName = url.substring(url.lastIndexOf('/') + 1);
|
||||
link.setAttribute('download', fileName);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
},
|
||||
//查看验收单
|
||||
async handleReport(row) {
|
||||
this.checkDataInfo = {
|
||||
leaseProject:row.proName,
|
||||
leaseUnit:row.departName
|
||||
}
|
||||
this.printTableData = [
|
||||
{
|
||||
typeName:row.typeName,
|
||||
typeModelName:row.typeModelName,
|
||||
unit:row.unit,
|
||||
num:row.num,
|
||||
maCode:row.maCode,
|
||||
ratedLoad:row.ratedLoad,
|
||||
testLoad:row.testLoad,
|
||||
holdingTime:row.holdingTime,
|
||||
testTime:row.testTime,
|
||||
nextTestTime:row.nextTestTime,
|
||||
checkResult:row.checkResult,
|
||||
remark: ''
|
||||
}
|
||||
]
|
||||
setTimeout(() => {
|
||||
this.chapter('检验专用章', '安徽送变电工程有限公司机具(物流)分公司')
|
||||
}, 200)
|
||||
this.openOutReport = true
|
||||
this.title = '出库检验单'
|
||||
},
|
||||
//出库检验单打印
|
||||
printCheck() {
|
||||
// this.$refs.remarksPrintRefCheck.print()
|
||||
// printJS({
|
||||
// printable: 'checkId1',
|
||||
// type: 'html',
|
||||
// targetStyles: ['*']
|
||||
// // 其他配置选项
|
||||
// })
|
||||
this.$nextTick(() => {
|
||||
printJS({
|
||||
printable: 'checkId1',
|
||||
type: 'html',
|
||||
style: `
|
||||
@page { size: A4; margin: 0; }
|
||||
body { margin: 0.5cm; font-family: SimSun; }
|
||||
#passId { font-size: 18px; padding: 0 20px; }
|
||||
`,
|
||||
scanStyles: false
|
||||
})
|
||||
})
|
||||
},
|
||||
// 关闭弹窗
|
||||
closeDialogAndRefresh() {
|
||||
this.openOutReport = false
|
||||
},
|
||||
chapter(text, companyName) {
|
||||
let canvas = document.getElementById('canvas')
|
||||
let context = canvas.getContext('2d')
|
||||
canvas.width = canvas.width
|
||||
context.height = canvas.height
|
||||
// // 清除画布内容
|
||||
// context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
//let text = "XXX专用章";
|
||||
//let companyName = "XXX科技股份有限公司";
|
||||
|
||||
// 绘制印章边框
|
||||
let width = canvas.width / 2
|
||||
let height = canvas.height / 2
|
||||
context.lineWidth = 3
|
||||
context.strokeStyle = '#f00'
|
||||
context.beginPath()
|
||||
context.arc(width, height, 80, 0, Math.PI * 2) //宽、高、半径
|
||||
context.stroke()
|
||||
|
||||
//画五角星
|
||||
this.create5star(context, width, height, 20, '#f00', 0)
|
||||
|
||||
// 绘制印章名称
|
||||
context.font = '100 13px 宋体'
|
||||
context.textBaseline = 'middle' //设置文本的垂直对齐方式
|
||||
context.textAlign = 'center' //设置文本的水平对对齐方式
|
||||
context.lineWidth = 1
|
||||
context.strokeStyle = '#ff2f2f'
|
||||
context.strokeText(text, width, height + 50)
|
||||
|
||||
// 绘制印章单位
|
||||
context.translate(width, height) // 平移到此位置,
|
||||
context.font = '100 13px 宋体'
|
||||
let count = companyName.length // 字数
|
||||
let angle = (4 * Math.PI) / (3 * (count - 1)) // 字间角度
|
||||
let chars = companyName.split('')
|
||||
let c
|
||||
for (let i = 0; i < count; i++) {
|
||||
c = chars[i] // 需要绘制的字符
|
||||
if (i == 0) {
|
||||
context.rotate((5 * Math.PI) / 6)
|
||||
} else {
|
||||
context.rotate(angle)
|
||||
}
|
||||
|
||||
context.save()
|
||||
context.translate(65, 0) // 平移到此位置,此时字和x轴垂直,公司名称和最外圈的距离
|
||||
context.rotate(Math.PI / 2) // 旋转90度,让字平行于x轴
|
||||
context.strokeStyle = '#ff5050' // 设置印章单位字体颜色为较浅的红色
|
||||
context.strokeText(c, 0, 0) // 此点为字的中心点
|
||||
context.restore()
|
||||
}
|
||||
},
|
||||
//绘制五角星
|
||||
create5star(context, sx, sy, radius, color, rotato) {
|
||||
context.save()
|
||||
context.fillStyle = color
|
||||
context.translate(sx, sy) //移动坐标原点
|
||||
context.rotate(Math.PI + rotato) //旋转
|
||||
context.beginPath() //创建路径
|
||||
// let x = Math.sin(0);
|
||||
// let y = Math.cos(0);
|
||||
let dig = (Math.PI / 5) * 4
|
||||
for (let i = 0; i < 5; i++) {
|
||||
//画五角星的五条边
|
||||
let x = Math.sin(i * dig)
|
||||
let y = Math.cos(i * dig)
|
||||
context.lineTo(x * radius, y * radius)
|
||||
}
|
||||
context.closePath()
|
||||
context.stroke()
|
||||
context.fill()
|
||||
context.restore()
|
||||
},
|
||||
// 二维码查看
|
||||
handleViewQrCode(row) {
|
||||
console.log('🚀 ~ handleViewQrCode ~ row:', row)
|
||||
this.rowObj = row
|
||||
this.uploadOpen = true
|
||||
this.qrCode = row.qrCode
|
||||
let str = 'http://ahjj.jypxks.com:9988/imw/backstage/machine/qrCodePage?qrcode=' + row.qrCode
|
||||
console.log('🚀 ~ handleViewQrCode ~ str:', str)
|
||||
this.$nextTick(() => {
|
||||
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
|
||||
})
|
||||
}, 500)
|
||||
|
||||
},
|
||||
downloadQrCode(row) {
|
||||
const qrContainer = document.createElement('div')
|
||||
document.body.appendChild(qrContainer)
|
||||
|
||||
const qrSize = 512 // 放大二维码
|
||||
const padding = 20 // 边距也放大
|
||||
const fontSize = 68 // 放大文字
|
||||
const maxTextWidth = qrSize
|
||||
|
||||
const qrcode = new QRCode(qrContainer, {
|
||||
text: 'http://ahjj.jypxks.com:9988/imw/backstage/machine/qrCodePage?qrcode=' + row.qrCode,
|
||||
width: qrSize,
|
||||
height: qrSize,
|
||||
colorDark: '#000000',
|
||||
colorLight: '#ffffff',
|
||||
correctLevel: QRCode.CorrectLevel.H
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
const img = qrContainer.querySelector('img') || qrContainer.querySelector('canvas')
|
||||
const text = row.maCode || ''
|
||||
|
||||
// 计算换行
|
||||
const ctxMeasure = document.createElement('canvas').getContext('2d')
|
||||
ctxMeasure.font = `${fontSize}px Arial`
|
||||
const words = text.split('')
|
||||
let line = ''
|
||||
const lines = []
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
const testLine = line + words[i]
|
||||
if (ctxMeasure.measureText(testLine).width > maxTextWidth) {
|
||||
lines.push(line)
|
||||
line = words[i]
|
||||
} else {
|
||||
line = testLine
|
||||
}
|
||||
}
|
||||
lines.push(line)
|
||||
|
||||
// 动态计算画布高度
|
||||
const lineHeight = fontSize + 10
|
||||
const qrCanvas = document.createElement('canvas')
|
||||
qrCanvas.width = qrSize + padding * 2
|
||||
qrCanvas.height = qrSize + padding * 2 + lines.length * lineHeight
|
||||
|
||||
const ctx = qrCanvas.getContext('2d')
|
||||
ctx.fillStyle = '#fff'
|
||||
ctx.fillRect(0, 0, qrCanvas.width, qrCanvas.height)
|
||||
|
||||
ctx.drawImage(img, padding, padding, qrSize, qrSize)
|
||||
|
||||
// 绘制文字
|
||||
ctx.fillStyle = '#000'
|
||||
ctx.font = `${fontSize}px Arial`
|
||||
ctx.textAlign = 'center'
|
||||
lines.forEach((ln, index) => {
|
||||
ctx.fillText(ln, qrCanvas.width / 2, qrSize + padding + fontSize / 1.2 + index * lineHeight)
|
||||
})
|
||||
|
||||
// 下载
|
||||
const a = document.createElement('a')
|
||||
a.href = qrCanvas.toDataURL('image/png')
|
||||
a.download = text + '.png'
|
||||
a.click()
|
||||
|
||||
document.body.removeChild(qrContainer)
|
||||
}, 500)
|
||||
},
|
||||
/** 单条下载 */
|
||||
handleDownload(row) {
|
||||
// 构建要传给后端的完整数据结构
|
||||
const payload = {
|
||||
items: [
|
||||
{
|
||||
proName: row.proName || '',
|
||||
departName: row.departName || '',
|
||||
typeName: row.typeName || '',
|
||||
typeModelName: row.typeModelName || '',
|
||||
qualifiedUrl: row.qualifiedUrl || null,
|
||||
testReportUrl: row.testReportUrl || null,
|
||||
thirdReportUrl: row.thirdReportUrl || null,
|
||||
factoryReportUrl: row.factoryReportUrl || null,
|
||||
otherReportUrl: row.otherReportUrl || null,
|
||||
unit:row.unit || '',
|
||||
num:row.num || '',
|
||||
maCode:row.maCode || '',
|
||||
ratedLoad:row.ratedLoad || '',
|
||||
testLoad:row.testLoad || '',
|
||||
holdingTime:row.holdingTime || '',
|
||||
testTime:row.testTime || '',
|
||||
nextTestTime:row.nextTestTime || '',
|
||||
checkResult:row.checkResult || '',
|
||||
remark: ''
|
||||
},
|
||||
],
|
||||
zipName: row.proName || 'report',
|
||||
};
|
||||
|
||||
// 访问后端接口(封装调用)
|
||||
downloadFileApi(payload)
|
||||
.then((res) => {
|
||||
downloadFile({
|
||||
fileName: (row.proName || '文件档案下载') + '.zip',
|
||||
fileData: res,
|
||||
fileType: 'application/zip',
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('单条下载失败:', err);
|
||||
this.$message.error('下载失败');
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 一键下载(多选)
|
||||
*/
|
||||
async handleBulkDownload() {
|
||||
const grouped = {};
|
||||
try {
|
||||
if (!this.infos || !this.infos.length) {
|
||||
this.$message.warning('请先勾选要下载的行');
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建 items
|
||||
const items = this.infos.map((x) => {
|
||||
const r = this.tableList.find(t => t.id === x.id) || {};
|
||||
return {
|
||||
proName: r.proName || '',
|
||||
departName: r.departName || '',
|
||||
typeName: r.typeName || '',
|
||||
typeModelName: r.typeModelName || '',
|
||||
qualifiedUrl: r.qualifiedUrl || null,
|
||||
testReportUrl: r.testReportUrl || null,
|
||||
thirdReportUrl: r.thirdReportUrl || null,
|
||||
factoryReportUrl: r.factoryReportUrl || null,
|
||||
otherReportUrl: r.otherReportUrl || null,
|
||||
unit: r.unit || '',
|
||||
num: r.num || '',
|
||||
maCode: r.maCode || '',
|
||||
ratedLoad: r.ratedLoad || '',
|
||||
testLoad: r.testLoad || '',
|
||||
holdingTime: r.holdingTime || '',
|
||||
testTime: r.testTime || '',
|
||||
nextTestTime: r.nextTestTime || '',
|
||||
checkResult: r.checkResult || '',
|
||||
remark: ''
|
||||
};
|
||||
});
|
||||
|
||||
// 按工程 -> 领用日期 -> 类型-规格分组
|
||||
items.forEach(item => {
|
||||
const proName = item.proName || "";
|
||||
const leaseDate = item.testTime || "";
|
||||
const typeFolder = `${item.typeName || ""}-${item.typeModelName || ""}`;
|
||||
|
||||
if (!grouped[proName]) grouped[proName] = {};
|
||||
if (!grouped[proName][leaseDate]) grouped[proName][leaseDate] = {};
|
||||
if (!grouped[proName][leaseDate][typeFolder]) grouped[proName][leaseDate][typeFolder] = [];
|
||||
|
||||
grouped[proName][leaseDate][typeFolder].push(item);
|
||||
});
|
||||
|
||||
// 拉平成后端需要的数组
|
||||
const flatItems = [];
|
||||
Object.keys(grouped).forEach(proName => {
|
||||
Object.keys(grouped[proName]).forEach(leaseDate => {
|
||||
Object.keys(grouped[proName][leaseDate]).forEach(typeFolder => {
|
||||
grouped[proName][leaseDate][typeFolder].forEach(item => {
|
||||
// 可以把 leaseDate 覆盖到 item.testTime,这样后端就可以直接使用
|
||||
flatItems.push({ ...item, testTime: leaseDate });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
const payload = {
|
||||
items: flatItems,
|
||||
zipName: `报告下载_${(new Date()).toISOString().slice(0,10)}`,
|
||||
};
|
||||
|
||||
// 调用统一的封装接口
|
||||
const res = await batchDownloadFileApi(payload);
|
||||
|
||||
// 前端生成下载
|
||||
downloadFile({
|
||||
fileName: payload.zipName + '.zip',
|
||||
fileData: res,
|
||||
fileType: 'application/zip'
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('一键下载失败', err);
|
||||
this.$message.error('一键下载失败');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
</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;
|
||||
}
|
||||
//隐藏图片上传框的css
|
||||
::v-deep.disabled {
|
||||
.el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue