|
@@ -94,21 +94,29 @@
|
|
|
|
|
|
<!-- 选择简历 -->
|
|
|
<selectResumeDialog v-model="showResume" :list="resumeList" @submit="handleSubmit" @close="handleClose"></selectResumeDialog>
|
|
|
- <!-- 复制分享链接 -->
|
|
|
+
|
|
|
+ <!-- 职位分享 -->
|
|
|
<Dialog
|
|
|
:visible="shareDialog" :widthType="2" :footer="false" titleClass="text-h6"
|
|
|
:title="$t('position.rewardsShared')"
|
|
|
@close="shareDialog = false"
|
|
|
>
|
|
|
<div>
|
|
|
- <div class="mb-3">方式一:生成图片并下载</div>
|
|
|
- <v-btn color="primary" variant="outlined" @click="generateAndDownloadImage">点击生成职位详情图片并下载</v-btn>
|
|
|
+ <div class="mb-3">方式一:保存图片分享给好友</div>
|
|
|
+ <div class="d-flex align-center flex-column">
|
|
|
+ <v-img :src="previewSrc" width="200" height="250"></v-img>
|
|
|
+ <div>
|
|
|
+ <v-btn color="primary" variant="outlined" prepend-icon="mdi-eye-outline" @click="showPreview = true">预览</v-btn>
|
|
|
+ <v-btn class="ml-3" color="primary" variant="outlined" prepend-icon="mdi-arrow-down-bold-box-outline" @click="handleDownloadImage">保存到本地</v-btn>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div class="mt-10" v-if="getToken()">
|
|
|
+ <div class="mt-10">
|
|
|
<div class="mb-3">方式二:复制以下链接分享给好友</div>
|
|
|
<div class="pa-4" style="background-color: #f0f0f0; border-radius: 8px;">{{ shareUrlTxt }}</div>
|
|
|
- <v-btn v-if="!getToken()" class="mt-1" color="warning" variant="text">您还未登录,登录后分享可享受分享有礼活动!</v-btn>
|
|
|
- <v-btn class="mt-4 ml-3" color="primary" variant="outlined" v-clipboard="() => shareUrlTxt" @click="copyText">点击复制分享链接</v-btn>
|
|
|
+ <div class="text-center">
|
|
|
+ <v-btn class="mt-5 ml-3" color="primary" variant="outlined" v-clipboard="() => shareUrlTxt" @click="copyText">点击复制分享链接</v-btn>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<template #footer>
|
|
|
<v-divider></v-divider>
|
|
@@ -117,17 +125,21 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
</Dialog>
|
|
|
+ <PreviewImg v-if="showPreview" :list="[previewSrc]" @close="showPreview = false" :isImage="true"></PreviewImg>
|
|
|
|
|
|
<Loading :visible="loading"></Loading>
|
|
|
<div style="position: absolute; left: -9999px; bottom: 0">
|
|
|
<PosterPage :jobId="id" ref="share"></PosterPage>
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- 快速登录 -->
|
|
|
+ <login-page v-if="showLogin" @loginSuccess="loginSuccess" @close="loginClose"></login-page>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { commissionCalculation } from '@/utils/position'
|
|
|
defineOptions({ name: 'position-details' })
|
|
|
+import { commissionCalculation } from '@/utils/position'
|
|
|
import { computed, ref } from 'vue'
|
|
|
import { useRouter } from 'vue-router'
|
|
|
import { timesTampChange } from '@/utils/date'
|
|
@@ -145,64 +157,57 @@ import { prologue, defaultText } from '@/hooks/web/useIM'
|
|
|
import { getUserAvatar } from '@/utils/avatar'
|
|
|
import PosterPage from './poster.vue'
|
|
|
import html2canvas from 'html2canvas'
|
|
|
+import { downloadBase64, DPR } from '@/utils'
|
|
|
+import loginPage from '@/views/common/loginDialog.vue'
|
|
|
|
|
|
const { t } = useI18n()
|
|
|
const router = useRouter()
|
|
|
const { id } = router.currentRoute.value.params
|
|
|
const delivery = ref(false) // 是否已投递简历
|
|
|
const loading = ref(false)
|
|
|
-
|
|
|
-const DPR = () => {
|
|
|
- // 获取设备dpi
|
|
|
- if (window.devicePixelRatio && window.devicePixelRatio > 1) {
|
|
|
- return window.devicePixelRatio * 2
|
|
|
- }
|
|
|
- // 直接返回高像素比
|
|
|
- return 8
|
|
|
-}
|
|
|
-
|
|
|
-const downloadBase64 = (content, fileName) => {
|
|
|
- const base64ToBlob = function (code) {
|
|
|
- let parts = code.split(';base64,')
|
|
|
- let contentType = parts[0].split(':')[1]
|
|
|
- let raw = window.atob(parts[1])
|
|
|
- let rawLength = raw.length
|
|
|
- let uInt8Array = new Uint8Array(rawLength)
|
|
|
- for (let i = 0; i < rawLength; ++i) {
|
|
|
- uInt8Array[i] = raw.charCodeAt(i)
|
|
|
- }
|
|
|
-
|
|
|
- return new Blob([uInt8Array], {
|
|
|
- type: contentType
|
|
|
- })
|
|
|
- }
|
|
|
- let aLink = document.createElement('a')
|
|
|
- let blob = base64ToBlob(content)
|
|
|
- aLink.download = fileName + '.png'
|
|
|
- aLink.href = URL.createObjectURL(blob)
|
|
|
- aLink.click()
|
|
|
- loading.value = false
|
|
|
-}
|
|
|
+const showLogin = ref(false)
|
|
|
+const previewSrc = ref('')
|
|
|
+const showPreview = ref(false)
|
|
|
|
|
|
const share = ref()
|
|
|
// 生成图片
|
|
|
-const generateAndDownloadImage = async () => {
|
|
|
- if (!share.value) {
|
|
|
- return
|
|
|
- }
|
|
|
+const generateAndDownloadImage = async () => {
|
|
|
+ if (!share.value) return
|
|
|
loading.value = true
|
|
|
- shareDialog.value = false
|
|
|
try {
|
|
|
const canvas = await html2canvas(share.value.$el, { scale: DPR(), useCORS: true })
|
|
|
const image = canvas.toDataURL().replace(/^data:image\/(png|jpg);base64,/, '')
|
|
|
- const base64img = `data:image/png;base64,${image}`
|
|
|
- const { name, areaName, payFrom, payTo } = info.value
|
|
|
- downloadBase64(base64img, `${name}_${areaName}_${payFrom}-${payTo}-${positionInfo.value.payName}`)
|
|
|
+ previewSrc.value = `data:image/png;base64,${image}`
|
|
|
+ loading.value = false
|
|
|
} catch (error) {
|
|
|
console.error('Error generating image:', error)
|
|
|
Snackbar.error('图片生成失败')
|
|
|
}
|
|
|
-}
|
|
|
+}
|
|
|
+
|
|
|
+// 保存图片到本地
|
|
|
+const handleDownloadImage = () => {
|
|
|
+ const { name, areaName, payFrom, payTo } = info.value
|
|
|
+ downloadBase64(previewSrc.value, `${name}_${areaName}_${payFrom}-${payTo}-${positionInfo.value.payName}`)
|
|
|
+}
|
|
|
+
|
|
|
+// 快速登录
|
|
|
+const loginSuccess = () => {
|
|
|
+ showLogin.value = false
|
|
|
+ Snackbar.success('登录成功')
|
|
|
+ userInfo.value = localStorage.getItem('userInfo') ? JSON.parse(localStorage.getItem('userInfo')) : {}
|
|
|
+ shareUrl.value = '/shareJob?' + new URLSearchParams({
|
|
|
+ jobId: id,
|
|
|
+ sharedById: userInfo.value?.id,
|
|
|
+ }).toString()
|
|
|
+ shareDialog.value = true
|
|
|
+ generateAndDownloadImage()
|
|
|
+}
|
|
|
+
|
|
|
+const loginClose = () => {
|
|
|
+ showLogin.value = false
|
|
|
+ Snackbar.warning('您已取消登录,无法分享职位给好友')
|
|
|
+}
|
|
|
|
|
|
// 相似职位
|
|
|
const similarList = ref([])
|
|
@@ -249,31 +254,29 @@ getCollectionStatus()
|
|
|
// 分享有礼
|
|
|
const shareDialog = ref(false)
|
|
|
const shareUrl = ref('')
|
|
|
-const userInfo = localStorage.getItem('userInfo') ? JSON.parse(localStorage.getItem('userInfo')) : {}
|
|
|
+const userInfo = ref(localStorage.getItem('userInfo') ? JSON.parse(localStorage.getItem('userInfo')) : {})
|
|
|
const handleShare = async () => {
|
|
|
// 分享链接携带参数: 用户id、职位id
|
|
|
- // if (!id || !userInfo.id) return
|
|
|
+ if (!getToken()) {
|
|
|
+ Snackbar.warning('您还未登录,请先登录后再试')
|
|
|
+ showLogin.value = true
|
|
|
+ return
|
|
|
+ }
|
|
|
+ generateAndDownloadImage()
|
|
|
shareUrl.value = '/shareJob?' + new URLSearchParams({
|
|
|
jobId: id,
|
|
|
- sharedById: userInfo?.id,
|
|
|
+ sharedById: userInfo.value?.id,
|
|
|
}).toString()
|
|
|
shareDialog.value = true
|
|
|
}
|
|
|
-// const openShareLink = () => { window.open(shareUrl.value) }
|
|
|
|
|
|
// 复制分享链接
|
|
|
const accessUrl = import.meta.env.VITE_ACCESS_BASE_URL
|
|
|
const shareUrlTxt = computed(() => {
|
|
|
return accessUrl + shareUrl.value
|
|
|
})
|
|
|
-const copyText = async () => {
|
|
|
+const copyText = () => {
|
|
|
Snackbar.success('复制成功')
|
|
|
- // try {
|
|
|
- // await navigator.clipboard.writeText(shareUrlTxt.value)
|
|
|
- // Snackbar.success('复制成功')
|
|
|
- // } catch (err) {
|
|
|
- // Snackbar.error('复制失败,请手动复制。')
|
|
|
- // }
|
|
|
}
|
|
|
|
|
|
// 收藏&取消收藏职位
|
|
@@ -335,6 +338,7 @@ const handleSubmit = async (val) =>{
|
|
|
}, 3000)
|
|
|
}
|
|
|
|
|
|
+// 沟通
|
|
|
const toDetails = async (info) => {
|
|
|
const userId = info.contact.userId
|
|
|
const enterpriseId = info.contact.enterpriseId
|
|
@@ -353,88 +357,5 @@ const toDetails = async (info) => {
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.banner {
|
|
|
- background-color: #fff;
|
|
|
- padding: 18px 0 20px;
|
|
|
-}
|
|
|
-.banner-title {
|
|
|
- line-height: 40px;
|
|
|
- font-size: 28px;
|
|
|
- font-weight: 600;
|
|
|
-}
|
|
|
-.banner-title h1 {
|
|
|
- display: inline-block;
|
|
|
- color: #37576c;
|
|
|
- font-size: 28px;
|
|
|
- margin-right: 30px;
|
|
|
- margin-top: 1px;
|
|
|
- max-width: 360px;
|
|
|
- vertical-align: middle;
|
|
|
-}
|
|
|
-.button-item {
|
|
|
- min-width: 110px;
|
|
|
- height: 36px
|
|
|
-}
|
|
|
-.salary {
|
|
|
- color: var(--v-error-base);
|
|
|
- line-height: 41px;
|
|
|
- font-weight: 600;
|
|
|
- height: auto;
|
|
|
- display: inline-block;
|
|
|
- vertical-align: sub;
|
|
|
-}
|
|
|
-.refresh-time {
|
|
|
- float: right;
|
|
|
- color: var(--color-666);
|
|
|
- font-size: 14px;
|
|
|
- line-height: 66px;
|
|
|
- vertical-align: sub;
|
|
|
-}
|
|
|
-.banner-tags span {
|
|
|
- font-weight: 600;
|
|
|
-}
|
|
|
-.radius {
|
|
|
- border-radius: 8px;
|
|
|
-}
|
|
|
-.content-left {
|
|
|
- width: 810px;
|
|
|
- padding: 20px 20px;
|
|
|
-}
|
|
|
-.content-right {
|
|
|
- flex: 1;
|
|
|
- padding: 20px 20px 20px 0;
|
|
|
-}
|
|
|
-.label-text {
|
|
|
- color: #7f7a7a;
|
|
|
- font-weight: 600;
|
|
|
-}
|
|
|
-.value-text {
|
|
|
- color: #000;
|
|
|
- font-weight: 400;
|
|
|
-}
|
|
|
-.requirement {
|
|
|
- white-space: pre-wrap;
|
|
|
- word-break: break-all;
|
|
|
- line-height: 28px;
|
|
|
- color: var(--color-333);
|
|
|
- font-size: 15px;
|
|
|
- text-align: justify;
|
|
|
- letter-spacing: 0;
|
|
|
-}
|
|
|
-.contact {
|
|
|
- height: 60px;
|
|
|
- line-height: 60px;
|
|
|
-}
|
|
|
-.contact-name {
|
|
|
- font-size: 20px;
|
|
|
- font-weight: 500;
|
|
|
- color: var(--color-222);
|
|
|
- line-height: 28px;
|
|
|
-}
|
|
|
-.contact-info {
|
|
|
- font-size: 15px;
|
|
|
- color: var(--color-666);
|
|
|
- line-height: 21px;
|
|
|
- margin-top: 8px;
|
|
|
-}
|
|
|
+@import '@/styles/recruit/position/index.scss'
|
|
|
</style>
|