فهرست منبع

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

lifanagju_citu 4 ماه پیش
والد
کامیت
a05868bc36

+ 1 - 1
.env.demo

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

+ 0 - 1
components.d.ts

@@ -29,7 +29,6 @@ declare module 'vue' {
     CtTextField: typeof import('./src/components/CtVuetify/CtTextField/index.vue')['default']
     DatePicker: typeof import('./src/components/DatePicker/index.vue')['default']
     Echarts: typeof import('./src/components/Echarts/index.vue')['default']
-    ElCascader: typeof import('element-plus/es')['ElCascader']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     Empty: typeof import('./src/components/Empty/index.vue')['default']
     File: typeof import('./src/components/Upload/file.vue')['default']

+ 1 - 0
package.json

@@ -3,6 +3,7 @@
   "version": "0.0.0",
   "scripts": {
     "dev": "vite --mode localDev --host 0.0.0.0",
+    "demo": "vite --mode demo --host 0.0.0.0",
     "build:dev": "vite build --mode production",
     "build:demo": "vite build --mode demo",
     "preview": "vite preview",

+ 2 - 1
src/components/Enterprise/hotPromoted.vue

@@ -3,7 +3,7 @@
     <div class="sub-li" v-for="(item, index) in list" :key="index">
       <div v-if="item">
         <!-- 公司信息 -->
-        <div class="company-info-top align-center" @click="handleClickEnterprise(item)">
+        <div class="company-info-top align-center" @click="jumpToEnterpriseDetail(item.enterprise.id, true)">
           <div class="float-left">
             <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>
@@ -51,6 +51,7 @@
 import { ref, watch } from 'vue'
 import { timesTampChange } from '@/utils/date'
 import { formatName } from '@/utils/getText'
+import { jumpToEnterpriseDetail } from '@/utils/position'
 
 const props = defineProps({
   items: {

+ 3 - 25
src/components/Enterprise/info.vue

@@ -4,9 +4,7 @@
     <div style="height: 50px; line-height: 50px;">
       <v-img class="float-left" :src="props.info.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'" :width="45" height="45"></v-img>
       <div class="ml-3 float-left">
-        <p class="enterprise-name cursor-pointer" @click="handleEnterprise(0)">{{ formatName(props.info.enterprise.anotherName || props.info.enterprise.name) }}</p>
-        <!-- <v-icon :color="statusInfo.color" size="20">{{ statusInfo.mdi }}</v-icon>
-        <span :style="{'color': statusInfo.color,'font-size': '14px'}">{{ statusInfo.label }}</span> -->
+        <p class="enterprise-name cursor-pointer" @click="jumpToEnterpriseDetail(props.info.enterprise.id, true)">{{ formatName(props.info.enterprise.anotherName || props.info.enterprise.name) }}</p>
       </div>
     </div>
     <div class="mt-3 border-bottom-dashed" style="font-size: 14px;">
@@ -16,7 +14,7 @@
       </div>
     </div>
     <div style="font-size: 12px;height: 50px; line-height: 50px">
-      <span class="float-right more-position" @click="handleEnterprise(1)">{{ $t('position.allBtn') }}<v-icon>mdi-chevron-right</v-icon></span>
+      <span class="float-right more-position" @click="jumpToEnterpriseDetail(info.enterprise.id, true, 1)">{{ $t('position.allBtn') }}<v-icon>mdi-chevron-right</v-icon></span>
     </div>
   </div>
 </template>
@@ -24,9 +22,8 @@
 <script setup>
 defineOptions({ name: 'enterprise-info' })
 import { ref } from 'vue'
-import { dealDictObjData } from '@/utils/position'
+import { dealDictObjData, jumpToEnterpriseDetail } from '@/utils/position'
 import { formatName } from '@/utils/getText'
-// import { getEnterpriseAuthDetails } from '@/api/position'
 
 const props = defineProps({
   info: {
@@ -39,32 +36,13 @@ const list = [
   { icon: 'mdi-account-multiple', label: 'scaleName' },
   { icon: 'mdi-family-tree', label: 'industryName' }
 ]
-// const statusList = [
-//   { label: '未认证', color: '#fb8c00', value: null, mdi: 'mdi-shield-remove' },
-//   { label: '审核中', color: '#fb8c00', value: '0', mdi: 'mdi-shield-half-full' },
-//   { label: '已认证', color: 'var(--v-primary-base)', value: '1', mdi: 'mdi-shield-check' },
-//   { label: '已驳回', color: '#fe574a', value: '2', mdi: 'mdi-shield-off' }
-// ]
 
 const obj = ref({})
-// const authInfo = ref({})
 const getData = async () => {
   const prise = props.info.enterprise
   obj.value = dealDictObjData({}, prise)
-  // 企业实名认证信息
-  // authInfo.value = await getEnterpriseAuthDetails(props.info.enterprise.id)
 }
 getData()
-
-// const statusInfo = computed(() => {
-//   const obj = (authInfo.value && Object.keys(authInfo.value).length) ? statusList.find(e => e.value === authInfo.value.status) : statusList[0]
-//   return obj
-// })
-
-const handleEnterprise = (val) => {
-  const key = val ? 'recruitmentPositions' : 'briefIntroduction'
-  window.open(`/recruit/personal/company/details/${props.info.enterprise.id}?key=${key}`)
-}
 </script>
 
 <style lang="scss" scoped>

+ 3 - 6
src/components/Position/item.vue

@@ -30,7 +30,7 @@
           </div>
           <div v-if="tab === 2" class="font-size-14 mb-3 text-end" style="color: #345768;">发布时间:{{ timesTampChange(item.createTime, 'Y-M-D h:m') }}</div>
         </div>
-        <div class="sub-li-bottom" @click="handleEnterprise(item)">
+        <div class="sub-li-bottom" @click="jumpToEnterpriseDetail(item.enterpriseId, true)">
           <div class="user-info">
             <div class="d-flex align-center">
               <v-avatar size="35">
@@ -55,9 +55,9 @@
 <script setup>
 defineOptions({ name: 'position-card-item' })
 import { ref, watch } from 'vue'
-import { commissionCalculation } from '@/utils/position'
+import { commissionCalculation, jumpToEnterpriseDetail } from '@/utils/position'
 import { timesTampChange } from '@/utils/date'
-import { formatName } from '@/utils/getText';
+import { formatName } from '@/utils/getText'
 
 const props = defineProps({
   items: {
@@ -88,9 +88,6 @@ const emits = defineEmits(['position', 'enterprise'])
 const handlePosition = (item) => {
   emits('position', item)
 }
-const handleEnterprise = (item) => {
-  emits('enterprise', item)
-}
 </script>
 
 <style lang="scss" scoped>

+ 3 - 6
src/components/Position/longCompany.vue

@@ -6,7 +6,7 @@
           <div class="float-left mr-5">
             <v-img :src="item.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'" :alt="item.anotherName" :width="40" style="height: 40px;border-radius: 4px;"/>
           </div>
-          <h3 :class="{'default-active': item.active }" class="cursor-pointer" @click="handleClickEnterprise(item, 'briefIntroduction')">{{ formatName(item.anotherName || item.name) }}</h3>
+          <h3 :class="{'default-active': item.active }" class="cursor-pointer" @click="jumpToEnterpriseDetail(item.id, true)">{{ formatName(item.anotherName || item.name) }}</h3>
           <p>{{ item.industryName }}<span v-if="item.industryName && item.scaleName" class="mx-2">|</span>{{ item.scaleName }}</p>
         </div>
         <div v-if="item.active">
@@ -20,7 +20,7 @@
             <span class="septal-line" v-if="i !== item.welfareList.length - 1 && val && item.welfareList[i + 1]"></span>
           </div>
         </div>
-        <div class="position" @click="handleClickEnterprise(item, 'recruitmentPositions')">
+        <div class="position" @click="jumpToEnterpriseDetail(item.id, true, 1)">
           查看全部职位
           <v-icon>mdi-menu-right</v-icon>
         </div>
@@ -35,6 +35,7 @@ import Snackbar from '@/plugins/snackbar'
 import { useI18n } from '@/hooks/web/useI18n'
 import { formatName } from '@/utils/getText'
 import { getEnterpriseUnsubscribe } from '@/api/enterprise'
+import { jumpToEnterpriseDetail } from '@/utils/position'
 
 const emits = defineEmits(['refresh'])
 defineProps({
@@ -43,10 +44,6 @@ defineProps({
 
 const { t } = useI18n()
 
-const handleClickEnterprise = (item, key) => {
-  window.open(`/recruit/personal/company/details/${item.id}?key=${key}`)
-}
-
 // 取消收藏
 const handleCancel = async (item) => {
   if (!item.id) return Snackbar.warning(t('sys.api.operationFailed'))

+ 2 - 6
src/components/Position/longStrip.vue

@@ -35,7 +35,7 @@
             <v-img width="50" height="50" :src="val.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/7.png'"></v-img>
           </div>
           <div class="ml-3">
-            <div class="cursor-pointer info-name" @click="handleToEnterprise(val)">{{ formatName(val.enterprise.anotherName || val.enterprise.name) }}</div>
+            <div class="cursor-pointer info-name" @click="jumpToEnterpriseDetail(val.enterprise.id)">{{ formatName(val.enterprise.anotherName || val.enterprise.name) }}</div>
             <div class="mt-3 ellipsis color-666 font-size-13" style="max-width: 260px;">
               <span v-for="(k, i) in desc" :key="k">
                 {{ val.enterprise[k] }}
@@ -66,6 +66,7 @@ import { getToken } from '@/utils/auth'
 import { checkPersonBaseInfo } from '@/utils/check'
 import dialogExtend from '@/plugins/dialogExtend'
 import { formatName } from '@/utils/getText'
+import { jumpToEnterpriseDetail } from '@/utils/position'
 
 const emits = defineEmits(['refresh'])
 const { t } = useI18n()
@@ -97,11 +98,6 @@ const handleToPositionDetails = (item) => {
   router.push(`/recruit/personal/position/details/${item.job.id}`)
 }
 
-// 企业详情
-const handleToEnterprise = (item) => {
-  router.push(`/recruit/personal/company/details/${item.enterprise.id}?key=briefIntroduction`)
-}
-
 let toDetailsInfo = {}
 // 立即沟通
 const toDetails = async (info) => {

+ 8 - 12
src/components/PositionLongStrip/item.vue

@@ -31,14 +31,14 @@
         </div>
       </div>
       <!-- 公司 -->
-      <div class="company" @click="handleEnterprise(item)">
+      <div class="company" @click="jumpToEnterpriseDetail(item.enterprise.id, true)">
         <div class="float-left">
           <v-img :src="item?.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'" :alt="item.enterprise.anotherName" :width="40" style="height: 40px;border-radius: 4px;"/>
         </div>
         <div class="company-info">
           <v-hover>
             <template v-slot:default="{ isHovering, props }">
-              <h3 v-bind="props" :class="{'default-active': isHovering }" class="title1">{{ formatName(item.enterprise.anotherName, item.enterprise.name) }}</h3>
+              <h3 v-bind="props" :class="{'default-active': isHovering }" class="title1">{{ formatName(item.enterprise.anotherName || item.enterprise.name) }}</h3>
             </template>
           </v-hover>
           <p class="mt-2">
@@ -57,12 +57,12 @@
           <span class="textColor666 dis">{{ jobTag }}</span>
         </template>
       </div>
-      <div class="footer-right">
-        <v-avatar size="x-small" :image="getUserAvatar(item.contact.avatar, item.contact.sex)"></v-avatar>
+      <div class="footer-right" v-if="item.contact">
+        <v-avatar size="x-small" :image="getUserAvatar(item.contact?.avatar, item.contact?.sex)"></v-avatar>
         <span class="mx-2 textColor666">
-          {{ item.contact.name }}
+          {{ item.contact?.name }}
           <span v-if="item?.contact?.postNameCn">|</span>
-          {{ item.contact.postNameCn }}
+          {{ item.contact?.postNameCn }}
         </span>
       </div>
     </div>
@@ -75,6 +75,7 @@ defineOptions({ name: 'long-strip-position-card-item' })
 import { ref, watch } from 'vue'
 import { getUserAvatar } from '@/utils/avatar'
 import { formatName } from '@/utils/getText'
+import { jumpToEnterpriseDetail } from '@/utils/position'
 
 const props = defineProps({
   items: {
@@ -99,15 +100,10 @@ const desc = [
 ]
 
 const handlePosition = (item) => {
-  const id = item.job.id // item.job.positionId
+  const id = item.job.id
   if (!id) return
   window.open(`/recruit/personal/position/details/${id}`)
 }
-const handleEnterprise = (item) => {
-  const id = item.enterprise.id // item.enterprise.enterpriseId
-  if (!id) return
-  window.open(`/recruit/personal/company/details/${id}?key=briefIntroduction`)
-}
 </script>
 
 <style lang="scss" scoped>

+ 16 - 12
src/config/axios/service.js

@@ -111,36 +111,38 @@ service.interceptors.request.use(
       const raw = config.url.split('?')[1]
       // const raw = config.encodeParams ? config.url.split('?')[1] : config.url.split('?')[1]
       const body = {
-        ...config.data,
-        ...config.params
+        ...typeof config.data === 'string' ? JSON.parse(config.data) : config.data,
+        ...typeof config.params === 'string' ? JSON.parse(config.params) : config.params
       }
       /**
        * header
        * params: { data, params, raw }
        * content
        */
-      if (import.meta.env.VITE_USER_NODE_ENV === 'production' && systemInfo.beijingTimestamp === 0) {
+      const env = import.meta.env.VITE_USER_NODE_ENV
+      // console.log(env)
+      if (env === 'production' && systemInfo.beijingTimestamp === 0) {
         const _timestamp = await getBeijingTimestamp()
         setBeijingTimestamp(_timestamp)
       }
       
-      const { noSign, ...header} = encryptionFun({
+      const header = encryptionFun({
         raw,
         body,
         appId: 'web_client',
         AppSecret: 'fa0fc0b5098b974b',
         // timestamp: 1735282548997,
-        timestamp: import.meta.env.VITE_USER_NODE_ENV === 'production' ? systemInfo.beijingTimestamp : new Date().getTime(),
+        timestamp: env === 'production' ? systemInfo.beijingTimestamp : new Date().getTime(),
       })
       const content = {
         data: config.data,
         params: config.params,
         body,
         raw,
-        noSign,
-        config,
-        browserInfo: getBrowserInfo()
+        config
+        // browserInfo: getBrowserInfo()
       }
+      console.log('加密参数', content)
       errorData.push({
         time: header.timestamp,
         url: config.url,
@@ -274,14 +276,15 @@ service.interceptors.response.use(
     }
     const _index = errorData.findIndex(e => e.url === config.url && e.time === +config.headers.timestamp)
     if (_index > -1) {
-      const _spliceItem = errorData.splice(_index, 1)
-      const _item = _spliceItem[0]
- 
+      const _d = errorData.splice(_index, 1)
+      // const _item = JSON.parse(JSON.stringify(errorData[_index]))
+      const _item = _d[0]
       // 保存错误信息
       if (code === 400) {
         sendError({ content: JSON.stringify(_item.content), mark: _item.time + '' })
       }
     }
+    // errorData.splice(_index, 1)
     if (code !== 200) {
       Snackbar.error(msg)
       return Promise.reject(msg)
@@ -333,7 +336,8 @@ const handleAuthorized = (response) => {
     }
     isReLogin.show = true
     Confirm(t('common.confirmTitle'), t('sys.api.timeoutMessage'), {
-      cancelCallback: true
+      cancelCallback: true,
+      hideCancelBtn: true // 不能取消
     }).then(() => {
       // resetRouter() // 重置静态路由表
       // deleteUserCache() // 删除用户缓存

+ 1 - 1
src/layout/index.vue

@@ -2,7 +2,7 @@
   <div class="parent" @click="layoutClick">
     <NavBar class="headers"></NavBar>
     <div class="content">
-      <router-view></router-view>
+      <router-view :key="router.currentRoute.value.path + Math.random()"></router-view>
       <!-- <router-view v-slot="{ Component }">
         <keep-alive>
           <component :is="Component" :key="router.currentRoute.value.path" v-if="router.currentRoute.value.meta?.keepAlive"/>

+ 8 - 10
src/router/modules/recruit.js

@@ -76,16 +76,6 @@ const recruit = [
           title: '我的'
         },
         children: [
-          // {
-          //   path: '/mall/user/cart',
-          //   component: () => import('@/views/mall/user/cart/index.vue'),
-          //   name: 'mallUserCart',
-          //   meta: {
-          //     title: '购物车',
-          //     enName: 'My Cart',
-          //     icon: 'mdi-cart-outline'
-          //   }
-          // },
           {
             path: '/mall/user/order',
             component: () => import('@/views/mall/user/order/index.vue'),
@@ -126,6 +116,14 @@ const recruit = [
           title: '订单详情'
         }
       },
+      {
+        path: '/mall/order/settlement/:id',
+        component: () => import('@/views/mall/settlement/index.vue'),
+        show: true,
+        meta: {
+          title: '订单结算页'
+        }
+      },
       // {
       //   path: '/mall/order',
       //   component: () => import('@/views/mall/order/index.vue'),

+ 1 - 3
src/utils/openEncryption.js

@@ -38,10 +38,8 @@ export const encryptionFun = ({raw, body, appId, AppSecret, timestamp}) => {
   if (body && Object.keys(body).length) {
     str += decodeURIComponent(JSON.stringify(body))
   }
-  const noSign = str + paramsStr
   return {
     ...initSign,
-    noSign: noSign,
-    sign: sha256(noSign)
+    sign: sha256(str + paramsStr)
   }
 }

+ 25 - 0
src/utils/position.js

@@ -96,4 +96,29 @@ export const FenYuanTransform = (count, type='toYuan') => {
   if (!count) return ''
   const Magnification = type === 'toCent' ? 100 : 1/100 
   return type === 'toCent' ? (count - 0)*Magnification : ((count - 0)*Magnification).toFixed(2)
+}
+
+
+
+
+// 跳转企业详情(有优选集团页面则跳转集团页面,没有则跳转企业详情页面)
+import router from '@/router'
+import { getWebContent } from '@/api/common'
+const preferred = ref({})
+
+const getSystemWebContent = async () => {
+  const data = await getWebContent()
+  // 优选集团
+  preferred.value = data.appPreferredGroup
+}
+
+export const jumpToEnterpriseDetail = async (id, isOpenWindow = false, tabKey = 0) => {
+  if (!preferred.value || !Object.keys(preferred.value).length) await getSystemWebContent()
+
+  // 跳转集团页面
+  if (preferred.value[id] && Object.keys(preferred.value[id]).length > 0) return window.open(`/recruit/personal/advertisement/${id}`)
+
+  // 不在优选集团中跳转企业详情
+  const key = tabKey ? 'recruitmentPositions' : 'briefIntroduction'
+  isOpenWindow ? window.open(`/recruit/personal/company/details/${id}?key=${key}`) : router.push(`/recruit/personal/company/details/${id}?key=${key}`)
 }

+ 1 - 1
src/version.js

@@ -1,2 +1,2 @@
 // 版本号
-export const vue_version = 'v25.01.02.1854'
+export const vue_version = 'v25.01.03.1816'

+ 18 - 8
src/views/mall/components/details.vue

@@ -1,10 +1,11 @@
 <!-- 商品详情 -->
 <template>
 <div>
-  <Navbar />
-  <div class="default-width pb-5 mt-3" v-if="state.goodsInfo && Object.keys(state.goodsInfo).length">
+  <!-- <Navbar /> -->
+  <div class="default-width pb-5 mt-3 pt-3" v-if="state.goodsInfo && Object.keys(state.goodsInfo).length">
     <v-card class="carousel border-radius-8 white-bgc pa-5" style="width: 100%;">
-      <div class=" d-flex">
+      <v-btn variant="text" size="x-large" prepend-icon="mdi-chevron-triple-left" color="primary" @click.stop="router.go(-1)">返回</v-btn>
+      <div class="mt-1 d-flex">
         <!-- 图片展示-轮播 -->
         <div style="width: 400px; height: 400px;">
           <div v-if="selectedSkuPicUrl" class="selectedSkuImgBox" @mouseover="showSelectedSkuImg = true" @mouseleave="showSelectedSkuImg = false">
@@ -29,12 +30,19 @@
           <!-- 小标题 -->
           <div class="title-introduction">{{ state.goodsInfo?.introduction || '--' }}</div>
           <!-- 价格 -->
-          <div class="prices py-4 px-5 my-3" :class="{'activePrices': showActivePrices}">
+          <div class="prices py-4 my-3">
             <div class="left">
               <div class="price mr-5"><span>¥</span>{{ selectedSkuPrice}}</div>
               <div class="marketPrice" v-if="selectedSkuMarketPrice && selectedSkuMarketPrice !== selectedSkuPrice">优惠前¥{{ selectedSkuMarketPrice}}</div>
             </div>
-            <div v-if="showActivePrices" class="right">下单即可参与房券抽奖活动,百分百中奖,快来下单参与抽奖吧~</div>
+            <div v-if="showActivePrices" :class="{'activePrices': showActivePrices}" class="right pa-3 mt-3">
+              <div>优惠大赠送!</div>
+              <div>购买一份人力资源薪酬报告,可获赠一张超值酒店住宿房券!!!先到先得,赠完为止。</div>
+              <div class="cursor-pointer">
+                <v-icon>mdi-help-circle-outline</v-icon>
+                <span class="text-decoration-underline">查看赠送活动详情</span>
+              </div>
+            </div>
           </div>
           <!-- 销量 -->
           <div class="salesCount mb-5 parameterColor"><span class="l-s-10">已售</span>:{{ state.goodsInfo?.salesCount || 0 }}</div>
@@ -166,12 +174,13 @@ const skuInfo = ref(null) // 购买商品规格信息
 const onBuy = async (e) => {
   if (!getToken()) return handleLogin()
   if (!e?.id) return Snackbar.warning('请选择商品规格!')
-  // console.log('购买规格信息:', e)
-  //
+
   skuInfo.value = JSON.stringify({
-    items: [{ skuId: e.id, count: e.goods_num, categoryId: state.goodsInfo.categoryId, }]
+    items: [{ skuId: e.id, count: e.goods_num, categoryId: state.goodsInfo.categoryId }]
   })
   showSettlement.value = true
+
+  // router.push(`/mall/order/settlement/${e.id}?count=${e.goods_num}`)
 }
 
 // 创建订单完成
@@ -276,6 +285,7 @@ const loginClose = () => {
 .activePrices {
   color: #fff;
   background-color: #fb0037;
+  border-radius: 10px;
 }
 .price {
   font-weight: 600;

+ 3 - 3
src/views/mall/home/index.vue

@@ -3,8 +3,8 @@
     <!-- 导航栏 -->
     <Navbar />
 
-    <div id="contentBox" ref="scrollBox">
-      <div class="default-width pb-10">
+    <div id="contentBox" ref="scrollBox" class="pt-3">
+      <div class="default-width pb-5">
         <!-- 轮播图 -->
         <div v-if="carouselList.length" style="height: 400px;">
           <v-carousel cycle hide-delimiter-background show-arrows="hover" style="height: 100%;">
@@ -59,7 +59,7 @@ onMounted(async () => {
 const tab = ref(0)
 const tabList = [
   { title: '热门商品', value: 0 },
-  { title: '积分兑换', value: 1 }
+  { title: '兑换专区', value: 1 }
 ]
 
 let template = ref(JSON.parse(localStorage.getItem('mallTemplate')) || {})

+ 188 - 0
src/views/mall/settlement/index.vue

@@ -0,0 +1,188 @@
+<template>
+	<v-card class="default-width pa-5 mb-5" style="min-height: 75vh; margin-top: 70px;">
+		<div>
+    <!-- 头部地址选择【配送地址】【自提地址】 -->
+    <AddressSelection v-model="addressState" class="addressBox elevation-3" />
+    
+    <!-- 购买的商品信息 -->
+    <v-card class="goodsListBox my-3 pa-3 elevation-5">
+      <s-goods-item
+        v-for="(item, index) in state.orderInfo.items"
+        :key="item.skuId"
+        :img="item.picUrl"
+        :title="item.spuName"
+        :skuText="item.properties.map((property) => property.valueName).join(' ')"
+        :price="item.price"
+        :num="item.count"
+        :style="{'marginTop': index ? '8px' : '0px'}"
+      />
+    </v-card>
+
+    <!-- 价格信息 -->
+    <div>
+      <div>
+        <!-- <div class="order-item d-flex color-666">
+          <div class="item-title mr-3 ">商品金额:</div>
+          <div>¥{{ fen2yuan(state.orderInfo.price.totalPrice) }}</div>
+        </div> -->
+        <!-- 快递配置时,信息的展示 -->
+        <!-- <div
+          class="order-item d-flex"
+          v-if="addressState.deliveryType === 1"
+        >
+          <div class="item-title mr-3">运{{ spaces() }}费:</div>
+          <div>
+            <span class="text-red" v-if="state.orderInfo.price.deliveryPrice > 0">
+              +¥{{ fen2yuan(state.orderInfo.price.deliveryPrice) }}
+            </span>
+            <div class="item-value" v-else>免运费</div>
+          </div>
+        </div> -->
+        <!-- 门店自提时,需要填写姓名和手机号 -->
+      </div>
+      
+      <div class="mt-5">
+        <v-text-field
+          v-model="state.orderPayload.remark"
+          label="订单备注" 
+          placeholder="建议留言前先与商家沟通"
+          variant="outlined" 
+          density="compact"
+          color="primary"
+        ></v-text-field>
+      </div>
+
+      <div class="total-box-footer d-flex flex-column align-end">
+        <div class="d-flex">
+          <div class="mr-3">
+            <span class="total-num">共</span>
+            <span class="mx-1" style="color: var(--v-primary-base);">{{ state.orderInfo.items.reduce((acc, item) => acc + item.count, 0) }}</span>
+            <span class="total-num">件</span>
+          </div>
+          <div>合计支付:</div>
+          <div class="total-num text-red"> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }}元</div>
+        </div>
+      </div>
+
+			<div class="text-center">
+				<div>请在30分钟内完成支付,支付成功后可以随机抽取赠送的房券。</div>
+				<v-btn class="elevation-5" color="primary" width="250">立即支付</v-btn>
+				<div>支付时间还剩余30分27秒</div>
+			</div>
+
+    </div>
+  </div>
+	</v-card>
+</template>
+
+<script setup>
+defineOptions({ name: 'mall-order-settlement' })
+import { useRoute, useRouter } from 'vue-router'
+import { reactive, ref, onMounted, watch } from 'vue'
+import AddressSelection from '@/views/mall/components/details/order/addressSelection.vue'
+import sGoodsItem from '@/views/mall/components/s-goods-item'
+import { fen2yuan } from '@/hooks/web/useGoods'
+import { spaces } from '@/utils/index.js'
+import { getTradeConfig, createOrder, settlementOrder } from '@/api/mall/trade'
+import Snackbar from '@/plugins/snackbar'
+
+const route = useRoute()
+const router = useRouter()
+const { id } = route.params
+const { count }	= route.query
+
+const state = reactive({
+  orderPayload: {},
+  orderInfo: {
+    items: [], // 商品项列表
+    price: {}, // 价格信息
+  },
+  showCoupon: false, // 是否展示优惠劵
+  couponInfo: [], // 优惠劵列表
+  showDiscount: false, // 是否展示营销活动
+  // ========== 积分 ==========
+  pointStatus: false, //是否使用积分
+});
+// 检测支付环境
+const payState = reactive({
+  orderType: 'goods', // 订单类型; goods - 商品订单, recharge - 充值订单
+  orderInfo: {}, // 支付单信息
+  payStatus: 0, // 0=检测支付环境, -2=未查询到支付单信息, -1=支付已过期, 1=待支付,2=订单已支付
+  payMethods: [], // 可选的支付方式
+  payment: '', // 选中的支付方式
+});
+const addressState = ref({
+  addressInfo: {}, // 选择的收货地址
+  deliveryType: undefined, // 收货方式:1-快递配送,2-门店自提
+  isPickUp: true, // 门店自提是否开启
+  pickUpInfo: {}, // 选择的自提门店信息
+  receiverName: '', // 收件人名称
+  receiverMobile: '', // 收件人手机
+});
+async function tradeConfig () {
+  // 获取交易配置
+  const data = await getTradeConfig();
+  addressState.value.isPickUp = data.deliveryPickUpEnabled;
+  // 价格计算
+  // 情况一:先自动选择“快递物流”
+  addressState.value.deliveryType = 1;
+  let orderCode = await getOrderInfo();
+  if (orderCode === 0) {
+    return;
+  }
+  // 情况二:失败,再自动选择“门店自提”
+  if (addressState.value.isPickUp) {
+    addressState.value.deliveryType = 2;
+    let orderCode = await getOrderInfo();
+    if (orderCode === 0) {
+      return;
+    }
+  }
+  // 情况三:都失败,则不选择
+  addressState.value.deliveryType = undefined;
+  await getOrderInfo()
+}
+
+// 检查库存 & 计算订单价格
+async function getOrderInfo() {
+    // 计算价格
+    const data = await settlementOrder({
+      items: [{ skuId: id, count }],
+      couponId: state.orderPayload.couponId,
+      deliveryType: addressState.value.deliveryType,
+      addressId: addressState.value.addressInfo.id, // 收件地址编号
+      pickUpStoreId: addressState.value.pickUpInfo.id, //自提门店编号
+      receiverName: addressState.value.receiverName, // 选择门店自提时,该字段为联系人名
+      receiverMobile: addressState.value.receiverMobile, // 选择门店自提时,该字段为联系人手机
+      pointStatus: state.pointStatus,
+      combinationActivityId: state.orderPayload.combinationActivityId,
+      combinationHeadId: state.orderPayload.combinationHeadId,
+      seckillActivityId: state.orderPayload.seckillActivityId,
+      pointActivityId: state.orderPayload.pointActivityId,
+    });
+    state.orderInfo = data;
+    state.couponInfo = data.coupons || [];
+    // 设置收货地址
+    if (state.orderInfo.address) {
+      addressState.value.addressInfo = state.orderInfo.address;
+    }
+    return 0;
+  }
+
+	// 使用 watch 监听地址和配送方式的变化
+  watch(addressState, async (newAddress, oldAddress) => {
+    // 如果收货地址或配送方式有变化,则重新计算价格
+    if (
+      newAddress.addressInfo.id !== oldAddress.addressInfo.id ||
+      newAddress.deliveryType !== oldAddress.deliveryType
+    ) {
+      await getOrderInfo();
+    }
+  });
+
+onMounted(async () => {
+  if (!id || !count) return router.go(-1)
+	await tradeConfig()
+})
+
+</script>

+ 2 - 8
src/views/recruit/personal/PersonalCenter/jobFeedback/components/interview/item.vue

@@ -39,7 +39,7 @@
               <v-img width="30" height="30" :src="val.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'"></v-img>
             </div>
             <div class="ellipsis" style="max-width: 400px;">
-              <span class="mx-2 enterprise-name" @click="handleToEnterprise(val)">{{ formatName(val.enterprise.anotherName || val.enterprise.name) }}</span>
+              <span class="mx-2 enterprise-name" @click="jumpToEnterpriseDetail(val.enterprise.id, true)">{{ formatName(val.enterprise.anotherName || val.enterprise.name) }}</span>
             [
               <span>{{ val.enterprise.industryName }}</span>
               <span>&nbsp;·&nbsp;{{ val.enterprise.scaleName }}</span>
@@ -61,6 +61,7 @@ import Confirm from '@/plugins/confirm'
 import { getUserAvatar } from '@/utils/avatar'
 import { useRouter } from 'vue-router'
 import { formatName } from '@/utils/getText'
+import { jumpToEnterpriseDetail } from '@/utils/position'
 
 const { t } = useI18n()
 const emits = defineEmits(['refresh'])
@@ -77,13 +78,6 @@ const props = defineProps({
 
 const router = useRouter()
 
-// 企业详情
-const handleToEnterprise = (item) => {
-  const id = item.enterprise.id
-  if (!id) return
-  router.push(`/recruit/personal/company/details/${id}?key=briefIntroduction`)
-}
-
 // 职位详情
 const handleToPositionDetails = (item) => {
   if (item.job.status === '1') return

+ 2 - 7
src/views/recruit/personal/PersonalCenter/jobFeedback/components/seenMe.vue

@@ -13,7 +13,7 @@
                 <p class="mt-2">{{ item?.post?.nameCn }}</p>
               </div>
             </div>
-            <div class="company" @click="handleEnterprise(item)">
+            <div class="company" @click="jumpToEnterpriseDetail(item.enterprise.id, false)">
               <div class="float-left">
                 <v-img :src="item?.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'" :alt="item.enterprise.anotherName" :width="40" style="height: 40px;border-radius: 4px;"/>
               </div>
@@ -59,6 +59,7 @@ import { getUserAvatar } from '@/utils/avatar'
 import { useRouter } from 'vue-router'
 import { useUserStore } from '@/store/user'
 import { formatName } from '@/utils/getText'
+import { jumpToEnterpriseDetail } from '@/utils/position'
 
 const router = useRouter()
 const total = ref(0)
@@ -90,12 +91,6 @@ const handleChangePage = (e) => {
   getData()
 }
 
-const handleEnterprise = (item) => {
-  const id = item.enterprise.id
-  if (!id) return
-  router.push(`/recruit/personal/company/details/${id}?key=briefIntroduction`)
-}
-
 const goBuy = () => {
   router.push('/recruit/personal/personalCenter/memberBenefits/membershipPackage')
 }

+ 2 - 5
src/views/recruit/personal/company/components/companyItem.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="company-box">
     <div class="sub-li" v-for="item in list" :key="item.enterprise.id">
-      <div class="company-info-top" @click="handleClickEnterprise(item)" @mouseenter="item.active = true" @mouseleave="item.active = false">
+      <div class="company-info-top" @click="jumpToEnterpriseDetail(item.enterprise.id, true)" @mouseenter="item.active = true" @mouseleave="item.active = false">
         <div class="float-left">
           <v-img :src="item.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'" :alt="item.enterprise.anotherName" :width="40" style="height: 40px;border-radius: 4px;"/>
         </div>
@@ -32,6 +32,7 @@
 
 <script setup>
 import { formatName } from '@/utils/getText'
+import { jumpToEnterpriseDetail } from '@/utils/position'
 
 defineOptions({ name: 'company-item'})
 defineProps({
@@ -39,10 +40,6 @@ defineProps({
 })
 
 const desc = ['areaName', 'eduName', 'expName']
-
-const handleClickEnterprise = (item) => {
-  window.open(`/recruit/personal/company/details/${item.enterprise.id}?key=briefIntroduction`)
-}
 // 职位详情
 const handleClickPosition = (job) => {
   window.open(`/recruit/personal/position/details/${job.id}`)

+ 10 - 9
src/views/recruit/personal/home/components/advertisement/index.vue

@@ -9,7 +9,7 @@
     </div>
 
     <div no-gutters class="mt-5 d-flex flex-wrap" style="width: 100%;">
-      <v-card v-for="(k, i) in list" :key="i" class="col-item" @click="handleOpen(k)">
+      <v-card v-for="(k, i) in list" :key="i" class="col-item" @click="jumpToEnterpriseDetail(k.link, true)">
         <v-img :src="k.img"/>
       </v-card>
     </div>
@@ -18,16 +18,17 @@
 
 <script setup>
 defineOptions({ name: 'advertisementPage'})
+import { jumpToEnterpriseDetail } from '@/utils/position'
 
-const props = defineProps({ list: Array, content: Object })
+defineProps({ list: Array, content: Object })
 
-const handleOpen = (k) => {
-  if (!k.link) return
-  if (props.content && Object.keys(props.content).length > 0 && props.content[k.link]) {
-    // 集团页面
-    window.open(`/recruit/personal/advertisement/${k.link}`)
-  } else window.open(`/recruit/personal/company/details/${k.link}?key=briefIntroduction`)
-}
+// const handleOpen = (k) => {
+//   if (!k.link) return
+//   if (props.content && Object.keys(props.content).length > 0 && props.content[k.link]) {
+//     // 集团页面
+//     window.open(`/recruit/personal/advertisement/${k.link}`)
+//   } else window.open(`/recruit/personal/company/details/${k.link}?key=briefIntroduction`)
+// }
 </script>
 
 <style scoped lang="scss">