<template>
|
<view class="order-detail-container">
|
<!-- 顶部订单信息 -->
|
<view class="order-header">
|
<view class="order-info">
|
<text class="info-label">订单编号:</text>
|
<text class="info-value">{{orderInfo.orderNo}}</text>
|
</view>
|
<view class="order-info">
|
<text class="info-label">客户:</text>
|
<text class="info-value">{{orderInfo.customer}}</text>
|
</view>
|
<view class="order-info">
|
<text class="info-label">创建时间:</text>
|
<text class="info-value">{{formatDisplayDate(orderInfo.createTime)}}</text>
|
</view>
|
</view>
|
|
<!-- 物料Tabs -->
|
<view class="material-tabs">
|
<scroll-view scroll-x class="tabs-scroll">
|
<view class="tabs-container">
|
<!-- 只显示前3个Tab -->
|
<view v-for="(tab, index) in tabs.slice(0, 3)" :key="index" class="tab-item"
|
:class="{'active': activeTab === index}" @click="switchTab(index)">
|
<text>{{tab.name}}</text>
|
</view>
|
|
<!-- 下拉按钮 -->
|
<view class="dropdown-btn" :class="{'active': activeTab >= 3}" v-if="tabs.length > 3"
|
@click="toggleCollapse">
|
<text>{{activeTab >= 3 ? tabs[activeTab].name : '更多'}}</text>
|
<uni-icons :type="isCollapsed ? 'arrowdown' : 'arrowup'" size="16"></uni-icons>
|
</view>
|
</view>
|
</scroll-view>
|
|
<!-- 下拉菜单 -->
|
<view class="dropdown-menu" v-if="!isCollapsed && tabs.length > 3">
|
<view v-for="(tab, index) in tabs.slice(3)" :key="index + 3" class="dropdown-item"
|
:class="{'active': activeTab === index + 3}" @click="switchTab(index + 3)">
|
<text>{{tab.name}}</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- Tab内容区 -->
|
<view class="tab-content">
|
<!-- 扫码输入框 -->
|
<view class="scan-section" v-if="dealOrView == 1">
|
<uni-easyinput v-model="scanInput" placeholder="请扫描二维码" @confirm="handleScanInput" :focus="focus"
|
:disabled="inputDisable" clearable></uni-easyinput>
|
</view>
|
|
<!-- 扫描记录 -->
|
<view class="scan-records">
|
<view class="section-title">
|
<text>扫描记录</text>
|
<text class="record-count">({{currentRecords.length}})</text>
|
</view>
|
|
<scroll-view scroll-y class="record-list">
|
<view v-for="(record, index) in currentRecords" :key="index" class="record-item"
|
@click="viewScanRecord(record.id)">
|
<view class="record-header">
|
<text class="record-time">扫描时间: {{ formatDisplayDate(record.scan_time)}}</text>
|
<text class="record-index">序号: {{currentRecords.length - index}}</text>
|
</view>
|
<view class="record-calibration">标定信息: {{record.reference_content}}</view>
|
<view class="record-status" :class="{'error': !record.is_matched}">
|
{{record.is_matched ? '✓' : '✗'}}
|
</view>
|
</view>
|
</scroll-view>
|
</view>
|
</view>
|
|
<!-- 首次扫描弹窗 -->
|
<uni-popup ref="firstScanPopup" type="dialog">
|
<view class="scan-popup">
|
<view class="popup-header">
|
<text>{{confirmHiden?'请选择核对标准':'请查看核对标准'}}</text>
|
</view>
|
<view class="popup-content">
|
<view class="scan-textarea">
|
<scroll-view scroll-y class="record-list">
|
<view class="text-line">
|
<view v-for="(char, index) in formattedText" :key="index" class="text-char"
|
:class="{'selected': selectedSegments.includes(index)}"
|
@click="confirmHiden?toggleSegment(index):()=>{}">
|
{{char}}
|
</view>
|
</view>
|
</scroll-view>
|
</view>
|
<view class="selection-info">
|
<text>已选择:</text>
|
<block v-if="getSelectedSegments().length > 0">
|
<text v-for="(segment, idx) in getSelectedSegments()" :key="idx">
|
{{segment.text}}
|
<text v-if="idx < getSelectedSegments().length - 1">|</text>
|
</text>
|
</block>
|
<text v-else>无</text>
|
</view>
|
</view>
|
<view class="popup-footer">
|
<button class="confirm-btn" v-show="confirmHiden" @click="confirmSelection">确认</button>
|
</view>
|
</view>
|
</uni-popup>
|
|
<!-- 错误提示弹窗 -->
|
<uni-popup ref="errorPopup" type="dialog">
|
<view class="error-popup">
|
<view class="popup-header">
|
<text>扫描错误</text>
|
</view>
|
<view class="popup-content">
|
<text>当前扫描结果不符合核对标准</text>
|
</view>
|
<view class="popup-footer">
|
<button class="confirm-btn" @click="closeErrorPopup">确定</button>
|
</view>
|
</view>
|
</uni-popup>
|
|
<!-- 查看物料信息 -->
|
<uni-popup ref="viewScanRecord" type="dialog">
|
<view class="scan-popup">
|
<view class="popup-header">
|
<text>查看物料信息</text>
|
</view>
|
<view class="popup-content">
|
<view>
|
<text style="font-size: 16px;">订单编号:</text>
|
<text
|
style="font-size: 16px;font-weight: bold;color: #2979ff;">{{currentScanRecord.orderNo}}</text>
|
</view>
|
<view>
|
<text style="font-size: 16px;">扫描时间:</text>
|
<text
|
style="font-size: 16px;font-weight: bold;">{{formatDisplayDate(currentScanRecord.scan_time)}}</text>
|
</view>
|
<view>
|
<text style="font-size: 16px;">物料名称:</text>
|
<text
|
style="font-size: 16px;font-weight: bold;color: #2979ff;">{{currentScanRecord.materialName}}</text>
|
</view>
|
<view>
|
<text style="font-size: 16px;">标定信息:</text>
|
<text
|
style="overflow-wrap: break-word;font-size: 16px;font-weight: bold;color: #2979ff;">{{currentScanRecord.reference_content}}</text>
|
</view>
|
<view>
|
<text style="font-size: 16px;">二维码信息:</text>
|
<text
|
style="overflow-wrap: break-word;font-size: 16px;font-weight: bold;">{{currentScanRecord.scan_content}}</text>
|
</view>
|
</view>
|
</view>
|
</uni-popup>
|
|
<!-- 查看原始单据 -->
|
<uni-popup ref="viewOrderImg" type="dialog">
|
<view class="scan-popup">
|
<view class="popup-header">
|
<text>查看原始单据</text>
|
</view>
|
<view class="popup-content">
|
<view class="doc-preview" v-if="originalDoc">
|
<image :src="originalDoc" mode="aspectFit" @click="previewImage"></image>
|
</view>
|
</view>
|
</view>
|
</uni-popup>
|
|
<!-- 在template中添加侧边弹窗 -->
|
<uni-popup ref="sideActionPopup" type="right">
|
<view class="side-action-popup">
|
<view class="popup-header">
|
<text>订单操作</text>
|
<uni-icons type="close" size="24" @click="hideSideActionPopup"></uni-icons>
|
</view>
|
|
<view class="side-action-content">
|
<view class="action-item" @click="viewCalibration">
|
<uni-icons type="eye" size="24" color="#2979ff"></uni-icons>
|
<text>查看当前标定内容</text>
|
</view>
|
|
<view class="action-item" @click="viewOrderImg">
|
<uni-icons type="image" size="24" color="#2979ff"></uni-icons>
|
<text>查看原始单据</text>
|
</view>
|
|
<view class="action-item" @click="editMat" v-if="dealOrView == 1">
|
<uni-icons type="compose" size="24" color="#2979ff"></uni-icons>
|
<text>编辑物料</text>
|
</view>
|
|
<view class="action-item" @click="adjustSeq" v-if="dealOrView == 1">
|
<uni-icons type="list" size="24" color="#2979ff"></uni-icons>
|
<text>调整顺序</text>
|
</view>
|
|
<!-- <view class="action-item" @click="exportData">
|
<uni-icons type="download" size="24" color="#2979ff"></uni-icons>
|
<text>导出数据</text>
|
</view> -->
|
|
<view class="action-item logout" @click="endOrder" v-if="dealOrView == 1">
|
<uni-icons type="minus" size="24" color="#f56c6c"></uni-icons>
|
<text>结束单据</text>
|
</view>
|
</view>
|
</view>
|
</uni-popup>
|
</view>
|
</template>
|
|
<script>
|
export default {
|
data() {
|
return {
|
orderInfo: {
|
orderNo: "",
|
createTime: "",
|
customer: ""
|
},
|
tabs: [], // 物料Tabs
|
activeTab: 0,
|
scanRecords: {}, // 各物料的扫描记录 {物料ID: [记录数组]}
|
verificationData: {}, // 各物料的验证数据 {物料ID: [验证文本数组]}
|
scanResult: "", // 当前扫描结果
|
scanInput: "", // 扫码输入
|
textSegments: [], // 文本分段
|
selectedSegments: [], // 选中的文本段
|
isFirstScan: {}, // 记录各物料是否是首次扫描
|
isCollapsed: true, // 是否折叠多余Tabs
|
selectedText: "", // 选中的文本内容
|
tempScanInput: '',
|
currentRecords: [],
|
focus: true,
|
confirmHiden: true,
|
inputDisable: false,
|
dealOrView: 1,
|
isFirstLoad: true,
|
currentScanRecord: {
|
scan_time: '',
|
reference_content: '',
|
is_matched: '',
|
orderNo: '',
|
materialName: '',
|
scan_content: '',
|
id: 0
|
},
|
originalDoc: ''
|
};
|
},
|
// 添加导航栏按钮点击处理
|
onNavigationBarButtonTap() {
|
uni.hideKeyboard();
|
this.$refs.sideActionPopup.open();
|
},
|
computed: {
|
// 格式化文本为行和单词的二维数组
|
formattedText() {
|
// 直接返回字符数组
|
return this.textSegments || [];
|
}
|
},
|
created() {
|
this.isFirstLoad = false
|
},
|
onShow() {
|
try {
|
//#ifdef APP-PLUS
|
if (this.orderInfo.orderNo.length > 0 && !this.isFirstLoad) {
|
const orderMatService = require('@/services/orderMatService').default
|
orderMatService.getMaterials(this.orderInfo.orderNo).then(res => {
|
// 接收物料列表
|
if (res) {
|
this.tabs = res.map(m => ({
|
id: m.id,
|
name: m.material_name
|
}));
|
// 初始化扫描状态
|
this.tabs.forEach(tab => {
|
const scanrecordService = require('@/services/scanrecordService').default
|
scanrecordService.getScanRecords(this.orderInfo.orderNo, tab.name).then(
|
res => {
|
this.scanRecords[tab.name] = res.length > 0 ? res : [];
|
this.isFirstScan[tab.name] = res.length > 0 ? false : true;
|
|
const materialId = this.tabs[this.activeTab]?.name;
|
this.currentRecords = materialId ? this.scanRecords[
|
materialId] || [] : [];
|
});
|
|
const materialContentService = require('@/services/materialContentService')
|
.default
|
materialContentService.getMaterialContent(this.orderInfo.orderNo, tab.name)
|
.then(res => {
|
this.verificationData[tab.name] = [];
|
for (var index = 0; index < res.length; index++) {
|
var element = res[index];
|
const text = element.reference_content.split('@#@');
|
this.verificationData[tab.name].push(text);
|
}
|
});
|
});
|
}
|
});
|
}
|
//#endif
|
if (!this.tabs || this.tabs.length == 0) {
|
uni.redirectTo({
|
url: '/pages/index/index'
|
})
|
}
|
} catch (e) {
|
console.error('detail.onShow', e)
|
}
|
},
|
onLoad(options) {
|
try {
|
// 接收订单信息
|
if (options.orderNo && options.createTime) {
|
this.orderInfo = {
|
orderNo: options.orderNo,
|
createTime: options.createTime,
|
customer: options.customer || "暂无信息"
|
};
|
}
|
|
if (options.dealOrView) {
|
this.dealOrView = options.dealOrView;
|
}
|
|
// 接收物料列表
|
if (options.materials) {
|
const materials = JSON.parse(decodeURIComponent(options.materials));
|
this.tabs = materials.map(m => ({
|
id: m.id,
|
name: m.name
|
}));
|
//#ifdef APP-PLUS
|
// 初始化扫描状态
|
this.tabs.forEach(tab => {
|
const scanrecordService = require('@/services/scanrecordService').default
|
scanrecordService.getScanRecords(this.orderInfo.orderNo, tab.name).then(res => {
|
|
this.scanRecords[tab.name] = res.length > 0 ? res : [];
|
this.isFirstScan[tab.name] = res.length > 0 ? false : true;
|
|
const materialId = this.tabs[this.activeTab]?.name;
|
this.currentRecords = materialId ? this.scanRecords[materialId] || [] : [];
|
});
|
|
const materialContentService = require('@/services/materialContentService').default
|
materialContentService.getMaterialContent(this.orderInfo.orderNo, tab.name).then(res => {
|
this.verificationData[tab.name] = [];
|
for (var index = 0; index < res.length; index++) {
|
var element = res[index];
|
const text = element.reference_content.split('@#@');
|
this.verificationData[tab.name].push(text);
|
}
|
});
|
});
|
//#endif
|
}
|
} catch (e) {
|
console.error('detail.onload', e)
|
}
|
},
|
methods: {
|
formatDisplayDate(dateString) {
|
if (!dateString) return ''
|
const date = new Date(dateString)
|
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
|
},
|
|
// 显示侧边弹窗
|
showSideActionPopup() {
|
this.$refs.sideActionPopup.open();
|
},
|
|
// 隐藏侧边弹窗
|
hideSideActionPopup() {
|
this.$refs.sideActionPopup.close();
|
},
|
|
// 查看标定内容
|
async viewCalibration() {
|
this.confirmHiden = false;
|
const materialId = this.tabs[this.activeTab]?.name;
|
this.selectedSegments = [];
|
this.textSegments = [];
|
const materialContentService = require('@/services/materialContentService').default
|
const matContent = await materialContentService.getAMaterialContent(this.orderInfo.orderNo,
|
materialId);
|
if (matContent.length > 0) {
|
const contentIndexes = matContent[0].reference_content_index.split("@#@");
|
let contentIndex = [];
|
if (contentIndexes.length > 1) {
|
for (var index = 0; index < contentIndexes.length - 1; index++) {
|
if (index === 0) {
|
let arr1 = JSON.parse(contentIndexes[index])
|
let arr2 = JSON.parse(contentIndexes[index + 1])
|
contentIndex = arr1.concat(arr2);
|
} else {
|
let arr2 = Array.from(contentIndexes[index + 1])
|
contentIndex = contentIndex.concat(arr2);
|
}
|
}
|
} else {
|
contentIndex = JSON.parse(contentIndexes[0])
|
}
|
|
this.textSegments = Array.from(matContent[0].original_content);
|
this.selectedSegments = contentIndex;
|
|
this.$refs.firstScanPopup.open();
|
|
this.hideSideActionPopup();
|
} else {
|
uni.showToast({
|
title: '暂未标定内容',
|
icon: 'error'
|
})
|
}
|
},
|
|
//编辑物料
|
editMat() {
|
uni.redirectTo({
|
url: `/pages/create/create?orderNo=${this.orderInfo.orderNo}&materials=${encodeURIComponent(
|
JSON.stringify(this.tabs)
|
)}&addOrOnlyAdjust=3&customer=${this.orderInfo.customer}`
|
})
|
},
|
|
//物料排序调整
|
adjustSeq() {
|
uni.redirectTo({
|
url: `/pages/create/create?orderNo=${this.orderInfo.orderNo}&materials=${encodeURIComponent(
|
JSON.stringify(this.tabs)
|
)}&addOrOnlyAdjust=2&customer=${this.orderInfo.customer}`
|
})
|
},
|
|
// 结束单据
|
async endOrder() {
|
this.hideSideActionPopup();
|
uni.showModal({
|
title: "提示",
|
content: "确定要结束当前单据吗?",
|
success: async res => {
|
if (res.confirm) {
|
|
const orderService = require('@/services/orderService').default
|
await orderService.updateOrderStatus(this.orderInfo.orderNo, 'completed')
|
|
uni.showToast({
|
title: "单据已结束",
|
icon: "success"
|
});
|
|
uni.redirectTo({
|
url: '/pages/index/index'
|
})
|
// 这里可以添加结束单据的逻辑
|
}
|
}
|
});
|
},
|
|
//查看扫描记录
|
viewScanRecord(id) {
|
const materialId = this.tabs[this.activeTab]?.name;
|
this.currentScanRecord = this.scanRecords[materialId].find(x => x.id == id)
|
this.$refs.viewScanRecord.open();
|
},
|
|
//预览图片
|
previewImage() {
|
this.hideSideActionPopup();
|
uni.previewImage({
|
urls: [this.originalDoc], // 需传入数组,即使只有一张图
|
current: 0 // 当前显示图片的索引
|
});
|
},
|
|
//查看订单图片
|
async viewOrderImg() {
|
this.hideSideActionPopup();
|
//#ifdef APP-PLUS
|
const orderService = require('@/services/orderService').default
|
const order = await orderService.getOrderByOrderNo(this.orderInfo.orderNo);
|
this.originalDoc = order.originalDoc;
|
//#endif
|
|
//#ifdef H5
|
this.originalDoc = '../../static/logo.png'
|
//#endif
|
|
this.$refs.viewOrderImg.open();
|
},
|
|
// 切换Tab
|
switchTab(index) {
|
this.activeTab = index;
|
// 选择后自动折叠下拉菜单
|
if (!this.isCollapsed) {
|
this.isCollapsed = true;
|
}
|
|
const materialId = this.tabs[this.activeTab]?.name;
|
this.currentRecords = materialId ? this.scanRecords[materialId] || [] : [];
|
},
|
|
// 处理扫码输入
|
async handleScanInput() {
|
this.inputDisable = true;
|
this.confirmHiden = true;
|
this.focus = false;
|
this.tempScanInput = this.scanInput;
|
const currentMaterial = this.tabs[this.activeTab];
|
if (!currentMaterial || !this.scanInput) return;
|
|
await this.handleScanResult(this.tempScanInput, currentMaterial.name);
|
// this.focus = true;
|
|
this.$nextTick(() => {
|
this.scanInput = ""; // 清空输入框
|
})
|
|
setTimeout(() => {
|
this.inputDisable = false;
|
this.focus = true;
|
}, 1000)
|
},
|
|
// 处理扫码结果
|
async handleScanResult(result, materialId) {
|
try {
|
this.scanResult = result;
|
|
//#ifdef H5
|
this.processFirstScan(result, materialId);
|
//#endif
|
|
//#ifdef APP-PLUS
|
if (this.isFirstScan[materialId]) {
|
// 首次扫描处理
|
this.processFirstScan(result, materialId);
|
} else {
|
// 后续扫描处理
|
await this.processSubsequentScan(result, materialId);
|
}
|
//#endif
|
} catch (e) {
|
console.error('handleScanResult', e)
|
}
|
|
},
|
|
// 处理首次扫描
|
processFirstScan(result, materialId) {
|
try {
|
// 将文本拆分为字符数组
|
this.textSegments = Array.from(result);
|
this.selectedSegments = [];
|
this.selectedText = "";
|
|
// 显示选择弹窗
|
this.$refs.firstScanPopup.open();
|
} catch (e) {
|
console.error('processFirstScan', e);
|
}
|
},
|
|
// 处理后续扫描
|
async processSubsequentScan(result, materialId) {
|
try {
|
let isValid = false;
|
let text = [];
|
const verificationTexts = this.verificationData[materialId];
|
for (var index = 0; index < verificationTexts.length; index++) {
|
var element = verificationTexts[index];
|
isValid = element.every(text => result.includes(text));
|
if (isValid) {
|
text = element;
|
break;
|
}
|
}
|
|
if (isValid) {
|
// 记录扫描结果
|
await this.recordScanResult(result, materialId, isValid, text);
|
} else {
|
// 无效时显示错误
|
this.$refs.errorPopup.open();
|
this.playErrorSound();
|
}
|
} catch (e) {
|
console.error('processSubsequentScan', e)
|
}
|
},
|
|
// 记录扫描结果
|
async recordScanResult(result, materialId, isValid, text = []) {
|
let scantime = this.formatDisplayDate(new Date().toISOString())
|
const record = {
|
scan_time: scantime,
|
reference_content: this.verificationData[materialId] ?
|
this.verificationData[materialId].join(" | ") : "无标定信息",
|
is_matched: isValid,
|
orderNo: this.orderInfo.orderNo,
|
materialName: materialId,
|
scan_content: result
|
};
|
let contents = this.getSelectedSegments();
|
if (text.length > 0) {
|
contents = text;
|
}
|
//#ifdef APP-PLUS
|
const scanrecordService = require('@/services/scanrecordService').default
|
const id = await scanrecordService.saveScanRecord(this.orderInfo.orderNo, this.tabs[this.activeTab]
|
.name, this
|
.tempScanInput, contents);
|
//#endif
|
|
record.id = id;
|
this.scanRecords[materialId].unshift(record); // 使用unshift确保倒序
|
},
|
|
// 确认选择
|
async confirmSelection() {
|
const materialId = this.tabs[this.activeTab].name;
|
|
// 标记为非首次扫描
|
this.isFirstScan[materialId] = false;
|
|
const contents = this.getSelectedSegments();
|
|
if (contents.length === 0) {
|
uni.showToast({
|
title: "未选择需要标定的文字信息",
|
icon: "exception"
|
});
|
return;
|
}
|
|
// 关闭弹窗
|
this.$refs.firstScanPopup.close();
|
|
let texts = []
|
for (var index = 0; index < contents.length; index++) {
|
var element = contents[index];
|
texts.push(element.text);
|
}
|
|
// 保存验证数据
|
this.verificationData[materialId].push(texts);
|
|
// 记录扫描结果
|
await this.recordScanResult(this.scanResult, materialId, true);
|
|
//#ifdef APP-PLUS
|
const materialContentService = require('@/services/materialContentService').default
|
await materialContentService.saveMaterialContent(this.orderInfo.orderNo, this.tabs[this.activeTab]
|
.name, this
|
.tempScanInput, contents);
|
|
const orderService = require('@/services/orderService').default
|
await orderService.updateOrderStatus(this.orderInfo.orderNo, 'processing')
|
//#endif
|
},
|
|
// 关闭错误弹窗
|
closeErrorPopup() {
|
this.$refs.errorPopup.close();
|
},
|
|
// 播放错误声音
|
playErrorSound() {
|
const innerAudioContext = uni.createInnerAudioContext();
|
innerAudioContext.src = "/static/fail.mp3";
|
innerAudioContext.play();
|
},
|
|
// 格式化时间
|
formatTime(date) {
|
const h = date
|
.getHours()
|
.toString()
|
.padStart(2, "0");
|
const m = date
|
.getMinutes()
|
.toString()
|
.padStart(2, "0");
|
const s = date
|
.getSeconds()
|
.toString()
|
.padStart(2, "0");
|
return `${h}:${m}:${s}`;
|
},
|
|
// 切换折叠状态
|
toggleCollapse() {
|
this.isCollapsed = !this.isCollapsed;
|
},
|
|
// 获取分段后的选中文本
|
getSelectedSegments() {
|
if (!this.selectedSegments || this.selectedSegments.length === 0)
|
return [];
|
|
// 对选中的索引进行排序
|
const sorted = [...this.selectedSegments].sort((a, b) => a - b);
|
|
const segments = [];
|
let currentSegment = [sorted[0]];
|
|
for (let i = 1; i < sorted.length; i++) {
|
if (sorted[i] === sorted[i - 1] + 1) {
|
// 连续字符,加入当前段
|
currentSegment.push(sorted[i]);
|
} else {
|
// 不连续,保存当前段并开始新段
|
segments.push(currentSegment);
|
currentSegment = [sorted[i]];
|
}
|
}
|
segments.push(currentSegment);
|
|
let content = segments.map(segment => ({
|
text: segment.map(index => this.textSegments[index]).join(""),
|
indexes: segment
|
}));
|
|
return content;
|
},
|
|
// 更新选中文本显示
|
updateSelectedText() {
|
const segments = this.getSelectedSegments();
|
this.selectedText = segments.map(s => s.text).join(" | ");
|
},
|
|
// 选择文本段
|
toggleSegment(index) {
|
const idx = this.selectedSegments.indexOf(index);
|
if (idx === -1) {
|
this.selectedSegments.push(index);
|
} else {
|
this.selectedSegments.splice(idx, 1);
|
}
|
this.updateSelectedText();
|
}
|
}
|
};
|
</script>
|
|
<style lang="scss">
|
/* 添加侧边弹窗样式 */
|
.side-action-popup {
|
width: 70vw;
|
height: 100%;
|
background-color: #fff;
|
|
.popup-header {
|
padding: 30rpx;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
border-bottom: 1rpx solid #eee;
|
|
text {
|
font-size: 32rpx;
|
font-weight: bold;
|
}
|
}
|
|
.side-action-content {
|
padding: 30rpx;
|
|
.action-item {
|
display: flex;
|
align-items: center;
|
padding: 30rpx 0;
|
border-bottom: 1rpx solid #f5f5f5;
|
|
text {
|
margin-left: 20rpx;
|
font-size: 30rpx;
|
}
|
|
&.logout {
|
color: #f56c6c;
|
}
|
}
|
}
|
}
|
|
/* 主题变量 */
|
$primary-color: #2979ff;
|
$primary-gradient: linear-gradient(135deg, #2979ff, #00b0ff);
|
$success-color: #52c41a;
|
$error-color: #f5222d;
|
$text-color: #333;
|
$text-light: #666;
|
$text-lighter: #999;
|
$border-color: rgba(41, 121, 255, 0.1);
|
$bg-color: #f5f9ff;
|
$card-bg: #fff;
|
$shadow-sm: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
$shadow-md: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
$shadow-lg: 0 8rpx 24rpx rgba(0, 0, 0, 0.1);
|
|
.order-detail-container {
|
height: 100vh;
|
display: flex;
|
flex-direction: column;
|
background-color: #f5f7fa;
|
|
.order-header {
|
padding: 20rpx;
|
background-color: #fff;
|
margin-bottom: 20rpx;
|
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.05);
|
|
.order-info {
|
display: flex;
|
margin-bottom: 10rpx;
|
font-size: 28rpx;
|
|
.info-label {
|
color: #666;
|
width: 150rpx;
|
}
|
|
.info-value {
|
color: #333;
|
font-weight: bold;
|
}
|
}
|
}
|
|
.material-tabs {
|
background-color: #fff;
|
padding: 0 20rpx;
|
border-bottom: 1rpx solid #eee;
|
position: relative;
|
|
.tabs-scroll {
|
width: 100%;
|
white-space: nowrap;
|
|
.tabs-container {
|
display: inline-flex;
|
align-items: center;
|
height: 80rpx;
|
|
.tab-item {
|
flex-shrink: 0;
|
display: flex;
|
align-items: center;
|
padding: 0 30rpx;
|
height: 100%;
|
font-size: 28rpx;
|
color: #666;
|
position: relative;
|
|
&.active {
|
color: #2979ff;
|
font-weight: bold;
|
|
&::after {
|
content: "";
|
position: absolute;
|
bottom: 0;
|
left: 30rpx;
|
right: 30rpx;
|
height: 4rpx;
|
background-color: #2979ff;
|
}
|
}
|
}
|
|
.dropdown-btn {
|
flex-shrink: 0;
|
display: flex;
|
align-items: center;
|
padding: 0 20rpx;
|
height: 60rpx;
|
font-size: 28rpx;
|
color: #666;
|
background-color: #f5f7fa;
|
border-radius: 8rpx;
|
margin-left: 10rpx;
|
max-width: 180rpx;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
|
&.active {
|
color: #2979ff;
|
font-weight: bold;
|
}
|
|
&:active {
|
background-color: #e8e8e8;
|
}
|
|
uni-icons {
|
margin-left: 10rpx;
|
flex-shrink: 0;
|
}
|
}
|
}
|
}
|
|
.dropdown-menu {
|
position: absolute;
|
top: 80rpx;
|
left: 20rpx;
|
right: 20rpx;
|
background-color: #fff;
|
border-radius: 8rpx;
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
z-index: 100;
|
max-height: 400rpx;
|
overflow-y: auto;
|
animation: fadeInDown 0.3s;
|
|
.dropdown-item {
|
padding: 20rpx 30rpx;
|
font-size: 28rpx;
|
color: #666;
|
border-bottom: 1rpx solid #f5f5f5;
|
|
&.active {
|
color: #2979ff;
|
background-color: #f0f7ff;
|
}
|
|
&:last-child {
|
border-bottom: none;
|
}
|
}
|
}
|
}
|
|
@keyframes fadeInDown {
|
from {
|
opacity: 0;
|
transform: translateY(-10rpx);
|
}
|
|
to {
|
opacity: 1;
|
transform: translateY(0);
|
}
|
}
|
|
.tab-content {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
padding: 20rpx;
|
background-color: #fff;
|
margin: 20rpx;
|
border-radius: 16rpx;
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
|
.scan-section {
|
margin-bottom: 30rpx;
|
padding: 20rpx;
|
background-color: #fff;
|
border-radius: 8rpx;
|
border: 1rpx solid #eee;
|
|
::v-deep .uni-easyinput__content {
|
min-height: 100rpx;
|
|
.uni-easyinput__input {
|
font-size: 36rpx;
|
text-align: center;
|
}
|
}
|
}
|
|
.scan-records {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
|
.section-title {
|
font-size: 28rpx;
|
color: #333;
|
margin-bottom: 20rpx;
|
display: flex;
|
align-items: center;
|
|
.record-count {
|
color: #999;
|
margin-left: 10rpx;
|
font-size: 24rpx;
|
}
|
}
|
|
.record-list {
|
flex: 1;
|
border: 1rpx solid #eee;
|
border-radius: 8rpx;
|
// padding: 0 20rpx;
|
width: calc(100% - 24px);
|
padding: 12px;
|
}
|
|
.record-item {
|
padding: 20rpx;
|
border-bottom: 1rpx solid #f5f5f5;
|
position: relative;
|
|
.record-header {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 10rpx;
|
|
.record-time {
|
font-size: 26rpx;
|
color: #666;
|
}
|
|
.record-index {
|
font-size: 26rpx;
|
color: #2979ff;
|
font-weight: bold;
|
}
|
}
|
|
.record-calibration {
|
font-size: 26rpx;
|
color: #333;
|
margin-bottom: 10rpx;
|
word-break: break-all;
|
}
|
|
.record-data {
|
font-size: 26rpx;
|
color: #666;
|
word-break: break-all;
|
margin-bottom: 10rpx;
|
}
|
|
.record-status {
|
position: absolute;
|
right: 20rpx;
|
bottom: 20rpx;
|
font-size: 32rpx;
|
|
&.error {
|
color: #f5222d;
|
}
|
}
|
}
|
}
|
}
|
|
.scan-popup,
|
.error-popup {
|
background-color: #fff;
|
border-radius: 16rpx;
|
width: 80vw;
|
max-width: 600rpx;
|
overflow: hidden;
|
|
.popup-header {
|
padding: 24rpx;
|
text-align: center;
|
font-size: 32rpx;
|
font-weight: bold;
|
border-bottom: 1rpx solid #eee;
|
}
|
|
.popup-content {
|
padding: 24rpx;
|
|
.scan-textarea {
|
width: 99%;
|
height: 400px;
|
border: 1rpx solid #eee;
|
border-radius: 8rpx;
|
padding: 16rpx;
|
margin-bottom: 20rpx;
|
font-size: 40rpx;
|
display: flex;
|
overflow: hidden;
|
position: relative;
|
|
.text-line {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 8rpx;
|
margin-bottom: 10rpx;
|
|
.text-char {
|
display: inline-flex;
|
justify-content: center;
|
align-items: center;
|
width: 35px;
|
height: 35px;
|
cursor: pointer;
|
transition: all 0.2s ease;
|
border-radius: 8rpx;
|
background-color: #f5f5f5;
|
font-size: 40rpx;
|
|
&.selected {
|
background: linear-gradient(135deg, #2979ff, #00b0ff);
|
color: white;
|
box-shadow: 0 2rpx 8rpx rgba(41, 121, 255, 0.3);
|
transform: scale(1.1);
|
}
|
|
&:active {
|
transform: scale(0.95);
|
}
|
}
|
}
|
}
|
|
.text-selection {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 10rpx;
|
|
.text-segment {
|
padding: 8rpx 16rpx;
|
background-color: #f5f5f5;
|
border-radius: 8rpx;
|
font-size: 26rpx;
|
color: #333;
|
|
&.selected {
|
background-color: #d0e9ff;
|
color: #2979ff;
|
}
|
}
|
}
|
}
|
|
.popup-footer {
|
padding: 25rpx;
|
border-top: 1rpx solid rgba(41, 121, 255, 0.1);
|
background-color: #f8fafc;
|
|
.confirm-btn {
|
background: linear-gradient(to right, #2979ff, #00b0ff);
|
color: #fff;
|
height: 90rpx;
|
line-height: 90rpx;
|
border-radius: 45rpx;
|
font-size: 30rpx;
|
box-shadow: 0 4rpx 12rpx rgba(41, 121, 255, 0.3);
|
transition: all 0.3s ease;
|
|
&:active {
|
transform: translateY(2rpx);
|
box-shadow: 0 2rpx 6rpx rgba(41, 121, 255, 0.3);
|
}
|
}
|
}
|
}
|
}
|
|
.doc-preview {
|
margin-top: 20rpx;
|
position: relative;
|
border: 1rpx dashed #ddd;
|
padding: 20rpx;
|
border-radius: 8rpx;
|
|
image {
|
width: 100%;
|
height: 300px;
|
margin-bottom: 20rpx;
|
}
|
|
.uni-icons {
|
position: absolute;
|
right: 10rpx;
|
top: 10rpx;
|
background-color: rgba(0, 0, 0, 0.5);
|
color: #fff;
|
border-radius: 50%;
|
padding: 5rpx;
|
}
|
}
|
</style>
|