<template>
|
<!-- 新建表单 - 优化后的UI样式 -->
|
<view v-if="isUpdate" class="create-form">
|
<view class="form-header">
|
<h2>新建入库检验单</h2>
|
<p class="form-subtitle">请按顺序填写以下信息</p>
|
</view>
|
|
<view class="form-content">
|
<!-- 检验单号 -->
|
<view class="form-section">
|
<view class="section-title">基本信息</view>
|
<view class="form-row">
|
<label class="form-label">检验单号:</label>
|
<span class="form-value">{{formData.releaseNo}}</span>
|
</view>
|
</view>
|
|
<!-- 选择区域 -->
|
<view class="form-section">
|
<view class="section-title">选择信息</view>
|
<view class="form-row">
|
<label class="form-label required">工作车间:</label>
|
<superwei-combox :candidates="departmentList" placeholder="请选择车间"
|
v-model="formData.workShop"
|
@select="onDepartmentChange"
|
class="form-select"></superwei-combox>
|
</view>
|
|
<view class="form-row">
|
<label class="form-label required">生产线别:</label>
|
<superwei-combox v-if="formData.workShop" :candidates="DAA020List" placeholder="请选择线体"
|
v-model="formData.lineName"
|
@select="onDaa020Change"
|
class="form-select"></superwei-combox>
|
<span v-else class="form-hint">请先选择工作车间</span>
|
</view>
|
|
<view class="form-row">
|
<label class="form-label required">生产工单:</label>
|
<superwei-combox v-if="formData.lineName" :candidates="DAA001List" placeholder="请选择工单"
|
v-model="formData.rBillNo"
|
@select="onDaa001Change"
|
class="form-select"></superwei-combox>
|
<span v-else class="form-hint">请先选择生产线别</span>
|
</view>
|
|
<view class="form-row">
|
<label class="form-label required">送检数量:</label>
|
<input type="number"
|
v-model="formData.quantity"
|
placeholder="请输入送检数量"
|
class="large-quantity-input"
|
@input="onQuantityChange"/>
|
</view>
|
</view>
|
|
<!-- 产品信息 -->
|
<view class="form-section" v-if="formData.itemName || formData.itemNo || formData.itemModel || formData.planQty">
|
<view class="section-title">产品信息</view>
|
<view class="form-row" v-if="formData.itemName">
|
<label class="form-label">产品名称:</label>
|
<span class="form-value">{{formData.itemName}}</span>
|
</view>
|
|
<view class="form-row" v-if="formData.itemNo">
|
<label class="form-label">物料编码:</label>
|
<span class="form-value">{{formData.itemNo}}</span>
|
</view>
|
|
<view class="form-row" v-if="formData.itemModel">
|
<label class="form-label">规格型号:</label>
|
<span class="form-value">{{formData.itemModel}}</span>
|
</view>
|
|
<view class="form-row" v-if="formData.planQty">
|
<label class="form-label">工单数量:</label>
|
<span class="form-value">{{formData.planQty}}</span>
|
</view>
|
|
<view class="form-row" v-if="formData.rbillNo">
|
<label class="form-label">送检批次:</label>
|
<span class="form-value">{{formData.rbillNo}}</span>
|
</view>
|
</view>
|
</view>
|
|
<view class="form-actions">
|
<button class="btn-primary"
|
v-if="!isShowTable && formData.workShop && formData.lineName && formData.rBillNo && formData.quantity"
|
@click="getItem">
|
<text class="btn-icon">✓</text>
|
生成检验单
|
</button>
|
<button class="btn-primary"
|
v-if="isShowTable && isUpdate"
|
@click="saveTable">
|
<text class="btn-icon">✓</text>
|
生成检验项目
|
</button>
|
</view>
|
</view>
|
|
<!-- 查看/编辑表单 - 使用LLJ类似的样式 -->
|
<view v-else class="inspection-sheet">
|
<!-- 头部信息 -->
|
<view class="sheet-header">
|
<h1>入库检验单</h1>
|
<view class="inspection-number">检验单号:{{formData.releaseNo}}</view>
|
</view>
|
|
<!-- 基本信息区 -->
|
<view class="basic-info">
|
<view class="info-row">
|
<span class="info-label">工单号:</span>
|
<span class="info-value">{{formData.billNo || formData.rBillNo}}</span>
|
<span class="info-label">创建人:</span>
|
<span class="info-value">{{formData.createBy}}</span>
|
</view>
|
<view class="info-row">
|
<span class="info-label">创建时间:</span>
|
<span class="info-value">{{formData.createDate}}</span>
|
<span class="info-label"> 提交状态:</span>
|
<span class="info-value">{{formData.fsubmit == 1 ? '已提交' : '未提交'}}</span>
|
</view>
|
</view>
|
|
<!-- 物料信息区 -->
|
<view class="material-info">
|
<view class="info-block">
|
<view class="info-label">物料编码:</view>
|
<view class="info-value">{{formData.itemNo}}</view>
|
</view>
|
<view class="info-block">
|
<view class="info-label">产品名称:</view>
|
<view class="info-value">{{formData.itemName}}</view>
|
</view>
|
<view class="info-block">
|
<view class="info-label">规格型号:</view>
|
<view class="info-value">{{formData.itemModel}}</view>
|
</view>
|
<view class="info-block">
|
<view class="info-label">送检数量:</view>
|
<view class="info-value highlight">{{formData.quantity}}</view>
|
</view>
|
<view class="info-block" v-if="formData.remarks">
|
<view class="info-label">不合格描述:</view>
|
<view class="info-value">{{formData.remarks}}</view>
|
</view>
|
</view>
|
|
<!-- 下拉选择区域 -->
|
<view class="dropdown-row">
|
<view class="info-label">工作车间:</view>
|
<view class="info-value">{{formData.workShop}}</view>
|
</view>
|
<view class="dropdown-row">
|
<view class="info-label">生产线别:</view>
|
<view class="info-value">{{formData.lineName || formData.daa015}}</view>
|
</view>
|
<view class="dropdown-row">
|
<view class="info-label">生产工单:</view>
|
<view class="info-value">{{formData.billNo || formData.rBillNo}}</view>
|
</view>
|
|
<view class="dropdown-row">
|
<view class="info-label">送检批次:</view>
|
<view class="info-value">{{formData.rbillNo}}</view>
|
</view>
|
|
<!-- 新增下拉框区域 -->
|
<view class="dropdown-row">
|
<view class="info-label">不良原因:</view>
|
<picker v-if="!isUpdate" :value="badreasonIndex" :range="badreasonOptions" @change="onBadreasonChange">
|
<view class="picker-text" :class="{ 'selected': badreason }">{{ badreason || '请选择不良原因' }}</view>
|
</picker>
|
<view v-else class="info-value">{{ badreason }}</view>
|
</view>
|
<view class="dropdown-row">
|
<view class="info-label">所属车间:</view>
|
<picker v-if="!isUpdate" :value="workshopIndex" :range="workshopOptions" @change="onWorkshopChange">
|
<view class="picker-text" :class="{ 'selected': WORKSHOP }">{{ WORKSHOP || '请选择所属车间' }}</view>
|
</picker>
|
<view v-else class="info-value">{{ WORKSHOP }}</view>
|
</view>
|
<view class="dropdown-row">
|
<view class="info-label">评审状态:</view>
|
<picker v-if="!isUpdate" :value="pstypeIndex" :range="pstypeOptions" @change="onPstypeChange">
|
<view class="picker-text" :class="{ 'selected': PSTYPE }">{{ PSTYPE || '请选择评审状态' }}</view>
|
</picker>
|
<view v-else class="info-value">{{ PSTYPE }}</view>
|
</view>
|
<view class="dropdown-row">
|
<view class="info-label">不良描述:</view>
|
<input v-if="!isUpdate" v-model="formData.fngDesc" placeholder="请输入不良描述" class="input-field" @blur="saveFngDesc" />
|
<view v-else class="info-value">{{ formData.fngDesc }}</view>
|
</view>
|
|
<!-- 表单上方操作按钮区 -->
|
<view class="top-action-buttons">
|
<button class="action-btn" v-if="formData.fsubmit != 1" @click="getInspectionItems">获取检验项目</button>
|
</view>
|
|
<!-- 检验项目表格 -->
|
<view class="inspection-table" v-if="formData.id">
|
<table>
|
<thead>
|
<tr>
|
<th width="20%" style="text-align: center;">检验项目</th>
|
<th width="50%" style="text-align: center;">检验描述</th>
|
<th width="15%" style="text-align: center;">记录(点击)</th>
|
</tr>
|
</thead>
|
<tbody>
|
<tr v-for="(item, index) in tableData" :key="index">
|
<td>{{ item.projName }}</td>
|
<td>
|
<view v-if="item.result=='合格'" class="watermark approved">
|
{{ getStatusText(item.result) }}
|
</view>
|
<view v-if="item.result=='不合格'" class="watermark rejected">
|
{{ getStatusText(item.result) }}
|
</view>
|
<view v-if="item.result==null || item.result=='未完成'" class="watermark pending">
|
{{ getStatusText(item.result) }}
|
</view>
|
<view class="description-text">{{ item.projName }}</view>
|
</td>
|
<td>
|
<button v-if="item.isCheck >= item.levelNum || formData.fsubmit == 1" class="record-btn" @click="toDetail(item)">查看</button>
|
<button v-else class="record-btn" @click="toDetail(item)">填写</button>
|
</td>
|
</tr>
|
</tbody>
|
</table>
|
<view v-if="tableData.length === 0" class="no-data-tip">
|
<text style="color: #999; font-size: 16px;">该检验单暂无检验项目,请点击"获取检验项目"按钮添加检验项目</text>
|
</view>
|
</view>
|
|
<!-- 表单下方操作按钮区 -->
|
<view class="bottom-action-buttons">
|
<button class="action-btn small" @click="toImage">上传/查看图片</button>
|
<button class="action-btn small" @click="viewAttachmentInfo">查看附件信息</button>
|
<button class="action-btn small" @click="saveRemarks" v-if="formData.fsubmit != 1">添加不合格描述</button>
|
<button class="action-btn small primary" @click="submitInspection" v-if="formData.fsubmit != 1 && tableData.length > 0">提交检验</button>
|
</view>
|
|
<!-- 修改不合格描述弹出框 -->
|
<view v-if="showPopup" class="overlay">
|
<view class="popup">
|
<h3>修改不合格描述</h3>
|
<form>
|
<view class="form-group">
|
<label class="form-label">不合格描述:</label>
|
<input class="form-input" type="text" v-model="remarks" placeholder="请输入不合格描述"/>
|
</view>
|
</form>
|
<button class="updateBut" @click="edit">修改</button>
|
<button @click="showPopup = !showPopup">取消</button>
|
</view>
|
</view>
|
|
<!-- 附件详情弹窗 -->
|
<view v-if="showAttachmentDetail" class="overlay">
|
<view class="popup attachment-detail-popup">
|
<h3 class="attachment-popup-title">附件详情</h3>
|
<div class="attachment-popup-divider"></div>
|
<div v-if="selectedAttachment" class="attachment-detail-content">
|
<div class="attachment-detail-row"><span class="attachment-label">ID:</span><span>{{ Math.trunc(selectedAttachment.id) }}</span></div>
|
<div class="attachment-detail-row"><span class="attachment-label">附件名:</span><span>{{ selectedAttachment.fattach }}</span></div>
|
<div class="attachment-detail-row"><span class="attachment-label">类型:</span><span>{{ selectedAttachment.ftype }}</span></div>
|
<div class="attachment-detail-row"><span class="attachment-label">版本:</span><span>{{ selectedAttachment.fversion }}</span></div>
|
<div class="attachment-detail-row"><span class="attachment-label">受控日期:</span><span>{{ selectedAttachment.fdate }}</span></div>
|
<div class="attachment-detail-row"><span class="attachment-label">上传人:</span><span>{{ selectedAttachment.createBy }}</span></div>
|
<div class="attachment-detail-row"><span class="attachment-label">上传时间:</span><span>{{ selectedAttachment.createDate }}</span></div>
|
<div class="attachment-actions-detail">
|
<button class="attachment-action-btn preview-btn"
|
@click="previewFtpFile(selectedAttachment)"
|
v-if="isPreviewable(selectedAttachment.fattach)">
|
🔍 在线预览
|
</button>
|
<button class="attachment-action-btn download-btn"
|
@click="downloadAttachment(selectedAttachment)">
|
📥 下载文件
|
</button>
|
</div>
|
</div>
|
<div v-else class="attachment-detail-empty">暂无附件信息</div>
|
<button class="attachment-popup-close" @click="closeAttachmentDetail">返回附件列表</button>
|
</view>
|
</view>
|
|
<!-- 附件列表弹窗 -->
|
<view v-if="showAttachmentPopup" class="overlay">
|
<view class="popup" style="width: 60vw; max-width: 500px;">
|
<h3>附件列表</h3>
|
<div v-if="attachmentsLoading">加载中...</div>
|
<div v-else-if="attachments.length === 0">暂无附件</div>
|
<ul class="attachment-list" v-else>
|
<li v-for="item in attachments" :key="item.id">
|
<div class="attachment-info">
|
<span class="attachment-name" @click="showAttachmentDetailDialog(item)">
|
{{ item.fattach }}
|
</span>
|
<div class="attachment-meta">
|
<span class="attachment-type">{{ item.ftype || '未知类型' }}</span>
|
</div>
|
</div>
|
<div class="attachment-actions">
|
<button class="secondary-btn" @click="showAttachmentDetailDialog(item)">详情</button>
|
<button class="secondary-btn preview-btn" @click="previewFtpFile(item)"
|
v-if="isPreviewable(item.fattach)">预览</button>
|
<button class="secondary-btn" @click="downloadAttachment(item)">下载</button>
|
</div>
|
</li>
|
</ul>
|
<button class="attachment-popup-close" @click="closeAttachmentPopup">关闭</button>
|
</view>
|
</view>
|
|
<!-- 文件预览弹窗 -->
|
<view v-if="showFilePreviewPopup" class="overlay">
|
<view class="popup file-preview-popup">
|
<h3 class="file-preview-title">{{ previewTitle }}</h3>
|
<div class="file-preview-divider"></div>
|
<div class="file-preview-content">
|
<!-- 文本内容预览 -->
|
<pre v-if="previewType === 'text'">{{ previewContent }}</pre>
|
|
<!-- 图片内容预览 -->
|
<view v-else-if="previewType === 'image'" class="image-preview-container">
|
<image
|
:src="previewContent"
|
mode="aspectFit"
|
class="preview-image-clickable"
|
@click="previewImageInPopup"
|
style="width: 100%; max-height: 400px; cursor: pointer;"
|
/>
|
<div class="image-zoom-hint">点击图片可放大查看</div>
|
</view>
|
|
<!-- Excel 等 Office 文件提示 -->
|
<view v-else-if="previewType === 'excel'" class="unsupported-preview">
|
<view class="unsupported-icon">📊</view>
|
<view class="unsupported-text">Excel 文件暂不支持在线预览</view>
|
<view class="unsupported-hint">请点击下载按钮获取完整文件</view>
|
</view>
|
|
<!-- 不支持的文件类型 -->
|
<view v-else class="unsupported-preview">
|
<view class="unsupported-icon">📄</view>
|
<view class="unsupported-text">此文件格式暂不支持预览</view>
|
<view class="unsupported-hint">请点击下载按钮获取完整文件</view>
|
</view>
|
</div>
|
<div class="file-preview-actions">
|
<button v-if="previewType !== 'text'" class="file-preview-btn download-btn" @click="downloadPreviewFile">📥 下载文件</button>
|
<button class="file-preview-btn close-btn" @click="closeFilePreview">关闭</button>
|
</div>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
export default {
|
data() {
|
return {
|
formData: {
|
id: "",
|
releaseNo: "",
|
createBy: "",
|
createDate: "",
|
daa020: "",
|
itemNo: "",
|
itemId: "", // 物料ID
|
billNo: "",
|
lineNo: "", // 生产线编号
|
catQty: "",
|
detailMem: "",
|
taskNo: "",
|
fcheckResu: "",
|
fsubmit: "", // 提交状态
|
remarks: "",
|
rbillNo: "",
|
workShop: "", // 工作车间
|
lineName: "", // 线体名称
|
quantity: "", // 送检数量
|
planQty: "", // 工单计划数量
|
fngDesc: "" // 不良描述
|
},
|
|
DAA020List: [],
|
|
DAA001List: [],
|
|
BillNoList: [],
|
|
lineList: [],
|
|
lineNo: "",
|
|
tableData: [],
|
|
isSubmit: true,
|
|
isUpdate: true,
|
|
isShowTable: false,
|
|
remarks: "",
|
|
showPopup: false,
|
departmentList: [], // 车间列表
|
selectedDepartmentId: "", // 选中的车间ID
|
// 附件相关数据
|
attachments: [],
|
showAttachmentPopup: false,
|
attachmentsLoading: false,
|
selectedAttachment: null,
|
showAttachmentDetail: false,
|
showFilePreviewPopup: false,
|
previewContent: '',
|
previewTitle: '',
|
previewItemNo: '',
|
previewType: '', // 'text', 'image', 'excel', 'unsupported'
|
|
// 新增下拉框相关数据
|
badreason: '',
|
PSTYPE: '',
|
WORKSHOP: '',
|
badreasonOptions: ['', '外观不良', '尺寸不良', '包装不良', '性能不良', '装配不良', '安规不良'],
|
badreasonIndex: 0,
|
workshopOptions: ['', '生产一部', '生产二部', '注塑车间', '其他'],
|
workshopIndex: 0,
|
pstypeOptions: ['', '特采/让步使用', '挑选/返工使用', '退货', '待判'],
|
pstypeIndex: 0,
|
};
|
},
|
onLoad(options) {
|
//options中包含了url附带的参数
|
|
let params = options;
|
|
if (params["id"]) {
|
this.isUpdate = false;
|
this.formData.id = params["id"];
|
this.formData.releaseNo = params["releaseNo"];
|
//getQaItemXj02
|
this.init();
|
} else {
|
//初始化检验单号
|
this.$post({
|
url: "/RKJ/getMaxReleaseNo"
|
}).then(res => {
|
this.formData.releaseNo = res.data.tbBillList;
|
this.formData.createBy = this.$loginInfo.account;
|
this.formData.createDate = this.$getDate("yyyy-mm-dd");
|
});
|
|
// 初始化车间下拉框
|
this.$post({
|
url: "/RKJ/GetDepartmentsWithLines"
|
}).then(res => {
|
this.departmentList = res.data.tbBillList.map(item => item.departmentname);
|
})
|
}
|
},
|
methods: {
|
getStatusClass(result) {
|
if (result === '合格') return 'status-pass';
|
if (result === '不合格') return 'status-fail';
|
return 'status-pending';
|
},
|
|
getStatusText(status) {
|
const statusMap = {
|
approved: '合格',
|
rejected: '不合格',
|
pending: '待确认'
|
}
|
if (status == null || status == '未完成') {
|
return statusMap['pending'] || '待确认';
|
} else if (status == '合格') {
|
return statusMap['approved'] || '合格';
|
} else {
|
return statusMap['rejected'] || '不合格';
|
}
|
},
|
|
removeXJ() {
|
if (this.formData.id) {
|
this.$post({
|
url: "/RKJ/removeXJ",
|
data: {
|
id: this.formData.id
|
}
|
}).then(res => {
|
if (res.data.tbBillList > 0) {
|
this.$showMessage("删除成功");
|
//关闭当前页面,返回上一页面或多级页面
|
uni.navigateBack();
|
} else {
|
this.$showMessage("删除失败");
|
}
|
});
|
} else {
|
this.$showMessage("请先选择检验单号");
|
}
|
},
|
getItem() {
|
|
if (!this.formData.workShop) {
|
this.$showMessage("请选择工作车间");
|
return;
|
}
|
|
if (!this.formData.lineName) {
|
this.$showMessage("请选择生产线体");
|
return;
|
}
|
|
if (!this.formData.rBillNo) {
|
this.$showMessage("请选择生产工单");
|
return;
|
}
|
|
if (!this.formData.quantity || parseFloat(this.formData.quantity) <= 0) {
|
this.$showMessage("请输入有效的送检数量");
|
return;
|
}
|
|
const quantity = parseFloat(this.formData.quantity);
|
const planQty = parseFloat(this.formData.planQty);
|
|
if (quantity > planQty) {
|
this.$showMessage("送检数量不能大于工单数量");
|
return;
|
}
|
|
// 确保必要字段被正确设置
|
if (!this.formData.itemId) {
|
this.$showMessage("物料ID获取失败,请重新选择工单");
|
return;
|
}
|
|
if (!this.formData.billNo) {
|
this.$showMessage("工单号获取失败,请重新选择工单");
|
return;
|
}
|
|
// 设置Daa015字段(生产线别)
|
this.formData.daa015 = this.formData.lineNo;
|
|
// 设置默认提交状态为未提交(0)
|
this.formData.fsubmit = 0;
|
|
this.$post({
|
url: "/RKJ/save",
|
data: {
|
from: this.formData,
|
userNo: this.$loginInfo.account,
|
quantity: this.formData.quantity,
|
//moidNum: this.formData.moidNum
|
items: this.tableData
|
}
|
}).then(res => {
|
this.formData.id = res.data.tbBillList;
|
|
// 保存车间选择信息
|
if (this.formData.workShop && this.selectedDepartmentId) {
|
this.$post({
|
url: "/RKJ/SaveDepartmentSelection",
|
data: {
|
id: this.formData.id,
|
departmentId: this.selectedDepartmentId,
|
departmentName: this.formData.workShop
|
}
|
});
|
}
|
|
this.$showMessage("检验单创建成功!该检验单未维护检验项目,请先维护检验项目!");
|
// 不调用init方法,避免检验单号发生变化
|
this.isUpdate = false;
|
});
|
},
|
//生产线别选择并初始话工单号
|
onDaa020Change(event) {
|
//获取生产线别的下标地址
|
this.formData.lineName = event;
|
|
const selectedLine = this.lineList[this.DAA020List.indexOf(event)];
|
this.lineNo = selectedLine.lineno;
|
|
// 设置生产线编号到formData
|
this.formData.lineNo = this.lineNo;
|
|
this.$post({
|
url: "/RKJ/getDaa001",
|
data: {
|
lineNo: this.lineNo
|
}
|
}).then(res => {
|
this.BillNoList = res.data.tbBillList;
|
// 工单号去重,只显示唯一
|
this.DAA001List = Array.from(new Set(res.data.tbBillList.map(s => s.daa001)));
|
this.formData.rBillNo = "";
|
// 不清空送检数量,保持用户已输入的值
|
this.formData.itemName = "";
|
this.formData.itemNo = "";
|
this.formData.itemId = ""; // 清空物料ID
|
this.formData.itemModel = "";
|
this.formData.planQty = "";
|
this.formData.rbillNo = ""; // 清空送检批次号
|
this.tableData = [];
|
})
|
},
|
// 车间选择事件
|
onDepartmentChange(event) {
|
this.formData.workShop = event;
|
|
// 根据车间名称获取车间ID
|
this.$post({
|
url: "/RKJ/GetDepartmentsWithLines"
|
}).then(res => {
|
const department = res.data.tbBillList.find(item => item.departmentname === event);
|
if (department) {
|
this.selectedDepartmentId = department.departmentid;
|
|
// 根据车间ID获取线体列表
|
this.$post({
|
url: "/RKJ/GetLinesByDepartment",
|
data: {
|
departmentId: this.selectedDepartmentId
|
}
|
}).then(lineRes => {
|
console.log("线体数据:", lineRes.data.tbBillList); // 添加调试日志
|
this.lineList = lineRes.data.tbBillList;
|
this.DAA020List = lineRes.data.tbBillList.map(item => item.linename);
|
|
// 清空相关数据
|
this.formData.lineName = "";
|
this.formData.lineNo = ""; // 清空生产线编号
|
this.formData.rBillNo = "";
|
this.formData.billNo = ""; // 清空工单号
|
// 不清空送检数量,保持用户已输入的值
|
this.formData.itemName = "";
|
this.formData.itemNo = "";
|
this.formData.itemId = ""; // 清空物料ID
|
this.formData.itemModel = "";
|
this.formData.planQty = "";
|
this.formData.rbillNo = ""; // 清空送检批次号
|
this.tableData = [];
|
});
|
}
|
});
|
},
|
//选取工单填充物料号和其他信息
|
onDaa001Change(e) {
|
this.formData.rBillNo = e;
|
|
// 找到当前工单号的完整数据
|
let data = this.BillNoList.find(item => item.daa001 === e);
|
if (!data) {
|
this.formData.itemName = "";
|
this.formData.itemNo = "";
|
this.formData.itemId = "";
|
this.formData.billNo = "";
|
this.formData.rbillNo = "";
|
this.formData.quantity = "";
|
this.formData.itemModel = "";
|
this.tableData = [];
|
return;
|
}
|
|
// 自动填充物料信息
|
this.formData.itemName = data.daa003; // 产品名称
|
this.formData.itemNo = data.daa002; // 产品编码
|
this.formData.itemId = data.itemId || ""; // 物料ID
|
this.formData.billNo = data.daa001; // 工单号作为billNo
|
this.formData.rbillNo = "无源单"; // 送检批次号(使用默认值)
|
this.formData.itemModel = data.daa004 || ""; // 产品规格
|
this.formData.planQty = data.daa008 || ""; // 工单数量
|
// 不清空送检数量,保持用户已输入的值
|
this.tableData = [];
|
},
|
// 送检数量变化事件
|
onQuantityChange(event) {
|
// 如果输入为空,不进行验证
|
if (!this.formData.quantity || this.formData.quantity === "") {
|
return;
|
}
|
|
const quantity = parseFloat(this.formData.quantity);
|
|
// 检查是否为有效数字
|
if (isNaN(quantity)) {
|
this.$showMessage("请输入有效的数字");
|
this.formData.quantity = "";
|
return;
|
}
|
|
// 只有在输入完成且数量大于0时才进行验证
|
if (quantity <= 0) {
|
this.$showMessage("送检数量必须大于0");
|
this.formData.quantity = "";
|
return;
|
}
|
|
// 只有在已选择工单且有工单数量时才进行数量比较
|
if (this.formData.planQty) {
|
const planQty = parseFloat(this.formData.planQty);
|
if (!isNaN(planQty) && quantity > planQty) {
|
this.$showMessage("送检数量不能大于工单数量");
|
this.formData.quantity = "";
|
return;
|
}
|
}
|
},
|
init() {
|
this.$post({
|
url: "/RKJ/getPage",
|
data: {
|
id: this.formData.id,
|
createUser: this.$loginInfo.account,
|
pageIndex: 1,
|
limit: 1,
|
}
|
}).then(res => {
|
let data = res.data.tbBillList[0];
|
if (data) {
|
// 保存原有的检验单号
|
const originalReleaseNo = this.formData.releaseNo;
|
|
// 映射数据库字段到前端字段
|
this.formData.id = data.id;
|
this.formData.releaseNo = data.releaseNo || originalReleaseNo;
|
this.formData.createBy = data.createBy;
|
this.formData.createDate = data.createDate;
|
this.formData.billNo = data.billNo;
|
this.formData.rbillNo = data.rbillNo;
|
this.formData.itemNo = data.itemNo;
|
this.formData.itemId = data.itemId;
|
this.formData.lineNo = data.lineNo;
|
this.formData.quantity = data.quantity;
|
this.formData.fcheckResu = data.fcheckResu;
|
this.formData.fcheckBy = data.fcheckBy;
|
this.formData.fcheckDate = data.fcheckDate;
|
this.formData.fsubmit = data.fsubmit; // 提交状态
|
this.formData.remarks = data.remarks;
|
this.formData.workShop = data.workShop;
|
this.formData.departmentId = data.departmentId;
|
|
// 从关联表获取的字段
|
this.formData.itemName = data.itemName;
|
this.formData.itemModel = data.itemModel;
|
this.formData.daa015 = data.daa015;
|
|
// 加载下拉框字段数据
|
this.badreason = data.blyy || '';
|
this.PSTYPE = data.pszt || '';
|
this.WORKSHOP = data.sscj || '';
|
this.formData.fngDesc = data.fngDesc || ''; // 加载不良描述
|
|
// 设置 picker 索引
|
this.badreasonIndex = this.badreasonOptions.indexOf(this.badreason);
|
this.workshopIndex = this.workshopOptions.indexOf(this.WORKSHOP);
|
this.pstypeIndex = this.pstypeOptions.indexOf(this.PSTYPE);
|
|
// 设置生产线名称(如果有lineNo)
|
if (this.formData.lineNo && this.formData.workShop) {
|
this.formData.lineName = this.formData.lineNo;
|
}
|
|
// 加载车间列表和相关信息
|
this.loadDepartmentAndLineInfo();
|
|
// 加载检验项目
|
this.loadInspectionItems();
|
}
|
});
|
},
|
|
// 加载车间和线体信息
|
loadDepartmentAndLineInfo() {
|
this.$post({
|
url: "/RKJ/GetDepartmentsWithLines"
|
}).then(deptRes => {
|
this.departmentList = deptRes.data.tbBillList.map(item => item.departmentname);
|
|
if (this.formData.workShop) {
|
const department = deptRes.data.tbBillList.find(item => item.departmentname === this.formData.workShop);
|
if (department) {
|
this.selectedDepartmentId = department.departmentid;
|
this.loadLineInfo();
|
}
|
}
|
});
|
},
|
|
// 加载线体信息
|
loadLineInfo() {
|
if (this.selectedDepartmentId) {
|
this.$post({
|
url: "/RKJ/GetLinesByDepartment",
|
data: {
|
departmentId: this.selectedDepartmentId
|
}
|
}).then(lineRes => {
|
this.lineList = lineRes.data.tbBillList;
|
this.DAA020List = lineRes.data.tbBillList.map(item => item.linename);
|
|
if (this.formData.lineNo) {
|
const selectedLine = this.lineList.find(line => line.lineNo === this.formData.lineNo);
|
if (selectedLine) {
|
this.formData.lineName = selectedLine.lineName;
|
}
|
this.loadWorkOrderInfo();
|
}
|
});
|
}
|
},
|
|
// 加载工单信息
|
loadWorkOrderInfo() {
|
if (this.formData.lineNo) {
|
this.$post({
|
url: "/RKJ/getDaa001",
|
data: {
|
lineNo: this.formData.lineNo
|
}
|
}).then(workOrderRes => {
|
this.BillNoList = workOrderRes.data.tbBillList;
|
this.DAA001List = Array.from(new Set(workOrderRes.data.tbBillList.map(s => s.daa001)));
|
});
|
}
|
},
|
|
// 加载检验项目
|
loadInspectionItems() {
|
this.$post({
|
url: "/RKJ/getItems",
|
data: {
|
pid: this.formData.id
|
}
|
}).then(res1 => {
|
let tableData = res1.data.tbBillList || [];
|
|
//当已检验个数都不为空时按照检测结构排序
|
tableData.sort((a, b) => {
|
if (a.result === '未完成' && b.result === '合格') {
|
return -1;
|
} else if (a.result === '合格' && b.result === '未完成') {
|
return 1;
|
} else {
|
return 0;
|
}
|
});
|
this.tableData = tableData;
|
|
// 如果没有检验项目,显示提示信息
|
if (this.tableData.length === 0) {
|
console.log("没有找到检验项目");
|
}
|
}).catch(error => {
|
console.error("加载检验项目失败:", error);
|
this.tableData = [];
|
});
|
},
|
toDetail(item) {
|
|
if (this.isUpdate) {
|
uni.showToast({
|
icon: "none",
|
title: "请先生成检验项目",
|
duration: 2000,
|
});
|
} else if (this.formData.fsubmit == 1) {
|
uni.showToast({
|
icon: "none",
|
title: "该检验单已提交,不能修改",
|
duration: 2000,
|
});
|
} else {
|
uni.navigateTo({
|
url: 'detail?id=' + item.id + '&billNo=' + this.formData.billNo + '&gid=' + this.formData
|
.id + '&itemInId=' + this.formData.itemInId
|
});
|
}
|
},
|
toImage() {
|
uni.navigateTo({
|
url: 'ImageItem?id=' + this.formData.id
|
});
|
},
|
saveRemarks() {
|
if (this.formData.fsubmit == 1) {
|
this.$showMessage("该检验单已提交,不能修改不合格描述");
|
return;
|
}
|
this.showPopup = !this.showPopup;
|
this.remarks = this.formData.remarks;
|
},
|
edit() {
|
if (this.remarks) {
|
//saveRemarksGid
|
this.$post({
|
url: "/RKJ/saveRemarksGid",
|
data: {
|
gid: this.formData.id,
|
remarks: this.remarks
|
}
|
}).then(res => {
|
if(res.data.tbBillList > 0){
|
this.formData.remarks = this.remarks;
|
this.showPopup = !this.showPopup;
|
this.$showMessage("保存成功");
|
}
|
})
|
}
|
},getInspectionItems() {
|
// 获取检验项目的逻辑 - 调用存储过程
|
this.$post({
|
url: "/RKJ/genUpdate",
|
data: {
|
id: this.formData.id,
|
no: this.formData.releaseNo,
|
user: this.$loginInfo.account
|
}
|
}).then(res => {
|
if (res.status == 0) {
|
uni.showToast({
|
title: res.data.message || "检验项目生成成功",
|
icon: 'success',
|
duration: 2000
|
});
|
// 延迟重新加载数据
|
setTimeout(() => {
|
this.init();
|
}, 2000);
|
} else {
|
uni.showToast({
|
title: res.data.message || "检验项目生成失败",
|
icon: 'error',
|
duration: 2000
|
});
|
}
|
}).catch(error => {
|
console.error("获取检验项目失败:", error);
|
this.$showMessage("获取检验项目失败,请重试");
|
});
|
},
|
getTable() {
|
// 确保quantity有值
|
if (!this.formData.quantity || parseFloat(this.formData.quantity) <= 0) {
|
this.$showMessage("请先输入有效的送检数量");
|
return;
|
}
|
|
this.$post({
|
url: "/RKJ/setJYItem",
|
data: {
|
itemNo: this.formData.itemNo,
|
quantity: this.formData.quantity
|
}
|
}).then(res => {
|
|
this.tableData = res.data.tbBillList;
|
if (this.tableData.length === 0) {
|
this.$showMessage("该物料未维护检验项目,请先维护检验项目!");
|
this.isSubmit = true;
|
this.tableData = [];
|
this.isShowTable = true;
|
// 保持新建模式,不切换到查看模式
|
this.isUpdate = true;
|
} else {
|
this.isSubmit = false;
|
this.isShowTable = true;
|
this.isUpdate = true;
|
}
|
});
|
},
|
saveTable() {
|
if (this.tableData.length === 0) {
|
return;
|
}
|
|
this.$post({
|
url: "/RKJ/saveItem",
|
data: {
|
gid: this.formData.id,
|
items: this.tableData,
|
userNo: this.$loginInfo.account
|
}
|
}).then(res => {
|
this.formData.id = res.data.tbBillList;
|
this.isShowTable = false;
|
this.isUpdate = false;
|
this.init();
|
})
|
},
|
cleanResult(){
|
if (this.formData.fsubmit == 1) {
|
this.$showMessage("该检验单已提交,不能清除检验结果");
|
return;
|
}
|
this.$post({
|
url: "/RKJ/cleanReqResult",
|
data: {
|
gid: this.formData.id,
|
userNo: this.$loginInfo.account
|
}
|
}).then(res => {
|
console.log(res);
|
if(res.status == 0){
|
this.init();
|
}else{
|
this.$showMessage(res.message);
|
}
|
|
})
|
},
|
|
// 提交检验方法
|
submitInspection() {
|
// 检查是否已提交
|
if (this.formData.fsubmit == 1) {
|
this.$showMessage("该检验单已提交,不能重复提交");
|
return;
|
}
|
|
// 检查是否有检验项目
|
if (this.tableData.length === 0) {
|
this.$showMessage("请先获取检验项目");
|
return;
|
}
|
|
// 检查是否所有检验项目都已完成
|
const unfinishedItems = this.tableData.filter(item =>
|
item.result === null || item.result === '未完成'
|
);
|
|
if (unfinishedItems.length > 0) {
|
this.$showMessage("还有检验项目未完成,请先完成所有检验项目");
|
return;
|
}
|
|
// 检查钉钉推送条件:PSZT为待判,且不良原因、不良描述、所属车间不为空
|
const shouldPushToDingTalk = this.PSTYPE === '待判' &&
|
this.badreason &&
|
this.formData.fngDesc &&
|
this.WORKSHOP;
|
|
let confirmMessage = '确定要提交此检验单吗?提交后将无法修改。';
|
if (shouldPushToDingTalk) {
|
confirmMessage += '\n\n满足钉钉推送条件,将自动推送到钉钉审批流程。';
|
}
|
|
// 确认提交
|
uni.showModal({
|
title: '确认提交',
|
content: confirmMessage,
|
success: (res) => {
|
if (res.confirm) {
|
this.$post({
|
url: "/RKJ/submitInspection",
|
data: {
|
id: this.formData.id,
|
userNo: this.$loginInfo.account
|
}
|
}).then(res => {
|
if (res.status == 0) {
|
let successMessage = "检验单提交成功!";
|
if (shouldPushToDingTalk) {
|
successMessage += "\n已推送到钉钉审批流程。";
|
}
|
this.$showMessage(successMessage);
|
// 更新本地状态
|
this.formData.fsubmit = 1;
|
// 刷新数据
|
this.init();
|
} else {
|
this.$showMessage(res.message || "提交失败");
|
}
|
}).catch(error => {
|
console.error("提交失败:", error);
|
this.$showMessage("提交失败,请重试");
|
});
|
}
|
}
|
});
|
},
|
viewAttachmentInfo() {
|
this.showAttachmentPopup = true; // 先弹窗
|
this.attachmentsLoading = true;
|
this.attachments = [];
|
this.$post({
|
url: "/RKJ/getAttachments",
|
data: { itemNo: this.formData.itemNo }
|
}).then(res => {
|
this.attachmentsLoading = false;
|
if (res.status === 0) {
|
this.attachments = res.data.tbBillList;
|
// 为每个附件设置默认可用状态
|
this.attachments.forEach((item, index) => {
|
this.$set(item, 'ftpAvailable', true); // 默认认为文件可用
|
this.$set(item, 'checking', false);
|
});
|
} else if (res.status === 1 && res.message === "该检验单未上传附件信息!") {
|
uni.showToast({ title: res.message, icon: "none" });
|
} else {
|
uni.showToast({ title: "获取附件失败", icon: "none" });
|
}
|
});
|
},
|
downloadAttachment(item) {
|
// 去除所有空格、全角空格、回车、换行
|
const fileName = item.fattach.replace(/[\s\u3000\r\n]+/g, '').trim();
|
// 使用配置的服务器地址和FTP服务器地址
|
const url = this.$store.state.serverInfo.serverAPI + "/RKJ/DownloadFtpFile?itemNo=" + encodeURIComponent(item.itemNo) + "&fileName=" + encodeURIComponent(fileName) + "&ftpServer=" + encodeURIComponent(this.$store.state.serverInfo.ftpServer);
|
|
// 检查运行环境
|
// #ifdef H5
|
// H5环境:使用浏览器下载
|
this.downloadFileInBrowser(url, fileName);
|
// #endif
|
|
// #ifdef APP-PLUS
|
// APP环境:使用uni.downloadFile
|
this.downloadFileInApp(url, fileName);
|
// #endif
|
|
// #ifdef MP
|
// 小程序环境:使用uni.downloadFile
|
this.downloadFileInApp(url, fileName);
|
// #endif
|
},
|
// 在浏览器中下载文件
|
downloadFileInBrowser(url, fileName) {
|
uni.showLoading({ title: '正在准备下载...' });
|
|
// 方法1:创建隐藏的a标签下载
|
try {
|
const link = document.createElement('a');
|
link.href = url;
|
link.download = fileName;
|
link.style.display = 'none';
|
document.body.appendChild(link);
|
link.click();
|
document.body.removeChild(link);
|
|
uni.hideLoading();
|
uni.showToast({
|
title: '下载已开始',
|
icon: 'success',
|
duration: 2000
|
});
|
} catch (error) {
|
console.log('a标签下载失败,尝试window.open方式:', error);
|
// 方法2:使用window.open
|
try {
|
window.open(url, '_blank');
|
uni.hideLoading();
|
uni.showToast({
|
title: '下载已开始',
|
icon: 'success',
|
duration: 2000
|
});
|
} catch (error2) {
|
console.log('window.open下载失败,尝试fetch方式:', error2);
|
// 方法3:使用fetch下载
|
this.downloadFileWithFetch(url, fileName);
|
}
|
}
|
},
|
// 使用fetch下载文件
|
downloadFileWithFetch(url, fileName) {
|
fetch(url)
|
.then(response => {
|
if (!response.ok) {
|
throw new Error(`HTTP error! status: ${response.status}`);
|
}
|
return response.blob();
|
})
|
.then(blob => {
|
// 创建blob URL
|
const blobUrl = window.URL.createObjectURL(blob);
|
|
// 创建下载链接
|
const link = document.createElement('a');
|
link.href = blobUrl;
|
link.download = fileName;
|
link.style.display = 'none';
|
document.body.appendChild(link);
|
link.click();
|
document.body.removeChild(link);
|
|
// 释放blob URL
|
window.URL.revokeObjectURL(blobUrl);
|
|
uni.hideLoading();
|
uni.showToast({
|
title: '下载成功',
|
icon: 'success',
|
duration: 2000
|
});
|
})
|
.catch(error => {
|
console.error('Fetch下载失败:', error);
|
uni.hideLoading();
|
if (error.message.includes('404')) {
|
uni.showModal({
|
title: '文件不存在',
|
content: `该附件在FTP服务器上不存在`,
|
showCancel: false
|
});
|
} else {
|
uni.showModal({
|
title: '下载失败',
|
content: `下载失败: ${error.message}`,
|
showCancel: false
|
});
|
}
|
});
|
},
|
// 在APP中下载文件
|
downloadFileInApp(url, fileName) {
|
// #ifdef APP-PLUS
|
uni.showLoading({ title: '从FTP服务器下载中...' });
|
|
// Android 获取存储路径
|
const saveDir = plus.os.name === 'Android' ? plus.io.convertLocalFileSystemURL('_downloads/') : plus.io.convertLocalFileSystemURL('_documents/');
|
const filePath = `${saveDir}${fileName}`;
|
|
const downloadTask = uni.downloadFile({
|
url: url,
|
filePath: filePath, // 指定保存路径
|
success: (res) => {
|
uni.hideLoading();
|
if (res.statusCode === 200) {
|
const fileInfo = {
|
name: fileName,
|
path: res.filePath || filePath,
|
tempPath: res.tempFilePath
|
};
|
|
uni.showModal({
|
title: '下载成功',
|
content: `文件已保存到:${fileInfo.path}`,
|
showCancel: true,
|
confirmText: '打开文件',
|
cancelText: '确定',
|
success: (modalRes) => {
|
if (modalRes.confirm) {
|
// 用户选择打开文件
|
this.openFileInApp(fileInfo);
|
}
|
}
|
});
|
} else if (res.statusCode === 404) {
|
uni.showModal({
|
title: '文件不存在',
|
content: `该附件在FTP服务器上不存在`,
|
showCancel: false
|
});
|
} else {
|
uni.showModal({
|
title: '下载失败',
|
content: `状态码:${res.statusCode}`,
|
showCancel: false
|
});
|
}
|
},
|
fail: (error) => {
|
uni.hideLoading();
|
console.error('下载失败:', error);
|
uni.showModal({
|
title: '下载失败',
|
content: `网络错误:${error.errMsg}`,
|
showCancel: false
|
});
|
}
|
});
|
|
// 监听下载进度
|
downloadTask.onProgressUpdate((res) => {
|
const progress = Math.round(res.progress);
|
uni.showLoading({
|
title: `下载中 ${progress}%`,
|
mask: true
|
});
|
});
|
// #endif
|
|
// #ifdef MP
|
// 小程序环境的简化实现
|
uni.showLoading({ title: '下载中...' });
|
uni.downloadFile({
|
url: url,
|
success: (res) => {
|
uni.hideLoading();
|
if (res.statusCode === 200) {
|
uni.showToast({ title: '下载完成', icon: 'success' });
|
}
|
},
|
fail: (error) => {
|
uni.hideLoading();
|
uni.showModal({ title: '下载失败', content: error.errMsg, showCancel: false });
|
}
|
});
|
// #endif
|
},
|
// APP中打开文件
|
openFileInApp(fileInfo) {
|
// #ifdef APP-PLUS
|
if (typeof plus !== 'undefined') {
|
const filePath = fileInfo.path || fileInfo.tempPath;
|
|
// 尝试打开文件
|
plus.runtime.openFile(filePath, {}, (error) => {
|
console.error('打开文件失败:', error);
|
uni.showModal({
|
title: '无法打开',
|
content: '系统中没有找到能打开此文件的应用程序',
|
showCancel: false
|
});
|
});
|
}
|
// #endif
|
},
|
// 预览FTP文件
|
previewFtpFile(item) {
|
const fileName = item.fattach.replace(/[\s\u3000\r\n]+/g, '').trim();
|
const fileExt = fileName.split('.').pop().toLowerCase();
|
|
// 检查文件类型是否支持预览
|
if (!this.isPreviewable(fileName)) {
|
uni.showModal({
|
title: '不支持预览',
|
content: '该文件类型不支持在线预览,请下载后查看',
|
showCancel: false
|
});
|
return;
|
}
|
|
const previewUrl = this.$store.state.serverInfo.serverAPI + "/RKJ/PreviewFtpFile?itemNo=" + encodeURIComponent(item.itemNo) + "&fileName=" + encodeURIComponent(fileName) + "&ftpServer=" + encodeURIComponent(this.$store.state.serverInfo.ftpServer);
|
|
// 根据文件类型进行不同的预览处理
|
if (['pdf'].includes(fileExt)) {
|
this.previewPdfFile(previewUrl, fileName);
|
} else if (['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(fileExt)) {
|
this.previewImageFile(previewUrl, fileName);
|
} else if (['txt'].includes(fileExt)) {
|
this.previewTextFile(previewUrl, fileName);
|
} else if (['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'].includes(fileExt)) {
|
this.previewOfficeFile(previewUrl, fileName);
|
} else {
|
// 尝试通用预览
|
this.previewGenericFile(previewUrl, fileName);
|
}
|
},
|
|
// 预览PDF文件
|
previewPdfFile(url, fileName) {
|
// 先下载PDF文件,转为base64后预览
|
uni.request({
|
url: url,
|
method: 'GET',
|
responseType: 'arraybuffer',
|
success: (res) => {
|
if (res.statusCode === 200) {
|
const base64Data = uni.arrayBufferToBase64(res.data);
|
// 存储到全局变量
|
getApp().globalData.tempPDF = base64Data;
|
uni.navigateTo({
|
url: `/pages/fileView/pdfView`
|
});
|
} else {
|
this.handlePreviewError(res.statusCode, fileName);
|
}
|
},
|
fail: (error) => {
|
this.handlePreviewError(0, fileName, error.errMsg);
|
}
|
});
|
},
|
|
// 预览图片文件
|
previewImageFile(url, fileName) {
|
// #ifdef APP-PLUS
|
// APP环境:先下载到本地再预览,避免网络图片加载问题
|
uni.showLoading({ title: '加载图片...' });
|
uni.downloadFile({
|
url: url,
|
success: (res) => {
|
uni.hideLoading();
|
if (res.statusCode === 200) {
|
// 使用本地临时路径
|
uni.navigateTo({
|
url: `/pages/fileView/imageView?url=${encodeURIComponent(res.tempFilePath)}`
|
});
|
} else {
|
this.handlePreviewError(res.statusCode, fileName);
|
}
|
},
|
fail: (error) => {
|
uni.hideLoading();
|
this.handlePreviewError(0, fileName, error.errMsg);
|
}
|
});
|
// #endif
|
|
// #ifdef H5 || MP
|
// H5和小程序:直接使用网络URL
|
uni.navigateTo({
|
url: `/pages/fileView/imageView?url=${encodeURIComponent(url)}`
|
});
|
// #endif
|
},
|
|
// 预览文本文件
|
previewTextFile(url, fileName) {
|
// 文本文件直接显示在弹窗中
|
uni.showLoading({ title: '加载文件内容...' });
|
uni.request({
|
url: url,
|
method: 'GET',
|
success: (res) => {
|
uni.hideLoading();
|
if (res.statusCode === 200) {
|
const fileType = this.getFileType(fileName);
|
|
if (fileType === 'text') {
|
// 文本文件:显示内容
|
this.showFilePreview(res.data, fileName);
|
} else if (fileType === 'image') {
|
// 图片文件:显示图片URL
|
this.showFilePreview(url, fileName);
|
} else {
|
// 其他文件类型:显示提示信息
|
this.showFilePreview('', fileName);
|
}
|
} else {
|
this.handlePreviewError(res.statusCode, fileName);
|
}
|
},
|
fail: (error) => {
|
uni.hideLoading();
|
this.handlePreviewError(0, fileName, error.errMsg);
|
}
|
});
|
},
|
|
// 检测文件类型
|
getFileType(fileName) {
|
const fileExt = fileName.split('.').pop().toLowerCase();
|
|
if (['txt', 'log', 'md', 'csv', 'json', 'xml'].includes(fileExt)) {
|
return 'text';
|
} else if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(fileExt)) {
|
return 'image';
|
} else if (['xls', 'xlsx', 'doc', 'docx', 'ppt', 'pptx'].includes(fileExt)) {
|
return 'excel';
|
} else {
|
return 'unsupported';
|
}
|
},
|
|
// 显示文件预览弹窗
|
showFilePreview(content, fileName) {
|
this.previewContent = content;
|
this.previewTitle = fileName;
|
this.previewItemNo = this.selectedAttachment?.itemNo || '';
|
this.previewType = this.getFileType(fileName);
|
this.showFilePreviewPopup = true;
|
},
|
|
// 关闭文件预览弹窗
|
closeFilePreview() {
|
this.showFilePreviewPopup = false;
|
this.previewContent = '';
|
this.previewTitle = '';
|
this.previewItemNo = '';
|
this.previewType = '';
|
},
|
|
// 下载预览文件
|
downloadPreviewFile() {
|
const item = { fattach: this.previewTitle, itemNo: this.previewItemNo };
|
this.downloadAttachment(item);
|
this.closeFilePreview();
|
},
|
|
// 在弹窗中预览图片(放大功能)
|
previewImageInPopup() {
|
// 使用uni.previewImage API实现图片放大预览
|
uni.previewImage({
|
current: this.previewContent, // 当前显示图片的链接
|
urls: [this.previewContent], // 需要预览的图片链接列表
|
loop: false, // 是否开启图片轮播
|
indicator: 'default', // 图片指示器类型
|
longPressActions: {
|
itemList: ['发送给朋友', '保存图片', '收藏'],
|
success: function (data) {
|
console.log('选中了第' + (data.tapIndex + 1) + '个按钮');
|
},
|
fail: function (err) {
|
console.log(err.errMsg);
|
}
|
},
|
success: () => {
|
console.log('图片预览成功');
|
},
|
fail: (err) => {
|
console.error('图片预览失败:', err);
|
uni.showToast({
|
title: '图片预览失败',
|
icon: 'none'
|
});
|
}
|
});
|
},
|
|
// 预览Office文件
|
previewOfficeFile(url, fileName) {
|
// 先检查Excel文件,使用专门的Excel预览页面
|
const fileExt = fileName.split('.').pop().toLowerCase();
|
if (['xls', 'xlsx'].includes(fileExt)) {
|
// Excel文件预览
|
uni.request({
|
url: url,
|
method: 'GET',
|
responseType: 'arraybuffer',
|
success: (res) => {
|
if (res.statusCode === 200) {
|
const base64Data = uni.arrayBufferToBase64(res.data);
|
// 存储 Base64 数据到本地存储
|
uni.setStorageSync('excelBase64Data', base64Data);
|
uni.navigateTo({
|
url: `/pages/fileView/excelView`
|
});
|
} else {
|
this.handlePreviewError(res.statusCode, fileName);
|
}
|
},
|
fail: (error) => {
|
this.handlePreviewError(0, fileName, error.errMsg);
|
}
|
});
|
} else if (['doc', 'docx'].includes(fileExt)) {
|
// Word文件,尝试使用Word预览页面或者微软在线预览
|
try {
|
const officePreviewUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`;
|
// 如果有webView页面,使用webView预览
|
this.previewGenericFile(officePreviewUrl, fileName);
|
} catch (error) {
|
this.handlePreviewError(0, fileName, '不支持此Office文件类型的预览');
|
}
|
} else {
|
// 其他Office文件,使用微软在线预览服务
|
const officePreviewUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`;
|
this.previewGenericFile(officePreviewUrl, fileName);
|
}
|
},
|
|
// 通用文件预览
|
previewGenericFile(url, fileName) {
|
// 由于没有通用的webView页面,显示提示并提供下载
|
uni.showModal({
|
title: '文件预览',
|
content: `文件 "${fileName}" 需要下载后查看,是否立即下载?`,
|
showCancel: true,
|
confirmText: '下载',
|
cancelText: '取消',
|
success: (res) => {
|
if (res.confirm) {
|
const item = { fattach: fileName, itemNo: this.selectedAttachment.itemNo };
|
this.downloadAttachment(item);
|
}
|
}
|
});
|
},
|
|
// 处理预览错误
|
handlePreviewError(statusCode, fileName, errorMsg = '') {
|
let message = '';
|
if (statusCode === 404) {
|
message = `文件 ${fileName} 在FTP服务器上不存在`;
|
} else if (statusCode === 0) {
|
message = `预览失败:${errorMsg}`;
|
} else {
|
message = `预览失败,状态码:${statusCode}`;
|
}
|
|
uni.showModal({
|
title: '预览失败',
|
content: message,
|
showCancel: true,
|
confirmText: '下载',
|
cancelText: '取消',
|
success: (res) => {
|
if (res.confirm) {
|
// 用户选择下载文件
|
const item = { fattach: fileName, itemNo: this.selectedAttachment.itemNo };
|
this.downloadAttachment(item);
|
}
|
}
|
});
|
},
|
onShow() {
|
//每次进入页面都会执行的方法
|
if (this.formData.id) {
|
this.init();
|
}
|
},
|
// 附件相关方法
|
closeAttachmentPopup() {
|
this.showAttachmentPopup = false;
|
},
|
showAttachmentDetailDialog(item) {
|
console.log('查看详情', item);
|
this.selectedAttachment = item;
|
this.showAttachmentPopup = false;
|
this.showAttachmentDetail = true;
|
console.log('showAttachmentDetail:', this.showAttachmentDetail);
|
},
|
closeAttachmentDetail() {
|
this.showAttachmentDetail = false;
|
this.selectedAttachment = null;
|
this.showAttachmentPopup = true;
|
},
|
isPreviewable(filename) {
|
if (!filename) return false;
|
const ext = filename.trim().split('.').pop().toLowerCase();
|
// 支持在线预览的文件类型
|
return [
|
'pdf', // PDF文件
|
'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', // 图片文件
|
'txt', 'log', 'md', // 文本文件
|
'doc', 'docx', // Word文档
|
'xls', 'xlsx', // Excel表格
|
'ppt', 'pptx', // PowerPoint演示文稿
|
'csv' // CSV文件
|
].includes(ext);
|
},
|
|
// 下拉框事件处理方法
|
onBadreasonChange(e) {
|
const index = e.detail.value;
|
this.badreasonIndex = index;
|
this.badreason = this.badreasonOptions[index];
|
this.saveDropdownFields('badreason');
|
},
|
onWorkshopChange(e) {
|
const index = e.detail.value;
|
this.workshopIndex = index;
|
this.WORKSHOP = this.workshopOptions[index];
|
this.saveDropdownFields('WORKSHOP');
|
},
|
onPstypeChange(e) {
|
const index = e.detail.value;
|
this.pstypeIndex = index;
|
this.PSTYPE = this.pstypeOptions[index];
|
this.saveDropdownFields('PSTYPE');
|
},
|
saveDropdownFields(fieldName) {
|
// 直接保存到数据库
|
const requestData = {
|
gid: this.formData.id,
|
releaseNo: this.formData.releaseNo,
|
BLYY: this.badreason || '',
|
SSCJ: this.WORKSHOP || '',
|
PSZT: this.PSTYPE || ''
|
};
|
console.log('发送的数据:', requestData);
|
console.log('badreason:', this.badreason);
|
console.log('WORKSHOP:', this.WORKSHOP);
|
console.log('PSTYPE:', this.PSTYPE);
|
console.log('选择的字段:', fieldName);
|
this.$post({
|
url: "/RKJ/saveDropdownFields",
|
data: requestData
|
}).then(res => {
|
if (res && res.data && res.data.data && res.data.data.tbBillList && res.data.data.tbBillList.length > 0) {
|
// 延迟重新加载数据,确保数据库更新完成
|
setTimeout(() => {
|
this.init();
|
}, 500);
|
}
|
}).catch(err => {
|
console.error('保存失败:', err);
|
});
|
},
|
saveFngDesc() {
|
// 保存不良描述到数据库
|
this.$post({
|
url: "/RKJ/saveFngDesc",
|
data: {
|
gid: this.formData.id,
|
fngDesc: this.formData.fngDesc
|
}
|
}).then(res => {
|
if (res.status == 0) {
|
this.$showMessage("不良描述保存成功");
|
} else {
|
this.$showMessage("不良描述保存失败");
|
}
|
}).catch(error => {
|
console.error("保存不良描述失败:", error);
|
this.$showMessage("保存不良描述失败,请重试");
|
});
|
}
|
}
|
};
|
</script>
|
|
<style>
|
/* 新建表单 - 优化后的UI样式 */
|
.create-form {
|
padding: 20px;
|
background-color: #f5f5f5;
|
min-height: 100vh;
|
font-family: 'Microsoft YaHei', 'Segoe UI', sans-serif;
|
}
|
|
.form-header {
|
text-align: center;
|
margin-bottom: 30px;
|
padding: 20px;
|
background-color: #fff;
|
border-radius: 8px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
}
|
|
.form-header h2 {
|
color: #2c3e50;
|
font-size: 24px;
|
margin: 0 0 8px 0;
|
font-weight: 600;
|
}
|
|
.form-subtitle {
|
color: #7f8c8d;
|
font-size: 14px;
|
margin: 0;
|
}
|
|
.form-content {
|
background-color: #fff;
|
border-radius: 8px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
margin-bottom: 20px;
|
overflow: hidden;
|
}
|
|
.form-section {
|
padding: 20px;
|
border-bottom: 1px solid #ecf0f1;
|
}
|
|
.form-section:last-child {
|
border-bottom: none;
|
}
|
|
.section-title {
|
font-size: 16px;
|
font-weight: 600;
|
color: #2c3e50;
|
margin-bottom: 15px;
|
padding-bottom: 8px;
|
border-bottom: 2px solid #3498db;
|
display: flex;
|
align-items: center;
|
}
|
|
.section-title::before {
|
content: "●";
|
color: #3498db;
|
margin-right: 8px;
|
font-size: 12px;
|
}
|
|
.form-row {
|
display: flex;
|
align-items: center;
|
margin-bottom: 15px;
|
padding: 12px 0;
|
transition: all 0.3s ease;
|
}
|
|
.form-row:hover {
|
background-color: #f8f9fa;
|
border-radius: 8px;
|
padding-left: 8px;
|
padding-right: 8px;
|
}
|
|
.form-row:last-child {
|
margin-bottom: 0;
|
}
|
|
.form-label {
|
width: 100px;
|
font-weight: 500;
|
color: #34495e;
|
flex-shrink: 0;
|
font-size: 14px;
|
display: flex;
|
align-items: center;
|
}
|
|
.form-label.required::after {
|
content: " *";
|
color: #e74c3c;
|
font-weight: bold;
|
}
|
|
.form-value {
|
color: #2c3e50;
|
flex: 1;
|
font-weight: 500;
|
padding: 8px 12px;
|
background-color: #f8f9fa;
|
border-radius: 6px;
|
border: 1px solid #e9ecef;
|
}
|
|
.form-select {
|
flex: 1;
|
padding: 10px 12px;
|
border: 2px solid #e9ecef;
|
border-radius: 8px;
|
background-color: white;
|
color: #2c3e50;
|
font-size: 14px;
|
transition: all 0.3s ease;
|
}
|
|
.form-select:focus {
|
border-color: #3498db;
|
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
|
outline: none;
|
}
|
|
.form-input {
|
flex: 1;
|
min-width: 200px;
|
padding: 8px 12px;
|
border: 1px solid #ddd;
|
border-radius: 4px;
|
font-size: 14px;
|
background-color: white;
|
box-sizing: border-box;
|
}
|
|
.large-quantity-input {
|
min-width: 200px !important;
|
padding: 8px 12px !important;
|
font-size: 14px !important;
|
border: 1px solid #ddd !important;
|
border-radius: 4px !important;
|
background-color: white !important;
|
transition: all 0.3s ease;
|
font-weight: normal !important;
|
text-align: left !important;
|
flex: 1;
|
}
|
|
.large-quantity-input:focus {
|
border-color: #3498db;
|
box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
|
outline: none;
|
background-color: white;
|
}
|
|
.large-quantity-input::placeholder {
|
color: #95a5a6;
|
font-size: 16px;
|
}
|
|
.input-field {
|
width: 100%;
|
padding: 8px 12px;
|
border: 1px solid #ddd;
|
border-radius: 4px;
|
font-size: 14px;
|
background-color: white;
|
box-sizing: border-box;
|
min-height: 36px;
|
}
|
|
.input-field:focus {
|
outline: none;
|
border-color: #3498db;
|
box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
|
}
|
|
.form-hint {
|
flex: 1;
|
color: #95a5a6;
|
font-size: 14px;
|
font-style: italic;
|
padding: 10px 12px;
|
background-color: #f8f9fa;
|
border-radius: 8px;
|
border: 1px dashed #bdc3c7;
|
}
|
|
.form-actions {
|
text-align: center;
|
padding: 20px;
|
background-color: #fff;
|
border-radius: 8px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
}
|
|
.btn-primary {
|
background-color: #3498db;
|
color: white;
|
padding: 14px 32px;
|
border: none;
|
border-radius: 8px;
|
font-size: 16px;
|
font-weight: 500;
|
cursor: pointer;
|
transition: all 0.3s ease;
|
display: inline-flex;
|
align-items: center;
|
justify-content: center;
|
gap: 8px;
|
box-shadow: 0 2px 8px rgba(52, 152, 219, 0.3);
|
}
|
|
.btn-primary:hover {
|
transform: translateY(-2px);
|
box-shadow: 0 6px 20px rgba(52, 152, 219, 0.4);
|
}
|
|
.btn-primary:active {
|
transform: translateY(0);
|
}
|
|
.btn-primary:disabled {
|
background: #bdc3c7;
|
cursor: not-allowed;
|
transform: none;
|
box-shadow: none;
|
}
|
|
.btn-icon {
|
font-size: 16px;
|
font-weight: bold;
|
}
|
|
/* 查看/编辑表单 - LLJ类似的样式 */
|
.inspection-sheet {
|
font-family: 'Microsoft YaHei', 'Segoe UI', sans-serif;
|
max-width: 1000px;
|
margin: 0 auto;
|
padding: 20px 20px 100px 20px; /* 底部增加内边距为固定按钮留空间 */
|
background-color: #fff;
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
min-height: 100vh;
|
position: relative;
|
}
|
|
/* 头部样式 */
|
.sheet-header {
|
text-align: center;
|
margin-bottom: 20px;
|
padding-bottom: 15px;
|
border-bottom: 2px solid #e0e0e0;
|
}
|
|
.sheet-header h1 {
|
color: #2c3e50;
|
font-size: 24px;
|
margin-bottom: 5px;
|
}
|
|
.inspection-number {
|
font-size: 16px;
|
font-weight: bold;
|
color: #3498db;
|
}
|
|
/* 基本信息区样式 */
|
.basic-info,
|
.material-info {
|
margin-bottom: 20px;
|
}
|
|
.info-row {
|
display: flex;
|
margin-bottom: 10px;
|
flex-wrap: wrap;
|
}
|
|
.info-label {
|
font-weight: bold;
|
color: #34495e;
|
min-width: 80px;
|
margin-right: 5px;
|
}
|
|
.info-value {
|
color: #2c3e50;
|
margin-right: 20px;
|
}
|
|
.picker-text {
|
padding: 6px 10px;
|
border: 1px solid #ddd;
|
border-radius: 4px;
|
background-color: white;
|
color: #999;
|
font-size: 14px;
|
min-height: 32px;
|
display: flex;
|
align-items: center;
|
max-width: 150px;
|
}
|
|
.picker-text.selected {
|
color: #e74c3c;
|
font-weight: 500;
|
}
|
|
.highlight {
|
font-weight: bold;
|
color: #e74c3c;
|
}
|
|
/* 物料信息区样式 */
|
.material-info {
|
border: 1px solid #eee;
|
padding: 15px;
|
border-radius: 5px;
|
}
|
|
.info-block {
|
display: flex;
|
align-items: center;
|
margin-bottom: 10px;
|
flex-wrap: wrap;
|
}
|
|
.dropdown-row {
|
display: flex;
|
align-items: center;
|
margin-bottom: 10px;
|
}
|
|
/* 表格样式 */
|
.inspection-table {
|
margin: 25px 0;
|
}
|
|
.inspection-table table {
|
width: 100%;
|
border-collapse: collapse;
|
}
|
|
.inspection-table th,
|
.inspection-table td {
|
padding: 12px 15px;
|
border: 1px solid #ddd;
|
text-align: left;
|
}
|
|
.inspection-table th {
|
background-color: #f8f9fa;
|
font-weight: bold;
|
color: #34495e;
|
}
|
|
.inspection-table tr:nth-child(even) {
|
background-color: #f9f9f9;
|
}
|
|
.inspection-table tr:hover {
|
background-color: #f1f5f9;
|
}
|
|
/* 水印样式 */
|
.watermark {
|
position: absolute;
|
font-size: 40px;
|
font-weight: bold;
|
opacity: 1;
|
z-index: 1;
|
pointer-events: none;
|
transform: rotate(-15deg);
|
width: 100%;
|
text-align: center;
|
top: 50%;
|
left: 50%;
|
transform: translate(-50%, -50%) rotate(-15deg);
|
}
|
|
.watermark.approved {
|
color: #2ecc71;
|
}
|
|
.watermark.rejected {
|
color: #e74c3c;
|
}
|
|
.watermark.pending {
|
color: #f39c12;
|
}
|
|
/* 描述文本容器 */
|
.description-text {
|
position: relative;
|
z-index: 2;
|
padding: 25px;
|
background-color: rgba(255, 255, 255, 0.7);
|
}
|
|
/* 调整表格单元格 */
|
.inspection-table td:nth-child(2) {
|
position: relative;
|
overflow: hidden;
|
padding: 0;
|
}
|
|
/* 表单上方操作按钮区样式 */
|
.top-action-buttons {
|
display: flex;
|
justify-content: flex-end;
|
gap: 10px;
|
margin: 20px 0;
|
padding: 15px;
|
background-color: #f8f9fa;
|
border-radius: 8px;
|
border: 1px solid #e9ecef;
|
}
|
|
/* 表单下方操作按钮区样式 */
|
.bottom-action-buttons {
|
display: flex;
|
justify-content: center;
|
gap: 8px;
|
padding: 12px;
|
flex-wrap: wrap;
|
align-items: center;
|
position: fixed; /* 固定在屏幕底部 */
|
bottom: 0; /* 距离底部0px */
|
left: 0; /* 距离左边0px */
|
right: 0; /* 距离右边0px */
|
background-color: #fff; /* 背景色 */
|
border-top: 1px solid #e9ecef; /* 顶部边框 */
|
z-index: 1000; /* 确保在最上层 */
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); /* 顶部阴影 */
|
}
|
|
.action-btn {
|
background-color: #ecf0f1;
|
color: #34495e;
|
padding: 12px 15px;
|
border: none;
|
border-radius: 6px;
|
cursor: pointer;
|
font-size: 14px;
|
font-weight: 500;
|
transition: all 0.3s ease;
|
text-align: center;
|
min-height: 44px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.action-btn:hover {
|
background-color: #d5dbdb;
|
transform: translateY(-1px);
|
}
|
|
.action-btn.primary {
|
background-color: #3498db;
|
color: #fff;
|
}
|
|
.action-btn.primary:hover {
|
background-color: #2980b9;
|
}
|
|
/* 小尺寸按钮样式 */
|
.action-btn.small {
|
padding: 10px 12px;
|
font-size: 14px;
|
min-height: 44px;
|
white-space: nowrap;
|
flex-shrink: 0;
|
min-width: 80px;
|
max-width: 120px;
|
flex: 1;
|
}
|
|
.record-btn {
|
padding: 6px 12px;
|
background-color: #f8f9fa;
|
border: 1px solid #ddd;
|
border-radius: 3px;
|
cursor: pointer;
|
transition: all 0.2s;
|
font-size: 14px;
|
color: #333;
|
}
|
|
.record-btn:hover {
|
background-color: #e9ecef;
|
}
|
|
/* 弹出框样式 */
|
.overlay {
|
position: fixed;
|
top: 0;
|
left: 0;
|
width: 100%;
|
height: 100%;
|
background-color: rgba(0, 0, 0, 0.5);
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
z-index: 1000;
|
}
|
|
.popup {
|
background-color: white;
|
border-radius: 8px;
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
width: 90%;
|
max-width: 400px;
|
max-height: 80vh;
|
overflow-y: auto;
|
padding: 20px;
|
}
|
|
.popup h3 {
|
font-size: 18px;
|
font-weight: 600;
|
color: #2c3e50;
|
margin: 0 0 20px 0;
|
}
|
|
.form-group {
|
margin-bottom: 15px;
|
}
|
|
.form-label {
|
display: block;
|
font-size: 14px;
|
color: #7f8c8d;
|
font-weight: 500;
|
margin-bottom: 5px;
|
}
|
|
.form-input {
|
width: 100%;
|
padding: 8px 12px;
|
border: 1px solid #ddd;
|
border-radius: 4px;
|
font-size: 14px;
|
background-color: white;
|
box-sizing: border-box;
|
}
|
|
.updateBut {
|
background-color: #3498db;
|
color: white;
|
padding: 10px 20px;
|
border: none;
|
border-radius: 4px;
|
cursor: pointer;
|
font-size: 14px;
|
margin-right: 10px;
|
}
|
|
.updateBut:hover {
|
background-color: #2980b9;
|
}
|
|
/* 无数据提示样式 */
|
.no-data-tip {
|
text-align: center;
|
padding: 40px 20px;
|
background-color: #f8f9fa;
|
border: 1px dashed #ddd;
|
border-radius: 8px;
|
margin: 20px 0;
|
}
|
|
/* 响应式设计 */
|
@media (max-width: 768px) {
|
.info-row {
|
flex-direction: column;
|
}
|
|
.info-block {
|
flex-direction: column;
|
align-items: flex-start;
|
}
|
|
.dropdown-row {
|
flex-direction: column;
|
align-items: flex-start;
|
}
|
|
.bottom-action-buttons {
|
flex-direction: column;
|
gap: 5px;
|
}
|
|
.action-btn.small {
|
min-width: 100%;
|
max-width: none;
|
}
|
}
|
|
/* 附件相关样式 */
|
.attachment-detail-popup {
|
width: 80vw;
|
max-width: 500px;
|
max-height: 70vh;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.attachment-popup-title {
|
font-size: 22px;
|
font-weight: 700;
|
color: #222;
|
margin-bottom: 8px;
|
letter-spacing: 1px;
|
text-align: center;
|
}
|
|
.attachment-popup-divider {
|
height: 1px;
|
background: linear-gradient(90deg,#e0e7ef 0%,#f5f7fa 100%);
|
margin-bottom: 18px;
|
}
|
|
.attachment-detail-content {
|
margin-bottom: 18px;
|
}
|
|
.attachment-detail-row {
|
display: flex;
|
align-items: center;
|
margin-bottom: 8px;
|
font-size: 15px;
|
}
|
|
.attachment-label {
|
min-width: 80px;
|
color: #1976d2;
|
font-weight: 500;
|
margin-right: 8px;
|
}
|
|
.attachment-detail-empty {
|
color: #888;
|
text-align: center;
|
margin: 30px 0;
|
font-size: 16px;
|
}
|
|
.attachment-popup-close {
|
margin-top: 18px;
|
width: 100%;
|
background: linear-gradient(90deg,#e0e0e0 0%,#f5f7fa 100%);
|
color: #444;
|
border-radius: 8px;
|
font-size: 16px;
|
padding: 10px 0;
|
border: none;
|
font-weight: 600;
|
letter-spacing: 1px;
|
transition: background 0.2s, color 0.2s;
|
box-shadow: 0 2px 8px rgba(60,60,60,0.06);
|
}
|
|
.attachment-popup-close:hover {
|
background: linear-gradient(90deg,#bdbdbd 0%,#e0e0e0 100%);
|
color: #1976d2;
|
}
|
|
/* 附件详情页面的操作按钮 */
|
.attachment-actions-detail {
|
margin: 20px 0;
|
display: flex;
|
gap: 12px;
|
justify-content: center;
|
flex-wrap: wrap;
|
}
|
|
.attachment-action-btn {
|
padding: 10px 20px;
|
border: none;
|
border-radius: 8px;
|
font-size: 14px;
|
font-weight: 600;
|
cursor: pointer;
|
transition: all 0.3s ease;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
min-width: 120px;
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
}
|
|
.attachment-action-btn.preview-btn {
|
background: linear-gradient(135deg, #4CAF50, #45a049);
|
color: white;
|
}
|
|
.attachment-action-btn.preview-btn:hover {
|
background: linear-gradient(135deg, #45a049, #3d8b40);
|
transform: translateY(-1px);
|
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
}
|
|
.attachment-action-btn.download-btn {
|
background: linear-gradient(135deg, #2196F3, #1976D2);
|
color: white;
|
}
|
|
.attachment-action-btn.download-btn:hover {
|
background: linear-gradient(135deg, #1976D2, #1565C0);
|
transform: translateY(-1px);
|
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
}
|
|
/* 文件预览弹窗样式 */
|
.file-preview-popup {
|
width: 80vw;
|
max-width: 600px;
|
max-height: 70vh;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.file-preview-title {
|
font-size: 18px;
|
font-weight: 700;
|
color: #222;
|
margin-bottom: 8px;
|
text-align: center;
|
word-break: break-all;
|
}
|
|
.file-preview-divider {
|
height: 1px;
|
background: linear-gradient(90deg,#e0e7ef 0%,#f5f7fa 100%);
|
margin-bottom: 16px;
|
}
|
|
.file-preview-content {
|
flex: 1;
|
max-height: 400px;
|
overflow-y: auto;
|
background: #f8fafc;
|
border-radius: 8px;
|
padding: 16px;
|
margin-bottom: 16px;
|
border: 1px solid #e2e8f0;
|
}
|
|
.file-preview-content pre {
|
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
font-size: 12px;
|
line-height: 1.5;
|
color: #2d3748;
|
white-space: pre-wrap;
|
word-wrap: break-word;
|
margin: 0;
|
}
|
|
/* 图片预览样式 */
|
.image-preview-container {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
min-height: 200px;
|
}
|
|
/* 不支持文件类型的提示样式 */
|
.unsupported-preview {
|
text-align: center;
|
padding: 40px 20px;
|
color: #666;
|
}
|
|
.unsupported-icon {
|
font-size: 48px;
|
margin-bottom: 16px;
|
}
|
|
.unsupported-text {
|
font-size: 16px;
|
font-weight: 600;
|
color: #333;
|
margin-bottom: 8px;
|
}
|
|
.unsupported-hint {
|
font-size: 14px;
|
color: #999;
|
line-height: 1.4;
|
}
|
|
.file-preview-actions {
|
display: flex;
|
gap: 12px;
|
justify-content: center;
|
}
|
|
.file-preview-btn {
|
padding: 8px 20px;
|
border: none;
|
border-radius: 6px;
|
font-size: 14px;
|
font-weight: 600;
|
cursor: pointer;
|
transition: all 0.3s ease;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
min-width: 120px;
|
}
|
|
.file-preview-btn.download-btn {
|
background: linear-gradient(135deg, #2196F3, #1976D2);
|
color: white;
|
}
|
|
.file-preview-btn.download-btn:hover {
|
background: linear-gradient(135deg, #1976D2, #1565C0);
|
transform: translateY(-1px);
|
}
|
|
.file-preview-btn.close-btn {
|
background: linear-gradient(135deg, #e0e0e0, #bdbdbd);
|
color: #444;
|
}
|
|
.file-preview-btn.close-btn:hover {
|
background: linear-gradient(135deg, #bdbdbd, #9e9e9e);
|
transform: translateY(-1px);
|
}
|
|
/* 列表弹窗美化 */
|
.attachment-list {
|
padding: 0;
|
margin: 0;
|
list-style: none;
|
max-height: 300px;
|
overflow-y: auto;
|
}
|
|
.attachment-list li {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding: 12px 0;
|
border-bottom: 1px solid #f0f0f0;
|
}
|
|
.attachment-info {
|
flex: 1;
|
margin-right: 10px;
|
}
|
|
.attachment-name {
|
color: #3498db;
|
cursor: pointer;
|
font-weight: 500;
|
transition: color 0.2s;
|
display: block;
|
margin-bottom: 4px;
|
}
|
|
.attachment-name:hover {
|
color: #217dbb;
|
text-decoration: underline;
|
}
|
|
.attachment-meta {
|
font-size: 12px;
|
}
|
|
.attachment-type {
|
color: #7f8c8d;
|
font-style: italic;
|
}
|
|
.attachment-actions {
|
display: flex;
|
gap: 8px;
|
flex-shrink: 0;
|
}
|
|
.attachment-list .secondary-btn {
|
padding: 4px 10px;
|
font-size: 13px;
|
border-radius: 3px;
|
background: #f5f7fa;
|
color: #333;
|
border: 1px solid #dbe2ea;
|
transition: background 0.2s, color 0.2s;
|
}
|
|
.attachment-list .secondary-btn:hover {
|
background: #e6f0fa;
|
color: #1976d2;
|
}
|
|
.preview-btn {
|
background: #e8f5e8 !important;
|
color: #2e7d2e !important;
|
border-color: #a5d6a5 !important;
|
}
|
|
.preview-btn:hover {
|
background: #d4eecc !important;
|
color: #1e5f1e !important;
|
}
|
|
/* 图片放大预览相关样式 */
|
.preview-image-clickable {
|
transition: transform 0.2s ease;
|
border-radius: 8px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
}
|
|
.preview-image-clickable:hover {
|
transform: scale(1.02);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
}
|
|
.image-zoom-hint {
|
text-align: center;
|
margin-top: 8px;
|
font-size: 12px;
|
color: #666;
|
font-style: italic;
|
}
|
|
.image-preview-container {
|
position: relative;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
}
|
</style>
|