浏览代码

添加导出pdf

yangg 1 月之前
父节点
当前提交
ea5acb8907
共有 3 个文件被更改,包括 501 次插入12 次删除
  1. 221 0
      package-lock.json
  2. 2 0
      package.json
  3. 278 12
      src/views/JobApplication/report/report.vue

+ 221 - 0
package-lock.json

@@ -34,8 +34,10 @@
 				"element-plus": "^2.8.0",
 				"element-tree-line": "^0.2.1",
 				"font-awesome": "^4.7.0",
+				"html2canvas": "^1.4.1",
 				"js-cookie": "^3.0.5",
 				"js-table2excel": "^1.1.2",
+				"jspdf": "^3.0.1",
 				"jsplumb": "^2.15.6",
 				"lodash-es": "^4.17.21",
 				"mitt": "^3.0.1",
@@ -3864,6 +3866,13 @@
 			"integrity": "sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==",
 			"dev": true
 		},
+		"node_modules/@types/raf": {
+			"version": "3.4.3",
+			"resolved": "https://registry.npmmirror.com/@types/raf/-/raf-3.4.3.tgz",
+			"integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
+			"license": "MIT",
+			"optional": true
+		},
 		"node_modules/@types/semver": {
 			"version": "7.5.8",
 			"resolved": "https://registry.npmmirror.com/@types/semver/-/semver-7.5.8.tgz",
@@ -3876,6 +3885,13 @@
 			"integrity": "sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==",
 			"dev": true
 		},
+		"node_modules/@types/trusted-types": {
+			"version": "2.0.7",
+			"resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+			"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+			"license": "MIT",
+			"optional": true
+		},
 		"node_modules/@types/web-bluetooth": {
 			"version": "0.0.16",
 			"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
@@ -4716,6 +4732,18 @@
 			"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
 			"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
 		},
+		"node_modules/atob": {
+			"version": "2.1.2",
+			"resolved": "https://registry.npmmirror.com/atob/-/atob-2.1.2.tgz",
+			"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+			"license": "(MIT OR Apache-2.0)",
+			"bin": {
+				"atob": "bin/atob.js"
+			},
+			"engines": {
+				"node": ">= 4.5.0"
+			}
+		},
 		"node_modules/autoprefixer": {
 			"version": "10.4.20",
 			"resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.20.tgz",
@@ -4782,6 +4810,15 @@
 			"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
 			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
 		},
+		"node_modules/base64-arraybuffer": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+			"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
+			"license": "MIT",
+			"engines": {
+				"node": ">= 0.6.0"
+			}
+		},
 		"node_modules/base64-js": {
 			"version": "1.5.1",
 			"resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
@@ -4958,6 +4995,18 @@
 				"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
 			}
 		},
+		"node_modules/btoa": {
+			"version": "1.2.1",
+			"resolved": "https://registry.npmmirror.com/btoa/-/btoa-1.2.1.tgz",
+			"integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==",
+			"license": "(MIT OR Apache-2.0)",
+			"bin": {
+				"btoa": "bin/btoa.js"
+			},
+			"engines": {
+				"node": ">= 0.4.0"
+			}
+		},
 		"node_modules/buffer": {
 			"version": "6.0.3",
 			"resolved": "https://registry.npmmirror.com/buffer/-/buffer-6.0.3.tgz",
@@ -5143,6 +5192,45 @@
 				}
 			]
 		},
+		"node_modules/canvg": {
+			"version": "3.0.11",
+			"resolved": "https://registry.npmmirror.com/canvg/-/canvg-3.0.11.tgz",
+			"integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
+			"license": "MIT",
+			"optional": true,
+			"dependencies": {
+				"@babel/runtime": "^7.12.5",
+				"@types/raf": "^3.4.0",
+				"core-js": "^3.8.3",
+				"raf": "^3.4.1",
+				"regenerator-runtime": "^0.13.7",
+				"rgbcolor": "^1.0.1",
+				"stackblur-canvas": "^2.0.0",
+				"svg-pathdata": "^6.0.3"
+			},
+			"engines": {
+				"node": ">=10.0.0"
+			}
+		},
+		"node_modules/canvg/node_modules/core-js": {
+			"version": "3.42.0",
+			"resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.42.0.tgz",
+			"integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==",
+			"hasInstallScript": true,
+			"license": "MIT",
+			"optional": true,
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/core-js"
+			}
+		},
+		"node_modules/canvg/node_modules/regenerator-runtime": {
+			"version": "0.13.11",
+			"resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+			"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+			"license": "MIT",
+			"optional": true
+		},
 		"node_modules/cfb": {
 			"version": "1.2.2",
 			"resolved": "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz",
@@ -5440,6 +5528,15 @@
 			"resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
 			"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
 		},
+		"node_modules/css-line-break": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz",
+			"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+			"license": "MIT",
+			"dependencies": {
+				"utrie": "^1.0.2"
+			}
+		},
 		"node_modules/cssesc": {
 			"version": "3.0.0",
 			"resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz",
@@ -5667,6 +5764,16 @@
 				"ssr-window": "^3.0.0-alpha.1"
 			}
 		},
+		"node_modules/dompurify": {
+			"version": "3.2.6",
+			"resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.2.6.tgz",
+			"integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==",
+			"license": "(MPL-2.0 OR Apache-2.0)",
+			"optional": true,
+			"optionalDependencies": {
+				"@types/trusted-types": "^2.0.7"
+			}
+		},
 		"node_modules/dotenv": {
 			"version": "16.4.7",
 			"resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.4.7.tgz",
@@ -6371,6 +6478,12 @@
 				"reusify": "^1.0.4"
 			}
 		},
+		"node_modules/fflate": {
+			"version": "0.8.2",
+			"resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.8.2.tgz",
+			"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
+			"license": "MIT"
+		},
 		"node_modules/file-entry-cache": {
 			"version": "8.0.0",
 			"resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -6892,6 +7005,19 @@
 				"url": "https://github.com/sponsors/wooorm"
 			}
 		},
+		"node_modules/html2canvas": {
+			"version": "1.4.1",
+			"resolved": "https://registry.npmmirror.com/html2canvas/-/html2canvas-1.4.1.tgz",
+			"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+			"license": "MIT",
+			"dependencies": {
+				"css-line-break": "^2.1.0",
+				"text-segmentation": "^1.0.3"
+			},
+			"engines": {
+				"node": ">=8.0.0"
+			}
+		},
 		"node_modules/humanize-duration": {
 			"version": "3.32.1",
 			"resolved": "https://registry.npmmirror.com/humanize-duration/-/humanize-duration-3.32.1.tgz",
@@ -7324,6 +7450,36 @@
 				"jsonrepair": "bin/cli.js"
 			}
 		},
+		"node_modules/jspdf": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmmirror.com/jspdf/-/jspdf-3.0.1.tgz",
+			"integrity": "sha512-qaGIxqxetdoNnFQQXxTKUD9/Z7AloLaw94fFsOiJMxbfYdBbrBuhWmbzI8TVjrw7s3jBY1PFHofBKMV/wZPapg==",
+			"license": "MIT",
+			"dependencies": {
+				"@babel/runtime": "^7.26.7",
+				"atob": "^2.1.2",
+				"btoa": "^1.2.1",
+				"fflate": "^0.8.1"
+			},
+			"optionalDependencies": {
+				"canvg": "^3.0.11",
+				"core-js": "^3.6.0",
+				"dompurify": "^3.2.4",
+				"html2canvas": "^1.0.0-rc.5"
+			}
+		},
+		"node_modules/jspdf/node_modules/core-js": {
+			"version": "3.42.0",
+			"resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.42.0.tgz",
+			"integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==",
+			"hasInstallScript": true,
+			"license": "MIT",
+			"optional": true,
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/core-js"
+			}
+		},
 		"node_modules/jsplumb": {
 			"version": "2.15.6",
 			"resolved": "https://registry.npmmirror.com/jsplumb/-/jsplumb-2.15.6.tgz",
@@ -8205,6 +8361,13 @@
 			"resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
 			"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="
 		},
+		"node_modules/performance-now": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz",
+			"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
+			"license": "MIT",
+			"optional": true
+		},
 		"node_modules/picocolors": {
 			"version": "1.1.1",
 			"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
@@ -8640,6 +8803,16 @@
 				"node": ">= 12.0.0"
 			}
 		},
+		"node_modules/raf": {
+			"version": "3.4.1",
+			"resolved": "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz",
+			"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+			"license": "MIT",
+			"optional": true,
+			"dependencies": {
+				"performance-now": "^2.1.0"
+			}
+		},
 		"node_modules/rc9": {
 			"version": "2.1.2",
 			"resolved": "https://registry.npmmirror.com/rc9/-/rc9-2.1.2.tgz",
@@ -8765,6 +8938,16 @@
 			"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
 			"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="
 		},
+		"node_modules/rgbcolor": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmmirror.com/rgbcolor/-/rgbcolor-1.0.1.tgz",
+			"integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
+			"license": "MIT OR SEE LICENSE IN FEEL-FREE.md",
+			"optional": true,
+			"engines": {
+				"node": ">= 0.8.15"
+			}
+		},
 		"node_modules/rollup": {
 			"version": "4.34.6",
 			"resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.34.6.tgz",
@@ -9166,6 +9349,16 @@
 			"resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-3.0.0.tgz",
 			"integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA=="
 		},
+		"node_modules/stackblur-canvas": {
+			"version": "2.7.0",
+			"resolved": "https://registry.npmmirror.com/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
+			"integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
+			"license": "MIT",
+			"optional": true,
+			"engines": {
+				"node": ">=0.1.14"
+			}
+		},
 		"node_modules/statuses": {
 			"version": "1.5.0",
 			"resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz",
@@ -9382,6 +9575,16 @@
 				"url": "https://github.com/sponsors/ljharb"
 			}
 		},
+		"node_modules/svg-pathdata": {
+			"version": "6.0.3",
+			"resolved": "https://registry.npmmirror.com/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
+			"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
+			"license": "MIT",
+			"optional": true,
+			"engines": {
+				"node": ">=12.0.0"
+			}
+		},
 		"node_modules/svg-tags": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz",
@@ -9516,6 +9719,15 @@
 			"resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
 			"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
 		},
+		"node_modules/text-segmentation": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmmirror.com/text-segmentation/-/text-segmentation-1.0.3.tgz",
+			"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+			"license": "MIT",
+			"dependencies": {
+				"utrie": "^1.0.2"
+			}
+		},
 		"node_modules/thenify": {
 			"version": "3.3.1",
 			"resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz",
@@ -9887,6 +10099,15 @@
 				"node": ">= 0.12.0"
 			}
 		},
+		"node_modules/utrie": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmmirror.com/utrie/-/utrie-1.0.2.tgz",
+			"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+			"license": "MIT",
+			"dependencies": {
+				"base64-arraybuffer": "^1.0.2"
+			}
+		},
 		"node_modules/uuid": {
 			"version": "9.0.1",
 			"resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz",

+ 2 - 0
package.json

@@ -35,8 +35,10 @@
 		"element-plus": "^2.8.0",
 		"element-tree-line": "^0.2.1",
 		"font-awesome": "^4.7.0",
+		"html2canvas": "^1.4.1",
 		"js-cookie": "^3.0.5",
 		"js-table2excel": "^1.1.2",
+		"jspdf": "^3.0.1",
 		"jsplumb": "^2.15.6",
 		"lodash-es": "^4.17.21",
 		"mitt": "^3.0.1",

+ 278 - 12
src/views/JobApplication/report/report.vue

@@ -9,6 +9,7 @@
       <div class="header-right">
         <div>报告生成时间:{{ reportTime }}</div>
         <div class="report-id">报告ID:{{ reportId }}</div>
+        <!-- 添加导出按钮 -->
       </div>
     </div>
 
@@ -168,7 +169,12 @@
         </div>
         <!-- 能力雷达图 -->
         <div class="radar-chart">
-          <v-chart class="radar" :option="radarOption" autoresize />
+          <v-chart 
+            ref="radarChart"
+            class="radar" 
+            :option="radarOption" 
+            autoresize 
+          />
         </div>
       </div>
 
@@ -354,7 +360,27 @@
   </div>
     </div>
   </div>
- 
+
+  <!-- 将导出按钮移到这里,添加fixed-btn类 -->
+  <el-button
+          type="primary"
+          circle
+           class="export-btn fixed-btn"
+          :loading="exporting"
+          @click="exportPDF"
+        >
+          <el-icon><Download /></el-icon>
+        </el-button>
+ <!--  <el-button 
+    type="primary"
+    size="small"
+    @click="exportPDF"
+    :loading="exporting"
+    class="export-btn fixed-btn"
+  >
+    <i class="el-icon-download"></i>
+    {{ exporting ? '导出中...' : '导出PDF' }}
+  </el-button> -->
 </div>
 
 <!-- 添加个人详细信息弹窗 -->
@@ -620,6 +646,10 @@ import { CanvasRenderer } from 'echarts/renderers'
 import { RadarChart } from 'echarts/charts'
 import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
 import VChart from 'vue-echarts'
+// 引入html2canvas和jspdf
+import html2canvas from 'html2canvas'
+import jsPDF from 'jspdf'
+import { Share, Download, Printer, ArrowUp, User } from '@element-plus/icons-vue'
 
 use([
   CanvasRenderer,
@@ -750,7 +780,9 @@ export default {
           { name: '沟通表达能力', value: 50, max: 100 }
         ],
         values: [50, 50, 50, 50, 50, 50]  // 初始值设为0
-      }
+      },
+      exporting: false, // 添加导出状态控制
+      radarChartInstance: null,
     }
   },
   async created() {
@@ -772,6 +804,17 @@ export default {
     this.checkDevice();
     // 监听窗口大小变化
     window.addEventListener('resize', this.checkDevice);
+    // 添加获取图表实例的ref
+    this.$nextTick(() => {
+      // 保存图表实例的引用
+      this.radarChartInstance = this.$refs.radarChart
+    })
+    // 等待组件渲染完成后保存图表实例
+    this.$nextTick(() => {
+      if (this.$refs.radarChart) {
+        this.radarChartInstance = this.$refs.radarChart
+      }
+    })
   },
   beforeDestroy() {
     // 移除滚动监听
@@ -787,30 +830,40 @@ export default {
           center: ['50%', '50%'],
           radius: '65%',
           splitNumber: 4,
-          shape: 'circle',   // 改为圆形
+          shape: 'circle',
           axisName: {
             color: '#666',
             fontSize: 12,
-            formatter: (name, indicator) => {
+            formatter: (name) => {
               const index = this.radarData.indicator.findIndex(item => item.name === name);
-              return `${this.radarData.values[index]} / 100\n${name}`;
+              const value = this.radarData.values[index];
+              // 添加中文释义
+              const nameMappings = {
+                '团队协作能力': '团队协作',
+                '应变能力': '应变能力',
+                '服务意识': '服务意识',
+                '客户需求洞察力': '需求洞察',
+                '沟通表达能力': '沟通表达'
+              };
+              const displayName = nameMappings[name] || name;
+              return `${value}\n${displayName}`;
             }
           },
-          nameGap: 15,      // 增加文字与图表的距离
+          nameGap: 15,
           axisLabel: {
             show: false
           },
           splitArea: {
             show: true,
             areaStyle: {
-              color: ['#fff']  // 渐变色填充
+              color: ['#fff']
             }
           },
           splitLine: {
             show: true,
             lineStyle: {
               color: '#E7E9ED',
-              type: 'solid',   // 改为实线
+              type: 'solid',
               width: 1
             }
           },
@@ -829,12 +882,12 @@ export default {
             normal: {
               lineStyle: {
                 color: '#c1dafc',
-                width: 2        // 增加线条宽度
+                width: 2
               },
               areaStyle: {
                 type: 'default',
-                color: 'rgba(193, 218, 252, 0.6)',  // 调整填充色透明度
-                shadowBlur: 10,                      // 添加阴影效果
+                color: 'rgba(193, 218, 252, 0.6)',
+                shadowBlur: 10,
                 shadowColor: 'rgba(193, 218, 252, 0.5)',
                 shadowOffsetY: 5
               }
@@ -1262,6 +1315,154 @@ export default {
 
       // 打印数据以便调试
       console.log('Updated radar data:', this.radarData);
+    },
+    // 添加检查图表实例的方法
+    async ensureChartRendered() {
+      let attempts = 0
+      const maxAttempts = 5
+      
+      while (!this.$refs.radarChart?.chart && attempts < maxAttempts) {
+        await new Promise(resolve => setTimeout(resolve, 200))
+        attempts++
+      }
+      
+      return this.$refs.radarChart?.chart
+    },
+    // 修改exportPDF方法中的相关部分
+    async exportPDF() {
+      try {
+        this.exporting = true
+        
+        // 1. 创建临时容器并设置固定宽度
+        const tempContainer = document.createElement('div')
+        tempContainer.style.width = '1200px'
+        tempContainer.style.background = '#fff'
+        tempContainer.style.position = 'absolute'
+        tempContainer.style.left = '-9999px'
+        
+        // 2. 克隆要导出的内容
+        const headerClone = document.querySelector('.report-header').cloneNode(true)
+        const contentClone = document.querySelector('.report-container').cloneNode(true)
+        
+        // 3. 特殊处理雷达图
+        const radarChart = contentClone.querySelector('.radar-chart')
+        if(radarChart) {
+          try {
+            // 确保图表已渲染
+            const echartsInstance = await this.ensureChartRendered()
+            if (echartsInstance) {
+              // 修改雷达图配置,确保导出时保持圆形
+              const exportOption = {
+                ...this.radarOption,
+                radar: {
+                  ...this.radarOption.radar,
+                  radius: '65%',
+                  center: ['50%', '50%'],
+                  nameGap: 15,
+                  axisName: {
+                    ...this.radarOption.radar.axisName,
+                    formatter: (name) => {
+                      const index = this.radarData.indicator.findIndex(item => item.name === name);
+                      const value = this.radarData.values[index];
+                      return `${value}\n${name}`;
+                    }
+                  }
+                }
+              }
+              
+              // 设置导出时的尺寸和配置
+              echartsInstance.setOption(exportOption)
+              const canvas = echartsInstance.getRenderedCanvas({
+                pixelRatio: 2,
+                width: 429,
+                height: 310 // 确保宽高相等
+              })
+              
+              const radarImg = document.createElement('img')
+              radarImg.src = canvas.toDataURL('image/png')
+              radarImg.style.width = '429px'
+              radarImg.style.height = '310px' // 保持宽高一致
+              radarImg.style.objectFit = 'contain'
+              
+              radarChart.innerHTML = ''
+              radarChart.appendChild(radarImg)
+              
+              // 导出后恢复原始配置
+              echartsInstance.setOption(this.radarOption)
+            }
+          } catch (err) {
+            console.warn('处理雷达图时出错:', err)
+          }
+        }
+
+        // 4. 添加到临时容器
+        tempContainer.appendChild(headerClone)
+        tempContainer.appendChild(contentClone)
+        document.body.appendChild(tempContainer)
+
+        // 5. 优化html2canvas配置
+        const canvas = await html2canvas(tempContainer, {
+          scale: 2, // 提高清晰度
+          useCORS: true,
+          allowTaint: true,
+          backgroundColor: '#ffffff',
+          windowWidth: 1200,
+          height: tempContainer.scrollHeight,
+          onclone: (clonedDoc) => {
+            // 处理克隆后的样式
+            const styles = clonedDoc.getElementsByTagName('style')
+            Array.from(styles).forEach(style => {
+              style.innerHTML = style.innerHTML.replace(/\@media/g, '._pdf_media')
+            })
+          }
+        })
+
+        // 6. 移除临时容器
+        document.body.removeChild(tempContainer)
+
+        // 7. 计算PDF尺寸和缩放
+        const imgWidth = 595.28 // A4宽度
+        const imgHeight = 841.89 // A4高度
+        const pageHeight = (imgWidth / canvas.width) * canvas.height
+        const pageCount = Math.ceil(pageHeight / imgHeight)
+
+        // 8. 创建PDF文档
+        const pdf = new jsPDF('p', 'pt', 'a4')
+        
+        // 9. 分页处理
+        for(let i = 0; i < pageCount; i++) {
+          if(i > 0) {
+            pdf.addPage()
+          }
+
+          // 计算每页显示的内容
+          const position = -imgHeight * i
+          pdf.addImage(
+            canvas.toDataURL('image/jpeg', 1.0),
+            'JPEG',
+            0,
+            position,
+            imgWidth,
+            pageHeight,
+            '',
+            'FAST'
+          )
+
+          // 添加页码
+         /*  pdf.setFontSize(10)
+          pdf.text(`${i + 1}/${pageCount}`, imgWidth - 30, imgHeight - 10) */
+        }
+
+        // 10. 生成文件名并下载
+        const fileName = `AI面试报告_${this.userInfo.name}_${this.reportTime}.pdf`
+        pdf.save(fileName)
+
+      } catch (error) {
+        console.error('导出PDF失败:', error)
+        this.$message.error('导出PDF失败,请稍后重试')
+      } finally {
+        this.exporting = false
+      }
     }
   }
 }
@@ -2576,4 +2777,69 @@ export default {
     }
   }
 }
+
+// 修改导出按钮样式
+.export-btn.fixed-btn {
+  position: fixed;
+  right: 40px;
+  bottom: 40px;
+  z-index: 999;
+  padding: 20px 20px;
+  border-radius: 24px;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+  transition: all 0.3s ease;
+  display: flex;
+  align-items: center;
+  gap: 4px;
+  
+  .el-icon-download {
+    font-size: 16px;
+  }
+  
+  &:hover {
+    transform: translateY(-2px);
+    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+  }
+  
+  &:active {
+    transform: translateY(0);
+  }
+}
+
+// 添加移动端适配
+@media screen and (max-width: 768px) {
+  .export-btn.fixed-btn {
+    right: 20px;
+    bottom: 20px;
+    padding: 10px 16px;
+  }
+}
+
+// 修改header-right样式以适应新增按钮
+.report-header {
+  .header-right {
+    display: flex;
+    align-items: center;
+    gap: 16px;
+    
+    .export-btn {
+      margin-left: auto; // 将按钮推到最右侧
+    }
+  }
+}
+
+// 添加移动端适配
+@media screen and (max-width: 768px) {
+  .report-header {
+    .header-right {
+      flex-wrap: wrap;
+      
+      .export-btn {
+        margin-left: 0;
+        margin-top: 8px;
+        width: 100%;
+      }
+    }
+  }
+}
 </style>