|
|
|
@ -0,0 +1,809 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="app-container">
|
|
|
|
|
<!-- 页面头部 -->
|
|
|
|
|
<div class="page-header">
|
|
|
|
|
<div class="header-title">
|
|
|
|
|
<i class="el-icon-monitor"></i>
|
|
|
|
|
<span>药品追溯系统</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="header-info">
|
|
|
|
|
<span>安全可靠 · 全程追溯 · 质量保证</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="header-wave"></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 扫码查询区域 -->
|
|
|
|
|
<el-card class="box-card scan-area" :body-style="{padding: '30px 20px'}">
|
|
|
|
|
<div class="scan-title">
|
|
|
|
|
<i class="el-icon-search pulse-icon"></i>
|
|
|
|
|
<span>药品追溯码查询</span>
|
|
|
|
|
</div>
|
|
|
|
|
<el-form :inline="true" :model="queryForm" size="mini">
|
|
|
|
|
<el-form-item class="query-form-item">
|
|
|
|
|
<el-input
|
|
|
|
|
v-model="queryForm.traceCode"
|
|
|
|
|
style="width: 600px"
|
|
|
|
|
placeholder="请扫描或输入药品追溯码"
|
|
|
|
|
clearable
|
|
|
|
|
@keyup.enter.native="handleSearch"
|
|
|
|
|
class="trace-input"
|
|
|
|
|
>
|
|
|
|
|
<i slot="prefix" class="el-icon-scan" style="font-size: 20px; color: #1976d2;"></i>
|
|
|
|
|
</el-input>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item class="query-form-item">
|
|
|
|
|
<el-button-group>
|
|
|
|
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch" size="mini" class="search-btn">查询
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button type="default" icon="el-icon-refresh" @click="resetForm" size="mini">重置</el-button>
|
|
|
|
|
</el-button-group>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
<!-- 药品基本信息 -->
|
|
|
|
|
<transition name="fade-transform" mode="out-in">
|
|
|
|
|
<el-card class="box-card info-card" v-if="drugInfo.nameCode" key="info-card">
|
|
|
|
|
<div slot="header" class="clearfix">
|
|
|
|
|
<span><i class="el-icon-medicine-box"></i> 药品基本信息</span>
|
|
|
|
|
</div>
|
|
|
|
|
<el-descriptions :column="2" border>
|
|
|
|
|
<el-descriptions-item label="产品名称">{{ drugInfo.cpmctymc }}</el-descriptions-item>
|
|
|
|
|
<el-descriptions-item label="产品标识">{{ drugInfo.nameCode }}</el-descriptions-item>
|
|
|
|
|
<el-descriptions-item label="规格">{{ drugInfo.prepnSpec }}</el-descriptions-item>
|
|
|
|
|
<el-descriptions-item label="包装规格">{{ drugInfo.bzgg }}</el-descriptions-item>
|
|
|
|
|
<el-descriptions-item label="生产厂家">{{ drugInfo.manufactory }}</el-descriptions-item>
|
|
|
|
|
<el-descriptions-item label="注册证号">{{ drugInfo.zczbhhzbapzbh }}</el-descriptions-item>
|
|
|
|
|
<el-descriptions-item label="包装材料">{{ drugInfo.packMatrial }}</el-descriptions-item>
|
|
|
|
|
<el-descriptions-item label="计量单位">{{ drugInfo.measname }}</el-descriptions-item>
|
|
|
|
|
</el-descriptions>
|
|
|
|
|
</el-card>
|
|
|
|
|
</transition>
|
|
|
|
|
|
|
|
|
|
<!-- 追溯记录 -->
|
|
|
|
|
<transition name="fade-transform" mode="out-in">
|
|
|
|
|
<div class="trace-container" v-if="orderRecords.length > 0" key="trace-container">
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="16">
|
|
|
|
|
<el-card class="box-card" :body-style="{padding: '0 0 15px 0'}">
|
|
|
|
|
<div slot="header" class="clearfix">
|
|
|
|
|
<span><i class="el-icon-document"></i> 追溯记录</span>
|
|
|
|
|
</div>
|
|
|
|
|
<el-table
|
|
|
|
|
v-loading="tableLoading"
|
|
|
|
|
:data="orderRecords"
|
|
|
|
|
border
|
|
|
|
|
stripe
|
|
|
|
|
highlight-current-row
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="billNo" label="单据号" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="billTypeName" label="单据类型" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="createTime" label="单据时间" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="fromCorpName" label="往来单位" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="deptName" label="部门" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="invName" label="库房" align="center"></el-table-column>
|
|
|
|
|
<el-table-column label="操作" width="120" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<el-button
|
|
|
|
|
type="text"
|
|
|
|
|
size="mini"
|
|
|
|
|
@click="viewOrderDetail(scope.row)"
|
|
|
|
|
class="detail-btn"
|
|
|
|
|
>
|
|
|
|
|
<i class="el-icon-view mr-5"></i>查看明细
|
|
|
|
|
</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
</el-card>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
<el-card class="box-card flow-card">
|
|
|
|
|
<div slot="header" class="clearfix">
|
|
|
|
|
<span><i class="el-icon-share"></i> 流通流程</span>
|
|
|
|
|
</div>
|
|
|
|
|
<el-steps :active="orderRecords.length" direction="vertical" finish-status="success" class="custom-steps">
|
|
|
|
|
<el-step
|
|
|
|
|
v-for="(item, index) in orderRecords"
|
|
|
|
|
:key="index"
|
|
|
|
|
:title="item.billTypeName"
|
|
|
|
|
:description="item.createTime + ' ' + item.billNo + ' ' + item.fromCorpName"
|
|
|
|
|
class="flow-step">
|
|
|
|
|
<i slot="icon" :class="getStepIcon(item.billTypeName)"></i>
|
|
|
|
|
</el-step>
|
|
|
|
|
</el-steps>
|
|
|
|
|
</el-card>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
</div>
|
|
|
|
|
</transition>
|
|
|
|
|
|
|
|
|
|
<!-- 明细记录 -->
|
|
|
|
|
<transition name="fade-transform" mode="out-in">
|
|
|
|
|
<el-card class="box-card detail-card" v-if="showOrderDetail" key="detail-card">
|
|
|
|
|
<div slot="header" class="clearfix">
|
|
|
|
|
<span><i class="el-icon-tickets"></i> 单据明细</span>
|
|
|
|
|
<el-button
|
|
|
|
|
style="float: right; padding: 3px 0"
|
|
|
|
|
type="text"
|
|
|
|
|
@click="showOrderDetail = false"
|
|
|
|
|
>
|
|
|
|
|
<i class="el-icon-close"></i>
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="detail-header" v-if="currentOrder">
|
|
|
|
|
<div class="detail-info">
|
|
|
|
|
<span class="detail-label">单据号:</span>
|
|
|
|
|
<span class="detail-value">{{ currentOrder.billNo }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="detail-info">
|
|
|
|
|
<span class="detail-label">单据类型:</span>
|
|
|
|
|
<span class="detail-value">{{ currentOrder.billTypeName }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="detail-info">
|
|
|
|
|
<span class="detail-label">单据时间:</span>
|
|
|
|
|
<span class="detail-value">{{ currentOrder.createTime }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<el-table
|
|
|
|
|
v-loading="detailLoading"
|
|
|
|
|
:data="orderDetails"
|
|
|
|
|
border
|
|
|
|
|
stripe
|
|
|
|
|
highlight-current-row
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="orderIdFk" label="单据号" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="nameCode" label="产品标识" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="coName" label="产品名称" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="spec" label="规格" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="batchNo" label="批号" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="productDate" label="生产日期" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="expireDate" label="有效期至" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="count" label="数量" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="measname" label="单位" align="center"></el-table-column>
|
|
|
|
|
<el-table-column prop="manufacturer" label="生产厂家" align="center"></el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
<div class="empty-data" v-if="orderDetails.length === 0 && !detailLoading">
|
|
|
|
|
<el-empty description="暂无明细数据"></el-empty>
|
|
|
|
|
</div>
|
|
|
|
|
</el-card>
|
|
|
|
|
</transition>
|
|
|
|
|
|
|
|
|
|
<!-- 无数据提示 -->
|
|
|
|
|
<transition name="fade-transform" mode="out-in">
|
|
|
|
|
<el-empty
|
|
|
|
|
v-if="!drugInfo.nameCode && !tableLoading && queryForm.traceCode"
|
|
|
|
|
description="未查询到相关追溯记录"
|
|
|
|
|
class="custom-empty"
|
|
|
|
|
key="empty-state"
|
|
|
|
|
>
|
|
|
|
|
<el-button type="primary" @click="resetForm">重新查询</el-button>
|
|
|
|
|
</el-empty>
|
|
|
|
|
</transition>
|
|
|
|
|
|
|
|
|
|
<!-- 页面底部 -->
|
|
|
|
|
<div class="page-footer">
|
|
|
|
|
<div class="footer-links">
|
|
|
|
|
<a href="#">关于我们</a>
|
|
|
|
|
<span>|</span>
|
|
|
|
|
<a href="#">使用帮助</a>
|
|
|
|
|
<span>|</span>
|
|
|
|
|
<a href="#">联系客服</a>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="footer-copyright">
|
|
|
|
|
© 2024 药品追溯系统 版权所有
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<script>
|
|
|
|
|
import {getOrderRecords, getOrderDetails, getDrugInfo} from '@/api/biz/traceQuery'
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
name: 'DrugTraceQuery',
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
// 折叠面板激活项
|
|
|
|
|
activeNames: ['1', '2', '3'],
|
|
|
|
|
// 查询表单
|
|
|
|
|
queryForm: {
|
|
|
|
|
traceCode: '',
|
|
|
|
|
page: 1,
|
|
|
|
|
limit: 50
|
|
|
|
|
},
|
|
|
|
|
// 表格加载状态
|
|
|
|
|
tableLoading: false,
|
|
|
|
|
detailLoading: false,
|
|
|
|
|
// 药品信息
|
|
|
|
|
drugInfo: {},
|
|
|
|
|
// 单据记录
|
|
|
|
|
orderRecords: [],
|
|
|
|
|
// 单据明细
|
|
|
|
|
orderDetails: [],
|
|
|
|
|
// 是否显示明细
|
|
|
|
|
showOrderDetail: false,
|
|
|
|
|
// 当前选中的单据
|
|
|
|
|
currentOrder: null
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
// 获取步骤图标
|
|
|
|
|
getStepIcon(billTypeName) {
|
|
|
|
|
// 根据单据类型返回不同的图标
|
|
|
|
|
const iconMap = {
|
|
|
|
|
'入库': 'el-icon-box',
|
|
|
|
|
'出库': 'el-icon-shopping-cart-full',
|
|
|
|
|
'采购': 'el-icon-shopping-bag-1',
|
|
|
|
|
'销售': 'el-icon-sell',
|
|
|
|
|
'调拨': 'el-icon-connection',
|
|
|
|
|
'盘点': 'el-icon-notebook-2',
|
|
|
|
|
'退货': 'el-icon-back'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 遍历图标映射,查找匹配的单据类型
|
|
|
|
|
for (const key in iconMap) {
|
|
|
|
|
if (billTypeName && billTypeName.includes(key)) {
|
|
|
|
|
return iconMap[key]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 默认图标
|
|
|
|
|
return 'el-icon-document'
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 搜索
|
|
|
|
|
handleSearch() {
|
|
|
|
|
if (!this.queryForm.traceCode) {
|
|
|
|
|
this.$message.warning('请输入药品追溯码')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
this.tableLoading = true
|
|
|
|
|
this.drugInfo = {}
|
|
|
|
|
this.orderRecords = []
|
|
|
|
|
this.orderDetails = []
|
|
|
|
|
this.showOrderDetail = false
|
|
|
|
|
|
|
|
|
|
// 查询药品信息
|
|
|
|
|
this.queryDrugInfo()
|
|
|
|
|
|
|
|
|
|
// 查询单据记录
|
|
|
|
|
this.queryOrderRecords()
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 查询药品信息
|
|
|
|
|
queryDrugInfo() {
|
|
|
|
|
getDrugInfo({
|
|
|
|
|
nameCode: this.queryForm.traceCode,
|
|
|
|
|
page: 1,
|
|
|
|
|
limit: 1
|
|
|
|
|
}).then(response => {
|
|
|
|
|
if (response.code === 20000 && response.data.list && response.data.list.length > 0) {
|
|
|
|
|
this.drugInfo = response.data.list[0]
|
|
|
|
|
} else {
|
|
|
|
|
this.drugInfo = {}
|
|
|
|
|
}
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
this.drugInfo = {}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 查询单据记录
|
|
|
|
|
queryOrderRecords() {
|
|
|
|
|
getOrderRecords({
|
|
|
|
|
traceCode: this.queryForm.traceCode,
|
|
|
|
|
page: this.queryForm.page,
|
|
|
|
|
limit: this.queryForm.limit
|
|
|
|
|
}).then(response => {
|
|
|
|
|
this.tableLoading = false
|
|
|
|
|
if (response.code === 20000) {
|
|
|
|
|
this.orderRecords = response.data.list || []
|
|
|
|
|
} else {
|
|
|
|
|
this.$message.error(response.message || '查询失败')
|
|
|
|
|
this.orderRecords = []
|
|
|
|
|
}
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
this.tableLoading = false
|
|
|
|
|
this.orderRecords = []
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 查看单据明细
|
|
|
|
|
viewOrderDetail(row) {
|
|
|
|
|
this.currentOrder = row
|
|
|
|
|
this.detailLoading = true
|
|
|
|
|
this.showOrderDetail = true
|
|
|
|
|
|
|
|
|
|
getOrderDetails({
|
|
|
|
|
orderIdFk: row.billNo,
|
|
|
|
|
page: 1,
|
|
|
|
|
limit: 100
|
|
|
|
|
}).then(response => {
|
|
|
|
|
this.detailLoading = false
|
|
|
|
|
if (response.code === 20000) {
|
|
|
|
|
this.orderDetails = response.data.list || []
|
|
|
|
|
if (this.orderDetails.length === 0) {
|
|
|
|
|
this.$message.info('该单据暂无明细记录')
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this.$message.error(response.message || '查询明细失败')
|
|
|
|
|
this.orderDetails = []
|
|
|
|
|
}
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
this.detailLoading = false
|
|
|
|
|
this.orderDetails = []
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 重置表单
|
|
|
|
|
resetForm() {
|
|
|
|
|
this.queryForm.traceCode = ''
|
|
|
|
|
this.drugInfo = {}
|
|
|
|
|
this.orderRecords = []
|
|
|
|
|
this.orderDetails = []
|
|
|
|
|
this.showOrderDetail = false
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 格式化日期
|
|
|
|
|
formatDate(dateStr) {
|
|
|
|
|
if (!dateStr) return ''
|
|
|
|
|
// 处理日期格式,例如将 220110 转换为 2022-01-10
|
|
|
|
|
if (dateStr.length === 6) {
|
|
|
|
|
const year = dateStr.substring(0, 2)
|
|
|
|
|
const month = dateStr.substring(2, 4)
|
|
|
|
|
const day = dateStr.substring(4, 6)
|
|
|
|
|
return `20${year}-${month}-${day}`
|
|
|
|
|
}
|
|
|
|
|
return dateStr
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
// 防止拖拽文件到页面
|
|
|
|
|
document.body.ondrop = function (event) {
|
|
|
|
|
event.preventDefault()
|
|
|
|
|
event.stopPropagation()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果URL中有追溯码参数,自动查询
|
|
|
|
|
const traceCode = this.$route.query.traceCode
|
|
|
|
|
if (traceCode) {
|
|
|
|
|
this.queryForm.traceCode = traceCode
|
|
|
|
|
this.handleSearch()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
/* 全局容器样式 */
|
|
|
|
|
.app-container {
|
|
|
|
|
padding: 25px;
|
|
|
|
|
background-color: #f0f2f5;
|
|
|
|
|
min-height: calc(100vh - 84px);
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 卡片通用样式 */
|
|
|
|
|
.box-card {
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
border: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.box-card:hover {
|
|
|
|
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
|
|
|
|
|
transform: translateY(-2px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 卡片头部样式 */
|
|
|
|
|
.box-card .el-card__header {
|
|
|
|
|
background: linear-gradient(135deg, #1976d2 0%, #42a5f5 100%);
|
|
|
|
|
padding: 16px 20px;
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.box-card .el-card__header span {
|
|
|
|
|
color: #fff;
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.box-card .el-card__header span i {
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 页面头部样式 */
|
|
|
|
|
.page-header {
|
|
|
|
|
background: linear-gradient(135deg, #1976d2 0%, #42a5f5 100%);
|
|
|
|
|
padding: 30px;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
color: #fff;
|
|
|
|
|
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15);
|
|
|
|
|
position: relative;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.page-header::before {
|
|
|
|
|
content: '';
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: -50%;
|
|
|
|
|
right: -50%;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 200%;
|
|
|
|
|
background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 70%);
|
|
|
|
|
transform: rotate(30deg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-title {
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-title i {
|
|
|
|
|
margin-right: 12px;
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-info {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
opacity: 0.9;
|
|
|
|
|
letter-spacing: 1px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 扫码区域样式 */
|
|
|
|
|
.scan-area {
|
|
|
|
|
text-align: center;
|
|
|
|
|
padding: 35px 25px;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.scan-title {
|
|
|
|
|
font-size: 22px;
|
|
|
|
|
color: #1976d2;
|
|
|
|
|
margin-bottom: 25px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.scan-title i {
|
|
|
|
|
margin-right: 12px;
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.query-form-item {
|
|
|
|
|
margin: 25px 10px;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.query-form-item .el-input {
|
|
|
|
|
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.query-form-item .el-input:focus-within {
|
|
|
|
|
box-shadow: 0 4px 12px rgba(25, 118, 210, 0.2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.query-form-item .el-input input {
|
|
|
|
|
height: 45px;
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 按钮样式 */
|
|
|
|
|
.el-button-group {
|
|
|
|
|
margin-left: 15px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-button-group .el-button {
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 12px 20px;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
height: 45px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-button-group .el-button:hover {
|
|
|
|
|
transform: translateY(-2px);
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-button-group .el-button.is-disabled:hover {
|
|
|
|
|
transform: none;
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 信息卡片样式 */
|
|
|
|
|
.info-card {
|
|
|
|
|
margin-top: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-descriptions {
|
|
|
|
|
margin: 20px 0;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-descriptions__label {
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #606266;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-descriptions__content {
|
|
|
|
|
color: #303133;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 表格样式 */
|
|
|
|
|
.el-table {
|
|
|
|
|
margin: 15px 0;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-table th {
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
color: #606266;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
padding: 12px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-table td {
|
|
|
|
|
padding: 12px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-table--striped .el-table__body tr.el-table__row--striped td {
|
|
|
|
|
background-color: #fafafa;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-table__body tr:hover > td {
|
|
|
|
|
background-color: #f0f7ff !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 步骤条样式 */
|
|
|
|
|
.trace-container {
|
|
|
|
|
margin-top: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.flow-card {
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-steps {
|
|
|
|
|
padding: 25px;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-step__title {
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-step__title.is-success {
|
|
|
|
|
color: #1976d2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-step__head.is-success {
|
|
|
|
|
color: #1976d2;
|
|
|
|
|
border-color: #1976d2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-step__description {
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
color: #909399;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-step__line {
|
|
|
|
|
background-color: #e8eaec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 空状态样式 */
|
|
|
|
|
.el-empty {
|
|
|
|
|
padding: 50px 0;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
margin: 24px 0;
|
|
|
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-empty__description {
|
|
|
|
|
margin-top: 15px;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #909399;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 页脚样式 */
|
|
|
|
|
.page-footer {
|
|
|
|
|
margin-top: 50px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
color: #606266;
|
|
|
|
|
padding: 25px 0;
|
|
|
|
|
border-top: 1px solid #ebeef5;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.footer-links {
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.footer-links a {
|
|
|
|
|
color: #606266;
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
margin: 0 15px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.footer-links span {
|
|
|
|
|
color: #dcdfe6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.footer-links a:hover {
|
|
|
|
|
color: #1976d2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.footer-copyright {
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
color: #909399;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 动画效果 */
|
|
|
|
|
.fade-transform-enter-active,
|
|
|
|
|
.fade-transform-leave-active {
|
|
|
|
|
transition: all 0.5s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.fade-transform-enter {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(20px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.fade-transform-leave-to {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(-20px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 脉冲效果 */
|
|
|
|
|
.pulse-icon {
|
|
|
|
|
animation: pulse 2s infinite;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes pulse {
|
|
|
|
|
0% {
|
|
|
|
|
transform: scale(1);
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
50% {
|
|
|
|
|
transform: scale(1.1);
|
|
|
|
|
opacity: 0.8;
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
transform: scale(1);
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 按钮悬停效果 */
|
|
|
|
|
.detail-btn:hover i {
|
|
|
|
|
transform: translateX(-2px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-btn {
|
|
|
|
|
background: linear-gradient(135deg, #1976d2 0%, #42a5f5 100%);
|
|
|
|
|
border: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-btn:hover {
|
|
|
|
|
background: linear-gradient(135deg, #1565c0 0%, #1976d2 100%);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 明细卡片样式 */
|
|
|
|
|
.detail-card {
|
|
|
|
|
margin-top: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.detail-header {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
padding: 15px 20px;
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.detail-info {
|
|
|
|
|
margin-right: 30px;
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.detail-label {
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #606266;
|
|
|
|
|
margin-right: 5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.detail-value {
|
|
|
|
|
color: #303133;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.empty-data {
|
|
|
|
|
padding: 30px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 自定义步骤条 */
|
|
|
|
|
.custom-steps {
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.flow-step {
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.flow-step .el-step__icon {
|
|
|
|
|
background-color: #e6f1fc;
|
|
|
|
|
border-color: #1976d2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.flow-step .el-step__icon.is-text {
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
border: 2px solid #1976d2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.flow-step .el-step__title {
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.mr-5 {
|
|
|
|
|
margin-right: 5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 自定义空状态 */
|
|
|
|
|
.custom-empty {
|
|
|
|
|
padding: 40px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 响应式调整 */
|
|
|
|
|
@media screen and (max-width: 768px) {
|
|
|
|
|
.app-container {
|
|
|
|
|
padding: 15px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.page-header {
|
|
|
|
|
padding: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-title {
|
|
|
|
|
font-size: 22px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.scan-area {
|
|
|
|
|
padding: 20px 15px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.query-form-item .el-input {
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
</script>
|