| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- <template>
- <div class="app-container">
- <el-row :gutter="20">
- <!--用户数据-->
- <el-col style="display:flex" :span="20" :xs="24">
- <el-form :model="queryParams" ref="queryRef" :inline="true">
- <el-form-item label="企业信用代码" prop="unifiedSocialCreditCode">
- <el-input v-model="queryParams.unifiedSocialCreditCode" placeholder="请输入企业信用代码" clearable
- style="width: 240px" />
- </el-form-item>
- <el-form-item label="企业名称" prop="enterpriseName">
- <el-input v-model="queryParams.enterpriseName" placeholder="请输入企业名称" clearable
- style="width: 240px" />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
- <el-button icon="Refresh" @click="resetQuery">重置</el-button>
- <el-button type="success" icon="Download" @click="handleBatchDownload" :disabled="selectedRows.length === 0">批量下载</el-button>
- </el-form-item>
- </el-form>
- </el-col>
- </el-row>
- <el-table stripe :data="tableData" style="width: 100%" height="710" @selection-change="handleSelectionChange">
- <el-table-column type="selection" width="55" />
- <el-table-column prop="enterpriseName" label="企业名称">
- </el-table-column>
- <el-table-column label="企业信用代码">
- <template #default="scope">
- <el-link v-if="store.getters.permissions.includes('*:*:*') || store.getters.permissions.includes('CEEnterprise:companydetail')" type="primary" @click="handleClick(scope.row)">{{ scope.row.unifiedSocialCreditCode }}</el-link>
- <div v-else>{{ scope.row.unifiedSocialCreditCode }}</div>
- </template>
- </el-table-column>
- <el-table-column prop="total" label="总分" align="center" width="100">
- <template #default="scope">
- {{ scope.row.total.toFixed(2) }}
- </template>
- </el-table-column>
- <el-table-column prop="grade" label="等级" width="100">
- </el-table-column>
- <el-table-column label="操作">
- <template #default="scope">
- <el-button @click="handlePreview(scope.row)" type="warning">预览企业二维码</el-button>
- <el-button @click="handleDownload(scope.row)" type="primary" :loading="downloadingRows.has(scope.row.unifiedSocialCreditCode)">
- 下载企业二维码
- </el-button>
- </template>
- </el-table-column>
- </el-table>
- <div style="position: fixed;bottom: 20px;right: 10px;">
- <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize" @pagination="getList" />
- </div>
- <el-dialog v-model="dialogQrcodeVisible" title="二维码预览" width="340px">
- <template #default>
- <div ref="qrcodeExport">
- <el-image style="width: 300px; height: 300px; margin: 0 auto;" :src="previewQrcodeSrc" />
- <div style="text-align: center;font-size: 14px;">{{currentPreviewInfo.unifiedSocialCreditCode}}</div>
- <div style="text-align: center;font-size: 16px;">{{currentPreviewInfo.enterpriseName}}</div>
- </div>
- </template>
- </el-dialog>
- <!-- 隐藏的canvas用于生成二维码 -->
- <canvas ref="hiddenCanvas" style="display: none;"></canvas>
- </div>
- </template>
- <script setup name="getCerating">
- import { ref, reactive, toRefs, onMounted } from 'vue';
- import { ElMessage, ElLoading } from 'element-plus';
- import { getCreditScoreList } from '@/api/ceenterprise/cerating';
- import { useRouter } from "vue-router";
- import store from "@/store";
- import QRCodeStyling from "qr-code-styling";
- import logo from '/public/favicon.ico';
- const router = useRouter();
- const site_url = import.meta.env.VITE_APP_SITE_URL;
- const currentPreviewInfo = ref({});
- const dialogQrcodeVisible = ref(false);
- const previewQrcodeSrc = ref('');
- const tableData = ref([]);
- const total = ref(0);
- const selectedRows = ref([]);
- const qrcodeExport = ref(null);
- const hiddenCanvas = ref(null);
- const downloadingRows = ref(new Set()); // 跟踪正在下载的行
- const data = reactive({
- form: {},
- queryParams: {
- pageNum: 1,
- pageSize: 20,
- unifiedSocialCreditCode: '',
- grade: null,
- total: null,
- enterpriseName: '',
- },
- });
- const {queryParams} = toRefs(data);
- // Initial data fetch on component mount
- onMounted(() => {
- getList();
- });
- /** 搜索按钮操作 */
- function handleQuery() {
- queryParams.value.pageNum = 1;
- getList();
- }
- /** 重置按钮操作 */
- function resetQuery() {
- queryParams.value.unifiedSocialCreditCode = "";
- queryParams.value.enterpriseName = "";
- handleQuery();
- }
- /** 查询用户列表 */
- function getList() {
- getCreditScoreList(queryParams.value).then((res) => {
- tableData.value = res.data.result;
- total.value = res.data.totalSize;
- }).catch(error => {
- console.error("获取列表失败:", error);
- ElMessage.error("获取列表失败,请稍后再试。");
- });
- }
- /** 处理行点击,跳转到详情页 */
- const handleClick = (row) => {
- const {unifiedSocialCreditCode, enterpriseName} = row;
- router.push({
- path: '/CEEnterprise/companydetail',
- query: {
- unifiedSocialCreditCode,
- enterpriseName
- }
- });
- };
- /** 生成二维码并返回canvas */
- const generateQRCode = async (row) => {
- return new Promise((resolve, reject) => {
- try {
- const qrCode = new QRCodeStyling({
- width: 600,
- height: 600,
- type: "canvas",
- data: site_url + '/mobile/companyPreview?uniCode=' + row.unifiedSocialCreditCode,
- image: logo,
- dotsOptions: {
- color: "#000000",
- type: "rounded"
- },
- backgroundOptions: {
- color: "#e9ebee",
- },
- imageOptions: {
- crossOrigin: "anonymous",
- margin: 20
- }
- });
- // 创建一个临时的canvas容器
- const tempContainer = document.createElement('div');
- tempContainer.style.position = 'absolute';
- tempContainer.style.left = '-9999px';
- tempContainer.style.top = '-9999px';
- document.body.appendChild(tempContainer);
- qrCode.append(tempContainer);
- // 等待二维码生成完成
- setTimeout(() => {
- const canvas = tempContainer.querySelector('canvas');
- if (canvas) {
- // 创建最终的canvas,包含二维码和文字
- const finalCanvas = document.createElement('canvas');
- const ctx = finalCanvas.getContext('2d');
- // 设置最终canvas的尺寸(二维码 + 文字区域)
- finalCanvas.width = 600;
- finalCanvas.height = 700; // 增加高度以容纳文字
- // 设置白色背景
- ctx.fillStyle = '#ffffff';
- ctx.fillRect(0, 0, finalCanvas.width, finalCanvas.height);
- // 绘制二维码
- ctx.drawImage(canvas, 0, 0);
- // 绘制文字
- ctx.fillStyle = '#000000';
- ctx.textAlign = 'center';
- // 绘制企业信用代码
- ctx.font = '24px Arial';
- ctx.fillText(row.unifiedSocialCreditCode, 300, 640);
- // 绘制企业名称
- ctx.font = 'bold 28px Arial';
- ctx.fillText(row.enterpriseName, 300, 680);
- // 清理临时元素
- document.body.removeChild(tempContainer);
- resolve(finalCanvas);
- } else {
- document.body.removeChild(tempContainer);
- reject(new Error('无法生企业二维码'));
- }
- }, 1000); // 给足够时间让二维码生成
- } catch (error) {
- reject(error);
- }
- });
- };
- /** 下载canvas为图片 */
- const downloadCanvas = (canvas, filename) => {
- try {
- const dataURL = canvas.toDataURL('image/png', 1.0);
- const link = document.createElement('a');
- link.href = dataURL;
- link.download = filename;
- document.body.appendChild(link);
- link.click();
- document.body.removeChild(link);
- } catch (error) {
- console.error('下载失败:', error);
- throw error;
- }
- };
- /** 处理下载单个二维码 */
- const handleDownload = async (row) => {
- const creditCode = row.unifiedSocialCreditCode;
- if (downloadingRows.value.has(creditCode)) {
- return; // 防止重复下载
- }
- downloadingRows.value.add(creditCode);
- try {
- const canvas = await generateQRCode(row);
- const filename = `${row.enterpriseName}_${creditCode}_二维码.png`;
- downloadCanvas(canvas, filename);
- ElMessage.success('二维码下载成功!');
- } catch (error) {
- console.error('下载二维码失败:', error);
- ElMessage.error('下载二维码失败,请稍后再试。');
- } finally {
- downloadingRows.value.delete(creditCode);
- }
- };
- /** 处理预览单个二维码 */
- const handlePreview = (row) => {
- currentPreviewInfo.value = row;
- const w = new QRCodeStyling({
- width: 600,
- height: 600,
- type: "svg",
- data: site_url + '/mobile/companyPreview?uniCode=' + row.unifiedSocialCreditCode,
- image: logo,
- dotsOptions: {
- color: "#000000",
- type: "rounded"
- },
- backgroundOptions: {
- color: "#e9ebee",
- },
- imageOptions: {
- crossOrigin: "anonymous",
- margin: 20
- }
- });
- w.getRawData().then(blob => {
- previewQrcodeSrc.value = URL.createObjectURL(blob);
- });
- dialogQrcodeVisible.value = true;
- };
- /** 处理表格行选择变化 */
- const handleSelectionChange = (selection) => {
- selectedRows.value = selection;
- };
- /** 批量下载二维码 */
- const handleBatchDownload = async () => {
- if (selectedRows.value.length === 0) {
- ElMessage.warning('请至少选择一个企业进行下载!');
- return;
- }
- const loadingInstance = ElLoading.service({
- fullscreen: true,
- text: `正在下载 ${selectedRows.value.length} 个二维码...`,
- background: 'rgba(0, 0, 0, 0.3)'
- });
- let successCount = 0;
- let failCount = 0;
- try {
- // 使用 Promise.allSettled 来处理并发下载,但限制并发数量
- const batchSize = 3; // 每批处理3个,避免浏览器卡顿
- for (let i = 0; i < selectedRows.value.length; i += batchSize) {
- const batch = selectedRows.value.slice(i, i + batchSize);
- const promises = batch.map(async (row) => {
- try {
- const canvas = await generateQRCode(row);
- const filename = `${row.enterpriseName}_${row.unifiedSocialCreditCode}_二维码.png`;
- downloadCanvas(canvas, filename);
- return {success: true, row};
- } catch (error) {
- console.error(`下载 ${row.enterpriseName} 的二维码失败:`, error);
- return {success: false, row, error};
- }
- });
- const results = await Promise.allSettled(promises);
- results.forEach((result) => {
- if (result.status === 'fulfilled' && result.value.success) {
- successCount++;
- } else {
- failCount++;
- }
- });
- // 更新加载文本
- loadingInstance.setText(`正在下载二维码... (${successCount + failCount}/${selectedRows.value.length})`);
- // 批次间稍作延迟,避免浏览器卡顿
- if (i + batchSize < selectedRows.value.length) {
- await new Promise(resolve => setTimeout(resolve, 500));
- }
- }
- // 显示结果消息
- if (failCount === 0) {
- ElMessage.success(`成功下载 ${successCount} 个企业二维码!`);
- } else if (successCount > 0) {
- ElMessage.warning(`下载完成:成功 ${successCount} 个,失败 ${failCount} 个`);
- } else {
- ElMessage.error('批量下载失败,请稍后再试。');
- }
- } catch (error) {
- console.error("批量下载过程中发生错误:", error);
- ElMessage.error("批量下载过程中发生错误。");
- } finally {
- loadingInstance.close();
- }
- };
- </script>
- <style scoped>
- .app-container {
- padding: 20px;
- }
- /* 添加一些加载状态的样式 */
- .el-button.is-loading {
- pointer-events: none;
- }
- </style>
|