Browse Source

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

lifanagju_citu 5 months ago
parent
commit
3f065ed56c
34 changed files with 213 additions and 142 deletions
  1. 1 1
      .env.demo
  2. 1 1
      .env.localDev
  3. 1 1
      .env.production
  4. 1 1
      package.json
  5. 2 2
      src/App.vue
  6. 4 4
      src/components/Enterprise/hotPromoted.vue
  7. 3 5
      src/components/Position/similarPositions.vue
  8. 1 4
      src/hooks/web/useIM.js
  9. 1 5
      src/layout/company/navBar.vue
  10. 7 4
      src/plugins/fullScreen/components/entUpdatePassword.vue
  11. 51 51
      src/router/modules/components/recruit/enterprise.js
  12. 0 1
      src/store/user.js
  13. 25 0
      src/store/webContent.js
  14. 1 1
      src/version.js
  15. 5 3
      src/views/login/forgotPassword.vue
  16. 6 4
      src/views/login/forgotPasswordEnt.vue
  17. 0 1
      src/views/login/index.vue
  18. 5 0
      src/views/publicRecruitment/components/table.vue
  19. 8 4
      src/views/recruit/components/message/components/chatting.vue
  20. 12 0
      src/views/recruit/components/message/index.vue
  21. 5 3
      src/views/recruit/entRegister/register.vue
  22. 7 4
      src/views/recruit/enterprise/hirePosition/components/item.vue
  23. 1 1
      src/views/recruit/enterprise/jobFair/detailsBox.vue
  24. 3 4
      src/views/recruit/enterprise/jobFair/editJob.vue
  25. 4 1
      src/views/recruit/enterprise/jobFair/index.vue
  26. 1 1
      src/views/recruit/enterprise/jobFair/job/item.vue
  27. 16 4
      src/views/recruit/enterprise/membershipPackage/dynamic/package.vue
  28. 2 1
      src/views/recruit/enterprise/positionManagement/components/add.vue
  29. 5 4
      src/views/recruit/enterprise/positionManagement/components/item.vue
  30. 14 14
      src/views/recruit/enterprise/systemManagement/groupAccount/index.vue
  31. 5 3
      src/views/recruit/enterprise/talentRecommendation/index.vue
  32. 5 3
      src/views/register/company.vue
  33. 5 3
      src/views/register/person.vue
  34. 5 3
      src/views/register/select.vue

+ 1 - 1
.env.demo

@@ -1,4 +1,4 @@
-NODE_ENV = 'demo'
+NODE_ENV = 'development'
 
 VITE_APP_TITLE = 门墩儿
 

+ 1 - 1
.env.localDev

@@ -1,4 +1,4 @@
-NODE_ENV = 'localDev'
+NODE_ENV = 'development'
 
 VITE_APP_TITLE = 门墩儿
 

+ 1 - 1
.env.development → .env.production

@@ -1,4 +1,4 @@
-NODE_ENV = 'development'
+NODE_ENV = 'production'
 
 VITE_APP_TITLE = 门墩儿
 

+ 1 - 1
package.json

@@ -3,7 +3,7 @@
   "version": "0.0.0",
   "scripts": {
     "dev": "vite --mode localDev --host 0.0.0.0",
-    "build:dev": "vite build --mode development",
+    "build:dev": "vite build --mode production",
     "build:demo": "vite build --mode demo",
     "preview": "vite preview",
     "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",

+ 2 - 2
src/App.vue

@@ -14,9 +14,9 @@ function open () {
 }
 onMounted(() => {
   nextTick(() => {
-    console.log('baseurl:', import.meta.env?.VITE_BASE_URL, 'vue_version:', vue_version) // 打印
+    // console.log('baseurl:', import.meta.env?.VITE_BASE_URL, 'vue_version:', vue_version) // 打印
     const process_ENV = process?.env?.NODE_ENV || ''
-    if (process_ENV === 'production' || process_ENV === 'development') {
+    if (process_ENV === 'production') {
       open()
     }
   })

+ 4 - 4
src/components/Enterprise/hotPromoted.vue

@@ -8,7 +8,7 @@
             <v-img :src="item?.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'" alt="" width="77" height="77" style="border-radius: 4px;"/>
           </div>
           <div class="company-info cursor-pointer">
-            <h3>{{ item.enterprise.anotherName }}</h3>
+            <h3>{{ item.enterprise.anotherName || item.enterprise.name }}</h3>
             <p>
               {{ item?.enterprise.scaleName }}
               <span class="septal-line" v-if="item.enterprise.industryName"></span>
@@ -24,14 +24,14 @@
           <li class="company-job-item" v-for="(k, i) in item.jobList" :key="i" :class="{'company-job-item-hover': k.active}" @mouseenter="k.active = true" @mouseleave="k.active = false" @click="handleClickPosition(k)">
             <div class="job-info" @mouseenter="k.active = true" @mouseleave="k.active = false" @click="handleClickPosition(k)">
               <div class="mb-2 d-flex">
-                <p :class="['name', 'cursor-pointer', {'default-active': k.active }]">{{ k.name }}</p>
+                <p :class="['name', 'cursor-pointer', {'default-active': k.active }]" :style="{'max-width': !k.payFrom && !k.payTo ? '290px' : '200px'}">{{ k.name }}</p>
                 <span v-if="!k.payFrom && !k.payTo" class="salary">面议</span>
                 <span v-else class="salary">{{ k.payFrom ? k.payFrom + '-' : '' }}{{ k.payTo }}{{ k.payName ? '/' + k.payName : '' }}</span>
               </div>
               <div style="height: 24px; overflow: hidden; color: #808080;">
                 <span v-for="(j, index) in desc" :key="index">
                   <span v-if="k[j.value] || (j.value === 'areaName' && !k.areaId)" class="mr-1 font-size-13">{{ (j.value === 'areaName' && !k.areaId) ? '全国' : k[j.value] }}</span>
-                  <span v-if="index !== desc.length - 1 && (k[desc[index + 1].value] || (j.value === 'areaName' && !k.areaId))" class="septal-line ml-1"></span>
+                  <span v-if="k[j.value] && index !== desc.length - 1 && (k[desc[index + 1].value] || (j.value === 'areaName' && !k.areaId))" class="septal-line ml-1"></span>
                 </span>
                 <span class="font-size-13 float-right">{{ timesTampChange(k.updateTime, 'Y-M-D') }}</span>
               </div>
@@ -179,7 +179,7 @@ ul li {
 }
 .name {
   position: relative;
-  max-width: 200px;
+  // max-width: 200px;
   line-height: 22px;
   font-weight: 700;
   color: #404040;

+ 3 - 5
src/components/Position/similarPositions.vue

@@ -2,7 +2,7 @@
   <div class="position-box">
     <h4 class="mb-3">{{ $t('position.similarPosition') }}</h4>
     <div v-for="(item, index) in props.list" :key="index" class="mb-2 cursor-pointer" @click="handlePosition(item)">
-      <p class="recruit-name">{{ item.name }}</p>
+      <p class="recruit-name" :style="{'max-width': !item.payFrom && !item.payTo ? '230px' : '140px'}">{{ item.name }}</p>
       <span v-if="!item.payFrom && !item.payTo" class="recruit-salary">面议</span>
       <span v-else class="recruit-salary">{{ item.payFrom ? item.payFrom + '-' : '' }}{{ item.payTo }}{{ item.payName ? '/' + item.payName :'' }}</span>
       <div :class="['enterprise', {'border-bottom-dashed': index !== list.length - 1}]">
@@ -37,10 +37,8 @@ const handlePosition = (item) => {
   padding: 20px 15px;
 }
 .recruit-name {
-  width: 95px;
   font-weight: 500;
   display: inline-block;
-  max-width: 95px;
   vertical-align: middle;
   white-space: nowrap;
   text-overflow: ellipsis;
@@ -62,9 +60,9 @@ const handlePosition = (item) => {
   margin-top: 8px;
 }
 .enterprise-name {
-  width: 120px;
+  width: 150px;
   display: inline-block;
-  max-width: 120px;
+  max-width: 150px;
   vertical-align: middle;
   white-space: nowrap;
   text-overflow: ellipsis;

+ 1 - 4
src/hooks/web/useIM.js

@@ -102,7 +102,6 @@ export function useDataSource () {
     }
     const resultConversations = []
     const resp = await getConversationSync(query)
-    // console.log(resp)
     const conversationList = resp
     if (conversationList) {
       conversationList.forEach(conversation => {
@@ -138,8 +137,6 @@ export function useDataSource () {
     const messageList = resp && resp["messages"]
     if (messageList) {
       messageList.forEach((msg) => {
-        // const message = Convert.toMessage(msg);
-        // msg.channel = new Channel(msg.channel_id, msg.channel_type)
         msg.payload = JSON.parse(Base64.decode(msg.payload))
         if (contentType[msg.payload.type]) {
           msg.payload.content = JSON.parse(msg.payload.content ?? '{}')
@@ -147,7 +144,6 @@ export function useDataSource () {
         resultMessages.push(msg)
       })
     }
-    // console.log(resultMessages)
     const more = resp.more === 1
     return {
       more,
@@ -383,6 +379,7 @@ export function send (text, _channel, type) {
   let _text
   if (contentType[type]) {
     _text = new contentType[type](text)
+    console.log(_text)
     WKSDK.shared().chatManager.send(_text, _channel)
     return
   }

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

@@ -21,7 +21,7 @@
           <div class="d-flex align-center px-3 border-right cursor-pointer commonHover" @click="router.push('/recruit/enterprise/membershipPackage?key=1')">
             <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> -->
+          <svg-icon v-if="baseInfo?.vipFlag" name="vip" size="30" class="ml-3"></svg-icon>
           
           <!-- 头像用户名 -->
           <div class="d-flex align-center" v-if="showBall">
@@ -109,10 +109,6 @@ onMounted(() => {
   }
 })
 
-// const handleToVip = () => {
-//   router.push({ path: '/recruit/enterprise/membershipPackage' })
-// }
-
 const handleLogoClick = () => { window.open('/recruitHome') } // 点击logo
 
 const enterpriseClick = (tabKey = 1) => {

+ 7 - 4
src/plugins/fullScreen/components/entUpdatePassword.vue

@@ -5,7 +5,7 @@
       v-model="dialog"
       max-width="100vw"
     >
-      <div class="white-bgc ma-n6 d-flex flex-column align-center justify-center" style="min-height: 100vh;">
+      <div class="white-bgc ma-n6 d-flex flex-column align-center justify-center" style="min-height: 100vh;" :style="{'background-image': 'url(' + webContent.loginBgUrl + ')'}">
         <staffChangePassword :hideGoBack="true" :hideWidth="true" :entChangePassword="true" elevation="0"></staffChangePassword>
       </div>
     </v-dialog>
@@ -13,19 +13,22 @@
 </template>
 
 <script setup>
+defineOptions({name: 'fullScreen-entUpdatePassword'})
 import { onMounted, ref } from 'vue'
+import { webContentStore } from '@/store/webContent'
 import staffChangePassword from '@/views/recruit/enterprise/staffChangePassword'
-defineOptions({name: 'fullScreen-entUpdatePassword'})
+
+const webContent = webContentStore()
 
 const dialog = ref(true)
-onMounted(() => {
+onMounted(async () => {
+  await webContent.getSystemWebContent()
   dialog.value = true
 })
 
 </script>
 <style lang="scss" scoped>
 .white-bgc {
-  background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
 }
 ::-webkit-scrollbar {

+ 51 - 51
src/router/modules/components/recruit/enterprise.js

@@ -112,6 +112,57 @@ const enterprise = [
       }
     ]
   },
+  {
+    path: '/recruit/enterprise/jobFair',
+    component: Layout,
+    name: 'jobFair',
+    meta: {
+      title: '招聘会',
+      enName: 'Job Fair',
+      icon: 'mdi-account-filter-outline'
+    },
+    children: [
+      {
+        path: '/recruit/enterprise/jobFair',
+        show: true,
+        meta: {
+          title: '招聘会',
+          enName: 'Job Fair'
+        },
+        component: () => import('@/views/recruit/enterprise/jobFair/index.vue')
+      },
+      {
+        path: '/recruit/enterprise/jobFair/details/:id',
+        show: true,
+        meta: {
+          title: '招聘会详情',
+          enName: 'Job Fair Details'
+        },
+        component: () => import('@/views/recruit/enterprise/jobFair/detailsBox.vue'),
+        children: [
+          {
+            path: '/recruit/enterprise/jobFair/details/:id',
+            show: true,
+            meta: {
+              title: '招聘会详情',
+              enName: 'Job Fair Details'
+            },
+            component: () => import('@/views/recruit/enterprise/jobFair/details.vue'),
+          },
+          {
+            path: '/recruit/enterprise/jobFair/details/:id/edit',
+            show: true,
+            meta: {
+              title: '职位编辑',
+              enName: 'Job Fair Edit'
+            },
+            component: () => import('@/views/recruit/enterprise/jobFair/editJob.vue')
+          }
+        ]
+      },
+      
+    ]
+  },
   {
     path: '/recruit/enterprise/talentPool',
     component: Layout,
@@ -303,57 +354,6 @@ const enterprise = [
       }
     ]
   },
-  {
-    path: '/recruit/enterprise/jobFair',
-    component: Layout,
-    name: 'jobFair',
-    meta: {
-      title: '招聘会',
-      enName: 'Job Fair',
-      icon: 'mdi-account-filter-outline'
-    },
-    children: [
-      {
-        path: '/recruit/enterprise/jobFair',
-        show: true,
-        meta: {
-          title: '招聘会',
-          enName: 'Job Fair'
-        },
-        component: () => import('@/views/recruit/enterprise/jobFair/index.vue')
-      },
-      {
-        path: '/recruit/enterprise/jobFair/details/:id',
-        show: true,
-        meta: {
-          title: '招聘会详情',
-          enName: 'Job Fair Details'
-        },
-        component: () => import('@/views/recruit/enterprise/jobFair/detailsBox.vue'),
-        children: [
-          {
-            path: '/recruit/enterprise/jobFair/details/:id',
-            show: true,
-            meta: {
-              title: '招聘会详情',
-              enName: 'Job Fair Details'
-            },
-            component: () => import('@/views/recruit/enterprise/jobFair/details.vue'),
-          },
-          {
-            path: '/recruit/enterprise/jobFair/details/:id/edit',
-            show: true,
-            meta: {
-              title: '职位编辑',
-              enName: 'Job Fair Edit'
-            },
-            component: () => import('@/views/recruit/enterprise/jobFair/editJob.vue')
-          }
-        ]
-      },
-      
-    ]
-  },
   {
     path: '/recruit/enterprise/membershipPackage',
     component: Layout,

+ 0 - 1
src/store/user.js

@@ -209,7 +209,6 @@ export const useUserStore = defineStore('user',
       async checkEnterpriseBaseInfo () {
         try {
           const data = await getEnterpriseBaseInfo()
-          console.log('获取《企业基本信息》:', data)
           if (data?.first !== false && data?.first !== 'false') {  // 首次登录才提示,不为false都属于首次登录
             localStorage.setItem('checkEnterpriseBaseInfoFalseHref', '/recruit/enterprise/entInfoSetting')
           }

+ 25 - 0
src/store/webContent.js

@@ -0,0 +1,25 @@
+import { defineStore } from 'pinia'
+import { getWebContent } from '@/api/common'
+
+export const webContentStore = defineStore('webContent',
+  {
+    state: () => ({
+      loginBgUrl: '' // 登录页背景图
+    }),
+    actions: {
+      async getSystemWebContent () {
+        try {
+          const data = await getWebContent()
+          this.loginBgUrl = data.pcLoginBackground && data.pcLoginBackground.length ? data.pcLoginBackground[0].img : 'https://minio.menduner.com/dev/menduner/login-bgc.jpg'
+        } catch (error) {
+          console.log(error)
+        }
+      }
+    }
+  },
+  {
+    persist: true,
+    devtools: true
+  }
+)
+

+ 1 - 1
src/version.js

@@ -1,2 +1,2 @@
 // 版本号
-export const vue_version = 'v24.12.06.1737'
+export const vue_version = 'v24.12.10.1751'

+ 5 - 3
src/views/login/forgotPassword.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="box">
+  <div class="box" :style="{'background-image': 'url(' + webContent.loginBgUrl + ')'}">
     <navBar v-if="!isMobile" :showLoginBtn="false" class="navBar"></navBar>
     <div class="content pa-10">
       <div class="resume-header">
@@ -24,12 +24,15 @@ import { useRouter, useRoute } from 'vue-router'
 import navBar from '@/layout/personal/navBar.vue'
 import editPasswordPage from '@/views/login/components/editPassword.vue'
 import { ref, onMounted } from 'vue'
+import { webContentStore } from '@/store/webContent'
 
 const router = useRouter()
 const route = useRoute()
+const webContent = webContentStore()
 
 const isMobile = ref(false)
-onMounted(() => {
+onMounted(async () => {
+  await webContent.getSystemWebContent()
   const userAgent = navigator.userAgent
   isMobile.value = /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(userAgent)
 })
@@ -45,7 +48,6 @@ onMounted(() => {
   position: relative;
   width: 100%;
   height: 100%;
-  background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
   display: flex;
   justify-content: center;

+ 6 - 4
src/views/login/forgotPasswordEnt.vue

@@ -1,11 +1,11 @@
 <template>
-  <div class="box">
+  <div class="box" :style="{'background-image': 'url(' + webContent.loginBgUrl + ')'}">
     <navBar v-if="!isMobile" :showLoginBtn="false" class="navBar"></navBar>
     <div class="content pa-10">
       <div class="resume-header">
         <div class="resume-title">企业修改密码</div>
       </div>
-      <editPasswordPage :showCancelBtn="false" openVerify @cancel="router.push('/login')">
+      <editPasswordPage :showCancelBtn="false" openVerify>
         <template #custom>
           <div class="font-size-14 text-end">
             <span class="color-primary cursor-pointer" @click="router.push('/login')">回到登录页</span>
@@ -20,13 +20,16 @@
 defineOptions({ name: 'forgotPasswordEnt'})
 import { useRouter } from 'vue-router'
 import navBar from '@/layout/personal/navBar.vue'
+import { webContentStore } from '@/store/webContent'
 import editPasswordPage from '@/views/login/components/editPasswordEnt.vue'
 import { ref, onMounted } from 'vue'
 
 const router = useRouter()
+const webContent = webContentStore()
 
 const isMobile = ref(false)
-onMounted(() => {
+onMounted(async () => {
+  await webContent.getSystemWebContent()
   const userAgent = navigator.userAgent
   isMobile.value = /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(userAgent)
 })
@@ -43,7 +46,6 @@ onMounted(() => {
   position: relative;
   width: 100%;
   height: 100%;
-  background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
   display: flex;
   justify-content: center;

+ 0 - 1
src/views/login/index.vue

@@ -259,7 +259,6 @@ const windowOpen = (url) => {
   position: relative;
   width: 100%;
   height: 100vh;
-  // background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
   overflow: hidden;
   .navBar {

+ 5 - 0
src/views/publicRecruitment/components/table.vue

@@ -18,12 +18,16 @@
         <span class="ml-2" style="color: #000000DE;">{{ item?.sendPerson?.name }}</span>
       </div>
     </template>
+    <template #hirePrice="{ item }">
+      {{ commissionCalculation(item?.job?.hirePrice / 100, 1) }}元
+    </template>
   </CtTable>
 </template>
 
 <script setup>
 defineOptions({ name: 'myPublicRecruitment-table-page'})
 import { timesTampChange } from '@/utils/date'
+import { commissionCalculation } from '@/utils/position'
 
 const emit = defineEmits(['page'])
 defineProps({
@@ -37,6 +41,7 @@ const headers = [
   { title: '牛人', value: 'sendPerson.name', key: 'name', sortable: false },
   { title: '应聘公司', key: 'enterprise.anotherName', sortable: false },
   { title: '应聘职位', key: 'job', value: item => item?.job?.name, sortable: false },
+  { title: '赏金', key: 'hirePrice', sortable: false },
   { title: '岗位薪资', key: 'salary', value: item => item?.job?.payFrom && item?.job?.payTo ? `${item?.job?.payFrom ? item?.job?.payFrom + '-' : ''}${item?.job?.payTo}` : '面议', sortable: false },
   { title: '推荐时间', key: 'createTime', value: item => timesTampChange(item.createTime), sortable: false },
 ]

+ 8 - 4
src/views/recruit/components/message/components/chatting.vue

@@ -24,7 +24,7 @@
       </div>
     </div>
     <v-divider></v-divider>
-    <div class="py-3 px-7" v-if="interview.length">
+    <div class="py-3 px-7" v-if="interview.length && info.channel?.channelID !== 'system'">
       <div v-for="val in interview" :key="val.id" class="color-666">
         <div class="d-flex justify-space-between">
           <div class="font-weight-bold color-primary">
@@ -50,7 +50,7 @@
         </div>
       </div>
     </div>
-    <v-divider v-if="interview.length"></v-divider>
+    <v-divider v-if="interview.length && info.channel?.channelID !== 'system'"></v-divider>
     <div class="my-3 message-box" @scroll="handleScroll" ref="chatRef">
       <div>
         <div class="d-flex justify-center" v-if="hasMore">
@@ -158,6 +158,9 @@
                 </v-card-actions>
               </v-card>
             </div>
+            <div v-else-if="val.payload.type === -1" class="message-text" :class="{ active: val.from_uid === IM.uid}">
+              {{ val.payload?.content.text }}
+            </div>
             <div v-else class="message-text" :class="{ active: val.from_uid === IM.uid}">
               {{ val.payload?.content }}
             </div>
@@ -201,10 +204,11 @@
         </div>
       </div>
     </div>
-    <div class="tools pa-3" v-if="Object.keys(info).length > 0">
+
+    <div class="tools pa-3" v-if="Object.keys(info).length > 0 && info.channel?.channelID !== 'system'">
       <slot name="tools"></slot>
     </div>
-    <div class="bottom-info">
+    <div class="bottom-info" v-if="Object.keys(info).length > 0 && info.channel?.channelID !== 'system'">
       <v-divider></v-divider>
       <div class="pa-3">
         <v-textarea

+ 12 - 0
src/views/recruit/components/message/index.vue

@@ -433,6 +433,18 @@ async function handleChange (items) {
       channel: myChannel,
       unread
     })
+    if (myChannel.channelID === 'system') {
+      channelItem.value = myChannel
+      const { list, more } = await getMoreMessages(1, channelItem.value)
+      messageItems.value = list.value
+      hasMore.value = more
+      chatRef.value.scrollBottom()
+      // 点开窗口消除未读数量
+      await resetUnread(channelItem.value, entBaseInfo?.enterpriseId)
+      await updateConversation()
+      updateUnreadCount()
+      return
+    }
     // 个人端获取面试信息
     if (!isEnterprise) getInterviewInviteList()
     const userId = userInfoVo.userInfoResp.userId

+ 5 - 3
src/views/recruit/entRegister/register.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="login-box py-5">
+  <div class="login-box py-5"  :style="{'background-image': 'url(' + webContent.loginBgUrl + ')'}">
     <v-card class="pa-5" :class="isMobile? 'mobileBox' : 'default-width'" :elevation="isMobile? '0' : '3'">
       <!-- 标题 -->
       <div class="mt-3" v-if="!isMobile">
@@ -113,10 +113,12 @@ import { enterpriseRegisterApply } from '@/api/personal/user'
 import { onMounted, ref, computed } from 'vue';
 import { checkCompanyEmail } from '@/utils/validate'
 import { getBusinessLicenseOCR } from '@/api/common'
+import { webContentStore } from '@/store/webContent'
 import Confirm from '@/plugins/confirm'
 import TextUI from '@/components/FormUI/TextInput'
 import { findFirstDuplicateWithIndices } from '@/utils/dealData'
 
+const webContent = webContentStore()
 const { t } = useI18n()
 const CtFormRef = ref()
 const loginLoading = ref(false)
@@ -130,7 +132,8 @@ let licenseUrl = ref('')
 
 // 组件挂载后添加事件监听器
 const isMobile = ref(false)
-onMounted(() => {
+onMounted(async () => {
+  await webContent.getSystemWebContent()
   const userAgent = navigator.userAgent
   isMobile.value = /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(userAgent)
 })
@@ -494,7 +497,6 @@ const passwordConfirmObj = {
   position: relative;
   width: 100%;
   height: 100%;
-  background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
 }
 .file-box {

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

@@ -44,8 +44,11 @@
           <span v-if="val.status === '1' && tab === 2" class="cursor-pointer actions" @click="toPay(val)">职位已关闭,点击激活职位</span>
           <span v-if="(val.status-0) === 99 && tab === 0" 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="tab !== 3 && val.edit" class="lines"></span>
-          <span v-if="tab !== 3 && val.edit" class="cursor-pointer actions" @click="handleEdit(val)">编辑</span>
+          <div v-if="tab !== 3">
+            <span class="lines"></span>
+            <span class="cursor-pointer" :class="{'actions': val.edit}" :style="{'color': val.edit ? '#333' : '#999'}" @click="handleEdit(val)">编辑</span>
+            <v-tooltip v-if="!val.edit" activator="parent" location="top">职位发布时间超过24小时的不支持编辑</v-tooltip>
+          </div>
           <!-- <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> 
@@ -152,7 +155,7 @@ const handleAction = async (index, { id }) => {
 const router = useRouter()
 // 职位编辑
 const handleEdit = async (val) => {
-  // if (props.tab !== 1) return
+  if (!val.id || !val.edit) return
   const data = await getEnterprisePubJobTypePermission()
   if (!data || !data.length) return Snackbar.warning('没有该操作权限,请联系平台管理员升级后再试')
   router.push(`/recruit/enterprise/hirePosition/edit?id=${val.id}`)
@@ -227,6 +230,6 @@ const handleToResume = (val) => {
   color: var(--color-888);
 }
 .actions:hover {
-  color: var(--v-primary-base);
+  color: var(--v-primary-base) !important;
 }
 </style>

+ 1 - 1
src/views/recruit/enterprise/jobFair/detailsBox.vue

@@ -14,7 +14,7 @@ const route = useRoute()
 
 const getMsg = async () => {
   const res = await getJobFair(route.params.id)
-  route.matched[1].meta.title = res.title.split('<p>').join('')
+  route.matched[1].meta.title = res.title.replace(/<\/?p[^>]*>/gi, '')
   system.setBreadcrumbs(route.matched, route.fullPath)
 }
 getMsg()

+ 3 - 4
src/views/recruit/enterprise/jobFair/editJob.vue

@@ -1,5 +1,5 @@
 <template>
-  <add :after-add="afterAdd" :valid="validate">
+  <add :after-add="afterAdd" :valid="validate" :isFair="true">
     <template #timeline>
       <v-timeline-item
           dot-color="light-blue darken-1"
@@ -16,7 +16,7 @@
 
 <script setup>
 defineOptions({ name: 'editJob' })
-import { ref, watch, computed } from 'vue'
+import { ref } from 'vue'
 import {  useRoute, useRouter } from 'vue-router'
 import CtForm from '@/components/CtForm'
 import Add from '@/views/recruit/enterprise/positionManagement/components/add.vue'
@@ -158,9 +158,8 @@ const afterAdd = async (jobId) => {
     Snackbar.success(t('common.publishSuccessMsg'))
     router.push(`/recruit/enterprise/jobFair/details/${route.params.id}`)
   } catch (error) {
-    console.log(error)
     console.error(error)
-    Snackbar.error(t('sys.api.operationFailed'))
+    Snackbar.error(error)
   }
 }
 </script>

+ 4 - 1
src/views/recruit/enterprise/jobFair/index.vue

@@ -1,15 +1,17 @@
 <template>
-  <v-card class="card-box pa-5 ">
+  <v-card v-if="list.length" class="card-box pa-5 ">
     <v-card v-for="(k, i) in list" :key="i" class="elevation-3">
       <img :src="k.pcHeadImg" style="width: 100%; height: 300px;">
       <div class="pa-5">
         <div class="color-primary font-weight-bold font-size-18 mb-1" v-html="k.title"></div>
+        <div class="color-666 mt-3">活动时间:{{ timesTampChange(k.startTime, 'Y-M-D') }}至{{ timesTampChange(k.endTime, 'Y-M-D') }}</div>
         <div class="text-end">
           <v-btn color="primary" variant="outlined" @click.stop="handleBlockEnterprise(k.id)">立即加入</v-btn>
         </div>
       </div>
     </v-card>
   </v-card>
+  <Empty v-else />
 </template>
 
 <script setup>
@@ -19,6 +21,7 @@ import { useRouter } from 'vue-router'
 import { getJobFairList } from '@/api/recruit/enterprise/jobFair'
 import { getCheckJobFairPermission } from '@/api/recruit/enterprise/jobFair'
 import Snackbar from '@/plugins/snackbar'
+import { timesTampChange } from '@/utils/date'
 
 const router = useRouter()
 const list = ref([])

+ 1 - 1
src/views/recruit/enterprise/jobFair/job/item.vue

@@ -2,7 +2,7 @@
   <div>
     <div v-if="items.length">
       <div v-for="val in items" :key="val.id" class="itemBox mb-3" style="height: 134px;">
-        <div class="d-flex justify-space-between cursor-pointer" style="padding: 10px 20px;" @click="handleEdit(val)">
+        <div class="d-flex justify-space-between cursor-pointer" style="padding: 10px 20px;">
           <div class="position">
             <div class="d-flex align-center">
               <span class="position-name">{{ val.name }}</span>

+ 16 - 4
src/views/recruit/enterprise/membershipPackage/dynamic/package.vue

@@ -23,6 +23,8 @@
     </v-slide-group-item>
   </v-slide-group>
 
+  <div v-if="!Object.keys(select).length" class="color-warning text-center mt-15 font-size-20">请选择要购买的套餐</div>
+
   <div v-if="payType && payQrCodeTxt" id="codeBox" class="code pa-5 resume-box">
     <div class="resume-header">
       <div class="resume-title">扫码支付</div>
@@ -82,7 +84,8 @@ import { useI18n } from '@/hooks/web/useI18n'; const { t } = useI18n()
 
 const current = ref()
 const select = ref({})
-const model = ref(0)
+const model = ref()
+const isMounted = ref(false)
 
 // 套餐列表
 const list = ref([])
@@ -90,7 +93,7 @@ const getPackageList = async () => {
   const data = await getEnterprisePackageList()
   list.value = data
   list.value.push({ id:'custom' })
-  select.value = data[0]
+  // select.value = data[0]
 }
 
 const showCustom = ref(false)
@@ -135,6 +138,7 @@ const payTypeChange = (val) => {
 }
 const timer = ref(null)
 onUnmounted(() => {
+  isMounted.value = false
   if (timer.value) clearInterval(timer.value); timer.value = null
 })
 
@@ -194,6 +198,13 @@ const paySubmit = async () => {
     }
     const res = await payOrderSubmit(params)
     if (!showCustom.value) payQrCodeTxt.value = res?.displayContent || '' // 生成二维码内容
+
+     // 离开当前页面后不执行
+    if (!isMounted.value) {
+      if (timer.value) clearInterval(timer.value); timer.value = null
+      return
+    }
+
     initIntervalFun()
     if (timer.value) clearInterval(timer.value); timer.value = null
     timer.value = setInterval(() => { payStatus() }, 1000) // 轮巡查询用户是否支付
@@ -220,8 +231,8 @@ const getCodeList = async () => {
           if (!payType.value) {
             // 默认值赋值(暂时只支持扫码)
             const bool = qrCodePay.includes(code)
-            // if (bool) payType.value = code
-            if (bool) payTypeChange(code)
+            if (bool) payType.value = code
+            // if (bool) payTypeChange(code)
           }
           payTypeList.value.push(item)
         }
@@ -231,6 +242,7 @@ const getCodeList = async () => {
 }
 
 nextTick(async () => {
+  isMounted.value = true
   await getPackageList()
   await getCodeList()
 })

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

@@ -54,6 +54,7 @@ import { createTradeOrder } from '@/api/position'
 const props = defineProps({
   afterAdd: Function,
   valid: Function,
+  isFair: Boolean
 })
 
 const { t } = useI18n()
@@ -117,7 +118,7 @@ const handleSave = async () => {
 const saveEmit = async () => {
   loading.value = true
   try {
-    const res = await saveJobAdvertised(submitParams)
+    const res = await saveJobAdvertised({ ...submitParams, fair: props.isFair ? true : false }) // fair:是否为招聘会职位编辑-必填
     // status:99为待支付职位,弹窗支付
     if (submitParams?.status && submitParams?.status === '99') {
       loading.value = true

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

@@ -65,9 +65,10 @@
             <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>  
-            <div v-if="tab !== 3 && val.edit">
+            <div v-if="tab !== 3">
               <span class="lines"></span>
-              <span class="cursor-pointer actions" @click="handleEdit(val)">{{ $t('common.edit') }}</span>
+              <span class="cursor-pointer" :class="{'actions': val.edit}" :style="{'color': val.edit ? '#333' : '#999'}" @click="handleEdit(val)">{{ $t('common.edit') }}</span>
+              <v-tooltip v-if="!val.edit" activator="parent" location="top">职位发布时间超过24小时的不支持编辑</v-tooltip>
             </div>
           </div>
         </div>
@@ -273,7 +274,7 @@ const handleSubmit = async () => {
 const router = useRouter()
 // 职位编辑
 const handleEdit = async (val) => {
-  if (!val.id) return
+  if (!val.id || !val.edit) return
   const data = await getEnterprisePubJobTypePermission()
   if (!data || !data.length) return Snackbar.warning('没有该操作权限,请联系平台管理员升级后再试')
   router.push(`/recruit/enterprise/position/edit?id=${val.id}`)
@@ -331,6 +332,6 @@ const handleToResume = (val) => {
   color: var(--color-888);
 }
 .actions:hover {
-  color: var(--v-primary-base);
+  color: var(--v-primary-base) !important;
 }
 </style>

+ 14 - 14
src/views/recruit/enterprise/systemManagement/groupAccount/index.vue

@@ -46,15 +46,15 @@
         >
           <template #name="{ item }">
             <div class="d-flex align-center">
-              <v-badge
+              <!-- <v-badge
                 v-if="(item?.sex === '1' || item?.sex === '2') && showBadge"
                 bordered
                 offset-y="6"
                 :color="badgeColor(item)"
                 :icon="badgeIcon(item)">
                 <v-avatar size="40" :image="getUserAvatar(item.avatar, item.sex)"></v-avatar>
-              </v-badge>
-              <v-avatar v-else size="40" :image="getUserAvatar(item.avatar, item.sex)"></v-avatar>
+              </v-badge> -->
+              <v-avatar size="40" :image="getUserAvatar(item.avatar, item.sex)"></v-avatar>
               <span class="ml-3">{{ item?.name }}</span>
             </div>
           </template>
@@ -141,13 +141,13 @@ const textItem = ref({
   clearable: true,
   label: '请输入用户名称搜索'
 })
-const badgeColor = computed(() => (item) => {
-  return (item && item.sex) ? (item.sex === '1' ? '#1867c0' : 'error') : 'error'
-})
+// const badgeColor = computed(() => (item) => {
+//   return (item && item.sex) ? (item.sex === '1' ? '#1867c0' : 'error') : 'error'
+// })
 
-const badgeIcon = computed(() => (item) => {
-  return (item && item.sex) ? (item.sex === '1' ? 'mdi-gender-male' : 'mdi-gender-female') : 'mdi-gender-female'
-})
+// const badgeIcon = computed(() => (item) => {
+//   return (item && item.sex) ? (item.sex === '1' ? 'mdi-gender-male' : 'mdi-gender-female') : 'mdi-gender-female'
+// })
 
 // 获取用户列表
 const getUserList = async () => {
@@ -266,10 +266,10 @@ const formItems = ref({
     }
   ]
 })
-getDict('menduner_sex').then(({ data }) => {
-  data = data?.length && data || []
-  formItems.value.options.find(e => e.key === 'sex').items = data
-})
+// getDict('menduner_sex').then(({ data }) => {
+//   data = data?.length && data || []
+//   formItems.value.options.find(e => e.key === 'sex').items = data
+// })
 
 
 // 编辑员工信息
@@ -336,7 +336,7 @@ const handleSubmit = async () => {
     id: editId.value
   } 
   formItems.value.options.forEach(e => { obj[e.key] = e.value })
-  if (!obj.sex || obj.sex === '0') return Snackbar.warning('请选择员工性别')
+  // if (!obj.sex || obj.sex === '0') return Snackbar.warning('请选择员工性别')
   await updateGroupUserAccount(obj)
   showEdit.value = false
   editId.value = null

+ 5 - 3
src/views/recruit/enterprise/talentRecommendation/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <div v-if="showLogin" class="login-content">
+    <div v-if="showLogin" class="login-content" :style="{'background-image': 'url(' + webContent.loginBgUrl + ')'}">
       <div class="login-content-box pa-10">
         <div class="login-content-box-title text-center mt-4">请先登录您的企业账号</div>
         <passwordFrom class="mt-10" ref="passRef" placeholder="请输入企业邮箱" :validEmail="true"></passwordFrom>
@@ -73,7 +73,9 @@ import { dealDictArrayData } from '@/utils/position'
 import { getUserAvatar } from '@/utils/avatar'
 import { useRouter } from 'vue-router'
 import FilterPage from './components/filter.vue'
+import { webContentStore } from '@/store/webContent'
 
+const webContent = webContentStore()
 const router = useRouter()
 const loading = ref(false)
 const passRef = ref(null)
@@ -134,7 +136,8 @@ const handleClearJob = () => {
 
 // 组件挂载后添加事件监听器
 const isMobile = ref(false)
-onMounted(() => {
+onMounted(async () => {
+  await webContent.getSystemWebContent()
   if (!token.value) {
     Snackbar.warning('请先登录')
     showLogin.value = true
@@ -253,7 +256,6 @@ const handleSearch = (val) => {
   position: relative;
   width: 100%;
   height: 100vh;
-  background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
   &-box {
     position: absolute;

+ 5 - 3
src/views/register/company.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="box" style="overflow-x: hidden;">
+  <div class="box" style="overflow-x: hidden;" :style="{'background-image': 'url(' + webContent.loginBgUrl + ')'}">
     <navBar v-if="!isMobile" :showLoginBtn="false" class="navBar"></navBar>
     <PhonePage v-if="!valid" :isCompany="true" @success="handleValidate" :isLogin="query.login ? true : false"></PhonePage>
   </div>
@@ -12,9 +12,12 @@ import navBar from '@/layout/personal/navBar.vue'
 import { ref, onMounted } from 'vue'
 import PhonePage from './person.vue'
 import { useRouter } from 'vue-router'
+import { webContentStore } from '@/store/webContent'
 
+const webContent = webContentStore()
 const isMobile = ref(false)
-onMounted(() => {
+onMounted(async () => {
+  await webContent.getSystemWebContent()
   const userAgent = navigator.userAgent
   isMobile.value = /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(userAgent)
 })
@@ -50,7 +53,6 @@ const handleValidate = async () => {
   position: relative;
   width: 100%;
   height: 100%;
-  background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
   background-repeat: no-repeat;
   background-position: center center;

+ 5 - 3
src/views/register/person.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="box">
+  <div class="box" :style="{'background-image': 'url(' + webContent.loginBgUrl + ')'}">
     <navBar v-if="!isMobile" :showLoginBtn="false" class="navBar"></navBar>
     <div class="content pa-10">
       <div class="content-title text-center mt-4">{{ isLogin ? '请输入您申请企业账号时填入的手机号进行效验' : '请输入手机号码进行注册认证'}}</div>
@@ -28,9 +28,12 @@ import { useUserStore } from '@/store/user'
 import Snackbar from '@/plugins/snackbar'
 import { checkCompanyEmail } from '@/utils/validate'
 import navBar from '@/layout/personal/navBar.vue'
+import { webContentStore } from '@/store/webContent'
 
+const webContent = webContentStore()
 const isMobile = ref(false)
-onMounted(() => {
+onMounted(async () => {
+  await webContent.getSystemWebContent()
   const userAgent = navigator.userAgent
   isMobile.value = /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(userAgent)
 })
@@ -96,7 +99,6 @@ const windowOpen = (url) => {
   position: relative;
   width: 100%;
   height: 100%;
-  background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
   display: flex;
   justify-content: center;

+ 5 - 3
src/views/register/select.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="register-box">
+  <div class="register-box" :style="{'background-image': 'url(' + webContent.loginBgUrl + ')'}">
     <navBar v-if="!isMobile" :showLoginBtn="false" class="navBar"></navBar>
     <div class="register-content">
       <h2 style="color: #666; font-weight: 400;">请选择您当前注册的身份</h2>
@@ -22,9 +22,12 @@ import navBar from '@/layout/personal/navBar.vue'
 defineOptions({ name: 'register-select'})
 import { useRouter } from 'vue-router'
 import { ref, onMounted } from 'vue'
+import { webContentStore } from '@/store/webContent'
 
+const webContent = webContentStore()
 const isMobile = ref(false)
-onMounted(() => {
+onMounted(async () => {
+  await webContent.getSystemWebContent()
   const userAgent = navigator.userAgent
   isMobile.value = /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(userAgent)
 })
@@ -41,7 +44,6 @@ const handleToRegister = (path) => {
   position: relative;
   width: 100%;
   height: 100%;
-  background-image: url('https://minio.menduner.com/dev/menduner/login-bgc.jpg');
   background-size: cover;
 }
 .register-content {