internshipRecord.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. <template>
  2. <view class="defaultBgc">
  3. <uni-segmented-control :current="current" class="MiSans-Normal" :values="controlList" @clickItem="handleChange" styleType="text" activeColor="#00B760" style="background-color: #fff;"></uni-segmented-control>
  4. <scroll-view class="scrollBox defaultBgc" scroll-y="true" @scrolltolower="loadingMore" style="height: calc(100vh - 36px);">
  5. <view v-if="dataList.length">
  6. <uni-card v-for="(val, index) in dataList" :key="index" :is-shadow="true" :border='false' shadow="0px 0px 3px 1px rgba(0,0,0,0.1)">
  7. <!-- 企业信息 -->
  8. <view class="entInfoBox d-flex align-center ss-p-10 ss-p-l-20 ss-m-b-20">
  9. <image class="enterAvatar" :src="val.enterprise.logoUrl ? val.enterprise.logoUrl : 'https://minio.menduner.com/dev/cd7f5e26a239fb0ab335585e04c709b065f52832fc31539b3a5423224fc6d16c.png'"></image>
  10. <view class="ellipsis ss-m-l-20" style="flex: 1;">
  11. <view class="enterpriseName font-size-16 ellipsis">{{ formatName(val.enterprise.anotherName || val.enterprise.name) }}</view>
  12. <!-- <view class="ss-m-t-5">
  13. <span class="color-999">{{ val.enterprise?.industryName || '' }}</span>
  14. <span class="divider tag-gap1" v-if="val.enterprise?.industryName && val.enterprise?.scaleName"> | </span>
  15. <span class="color-999">{{ val.enterprise?.scaleName || '' }}</span>
  16. </view> -->
  17. </view>
  18. </view>
  19. <!-- 职位信息 -->
  20. <view class="list-shape ss-p-b-10" >
  21. <view class="titleBox my-5">
  22. <view class="job-name font-size-16" :style="{'max-width': !val.job.payFrom && !val.job.payTo ? '65vw' : '50vw'}">{{ formatName(val.job.name) }}</view>
  23. <span v-if="!val.job.payFrom && !val.job.payTo" class="salary-text">面议</span>
  24. <span v-else class="salary-text">{{ val.job.payFrom }}-{{ val.job.payTo }}{{ val.job.payName ? '/' + val.job.payName : '' }}</span>
  25. </view>
  26. <view style="font-size: 13px;" class="ss-m-t-10">
  27. <span class="tag-gap" style="color: #808080;">
  28. <span>{{ val.job.area?.str ?? '全国' }}</span>
  29. <span class="ss-m-x-10" v-if="val.job.eduName">|</span>
  30. <span>{{ val.job.eduName }}</span>
  31. <span class="ss-m-x-10" v-if="val.job.expName">|</span>
  32. <span>{{ val.job.expName }}</span>
  33. </span>
  34. </view>
  35. </view>
  36. <view>实习时间:{{ timesTampChange(val?.startTime, 'Y-M-D') }} 至 {{ timesTampChange(val?.endTime, 'Y-M-D') }}</view>
  37. <view v-if="current" style="text-align: right;">
  38. <view class="line ss-m-y-20"></view>
  39. <button @tap="handleToReport(val)" class="ss-m-r-10" type="warning" size="mini" style="color:#fff; backgroundColor:#fb8c00;borderColor:#fb8c00">实习报告</button>
  40. <button @tap="handleToCertificate(val)" class="ss-m-x-10" type="warning" size="mini" style="color:#fff; backgroundColor:#00b760;borderColor:#00b760">实习证书</button>
  41. <button @tap="preview(val?.recommendationLetter)" class="ss-m-l-10" type="warning" size="mini" style="color:#fff; backgroundColor:#00897b;borderColor:#00897b">企业推荐信</button>
  42. </view>
  43. <!-- 等待中 -->
  44. <view v-if="!current && !val.internshipEnterprise" style="text-align: right;">
  45. <view class="line ss-m-y-20"></view>
  46. <button @tap.stop="handleReport(val)" class="ss-m-l-10" type="warning" size="mini" style="color:#fff; backgroundColor:#00897b;borderColor:#00897b">上报为实习企业</button>
  47. </view>
  48. </uni-card>
  49. <uni-load-more :status="more" />
  50. </view>
  51. <view v-else class="nodata-img-parent">
  52. <image src="https://minio.menduner.com/dev/bb43df1dc91945e05ee93da76e49b34f87b0d10203eb76c20e2d4999a13b9a0a.png" mode="widthFix" style="width: 100vw;height: 100vh;"></image>
  53. </view>
  54. </scroll-view>
  55. <!-- 确认框 -->
  56. <uni-popup ref="confirmRef" type="dialog">
  57. <uni-popup-dialog
  58. type="warn"
  59. cancelText="取消"
  60. confirmText="确认"
  61. title="系统提示"
  62. content="是否确定上报为实习企业?"
  63. @confirm="handleConfirm"
  64. ></uni-popup-dialog>
  65. </uni-popup>
  66. </view>
  67. </template>
  68. <script setup>
  69. import { ref } from 'vue'
  70. import { getDict } from '@/hooks/useDictionaries'
  71. import { getStudentPage } from '@/api/student'
  72. import { formatName } from '@/utils/getText'
  73. import { timesTampChange } from '@/utils/date'
  74. import { dealDictObjData } from '@/utils/position'
  75. import { preview } from '@/utils/preview'
  76. import { reportStudentPracticeEnterprise } from '@/api/student'
  77. const more = ref('more')
  78. const current = ref(0)
  79. const query = ref({
  80. pageNo: 1,
  81. pageSize: 10
  82. })
  83. const total = ref(0)
  84. const dataList = ref([])
  85. const getData = async () => {
  86. try {
  87. const params = {
  88. studentProcessStatus: tabList.value[current.value]?.value,
  89. status: 1,
  90. ...query.value
  91. }
  92. if (!params?.status) return
  93. const { data } = await getStudentPage(params)
  94. const list = data?.list?.length && data.list || []
  95. list.forEach(e => {
  96. e.enterprise = dealDictObjData({}, e.enterprise)
  97. e.job = dealDictObjData({}, e.job)
  98. })
  99. //
  100. dataList.value = dataList.value.concat(list)
  101. total.value = data?.total || 0
  102. more.value = dataList.value?.length === total.value ? 'noMore' : 'more'
  103. } catch (error) {
  104. query.pageNo--
  105. more.value = 'more'
  106. }
  107. }
  108. const handleChange = (e) => {
  109. current.value = e.currentIndex
  110. query.value.pageNo = 1
  111. dataList.value = []
  112. getData()
  113. }
  114. // 加载更多
  115. const loadingMore = () => {
  116. if (total.value <= 0) return
  117. more.value = 'loading'
  118. query.value.pageNo++
  119. getData()
  120. }
  121. const tabList = ref([])
  122. const controlList = ref([])
  123. const getTabList = async () => {
  124. const { data } = await getDict('student_practice_status')
  125. if (data.code !== 0) {
  126. return
  127. }
  128. tabList.value = data?.data?.length && data.data || []
  129. controlList.value = tabList.value.map(e => e.label) || []
  130. if (tabList.value?.length) getData()
  131. }
  132. getTabList()
  133. // 实习报告
  134. const handleToReport = (val) => {
  135. uni.navigateTo({ url: `/pagesA/student/internshipReport?enterpriseId=${val?.enterprise?.id}` })
  136. }
  137. // 查看证书详情
  138. const handleToCertificate = (val) => {
  139. const itemData = JSON.stringify({
  140. student: { schoolName: formatName(val?.student?.schoolInfo?.name), majorName: val?.student?.major?.nameCn },
  141. person: { name: val?.person?.name },
  142. enterprise: { anotherName: formatName(val?.enterprise?.anotherName || val?.enterprise?.name) },
  143. startTime: val?.startTime,
  144. endTime: val?.endTime,
  145. evaluate: val?.evaluate,
  146. certificate: val?.certificate,
  147. createTime: val?.createTime
  148. })
  149. uni.navigateTo({ url: `/pagesA/student/certificateDetail?itemData=${itemData}` })
  150. }
  151. const handleConfirm = async() => {
  152. try {
  153. const enterpriseId = handleVal.value?.enterprise?.id
  154. const jobId = handleVal.value?.job?.id
  155. await reportStudentPracticeEnterprise(enterpriseId, jobId)
  156. uni.showToast({ title: '上报成功', icon: 'success' })
  157. } catch (error) {
  158. uni.showToast({ title: error?.msg || error, icon: 'none' })
  159. } finally {
  160. confirmRef.value.close()
  161. query.value.pageNo = 1
  162. dataList.value = []
  163. getData()
  164. }
  165. }
  166. const confirmRef = ref()
  167. const handleVal = ref('')
  168. // 上报为实习企业
  169. const handleReport = (val) => {
  170. if (!val?.enterprise?.id || !val?.job?.id) uni.showToast({ title: '企业或职位信息错误', icon: 'none' })
  171. handleVal.value = val
  172. confirmRef.value.open()
  173. }
  174. </script>
  175. <style scoped lang="scss">
  176. :deep(.segmented-control) {
  177. background-color: #fff !important;
  178. }
  179. .enterpriseName {
  180. color: #0E100F;
  181. // font-weight: 700;
  182. }
  183. .enterAvatar {
  184. width: 25px;
  185. height: 25px;
  186. // border-radius: 50%;
  187. margin: auto;
  188. }
  189. .line {
  190. border-top: 1px solid #ccc;
  191. }
  192. .list-shape {
  193. background-color: #fff;
  194. border-radius: 12px 12px 0 0;
  195. .titleBox {
  196. display: flex;
  197. align-items: center;
  198. justify-content: space-between;
  199. }
  200. }
  201. .salary-text {
  202. float: right;
  203. font-size: 15px;
  204. color: #00B760;
  205. font-weight: 700;
  206. }
  207. .job-name {
  208. font-size: 30rpx;
  209. // font-weight: 700;
  210. color: #0E100F;
  211. overflow: hidden;
  212. white-space: nowrap;
  213. text-overflow: ellipsis;
  214. }
  215. .ellipsis {
  216. white-space: nowrap;
  217. text-overflow: ellipsis;
  218. overflow: hidden;
  219. }
  220. .entInfoBox {
  221. background: linear-gradient(90deg, #f5fcfc, #fcfbfa);
  222. }
  223. </style>