Browse Source

Merge branch 'dev' of https://git.citupro.com/zhengnaiwen_citu/menduner into dev

lifanagju_citu 6 months ago
parent
commit
1b4b7595a6

+ 7 - 7
.env.development

@@ -1,21 +1,21 @@
 NODE_ENV = 'development'
 
 # 版本号 v 1818
-VITE_VERSION = 'v24.11.15.1818'
+VITE_VERSION = 'v24.11.18.1830'
 
 VITE_APP_TITLE = 门墩儿
 
 # 访问路径
-VITE_ACCESS_BASE_URL = 'http://menduner.citupro.com:7878' # 发布测试环境 
-# VITE_ACCESS_BASE_URL = 'https://www.menduner.com' # 发布生产环境 
+# VITE_ACCESS_BASE_URL = 'http://menduner.citupro.com:7878' # 发布测试环境 
+VITE_ACCESS_BASE_URL = 'https://www.menduner.com' # 发布生产环境 
 # 
 # 请求路径
-VITE_BASE_URL = 'http://menduner.citupro.com:7878' # 发布测试环境 
-# VITE_BASE_URL = 'https://www.menduner.com' # 发布生产环境 
+# VITE_BASE_URL = 'http://menduner.citupro.com:7878' # 发布测试环境 
+VITE_BASE_URL = 'https://www.menduner.com' # 发布生产环境 
 
 # 预览路径
-VITE_PREVIEW_URL = 'http://192.168.3.91:8012' # 发布测试环境 
-# VITE_PREVIEW_URL = 'https://kkfileview.menduner.com/' # 发布生产环境 
+# VITE_PREVIEW_URL = 'http://192.168.3.91:8012' # 发布测试环境 
+VITE_PREVIEW_URL = 'https://kkfileview.menduner.com/' # 发布生产环境 
 
 # 租户id
 VITE_TENANTCODE = '155'

+ 9 - 1
src/api/recruit/personal/myWallet.js

@@ -19,7 +19,15 @@ export const setWalletRecharge = async (data) => {
 // 获得钱包充值记录分页
 export const getUserWalletRechargePage = async (params) => {
   return await request.get({
-    url: 'app-api/pay/wallet-recharge/page',
+    url: '/app-api/pay/wallet-recharge/page',
     params
   })
 }
+
+// 余额明细
+export const getUserBalanceDetails = async (params) => {
+  return await request.get({
+    url: '/app-api/pay/wallet-transaction/page',
+    params
+  })
+}

+ 28 - 9
src/components/pay/index.vue

@@ -12,11 +12,12 @@
     </template>
 
     <!-- 赏金所需 -->
-    <div class="pt-3 pb-5" style="color: var(--v-error-base); font-weight: bold; text-align: center;">
+    <div :class="{'pb-5': !showOriginalPrice}" style="color: var(--v-error-base); font-weight: bold; text-align: center;">
       <!-- <span class="font-size-13">¥</span> -->
-      <span class="font-size-30"> {{ cost / 100 }}</span>
-      <span class="font-size-15 ml-1">{{ payUnit }}</span>
+      <span class="font-size-40"> {{ cost / 100 }}</span>
+      <span class="font-size-16 ml-1">{{ payUnit }}</span>
     </div>
+    <div v-if="showOriginalPrice" class="text-center text-decoration-line-through pb-5 color-666">原价:599{{ payUnit }}</div>
     <template v-if="payTypeList?.length">
       <v-chip-group v-model="payType" selected-class="text-primary" column mandatory @update:modelValue="payTypeChange">
         <v-chip filter v-for="k in payTypeList" :key="k.code" :value="k.code" class="mr-3" label>
@@ -29,13 +30,13 @@
         <!-- 钱包支付 -->
         <div v-if="isWalletPay" class="py-10" style="text-align: center;">
           <div>
-            <span>剩余点数:</span>
+            <span>剩余M豆:</span>
             <span style="color: var(--v-primary-base);">{{ accountBalance }}</span>
           </div>
           <div class="my-3" v-if="notEnoughMoney">
             <span class="color-error">
               <!-- 当前剩余点数不足,<span class="text-decoration-underline cursor-pointer" @click="handleRecharge">去充值</span> -->
-              当前剩余点数不足,请微信扫码付款
+              当前剩余M豆不足,请微信扫码付款
             </span>
           </div>
         </div>
@@ -63,6 +64,10 @@
         </div>
       </div>
     </template>
+    <div v-if="showEnterpriseJump" class="text-end text-decoration-underline color-primary mt-10 cursor-pointer" @click="handleToJump">
+      职位发布次数不够用?点击查看更多优惠套餐
+      <v-icon>mdi-chevron-double-right</v-icon>
+    </div>
   </v-card>
 
   <CtDialog :visible="showRecharge" :widthType="1" titleClass="text-h6" title="点数充值" :footer="false" submitText="确认" @close="handleRechargeClose">
@@ -118,14 +123,24 @@ const props = defineProps({
   },
   unit: {
     type: String,
-    default: '点数'
+    default: 'M豆'
+  },
+  // 是否展示企业职位发布去购买更多套餐
+  showEnterpriseJump: {
+    type: Boolean,
+    default: false
+  },
+  // 原价
+  showOriginalPrice: {
+    type: Boolean,
+    default: false
   }
 })
 
 const showRecharge = ref(false)
 const loading = ref(true)
 const tip = ref('')
-const payUnit = ref('点数')
+const payUnit = ref('M豆')
 
 // 步骤:
 //      1. 获取支付方式类型列表getCodeList (appId不同时数据返回有区别)
@@ -227,7 +242,7 @@ const isWalletPay = ref(false)
 const isQrCodePay = ref(false)
 const payTypeChange = (value) => {
   payType.value = value
-  payUnit.value = value === 'wx_native' ? '元' : '点数'
+  payUnit.value = value === 'wx_native' ? '元' : 'M豆'
   tip.value = payTypeList.value.find(e => e.code === payType.value)?.tip || ''
   isQrCodePay.value = qrCodePay.includes(payType.value)
   isWalletPay.value = walletPay.includes(payType.value)
@@ -365,8 +380,12 @@ const formatDuration = (remainder) => {
   return `${minutes}分${remainingSeconds}秒`
 }
 
+const handleToJump = () => {
+  window.open('/recruit/enterprise/membershipPackage')
+}
+
 </script>
 
 <style lang="scss" scoped>
-.font-size-30 { font-size: 30px; }
+.font-size-40 { font-size: 40px; }
 </style>

+ 9 - 14
src/hooks/web/useDictionaries.js

@@ -9,23 +9,10 @@ import {
   getAreaTreeData,
   getPositionData
 } from '@/api/common/index'
-// 定义对应的api
-// const DICT_CITY_API = {
-//   menduner_exp_type: getDictData
-// }
 import { getSecondNodes } from '@/utils/dealData'
 
 // const setDict = (type, val, cacheTime = 7200) => {
 const setDict = (type, val) => {
-  if (type === 'areaTreeData') {
-    const obj = val.find(e => e.name === '中国')
-    val = obj?.children ? obj.children.map(e =>{
-      // 市辖区直接显示区
-      const municipality = e.children && e.children.length && e.children[0].name === '市辖区'
-      if (municipality && e.children[0].children?.length) e.children = e.children[0].children
-      return e
-    }) : []
-  }
   if (type === 'positionSecondData') {
     val = getSecondNodes(val)
   }
@@ -66,7 +53,15 @@ export const getDict = (type, params, apiType = 'dict') => {
         positionSecondData: getPositionTreeData
       }
       apiFn[apiType](query).then(data => {
-        // setDict(type, data, Date.now())
+        if (type === 'areaTreeData') {
+          const obj = data.find(e => e.name === '中国')
+          data = obj?.children ? obj.children.map(e =>{
+            // 市辖区直接显示区
+            const municipality = e.children && e.children.length && e.children[0].name === '市辖区'
+            if (municipality && e.children[0].children?.length) e.children = e.children[0].children
+            return e
+          }) : []
+        }
         setDict(type, data)
         resolve({ data })
       })

+ 1 - 1
src/layout/company/navBar.vue

@@ -19,7 +19,7 @@
           </div>
           <div class="ml-3 cursor-pointer border-left border-right px-3 commonHover" @click="handleLogout(false)">我要求职</div>
           <div class="d-flex align-center px-3 border-right">
-            <div>{{ $t('enterprise.account.remainingPoints') }}:{{ enterpriseUserAccount?.balance ? enterpriseUserAccount?.balance / 100 : 0 }}点</div>
+            <div>剩余M豆:{{ enterpriseUserAccount?.balance ? enterpriseUserAccount?.balance / 100 : 0 }}个</div>
           </div>
           <!-- <svg-icon @click="handleToVip" name="vip" size="30" class="cursor-pointer ml-3"></svg-icon> -->
           

+ 18 - 9
src/router/modules/components/recruit/enterprise.js

@@ -276,7 +276,7 @@ const enterprise = [
   {
     component: Layout,
     path: '/recruit/enterprise/financialCenter',
-    redirect: '/recruit/enterprise/membershipPackage',
+    redirect: '/recruit/enterprise/tradingOrder',
     name: 'enterpriseMemberCenter',
     meta: {
       title: '财务中心',
@@ -285,14 +285,6 @@ const enterprise = [
       // isAdmin: true // 企业管理员菜单
     },
     children: [
-      // {
-      //   path: '/recruit/enterprise/membershipPackage',
-      //   meta: {
-      //     title: '会员权益',
-      //     enName: 'Membership Benefits'
-      //   },
-      //   component: () => import('@/views/recruit/enterprise/membershipPackage/index.vue')
-      // },
       {
         path: '/recruit/enterprise/tradingOrder',
         meta: {
@@ -361,6 +353,23 @@ const enterprise = [
       },
       
     ]
+  },
+  {
+    path: '/recruit/enterprise/membershipPackage',
+    component: Layout,
+    name: 'membershipPackage',
+    meta: {
+      title: '会员套餐',
+      enName: 'Membership Benefits',
+      icon: 'mdi-wallet-membership'
+    },
+    children: [
+      {
+        path: '/recruit/enterprise/membershipPackage',
+        show: true,
+        component: () => import('@/views/recruit/enterprise/membershipPackage/index.vue')
+      }
+    ]
   }
 ]
 export default enterprise

+ 5 - 5
src/views/about/index.vue

@@ -34,7 +34,7 @@
               <p class="font-size-18">{{ val.name }}</p>
               <p class="font-size-14 my-1">{{ val.job }}</p>
               <p class="font-size-14">{{ val.company }}</p>
-              <p class="font-size-14 mt-5">{{ val.desc }}</p>
+              <p class="font-size-14 mt-5" v-html="val.desc"></p>
             </div>
           </div>
         </div>
@@ -92,21 +92,21 @@ const introduce = [
     job: 'Seasoned Hotelier',
     company: 'Hotel and Tourism Consulting',
     avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%875.png',
-    desc: 'I wish to congratulate Simon Tian on the establishment of Menduner. There is no doubt of the future success for this enterprise and its clients given the proven ability, skills and professional experience that Simon and his team can provide.'
+    desc: 'I wish to congratulate Simon Tian on the establishment of Menduner. There is no doubt of the future success for this enterprise and its clients given the proven ability, <br/>skills and professional experience that Simon and his team can provide.'
   },
   {
     name: '肖君 先生',
     job: '高级运营副总裁',
     company: '朗廷酒店集团中国区域',
     avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%876.png',
-    desc: '门墩儿是专属于酒店行业的职业发展社交平台。希望能在这里携手更多志同道合的伙伴,追求我们共同的梦想。'
+    desc: '门墩儿是专属于酒店行业的职业发展社交平台。希望能在这里携手更多志同道合的伙伴,<br/>追求我们共同的梦想。'
   },
   {
     name: 'Nelson Li 李可',
     job: '泛海酒店投资管理有限公司副总经理',
     company: '武汉泛海费尔蒙酒店业主代表',
     avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%877.png',
-    desc: '世界每时每刻都在发生变化,唯一不变的是我们对于这个行业的初心和热情。很高兴看到一群有梦想的酒店人为了遇见更好的自己,为了中国酒店业的未来勇敢的迈出了这一步…“精诚所至 金石为开”,愿“门墩儿”与中国酒店人共同成长,加油!'
+    desc: '世界每时每刻都在发生变化,唯一不变的是我们对于这个行业的初心和热情。很高兴看到一群有梦想的酒店人为了遇见更好的自己,为了中国酒店业的未来勇敢的迈出了这一步…<br/>“精诚所至 金石为开”,愿“门墩儿”与中国酒店人共同成长,加油!'
   },
   {
     name: 'Gerhard H. Zimmer',
@@ -120,7 +120,7 @@ const introduce = [
     job: '创始人',
     company: '禾禾木文化发展有限公司',
     avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%879.png',
-    desc: '找到对的门,认识对的人. 门墩儿,比酒店人更懂酒店人,从这里开启不同的圈层,打开职业生涯你不敢想象的可能!'
+    desc: '找到对的门,认识对的人. 门墩儿,比酒店人更懂酒店人,从这里开启不同的圈层,<br/>打开职业生涯你不敢想象的可能!'
   }
 ]
 </script>

+ 1 - 1
src/views/recruit/enterprise/hirePosition/components/add.vue

@@ -94,7 +94,7 @@ const saveEmit = async () => {
   loading.value = true
   try {
     const res = await saveJobAdvertised(submitParams)
-    Snackbar.success(submitParams.id ? t('common.editSuccessMsg') : t('common.publishSuccessMsg1'))
+    Snackbar.success(submitParams.id ? t('common.editSuccessMsg') : '已发布到职位列表《全员猎聘》,请前往支付')
     // 生成订单
     await createTradeOrder({
       spuId: res,

+ 17 - 17
src/views/recruit/enterprise/hirePosition/components/baseInfo.vue

@@ -4,19 +4,19 @@
       <template #numericalValue>
         <div class="font-size-14 color-error my-1">
           <div class="d-flex align-center font-size-13">
-          <div style="color: var(--v-error-base); cursor: pointer; text-decoration: underline;" @click="handleViewRule">
-            <v-icon size="20" color="error">mdi-help-circle-outline</v-icon>
-            众聘岗位规则说明。
+            <div style="color: var(--v-error-base); cursor: pointer; text-decoration: underline;" @click="handleViewRule">
+              <v-icon size="20" color="error">mdi-help-circle-outline</v-icon>
+              全员猎聘岗位规则说明。
+            </div>
+            <div class=" ml-5" style="color: var(--v-error-base);">
+              全员猎聘岗位分配比例:推荐人占比{{ ratio.recommendRate }}%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 平台占比{{ ratio.headhuntRate }}%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 投递人占比{{ ratio.cvRate }}%
+            </div>
           </div>
-          <div class=" ml-5" style="color: var(--v-error-base);">
-            众聘岗位分配比例:推荐人占比{{ ratio.recommendRate }}%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 平台占比{{ ratio.headhuntRate }}%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 投递人占比{{ ratio.cvRate }}%
-          </div>
-        </div>
           <div class="d-flex">
-            按众聘岗位分配比例计算后的赏金
-            <span class="calculation ml-3">推荐人{{ calculation('hirePrice', 1, true) }}</span>
-            <span class="calculation">平台{{ calculation('hirePrice', 0, true) }}</span>
-            <span class="calculation">投递人{{ calculation('hirePrice', 2, true) }}</span>
+            按全员猎聘岗位分配比例计算后的赏金(M豆): 
+            <span class="calculation ml-3">推荐人{{ calculation('hirePrice', 1, true) }}个</span>
+            <span class="calculation">平台{{ calculation('hirePrice', 0, true) }}个</span>
+            <span class="calculation">投递人{{ calculation('hirePrice', 2, true) }}</span>
           </div>
         </div>
       </template>
@@ -51,7 +51,7 @@
       </template>
     </CtForm>
 
-    <CtDialog :visible="show" :widthType="1" titleClass="text-h6" title="聘岗位规则说明" :footer="false" @close="show = false">
+    <CtDialog :visible="show" :widthType="1" titleClass="text-h6" title="全员猎聘岗位规则说明" :footer="false" @close="show = false">
       <RulePage />
     </CtDialog>
   </div>
@@ -93,7 +93,7 @@ const items = ref({
       type: 'number',
       key: 'hirePrice',
       value: null,
-      label: '请填写点数 * (1赏金=1点数,点数填入不得少于10且为10的倍数)',
+      label: '请填写赏金 * (1赏金=1M豆)',
       suffix: '点',
       hideDetails: true,
       change: val => hirePriceChange(val, 'hirePrice')
@@ -231,9 +231,9 @@ const handleViewRule = () => {
 const hirePriceChange = (value, key) => {
   let calcCost = value-0
   if (calcCost < 10 ) calcCost = 10
-  else {
-    calcCost = parseInt(calcCost/10)*10
-  }
+  // else {
+  //   calcCost = parseInt(calcCost/10)*10
+  // }
   const obj = items.value.options.find(k => k.key === key)
   if (obj) {
     obj.value = calcCost
@@ -293,6 +293,6 @@ defineExpose({
 }
 .calculation {
   display: block;
-  width: 120px;
+  width: 115px;
 }
 </style>

+ 24 - 7
src/views/recruit/enterprise/hirePosition/components/item.vue

@@ -21,12 +21,15 @@
             <span>{{ val.positionName }}</span>
           </div>
           <div v-if="val?.hire" class="mt-2">
-            <v-chip v-if="val?.hirePrice && val.hirePrice > 0" class="mr-3" label color="primary" size="small">赏金:{{ val.hirePrice / 100 }}元</v-chip>
+            <v-chip v-if="val?.hirePrice && val.hirePrice > 0" class="mr-3" label color="primary" size="small">M豆:{{ commissionCalculation(val.hirePrice / 100, 1) }}个</v-chip>
           </div>
         </div>
-        <div class="d-flex align-center">
-          <v-chip v-if="(val.status-0) === 99" color="warning" label>职位待发布,支付后成功后自动发布</v-chip>
-          <v-chip v-if="val.status === '1' && tab === 2" color="error" class="cursor-pointer" label  style="text-decoration: underline;"  @click="toPay(val)">职位已关闭,点击激活职位</v-chip>
+        <div v-if="tab !== 0" class="text-center color-primary d-flex flex-column justify-center cursor-pointer" @click="handleToResume(val)">
+          <div class="font-weight-bold font-size-18">{{ val.count || 0 }}</div>
+          <div class="font-size-14">已投递简历</div>
+        </div>
+        <div v-if="(val.status-0) === 99" class="d-flex align-center">
+          <v-chip color="warning" label>职位待发布,支付后成功后自动发布</v-chip>
         </div>
       </div>
       <div class="bottom pa-5 d-flex justify-space-between align-center">
@@ -38,11 +41,14 @@
           </span>
         </div>
         <div class="d-flex align-center">
+          <span v-if="val.status === '1' && tab === 2" class="cursor-pointer actions" @click="toPay(val)">职位已关闭,点击激活职位</span>
           <span v-if="(val.status-0) === 99" class="cursor-pointer color-primary" @click="toPay(val)">去支付</span>
           <span v-if="(val.status - 0) !== 99 && val.status !== '1' && tab === 1" class="cursor-pointer actions" @click="handleAction(0, val)">{{ $t('common.close') }}</span>
           <span v-if="(val.status - 0) !== 99 && val.status !== '1' && tab === 1" class="lines"></span>
-          <span v-if="tab === 1" class="cursor-pointer" @click="handleEdit(val)">编辑</span>
-          <span v-if="tab === 3" class="cursor-pointer" @click="handleUpdateExpireTime(val)">修改到期时间</span>
+          <span v-if="tab === 1" class="cursor-pointer actions" @click="handleEdit(val)">编辑</span>
+          <!-- <span v-if="tab === 3" class="cursor-pointer actions" @click="handleUpdateExpireTime(val)">修改到期时间</span> -->
+          <span class="lines" v-if="tab !== 3"></span>
+          <span class="cursor-pointer actions" @click="handleDetail(val)">详情</span> 
         </div>
       </div>
     </div>
@@ -65,7 +71,7 @@
 </template>
 
 <script setup>
-// import { commissionCalculation } from '@/utils/position'
+import { commissionCalculation } from '@/utils/position'
 defineOptions({ name: 'enterprise-position-item'})
 import { ref } from 'vue'
 import { useRouter } from 'vue-router'
@@ -168,6 +174,17 @@ const handleSubmit = async () => {
   showExpire.value = false
   emit('refresh')
 }
+
+// 职位详情
+const handleDetail = async (val) => {
+  if (!val.id) return
+  window.open(`/recruit/enterprise/position/details?id=${val.id}`)
+}
+
+// 查看职位投递简历
+const handleToResume = (val) => {
+  router.push(`/recruit/enterprise/resume?id=${val.id}&hire=1`)
+}
 </script>
 
 <style scoped lang="scss">

+ 1 - 1
src/views/recruit/enterprise/hirePosition/components/rule.vue

@@ -30,7 +30,7 @@ const rule = [
     title: '三、赏金与积分奖励',
     desc: [
       '1、若被推荐的人员成功入职至推荐岗位,并且符合该岗位定制化设置的赏金活动规则要求,推荐人将获得相应的赏金或积分奖励。积分奖励可直接用于在门墩儿平台上兑换礼品或优惠券。',
-      '2、在门墩儿平台上,聘岗位所直接显示的赏金金额,是平台在扣除服务费用之前的原始金额。这一设置旨在为用户提供一个清晰、透明的赏金信息展示,让用户能够直接了解到岗位推荐的潜在价值。'
+      '2、在门墩儿平台上,全员猎聘岗位所直接显示的赏金金额,是平台在扣除服务费用之前的原始金额。这一设置旨在为用户提供一个清晰、透明的赏金信息展示,让用户能够直接了解到岗位推荐的潜在价值。'
     ],
     tip: '(需要注意的是:实际发放至用户账户的赏金,将以系统页面所显示金额的70%形式呈现。这是因为门墩儿平台在为用户提供岗位推荐服务的同时,也需要扣除一定的服务费用,以维持平台的正常运营和提供持续、优质的服务。)'
   },

+ 1 - 1
src/views/recruit/enterprise/hirePosition/index.vue

@@ -59,7 +59,7 @@ const query = ref({
 })
 const exportLoading = ref(false)
 
-const tab = ref(0)
+const tab = ref(1)
 
 const tabList = [
   { label: '待支付', value: 0, status: 99 },

+ 2 - 2
src/views/recruit/enterprise/interviewManagement/components/item.vue

@@ -36,7 +36,7 @@
           <span v-else>{{ statusList.find(e => e.value === item.status)?.label }}</span>
         </span>
       </div>
-      <div>
+      <div class="cursor-pointer">
         <template v-if="item.job?.status !== '1'" >
           <span v-if="editStatus.indexOf(item.status) !== -1" class="font-size-15 color-primary" @click="handleActionClick('edit', item)">修改面试</span>
           <span v-if="againStatus.indexOf(item.status) !== -1" class="font-size-15 color-primary" @click="handleActionClick('edit', item)">重新邀约</span>
@@ -242,11 +242,11 @@ const handleSubmit = async () => {
 
 <style scoped lang="scss">
 .listItem {
-  cursor: pointer;
   width: 100%;
   min-width: 600px;
   overflow: auto;
   height: 76px;
+  text-align: center;
   border: 1px solid #e5e6eb;
   border-radius: 5px;
   

+ 45 - 3
src/views/recruit/enterprise/membershipPackage/index.vue

@@ -1,13 +1,26 @@
 <!-- 购买套餐 -->
 <template>
   <v-card class="card-box pa-3" style="min-width: 1100px;">
-    <v-tabs v-model="tab" align-tabs="center" color="rgb(195 15 15)">
+    <!-- <v-tabs v-model="tab" align-tabs="center" color="rgb(195 15 15)">
       <v-tab :value="0" class="font-weight-bold font-size-18">套餐列表</v-tab>
       <v-tab :value="1" class="font-weight-bold font-size-18">当前套餐</v-tab>
     </v-tabs>
     <Package v-if="tab === 0"></Package>
     <div v-if="tab === 1">
       <empty :elevation="false" message="无购买的套餐内容" class="mt-15"></empty>
+    </div> -->
+
+    <div class="d-flex list">
+      <div v-for="(val, index) in list" :key="index" class="list-item text-center cursor-pointer" :class="{'active': index === active}" @click="active = index">
+        <h4 class="mt-5">{{ val.title }}</h4>
+        <div class="color-primary">
+          <span>¥</span>
+          <span style="font-size: 35px;">{{ val.price }}</span>
+          <span> 元</span>
+        </div>
+        <div class="text-decoration-line-through color-666">原价:{{ val.originalPrice }}元</div>
+        <div class="font-size-14 color-999 mt-3 periodValidity py-2">有效期:120天</div>
+      </div>
     </div>
   </v-card>
 </template>
@@ -15,13 +28,42 @@
 <script setup>
 defineOptions({name: 'enterprise-memberCenter-myAccount'})
 import { ref } from 'vue'
-import Package from './components/package.vue'
+// import Package from './components/package.vue'
+
+// const tab = ref(0)
 
-const tab = ref(0)
+const active = ref(0)
+const list = [
+  { title: '1个职位', price: 399, originalPrice: 599 },
+  { title: '2个职位', price: 599, originalPrice: 799 },
+  { title: '3个职位', price: 799, originalPrice: 999 },
+  { title: '5个职位', price: 999, originalPrice: 1299 }
+]
 </script>
 
 <style lang="scss" scoped>
 :deep(.v-slide-group__content) {
   background: linear-gradient(45deg, #ff8a04, transparent);
 }
+
+.list {
+  &-item {
+    width: 25%;
+    height: 172px;
+    background-color: #fcfcfd;
+    border: 1px solid #f3f3f3;
+    border-radius: 8px;
+    margin-right: 12px;
+    &:last-child {
+      margin-right: 0;
+    }
+    .periodValidity {
+      background-color: #f2f4f7;
+      border-radius: 0 0 8px 8px;
+    }
+  }
+  .active {
+    border: 1px solid #00897B;
+  }
+}
 </style>

+ 2 - 0
src/views/recruit/enterprise/positionManagement/components/add.vue

@@ -28,6 +28,8 @@
       :cost="payInfo.cost"
       :spuId="payInfo.spuId"
       :spuName="payInfo.spuName"
+      :showEnterpriseJump="true"
+      :showOriginalPrice="true"
       :orderType="1"
       @paySuccess="paySuccess"
       @close="showConfirmPaymentDialog = false"

+ 15 - 4
src/views/recruit/enterprise/positionManagement/components/item.vue

@@ -36,8 +36,12 @@
             <span>{{ val.positionName }}</span>
           </div>
         </div>
-        <div class="d-flex align-center">
-          <v-chip v-if="(val.status-0) === 99" color="warning" label>职位待发布,支付后成功后自动发布</v-chip>
+        <div v-if="tab !== 0" class="text-center color-primary d-flex flex-column justify-center cursor-pointer" @click="handleToResume(val)">
+          <div class="font-weight-bold font-size-18">{{ val.count || 0 }}</div>
+          <div class="font-size-14">已投递简历</div>
+        </div>
+        <div v-if="(val.status-0) === 99" class="d-flex align-center">
+          <v-chip color="warning" label>职位待发布,支付后成功后自动发布</v-chip>
         </div>
       </div>
       <div class="bottom pa-5 d-flex justify-space-between align-center">
@@ -57,9 +61,9 @@
               <span class="lines"></span>
               <span class="cursor-pointer actions" @click="handleEdit(val)">{{ $t('common.edit') }}</span>
             </div>
-            <div v-if="tab === 3" class="cursor-pointer actions" @click="handleUpdateExpireTime(val)">修改到期时间</div>
+            <!-- <div v-if="tab === 3" class="cursor-pointer actions" @click="handleUpdateExpireTime(val)">修改到期时间</div> -->
             <span v-if="(val.status-0) === 99" class="cursor-pointer color-primary" @click="toPay(val)">去支付</span>
-            <span class="lines" v-if="tab !== 2"></span>
+            <span class="lines" v-if="tab !== 2 && tab !== 3"></span>
             <span v-if="tab === 2" class="cursor-pointer actions" @click="handleAction(1, '', val, val)">激活</span>
             <span class="lines" v-if="tab === 2"></span>
             <span class="cursor-pointer actions" @click="handleDetail(val)">详情</span>  
@@ -74,6 +78,8 @@
     :cost="39900"
     :spuId="spuId"
     :spuName="spuName"
+    :showEnterpriseJump="true"
+    :showOriginalPrice="true"
     :orderType="1"
     @paySuccess="paySuccess"
     @close="showConfirmPaymentDialog = false"
@@ -268,6 +274,11 @@ const handleDetail = async (val) => {
   if (!val.id) return
   window.open(`/recruit/enterprise/position/details?id=${val.id}`)
 }
+
+// 查看职位投递简历
+const handleToResume = (val) => {
+  router.push(`/recruit/enterprise/resume?id=${val.id}`)
+}
 </script>
 
 <style scoped lang="scss">

+ 28 - 14
src/views/recruit/enterprise/resume/components/screen.vue

@@ -40,7 +40,9 @@ import CommonStyle from './commonStyle.vue'
 
 const emit = defineEmits(['search', 'reset', 'select', 'change'])
 const props = defineProps({
-  tab: Number
+  tab: Number,
+  jobId: String,
+  hire: String
 })
 
 const selected = ref()
@@ -52,7 +54,6 @@ const list = ref([
     defaultTitle: '应聘岗位',
     key: 'jobId',
     selected: [],
-    api: getJobAdvertised,
     items: []
   },
   {
@@ -81,6 +82,18 @@ const list = ref([
   }
 ])
 
+const getJobList = async (k) => {
+  const data = await getJobAdvertised()
+  if (!data.length) return
+  const list = dealDictArrayData([], data)
+  k.items = list.map(e => {
+    const salary = e.payFrom && e.payTo ? `${e.payFrom}-${e.payTo}${e.payName ? '/' + e.payName : ''}` : '面议'
+    return { label: `${e.name}${e.areaName ? '_' + e.areaName : ''} ${salary}`, value: e.id }
+  })
+  return k.items
+}
+
+
 // 获取字典数据
 list.value.forEach(k => {
   if (k.dictTypeName) {
@@ -88,18 +101,7 @@ list.value.forEach(k => {
       data = data?.length && data || []
       k.items = data
     })
-  }
-  if (k.api) {
-    k.api({}).then(data => {
-      if (data.length) {
-        const list = dealDictArrayData([], data)
-        k.items = list.map(e => {
-          const salary = e.payFrom && e.payTo ? `${e.payFrom}-${e.payTo}${e.payName ? '/' + e.payName : ''}` : '面议'
-          return { label: `${e.name}${e.areaName ? '_' + e.areaName : ''} ${salary}`, value: e.id }
-        })
-      }
-    })
-  }
+  } else getJobList(k)
 })
 
 // 单击
@@ -110,6 +112,18 @@ const handleClick = (item, val) => {
   emit('search', { key: val.key, value: obj ? '' : item.value })
 }
 
+if (props.jobId) {
+  const job = list.value.find(e => e.key === 'jobId')
+  getJobList(job).then(data => {
+    if (!data || !data.length) return
+    const id = data.find(e => e.value === props.jobId)
+    handleClick(id, job)
+  })
+  if (props.hire) {
+    bounty.value = props.hire === '1' ? true : false
+  }
+}
+
 // 重置
 const handleReset = () => {
   list.value.map(e => {

+ 3 - 3
src/views/recruit/enterprise/resume/components/table.vue

@@ -25,8 +25,8 @@
             :icon="badgeIcon(item)">
             <v-avatar size="40" :image="getUserAvatar(item.person.avatar, item.person.sex)"></v-avatar>
           </v-badge>
-          <v-avatar v-else size="40" :image="getUserAvatar(item.person.avatar, item.person.sex)"></v-avatar>
-          <span class="defaultLink ml-3">{{ item?.person?.name }}</span>
+          <v-avatar v-else size="40" :image="getUserAvatar(item.person?.avatar, item.person?.sex)"></v-avatar>
+          <span class="defaultLink ml-3">{{ item?.person?.name || item?.phone }}</span>
         </div>
       </template>
       <template #status="{ item }">
@@ -40,7 +40,7 @@
         <v-btn v-if="tab === 0" :color="item.jobClosed ? 'grey' : 'primary'" variant="text" @click="handleToCommunicate(item)">立即沟通<v-tooltip v-if="item.jobClosed" activator="parent" location="top">职位已关闭</v-tooltip></v-btn>
         <v-btn v-if="tab === 0 || tab === 1" color="primary" variant="text" @click="handleEliminate(item)">不合适</v-btn>
         <v-btn v-if="!item.inTalentPool" color="primary" variant="text" @click="handleJoinToTalentPool(item)">加入储备</v-btn>
-        <v-btn v-if="tab === 1 && (item.status === '3' || item.status === '4')" color="primary" variant="text" @click="handleEnterByEnterprise(item)">入职</v-btn>
+        <v-btn v-if="tab === 1 && ['3', '4'].includes(item.status)" color="primary" variant="text" @click="handleEnterByEnterprise(item)">入职</v-btn>
         <v-btn v-if="tab === 4" color="primary" variant="text" @click="handleCancelEliminate(item)">取消不合适</v-btn>
         <v-btn v-if="tab === 2 && item?.job?.hire" color="primary" variant="text" @click="handleSettlement(item)">结算</v-btn>
       </template>

+ 15 - 3
src/views/recruit/enterprise/resume/index.vue

@@ -7,7 +7,15 @@
       </v-tabs>
       <TextInput v-model="textItems.value" :item="textItems" @appendInnerClick="handleSearch" @enter="handleSearch"></TextInput>
     </div>
-    <Screen :tab="tab" @search="handleScreen" @reset="handleScreenReset" @select="handleSelect" @change="handleChangeBounty"></Screen>
+    <Screen
+     :tab="tab" 
+     :jobId="router.currentRoute.value?.query?.id" 
+     :hire="router.currentRoute.value?.query?.hire"
+      @search="handleScreen"
+      @reset="handleScreenReset"
+      @select="handleSelect"
+      @change="handleChangeBounty"
+    ></Screen>
 
     <v-window v-model="tab" class="mt-1">
       <v-window-item v-for="k in tabList" :value="k.value" :key="k.value">
@@ -28,7 +36,9 @@ import { getInterviewInvitePage } from '@/api/recruit/enterprise/interview'
 import TablePage from './components/table.vue'
 import Screen from './components/screen.vue'
 import { timesTampChange } from '@/utils/date'
+import { useRouter } from 'vue-router'
 
+const router = useRouter()
 const total = ref(0)
 const query = ref({
   pageNo: 1,
@@ -79,13 +89,14 @@ const getList = async () => {
   items.value = list.map(e => {
     let obj = e
     obj.jobClosed = e?.job?.status === '1' || false // 职位已关闭
-    obj.person = Object.assign(e.person, dealDictObjData({}, e.person))
+    if (e.person) obj.person = Object.assign(e.person, dealDictObjData({}, e.person))
     obj.job = Object.assign(e.job, dealDictObjData({}, e.job))
     obj.createTime = timesTampChange(e.createTime, 'Y-M-D h:m')
     return obj
   })
 }
-getList()
+// 没有带id时一进来才刷新,带id由组件传值刷新
+if (!router.currentRoute.value?.query?.id) getList()
 
 // 分页
 const handleChangePage = (i) => {
@@ -105,6 +116,7 @@ const handleSearch = () => {
 const handleScreen = ({ value, key }) => {
   if (value) query.value[key] = value
   else delete query.value[key]
+  if (router.currentRoute.value?.query?.hire) query.value.hire = true
   getList()
 }
 

+ 16 - 7
src/views/recruit/personal/PersonalCenter/wallet/myBalance/index.vue

@@ -22,7 +22,7 @@
     <div class="mt-3 white-bgc pa-3 pt-3">
       <v-tabs v-model="tab" align-tabs="start" color="primary" bg-color="#f7f8fa" @update:model-value="handleChangeTab">
         <v-tab value="rechargeDetails">{{ $t('points.rechargeDetails') }}</v-tab>
-        <!-- <v-tab :value="otherHeader">otherHeader</v-tab> -->
+        <v-tab value="balanceDetails">余额明细</v-tab>
       </v-tabs>
       <CtTable
         class="mt-3"
@@ -47,7 +47,7 @@ defineOptions({name: 'myWallet-myBalance-index'})
 import { ref } from 'vue'
 import { timesTampChange } from '@/utils/date'
 import { FenYuanTransform } from '@/utils/position'
-import { getUserWalletRechargePage } from '@/api/recruit/personal/myWallet.js'
+import { getUserWalletRechargePage, getUserBalanceDetails } from '@/api/recruit/personal/myWallet.js'
 import { useUserStore } from '@/store/user'
 
 const tab = ref('rechargeDetails')
@@ -66,6 +66,12 @@ const query = ref({
 })
 const dataList = ref([])
 
+const formatToFraction = (num) => {
+  if (typeof num === 'undefined') return '0.00'
+  const parsedNumber = typeof num === 'string' ? parseFloat(num) : num
+  return (parsedNumber / 100.0).toFixed(2)
+}
+
 const headerList = {
   rechargeDetails: [
     { title: '充值金额', key: 'payPrice', value: item =>  FenYuanTransform(item.payPrice) + '元', sortable: false },
@@ -73,13 +79,18 @@ const headerList = {
     { title: '支付订单编号', key: 'payOrderId', sortable: false },
     { title: '交易时间', key: 'payTime', value: item =>  timesTampChange(item.payTime), sortable: false },
   ],
-  // otherHeader: []
+  balanceDetails: [
+    { title: '交易类型', key: 'title', sortable: false },
+    { title: '交易金额', key: 'price', sortable: false, value: item => formatToFraction(item.price) + '元' },
+    { title: '交易后余额', key: 'balance', sortable: false, value: item => item.balance / 100 + '元' },
+    { title: '交易时间', key: 'createTime', value: item =>  timesTampChange(item.createTime), sortable: false }
+  ]
 }
 
-
 // 积分、签到明细
 const getData = async () => {
-  const res = await getUserWalletRechargePage(query.value)
+  const api = tab.value === 'rechargeDetails' ? getUserWalletRechargePage : getUserBalanceDetails
+  const res = await api(query.value)
   dataList.value = res.list
   total.value = res.total
 }
@@ -108,8 +119,6 @@ const handleRecharge = () => {
   padding: 10px 0;
   border-radius: 10px;
   background-color: var(--default-bgc);
-  // background-color: var(--color-f3);
-  // font-family: 宋体, SimSun;
 }
 .item-title {
   font-size: 20px;