<template>
|
<div class="app-container">
|
<el-card class="box-card">
|
<!-- 搜索区域 -->
|
<el-row :gutter="20"
|
class="search-row">
|
<el-col :span="6">
|
<el-input v-model="searchForm.productName"
|
placeholder="请输入产品名称"
|
clearable
|
@keyup.enter="handleSearch">
|
<template #prefix>
|
<el-icon>
|
<Search />
|
</el-icon>
|
</template>
|
</el-input>
|
</el-col>
|
<el-col :span="6">
|
<el-select v-model="searchForm.identifierType"
|
placeholder="请选择标识类型"
|
clearable>
|
<el-option label="二维码"
|
value="二维码"></el-option>
|
<el-option label="防伪码"
|
value="防伪码"></el-option>
|
</el-select>
|
</el-col>
|
<el-col :span="6">
|
<el-select v-model="searchForm.status"
|
placeholder="请选择状态"
|
clearable>
|
<el-option label="已生成"
|
value="已生成"></el-option>
|
<el-option label="已分配"
|
value="已分配"></el-option>
|
<el-option label="已使用"
|
value="已使用"></el-option>
|
<el-option label="已作废"
|
value="已作废"></el-option>
|
</el-select>
|
</el-col>
|
<el-col :span="6">
|
<el-button type="primary"
|
@click="handleSearch">搜索</el-button>
|
<el-button @click="resetSearch">重置</el-button>
|
<el-button style="float: right;"
|
type="primary"
|
@click="handleAdd">
|
新增标识
|
</el-button>
|
</el-col>
|
</el-row>
|
<!-- 产品标识列表 -->
|
<el-table :data="filteredList"
|
style="width: 100%"
|
v-loading="loading"
|
border
|
stripe
|
height="calc(100vh - 22em)">
|
<el-table-column prop="id"
|
label="ID"
|
width="80"
|
align="center" />
|
<el-table-column prop="productName"
|
label="产品名称"
|
width="150" />
|
<el-table-column prop="productCode"
|
label="产品编码"
|
width="120" />
|
<el-table-column prop="batchNo"
|
label="批次号"
|
width="120" />
|
<el-table-column prop="identifierType"
|
label="标识类型"
|
width="100">
|
<template #default="scope">
|
<el-tag :type="getIdentifierTypeType(scope.row.identifierType)">
|
{{ scope.row.identifierType }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="identifierCode"
|
label="标识码" />
|
<el-table-column prop="status"
|
label="状态"
|
width="100">
|
<template #default="scope">
|
<el-tag :type="getStatusType(scope.row.status)">
|
{{ scope.row.status }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="generateTime"
|
label="生成时间"
|
width="160" />
|
<el-table-column label="操作"
|
fixed="right"
|
align="center"
|
width="280">
|
<template #default="scope">
|
<el-button link
|
type="primary"
|
@click="handleView(scope.row)">查看</el-button>
|
<el-button link
|
type="primary"
|
@click="handleEdit(scope.row)">编辑</el-button>
|
<el-button link
|
type="success"
|
@click="generateQRCode(scope.row)">生成二维码</el-button>
|
<el-button link
|
type="primary"
|
@click="handleExport(scope.row)">导出</el-button>
|
<el-button link
|
type="primary"
|
@click="handleReassign(scope.row)"
|
v-if="scope.row.status === '已分配'">重新分配</el-button>
|
<el-button link
|
type="danger"
|
@click="handleDelete(scope.row)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<!-- 分页 -->
|
<pagination :total="pagination.total"
|
layout="total, sizes, prev, pager, next, jumper"
|
:page="pagination.currentPage"
|
:limit="pagination.pageSize"
|
@pagination="handleCurrentChange" />
|
</el-card>
|
<!-- 新增/编辑对话框 -->
|
<el-dialog v-model="dialogVisible"
|
:title="dialogTitle"
|
width="700px">
|
<el-form :model="form"
|
:rules="rules"
|
ref="formRef"
|
label-width="100px">
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="产品名称"
|
prop="productName">
|
<el-input v-model="form.productName"
|
placeholder="请输入产品名称"></el-input>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="产品编码"
|
prop="productCode">
|
<el-input v-model="form.productCode"
|
placeholder="请输入产品编码"></el-input>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="批次号"
|
prop="batchNo">
|
<el-input v-model="form.batchNo"
|
placeholder="请输入批次号"></el-input>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="标识类型"
|
prop="identifierType">
|
<el-select v-model="form.identifierType"
|
placeholder="请选择标识类型"
|
style="width: 100%">
|
<el-option label="二维码"
|
value="二维码"></el-option>
|
<el-option label="防伪码"
|
value="防伪码"></el-option>
|
</el-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="生成数量"
|
prop="quantity">
|
<el-input-number v-model="form.quantity"
|
:min="1"
|
:max="10000"
|
style="width: 100%"></el-input-number>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="状态"
|
prop="status">
|
<el-select v-model="form.status"
|
placeholder="请选择状态"
|
style="width: 100%">
|
<el-option label="已生成"
|
value="已生成"></el-option>
|
<el-option label="已分配"
|
value="已分配"></el-option>
|
<el-option label="已使用"
|
value="已使用"></el-option>
|
<el-option label="已作废"
|
value="已作废"></el-option>
|
</el-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="24">
|
<el-form-item label="备注"
|
prop="remark">
|
<el-input type="textarea"
|
v-model="form.remark"
|
placeholder="请输入备注信息"
|
rows="3"></el-input>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary"
|
@click="handleSubmit">确 定</el-button>
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
<!-- 标识生成对话框 -->
|
<el-dialog v-model="generateDialogVisible"
|
title="标识生成"
|
width="500px">
|
<el-form label-width="100px">
|
<el-form-item label="产品名称">
|
<span>{{ currentProduct.productName }}</span>
|
</el-form-item>
|
<el-form-item label="产品编码">
|
<span>{{ currentProduct.productCode }}</span>
|
</el-form-item>
|
<el-form-item label="批次号">
|
<span>{{ currentProduct.batchNo }}</span>
|
</el-form-item>
|
<el-form-item label="标识类型">
|
<span>{{ currentProduct.identifierType }}</span>
|
</el-form-item>
|
<el-form-item label="生成数量"
|
prop="generateQuantity">
|
<el-input-number v-model="generateQuantity"
|
:min="1"
|
:max="10000"
|
style="width: 100%"></el-input-number>
|
</el-form-item>
|
<el-form-item label="编码规则"
|
prop="codeRule">
|
<el-select v-model="codeRule"
|
placeholder="请选择编码规则"
|
style="width: 100%">
|
<el-option label="产品编码+批次号+序号"
|
value="产品编码+批次号+序号"></el-option>
|
<el-option label="时间戳+随机数"
|
value="时间戳+随机数"></el-option>
|
<el-option label="自定义规则"
|
value="自定义规则"></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="自定义前缀"
|
prop="customPrefix"
|
v-if="codeRule === '自定义规则'">
|
<el-input v-model="customPrefix"
|
placeholder="请输入自定义前缀"></el-input>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary"
|
@click="generateIdentifiers">生 成</el-button>
|
<el-button @click="generateDialogVisible = false">取 消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
<!-- 重新分配对话框 -->
|
<el-dialog v-model="reassignDialogVisible"
|
title="重新分配标识"
|
width="500px">
|
<el-form label-width="100px">
|
<el-form-item label="产品名称">
|
<span>{{ currentProduct.productName }}</span>
|
</el-form-item>
|
<el-form-item label="标识码">
|
<span>{{ currentProduct.identifierCode }}</span>
|
</el-form-item>
|
<el-form-item label="新批次号"
|
prop="newBatchNo">
|
<el-input v-model="newBatchNo"
|
placeholder="请输入新批次号"></el-input>
|
</el-form-item>
|
<el-form-item label="分配原因"
|
prop="reassignReason">
|
<el-input type="textarea"
|
v-model="reassignReason"
|
rows="3"
|
placeholder="请输入重新分配原因"></el-input>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary"
|
@click="saveReassign">确 定</el-button>
|
<el-button @click="reassignDialogVisible = false">取 消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
<!-- 二维码预览对话框 -->
|
<el-dialog v-model="qrCodeDialogVisible"
|
title="二维码预览"
|
width="500px"
|
center>
|
<div class="qr-preview-container">
|
<div v-if="qrCodeUrl"
|
class="qr-image-container">
|
<img :src="qrCodeUrl"
|
alt="二维码"
|
class="qr-image" />
|
<div class="qr-info">
|
<p><strong>产品名称:</strong>{{ currentQRProduct.productName }}</p>
|
<p><strong>产品编码:</strong>{{ currentQRProduct.productCode }}</p>
|
<p><strong>批次号:</strong>{{ currentQRProduct.batchNo }}</p>
|
<p><strong>标识码:</strong>{{ currentQRProduct.identifierCode }}</p>
|
<p><strong>标识类型:</strong>{{ currentQRProduct.identifierType }}</p>
|
</div>
|
</div>
|
<div v-else
|
class="qr-loading">
|
<el-icon class="is-loading">
|
<Loading />
|
</el-icon>
|
<p>正在生成二维码...</p>
|
</div>
|
</div>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button @click="qrCodeDialogVisible = false">关闭</el-button>
|
<el-button v-if="qrCodeUrl"
|
type="primary"
|
@click="copyQRContent"
|
icon="CopyDocument">
|
复制内容
|
</el-button>
|
<el-button v-if="qrCodeUrl"
|
type="success"
|
@click="downloadQRCode"
|
icon="Download">
|
下载二维码
|
</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, computed } from "vue";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
import { Plus, Search, Loading, Download } from "@element-plus/icons-vue";
|
import Pagination from "@/components/PIMTable/Pagination.vue";
|
import QRCode from "qrcode";
|
|
// 响应式数据
|
const loading = ref(false);
|
const searchForm = reactive({
|
productName: "",
|
identifierType: "",
|
status: "",
|
});
|
|
const identifierList = ref([
|
{
|
id: 1,
|
productName: "工业传感器A型",
|
productCode: "SENSOR001",
|
batchNo: "B202312001",
|
identifierType: "二维码",
|
identifierCode: "QR_SENSOR001_B202312001_001",
|
status: "已分配",
|
generateTime: "2023-12-01 10:00:00",
|
remark: "重要产品标识",
|
},
|
{
|
id: 2,
|
productName: "控制面板B型",
|
productCode: "PANEL002",
|
batchNo: "B202312002",
|
identifierType: "防伪码",
|
identifierCode: "SEC_PANEL002_B202312002_001",
|
status: "已生成",
|
generateTime: "2023-12-02 14:30:00",
|
remark: "常规产品标识",
|
},
|
{
|
id: 3,
|
productName: "数据采集器C型",
|
productCode: "COLLECTOR003",
|
batchNo: "B202312003",
|
identifierType: "防伪码",
|
identifierCode: "SEC_COLLECTOR003_B202312003_001",
|
status: "已使用",
|
generateTime: "2023-12-03 09:15:00",
|
remark: "测试产品标识",
|
},
|
]);
|
|
const pagination = reactive({
|
total: 3,
|
currentPage: 1,
|
pageSize: 10,
|
});
|
|
const dialogVisible = ref(false);
|
const dialogTitle = ref("新增标识");
|
const form = reactive({
|
productName: "",
|
productCode: "",
|
batchNo: "",
|
identifierType: "",
|
quantity: 1,
|
status: "已生成",
|
remark: "",
|
});
|
|
const rules = {
|
productName: [{ required: true, message: "请输入产品名称", trigger: "blur" }],
|
productCode: [{ required: true, message: "请输入产品编码", trigger: "blur" }],
|
batchNo: [{ required: true, message: "请输入批次号", trigger: "blur" }],
|
identifierType: [
|
{ required: true, message: "请选择标识类型", trigger: "change" },
|
],
|
quantity: [{ required: true, message: "请输入生成数量", trigger: "blur" }],
|
status: [{ required: true, message: "请选择状态", trigger: "change" }],
|
};
|
|
const isEdit = ref(false);
|
const editId = ref(null);
|
const generateDialogVisible = ref(false);
|
const reassignDialogVisible = ref(false);
|
const currentProduct = ref({});
|
const generateQuantity = ref(1);
|
const codeRule = ref("");
|
const customPrefix = ref("");
|
const newBatchNo = ref("");
|
const reassignReason = ref("");
|
const formRef = ref();
|
|
// 二维码相关变量
|
const qrCodeDialogVisible = ref(false);
|
const qrCodeUrl = ref("");
|
const currentQRProduct = ref({});
|
|
// 计算属性
|
const filteredList = computed(() => {
|
let list = identifierList.value;
|
if (searchForm.productName) {
|
list = list.filter(item =>
|
item.productName.includes(searchForm.productName)
|
);
|
}
|
if (searchForm.identifierType) {
|
list = list.filter(
|
item => item.identifierType === searchForm.identifierType
|
);
|
}
|
if (searchForm.status) {
|
list = list.filter(item => item.status === searchForm.status);
|
}
|
return list;
|
});
|
|
// 方法
|
const getIdentifierTypeType = type => {
|
const typeMap = {
|
二维码: "success",
|
防伪码: "warning",
|
};
|
return typeMap[type] || "info";
|
};
|
|
const getStatusType = status => {
|
const statusMap = {
|
已生成: "info",
|
已分配: "primary",
|
已使用: "success",
|
已作废: "danger",
|
};
|
return statusMap[status] || "info";
|
};
|
|
const handleSearch = () => {
|
// 搜索逻辑已在computed中处理
|
};
|
|
const resetSearch = () => {
|
searchForm.productName = "";
|
searchForm.identifierType = "";
|
searchForm.status = "";
|
};
|
|
const handleAdd = () => {
|
dialogTitle.value = "新增标识";
|
isEdit.value = false;
|
form.productName = "";
|
form.productCode = "";
|
form.batchNo = "";
|
form.identifierType = "";
|
form.quantity = 1;
|
form.status = "已生成";
|
form.remark = "";
|
dialogVisible.value = true;
|
};
|
|
const handleView = row => {
|
// 查看标识详情
|
ElMessage.info("查看标识详情功能待实现");
|
};
|
|
const handleEdit = row => {
|
dialogTitle.value = "编辑标识";
|
isEdit.value = true;
|
editId.value = row.id;
|
Object.assign(form, row);
|
dialogVisible.value = true;
|
};
|
|
const handleExport = row => {
|
// 导出标识
|
ElMessage.success(`已导出标识: ${row.identifierCode}`);
|
};
|
|
const handleReassign = row => {
|
currentProduct.value = row;
|
newBatchNo.value = "";
|
reassignReason.value = "";
|
reassignDialogVisible.value = true;
|
};
|
|
const handleDelete = row => {
|
ElMessageBox.confirm("确认删除该标识吗?", "提示", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning",
|
}).then(() => {
|
const index = identifierList.value.findIndex(item => item.id === row.id);
|
if (index > -1) {
|
identifierList.value.splice(index, 1);
|
pagination.total--;
|
ElMessage.success("删除成功");
|
}
|
});
|
};
|
|
// 生成二维码
|
const generateQRCode = async row => {
|
try {
|
// 检查必要字段
|
if (!row.productName || !row.productCode || !row.batchNo) {
|
ElMessage.warning("产品信息不完整,无法生成二维码");
|
return;
|
}
|
|
currentQRProduct.value = row;
|
qrCodeUrl.value = "";
|
qrCodeDialogVisible.value = true;
|
|
// 构建二维码内容
|
let qrContent = "";
|
if (row.identifierType === "二维码") {
|
qrContent = `${row.productName}|${row.productCode}|${row.batchNo}|${row.identifierCode}`;
|
} else if (row.identifierType === "防伪码") {
|
// 防伪码格式:SEC_产品编码_批次号_时间戳_随机数
|
const timestamp = Date.now();
|
const random = Math.random().toString(36).substr(2, 8);
|
qrContent = `SEC_${row.productCode}_${row.batchNo}_${timestamp}_${random}`;
|
}
|
|
// 生成二维码
|
qrCodeUrl.value = await QRCode.toDataURL(qrContent, {
|
width: 256,
|
margin: 2,
|
color: {
|
dark: "#000000",
|
light: "#FFFFFF",
|
},
|
errorCorrectionLevel: row.identifierType === "防伪码" ? "H" : "M",
|
});
|
|
ElMessage.success("二维码生成成功!");
|
} catch (error) {
|
console.error("生成二维码失败:", error);
|
ElMessage.error("生成二维码失败:" + error.message);
|
qrCodeDialogVisible.value = false;
|
}
|
};
|
|
// 下载二维码
|
const downloadQRCode = () => {
|
if (!qrCodeUrl.value) {
|
ElMessage.warning("请先生成二维码");
|
return;
|
}
|
|
const a = document.createElement("a");
|
a.href = qrCodeUrl.value;
|
a.download = `${currentQRProduct.value.productName}_${
|
currentQRProduct.value.identifierType
|
}_${new Date().getTime()}.png`;
|
document.body.appendChild(a);
|
a.click();
|
document.body.removeChild(a);
|
ElMessage.success("下载成功!");
|
};
|
|
// 复制二维码内容
|
const copyQRContent = async () => {
|
if (!currentQRProduct.value) {
|
ElMessage.warning("没有可复制的内容");
|
return;
|
}
|
|
try {
|
let content = "";
|
if (currentQRProduct.value.identifierType === "二维码") {
|
content = `${currentQRProduct.value.productName}|${currentQRProduct.value.productCode}|${currentQRProduct.value.batchNo}|${currentQRProduct.value.identifierCode}`;
|
} else if (currentQRProduct.value.identifierType === "防伪码") {
|
const timestamp = Date.now();
|
const random = Math.random().toString(36).substr(2, 8);
|
content = `SEC_${currentQRProduct.value.productCode}_${currentQRProduct.value.batchNo}_${timestamp}_${random}`;
|
}
|
|
await navigator.clipboard.writeText(content);
|
ElMessage.success("内容已复制到剪贴板");
|
} catch (error) {
|
// 降级方案
|
const textArea = document.createElement("textarea");
|
textArea.value = content;
|
document.body.appendChild(textArea);
|
textArea.select();
|
document.execCommand("copy");
|
document.body.removeChild(textArea);
|
ElMessage.success("内容已复制到剪贴板");
|
}
|
};
|
|
const generateIdentifiers = () => {
|
if (!codeRule.value) {
|
ElMessage.warning("请选择编码规则");
|
return;
|
}
|
|
// 生成标识的逻辑
|
const newIdentifiers = [];
|
for (let i = 1; i <= generateQuantity.value; i++) {
|
let identifierCode = "";
|
if (codeRule.value === "产品编码+批次号+序号") {
|
identifierCode = `${currentProduct.value.productCode}_${
|
currentProduct.value.batchNo
|
}_${String(i).padStart(3, "0")}`;
|
} else if (codeRule.value === "时间戳+随机数") {
|
identifierCode = `TS_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
} else if (codeRule.value === "自定义规则") {
|
identifierCode = `${customPrefix.value || "CUSTOM"}_${Date.now()}_${i}`;
|
}
|
|
newIdentifiers.push({
|
id: Math.max(...identifierList.value.map(item => item.id)) + i,
|
productName: currentProduct.value.productName,
|
productCode: currentProduct.value.productCode,
|
batchNo: currentProduct.value.batchNo,
|
identifierType: currentProduct.value.identifierType,
|
identifierCode: identifierCode,
|
status: "已生成",
|
generateTime: new Date().toLocaleString(),
|
remark: "批量生成",
|
});
|
}
|
|
identifierList.value.push(...newIdentifiers);
|
pagination.total += newIdentifiers.length;
|
ElMessage.success(`成功生成 ${newIdentifiers.length} 个标识`);
|
generateDialogVisible.value = false;
|
};
|
|
const saveReassign = () => {
|
if (!newBatchNo.value) {
|
ElMessage.warning("请输入新批次号");
|
return;
|
}
|
|
const index = identifierList.value.findIndex(
|
item => item.id === currentProduct.value.id
|
);
|
if (index > -1) {
|
identifierList.value[index].batchNo = newBatchNo.value;
|
identifierList.value[index].status = "已分配";
|
ElMessage.success("标识重新分配成功");
|
reassignDialogVisible.value = false;
|
}
|
};
|
|
const handleSubmit = () => {
|
formRef.value.validate(valid => {
|
if (valid) {
|
if (isEdit.value) {
|
// 编辑
|
const index = identifierList.value.findIndex(
|
item => item.id === editId.value
|
);
|
if (index > -1) {
|
identifierList.value[index] = { ...form, id: editId.value };
|
ElMessage.success("编辑成功");
|
}
|
} else {
|
// 新增
|
const newId =
|
Math.max(...identifierList.value.map(item => item.id)) + 1;
|
|
// 根据标识类型生成不同的标识码
|
let identifierCode = "";
|
if (form.identifierType === "二维码") {
|
identifierCode = `QR_${form.productCode}_${form.batchNo}_001`;
|
} else if (form.identifierType === "防伪码") {
|
identifierCode = `SEC_${form.productCode}_${form.batchNo}_001`;
|
}
|
|
identifierList.value.push({
|
...form,
|
id: newId,
|
identifierCode: identifierCode,
|
generateTime: new Date().toLocaleString(),
|
});
|
pagination.total++;
|
ElMessage.success("新增成功");
|
}
|
dialogVisible.value = false;
|
}
|
});
|
};
|
|
const handleCurrentChange = val => {
|
pagination.currentPage = val.page;
|
pagination.pageSize = val.limit;
|
};
|
</script>
|
|
<style scoped>
|
.search-row {
|
margin-bottom: 20px;
|
}
|
|
.quick-actions-row {
|
margin-bottom: 20px;
|
}
|
|
.quick-actions-row .el-alert {
|
margin-bottom: 0;
|
}
|
|
.quick-actions-row .el-alert p {
|
margin: 5px 0;
|
font-size: 14px;
|
line-height: 1.5;
|
}
|
|
/* 二维码预览样式 */
|
.qr-preview-container {
|
text-align: center;
|
padding: 20px;
|
}
|
|
.qr-image-container {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
gap: 20px;
|
}
|
|
.qr-image {
|
max-width: 100%;
|
height: auto;
|
border: 2px solid #e0e0e0;
|
border-radius: 8px;
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
}
|
|
.qr-info {
|
text-align: left;
|
background: #f8f9fa;
|
padding: 15px;
|
border-radius: 8px;
|
min-width: 300px;
|
}
|
|
.qr-info p {
|
margin: 8px 0;
|
color: #666;
|
font-size: 14px;
|
}
|
|
.qr-loading {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
gap: 15px;
|
padding: 40px 0;
|
}
|
|
.qr-loading .el-icon {
|
font-size: 32px;
|
color: #409eff;
|
}
|
|
.qr-loading p {
|
color: #666;
|
margin: 0;
|
}
|
</style>
|