Browse Source

信息填写完成度

lifanagju_citu 8 tháng trước cách đây
mục cha
commit
9e0bd4b62a

+ 16 - 13
src/components/ProgressBar/index.vue

@@ -1,21 +1,21 @@
 <!-- 进度条 -->
 <template>
-  <div class="pa-3 white-bgc">
-    <div>{{ props.label }}</div>
-    <div class="d-flex align-center cursor-pointer mt-1" @click="handleClick">
+  <div :class="{'pa-3': pa, 'd-flex': inlineDisplay, 'white-bgc': whiteBgc}">
+    <div :style="`font-size: ${props.fontSize || 13}px;`">{{ props.label }}</div>
+    <div class="d-flex align-center" :class="inlineDisplay ? 'ml-2' : 'mt-1'" style="flex: 1;">
       <v-progress-linear
         :bg-color="barBgColor"
-        :color="props.color"
-        :height="props.height"
-        min="0"
-        :max="props.total"
+        :color="props.barColor"
+        :height="props.barHeight"
         :model-value="props.num"
         :rounded="props.rounded"
+        :max="props.total"
+        min="0"
       ></v-progress-linear>
       <div
         v-if="props.total !== 0"
         class="ms-4 text-h7"
-        style="font-size: 13px;"
+        :style="`font-size: ${props.fontSize || 13}px; color: ${props.percentageColor || '#000'}`"
       >{{ Number.isInteger(props.num/props.total*100) ? (props.num/props.total*100) : (props.num/props.total*100).toFixed(2) }}%</div>
     </div>
   </div>
@@ -26,16 +26,19 @@ defineOptions({name: 'ProgressBar-index'})
 const props = defineProps({
   num: { type: Number, default: 1 },
   total: { type: Number, default: 2 },
-  height: { type: Number, default: 6 },
-  color: { type: String, default: 'var(--v-primary-base)' },
+  barHeight: { type: Number, default: 6 },
+  fontSize: { type: Number, default: 13 },
+  barColor: { type: String, default: 'var(--v-primary-base)' },
   barBgColor: { type: String, default: '#92aed9' },
+  percentageColor: { type: String, default: '#000' },
   rounded: { type: Boolean, default: true },
   label: { type: String, default: '简历完成度' },
-  list: { type: Array, default: () => [] },
+  // list: { type: Array, default: () => [] },
+  inlineDisplay: { type: Boolean, default: false },
+  whiteBgc: { type: Boolean, default: true },
+  pa: { type: Boolean, default: true },
 })
 
-const handleClick = () => {}
-
 </script>
 <style lang="scss" scoped>
 </style>

+ 66 - 14
src/views/recruit/enterprise/informationManagement/informationSettings.vue

@@ -1,15 +1,45 @@
 <!-- 企业信息设置 -->
 <template>
   <div>
+    <div v-if="completeNum !== tabList?.length" class="white-bgc mb-3">
+      <ProgressBar
+        label="企业信息填写完成度:"
+        :num="completeNum"
+        :total="tabList?.length"
+        :fontSize="14"
+        :inlineDisplay="true"
+        style="width: 350px;"
+      ></ProgressBar>
+    </div>
     <v-card class="card-box pa-5" style="min-height: 500px">
       <v-tabs v-model="tab" @update:model-value="handleTabClick" align-tabs="start" color="primary" bg-color="#f7f8fa">
-        <v-tab v-for="val in tabList" :key="val.value" :value="val.value">{{ val.label }}</v-tab>
+        <v-tab v-for="val in tabList" :key="val.value" :value="val.value" >
+          {{ val.label }}
+          <template v-slot:append>
+            <template v-if="val.status === false">
+              <v-icon color="orange">mdi-information-outline</v-icon>
+              <v-tooltip activator="parent" location="top">请完善{{ val.label }}</v-tooltip>
+            </template>
+          </template>
+        </v-tab>
       </v-tabs>
-      <v-window v-model="tab" class="mt-3">
+      <div class="mt-3">
+        <template v-for="item in tabList" :key="item.id">
+          <div v-show="item.value === tab">
+            <component
+              ref="tabRef"
+              class="mb-3"
+              :is="item.path"
+              @complete="complete"
+            />
+          </div>
+        </template>
+      </div>
+      <!-- <v-window v-model="tab" class="mt-3">
         <v-window-item :value="val.value" v-for="val in tabList" :key="val.value">
           <component :is="val.path" ref="tabRef"></component>
         </v-window-item>
-      </v-window>
+      </v-window> -->
     </v-card>
   </div>
 </template>
@@ -23,7 +53,8 @@ import welfareLabel from './informationSettingsComponents/welfareLabel.vue'
 import enterpriseLabel from './informationSettingsComponents/enterpriseLabel.vue'
 import businessInformation from './informationSettingsComponents/businessInformation.vue'
 import authentication from './informationSettingsComponents/authentication.vue'
-import { ref, watch } from 'vue'
+import ProgressBar from '@/components/ProgressBar'
+import { ref, shallowRef, watch } from 'vue'
 import { 
   useRoute, 
   // useRouter
@@ -34,17 +65,17 @@ const route = useRoute()
 // const router = useRouter()
 const { t } = useI18n()
 // tab
-const tabRef = ref()
+const tabRef = shallowRef()
 const tab = ref(1)
-const tabList = [
-  { label: t('enterprise.infoSetting.basicInfo'), value: 1, path: basicInfo },
-  { label: t('enterprise.infoSetting.enterpriseLogo'), value: 2, path: enterpriseLogo },
-  { label: t('enterprise.infoSetting.enterpriseAlbum'), value: 3, path: enterpriseAlbum },
-  { label: t('enterprise.infoSetting.welfareLabel'), value: 4, path: welfareLabel },
-  { label: t('enterprise.infoSetting.enterpriseLabel'), value: 7, path: enterpriseLabel },
-  { label: t('enterprise.infoSetting.businessInformation'), value: 5, path: businessInformation },
-  { label: t('setting.realNameAuthentication'), value: 6, path: authentication },
-]
+const tabList = ref([
+  { label: t('enterprise.infoSetting.basicInfo'), value: 1, path: basicInfo, id: 'basicInfo' },
+  { label: t('enterprise.infoSetting.enterpriseLogo'), value: 2, path: enterpriseLogo, id: 'enterpriseLogo' },
+  { label: t('enterprise.infoSetting.enterpriseAlbum'), value: 3, path: enterpriseAlbum, id: 'enterpriseAlbum' },
+  { label: t('enterprise.infoSetting.welfareLabel'), value: 4, path: welfareLabel, id: 'welfareLabel' },
+  { label: t('enterprise.infoSetting.enterpriseLabel'), value: 7, path: enterpriseLabel, id: 'enterpriseLabel' },
+  { label: t('enterprise.infoSetting.businessInformation'), value: 5, path: businessInformation, id: 'businessInformation' },
+  { label: t('setting.realNameAuthentication'), value: 6, path: authentication, id: 'authentication' },
+])
 
 watch(() => route?.query?.tabKey, (newVal) => { // newQuery, oldQuery
   if (newVal) tab.value = newVal - 0
@@ -57,7 +88,28 @@ const handleTabClick = () => {
   }
   // router.push(`${route.path}?tabKey=${tab.value.toString()}`)
 }
+
+const completeNum = ref(0)
+const complete = (val) => {
+  if (!val?.id) return
+  completeNum.value = 0
+  tabList.value.forEach(e => {
+    if (e.id === val.id) {
+      e.status = val.status || false
+    }
+    if (e.status) {
+      completeNum.value++
+    }
+  })
+}
 </script>
 
 <style scoped lang="scss">
+.topTip {
+  background-color: #f7f8fa;
+  color: #2f3640;
+  padding: 12px 20px;
+  margin: 10px 0 20px;
+  font-size: 14px;
+}
 </style>

+ 6 - 0
src/views/recruit/enterprise/informationManagement/informationSettingsComponents/authentication.vue

@@ -53,6 +53,7 @@ import { ref } from 'vue'
 import { isValidIdCard18, maskNumber } from '@/utils/validate'
 import { getEnterpriseAuth, saveEnterpriseAuth } from '@/api/recruit/enterprise/information'
 import Snackbar from '@/plugins/snackbar'
+const emit = defineEmits(['complete'])
 
 // 是否已实名
 const info = ref({})
@@ -108,6 +109,7 @@ const formItems = ref({
 
 const getData = async () => {
   const data = await getEnterpriseAuth()
+  emit('complete', { status: Boolean(data?.status === '1'), id: 'authentication' })
   if (!data) return authentication.value = false
   authentication.value = true
   info.value = data
@@ -136,6 +138,10 @@ const handleSave = async () => {
   query.value = {}
   getData()
 }
+
+defineExpose({
+  getData: getData()
+})
 </script>
 
 <style scoped lang="scss">

+ 7 - 0
src/views/recruit/enterprise/informationManagement/informationSettingsComponents/basicInfo.vue

@@ -40,6 +40,7 @@ import { getDict } from '@/hooks/web/useDictionaries'
 import { useI18n } from '@/hooks/web/useI18n'
 import industryTypeCard from '@/components/industryTypeCard'
 import Snackbar from '@/plugins/snackbar'
+const emit = defineEmits(['complete'])
 
 const { t } = useI18n()
 const CtFormRef = ref()
@@ -199,11 +200,13 @@ const statusInfo = computed(() => {
   return obj
 })
 
+let completeStatus = false
 // 获取基本信息
 const getBaseInfo = async () => {
   const data = await getEnterpriseBaseInfo()
   if (!data) return
   query.id = data.id
+  completeStatus = true
   formItems.value.options.forEach(item => {
     if (item.dictTypeName) {
       getDict(item.dictTypeName).then(({ data }) => {
@@ -215,7 +218,11 @@ const getBaseInfo = async () => {
     if (item.key === 'industryId') {
       item.value = industryList.value.find(e => e.id === data[item.key])?.nameCn
     } else item.value = data[item.key]
+    // 完成度展示
+    if (item.value === undefined || item.value === null || item.value === '') completeStatus = false
   })
+  // 完成度展示
+  emit('complete', { status: completeStatus, id: 'basicInfo' })
 }
 getBaseInfo()
 

+ 19 - 6
src/views/recruit/enterprise/informationManagement/informationSettingsComponents/businessInformation.vue

@@ -14,6 +14,7 @@ import { getEnterpriseBusiness, updateEnterpriseBusiness } from '@/api/enterpris
 import Snackbar from '@/plugins/snackbar'
 import { reactive, ref } from 'vue'
 import { getDict } from '@/hooks/web/useDictionaries'
+const emit = defineEmits(['complete'])
 
 defineOptions({name: 'informationSettingsComponents-businessInformation'})
 const formItems = ref({
@@ -165,14 +166,26 @@ const handleSave = async () => {
   getBaseInfo()
 }
 
+let completeStatus = false
 // 获取基本信息
 const getBaseInfo = async () => {
-  const data = await getEnterpriseBusiness()
-  if (!data) return
-  query.id = data.id
-  formItems.value.options.forEach(item => {
-    item.value = data[item.key]
-  })
+  try {
+    const data = await getEnterpriseBusiness()
+    if (!data) return
+    query.id = data.id
+    completeStatus = true
+    formItems.value.options.forEach(item => {
+      item.value = data[item.key]
+      // 完成度展示
+      if (item.key !== 'formerName') {
+        if (item.value === undefined || item.value === null || item.value === '') completeStatus = false
+      }
+    })
+    // 完成度展示
+    emit('complete', { status: completeStatus, id: 'businessInformation' })
+  } catch (error) {
+    emit('complete', { status: completeStatus, id: 'businessInformation' })
+  }
 }
 getBaseInfo()
 

+ 3 - 0
src/views/recruit/enterprise/informationManagement/informationSettingsComponents/enterpriseAlbum.vue

@@ -47,12 +47,15 @@ import { useI18n } from '@/hooks/web/useI18n'
 import { getEnterpriseBaseInfo, updateEnterpriseAlbum } from '@/api/enterprise'
 import Snackbar from '@/plugins/snackbar'
 import Confirm from '@/plugins/confirm'
+const emit = defineEmits(['complete'])
 
 const { t } = useI18n()
 const imgList = ref([])
 
 const getInfo = async () => {
   const data = await getEnterpriseBaseInfo()
+  // 完成度展示
+  emit('complete', { status: Boolean(data?.albumList?.length), id: 'enterpriseAlbum' })
   if (!data || !data.albumList) return
   imgList.value = data.albumList
 }

+ 4 - 0
src/views/recruit/enterprise/informationManagement/informationSettingsComponents/enterpriseLabel.vue

@@ -46,6 +46,8 @@ import { useI18n } from '@/hooks/web/useI18n'; const { t } = useI18n()
 import { getEnterpriseBaseInfo, updateEnterpriseTag, getTagTreeDataApi } from '@/api/enterprise'
 import { ref } from 'vue';
 defineOptions({name: 'informationSettingsComponents-enterpriseLabel'})
+const emit = defineEmits(['complete'])
+
 const customTag = ref(false)
 const limitNum = ref(10)
 let chosen = ref([])
@@ -95,6 +97,8 @@ getTagTreeData()
 const getData = async () => {
   const data = await getEnterpriseBaseInfo()
   chosen.value = data?.tagList || []
+  // 完成度展示
+  emit('complete', { status: Boolean(chosen.value?.length), id: 'enterpriseLabel' })
 }
 getData()
 const textItem = ref({

+ 3 - 0
src/views/recruit/enterprise/informationManagement/informationSettingsComponents/enterpriseLogo.vue

@@ -49,6 +49,7 @@ import { uploadFile } from '@/api/common'
 import { useI18n } from '@/hooks/web/useI18n'
 import { updateEnterpriseLogo, getEnterpriseBaseInfo } from '@/api/enterprise'
 import Snackbar from '@/plugins/snackbar'
+const emit = defineEmits(['complete'])
 
 const { t } = useI18n()
 let squareImageUrl = ref('')
@@ -59,8 +60,10 @@ const getInfo = async () => {
   const data = await getEnterpriseBaseInfo()
   if (data && data?.logoUrl) {
     squareImageUrl.value = data.logoUrl
+    // 完成度展示
     await userStore.getEnterpriseInfo() // 更新当前登录的企业用户信息
   }
+  emit('complete', { status: Boolean(squareImageUrl.value), id: 'enterpriseLogo' })
 }
 getInfo()
 

+ 0 - 10
src/views/recruit/enterprise/informationManagement/informationSettingsComponents/enterpriseVideo.vue

@@ -1,10 +0,0 @@
-<!-- 企业视频 -->
-<template>
-  <div>enterpriseVideo</div>
-</template>
-
-<script setup>
-defineOptions({name: 'informationSettingsComponents-enterpriseVideo'})
-</script>
-<style lang="scss" scoped>
-</style>

+ 0 - 10
src/views/recruit/enterprise/informationManagement/informationSettingsComponents/recruitmentQRCode.vue

@@ -1,10 +0,0 @@
-<!-- 招聘二维码 -->
-<template>
-  <div>recruitmentQRCode</div>
-</template>
-
-<script setup>
-defineOptions({name: 'informationSettingsComponents-recruitmentQRCode'})
-</script>
-<style lang="scss" scoped>
-</style>

+ 4 - 0
src/views/recruit/enterprise/informationManagement/informationSettingsComponents/welfareLabel.vue

@@ -46,6 +46,8 @@ import { useI18n } from '@/hooks/web/useI18n'; const { t } = useI18n()
 import { getEnterpriseBaseInfo, updateEnterpriseWelfare, getTagTreeDataApi } from '@/api/enterprise'
 import { ref } from 'vue';
 defineOptions({name: 'informationSettingsComponents-welfareLabel'})
+const emit = defineEmits(['complete'])
+
 const customTag = ref(false)
 const limitNum = ref(10)
 let chosen = ref([])
@@ -95,6 +97,8 @@ getTagTreeData()
 const getData = async () => {
   const data = await getEnterpriseBaseInfo()
   chosen.value = data?.welfareList || []
+  // 完成度展示
+  emit('complete', { status: Boolean(chosen.value?.length), id: 'welfareLabel' })
 }
 getData()
 const textItem = ref({

+ 1 - 1
src/views/recruit/personal/remuse/components/basicInfo.vue

@@ -455,7 +455,7 @@ items.value.options.forEach((e, index) => {
     const id = baseInfo.value[e.key]
     deal(id, e.key, 'regProvinceId')
   }
-  if (e.value === undefined || e.value === null) completeStatus = false
+  if (e.value === undefined || e.value === null || e.value === '') completeStatus = false
 })
 // 完成度展示
 emit('complete', { status: completeStatus, id: 'basicInfo' })

+ 1 - 1
src/views/recruit/personal/remuse/components/projectExperience.vue

@@ -124,7 +124,7 @@ const projectExp = ref([])
 const getResumeTrainExpData = async () => {
   const data = await getResumeProjectExp()
   // 完成度展示
-  emit('complete', { status: Boolean(!data?.length), id: 'projectExperience' })
+  emit('complete', { status: Boolean(data?.length), id: 'projectExperience' })
   projectExp.value = data
 }
 getResumeTrainExpData()

+ 14 - 6
src/views/recruit/personal/remuse/index.vue

@@ -12,7 +12,10 @@
             <template v-slot:append>
               <!-- <v-icon v-if="!item.status">mdi-information-outline</v-icon> -->
               <v-icon v-if="item.status" color="primary">mdi-check</v-icon>
-              <v-icon v-else color="error">mdi-information-outline</v-icon>
+              <template v-else>
+                <v-icon color="orange">mdi-information-outline</v-icon>
+                <v-tooltip activator="parent" location="top">请完善{{ item.text }}</v-tooltip>
+              </template>
             </template>
           </v-list-item>
         </v-list>
@@ -20,7 +23,7 @@
         <ProgressBar
           class="mt-2"
           :num="completeNum"
-          :total="items.length"
+          :total="items?.length"
         ></ProgressBar>
       </v-card>
     </div>
@@ -98,10 +101,15 @@ const handleClick = (item) => {
 const completeNum = ref(0)
 const complete = (val) => {
   if (!val?.id) return
-  const item = items.value.find(e => e.id === val.id)
-  if (!item) return
-  if (val.status) completeNum.value++
-  item.status = val.status || false
+  completeNum.value = 0
+  items.value.forEach(e => {
+    if (e.id === val.id) {
+      e.status = val.status || false
+    }
+    if (e.status) {
+      completeNum.value++
+    }
+  })
 }
 </script>