123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- <template>
- <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" :tab="tab" @preview="handlePreview" @refresh="handleChangePage(1)" />
- <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">{{ studentInfo?.schoolInfo?.name }}</span>
- <span class="cer-text">{{ studentInfo?.major?.nameCn }}</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>
- <Loading :visible="showLoading"></Loading>
- </template>
- <script setup>
- // 实习企业
- defineOptions({ name: 'PersonalCenterStudentInternshipCompany'})
- import { ref, onMounted } from 'vue'
- 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(1)
- const tabList = ref([])
- const items = ref([])
- const share = ref(null)
- const total = ref(0)
- const query = ref({
- pageNo: 1,
- pageSize: 10,
- status: '1'
- })
- const itemData = ref({})
- const studentInfo = ref(localStorage.getItem('studentInfo') ? JSON.parse(localStorage.getItem('studentInfo')) : {})
- const getList = async () => {
- query.value.studentProcessStatus = tabList.value[tab.value]?.value
- const result = await getStudentPracticePage(query.value)
- items.value = result?.list.map(e => {
- e.enterprise = dealDictObjData({}, e.enterprise)
- e.job = dealDictObjData({}, e.job)
- return e
- })
- total.value = result?.total || 0
- }
- onMounted(async () => {
- const { data } = await getDict('student_practice_status')
- tabList.value = data || []
- await getList()
- })
- const handleChangeTab = () => {
- items.value = []
- total.value = 0
- query.value.pageNo = 1
- getList()
- }
- 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>
|