From a39835be01d690b508acd54efde7a1709e40f40f Mon Sep 17 00:00:00 2001 From: xuxin <15279969124@163.com> Date: Fri, 3 Apr 2026 17:52:07 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=80=E5=8E=86=E4=B8=8A=E4=BC=A0=EF=BC=8Cpd?= =?UTF-8?q?f=E7=AE=80=E5=8E=86=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- auto-imports.d.ts | 1 + components.d.ts | 3 + package.json | 1 + pnpm-lock.yaml | 179 +++++ src/api/resume.ts | 372 +++++++++ src/assets/images/home/avatar-temporary.png | Bin 0 -> 37590 bytes src/assets/images/logo.png | Bin 0 -> 7484 bytes .../components/job-resume-custom-dialog.scss | 1 + src/assets/styles/components/side-nav.scss | 7 + src/assets/styles/index.scss | 7 + src/assets/styles/pages/home.scss | 283 +++++-- src/assets/styles/pages/jobs.scss | 8 + src/assets/styles/pages/resume-detail.scss | 87 ++- src/assets/styles/pages/resume.scss | 13 + src/components/JobResumeCustomDialog.vue | 79 +- src/components/ProfileEditDrawer.vue | 62 +- src/components/SideNav.vue | 7 +- src/stores/index.ts | 17 +- src/types/html2pdf.d.ts | 22 + src/utils/aiRequest.ts | 54 ++ src/views/Home.vue | 309 ++++++-- src/views/Jobs.vue | 4 +- src/views/Resume.vue | 141 +++- src/views/ResumeDetail.vue | 715 ++++++++++++++++-- vite.config.ts | 5 + 25 files changed, 2076 insertions(+), 301 deletions(-) create mode 100644 src/api/resume.ts create mode 100644 src/assets/images/home/avatar-temporary.png create mode 100644 src/assets/images/logo.png create mode 100644 src/types/html2pdf.d.ts create mode 100644 src/utils/aiRequest.ts diff --git a/auto-imports.d.ts b/auto-imports.d.ts index 8c1957b..e66cf19 100644 --- a/auto-imports.d.ts +++ b/auto-imports.d.ts @@ -6,6 +6,7 @@ // biome-ignore lint: disable export {} declare global { + const ElLoading: typeof import('element-plus/es').ElLoading const ElMessage: typeof import('element-plus/es').ElMessage const ElMessageBox: typeof import('element-plus/es').ElMessageBox } diff --git a/components.d.ts b/components.d.ts index e233fe8..6b640a2 100644 --- a/components.d.ts +++ b/components.d.ts @@ -42,4 +42,7 @@ declare module 'vue' { SettingsDialog: typeof import('./src/components/SettingsDialog.vue')['default'] SideNav: typeof import('./src/components/SideNav.vue')['default'] } + export interface GlobalDirectives { + vLoading: typeof import('element-plus/es')['ElLoadingDirective'] + } } diff --git a/package.json b/package.json index dfa730b..a67b6aa 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@element-plus/icons-vue": "^2.3.2", "axios": "^1.13.6", "element-plus": "^2.13.3", + "html2pdf.js": "^0.14.0", "sass": "^1.97.3", "vue": "^3.5.25", "vue-router": "^4.6.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 17c8b4c..3a7aae4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: element-plus: specifier: ^2.13.3 version: 2.13.3(vue@3.5.29(typescript@5.9.3)) + html2pdf.js: + specifier: ^0.14.0 + version: 0.14.0 sass: specifier: ^1.97.3 version: 1.97.3 @@ -83,6 +86,10 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + '@babel/types@7.29.0': resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} @@ -532,6 +539,15 @@ packages: '@types/node@24.11.0': resolution: {integrity: sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw==} + '@types/pako@2.0.4': + resolution: {integrity: sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==} + + '@types/raf@3.4.3': + resolution: {integrity: sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} @@ -717,6 +733,10 @@ packages: bare-url@2.3.2: resolution: {integrity: sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==} + base64-arraybuffer@1.0.2: + resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} + engines: {node: '>= 0.6.0'} + basic-ftp@5.2.0: resolution: {integrity: sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==} engines: {node: '>=10.0.0'} @@ -748,6 +768,10 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + canvg@3.0.11: + resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==} + engines: {node: '>=10.0.0'} + chokidar@4.0.3: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} @@ -797,6 +821,9 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} + core-js@3.49.0: + resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==} + cosmiconfig@9.0.1: resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} engines: {node: '>=14'} @@ -806,6 +833,9 @@ packages: typescript: optional: true + css-line-break@2.1.0: + resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -856,6 +886,9 @@ packages: devtools-protocol@0.0.1566079: resolution: {integrity: sha512-MJfAEA1UfVhSs7fbSQOG4czavUp1ajfg6prlAN0+cmfa2zNjaIbvq8VneP7do1WAQQIvgNJWSMeP6UyI90gIlQ==} + dompurify@3.3.3: + resolution: {integrity: sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -973,6 +1006,9 @@ packages: fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + fast-png@6.4.0: + resolution: {integrity: sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==} + fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} @@ -988,6 +1024,9 @@ packages: picomatch: optional: true + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -1061,6 +1100,13 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + html2canvas@1.4.1: + resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==} + engines: {node: '>=8.0.0'} + + html2pdf.js@0.14.0: + resolution: {integrity: sha512-yvNJgE/8yru2UeGflkPdjW8YEY+nDH5X7/2WG4uiuSCwYiCp8PZ8EKNiTAa6HxJ1NjC51fZSIEq6xld5CADKBQ==} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -1100,6 +1146,9 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + iobuffer@5.4.0: + resolution: {integrity: sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==} + ip-address@10.1.0: resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} engines: {node: '>= 12'} @@ -1147,6 +1196,9 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + jspdf@4.2.1: + resolution: {integrity: sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -1265,6 +1317,9 @@ packages: resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} engines: {node: '>= 14'} + pako@2.1.0: + resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -1289,6 +1344,9 @@ packages: pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1351,6 +1409,9 @@ packages: quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + raf@3.4.1: + resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -1367,6 +1428,9 @@ packages: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -1382,6 +1446,10 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + rgbcolor@1.0.1: + resolution: {integrity: sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==} + engines: {node: '>= 0.8.15'} + rollup@4.59.0: resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -1461,6 +1529,10 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + stackblur-canvas@2.7.0: + resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==} + engines: {node: '>=0.1.14'} + statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} @@ -1483,6 +1555,10 @@ packages: strip-literal@3.1.0: resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + svg-pathdata@6.0.3: + resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==} + engines: {node: '>=12.0.0'} + tar-fs@3.1.1: resolution: {integrity: sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==} @@ -1495,6 +1571,9 @@ packages: text-decoder@1.2.7: resolution: {integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==} + text-segmentation@1.0.3: + resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} @@ -1574,6 +1653,9 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + utrie@1.0.2: + resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==} + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -1715,6 +1797,8 @@ snapshots: dependencies: '@babel/types': 7.29.0 + '@babel/runtime@7.29.2': {} + '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 @@ -2045,6 +2129,14 @@ snapshots: dependencies: undici-types: 7.16.0 + '@types/pako@2.0.4': {} + + '@types/raf@3.4.3': + optional: true + + '@types/trusted-types@2.0.7': + optional: true + '@types/web-bluetooth@0.0.20': {} '@types/yauzl@2.10.3': @@ -2250,6 +2342,8 @@ snapshots: dependencies: bare-path: 3.0.0 + base64-arraybuffer@1.0.2: {} + basic-ftp@5.2.0: {} body-parser@1.20.4: @@ -2290,6 +2384,18 @@ snapshots: callsites@3.1.0: {} + canvg@3.0.11: + dependencies: + '@babel/runtime': 7.29.2 + '@types/raf': 3.4.3 + core-js: 3.49.0 + raf: 3.4.1 + regenerator-runtime: 0.13.11 + rgbcolor: 1.0.1 + stackblur-canvas: 2.7.0 + svg-pathdata: 6.0.3 + optional: true + chokidar@4.0.3: dependencies: readdirp: 4.1.2 @@ -2334,6 +2440,9 @@ snapshots: cookie@0.7.2: {} + core-js@3.49.0: + optional: true + cosmiconfig@9.0.1(typescript@5.9.3): dependencies: env-paths: 2.2.1 @@ -2343,6 +2452,10 @@ snapshots: optionalDependencies: typescript: 5.9.3 + css-line-break@2.1.0: + dependencies: + utrie: 1.0.2 + csstype@3.2.3: {} data-uri-to-buffer@6.0.2: {} @@ -2374,6 +2487,10 @@ snapshots: devtools-protocol@0.0.1566079: {} + dompurify@3.3.3: + optionalDependencies: + '@types/trusted-types': 2.0.7 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -2551,6 +2668,12 @@ snapshots: fast-fifo@1.3.2: {} + fast-png@6.4.0: + dependencies: + '@types/pako': 2.0.4 + iobuffer: 5.4.0 + pako: 2.1.0 + fast-uri@3.1.0: {} fd-slicer@1.1.0: @@ -2561,6 +2684,8 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fflate@0.8.2: {} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -2641,6 +2766,17 @@ snapshots: dependencies: function-bind: 1.1.2 + html2canvas@1.4.1: + dependencies: + css-line-break: 2.1.0 + text-segmentation: 1.0.3 + + html2pdf.js@0.14.0: + dependencies: + dompurify: 3.3.3 + html2canvas: 1.4.1 + jspdf: 4.2.1 + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -2696,6 +2832,8 @@ snapshots: inherits@2.0.4: {} + iobuffer@5.4.0: {} + ip-address@10.1.0: {} ipaddr.js@1.9.1: {} @@ -2730,6 +2868,17 @@ snapshots: json-schema-traverse@1.0.0: {} + jspdf@4.2.1: + dependencies: + '@babel/runtime': 7.29.2 + fast-png: 6.4.0 + fflate: 0.8.2 + optionalDependencies: + canvg: 3.0.11 + core-js: 3.49.0 + dompurify: 3.3.3 + html2canvas: 1.4.1 + lines-and-columns@1.2.4: {} local-pkg@1.1.2: @@ -2834,6 +2983,8 @@ snapshots: degenerator: 5.0.1 netmask: 2.0.2 + pako@2.1.0: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -2855,6 +3006,9 @@ snapshots: pend@1.2.0: {} + performance-now@2.1.0: + optional: true + picocolors@1.1.1: {} picomatch@2.3.1: @@ -2956,6 +3110,11 @@ snapshots: quansync@0.2.11: {} + raf@3.4.1: + dependencies: + performance-now: 2.1.0 + optional: true + range-parser@1.2.1: {} raw-body@2.5.3: @@ -2969,6 +3128,9 @@ snapshots: readdirp@5.0.0: {} + regenerator-runtime@0.13.11: + optional: true + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -2978,6 +3140,9 @@ snapshots: resolve-from@4.0.0: {} + rgbcolor@1.0.1: + optional: true + rollup@4.59.0: dependencies: '@types/estree': 1.0.8 @@ -3116,6 +3281,9 @@ snapshots: source-map@0.6.1: optional: true + stackblur-canvas@2.7.0: + optional: true + statuses@2.0.2: {} stoppable@1.1.0: {} @@ -3143,6 +3311,9 @@ snapshots: dependencies: js-tokens: 9.0.1 + svg-pathdata@6.0.3: + optional: true + tar-fs@3.1.1: dependencies: pump: 3.0.4 @@ -3179,6 +3350,10 @@ snapshots: transitivePeerDependencies: - react-native-b4a + text-segmentation@1.0.3: + dependencies: + utrie: 1.0.2 + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) @@ -3265,6 +3440,10 @@ snapshots: utils-merge@1.0.1: {} + utrie@1.0.2: + dependencies: + base64-arraybuffer: 1.0.2 + vary@1.1.2: {} vite@7.3.1(@types/node@24.11.0)(sass@1.97.3): diff --git a/src/api/resume.ts b/src/api/resume.ts new file mode 100644 index 0000000..29e7027 --- /dev/null +++ b/src/api/resume.ts @@ -0,0 +1,372 @@ +import request from '@/utils/request' +import type { ApiResult } from '@/api/auth' + +// ==================== 简历列表相关 ==================== + +/** 时间戳结构(Instant) */ +export interface InstantTime { + /** 秒级时间戳 */ + seconds?: number + /** 纳秒部分 */ + nanos?: number +} + +/** 简历列表项 */ +export interface ResumeListItem { + /** 简历 ID(字符串,避免大整数精度丢失) */ + id?: string + /** 简历名称 */ + resumeName?: string + /** 目标岗位 */ + targetPosition?: string + /** 是否默认简历 0=否 1=是 */ + isDefault?: number + /** 简历修改时间 */ + updateTime?: InstantTime + /** 简历创建时间 */ + createTime?: InstantTime +} + +/** + * 获取简历列表 + * GET /resume/list + */ +export function fetchResumeList() { + return request.get>('/resume/list') +} + +// ==================== 描述段落(通用) ==================== + +/** 描述段落 */ +export interface DescriptionParagraph { + /** 段落标识,前端生成的短ID */ + id?: string + /** 段落文本内容 */ + text?: string +} + +// ==================== 简历主表 ==================== + +/** 简历主表数据 */ +export interface ResumeMainData { + /** 简历 ID(字符串,避免大整数精度丢失) */ + id?: string + /** 简历名称 */ + resumeName?: string + /** 目标岗位 */ + targetPosition?: string + /** 是否默认简历 0=否 1=是 */ + isDefault?: number + /** 头像URL */ + avatarUrl?: string + /** 真实姓名 */ + name?: string + /** 邮箱 */ + email?: string + /** 手机号码 */ + mobileNumber?: string + /** 所在城市 */ + city?: string + /** 微信号 */ + wechatNumber?: string + /** 作品集链接 */ + portfolioUrl?: string + /** 技能标签列表 */ + skills?: string[] + /** 证书标签列表 */ + certificates?: string[] + /** 个人概述 */ + summary?: string +} + +/** + * 查询简历主表 + * GET /resume?resumeId=xxx + */ +export function fetchResumeMain(resumeId: string) { + return request.get>('/resume', { + params: { resumeId }, + }) +} + +// ==================== 教育经历 ==================== + +/** 教育经历项 */ +export interface ResumeEducation { + /** ID(字符串,避免大整数精度丢失) */ + id?: string + /** 学校名称 */ + school?: string + /** 专业 */ + major?: string + /** 学历:大专/本科/硕士/博士 */ + degree?: string + /** 学习形式:全日制/非全日制 */ + studyType?: string + /** 开始时间,格式:2023.09 */ + startDate?: string + /** 结束时间,格式:2024.06 */ + endDate?: string + /** 描述段落 */ + description?: DescriptionParagraph[] +} + +/** + * 查询简历的教育经历列表 + * GET /resume/education?resumeId=xxx + */ +export function fetchResumeEducation(resumeId: string) { + return request.get>('/resume/education', { + params: { resumeId }, + }) +} + +// ==================== 工作经历 ==================== + +/** 工作经历项 */ +export interface ResumeWork { + /** ID(字符串,避免大整数精度丢失) */ + id?: string + /** 公司名称 */ + companyName?: string + /** 职位 */ + position?: string + /** 开始时间 */ + startDate?: string + /** 结束时间 */ + endDate?: string + /** 描述段落 */ + description?: DescriptionParagraph[] +} + +/** + * 查询简历的工作经历列表 + * GET /resume/work?resumeId=xxx + */ +export function fetchResumeWork(resumeId: string) { + return request.get>('/resume/work', { + params: { resumeId }, + }) +} + +// ==================== 实习经历 ==================== + +/** 实习经历项 */ +export interface ResumeInternship { + /** ID(字符串,避免大整数精度丢失) */ + id?: string + /** 公司名称 */ + companyName?: string + /** 职位 */ + position?: string + /** 开始时间 */ + startDate?: string + /** 结束时间 */ + endDate?: string + /** 描述段落 */ + description?: DescriptionParagraph[] +} + +/** + * 查询简历的实习经历列表 + * GET /resume/internship?resumeId=xxx + */ +export function fetchResumeInternship(resumeId: string) { + return request.get>('/resume/internship', { + params: { resumeId }, + }) +} + +// ==================== 项目经历 ==================== + +/** 项目经历项 */ +export interface ResumeProject { + /** ID(字符串,避免大整数精度丢失) */ + id?: string + /** 所属公司 */ + companyName?: string + /** 项目名称 */ + projectName?: string + /** 担任角色 */ + role?: string + /** 开始时间 */ + startDate?: string + /** 结束时间 */ + endDate?: string + /** 描述段落 */ + description?: DescriptionParagraph[] +} + +/** + * 查询简历的项目经历列表 + * GET /resume/project?resumeId=xxx + */ +export function fetchResumeProject(resumeId: string) { + return request.get>('/resume/project', { + params: { resumeId }, + }) +} + +// ==================== 竞赛经历 ==================== + +/** 竞赛经历项 */ +export interface ResumeCompetition { + /** ID(字符串,避免大整数精度丢失) */ + id?: string + /** 竞赛名称 */ + competitionName?: string + /** 获奖情况 */ + award?: string + /** 获奖时间,格式:2023.07 */ + awardDate?: string + /** 描述段落 */ + description?: DescriptionParagraph[] +} + +/** + * 查询简历的竞赛经历列表 + * GET /resume/competition?resumeId=xxx + */ +export function fetchResumeCompetition(resumeId: string) { + return request.get>('/resume/competition', { + params: { resumeId }, + }) +} + +// ==================== 简历保存相关 ==================== + +/** 保存简历主表参数 */ +export interface SaveResumeMainParams { + /** 简历 ID */ + resumeId: string + /** 简历名称 */ + resumeName?: string + /** 目标岗位 */ + targetPosition?: string + /** 真实姓名 */ + name?: string + /** 邮箱 */ + email?: string + /** 手机号码 */ + mobileNumber?: string + /** 所在城市 */ + city?: string + /** 微信号 */ + wechatNumber?: string + /** 作品集链接 */ + portfolioUrl?: string + /** 技能标签列表 */ + skills?: string[] + /** 证书标签列表 */ + certificates?: string[] + /** 个人概述 */ + summary?: string +} + +/** + * 保存/更新简历主表信息 + * POST /resume + */ +export function saveResumeMain(data: SaveResumeMainParams) { + return request.post('/resume', data) +} + +/** 保存简历教育经历参数(单条) */ +export interface SaveResumeEducationItem { + /** 学校名称 */ + school?: string + /** 专业 */ + major?: string + /** 学历 */ + degree?: string + /** 学习形式 */ + studyType?: string + /** 开始时间 */ + startDate?: string + /** 结束时间 */ + endDate?: string + /** 描述段落 */ + description?: DescriptionParagraph[] +} + +/** + * 保存简历教育经历(全量覆盖) + * POST /resume/education + */ +export function saveResumeEducation(resumeId: string, data: SaveResumeEducationItem[]) { + return request.post('/resume/education', { resumeId, items: data }) +} + +/** 保存简历工作经历参数(单条) */ +export interface SaveResumeWorkItem { + /** 公司名称 */ + companyName?: string + /** 职位 */ + position?: string + /** 开始时间 */ + startDate?: string + /** 结束时间 */ + endDate?: string + /** 描述段落 */ + description?: DescriptionParagraph[] +} + +/** + * 保存简历工作经历(全量覆盖) + * POST /resume/work + */ +export function saveResumeWork(resumeId: string, data: SaveResumeWorkItem[]) { + return request.post('/resume/work', { resumeId, items: data }) +} + +/** + * 保存简历实习经历(全量覆盖) + * POST /resume/internship + */ +export function saveResumeInternship(resumeId: string, data: SaveResumeWorkItem[]) { + return request.post('/resume/internship', { resumeId, items: data }) +} + +/** 保存简历项目经历参数(单条) */ +export interface SaveResumeProjectItem { + /** 项目名称 */ + projectName?: string + /** 所属公司 */ + companyName?: string + /** 担任角色 */ + role?: string + /** 开始时间 */ + startDate?: string + /** 结束时间 */ + endDate?: string + /** 描述段落 */ + description?: DescriptionParagraph[] +} + +/** + * 保存简历项目经历(全量覆盖) + * POST /resume/project + */ +export function saveResumeProject(resumeId: string, data: SaveResumeProjectItem[]) { + return request.post('/resume/project', { resumeId, items: data }) +} + +/** 保存简历竞赛经历参数(单条) */ +export interface SaveResumeCompetitionItem { + /** 竞赛名称 */ + competitionName?: string + /** 获奖情况 */ + award?: string + /** 获奖时间 */ + awardDate?: string + /** 描述段落 */ + description?: DescriptionParagraph[] +} + +/** + * 保存简历竞赛经历(全量覆盖) + * POST /resume/competition + */ +export function saveResumeCompetition(resumeId: string, data: SaveResumeCompetitionItem[]) { + return request.post('/resume/competition', { resumeId, items: data }) +} diff --git a/src/assets/images/home/avatar-temporary.png b/src/assets/images/home/avatar-temporary.png new file mode 100644 index 0000000000000000000000000000000000000000..c6e4b19ebf344a5de0ae1b2d725990fd98d7ab7b GIT binary patch literal 37590 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 z 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­GEb$Apba_=Py~QhV^<4= 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 import { ref, computed, nextTick } from 'vue' +import html2pdf from 'html2pdf.js' import JobResumeTemplate from '@/components/JobResumeTemplate.vue' import type { ResumeTemplateData } from '@/components/JobResumeTemplate.vue' import { fetchProfile, fetchEducation, fetchWork, fetchInternship, fetchProject, fetchCompetition } from '@/api/profile' @@ -588,10 +589,82 @@ function toggleDownloadMenu() { } /** 处理下载(PDF/Word) */ -function handleDownload(type: 'pdf' | 'word') { +async function handleDownload(type: 'pdf' | 'word') { showDownloadMenu.value = false - // TODO: 实现简历HTML转PDF/Word下载 - console.log(`[下载简历] 格式: ${type}`) + + if (type === 'pdf') { + // 通过 JobResumeTemplate 组件暴露的 resumeRef 获取简历DOM + const element = resumeTemplateRef.value?.resumeRef + if (!element) { + console.error('[下载简历] 无法获取简历模板DOM') + return + } + + // html2pdf 配置选项 + const options = { + margin: [10, 10, 10, 10] as [number, number, number, number], + filename: `${resumeTemplateData.value.name || '简历'}_定制简历.pdf`, + image: { type: 'jpeg', quality: 0.98 }, + html2canvas: { scale: 2, useCORS: true, logging: false }, + jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' as const }, + } + + try { + await html2pdf().set(options).from(element).save() + } catch (err) { + console.error('[下载简历] PDF生成失败', err) + } + } else { + // 将简历HTML转为Word文档并下载(使用HTML格式的.doc文件,Word可正常打开) + const element = resumeTemplateRef.value?.resumeRef + if (!element) { + console.error('[下载简历] 无法获取简历模板DOM') + return + } + + try { + // 获取页面样式表内容 + const styleSheets = Array.from(document.styleSheets) + let cssText = '' + styleSheets.forEach((sheet) => { + try { + Array.from(sheet.cssRules).forEach((rule) => { + cssText += rule.cssText + '\n' + }) + } catch { + // 跨域样式表无法读取,跳过 + } + }) + + // 组装完整HTML文档(Word可识别的HTML格式) + const fullHtml = ` + + + + + + + + ${element.outerHTML} + + ` + + // 生成Blob并触发下载 + const blob = new Blob([fullHtml], { type: 'application/msword' }) + const fileName = `${resumeTemplateData.value.name || '简历'}_定制简历.doc` + const link = document.createElement('a') + link.href = URL.createObjectURL(blob) + link.download = fileName + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + URL.revokeObjectURL(link.href) + } catch (err) { + console.error('[下载简历] Word生成失败', err) + } + } } /** 立即去投递 */ diff --git a/src/components/ProfileEditDrawer.vue b/src/components/ProfileEditDrawer.vue index 56b73da..76b28f4 100644 --- a/src/components/ProfileEditDrawer.vue +++ b/src/components/ProfileEditDrawer.vue @@ -109,11 +109,9 @@ *学历类型
- + -
@@ -121,13 +119,9 @@ *学历
- + -
@@ -742,6 +736,19 @@ + + + diff --git a/vite.config.ts b/vite.config.ts index b817698..f3f7f21 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -40,6 +40,11 @@ export default defineConfig({ target: 'http://127.0.0.1:8080', changeOrigin: true, }, + '/ai-api': { + target: 'http://192.168.31.133:8000', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/ai-api/, ''), + }, }, }, css: {