下料
This commit is contained in:
@@ -181,8 +181,10 @@ export const reqSaveAntiCorrosionCheck = (data={})=>post(`/AntiCorrosionCheck/Sa
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取防腐填报记录
|
* 获取防腐填报记录
|
||||||
* @param {String} materialCode
|
* @param {Object} params - { materialCode, projectId }
|
||||||
*/
|
*/
|
||||||
export const reqGetAntiCorrosionCheck = (params) => get(`/AntiCorrosionCheck/GetRecordsByMaterialCode?materialCode=${params.materialCode}&projectId=${params.projectId}`)
|
export const reqGetAntiCorrosionCheck = (params = {}) => {
|
||||||
|
return get('/AntiCorrosionCheck/GetRecordsByMaterialCode', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1667,3 +1667,100 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== 详情页区块与卡片通用样式(do_anti_rust / 焊口详情页等)=====
|
||||||
|
.section {
|
||||||
|
margin: 0 24rpx 20rpx;
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
margin-bottom: 14rpx;
|
||||||
|
padding: 0 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__bar {
|
||||||
|
width: 6rpx;
|
||||||
|
height: 26rpx;
|
||||||
|
background: #2979ff;
|
||||||
|
border-radius: 3rpx;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #0f1724;
|
||||||
|
letter-spacing: 0.5rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
&__row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 22rpx 28rpx;
|
||||||
|
border-bottom: 1rpx solid #e8ecf1;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--stack {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
.card__label {
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
.card__value-wrap {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
width: 180rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #6b7c93;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #0f1724;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value-wrap {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__unit {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #6b7c93;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__input {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #0f1724;
|
||||||
|
text-align: left;
|
||||||
|
height: 48rpx;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: #b0bec5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,673 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view>
|
|
||||||
<view class="uni-list">
|
|
||||||
<!-- 隐藏画布,用于标签绘制 -->
|
|
||||||
<canvas :id="canvasId" :canvas-id="canvasId" type="2d"
|
|
||||||
:style="{ width: labelWidth + 'px', height: labelHeight + 'px' }"
|
|
||||||
style="position: fixed; left: -999999rpx; top: -999999rpx" />
|
|
||||||
<!-- 打印机列表 -->
|
|
||||||
<view class="uni-list-cell">
|
|
||||||
<view class="uni-list-cell-left">打印机:</view>
|
|
||||||
<view class="uni-list-cell-db">
|
|
||||||
<picker :value="deviceIndex" :range="deviceList" @change="onDeviceChanged" range-key="name">
|
|
||||||
<view class="uni-input">{{ deviceList[deviceIndex].name }}</view>
|
|
||||||
</picker>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 出纸方向 -->
|
|
||||||
<view class="uni-list-cell">
|
|
||||||
<view class="uni-list-cell-left">出纸方向:</view>
|
|
||||||
<view class="uni-list-cell-db">
|
|
||||||
<picker :value="rotationIndex" :range="rotationList" @change="onRotationChanged" range-key="name">
|
|
||||||
<view class="uni-input">{{ rotationList[rotationIndex].name }}</view>
|
|
||||||
</picker>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 标签纸类型 -->
|
|
||||||
<view class="uni-list-cell">
|
|
||||||
<view class="uni-list-cell-left">纸张类型:</view>
|
|
||||||
<view class="uni-list-cell-db">
|
|
||||||
<picker :value="gapIndex" :range="gapList" @change="onGapTypeChanged" range-key="name">
|
|
||||||
<view class="uni-input">{{ gapList[gapIndex].name }}</view>
|
|
||||||
</picker>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 打印浓度 -->
|
|
||||||
<view class="uni-list-cell">
|
|
||||||
<view class="uni-list-cell-left">打印浓度:</view>
|
|
||||||
<view class="uni-list-cell-db">
|
|
||||||
<picker :value="darknessIndex" :range="darknessList" @change="onDarknessChanged" range-key="name">
|
|
||||||
<view class="uni-input">{{ darknessList[darknessIndex].name }}</view>
|
|
||||||
</picker>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 打印速度 -->
|
|
||||||
<view class="uni-list-cell">
|
|
||||||
<view class="uni-list-cell-left">打印速度:</view>
|
|
||||||
<view class="uni-list-cell-db">
|
|
||||||
<picker :value="speedIndex" :range="speedList" @change="onPrintSpeedChanged" range-key="name">
|
|
||||||
<view class="uni-input">{{ speedList[speedIndex].name }}</view>
|
|
||||||
</picker>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 图片处理灰度阈值 -->
|
|
||||||
<view class="uni-list-cell">
|
|
||||||
<view class="uni-list-cell-left">灰度阈值:</view>
|
|
||||||
<view class="uni-list-cell-db">
|
|
||||||
<input class="uni-input" type="number" v-model="threshold" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<!-- 打印方式,两种不同的写法 -->
|
|
||||||
<view class="uni-list-cell uni-list-cell-pd">
|
|
||||||
<view class="uni-list-cell-db">JSON配置模式</view>
|
|
||||||
<switch :checked="jsonMode" @change="onPrintModeChanged" style="transform: scale(0.75)" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="button-sp-area">
|
|
||||||
<button class="mini-btn" type="warn" size="mini" plain="true" @click="handleStopDiscovery">停止搜索</button>
|
|
||||||
<button class="mini-btn" type="primary" size="mini" plain="true" @click="handleStartDiscovery">
|
|
||||||
搜索打印机
|
|
||||||
</button>
|
|
||||||
</view>
|
|
||||||
<view class="button-sp-area">
|
|
||||||
<button class="mini-btn" type="warn" size="mini" plain="true" @click="handleClosePrinter">
|
|
||||||
关闭打印机
|
|
||||||
</button>
|
|
||||||
<button class="mini-btn" type="primary" size="mini" plain="true" @click="handleOpenPrinter">
|
|
||||||
打开打印机
|
|
||||||
</button>
|
|
||||||
<button class="mini-btn" type="primary" size="mini" @click="handlePrintLabel">打印</button>
|
|
||||||
</view>
|
|
||||||
<view style="text-align: center; padding: 10px">
|
|
||||||
<view style="margin: 10px; border: solid lightgray 1px">
|
|
||||||
<image v-for="item in previewList" :src="item.value" :key="item.key" class="image" mode="widthFix"
|
|
||||||
style="margin: 10rpx; border: dashed lightgray 1px" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {
|
|
||||||
DrawType,
|
|
||||||
LPAPIFactory,
|
|
||||||
LPAPI
|
|
||||||
} from "../../uni_modules/dothan-lpapi-ble/js_sdk";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
canvasId: "lpapi-ble-uni1",
|
|
||||||
labelWidth: 960,
|
|
||||||
labelHeight: 960,
|
|
||||||
deviceList: [{
|
|
||||||
name: "未检测到打印机",
|
|
||||||
}, ],
|
|
||||||
rotationIndex: 0,
|
|
||||||
rotationList: [{
|
|
||||||
name: "横向打印",
|
|
||||||
value: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "右转90度",
|
|
||||||
value: 90
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "转转180度",
|
|
||||||
value: 180
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "左转90度",
|
|
||||||
value: 270
|
|
||||||
},
|
|
||||||
],
|
|
||||||
deviceIndex: 0,
|
|
||||||
gapList: [{
|
|
||||||
name: "随打印机设置",
|
|
||||||
value: 255
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "小票纸",
|
|
||||||
value: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "不干胶",
|
|
||||||
value: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "卡纸",
|
|
||||||
value: 3
|
|
||||||
},
|
|
||||||
],
|
|
||||||
gapIndex: 0,
|
|
||||||
darknessList: [{
|
|
||||||
name: "随打印机设置",
|
|
||||||
value: 255
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "6 (正常)",
|
|
||||||
value: 6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "7",
|
|
||||||
value: 7
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "8",
|
|
||||||
value: 8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "9",
|
|
||||||
value: 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "10 (较浓)",
|
|
||||||
value: 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "11",
|
|
||||||
value: 11
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "12",
|
|
||||||
value: 12
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "13",
|
|
||||||
value: 13
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "14",
|
|
||||||
value: 14
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "15 (最浓)",
|
|
||||||
value: 15
|
|
||||||
},
|
|
||||||
],
|
|
||||||
darknessIndex: 0,
|
|
||||||
speedList: [{
|
|
||||||
name: "随打印机设置",
|
|
||||||
value: 255
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "最慢",
|
|
||||||
value: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "较慢",
|
|
||||||
value: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "正常",
|
|
||||||
value: 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "较快",
|
|
||||||
value: 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "最快",
|
|
||||||
value: 5
|
|
||||||
},
|
|
||||||
],
|
|
||||||
speedIndex: 0,
|
|
||||||
isAppPlus: false,
|
|
||||||
isWeiXin: false,
|
|
||||||
isAlipay: false,
|
|
||||||
/**
|
|
||||||
* 图片预览列表
|
|
||||||
* @type {{value: string; key: string;}[]}
|
|
||||||
***/
|
|
||||||
previewList: [],
|
|
||||||
threshold: 128,
|
|
||||||
jsonMode: false,
|
|
||||||
/**
|
|
||||||
* @type {LPAPI}
|
|
||||||
*/
|
|
||||||
lpapi: undefined,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
onLoad(options) {
|
|
||||||
console.log("========== onLoad ==========");
|
|
||||||
//option为object类型,会序列化上个页面传递的参数
|
|
||||||
console.log(`---- type = ${options.type}`, options);
|
|
||||||
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
this.isAppPlus = true;
|
|
||||||
// #endif
|
|
||||||
// #ifdef MP-ALIPAY
|
|
||||||
this.isAlipay = true;
|
|
||||||
// #endif
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
this.isWeiXin = true;
|
|
||||||
// #endif
|
|
||||||
//
|
|
||||||
this.lpapi = LPAPIFactory.getInstance({
|
|
||||||
// 日志信息显示级别,值为 0 - 4,0表示不显示调试信息,4表示显示所有调试信息
|
|
||||||
showLog: 4,
|
|
||||||
// bleAdapter: bleAdapter,
|
|
||||||
// writeExtendWaits: 3,
|
|
||||||
// dataSendMode: 1,
|
|
||||||
});
|
|
||||||
// 搜索蓝牙设备
|
|
||||||
this.lpapi.startDiscovery({
|
|
||||||
timeout: 0,
|
|
||||||
deviceFound: (devices) => {
|
|
||||||
this.onDeviceFound(devices);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// 微信小程序、支付宝小程序创建绘制上下文的时候,可以不用传递 canvasId,此时会通过离屏Canvas来创建绘制上下文环境。
|
|
||||||
if (this.isWeiXin) {
|
|
||||||
this.context = this.lpapi.createDrawContext();
|
|
||||||
} else {
|
|
||||||
// 备注:支付宝小程序新版本有问题,需要去掉 canvas 中的 type="2d"才可以。
|
|
||||||
this.context = this.lpapi.createDrawContext({
|
|
||||||
// 用于进行标签绘制的画布ID
|
|
||||||
canvasId: this.canvasId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//
|
|
||||||
if (this.context) {
|
|
||||||
this.lpapi.setDrawContext(this.context);
|
|
||||||
// 预览标签内容
|
|
||||||
this.handlePreviewLabel();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onCanvasReady() {
|
|
||||||
console.log("========== onCanvasReady ==========");
|
|
||||||
console.log(`---- isAlipay: ${this.isAlipay}`);
|
|
||||||
if (this.isAlipay) {
|
|
||||||
// 支付宝小程序中在屏 Canvas的使用的时候,1:配置 type="2d",2:设置 onReady 事件,在onReady中通过 selectorQuery来获取canvas实例。
|
|
||||||
// this.queryCanvas((canvas) => {
|
|
||||||
// this.context = this.lpapi.createDrawContext({
|
|
||||||
// canvas: canvas,
|
|
||||||
// });
|
|
||||||
// if (this.context) {
|
|
||||||
// this.lpapi.setDrawContext(this.context);
|
|
||||||
// }
|
|
||||||
// this.handlePreviewLabel();
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onShow() {
|
|
||||||
console.log("========== onShow ==========");
|
|
||||||
// 建议在 onShow的时候,修改下标签的绘制上下文,避免因在context没有更新导致的 canvas不显示的问题。
|
|
||||||
if (this.context) {
|
|
||||||
this.lpapi.setDrawContext(this.context);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onUnload() {
|
|
||||||
console.log("========== onUnload ==========");
|
|
||||||
this.handleClosePrinter();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
queryCanvas(callback) {
|
|
||||||
// 微信小程序、支付宝小程序等 最新版本初始化方式
|
|
||||||
// 注意:canvas 中必须配置 type="2d" 才能生效。
|
|
||||||
try {
|
|
||||||
uni.createSelectorQuery()
|
|
||||||
.select(`#${this.canvasId}`)
|
|
||||||
.node()
|
|
||||||
.exec((res) => {
|
|
||||||
console.log(`------- exec.result: --------`);
|
|
||||||
console.log(res);
|
|
||||||
const canvas = res[0]?.node;
|
|
||||||
// this.printCanvas = canvas;
|
|
||||||
callback(canvas);
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(`---- 不支持通过该方式获取 Canvas 对象!`);
|
|
||||||
console.warn(e);
|
|
||||||
callback(undefined);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onDeviceChanged(e) {
|
|
||||||
console.log(`---------- onDeviceChanged:${e.detail.value} ----------`);
|
|
||||||
this.deviceIndex = e ? e.detail.value : 0;
|
|
||||||
},
|
|
||||||
onRotationChanged(e) {
|
|
||||||
console.log(`---------- onRotationChanged: ${e.detail.value} ----------`);
|
|
||||||
this.rotationIndex = e ? e.detail.value : 0;
|
|
||||||
},
|
|
||||||
onGapTypeChanged(e) {
|
|
||||||
console.log(`---------- onGapTypeChanged:${e.detail.value} ----------`);
|
|
||||||
this.gapIndex = e ? e.detail.value : 0;
|
|
||||||
},
|
|
||||||
onDarknessChanged(e) {
|
|
||||||
console.log(`---------- onDarknessChanged:${e.detail.value} ----------`);
|
|
||||||
this.darknessIndex = e ? e.detail.value : 0;
|
|
||||||
},
|
|
||||||
onPrintSpeedChanged(e) {
|
|
||||||
console.log(`---------- onPrintSpeedChanged:${e.detail.value} ----------`);
|
|
||||||
this.speedIndex = e ? e.detail.value : 0;
|
|
||||||
},
|
|
||||||
onPrintModeChanged(e) {
|
|
||||||
console.log(`---------- onPrintModeChanged: ${e.detail.value} ----------`);
|
|
||||||
this.jsonMode = e.detail.value;
|
|
||||||
this.handlePreviewLabel();
|
|
||||||
},
|
|
||||||
handleStartDiscovery() {
|
|
||||||
uni.showLoading({
|
|
||||||
title: "正在搜索打印机...",
|
|
||||||
});
|
|
||||||
this.lpapi.startDiscovery({
|
|
||||||
timeout: 5000,
|
|
||||||
deviceFound: (devices) => {
|
|
||||||
this.onDeviceFound(devices);
|
|
||||||
},
|
|
||||||
adapterStateChange: (result) => {
|
|
||||||
if (!result.discovering) {
|
|
||||||
uni.hideLoading();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleStopDiscovery() {
|
|
||||||
this.lpapi.stopDiscovery();
|
|
||||||
},
|
|
||||||
handleOpenPrinter() {
|
|
||||||
const currDevice = this.getDevice();
|
|
||||||
const isAlipay = this.isAlipay;
|
|
||||||
if (currDevice && currDevice.deviceId) {
|
|
||||||
//
|
|
||||||
uni.showLoading({
|
|
||||||
title: "正在链接打印机...",
|
|
||||||
});
|
|
||||||
return this.lpapi
|
|
||||||
.openPrinter({
|
|
||||||
name: currDevice.name,
|
|
||||||
deviceId: currDevice.deviceId,
|
|
||||||
// 如果打印机链接失败的话,可以尝试连续进行多次链接。
|
|
||||||
tryTimes: isAlipay ? 1 : 5,
|
|
||||||
success: (resp) => {
|
|
||||||
console.log(`---- 【打印机链接成功】`);
|
|
||||||
console.log(resp.resultInfo);
|
|
||||||
uni.hideLoading();
|
|
||||||
//
|
|
||||||
uni.showToast({
|
|
||||||
title: "打印机链接成功!",
|
|
||||||
icon: "success",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
fail: (resp) => {
|
|
||||||
console.warn(`---- 【打印机链接失败】:`);
|
|
||||||
console.warn(JSON.stringify(resp));
|
|
||||||
//
|
|
||||||
uni.hideLoading();
|
|
||||||
//
|
|
||||||
uni.showToast({
|
|
||||||
title: "打印机链接失败!",
|
|
||||||
icon: "fail",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((res) => {
|
|
||||||
return res.statusCode === 0;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.warn("---- 未检测到打印机!");
|
|
||||||
uni.showToast({
|
|
||||||
title: "未检测到打印机",
|
|
||||||
icon: "fail",
|
|
||||||
});
|
|
||||||
if (typeof callback === "function") {
|
|
||||||
callback(false);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleClosePrinter() {
|
|
||||||
console.log(`---- 关闭打印机!`);
|
|
||||||
this.lpapi.closePrinter();
|
|
||||||
},
|
|
||||||
onDeviceFound(devices) {
|
|
||||||
console.log(`---- 检测到打印机:`);
|
|
||||||
console.log(devices);
|
|
||||||
if (devices && devices.length > 0) {
|
|
||||||
this.deviceList.splice(0);
|
|
||||||
for (let item of devices) {
|
|
||||||
this.deviceList.push(item);
|
|
||||||
//
|
|
||||||
// const advertisData = item.advertisData ? new Uint8Array(item.advertisData) : undefined;
|
|
||||||
// const advDataStr = advertisData ? LPAUtils.arrayBufferToHex16(advertisData) : "-";
|
|
||||||
// console.log(`---- advertisData [${item.name}] : [${advDataStr}]`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getDevice() {
|
|
||||||
return this.deviceList[this.deviceIndex];
|
|
||||||
},
|
|
||||||
getOrientation() {
|
|
||||||
return this.rotationList[this.rotationIndex].value;
|
|
||||||
},
|
|
||||||
getGapType() {
|
|
||||||
return this.gapList[this.gapIndex].value;
|
|
||||||
},
|
|
||||||
getPrintDarkness() {
|
|
||||||
return this.darknessList[this.darknessIndex].value;
|
|
||||||
},
|
|
||||||
getPrintSpeed() {
|
|
||||||
return this.speedList[this.speedIndex].value;
|
|
||||||
},
|
|
||||||
getThreshold() {
|
|
||||||
return Number(this.threshold);
|
|
||||||
},
|
|
||||||
updateCanvas(jobInfo) {
|
|
||||||
// 如果通过 createSelectorQuery 获取到了 Canvas 实例,则不需要延迟处理;
|
|
||||||
// 在微信小程序、支付宝小程序中是支持该功能的;
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
// 更新canvas大小;
|
|
||||||
if (jobInfo.canvas) {
|
|
||||||
this.labelWidth = jobInfo.canvas.width;
|
|
||||||
this.labelHeight = jobInfo.canvas.height;
|
|
||||||
// 等 Canvas 大小更新后在执行后续绘制操作;
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve(true);
|
|
||||||
}, 100);
|
|
||||||
} else {
|
|
||||||
resolve(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handlePreviewLabel() {
|
|
||||||
// 1. 先清空当前的图片列表
|
|
||||||
this.previewList.splice(0);
|
|
||||||
// 2. 创建并绘制标签内容
|
|
||||||
this.printLabel(true).then((res) => {
|
|
||||||
console.warn(`----- previewLabel.result: ${res.statusCode}`, res.errMsg);
|
|
||||||
// 3. 标签绘制完毕后,预览标签内容
|
|
||||||
if (res.statusCode === 0) {
|
|
||||||
console.warn(`---- 所有页面全部生成完毕!`);
|
|
||||||
res.previewData.forEach((value) => {
|
|
||||||
this.previewList.push({
|
|
||||||
value: value,
|
|
||||||
// 为了保证 v-for循环的唯一性,随便生成一个随机ID
|
|
||||||
key: `${new Date().getTime()}-${Math.random() * 1000}`,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.warn(`---- 标签预览失败!`, res);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
async handlePrintLabel() {
|
|
||||||
// 1. 连接打印机
|
|
||||||
const openResult = await this.handleOpenPrinter();
|
|
||||||
if (!openResult) {
|
|
||||||
uni.showToast({
|
|
||||||
title: "打印机连接失败!",
|
|
||||||
icon: "success",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 2. 创建标签后直接打印
|
|
||||||
this.printLabel(false).then((res) => {
|
|
||||||
if (res.statusCode === 0) {
|
|
||||||
uni.showToast({
|
|
||||||
title: "打印成功!",
|
|
||||||
icon: "success",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.warn(`---- 打印失败!`);
|
|
||||||
if (res.errMsg) {
|
|
||||||
uni.showToast({
|
|
||||||
title: res.errMsg,
|
|
||||||
icon: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
printLabel(isPreview) {
|
|
||||||
if (this.jsonMode) {
|
|
||||||
return this.printLabelWithJsonMode(isPreview);
|
|
||||||
} else {
|
|
||||||
return this.printLabelWithDrawMode(isPreview);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 通过 draw 的方式绘制标签内容。
|
|
||||||
*/
|
|
||||||
async printLabelWithDrawMode(isPreview) {
|
|
||||||
console.log(`---- qrcodePrintWithDrawMode:`);
|
|
||||||
const api = this.lpapi;
|
|
||||||
//
|
|
||||||
const labelWidth = 40;
|
|
||||||
const labelHeight = 30;
|
|
||||||
const margin = 2;
|
|
||||||
//
|
|
||||||
const jobInfo = api.startJob({
|
|
||||||
context: this.context,
|
|
||||||
width: labelWidth,
|
|
||||||
height: labelHeight,
|
|
||||||
orientation: this.getOrientation(),
|
|
||||||
isPreview: isPreview,
|
|
||||||
});
|
|
||||||
//
|
|
||||||
await this.updateCanvas(jobInfo);
|
|
||||||
// 绘制外边框
|
|
||||||
api.drawRectangle({
|
|
||||||
width: labelWidth,
|
|
||||||
height: labelHeight,
|
|
||||||
});
|
|
||||||
api.draw1DBarcode({
|
|
||||||
text: "12345678",
|
|
||||||
x: margin,
|
|
||||||
y: margin,
|
|
||||||
width: labelWidth - margin * 2,
|
|
||||||
height: labelHeight - margin * 2,
|
|
||||||
textHeight: 5,
|
|
||||||
barcodeType: 22,
|
|
||||||
});
|
|
||||||
//
|
|
||||||
return api.commitJob({
|
|
||||||
gapType: this.getGapType(),
|
|
||||||
printDarkness: this.getPrintDarkness(),
|
|
||||||
printSpeed: this.getPrintSpeed(),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 通过 JSON 方式绘制标签内容。
|
|
||||||
*/
|
|
||||||
printLabelWithJsonMode(isPreview) {
|
|
||||||
console.log(`---- qrcodePrintWithJsonMode:`);
|
|
||||||
const device = this.getDevice();
|
|
||||||
const labelWidth = 40;
|
|
||||||
const labelHeight = 30;
|
|
||||||
const margin = 2;
|
|
||||||
//
|
|
||||||
return this.lpapi.print({
|
|
||||||
// 配置标签信息
|
|
||||||
jobInfo: {
|
|
||||||
jobWidth: labelWidth,
|
|
||||||
jobHeight: labelHeight,
|
|
||||||
orientation: this.getOrientation(),
|
|
||||||
isPreview: isPreview, // 当前任务是否是预览任务
|
|
||||||
},
|
|
||||||
// 配置打印机信息
|
|
||||||
printerInfo: {
|
|
||||||
name: device?.name,
|
|
||||||
deviceId: device?.deviceId,
|
|
||||||
},
|
|
||||||
jobPage: [{
|
|
||||||
type: DrawType.rect,
|
|
||||||
width: labelWidth,
|
|
||||||
height: labelHeight,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: DrawType.barcode,
|
|
||||||
text: "12345678",
|
|
||||||
x: margin,
|
|
||||||
y: margin,
|
|
||||||
width: labelWidth - margin * 2,
|
|
||||||
height: labelHeight - margin * 2,
|
|
||||||
textHeight: 5,
|
|
||||||
barcodeType: 22,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
onJobCreated: (jobInfo) => {
|
|
||||||
// 通过双向绑定方式更新画布大小
|
|
||||||
return this.updateCanvas(jobInfo);
|
|
||||||
},
|
|
||||||
onPageComplete(res) {
|
|
||||||
// 标签页面渲染完毕时的回调函数,预览模式下可展示标签打印效果。
|
|
||||||
},
|
|
||||||
onPagePrintComplete(res) {
|
|
||||||
// 标签页面打印完毕时的回调函数。
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
button {
|
|
||||||
margin-top: 15upx;
|
|
||||||
margin-bottom: 15upx;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
height: 200rpx;
|
|
||||||
width: 200rpx;
|
|
||||||
margin: 200rpx auto 50rpx auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-area {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 36rpx;
|
|
||||||
color: #8f8f94;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin-top: 30rpx;
|
|
||||||
margin-bottom: 30rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-sp-area {
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 90%;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mini-btn {
|
|
||||||
flex: 1;
|
|
||||||
margin-right: 10rpx;
|
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<!-- 有记录 -->
|
<!-- 有记录 -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<view class="anti-record__section">
|
<view class="anti-record__section" :style="{ ...props.customStyle }">
|
||||||
<view class="anti-record__header">
|
<view class="anti-record__header">
|
||||||
<view class="anti-record__bar"></view>
|
<view class="anti-record__bar"></view>
|
||||||
<text class="anti-record__title">防腐记录</text>
|
<text class="anti-record__title">防腐记录</text>
|
||||||
@@ -39,6 +39,18 @@
|
|||||||
<text class="anti-record__label">漆膜厚度</text>
|
<text class="anti-record__label">漆膜厚度</text>
|
||||||
<text class="anti-record__value">{{ latest.FilmThickness || '--' }}</text>
|
<text class="anti-record__value">{{ latest.FilmThickness || '--' }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="anti-record__row">
|
||||||
|
<text class="anti-record__label">喷砂情况</text>
|
||||||
|
<view class="anti-record__value">
|
||||||
|
{{ latest.SandBlasting || '--' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="anti-record__row">
|
||||||
|
<text class="anti-record__label">除锈喷砂情况</text>
|
||||||
|
<view class="anti-record__value">
|
||||||
|
{{ latest.RustSandBlasting || '--' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
<view class="anti-record__row">
|
<view class="anti-record__row">
|
||||||
<text class="anti-record__label">检查人</text>
|
<text class="anti-record__label">检查人</text>
|
||||||
<text class="anti-record__value">{{ latest.CheckPersonName || '--' }}</text>
|
<text class="anti-record__value">{{ latest.CheckPersonName || '--' }}</text>
|
||||||
@@ -56,15 +68,21 @@
|
|||||||
<text class="anti-record__tag-text">{{ latest.CheckResult || '--' }}</text>
|
<text class="anti-record__tag-text">{{ latest.CheckResult || '--' }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="anti-record__row anti-record__row--stack">
|
<view class="anti-record__row" v-if="latest.CheckResult !== '合格'">
|
||||||
<text class="anti-record__label--stack">不合格原因</text>
|
<view class="anti-record__label">不合格原因</view>
|
||||||
<text class="anti-record__value anti-record__value--stack">{{ latest.UnqualifiedReason }}</text>
|
<text class="anti-record__value">{{ latest.UnqualifiedReason }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="anti-record__row anti-record__row--stack">
|
<view class="anti-record__row" v-if="latest.CheckResult !== '合格'">
|
||||||
<text class="anti-record__label--stack">整改要求</text>
|
<view class="anti-record__label">整改要求</view>
|
||||||
<text class="anti-record__value anti-record__value--stack">{{ latest.RectifyRequirement
|
<text class="anti-record__value">{{ latest.RectifyRequirement
|
||||||
}}</text>
|
}}</text>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="anti-record__row--stack">
|
||||||
|
<text class="anti-record__label--stack">照片</text>
|
||||||
|
<view class="anti-record__value--stack">
|
||||||
|
<nbd-photo-view :attachUrl="latest.AttachUrl1" :cols="4" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -95,6 +113,18 @@
|
|||||||
<text class="anti-record__label">漆膜厚度</text>
|
<text class="anti-record__label">漆膜厚度</text>
|
||||||
<text class="anti-record__value">{{ item.FilmThickness || '--' }}</text>
|
<text class="anti-record__value">{{ item.FilmThickness || '--' }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="anti-record__row">
|
||||||
|
<text class="anti-record__label">喷砂情况</text>
|
||||||
|
<view class="anti-record__value">
|
||||||
|
{{ item.SandBlasting || '--' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="anti-record__row">
|
||||||
|
<text class="anti-record__label">除锈喷砂情况</text>
|
||||||
|
<view class="anti-record__value">
|
||||||
|
{{ item.RustSandBlasting || '--' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
<view class="anti-record__row">
|
<view class="anti-record__row">
|
||||||
<text class="anti-record__label">检查人</text>
|
<text class="anti-record__label">检查人</text>
|
||||||
<text class="anti-record__value">{{ item.CheckPersonName || '--' }}</text>
|
<text class="anti-record__value">{{ item.CheckPersonName || '--' }}</text>
|
||||||
@@ -113,15 +143,21 @@
|
|||||||
<text class="anti-record__tag-text">{{ item.CheckResult || '--' }}</text>
|
<text class="anti-record__tag-text">{{ item.CheckResult || '--' }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="anti-record__row anti-record__row--stack" v-if="item.CheckResult === '不合格'">
|
<view class="anti-record__row" v-if="item.CheckResult === '不合格'">
|
||||||
<text class="anti-record__label--stack">不合格原因</text>
|
<text class="anti-record__label">不合格原因</text>
|
||||||
<text class="anti-record__value anti-record__value--stack">{{ item.UnqualifiedReason
|
<view class="anti-record__value">{{ item.UnqualifiedReason
|
||||||
}}</text>
|
}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="anti-record__row" v-if="item.CheckResult === '不合格'">
|
||||||
|
<text class="anti-record__label">整改要求</text>
|
||||||
|
<view class="anti-record__value-">{{ item.RectifyRequirement
|
||||||
|
}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="anti-record__row--stack">
|
||||||
|
<text class="anti-record__label--stack">照片</text>
|
||||||
|
<view class="anti-record__value--stack">
|
||||||
|
<nbd-photo-view :attachUrl="item.AttachUrl1" :cols="4" />
|
||||||
</view>
|
</view>
|
||||||
<view class="anti-record__row anti-record__row--stack" v-if="item.CheckResult === '不合格'">
|
|
||||||
<text class="anti-record__label--stack">整改要求</text>
|
|
||||||
<text class="anti-record__value anti-record__value--stack">{{ item.RectifyRequirement
|
|
||||||
}}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
@@ -136,7 +172,8 @@ import { ref, computed, watch } from 'vue'
|
|||||||
import { reqGetAntiCorrosionCheck } from '@/api/hj.js'
|
import { reqGetAntiCorrosionCheck } from '@/api/hj.js'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
params: { type: Object, default: () => ({}) }
|
params: { type: Object, default: () => ({}) },
|
||||||
|
customStyle: { type: Object, default: () => ({}) },
|
||||||
})
|
})
|
||||||
|
|
||||||
const list = ref([])
|
const list = ref([])
|
||||||
@@ -146,9 +183,11 @@ const showPopup = ref(false)
|
|||||||
const latest = computed(() => list.value[0] || null)
|
const latest = computed(() => list.value[0] || null)
|
||||||
|
|
||||||
const fetchRecords = async () => {
|
const fetchRecords = async () => {
|
||||||
|
|
||||||
const { materialCode, projectId } = props.params
|
const { materialCode, projectId } = props.params
|
||||||
if (!materialCode || !projectId) return
|
if (!materialCode || !projectId) return
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await reqGetAntiCorrosionCheck(props.params)
|
const res = await reqGetAntiCorrosionCheck(props.params)
|
||||||
if (res.code === 1 && res.data) {
|
if (res.code === 1 && res.data) {
|
||||||
@@ -261,6 +300,7 @@ $text-secondary: #8e99a4;
|
|||||||
}
|
}
|
||||||
|
|
||||||
&--stack {
|
&--stack {
|
||||||
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
||||||
.anti-record__value {
|
.anti-record__value {
|
||||||
@@ -275,7 +315,7 @@ $text-secondary: #8e99a4;
|
|||||||
color: $text-secondary;
|
color: $text-secondary;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-right: 24rpx;
|
margin-right: 24rpx;
|
||||||
width: 140rpx;
|
width: 160rpx;
|
||||||
|
|
||||||
&--stack {
|
&--stack {
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
@@ -295,6 +335,9 @@ $text-secondary: #8e99a4;
|
|||||||
|
|
||||||
&--stack {
|
&--stack {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
|
padding-left: 20rpx;
|
||||||
|
padding-bottom: 8rpx;
|
||||||
|
padding-top: 8rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +398,7 @@ $text-secondary: #8e99a4;
|
|||||||
|
|
||||||
&__popup {
|
&__popup {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 70vh;
|
height: 80vh;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 24rpx 24rpx 0 0;
|
border-radius: 24rpx 24rpx 0 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<view class="nvd-photo-view">
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view v-if="photos.length === 0" class="nvd-photo-view__empty">
|
||||||
|
<text class="nvd-photo-view__empty-text">暂无图片</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 图片网格 -->
|
||||||
|
<view v-else class="nvd-photo-view__grid">
|
||||||
|
<view
|
||||||
|
v-for="(photo, index) in photos"
|
||||||
|
:key="photo._id"
|
||||||
|
class="nvd-photo-view__item"
|
||||||
|
:style="{ width: `${750 / cols}rpx`, height: `${750 / cols}rpx` }"
|
||||||
|
@click="handlePreview(index)"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
class="nvd-photo-view__img"
|
||||||
|
:src="photo.src"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { parseAttachUrls } from '@/utils/request.js'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
/** 逗号分隔的附件路径字符串,如 "FileUpLoad/a.png,FileUpLoad/b.png" */
|
||||||
|
attachUrl: { type: String, default: '' },
|
||||||
|
/** 每行显示列数 */
|
||||||
|
cols: { type: Number, default: 3 }
|
||||||
|
})
|
||||||
|
|
||||||
|
const photos = computed(() => {
|
||||||
|
if (!props.attachUrl) return []
|
||||||
|
return parseAttachUrls(props.attachUrl)
|
||||||
|
})
|
||||||
|
|
||||||
|
const handlePreview = (index) => {
|
||||||
|
const urls = photos.value.map((p) => p.src)
|
||||||
|
uni.previewImage({ current: index, urls })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$radius: 10rpx;
|
||||||
|
$gap: 10rpx;
|
||||||
|
|
||||||
|
.nvd-photo-view {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&__empty {
|
||||||
|
padding: 48rpx 24rpx;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&-text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #8e99a4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
padding: 12rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: $radius;
|
||||||
|
background: #f0f2f5;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
<view class="card">
|
<view class="card">
|
||||||
<!-- 防腐等级/涂漆代码(下拉选择) -->
|
<!-- 防腐等级/涂漆代码(下拉选择) -->
|
||||||
<view class="card__row" @click="showPaintCodePicker = true">
|
<view class="card__row" @click="showPaintCodePicker = true">
|
||||||
<text class="card__label">防腐等级</text>
|
<text class="card__label required">防腐等级</text>
|
||||||
<view class="card__value-wrap card__value-wrap--clickable">
|
<view class="card__value-wrap card__value-wrap--clickable">
|
||||||
<text class="card__value" :class="{ 'card__value--placeholder': !antiForm.AnticorrosionLevel }">
|
<text class="card__value" :class="{ 'card__value--placeholder': !antiForm.AnticorrosionLevel }">
|
||||||
{{ antiForm.AnticorrosionLevel || '请选择防腐等级' }}
|
{{ antiForm.AnticorrosionLevel || '请选择防腐等级' }}
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<!-- 漆膜厚度 -->
|
<!-- 漆膜厚度 -->
|
||||||
<view class="card__row">
|
<view class="card__row">
|
||||||
<text class="card__label">漆膜厚度</text>
|
<text class="card__label required">漆膜厚度</text>
|
||||||
<view class="card__value-wrap">
|
<view class="card__value-wrap">
|
||||||
<input class="card__input" v-model="antiForm.FilmThickness" type="digit"
|
<input class="card__input" v-model="antiForm.FilmThickness" type="digit"
|
||||||
placeholder="请输入漆膜厚度" />
|
placeholder="请输入漆膜厚度" />
|
||||||
@@ -118,14 +118,13 @@
|
|||||||
<view class="card__row">
|
<view class="card__row">
|
||||||
<text class="card__label">自检结果</text>
|
<text class="card__label">自检结果</text>
|
||||||
<view class="card__value-wrap card__value-wrap--clickable">
|
<view class="card__value-wrap card__value-wrap--clickable">
|
||||||
<nbd-check-btn v-model="antiForm.CheckResult" passKey="合格" failKey="不合格" passText="合格" failText="不合格" />
|
<nbd-check-btn v-model="antiForm.CheckResult" passKey="合格" failKey="不合格" passText="合格"
|
||||||
|
failText="不合格" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view
|
<view class="fail-section"
|
||||||
class="fail-section"
|
:class="{ 'is-visible': failVisible, 'is-enter': failAnimating, 'is-leave': failLeaving }">
|
||||||
:class="{ 'is-visible': failVisible, 'is-enter': failAnimating, 'is-leave': failLeaving }"
|
|
||||||
>
|
|
||||||
<!-- 不合格原因 -->
|
<!-- 不合格原因 -->
|
||||||
<view class="card__row card__row--stack">
|
<view class="card__row card__row--stack">
|
||||||
<text class="card__label">不合格原因</text>
|
<text class="card__label">不合格原因</text>
|
||||||
@@ -180,7 +179,7 @@ import { onLoad } from '@dcloudio/uni-app'
|
|||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { watch, nextTick } from 'vue'
|
import { watch, nextTick } from 'vue'
|
||||||
import { useUserStore } from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
import { reqMaterialInfoByMaterialCode, reqPaintCodeList, reqSaveAntiCorrosionCheck } from '@/api/hj.js'
|
import { reqMaterialInfoByMaterialCode, reqPaintCodeList, reqSaveAntiCorrosionCheck , reqGetAntiCorrosionCheck } from '@/api/hj.js'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const { userInfo, currentProject } = storeToRefs(userStore)
|
const { userInfo, currentProject } = storeToRefs(userStore)
|
||||||
@@ -258,10 +257,25 @@ onLoad((opt) => {
|
|||||||
const loadData = async (id) => {
|
const loadData = async (id) => {
|
||||||
try {
|
try {
|
||||||
uni.showLoading({ title: '加载中...', mask: true })
|
uni.showLoading({ title: '加载中...', mask: true })
|
||||||
const res = await reqMaterialInfoByMaterialCode(encodeURIComponent(id))
|
const [res, res1] = await Promise.all([
|
||||||
|
reqMaterialInfoByMaterialCode(encodeURIComponent(id)),
|
||||||
|
reqGetAntiCorrosionCheck({ materialCode: id, projectId: currentProject.value.ProjectId })
|
||||||
|
])
|
||||||
if (res.code === 1 && res.data) {
|
if (res.code === 1 && res.data) {
|
||||||
form.value = res.data
|
form.value = res.data
|
||||||
}
|
}
|
||||||
|
if (res1.code === 1 && res1.data) {
|
||||||
|
let antiData = res1.data
|
||||||
|
if(antiData&&antiData.length>0){
|
||||||
|
antiForm.value = {
|
||||||
|
...antiData[0],
|
||||||
|
CheckResult: '合格',
|
||||||
|
UnqualifiedReason: '',
|
||||||
|
RectifyRequirement: '',
|
||||||
|
Remark: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('加载焊口数据失败:', err)
|
console.error('加载焊口数据失败:', err)
|
||||||
uni.showToast({ title: '加载失败', icon: 'none' })
|
uni.showToast({ title: '加载失败', icon: 'none' })
|
||||||
@@ -271,15 +285,15 @@ const loadData = async (id) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
// if (!antiForm.value.PaintId) {
|
if (!antiForm.value.PaintId) {
|
||||||
// uni.showToast({ title: '请选择防腐等级', icon: 'none' })
|
uni.showToast({ title: '请选择防腐等级', icon: 'none' })
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
if( !antiForm.value.UnqualifiedReason && antiForm.value.CheckResult === '不合格') {
|
if (!antiForm.value.UnqualifiedReason && antiForm.value.CheckResult === '不合格') {
|
||||||
uni.showToast({ title: '请输入不合格原因', icon: 'none' })
|
uni.showToast({ title: '请输入不合格原因', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if( !antiForm.value.RectifyRequirement && antiForm.value.CheckResult === '不合格') {
|
if (!antiForm.value.RectifyRequirement && antiForm.value.CheckResult === '不合格') {
|
||||||
uni.showToast({ title: '请输入整改要求', icon: 'none' })
|
uni.showToast({ title: '请输入整改要求', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -311,7 +325,7 @@ const handleSubmit = async () => {
|
|||||||
CreateUser: userInfo.PersonId, // 创建人员
|
CreateUser: userInfo.PersonId, // 创建人员
|
||||||
AttachUrl1: files.value, // 照片
|
AttachUrl1: files.value, // 照片
|
||||||
}
|
}
|
||||||
console.log("提交数据==============>",data)
|
console.log("提交数据==============>", data)
|
||||||
try {
|
try {
|
||||||
const res = await reqSaveAntiCorrosionCheck(data)
|
const res = await reqSaveAntiCorrosionCheck(data)
|
||||||
if (res.code === 1) {
|
if (res.code === 1) {
|
||||||
@@ -448,6 +462,7 @@ $shadow-md: 0 2rpx 12rpx rgba(0, 0, 0, 0.04), 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(24rpx);
|
transform: translateY(24rpx);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
@@ -455,9 +470,12 @@ $shadow-md: 0 2rpx 12rpx rgba(0, 0, 0, 0.04), 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes breathe {
|
@keyframes breathe {
|
||||||
0%, 100% {
|
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
@@ -468,8 +486,13 @@ $shadow-md: 0 2rpx 12rpx rgba(0, 0, 0, 0.04), 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
|
|||||||
margin: 0 24rpx 20rpx;
|
margin: 0 24rpx 20rpx;
|
||||||
animation: fadeUp 0.5s ease-out both;
|
animation: fadeUp 0.5s ease-out both;
|
||||||
|
|
||||||
&:nth-child(2) { animation-delay: 0.05s; }
|
&:nth-child(2) {
|
||||||
&:nth-child(3) { animation-delay: 0.15s; }
|
animation-delay: 0.05s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
animation-delay: 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -599,6 +622,10 @@ $shadow-md: 0 2rpx 12rpx rgba(0, 0, 0, 0.04), 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
|
|||||||
background: $primary-mid;
|
background: $primary-mid;
|
||||||
border-radius: 2rpx;
|
border-radius: 2rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.required::before {
|
||||||
|
background: #ff0000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__value {
|
&__value {
|
||||||
|
|||||||
+223
-236
@@ -15,96 +15,48 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 坡口参数 - 测量仪表 -->
|
<block v-for="(item, index) in info.preWeldMaterialItems" :key="item.MaterialCode || index">
|
||||||
<!-- <view class="section">
|
<!-- 材料信息 -->
|
||||||
<view class="section__header">
|
|
||||||
<view class="section__bar"></view>
|
|
||||||
<text class="section__title">坡口参数</text>
|
|
||||||
</view>
|
|
||||||
<view class="spec-grid">
|
|
||||||
<view class="spec-item">
|
|
||||||
<view class="spec-item__header">
|
|
||||||
<text class="spec-item__label">坡口角度</text>
|
|
||||||
<text class="spec-item__value">{{ info.GrooveAngle || '--' }}<text class="spec-item__unit">°</text></text>
|
|
||||||
</view>
|
|
||||||
<view class="spec-item__bar-track">
|
|
||||||
<view class="spec-item__bar-fill" :style="{ width: gaugeWidth(info.GrooveAngle, 0, 90) }"></view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="spec-item">
|
|
||||||
<view class="spec-item__header">
|
|
||||||
<text class="spec-item__label">组对间隙</text>
|
|
||||||
<text class="spec-item__value">{{ info.FitupGap || '--' }}<text class="spec-item__unit">mm</text></text>
|
|
||||||
</view>
|
|
||||||
<view class="spec-item__bar-track">
|
|
||||||
<view class="spec-item__bar-fill fill--amber" :style="{ width: gaugeWidth(info.FitupGap, 0, 10) }"></view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="spec-item">
|
|
||||||
<view class="spec-item__header">
|
|
||||||
<text class="spec-item__label">错边量</text>
|
|
||||||
<text class="spec-item__value">{{ info.Misalignment || '--' }}<text class="spec-item__unit">mm</text></text>
|
|
||||||
</view>
|
|
||||||
<view class="spec-item__bar-track">
|
|
||||||
<view class="spec-item__bar-fill fill--teal" :style="{ width: gaugeWidth(info.Misalignment, 0, 5) }"></view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view> -->
|
|
||||||
|
|
||||||
<!-- 坡口类型 -->
|
|
||||||
<!-- <view class="section">
|
|
||||||
<view class="section__header">
|
|
||||||
<view class="section__bar"></view>
|
|
||||||
<text class="section__title">坡口信息</text>
|
|
||||||
</view>
|
|
||||||
<view class="card">
|
|
||||||
<view class="card__row">
|
|
||||||
<text class="card__label">坡口类型名称</text>
|
|
||||||
<view class="card__value-wrap">
|
|
||||||
<text class="card__value">{{ info.GrooveTypeName || '--' }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="card__row">
|
|
||||||
<text class="card__label">坡口类型编号</text>
|
|
||||||
<view class="card__value-wrap">
|
|
||||||
<text class="card__value">{{ info.GrooveTypeCode || '--' }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="card__row">
|
|
||||||
<text class="card__label">坡口加工类型</text>
|
|
||||||
<text class="card__value">{{ info.GrooveProcessType || '--' }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view> -->
|
|
||||||
|
|
||||||
<!-- 材料校验 -->
|
|
||||||
<view class="section">
|
<view class="section">
|
||||||
<view class="section__header">
|
<view class="section__header">
|
||||||
<view class="section__bar"></view>
|
<view class="section__bar"></view>
|
||||||
<text class="section__title">材料校验</text>
|
<text class="section__title">{{ item.MaterialName || item.MaterialCode || '--' }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="check-card">
|
<view class="card">
|
||||||
<view class="check-item">
|
<view class="card__row">
|
||||||
<view class="check-item__left">
|
<text class="card__label">炉号</text>
|
||||||
<text class="check-item__label">材料编码及炉批号校验</text>
|
<text class="card__value">
|
||||||
<text class="check-item__desc">核对实物编码与批次信息</text>
|
{{ item.HeatNo || '--' }}
|
||||||
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="check-item__action">
|
<view class="card__row">
|
||||||
<nbd-check-btn v-model="check.CodeBatch" :passKey="true" :failKey="false" passText="通过" failText="不通过" />
|
<text class="card__label">批号</text>
|
||||||
|
<text class="card__value">{{ item.BatchNo || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">规格</text>
|
||||||
|
<text class="card__value">{{ item.MaterialSpec || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">单位</text>
|
||||||
|
<text class="card__value">{{ item.MaterialUnit || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row card__row--stack">
|
||||||
|
<text class="card__label">材料描述</text>
|
||||||
|
<text class="card__value">{{ item.MaterialDef || '--' }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="check-item">
|
<view class="nav-row" @click="handleMutualCheck(item.MaterialCode)">
|
||||||
<view class="check-item__left">
|
<view class="nav-row__left">
|
||||||
<text class="check-item__label">材料数量校验</text>
|
<view class="nav-row__dot"></view>
|
||||||
<text class="check-item__desc">核对实物数量与单据一致</text>
|
<text class="nav-row__label">互检上一工序</text>
|
||||||
</view>
|
|
||||||
<view class="check-item__action">
|
|
||||||
<nbd-check-btn v-model="check.Quantity" :passKey="true" :failKey="false" passText="通过" failText="不通过" />
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
<text class="nav-row__arrow">›</text>
|
||||||
</view>
|
</view>
|
||||||
|
<!-- 防腐记录 -->
|
||||||
|
<nbd-anti-record :custom-style="{ margin: '0rpx'}" :params="{ materialCode: item.MaterialCode, projectId: currentProject.ProjectId }" />
|
||||||
</view>
|
</view>
|
||||||
|
</block>
|
||||||
|
|
||||||
<!-- 备注 -->
|
<!-- 备注 -->
|
||||||
<view class="section">
|
<view class="section">
|
||||||
@@ -113,13 +65,8 @@
|
|||||||
<text class="section__title">备注</text>
|
<text class="section__title">备注</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="remark-card">
|
<view class="remark-card">
|
||||||
<textarea
|
<textarea class="remark-input" v-model="remark" placeholder="请输入备注信息(选填)" :maxlength="200"
|
||||||
class="remark-input"
|
auto-height />
|
||||||
v-model="remark"
|
|
||||||
placeholder="请输入备注信息(选填)"
|
|
||||||
:maxlength="200"
|
|
||||||
auto-height
|
|
||||||
/>
|
|
||||||
<text class="remark-count">{{ remark.length }}/200</text>
|
<text class="remark-count">{{ remark.length }}/200</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -145,30 +92,33 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useUserStore } from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
|
|
||||||
import { reqPreWeldJointByWeldJointId, reqSaveCuttingCheck } from '@/api/hj'
|
import { reqPreWeldJointByWeldJointId, reqSaveCuttingCheck } from '@/api/hj'
|
||||||
|
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const { userInfo, currentProject } = storeToRefs(userStore)
|
const { userInfo, currentProject } = storeToRefs(userStore)
|
||||||
|
|
||||||
const info = ref({})
|
const info = ref({})
|
||||||
const remark = ref('')
|
const remark = ref('')
|
||||||
const formAttachUrl = ref('')
|
const formAttachUrl = ref('')
|
||||||
|
const id = ref('')
|
||||||
|
|
||||||
const check = ref({
|
const check = ref({
|
||||||
CodeBatch: true,
|
CodeBatch: true,
|
||||||
Quantity: true
|
Quantity: true
|
||||||
})
|
})
|
||||||
|
|
||||||
// 照片组件引用
|
// 照片组件引用
|
||||||
const photoRef = ref(null)
|
const photoRef = ref(null)
|
||||||
|
|
||||||
const handleSubmit = () => {
|
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '确认提交',
|
title: '确认提交',
|
||||||
content: '确定提交校验结果吗?',
|
content: '确定提交校验结果吗?',
|
||||||
@@ -183,7 +133,7 @@
|
|||||||
|
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const pad = (n) => String(n).padStart(2, '0')
|
const pad = (n) => String(n).padStart(2, '0')
|
||||||
const checkTime = `${now.getFullYear()}-${pad(now.getMonth()+1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
|
const checkTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
ProjectId: currentProject.value?.ProjectId,
|
ProjectId: currentProject.value?.ProjectId,
|
||||||
@@ -202,15 +152,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoad((opt) => {
|
onLoad((opt) => {
|
||||||
if (opt.id) {
|
if (opt.id) {
|
||||||
getInfo(opt.id)
|
id.value = opt.id
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const getInfo = async (id) => {
|
onShow(() => {
|
||||||
|
if (id.value) {
|
||||||
|
getInfo(id.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const getInfo = async (id) => {
|
||||||
try {
|
try {
|
||||||
uni.showLoading({ title: '加载中...', mask: true })
|
uni.showLoading({ title: '加载中...', mask: true })
|
||||||
const res = await reqPreWeldJointByWeldJointId(id)
|
const res = await reqPreWeldJointByWeldJointId(id)
|
||||||
@@ -224,39 +180,47 @@
|
|||||||
} finally {
|
} finally {
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const gaugeWidth = (val, min, max) => {
|
const handleMutualCheck = (id) => {
|
||||||
|
if (!id) {
|
||||||
|
uni.showToast({ title: '缺少材料信息', icon: 'none' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.navigateTo({ url: `/scanpages/hj/do_anti_rust?id=${id}` })
|
||||||
|
}
|
||||||
|
|
||||||
|
const gaugeWidth = (val, min, max) => {
|
||||||
if (!val && val !== 0) return '0%'
|
if (!val && val !== 0) return '0%'
|
||||||
const num = parseFloat(val)
|
const num = parseFloat(val)
|
||||||
if (isNaN(num)) return '0%'
|
if (isNaN(num)) return '0%'
|
||||||
const pct = Math.min(Math.max((num - min) / (max - min) * 100, 0), 100)
|
const pct = Math.min(Math.max((num - min) / (max - min) * 100, 0), 100)
|
||||||
return pct + '%'
|
return pct + '%'
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
$primary: #2979ff;
|
$primary: #2979ff;
|
||||||
$primary-light: #e8f0fe;
|
$primary-light: #e8f0fe;
|
||||||
$primary-mid: #d0ddff;
|
$primary-mid: #d0ddff;
|
||||||
$primary-dark: #1a56cc;
|
$primary-dark: #1a56cc;
|
||||||
$bg: #f0f2f5;
|
$bg: #f0f2f5;
|
||||||
$text: #0f1724;
|
$text: #0f1724;
|
||||||
$text-secondary: #6b7c93;
|
$text-secondary: #6b7c93;
|
||||||
$border: #e8ecf1;
|
$border: #e8ecf1;
|
||||||
$card-bg: #ffffff;
|
$card-bg: #ffffff;
|
||||||
$radius: 16rpx;
|
$radius: 16rpx;
|
||||||
$shadow-sm: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
$shadow-sm: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||||
$shadow-md: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
$shadow-md: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
.detail-page {
|
.detail-page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: $bg;
|
background: $bg;
|
||||||
padding-bottom: 180rpx;
|
padding-bottom: 180rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 焊口主标识 =====
|
// ===== 焊口主标识 =====
|
||||||
.joint-hero {
|
.joint-hero {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 24rpx;
|
margin: 24rpx;
|
||||||
padding: 36rpx 32rpx 28rpx;
|
padding: 36rpx 32rpx 28rpx;
|
||||||
@@ -278,8 +242,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes shimmer {
|
@keyframes shimmer {
|
||||||
0%, 100% { background-position: 0% 0; }
|
|
||||||
50% { background-position: 100% 0; }
|
0%,
|
||||||
|
100% {
|
||||||
|
background-position: 0% 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
background-position: 100% 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__code {
|
&__code {
|
||||||
@@ -336,43 +307,10 @@
|
|||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 区块标题 =====
|
// ===== 坡口参数仪表 =====
|
||||||
.section {
|
.spec-grid {
|
||||||
margin: 0 24rpx 20rpx;
|
|
||||||
|
|
||||||
&__header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12rpx;
|
|
||||||
margin-bottom: 14rpx;
|
|
||||||
padding: 0 6rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__bar {
|
|
||||||
width: 6rpx;
|
|
||||||
height: 26rpx;
|
|
||||||
background: linear-gradient(180deg, $primary, #6ba3ff);
|
|
||||||
border-radius: 3rpx;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__title {
|
|
||||||
font-size: 28rpx;
|
|
||||||
font-weight: 600;
|
|
||||||
color: $text;
|
|
||||||
letter-spacing: 0.5rpx;
|
|
||||||
}
|
|
||||||
.img-box{
|
|
||||||
padding: 20rpx;
|
|
||||||
border-radius: 16rpx;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 坡口参数仪表 =====
|
|
||||||
.spec-grid {
|
|
||||||
background: $card-bg;
|
background: $card-bg;
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
padding: 8rpx 0;
|
padding: 8rpx 0;
|
||||||
@@ -449,75 +387,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 信息卡片 =====
|
|
||||||
.card {
|
// ===== 校验卡片 =====
|
||||||
|
.check-card {
|
||||||
background: $card-bg;
|
background: $card-bg;
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: $shadow-md;
|
box-shadow: $shadow-md;
|
||||||
|
}
|
||||||
|
|
||||||
&__row {
|
.check-item {
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 22rpx 28rpx;
|
|
||||||
border-bottom: 1rpx solid $border;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background: #fafbfc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__label {
|
|
||||||
width: 180rpx;
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: $text-secondary;
|
|
||||||
flex-shrink: 0;
|
|
||||||
position: relative;
|
|
||||||
padding-left: 16rpx;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
width: 4rpx;
|
|
||||||
height: 16rpx;
|
|
||||||
background: $primary-mid;
|
|
||||||
border-radius: 2rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__value {
|
|
||||||
flex: 1;
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: $text;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__value-wrap {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 校验卡片 =====
|
|
||||||
.check-card {
|
|
||||||
background: $card-bg;
|
|
||||||
border-radius: $radius;
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: $shadow-md;
|
|
||||||
}
|
|
||||||
|
|
||||||
.check-item {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 22rpx 28rpx;
|
padding: 22rpx 28rpx;
|
||||||
@@ -550,10 +431,10 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-left: 20rpx;
|
margin-left: 20rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 提交栏(悬浮底部) =====
|
// ===== 提交栏(悬浮底部) =====
|
||||||
.submit-bar {
|
.submit-bar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@@ -561,9 +442,9 @@
|
|||||||
padding: 20rpx 24rpx;
|
padding: 20rpx 24rpx;
|
||||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||||
background: linear-gradient(180deg, rgba(240, 242, 245, 0) 0%, $bg 20%);
|
background: linear-gradient(180deg, rgba(240, 242, 245, 0) 0%, $bg 20%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.submit-btn {
|
.submit-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -598,10 +479,10 @@
|
|||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
letter-spacing: 2rpx;
|
letter-spacing: 2rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== 备注输入框 =====
|
// ===== 备注输入框 =====
|
||||||
.remark-card {
|
.remark-card {
|
||||||
background: $card-bg;
|
background: $card-bg;
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
padding: 24rpx 28rpx;
|
padding: 24rpx 28rpx;
|
||||||
@@ -630,6 +511,112 @@
|
|||||||
font-size: 22rpx;
|
font-size: 22rpx;
|
||||||
color: $text-secondary;
|
color: $text-secondary;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================================================
|
||||||
|
// 材料质检区块 —— 三合一 section
|
||||||
|
// ================================================================
|
||||||
|
|
||||||
|
// section 容器:微背景 + 内边距聚合三个子元素
|
||||||
|
.section {
|
||||||
|
background: #fafbfc;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 24rpx 0 0;
|
||||||
|
margin-bottom: 28rpx;
|
||||||
|
box-shadow: $shadow-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 材料详情卡片 ----
|
||||||
|
// 底部圆角清零,与下方 nav-row 无缝衔接
|
||||||
|
.card {
|
||||||
|
border-radius: $radius $radius 0 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编码类字段(炉号 / 批号 / 规格 / 单位)→ monospace
|
||||||
|
.card__value {
|
||||||
|
font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: $text;
|
||||||
|
letter-spacing: 0.3rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 材料描述 → 回退系统字体
|
||||||
|
.card__row--stack .card__value {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: normal;
|
||||||
|
color: $text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 互检导航按钮 ----
|
||||||
|
.nav-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 0;
|
||||||
|
padding: 24rpx 28rpx;
|
||||||
|
background: $card-bg;
|
||||||
|
border-radius: 0;
|
||||||
|
border-top: 1rpx solid $border;
|
||||||
|
box-shadow: none;
|
||||||
|
transition: background 0.2s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 14rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__dot {
|
||||||
|
width: 10rpx;
|
||||||
|
height: 10rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: $primary;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $text;
|
||||||
|
letter-spacing: 1rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__arrow {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: $text-secondary;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1;
|
||||||
|
margin-right: -4rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 防腐记录 ----
|
||||||
|
// 覆盖组件内部边距(已由父 .section 聚合)
|
||||||
|
:deep(.anti-record__section) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 防腐记录卡片底部圆角收口,与 section 容器对齐
|
||||||
|
:deep(.anti-record__card) {
|
||||||
|
border-radius: 0 0 $radius $radius;
|
||||||
|
border-top: 1rpx solid $border;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 防腐记录 header 缩进对齐,隐藏蓝色竖条(父 section header 已承载标题层级)
|
||||||
|
:deep(.anti-record__header) {
|
||||||
|
padding: 20rpx 28rpx 12rpx;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.anti-record__bar) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
+79
-126
@@ -1,135 +1,88 @@
|
|||||||
import { useUserStore } from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
|
|
||||||
// TODO: 替换为实际的 API 地址
|
|
||||||
export const baseUrl = 'https://lygcgs.com.cn:8078/shjapi/api/'
|
export const baseUrl = 'https://lygcgs.com.cn:8078/shjapi/api/'
|
||||||
export const baseFileUrl = 'https://lygcgs.com.cn:8078/shj/'
|
export const baseFileUrl = 'https://lygcgs.com.cn:8078/shj/'
|
||||||
// ===== 防止重复请求 =====
|
|
||||||
const pendingRequests = new Map()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成请求唯一标识
|
* 将参数对象序列化为 URL query string
|
||||||
|
* 手动构建确保跨平台(小程序 / H5 / App)行为一致
|
||||||
|
* - 过滤 undefined 和 null
|
||||||
|
* - encodeURIComponent 编码中文和特殊字符
|
||||||
*/
|
*/
|
||||||
function getRequestKey(config) {
|
function toQueryString(params) {
|
||||||
const { url = '', method = 'GET', data = {} } = config
|
if (!params) return ''
|
||||||
const paramStr = JSON.stringify(data)
|
const parts = Object.keys(params)
|
||||||
return `${method}:${url}:${paramStr}`
|
.filter((k) => params[k] !== undefined && params[k] !== null)
|
||||||
|
.map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`)
|
||||||
|
return parts.length ? '?' + parts.join('&') : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查是否为重复请求
|
* 核心请求方法(兼容 小程序 / H5 / App)
|
||||||
|
*
|
||||||
|
* @param {string} url - API 路径(不含 baseUrl)
|
||||||
|
* @param {object} options - 可选配置
|
||||||
|
* {string} method - GET | POST,默认 GET
|
||||||
|
* {object} data - GET 时自动拼入 query string,POST 时作为请求体
|
||||||
|
* {object} header - 自定义请求头
|
||||||
|
* {boolean} loading - 是否显示 loading,默认 true
|
||||||
|
* {boolean} toast - 是否在失败时弹 toast,默认 true
|
||||||
*/
|
*/
|
||||||
function checkDuplicate(config) {
|
export function request(url, options = {}) {
|
||||||
const key = getRequestKey(config)
|
const {
|
||||||
if (pendingRequests.has(key)) {
|
method = 'GET',
|
||||||
const meta = config.meta || {}
|
data,
|
||||||
if (meta.toast !== false) {
|
header = {},
|
||||||
uni.showToast({ title: '请求过于频繁,请稍后再试', icon: 'none' })
|
loading = true,
|
||||||
|
toast = true
|
||||||
|
} = options
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const headers = {
|
||||||
|
'content-type': 'application/json',
|
||||||
|
...header
|
||||||
}
|
}
|
||||||
return new Error('duplicate request')
|
if (userStore.token) {
|
||||||
|
headers.token = userStore.token
|
||||||
}
|
}
|
||||||
pendingRequests.set(key, true)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// GET: 手动拼 query string(不依赖 uni.request 各平台差异)
|
||||||
* 移除请求标识
|
let fullUrl = `${baseUrl}${url}`
|
||||||
*/
|
if (method === 'GET' && data) {
|
||||||
function removePending(config) {
|
fullUrl += toQueryString(data)
|
||||||
const key = getRequestKey(config)
|
|
||||||
pendingRequests.delete(key)
|
|
||||||
}
|
|
||||||
// ========================
|
|
||||||
|
|
||||||
// uview-pro 全局请求配置
|
|
||||||
export const httpRequestConfig = {
|
|
||||||
baseUrl,
|
|
||||||
header: {
|
|
||||||
'content-type': 'application/json'
|
|
||||||
},
|
|
||||||
meta: {
|
|
||||||
originalData: true,
|
|
||||||
toast: true,
|
|
||||||
loading: true
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 全局请求/响应拦截器
|
if (loading) {
|
||||||
export const httpInterceptor = {
|
|
||||||
request: (config) => {
|
|
||||||
// 检查重复请求
|
|
||||||
const dupError = checkDuplicate(config)
|
|
||||||
if (dupError) throw dupError
|
|
||||||
|
|
||||||
const meta = config.meta || {}
|
|
||||||
if (meta.loading) {
|
|
||||||
uni.showLoading({ title: '加载中...', mask: true })
|
uni.showLoading({ title: '加载中...', mask: true })
|
||||||
}
|
}
|
||||||
const userStore = useUserStore()
|
|
||||||
if (userStore.token) {
|
|
||||||
config.header.token = userStore.token
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
},
|
|
||||||
response: (response) => {
|
|
||||||
const meta = response.config?.meta || {}
|
|
||||||
if (meta.loading) {
|
|
||||||
uni.hideLoading()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 请求完成,移除标识
|
return new Promise((resolve, reject) => {
|
||||||
removePending(response.config)
|
uni.request({
|
||||||
|
url: fullUrl,
|
||||||
// 根据业务处理错误、例如登录失效等处理接口返回错误码
|
method,
|
||||||
if (response.data.code !== 1) {
|
data: method === 'POST' ? data : undefined,
|
||||||
if (meta.toast) {
|
header: headers,
|
||||||
|
success: (res) => {
|
||||||
|
if (loading) uni.hideLoading()
|
||||||
|
const body = res.data
|
||||||
|
if (body.code !== 1) {
|
||||||
|
if (toast) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: response.data.message || '请求失败',
|
title: body.message || '请求失败',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 401 登录失效,跳转登录页
|
if (body.code === 401) {
|
||||||
if (response.data.code === 401) {
|
|
||||||
const userStore = useUserStore()
|
|
||||||
userStore.logout()
|
userStore.logout()
|
||||||
uni.reLaunch({ url: '/pages/login/index' })
|
uni.reLaunch({ url: '/pages/login/index' })
|
||||||
}
|
}
|
||||||
throw new Error(response.data.message || '请求失败')
|
reject(new Error(body.message || '请求失败'))
|
||||||
}
|
return
|
||||||
uni.showToast({
|
|
||||||
title: response.data.message || '请求成功',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 便捷请求方法(基于 uni.request 封装)
|
|
||||||
* 也可用 uni.$http.get / uni.$http.post(uview-pro)
|
|
||||||
*/
|
|
||||||
export function request(options) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// 运行请求拦截器
|
|
||||||
const config = { ...httpRequestConfig, ...options }
|
|
||||||
const finalConfig = httpInterceptor.request({
|
|
||||||
...config,
|
|
||||||
header: { ...httpRequestConfig.header, ...options.header }
|
|
||||||
})
|
|
||||||
|
|
||||||
uni.request({
|
|
||||||
...finalConfig,
|
|
||||||
url: `${finalConfig.baseUrl}${finalConfig.url}`,
|
|
||||||
success: (res) => {
|
|
||||||
try {
|
|
||||||
const data = httpInterceptor.response({ data: res.data, config: finalConfig })
|
|
||||||
resolve(data)
|
|
||||||
} catch (err) {
|
|
||||||
reject(err)
|
|
||||||
}
|
}
|
||||||
|
resolve(body)
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
removePending(finalConfig) // 网络失败也要清理标识
|
if (loading) uni.hideLoading()
|
||||||
uni.hideLoading()
|
|
||||||
uni.showToast({ title: '网络连接失败', icon: 'none' })
|
uni.showToast({ title: '网络连接失败', icon: 'none' })
|
||||||
reject(err)
|
reject(err)
|
||||||
}
|
}
|
||||||
@@ -137,17 +90,26 @@ export function request(options) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET 快捷方法
|
/**
|
||||||
export const get = (url, params = {}) => {
|
* GET 快捷方法
|
||||||
return request({ url, method: 'GET', data: params })
|
* 兼容两种调用方式:
|
||||||
|
* get('/path?key=val') 旧风格(URL 自带参数)
|
||||||
|
* get('/path', { key: 'val' }) 新风格(参数对象,自动编码)
|
||||||
|
*/
|
||||||
|
export const get = (url, params) => {
|
||||||
|
if (params) {
|
||||||
|
url += toQueryString(params)
|
||||||
|
}
|
||||||
|
return request(url, { method: 'GET' })
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST 快捷方法
|
/**
|
||||||
export const post = (url, data = {}) => {
|
* POST 快捷方法
|
||||||
return request({ url, method: 'POST', data })
|
*/
|
||||||
|
export const post = (url, data) => {
|
||||||
|
return request(url, { method: 'POST', data })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析附件 URL 字符串为可展示的照片列表
|
* 解析附件 URL 字符串为可展示的照片列表
|
||||||
* @param {string} urlStr - 逗号分隔的附件路径,如 "FileUpLoad/xxx.png,FileUpLoad/yyy.png"
|
* @param {string} urlStr - 逗号分隔的附件路径,如 "FileUpLoad/xxx.png,FileUpLoad/yyy.png"
|
||||||
@@ -157,7 +119,7 @@ export const post = (url, data = {}) => {
|
|||||||
export const parseAttachUrls = (urlStr, startId = 0) => {
|
export const parseAttachUrls = (urlStr, startId = 0) => {
|
||||||
if (!urlStr) return []
|
if (!urlStr) return []
|
||||||
let id = startId
|
let id = startId
|
||||||
return urlStr.split(',').filter(Boolean).map(url => ({
|
return urlStr.split(',').filter(Boolean).map((url) => ({
|
||||||
_id: ++id,
|
_id: ++id,
|
||||||
src: `${baseFileUrl}${url}`,
|
src: `${baseFileUrl}${url}`,
|
||||||
_attachUrl: url,
|
_attachUrl: url,
|
||||||
@@ -166,20 +128,11 @@ export const parseAttachUrls = (urlStr, startId = 0) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getUrlParam = (url, name) => {
|
export const getUrlParam = (url, name) => {
|
||||||
if (!url || !name) return null;
|
if (!url || !name) return null
|
||||||
|
const regex = new RegExp(`[?&]${name}=([^&]*)`, 'i')
|
||||||
// 构造正则:匹配 ?name= 或 &name= 后面的值
|
const match = url.match(regex)
|
||||||
// [?&] : 匹配起始分隔符
|
|
||||||
// ${name}: 匹配具体的参数名
|
|
||||||
// = : 匹配等号
|
|
||||||
// ([^&]*) : 捕获组,匹配直到下一个 & 或字符串结束的内容
|
|
||||||
const regex = new RegExp(`[?&]${name}=([^&]*)`, 'i'); // 'i' 表示忽略大小写
|
|
||||||
|
|
||||||
const match = url.match(regex);
|
|
||||||
|
|
||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
return decodeURIComponent(match[1]);
|
return decodeURIComponent(match[1])
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
return null;
|
}
|
||||||
};
|
|
||||||
|
|||||||
Reference in New Issue
Block a user