فهرست منبع

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

lifanagju_citu 11 ماه پیش
والد
کامیت
0a3132bcba

+ 1 - 1
components.d.ts

@@ -20,7 +20,7 @@ declare module 'vue' {
     CtPagination: typeof import('./src/components/CtPagination/index.vue')['default']
     CtSearch: typeof import('./src/components/CtSearch/index.vue')['default']
     CtTextField: typeof import('./src/components/CtVuetify/CtTextField/index.vue')['default']
-    DatePicker: typeof import('./src/components/DatePicker/index.vue')['default']
+    DatePicker: typeof import('./src/components/FormUI/datePicker/index.vue')['default']
     Details: typeof import('./src/components/Enterprise/details.vue')['default']
     Empty: typeof import('./src/components/Empty/index.vue')['default']
     HeadSearch: typeof import('./src/components/headSearch/index.vue')['default']

+ 176 - 0
src/layout/company/navBar.vue

@@ -0,0 +1,176 @@
+<template>
+  <div>
+    <v-toolbar
+      class="banner"
+      density="compact"
+      style="padding-left: 0px;height: 50px;font-size: 14px;"
+    >
+      <div class="innerBox d-flex justify-space-between">
+        <div>
+          <div class="nav-logo" style="cursor: pointer;" @click="handleLogoClick">
+            <v-img src="../../assets/logo.png"  aspect-ratio="16/9" cover :width="90" style="height: 40px"></v-img>
+          </div>
+        </div>
+        
+        <div class="d-flex user-nav">
+          <div class="d-flex align-center cursor-pointer">
+            <v-img rounded width="40" height="40" src="https://minio.citupro.com/dev/menduner/7.png" ></v-img>
+            <span class="ml-3">广州辞图科技有限公司</span>
+          </div>
+          <div class="line"></div>
+          
+          <!-- 头像用户名 -->
+          <div class="d-flex align-center" v-if="getToken()">
+            <v-menu open-on-hover>
+              <template v-slot:activator="{ props }">
+                <div class="d-flex ml-5 pl-2 align-center cursor-pointer" v-bind="props" @click="handleToPersonalCenter">
+                  <v-avatar>
+                    <v-img alt="" :src="baseInfo?.avatar ?? 'https://minio.citupro.com/dev/menduner/7.png'"></v-img>
+                  </v-avatar>
+                  <div class="ml-2">{{ baseInfo?.name ?? $t('sys.tourist') }}</div>
+                </div>
+              </template>
+
+              <v-list>
+                <v-list-item v-for="(item, index) in items" :key="index" @click="item.change">
+                  <template v-slot:prepend>
+                    <v-icon :icon="item.icon"></v-icon>
+                  </template>
+                  <v-list-item-title>{{ item.title }}</v-list-item-title>
+                </v-list-item>
+              </v-list>
+            </v-menu>
+          </div>
+
+          <!-- 语言切换 -->
+          <v-menu>
+            <template v-slot:activator="{ props }">
+              <v-btn
+                class="ml-3"
+                color="primary"
+                size="small"
+                icon="mdi-translate"
+                v-bind="props"
+              >
+              </v-btn>
+            </template>
+            <v-list density="compact">
+              <v-list-item
+                v-for="item in localeStore.localeMap"
+                :key="item.name"
+                :value="item.lang"
+                :active="localeStore.currentLocale.lang === item.lang"
+                @click="localeStore.setCurrentLocale(item)"
+              >
+                <v-list-item-title>{{ item.name }}</v-list-item-title>
+              </v-list-item>
+            </v-list>
+          </v-menu>
+
+          <v-btn size="small" icon="mdi-bell-outline"></v-btn>
+        </div>
+      </div>
+    </v-toolbar>
+  </div>
+</template>
+
+<script setup>
+import { reactive, ref } from 'vue'
+import { getToken } from '@/utils/auth'
+import { useUserStore } from '@/store/user'
+import { useLocaleStore } from '@/store/locale'
+defineOptions({ name: 'personal-navbar' })
+
+defineProps({
+  sticky: {
+    type: Boolean,
+    default: true
+  }
+})
+
+const localeStore = useLocaleStore()
+const userStore = useUserStore()
+
+import { useRouter } from 'vue-router'
+const router = useRouter()
+const handleLogoClick = () => { router.push({ path: '/enterprise/home'}) }
+
+const show = ref(false)
+const userType = ref(0) // 0企业用户、1个人用户
+const changeRole = () => {
+  if (userType.value) {
+    show.value = true
+    router.push({ path: '/enterprise/register' })
+  } else {
+    // 重新走登录拿数据
+  }
+}
+
+const handleToPersonalCenter = () => {
+  // router.push({ path: '/personalCenter' })
+}
+
+// 退出登录
+const handleLogout = async () => {
+  await userStore.userLogout()
+  router.push({ path: '/login' })
+}
+
+const items = ref([
+  { title: '联系人信息', icon: 'mdi-account-outline', change: () => router.push({ path: '/resume' }) },
+  { title: '账号管理', icon: 'mdi-cog-outline', change: () => router.push({ path: '/personalAccount/accountBinding' }) },
+  { title: '切换为求职者', icon: 'mdi-swap-horizontal', change: changeRole },
+  { title: '退出登录', icon: 'mdi-logout', change: handleLogout }
+])
+const baseInfo = reactive(JSON.parse(localStorage.getItem('baseInfo'))) // 人才信息
+</script>
+
+<style lang="scss" scoped>
+.banner {
+  width: 100%;
+  height: 50px;
+  z-index: var(--zIndex-nav) !important;
+  color: #fff;
+  background-color: #d5e6e8;
+  padding-left: 0px;
+  height: 50px;
+  font-size: 15px;
+  .left {
+    height: 100%;
+    display: flex;
+    align-items: center;
+    font-size: 20px;
+    cursor: pointer;
+  }
+}
+.hover:hover {
+  cursor: pointer;
+  background: rgba(0, 0, 0, 0.03);
+}
+.innerBox {
+  position: relative;
+  width: 100%;
+  align-items: center;
+  padding: 0 30px;
+}
+.nav-logo {
+  float: left;
+}
+.nav {
+  font-size: 0;
+  float: left;
+  margin-left: 50px;
+  height: 49px;
+  line-height: 49px;
+}
+.user-nav {
+  color: var(--v-primary-base);
+}
+.line {
+  width: 1px;
+  height: 25px;
+  background-color: #fff;
+  margin: 0 10px;
+  margin: 8px 0 0 29px;
+}
+</style>

+ 81 - 0
src/layout/company/side.vue

@@ -0,0 +1,81 @@
+<template>
+  <div>
+    <v-list class="side-box" color="primary">
+      <template v-for="(item, index) in list">
+        <template v-if="!item.children.length">
+          <v-list-item
+            :key="`${item.name}_${index}`"
+            active-class="active"
+            color="primary"
+            :href="item.path"
+            :to="item.path"
+            rounded="shaped"
+            :prepend-icon="item.icon"
+            :title="item.title"
+          >
+          </v-list-item>
+        </template>
+        <v-list-group
+          v-else
+          color="primary"
+          rounded="shaped"
+          :key="`${item.name}_${index}`"
+          :value="route.path.indexOf(item.name) > -1"
+          :prepend-icon="item.icon"
+        >
+          <template v-slot:activator="{ props }">
+            <v-list-item v-bind="props" :title="item.title"></v-list-item>
+          </template>
+          <v-list-item
+            v-for="(val, index) in item.children"
+            :key="index"
+            color="primary"
+            :href="val.path"
+            style="padding-left: 40px;"
+            :to="val.path"
+            :title="val.title"
+            rounded="shaped"
+            :value="val.title"
+          ></v-list-item>
+        </v-list-group>
+      </template>
+    </v-list>
+  </div>
+</template>
+
+<script setup>
+defineOptions({ name: 'enterprise-side'})
+import { computed } from 'vue'
+import { useRoute } from 'vue-router'
+import enterpriseRoute from '@/router/modules/enterprise'
+
+const route = useRoute()
+const list = computed(() => {
+  return getList(enterpriseRoute)
+})
+
+const getList = (arr, obj = []) => {
+  arr.forEach(element => {
+    if (element.show) return
+    const data = {}
+    data.title = element?.meta?.title
+    data.enName = element?.meta?.enName
+    data.icon = element?.meta?.icon
+    data.name = element?.name
+    data.path = element?.path
+    data.children = []
+    if (element?.children) {
+      getList(element.children, data.children)
+    }
+    obj.push(data)
+  })
+  return obj
+}
+</script>
+
+<style scoped lang="scss">
+.side-box {
+  width: 250px;
+  height: 100%;
+}
+</style>

+ 56 - 0
src/layout/company/slider.vue

@@ -0,0 +1,56 @@
+<template>
+  <div class="slider-box">
+    <div v-for="(item, index) in list" :key="index" class="slider-box-item" @click="handleClick(index)">
+      <v-btn size="30" class="icons" icon variant="text">
+        <v-icon class="icons" size="30">{{ item.mdi }}</v-icon>
+        <v-tooltip :text="item.tips" location="start" activator="parent">
+          <div v-if="item.showImg" class="ma-3" style="text-align: center">
+            <v-img cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/static/mendunerCode.jpg" :width="170" style="height: 170px;"></v-img>
+            <span class="tips-text">关注门墩儿直聘微信公众号</span>
+          </div>
+          <span v-else>{{ item.tips }}</span>
+        </v-tooltip>
+      </v-btn>
+    </div>
+  </div>
+</template>
+
+<script setup>
+defineOptions({ name: 'personalSlider' })
+const list = [
+  { mdi: 'mdi-arrow-up-bold', tips: '返回顶部' },
+  { mdi: 'mdi-qrcode', tips: '微信公众号', showImg: 'https://minio.citupro.com/dev/static/mendunerCode.jpg' },
+  { mdi: 'mdi-face-agent', tips: '客服' }
+]
+
+const handleClick = (index) => {
+  // 回到顶部
+  if (index === 0) window.scrollTo({ top: 0, behavior: 'smooth' })
+}
+</script>
+
+<style lang="scss" scoped>
+.slider-box {
+  width: 44px;
+  height: 134px;
+  background-color: #fff;
+  border-radius: 22px;
+  box-shadow: 0 4px 20px 0 rgba(0,0,0,.06);
+}
+.slider-box-item {
+  width: 44px;
+  height: 44px;
+  padding: 6px 0;
+  text-align: center;
+}
+.icons {
+  color: #ccc;
+  &:hover {
+    color: var(--v-primary-base);
+  }
+}
+.tip-text {
+  font-size: 14px;
+  color: #222;
+}
+</style>

+ 58 - 0
src/layout/enterprise.vue

@@ -0,0 +1,58 @@
+<template>
+  <div class="parent" @click="layoutClick">
+    <Headers class="headers"></Headers>
+    <div class="content">
+      <side></side>
+      <div class="pa-3">
+        <router-view></router-view>
+      </div>
+    </div>
+    <Slider v-if="whiteList.indexOf(router.currentRoute.value.path) === -1" class="slider"></Slider>
+  </div>
+</template>
+
+<script setup>
+import Headers from './company/navBar.vue'
+import Slider from './company/slider.vue'
+import side from './company/side.vue'
+import { useSharedState } from '@/store/sharedState'
+import { useRouter } from 'vue-router'
+defineOptions({ name: 'enterprise-layout-index' })
+
+// 不展示侧边栏名单
+const whiteList = ['/login', '/privacyPolicy', '/userAgreement', '/register']
+const router = useRouter()
+
+const sharedState = useSharedState()
+
+const layoutClick = () => {
+  sharedState.increment()
+}
+</script>
+
+<style lang="scss" scoped>
+.parent {
+  background-color: var(--default-bgc);
+  position: relative;
+}
+.headers {
+  position: fixed;
+  right: 0;
+  right: 0;
+  left: 0;
+  top: 0;
+  z-index: 999;
+}
+.slider {
+  position: fixed;
+  bottom: 50%;
+  right: 24px;
+  translate: 0 50%;
+  z-index: 999;
+}
+.content {
+  display: flex;
+  margin-top: 50px;
+  height: calc(100vh - 48px);
+}
+</style>

+ 1 - 1
src/layout/index.vue

@@ -15,7 +15,7 @@ import Footers from './personal/footer.vue'
 import Slider from './personal/slider.vue'
 import { useSharedState } from '@/store/sharedState'
 import { useRouter } from 'vue-router'
-defineOptions({ name: 'layout-index' })
+defineOptions({ name: 'personal-layout-index' })
 
 // 不展示侧边栏名单
 const whiteList = ['/login', '/privacyPolicy', '/userAgreement', '/register']

+ 101 - 6
src/router/modules/enterprise.js

@@ -1,18 +1,113 @@
 // 企业路由信息
-import Layout from '@/layout'
+import Layout from '@/layout/enterprise.vue'
 
 const enterprise = [
   {
-    path: '/enterprise/details/:id',
+    path: '/enterprise/talentPool',
     component: Layout,
-    name: 'enterpriseDetails',
+    name: 'talentPool',
     meta: {
-      title: '企业详情'
+      title: '人才库',
+      enName: 'Talent Pool',
+      icon: 'mdi-account-multiple'
     },
     children: [
       {
-        path: '/enterprise/details/:id',
-        component: () => import('@/views/enterprise/components/enterpsieDetails.vue')
+        path: '/enterprise/talentPool',
+        show: true,
+        component: () => import('@/views/enterprise/talentPool/index.vue')
+      }
+    ]
+  },
+  {
+    path: '/enterprise/statistics',
+    component: Layout,
+    name: 'enterpriseStatistics',
+    meta: {
+      title: '统计分析',
+      enName: 'Statistics',
+      icon: 'mdi-chart-arc'
+    },
+    children: [
+      // {
+      //   path: '/enterprise/statistics',
+      //   show: true,
+      //   component: () => import('@/views/enterprise/statistics/index.vue')
+      // },
+      {
+        path: '/enterprise/statistics/overallAnalysis',
+        meta: {
+          title: '整体分析'
+        },
+        component: () => import('@/views/enterprise/statistics/overallAnalysis.vue')
+      }
+    ]
+  },
+  {
+    path: '/enterprise/position',
+    component: Layout,
+    name: 'jobManagement',
+    meta: {
+      title: '职位管理',
+      enName: 'Job Management',
+      icon: 'mdi-format-list-bulleted-square'
+    },
+    children: [
+      {
+        path: '/enterprise/position',
+        show: true,
+        component: () => import('@/views/enterprise/positionManagement/index.vue')
+      }
+    ]
+  },
+  {
+    path: '/enterprise/communication',
+    component: Layout,
+    name: 'Communication',
+    meta: {
+      title: '沟通',
+      enName: 'Communication',
+      icon: 'mdi-bell-outline'
+    },
+    children: [
+      {
+        path: '/enterprise/communication',
+        show: true,
+        component: () => import('@/views/enterprise/communication/index.vue')
+      }
+    ]
+  },
+  {
+    path: '/enterprise/infoManagement',
+    component: Layout,
+    name: 'infoManagement',
+    meta: {
+      title: '信息管理',
+      enName: 'Info Management',
+      icon: 'mdi-list-box'
+    },
+    children: [
+      {
+        path: '/enterprise/infoManagement',
+        show: true,
+        component: () => import('@/views/enterprise/infoManagement/index.vue')
+      }
+    ]
+  },
+  {
+    path: '/enterprise/systemManagement',
+    component: Layout,
+    name: 'systemManagement',
+    meta: {
+      title: '系统管理',
+      enName: 'System Management',
+      icon: 'mdi-tune'
+    },
+    children: [
+      {
+        path: '/enterprise/systemManagement',
+        show: true,
+        component: () => import('@/views/enterprise/systemManagement/index.vue')
       }
     ]
   }

+ 14 - 0
src/router/modules/recruit.js

@@ -32,6 +32,20 @@ const recruit = [
         }
       }
     ]
+  },
+  {
+    path: '/enterprise/details/:id',
+    component: Layout,
+    name: 'enterpriseDetails',
+    meta: {
+      title: '企业详情'
+    },
+    children: [
+      {
+        path: '/enterprise/details/:id',
+        component: () => import('@/views/enterprise/components/enterpsieDetails.vue')
+      }
+    ]
   }
 ]
 export default recruit

+ 3 - 1
src/views/Home/enterprise/index.vue → src/views/Home/company/index.vue

@@ -4,10 +4,11 @@
     <v-btn class="half-button mt-5" size="small" color="primary" variant="tonal" @click="handleChange">切换为求职者</v-btn>
   </div>
 </template>
+
 <script setup>
+defineOptions({ name:'enterprise-home-index'})
 // import { useLoginType } from '@/store/loginType'
 // import { useRouter } from 'vue-router'
-defineOptions({ name:'enterprise-index'})
 
 // const router = useRouter()
 // const changeLoginType = useLoginType()
@@ -16,6 +17,7 @@ const handleChange = () => {
   // changeLoginType.change(1)
 }
 </script>
+
 <style lang="scss" scoped>
 
 </style>

+ 13 - 0
src/views/Home/enterprise.vue

@@ -0,0 +1,13 @@
+<template>
+  <enterprise></enterprise>
+</template>
+
+<script setup>
+defineOptions({ name: 'enterprise-home-index'})
+
+import enterprise from './company'
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 3 - 7
src/views/Home/index.vue

@@ -1,16 +1,12 @@
 <template>
-  <div>
-    <enterprise v-if="type" ref="enterpriseRef"></enterprise>
-    <personal v-else ref="personalRef"></personal>
-  </div>
+  <personal ref="personalRef"></personal>
 </template>
+
 <script setup>
 defineOptions({ name:'home-index'})
-import { ref } from 'vue';
-import enterprise from './enterprise/index.vue'
 import personal from './personal/index.vue'
-const type = ref(0)
 </script>
+
 <style lang="scss" scoped>
 
 </style>

+ 11 - 0
src/views/enterprise/communication/index.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>沟通</div>
+</template>
+
+<script setup>
+defineOptions({ name: 'enterprise-communication'})
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 11 - 0
src/views/enterprise/infoManagement/index.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>企业资料管理</div>
+</template>
+
+<script setup>
+defineOptions({ name: 'enterprise-info-management'})
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 11 - 0
src/views/enterprise/positionManagement/index.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>职位管理</div>
+</template>
+
+<script setup>
+defineOptions({ name: 'formPage'})
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 11 - 0
src/views/enterprise/statistics/index.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>统计分析</div>
+</template>
+
+<script setup>
+defineOptions({ name: 'enterprise-statistics'})
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 11 - 0
src/views/enterprise/statistics/overallAnalysis.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>整体分析</div>
+</template>
+
+<script setup>
+defineOptions({ name: 'overallAnalysis'})
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 11 - 0
src/views/enterprise/systemManagement/index.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>系统管理</div>
+</template>
+
+<script setup>
+defineOptions({ name: 'enterprise-system-management'})
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 11 - 0
src/views/enterprise/talentPool/index.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>人才库</div>
+</template>
+
+<script setup>
+defineOptions({ name: 'enterprise-talent-pool'})
+</script>
+
+<style scoped lang="scss">
+
+</style>