658 lines
20 KiB
Vue
658 lines
20 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="app-container">
|
|||
|
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
|||
|
|
<el-form-item label="证明书号" prop="certificateNo">
|
|||
|
|
<el-input
|
|||
|
|
v-model="queryParams.certificateNo"
|
|||
|
|
placeholder="请输入证明书号"
|
|||
|
|
clearable
|
|||
|
|
@keyup.enter.native="handleQuery"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="合同号" prop="contractNo">
|
|||
|
|
<el-input
|
|||
|
|
v-model="queryParams.contractNo"
|
|||
|
|
placeholder="请输入合同号"
|
|||
|
|
clearable
|
|||
|
|
@keyup.enter.native="handleQuery"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="产品名称" prop="productName">
|
|||
|
|
<el-input
|
|||
|
|
v-model="queryParams.productName"
|
|||
|
|
placeholder="请输入产品名称"
|
|||
|
|
clearable
|
|||
|
|
@keyup.enter.native="handleQuery"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="执行标准" prop="standard">
|
|||
|
|
<el-input
|
|||
|
|
v-model="queryParams.standard"
|
|||
|
|
placeholder="请输入执行标准"
|
|||
|
|
clearable
|
|||
|
|
@keyup.enter.native="handleQuery"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="收货单位" prop="consignee">
|
|||
|
|
<el-input
|
|||
|
|
v-model="queryParams.consignee"
|
|||
|
|
placeholder="请输入收货单位"
|
|||
|
|
clearable
|
|||
|
|
@keyup.enter.native="handleQuery"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="生产厂家" prop="manufacturer">
|
|||
|
|
<el-input
|
|||
|
|
v-model="queryParams.manufacturer"
|
|||
|
|
placeholder="请输入生产厂家"
|
|||
|
|
clearable
|
|||
|
|
@keyup.enter.native="handleQuery"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item>
|
|||
|
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|||
|
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-form>
|
|||
|
|
|
|||
|
|
<el-row :gutter="10" class="mb8">
|
|||
|
|
<el-col :span="1.5">
|
|||
|
|
<el-button
|
|||
|
|
type="primary"
|
|||
|
|
plain
|
|||
|
|
icon="el-icon-plus"
|
|||
|
|
size="mini"
|
|||
|
|
@click="handleAdd"
|
|||
|
|
>新增</el-button>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="1.5">
|
|||
|
|
<el-button
|
|||
|
|
type="success"
|
|||
|
|
plain
|
|||
|
|
icon="el-icon-edit"
|
|||
|
|
size="mini"
|
|||
|
|
:disabled="single"
|
|||
|
|
@click="handleUpdate"
|
|||
|
|
>修改</el-button>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="1.5">
|
|||
|
|
<el-button
|
|||
|
|
type="danger"
|
|||
|
|
plain
|
|||
|
|
icon="el-icon-delete"
|
|||
|
|
size="mini"
|
|||
|
|
:disabled="multiple"
|
|||
|
|
@click="handleDelete"
|
|||
|
|
>删除</el-button>
|
|||
|
|
</el-col>
|
|||
|
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|||
|
|
</el-row>
|
|||
|
|
|
|||
|
|
<div v-loading="loading" class="certificate-list">
|
|||
|
|
<div
|
|||
|
|
v-for="item in certificateList"
|
|||
|
|
:key="item.certificateId"
|
|||
|
|
class="certificate-card"
|
|||
|
|
:class="{ 'certificate-card-selected': selectedIds.includes(item.certificateId) }"
|
|||
|
|
@click="handleCardClick(item)"
|
|||
|
|
>
|
|||
|
|
<div class="card-top-bar"></div>
|
|||
|
|
|
|||
|
|
<div class="card-title-row">
|
|||
|
|
<span class="card-doc-type">质量保证书</span>
|
|||
|
|
<span class="card-sep">|</span>
|
|||
|
|
<span class="card-env">MES-QC-{{ item.certificateNo || '' }}</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="card-cert-no">
|
|||
|
|
<span class="card-cert-no-label">No.</span>
|
|||
|
|
<span class="card-cert-no-value">{{ item.certificateNo }}</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="card-info-grid">
|
|||
|
|
<div class="card-info-item">
|
|||
|
|
<span class="card-info-label">合同号</span>
|
|||
|
|
<span class="card-info-value">{{ item.contractNo || '-' }}</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="card-info-item">
|
|||
|
|
<span class="card-info-label">产品名称</span>
|
|||
|
|
<span class="card-info-value">{{ item.productName || '-' }}</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="card-info-item">
|
|||
|
|
<span class="card-info-label">执行标准</span>
|
|||
|
|
<span class="card-info-value">{{ item.standard || '-' }}</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="card-info-item">
|
|||
|
|
<span class="card-info-label">收货单位</span>
|
|||
|
|
<span class="card-info-value">{{ item.consignee || '-' }}</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="card-info-item">
|
|||
|
|
<span class="card-info-label">生产厂家</span>
|
|||
|
|
<span class="card-info-value">{{ item.manufacturer || '-' }}</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="card-info-item">
|
|||
|
|
<span class="card-info-label">签发日期</span>
|
|||
|
|
<span class="card-info-value">{{ parseTime(item.issueDate, '{y}-{m}-{d}') }}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="card-footer">
|
|||
|
|
<div class="card-stamp-placeholder">质检专用</div>
|
|||
|
|
<div class="card-actions">
|
|||
|
|
<el-button size="mini" type="text" icon="el-icon-edit" @click.stop="handleUpdate(item)">修改</el-button>
|
|||
|
|
<el-button size="mini" type="text" icon="el-icon-delete" @click.stop="handleDelete(item)">删除</el-button>
|
|||
|
|
<el-button size="mini" type="text" icon="el-icon-view" @click.stop="handlePreview(item)">预览</el-button>
|
|||
|
|
<el-button size="mini" type="text" icon="el-icon-printer" @click.stop="handlePrint(item)">打印</el-button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<pagination
|
|||
|
|
v-show="total>0"
|
|||
|
|
:total="total"
|
|||
|
|
:page.sync="queryParams.pageNum"
|
|||
|
|
:limit.sync="queryParams.pageSize"
|
|||
|
|
@pagination="getList"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<!-- 添加或修改质量证明书主对话框 -->
|
|||
|
|
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
|
|||
|
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
|||
|
|
<el-form-item label="证明书号" prop="certificateNo">
|
|||
|
|
<el-input v-model="form.certificateNo" placeholder="请输入证明书号" />
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="合同号" prop="contractNo">
|
|||
|
|
<el-input v-model="form.contractNo" placeholder="请输入合同号" />
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="产品名称" prop="productName">
|
|||
|
|
<el-input v-model="form.productName" placeholder="请输入产品名称" />
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="执行标准" prop="standard">
|
|||
|
|
<el-input v-model="form.standard" placeholder="请输入执行标准" />
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="收货单位" prop="consignee">
|
|||
|
|
<el-input v-model="form.consignee" placeholder="请输入收货单位" />
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="生产厂家" prop="manufacturer">
|
|||
|
|
<el-input v-model="form.manufacturer" placeholder="请输入生产厂家" />
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="签发日期" prop="issueDate">
|
|||
|
|
<el-date-picker clearable
|
|||
|
|
v-model="form.issueDate"
|
|||
|
|
type="datetime"
|
|||
|
|
value-format="yyyy-MM-dd HH:mm:ss"
|
|||
|
|
placeholder="请选择签发日期">
|
|||
|
|
</el-date-picker>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="质保证明说明" prop="note">
|
|||
|
|
<el-input v-model="form.note" type="textarea" placeholder="请输入内容" auto-height />
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="备注" prop="remark">
|
|||
|
|
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" auto-height />
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-form>
|
|||
|
|
<div slot="footer" class="dialog-footer">
|
|||
|
|
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
|||
|
|
<el-button @click="cancel">取 消</el-button>
|
|||
|
|
</div>
|
|||
|
|
</el-dialog>
|
|||
|
|
|
|||
|
|
<!-- 预览对话框 -->
|
|||
|
|
<el-dialog :title="previewTitle" :visible.sync="previewVisible" width="1200px" append-to-body fullscreen>
|
|||
|
|
<div class="preview-content-wrapper">
|
|||
|
|
<CertificatePrintPreview
|
|||
|
|
ref="printComponent"
|
|||
|
|
:visible="true"
|
|||
|
|
:preview="true"
|
|||
|
|
:certificate="previewData"
|
|||
|
|
:items="previewItems"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
<div slot="footer" class="dialog-footer">
|
|||
|
|
<el-button type="primary" @click="handleExportPdfFromPreview">导出PDF</el-button>
|
|||
|
|
<el-button type="success" @click="handlePrintFromPreview">打印</el-button>
|
|||
|
|
<el-button @click="previewVisible = false">关闭</el-button>
|
|||
|
|
</div>
|
|||
|
|
</el-dialog>
|
|||
|
|
|
|||
|
|
<!-- 隐藏的打印组件 -->
|
|||
|
|
<CertificatePrintPreview
|
|||
|
|
v-show="false"
|
|||
|
|
ref="hiddenPrintComponent"
|
|||
|
|
:certificate="printCertificateData"
|
|||
|
|
:items="printItemsData"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import { listCertificate, getCertificate, delCertificate, addCertificate, updateCertificate } from "@/api/mes/qc/certificate";
|
|||
|
|
import { listCertificateItem } from "@/api/mes/qc/certificateItem";
|
|||
|
|
import CertificatePrintPreview from "./components/CertificatePrintPreview.vue";
|
|||
|
|
import { print as printPdf, downloadPdf } from "./lib/printUtils";
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
name: "Certificate",
|
|||
|
|
components: {
|
|||
|
|
CertificatePrintPreview
|
|||
|
|
},
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
buttonLoading: false,
|
|||
|
|
loading: true,
|
|||
|
|
ids: [],
|
|||
|
|
selectedIds: [],
|
|||
|
|
single: true,
|
|||
|
|
multiple: true,
|
|||
|
|
showSearch: true,
|
|||
|
|
total: 0,
|
|||
|
|
certificateList: [],
|
|||
|
|
title: "",
|
|||
|
|
open: false,
|
|||
|
|
previewVisible: false,
|
|||
|
|
previewTitle: "",
|
|||
|
|
previewData: {},
|
|||
|
|
previewItems: [],
|
|||
|
|
printComponentVisible: false,
|
|||
|
|
printCertificateData: {},
|
|||
|
|
printItemsData: [],
|
|||
|
|
queryParams: {
|
|||
|
|
pageNum: 1,
|
|||
|
|
pageSize: 10,
|
|||
|
|
certificateNo: undefined,
|
|||
|
|
contractNo: undefined,
|
|||
|
|
productName: undefined,
|
|||
|
|
standard: undefined,
|
|||
|
|
consignee: undefined,
|
|||
|
|
manufacturer: undefined,
|
|||
|
|
},
|
|||
|
|
form: {},
|
|||
|
|
rules: {
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
created() {
|
|||
|
|
this.getList();
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
/** 查询质量证明书主列表 */
|
|||
|
|
getList() {
|
|||
|
|
this.loading = true;
|
|||
|
|
listCertificate(this.queryParams).then(response => {
|
|||
|
|
this.certificateList = response.rows;
|
|||
|
|
this.total = response.total;
|
|||
|
|
this.loading = false;
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
// 取消按钮
|
|||
|
|
cancel() {
|
|||
|
|
this.open = false;
|
|||
|
|
this.reset();
|
|||
|
|
},
|
|||
|
|
// 表单重置
|
|||
|
|
reset() {
|
|||
|
|
this.form = {
|
|||
|
|
certificateId: undefined,
|
|||
|
|
certificateNo: undefined,
|
|||
|
|
contractNo: undefined,
|
|||
|
|
productName: undefined,
|
|||
|
|
standard: undefined,
|
|||
|
|
consignee: undefined,
|
|||
|
|
manufacturer: undefined,
|
|||
|
|
issueDate: undefined,
|
|||
|
|
note: 'D.T=Denu_Test \t T.S=Tensile Strength \t D=弯心直径MandrelDiameter \n Strength \t G.L=拉伸标距GaugeLength \t EL=Percentage Elongation After Fracture',
|
|||
|
|
remark: '1.本产品经检验满足订货标准要求。The material has been tested with satisfactory resultsin accordance with the speciicatication \n 2.本质量证明书中空白项目均不作为交货条件。The blank items shouldn’tbe regarded as delivery conditions. \n 3.盖章后生效。The quality certificate willcome into force with a valid stamp.',
|
|||
|
|
delFlag: undefined,
|
|||
|
|
createTime: undefined,
|
|||
|
|
createBy: undefined,
|
|||
|
|
updateTime: undefined,
|
|||
|
|
updateBy: undefined
|
|||
|
|
};
|
|||
|
|
this.resetForm("form");
|
|||
|
|
},
|
|||
|
|
/** 搜索按钮操作 */
|
|||
|
|
handleQuery() {
|
|||
|
|
this.queryParams.pageNum = 1;
|
|||
|
|
this.getList();
|
|||
|
|
},
|
|||
|
|
/** 重置按钮操作 */
|
|||
|
|
resetQuery() {
|
|||
|
|
this.resetForm("queryForm");
|
|||
|
|
this.handleQuery();
|
|||
|
|
},
|
|||
|
|
handleCardClick(item) {
|
|||
|
|
const index = this.selectedIds.indexOf(item.certificateId);
|
|||
|
|
if (index > -1) {
|
|||
|
|
this.selectedIds.splice(index, 1);
|
|||
|
|
} else {
|
|||
|
|
this.selectedIds.push(item.certificateId);
|
|||
|
|
}
|
|||
|
|
this.updateSelectionStatus();
|
|||
|
|
},
|
|||
|
|
handleCheckboxChange(certificateId, event) {
|
|||
|
|
if (event.target.checked) {
|
|||
|
|
if (!this.selectedIds.includes(certificateId)) {
|
|||
|
|
this.selectedIds.push(certificateId);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
const index = this.selectedIds.indexOf(certificateId);
|
|||
|
|
if (index > -1) {
|
|||
|
|
this.selectedIds.splice(index, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
this.updateSelectionStatus();
|
|||
|
|
},
|
|||
|
|
updateSelectionStatus() {
|
|||
|
|
this.ids = [...this.selectedIds];
|
|||
|
|
this.single = this.selectedIds.length !== 1;
|
|||
|
|
this.multiple = this.selectedIds.length === 0;
|
|||
|
|
},
|
|||
|
|
/** 新增按钮操作 */
|
|||
|
|
handleAdd() {
|
|||
|
|
this.reset();
|
|||
|
|
this.open = true;
|
|||
|
|
this.title = "添加质量证明书主";
|
|||
|
|
},
|
|||
|
|
/** 修改按钮操作 */
|
|||
|
|
handleUpdate(row) {
|
|||
|
|
this.loading = true;
|
|||
|
|
this.reset();
|
|||
|
|
const certificateId = row.certificateId || this.ids
|
|||
|
|
getCertificate(certificateId).then(response => {
|
|||
|
|
this.loading = false;
|
|||
|
|
this.form = response.data;
|
|||
|
|
this.open = true;
|
|||
|
|
this.title = "修改质量证明书主";
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
/** 提交按钮 */
|
|||
|
|
submitForm() {
|
|||
|
|
this.$refs["form"].validate(valid => {
|
|||
|
|
if (valid) {
|
|||
|
|
this.buttonLoading = true;
|
|||
|
|
if (this.form.certificateId != null) {
|
|||
|
|
updateCertificate(this.form).then(response => {
|
|||
|
|
this.$modal.msgSuccess("修改成功");
|
|||
|
|
this.open = false;
|
|||
|
|
this.getList();
|
|||
|
|
}).finally(() => {
|
|||
|
|
this.buttonLoading = false;
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
addCertificate(this.form).then(response => {
|
|||
|
|
this.$modal.msgSuccess("新增成功");
|
|||
|
|
this.open = false;
|
|||
|
|
this.getList();
|
|||
|
|
}).finally(() => {
|
|||
|
|
this.buttonLoading = false;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
/** 删除按钮操作 */
|
|||
|
|
handleDelete(row) {
|
|||
|
|
const certificateIds = row.certificateId || this.ids;
|
|||
|
|
this.$modal.confirm('是否确认删除质量证明书主编号为"' + certificateIds + '"的数据项?').then(() => {
|
|||
|
|
this.loading = true;
|
|||
|
|
return delCertificate(certificateIds);
|
|||
|
|
}).then(() => {
|
|||
|
|
this.loading = false;
|
|||
|
|
this.getList();
|
|||
|
|
this.$modal.msgSuccess("删除成功");
|
|||
|
|
}).catch(() => {
|
|||
|
|
}).finally(() => {
|
|||
|
|
this.loading = false;
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
/** 预览按钮操作 */
|
|||
|
|
async handlePreview(row) {
|
|||
|
|
const certificateId = row.certificateId;
|
|||
|
|
this.loading = true;
|
|||
|
|
try {
|
|||
|
|
const [certRes, itemsRes] = await Promise.all([
|
|||
|
|
getCertificate(certificateId),
|
|||
|
|
listCertificateItem({ certificateId, pageSize: 100 })
|
|||
|
|
]);
|
|||
|
|
this.previewData = certRes.data;
|
|||
|
|
this.previewItems = itemsRes.rows || [];
|
|||
|
|
this.previewTitle = `预览 - ${certRes.data.certificateNo}`;
|
|||
|
|
this.previewVisible = true;
|
|||
|
|
} catch (error) {
|
|||
|
|
this.$message.error('获取数据失败');
|
|||
|
|
} finally {
|
|||
|
|
this.loading = false;
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
/** 打印按钮操作 */
|
|||
|
|
async handlePrint(row) {
|
|||
|
|
const certificateId = row.certificateId;
|
|||
|
|
await this.preparePrintComponent(certificateId);
|
|||
|
|
await this.$nextTick();
|
|||
|
|
const el = this.$refs.hiddenPrintComponent.$refs.certificateContent;
|
|||
|
|
await printPdf(el);
|
|||
|
|
},
|
|||
|
|
/** 从预览打印 */
|
|||
|
|
async handlePrintFromPreview() {
|
|||
|
|
await this.$nextTick();
|
|||
|
|
const el = this.$refs.printComponent.$refs.certificateContent;
|
|||
|
|
await printPdf(el);
|
|||
|
|
},
|
|||
|
|
/** 导出PDF按钮操作 */
|
|||
|
|
async handleExportPdf() {
|
|||
|
|
if (this.ids.length !== 1) {
|
|||
|
|
this.$message.warning('请选择一条质保书进行导出');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
await this.preparePrintComponent(this.ids[0]);
|
|||
|
|
await this.$nextTick();
|
|||
|
|
const fileName = `${this.printCertificateData.certificateNo || '质量证明书'}_${new Date().getTime()}.pdf`;
|
|||
|
|
const el = this.$refs.hiddenPrintComponent.$refs.certificateContent;
|
|||
|
|
await downloadPdf(el, fileName);
|
|||
|
|
this.$message.success('导出成功');
|
|||
|
|
},
|
|||
|
|
/** 从预览导出PDF */
|
|||
|
|
async handleExportPdfFromPreview() {
|
|||
|
|
await this.$nextTick();
|
|||
|
|
const fileName = `${this.previewData.certificateNo || '质量证明书'}_${new Date().getTime()}.pdf`;
|
|||
|
|
const el = this.$refs.printComponent.$refs.certificateContent;
|
|||
|
|
await downloadPdf(el, fileName);
|
|||
|
|
this.$message.success('导出成功');
|
|||
|
|
},
|
|||
|
|
async preparePrintComponent(certificateId) {
|
|||
|
|
this.loading = true;
|
|||
|
|
try {
|
|||
|
|
const [certRes, itemsRes] = await Promise.all([
|
|||
|
|
getCertificate(certificateId),
|
|||
|
|
listCertificateItem({ certificateId, pageSize: 100 })
|
|||
|
|
]);
|
|||
|
|
this.printCertificateData = certRes.data;
|
|||
|
|
this.printItemsData = itemsRes.rows || [];
|
|||
|
|
this.printComponentVisible = true;
|
|||
|
|
await this.$nextTick();
|
|||
|
|
} catch (error) {
|
|||
|
|
this.$message.error('获取数据失败');
|
|||
|
|
} finally {
|
|||
|
|
this.loading = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.certificate-list {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
|
|||
|
|
gap: 18px;
|
|||
|
|
padding: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.preview-content-wrapper {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.certificate-card {
|
|||
|
|
background: #fcf9f2;
|
|||
|
|
border: 1px solid #d6cfc0;
|
|||
|
|
border-radius: 2px;
|
|||
|
|
padding: 18px 20px 14px;
|
|||
|
|
cursor: pointer;
|
|||
|
|
transition: all 0.2s ease;
|
|||
|
|
position: relative;
|
|||
|
|
box-shadow:
|
|||
|
|
0 1px 3px rgba(0, 0, 0, 0.06),
|
|||
|
|
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-top-bar {
|
|||
|
|
position: absolute;
|
|||
|
|
top: 0;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
height: 3px;
|
|||
|
|
background: linear-gradient(90deg, #3a3a3a 0%, #7a7a7a 50%, #3a3a3a 100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.certificate-card:hover {
|
|||
|
|
border-color: #b8ad98;
|
|||
|
|
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.certificate-card-selected {
|
|||
|
|
border-color: #7a6f5e;
|
|||
|
|
border-width: 2px;
|
|||
|
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(0, 0, 0, 0.08);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-checkbox {
|
|||
|
|
position: absolute;
|
|||
|
|
top: 14px;
|
|||
|
|
right: 14px;
|
|||
|
|
z-index: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-title-row {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 8px;
|
|||
|
|
margin-bottom: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-doc-type {
|
|||
|
|
font-size: 15px;
|
|||
|
|
font-weight: 700;
|
|||
|
|
color: #2a2a2a;
|
|||
|
|
letter-spacing: 2px;
|
|||
|
|
font-family: "SimSun", "Songti SC", "Noto Serif SC", serif;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-sep {
|
|||
|
|
color: #c0b8a8;
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 200;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-env {
|
|||
|
|
font-size: 10px;
|
|||
|
|
color: #9a9080;
|
|||
|
|
letter-spacing: 0.5px;
|
|||
|
|
font-family: "Courier New", monospace;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-cert-no {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: baseline;
|
|||
|
|
gap: 4px;
|
|||
|
|
margin-bottom: 14px;
|
|||
|
|
padding-bottom: 12px;
|
|||
|
|
border-bottom: 1px solid #ddd6c8;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-cert-no-label {
|
|||
|
|
font-size: 11px;
|
|||
|
|
color: #8a8070;
|
|||
|
|
font-style: italic;
|
|||
|
|
font-family: "Times New Roman", serif;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-cert-no-value {
|
|||
|
|
font-size: 20px;
|
|||
|
|
font-weight: 700;
|
|||
|
|
color: #1a1a1a;
|
|||
|
|
letter-spacing: 1px;
|
|||
|
|
font-family: "Courier New", "Times New Roman", monospace;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-info-grid {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: 1fr 1fr;
|
|||
|
|
gap: 2px 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-info-item {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: baseline;
|
|||
|
|
padding: 5px 0;
|
|||
|
|
border-bottom: 1px dotted #e6dfd0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-info-item:nth-last-child(-n+2) {
|
|||
|
|
border-bottom: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-info-label {
|
|||
|
|
font-size: 11px;
|
|||
|
|
color: #8a8270;
|
|||
|
|
min-width: 58px;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-info-value {
|
|||
|
|
font-size: 13px;
|
|||
|
|
color: #222;
|
|||
|
|
font-weight: 500;
|
|||
|
|
overflow: hidden;
|
|||
|
|
text-overflow: ellipsis;
|
|||
|
|
white-space: nowrap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-footer {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-top: 12px;
|
|||
|
|
padding-top: 10px;
|
|||
|
|
border-top: 1px solid #ddd6c8;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-stamp-placeholder {
|
|||
|
|
width: 44px;
|
|||
|
|
height: 44px;
|
|||
|
|
border: 1.5px solid #9a8a7a;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
color: #9a8a7a;
|
|||
|
|
font-size: 9px;
|
|||
|
|
font-weight: bold;
|
|||
|
|
text-align: center;
|
|||
|
|
line-height: 1.2;
|
|||
|
|
font-family: "SimSun", serif;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-actions {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 6px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-actions .el-button {
|
|||
|
|
padding: 3px 6px;
|
|||
|
|
font-size: 12px;
|
|||
|
|
}
|
|||
|
|
</style>
|