|
|
@@ -0,0 +1,488 @@
|
|
|
+<template>
|
|
|
+ <div class="traceability-page">
|
|
|
+ <!-- 顶部导航栏 -->
|
|
|
+ <!-- <div class="navbar">
|
|
|
+ <button class="back-button" @click="handleBack">
|
|
|
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
+ <path d="M19 12H5M12 19l-7-7 7-7"/>
|
|
|
+ </svg>
|
|
|
+ </button>
|
|
|
+ <h1 class="navbar-title">溯源</h1>
|
|
|
+ <div class="navbar-right"></div>
|
|
|
+ </div> -->
|
|
|
+
|
|
|
+ <!-- 主内容区 -->
|
|
|
+ <div class="content-wrapper">
|
|
|
+ <!-- 编辑中标签 -->
|
|
|
+ <!-- <div class="edit-tag">编辑中</div> -->
|
|
|
+
|
|
|
+ <!-- 产品图片区域 -->
|
|
|
+ <div class="product-image-section">
|
|
|
+ <div class="image-container">
|
|
|
+ <img v-if="detail.purchaseInfo && detail.purchaseInfo.purchaseImgUrl" class="product-image" :src="detail.purchaseInfo.purchaseImgUrl" alt="产品图片">
|
|
|
+ <div v-else>暂无图片</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 产品基本信息区域 -->
|
|
|
+ <div class="product-info-section">
|
|
|
+ <div class="info-title">产品基本信息</div>
|
|
|
+ <div class="info-content">
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">品名:</span>
|
|
|
+ <span class="info-value">{{ detail.productName }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">产地:</span>
|
|
|
+ <span class="info-value">{{ detail.purchaseOrigins }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">商品编码:</span>
|
|
|
+ <span class="info-value">{{ detail.productCode }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">批号:</span>
|
|
|
+ <span class="info-value">{{ detail.batchNo }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="showMoreInfo">
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">规格:</span>
|
|
|
+ <span class="info-value">{{ detail.specification }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">内控等级:</span>
|
|
|
+ <span class="info-value">{{ detail.level }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">内控规格:</span>
|
|
|
+ <span class="info-value"></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">执行标准:</span>
|
|
|
+ <span class="info-value">{{ detail.enforceStandards }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">性味与归经:</span>
|
|
|
+ <span class="info-value"></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">功能与主治:</span>
|
|
|
+ <span class="info-value"></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">用法与用量:</span>
|
|
|
+ <span class="info-value"></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="info-row">
|
|
|
+ <div class="info-col">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="info-label">贮藏:</span>
|
|
|
+ <span class="info-value">{{ detail.layBy }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 查看更多信息按钮 -->
|
|
|
+ <div class="more-info-btn" @click="toggleMoreInfo">
|
|
|
+ <span>{{ showMoreInfo ? '收起' : '查看更多信息' }}</span>
|
|
|
+ <i :class="[showMoreInfo ? 'el-icon-arrow-up' : 'el-icon-arrow-down']"></i>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 功能按钮区域 -->
|
|
|
+ <div class="function-buttons">
|
|
|
+ <div class="button-row">
|
|
|
+ <div class="function-btn" @click="navigateToPurchase">
|
|
|
+ <img class="btn-icon" :src="cartIconSrc" alt="采购溯源图标">
|
|
|
+ <span class="btn-text">采购溯源</span>
|
|
|
+ </div>
|
|
|
+ <div class="function-btn" @click="navigateToProduction">
|
|
|
+ <img class="btn-icon" :src="productionIconSrc" alt="生产溯源图标">
|
|
|
+ <span class="btn-text">生产溯源</span>
|
|
|
+ </div>
|
|
|
+ <div class="function-btn" @click="navigateToQuality">
|
|
|
+ <img class="btn-icon" :src="qualityIconSrc" alt="质检溯源图标">
|
|
|
+ <span class="btn-text">质检溯源</span>
|
|
|
+ </div>
|
|
|
+ <div class="function-btn" @click="navigateToCompany">
|
|
|
+ <img class="btn-icon" :src="companyIconSrc" alt="企业信息图标">
|
|
|
+ <span class="btn-text">企业信息</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { queryPrintV2detail } from '@/api/traceability';
|
|
|
+export default {
|
|
|
+ name: 'TraceabilityPage',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ traceId: '',
|
|
|
+ detail: {},
|
|
|
+ showMoreInfo: false,
|
|
|
+ // 使用项目中已有的图标路径
|
|
|
+ productImageSrc: require('@/assets/traceability/1.svg'),
|
|
|
+ selectIconSrc: require('@/assets/traceability/1.svg'),
|
|
|
+ cartIconSrc: require('@/assets/traceability/1.svg'),
|
|
|
+ productionIconSrc: require('@/assets/traceability/1.svg'),
|
|
|
+ qualityIconSrc: require('@/assets/traceability/1.svg'),
|
|
|
+ companyIconSrc: require('@/assets/traceability/1.svg'),
|
|
|
+ };
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ // 组件挂载时获取路由传递的ID
|
|
|
+ this.getTraceabilityId();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ handleBack() {
|
|
|
+ // 返回上一页
|
|
|
+ this.$router.back();
|
|
|
+ },
|
|
|
+ toggleMoreInfo() {
|
|
|
+ // 切换显示更多信息
|
|
|
+ this.showMoreInfo = !this.showMoreInfo;
|
|
|
+ },
|
|
|
+ navigateToPurchase() {
|
|
|
+ // 跳转到采购溯源页面并传递detail对象
|
|
|
+ this.$router.push({
|
|
|
+ path: '/traceability/purchase',
|
|
|
+ query: {
|
|
|
+ detail: JSON.stringify(this.detail)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ navigateToProduction() {
|
|
|
+ // 跳转到生产溯源页面
|
|
|
+ this.$router.push({
|
|
|
+ path: '/traceability/production',
|
|
|
+ query: {
|
|
|
+ detail: JSON.stringify(this.detail)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ navigateToQuality() {
|
|
|
+ // 跳转到质检溯源页面
|
|
|
+ this.$router.push({
|
|
|
+ path: '/traceability/quality',
|
|
|
+ query: {
|
|
|
+ detail: JSON.stringify(this.detail)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ navigateToCompany() {
|
|
|
+ // 跳转到企业信息页面
|
|
|
+ this.$router.push({
|
|
|
+ path: '/traceability/company',
|
|
|
+ query: {
|
|
|
+ detail: JSON.stringify(this.detail)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ getTraceabilityId() {
|
|
|
+ // 从路由参数中获取ID
|
|
|
+ // 首先尝试从params中获取
|
|
|
+ const paramsId = this.$route.params.id;
|
|
|
+ // 然后尝试从query中获取
|
|
|
+ const queryId = this.$route.query.id;
|
|
|
+
|
|
|
+ // 设置ID,优先使用params中的ID
|
|
|
+ this.traceId = paramsId || queryId || '';
|
|
|
+
|
|
|
+ // 如果获取到了ID,可以根据需要进行后续操作
|
|
|
+ if (this.traceId) {
|
|
|
+ console.log('获取到溯源ID:', this.traceId);
|
|
|
+ // 这里可以根据ID加载对应的数据
|
|
|
+ this.loadTraceabilityData(this.traceId);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ loadTraceabilityData(id) {
|
|
|
+ queryPrintV2detail({
|
|
|
+ workOrderId: id
|
|
|
+ }).then(res => {
|
|
|
+ console.log('获取到溯源详情:', res.data);
|
|
|
+ this.detail = res.data;
|
|
|
+ }).catch(err => {
|
|
|
+ console.error('获取溯源详情失败:', err);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ // 监听路由变化,当路由参数改变时重新获取ID
|
|
|
+ '$route': {
|
|
|
+ handler: 'getTraceabilityId',
|
|
|
+ immediate: true
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.traceability-page {
|
|
|
+ background-color: #fff;
|
|
|
+ min-height: 100vh;
|
|
|
+ background-image: url('~@/assets/traceability/bg.jpg');
|
|
|
+ background-size: cover;
|
|
|
+ background-position: center;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.navbar {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ height: 60px;
|
|
|
+ background-color: #fff;
|
|
|
+ color: #000;
|
|
|
+ padding: 0 20px;
|
|
|
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ z-index: 1000;
|
|
|
+}
|
|
|
+
|
|
|
+.back-button {
|
|
|
+ background: none;
|
|
|
+ border: none;
|
|
|
+ color: #000;
|
|
|
+ cursor: pointer;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.navbar-title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ margin: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.navbar-right {
|
|
|
+ width: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.content-wrapper {
|
|
|
+ padding: 80px 20px 20px;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.edit-tag {
|
|
|
+ position: absolute;
|
|
|
+ top: 80px;
|
|
|
+ left: 0;
|
|
|
+ width: 80px;
|
|
|
+ height: 30px;
|
|
|
+ background: linear-gradient(135deg, #ff6b6b, #ff8e53);
|
|
|
+ color: #fff;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 30px;
|
|
|
+ font-size: 13px;
|
|
|
+ border-radius: 0 15px 15px 0;
|
|
|
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
|
|
+ z-index: 10;
|
|
|
+}
|
|
|
+
|
|
|
+.product-image-section {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ margin-bottom: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.image-container {
|
|
|
+ width: 150px;
|
|
|
+ height: 150px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background-color: #fff;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
|
+ border: 8px solid #fff;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+/* 添加红色装饰边框 */
|
|
|
+.image-container::before {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: -12px;
|
|
|
+ left: -12px;
|
|
|
+ right: -12px;
|
|
|
+ bottom: -12px;
|
|
|
+ border-radius: 50%;
|
|
|
+ border: 1px dashed #ff6b6b;
|
|
|
+ opacity: 0.6;
|
|
|
+}
|
|
|
+
|
|
|
+.product-image {
|
|
|
+ width: 120px;
|
|
|
+ height: 120px;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.product-info-section {
|
|
|
+ background-color: rgba(255, 255, 255, 0.95);
|
|
|
+ border-radius: 10px;
|
|
|
+ padding: 15px;
|
|
|
+ margin-bottom: 30px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
+ border: 1px solid #ffe6e6;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.info-title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #fff;
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ padding: 5px 20px;
|
|
|
+ background: #bd0402;
|
|
|
+ border-radius: 5px;
|
|
|
+ box-shadow: 0 1px 4px rgba(255, 107, 107, 0.3);
|
|
|
+ position: absolute;
|
|
|
+ top: -10px;
|
|
|
+ left: 30%;
|
|
|
+ // transform: translateX(-50%);
|
|
|
+}
|
|
|
+
|
|
|
+.info-content {
|
|
|
+ margin-bottom: 10px;
|
|
|
+ padding-top: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.info-row {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.info-col {
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.info-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+}
|
|
|
+
|
|
|
+.info-label {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #bd0402;
|
|
|
+ margin-right: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.info-value {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333;
|
|
|
+ font-weight: 500;
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.more-info-btn {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #bd0402;
|
|
|
+ padding: 5px 0;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.dropdown-icon {
|
|
|
+ width: 12px;
|
|
|
+ height: 12px;
|
|
|
+ margin-left: 5px;
|
|
|
+ transition: transform 0.3s;
|
|
|
+}
|
|
|
+
|
|
|
+.function-buttons {
|
|
|
+ margin-bottom: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.button-row {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.function-btn {
|
|
|
+ flex: 1;
|
|
|
+ height: 120px;
|
|
|
+ background: #bd0402;
|
|
|
+ border-radius: 10px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ color: #fff;
|
|
|
+ box-shadow: 0 4px 12px rgba(255, 107, 107, 0.3);
|
|
|
+ transition: transform 0.2s;
|
|
|
+ border: 1px solid #fff;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.function-btn:hover {
|
|
|
+ transform: translateY(-2px);
|
|
|
+}
|
|
|
+
|
|
|
+.function-btn:active {
|
|
|
+ transform: scale(0.98);
|
|
|
+}
|
|
|
+
|
|
|
+.btn-icon {
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ margin-bottom: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.btn-text {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+</style>
|