|
@@ -1,43 +1,75 @@
|
|
|
<template>
|
|
|
- <v-tabs v-model="tab" align-tabs="start" color="primary" bg-color="#f7f8fa" @update:modelValue="handleChangeTab">
|
|
|
- <v-tab v-for="(k, index) in tabList" :key="index" :value="k.value">{{ k.label }}</v-tab>
|
|
|
- </v-tabs>
|
|
|
+ <div class="position-relative">
|
|
|
+ <v-tabs v-model="tab" align-tabs="start" color="primary" bg-color="#f7f8fa" @update:modelValue="handleChangeTab">
|
|
|
+ <v-tab v-for="(k, index) in tabList" :key="index" :value="k.value">{{ k.label }}</v-tab>
|
|
|
+ </v-tabs>
|
|
|
|
|
|
- <div v-if="items?.length">
|
|
|
- <ItemPage class="mt-3" :items="items" />
|
|
|
- <CtPagination
|
|
|
- v-if="total > 0"
|
|
|
- :total="total"
|
|
|
- :page="query.pageNo"
|
|
|
- :limit="query.pageSize"
|
|
|
- @handleChange="handleChangePage"
|
|
|
- ></CtPagination>
|
|
|
+ <div v-if="items?.length">
|
|
|
+ <ItemPage class="mt-3" :items="items" @preview="handlePreview" />
|
|
|
+ <CtPagination
|
|
|
+ v-if="total > 0"
|
|
|
+ :total="total"
|
|
|
+ :page="query.pageNo"
|
|
|
+ :limit="query.pageSize"
|
|
|
+ @handleChange="handleChangePage"
|
|
|
+ ></CtPagination>
|
|
|
+ </div>
|
|
|
+ <Empty v-else :elevation="false" />
|
|
|
+
|
|
|
+ <!-- 生成实习证书 -->
|
|
|
+ <div class="position-absolute position-relative" style="left: -9999px; bottom: 0;" ref="share">
|
|
|
+ <img src="https://minio.citupro.com/dev/static/bgc.jpg" width="500" height="700" cover />
|
|
|
+ <div class="cer-introduce">
|
|
|
+ 兹有
|
|
|
+ <span class="cer-text">{{ itemData?.student?.schoolName }}</span>
|
|
|
+ <span class="cer-text">{{ itemData?.student?.majorName }}</span>
|
|
|
+ 专业<span class="cer-text">{{ itemData?.person?.name }}</span>
|
|
|
+ 同学于<span class="cer-text">{{ itemData?.startTime ? timesTampChange(itemData?.startTime, 'Y-M-D') : '' }}</span>
|
|
|
+ 至<span class="cer-text">{{ itemData?.endTime ? timesTampChange(itemData?.endTime, 'Y-M-D') : '' }}</span>
|
|
|
+ 在<span class="cer-text">{{ formatName(itemData?.enterprise?.anotherName || itemData?.enterprise?.name) }}</span>
|
|
|
+ 实习。
|
|
|
+ </div>
|
|
|
+ <div class="cer-comment">{{ itemData?.evaluate }}</div>
|
|
|
+ <div class="cer-prove">特此证明。</div>
|
|
|
+ <div class="cer-end">
|
|
|
+ <div>{{ itemData?.createTime ? timesTampChange(itemData?.createTime, 'Y-M-D') : '' }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <Empty v-else :elevation="false" />
|
|
|
+
|
|
|
+ <Loading :visible="showLoading"></Loading>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
// 实习企业
|
|
|
defineOptions({ name: 'PersonalCenterStudentInternshipCompany'})
|
|
|
import { ref, onMounted } from 'vue'
|
|
|
-import { getInternshipPage } from '@/api/recruit/personal/student.js'
|
|
|
+import { getStudentPracticePage } from '@/api/recruit/personal/student.js'
|
|
|
import ItemPage from './item.vue'
|
|
|
import { getDict } from '@/hooks/web/useDictionaries'
|
|
|
import { dealDictObjData } from '@/utils/position'
|
|
|
+import { usePersonCenterStore } from '@/store/personCenter'
|
|
|
+import { formatName } from '@/utils/getText'
|
|
|
+import { timesTampChange } from '@/utils/date'
|
|
|
+import Snackbar from '@/plugins/snackbar'
|
|
|
+import html2canvas from 'html2canvas'
|
|
|
+import { DPR } from '@/utils'
|
|
|
|
|
|
const tab = ref(0)
|
|
|
const tabList = ref([])
|
|
|
const items = ref([])
|
|
|
+const share = ref(null)
|
|
|
const total = ref(0)
|
|
|
const query = ref({
|
|
|
pageNo: 1,
|
|
|
pageSize: 10,
|
|
|
status: ''
|
|
|
})
|
|
|
+const itemData = ref({})
|
|
|
|
|
|
const getList = async () => {
|
|
|
query.value.status = tabList.value[tab.value]?.value
|
|
|
- const result = await getInternshipPage(query.value)
|
|
|
+ const result = await getStudentPracticePage(query.value)
|
|
|
items.value = result?.list.map(e => {
|
|
|
e.enterprise = dealDictObjData({}, e.enterprise)
|
|
|
e.job = dealDictObjData({}, e.job)
|
|
@@ -62,8 +94,74 @@ const handleChangePage = (page) => {
|
|
|
query.value.pageNo = page
|
|
|
getList()
|
|
|
}
|
|
|
+
|
|
|
+// 生成实习证书图片
|
|
|
+const showLoading = ref(false)
|
|
|
+const personCenterStore = usePersonCenterStore()
|
|
|
+const generateAndDownloadImage = async () => {
|
|
|
+ try {
|
|
|
+ const canvas = await html2canvas(share.value, { scale: DPR(), useCORS: true })
|
|
|
+ const image = canvas.toDataURL().replace(/^data:image\/(png|jpg);base64,/, '')
|
|
|
+
|
|
|
+ const fileName = `实习证书 - ${formatName(itemData.value?.enterpriseName)}`
|
|
|
+ personCenterStore.setPreviewData([`data:image/png;base64,${image}`], 0, fileName)
|
|
|
+ showLoading.value = false
|
|
|
+ } catch (error) {
|
|
|
+ console.error('图片生成失败', error)
|
|
|
+ Snackbar.warning('加载失败,请稍后重试')
|
|
|
+ showLoading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 实习证书预览
|
|
|
+const handlePreview = (item) => {
|
|
|
+ itemData.value = item
|
|
|
+ if (!share.value) return
|
|
|
+ showLoading.value = true
|
|
|
+ setTimeout(() => {
|
|
|
+ generateAndDownloadImage()
|
|
|
+ }, 1000)
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
-
|
|
|
+.cer-text{
|
|
|
+ text-decoration: underline;
|
|
|
+ margin: 0 3px;
|
|
|
+ font-weight: 700;
|
|
|
+}
|
|
|
+.cer-introduce{
|
|
|
+ width: 70%;
|
|
|
+ position: absolute;
|
|
|
+ top: 51%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%,-50%);
|
|
|
+ text-indent: 2em;
|
|
|
+}
|
|
|
+.cer-comment{
|
|
|
+ width: 70%;
|
|
|
+ position: absolute;
|
|
|
+ top: 68%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%,-50%);
|
|
|
+ text-indent: 2em;
|
|
|
+ display: -webkit-box;
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
+ -webkit-line-clamp: 3;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+}
|
|
|
+.cer-prove{
|
|
|
+ width: 70%;
|
|
|
+ position: absolute;
|
|
|
+ top: 82%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%,-50%);
|
|
|
+ text-indent: 2em;
|
|
|
+}
|
|
|
+.cer-end{
|
|
|
+ position: absolute;
|
|
|
+ top: 87%;
|
|
|
+ right: 16%;
|
|
|
+}
|
|
|
</style>
|