Ver código fonte

冲突合并

Xiao_123 9 meses atrás
pai
commit
8b12feb4cb

+ 25 - 0
api/common.js

@@ -41,6 +41,19 @@ export const smsLogin = (data) => {
   })
 }
 
+// 短信登录
+export const userRegister = (data) => {
+  return request({
+    url: '/app-api/menduner/system/auth/register',
+    method: 'POST',
+    data,
+    custom: {
+      showLoading: false
+    }
+  })
+}
+
+
 // 密码登录
 export const passwordLogin = (data) => {
   return request({
@@ -246,6 +259,18 @@ export const deleteConversation = async (data) => {
     }
   })
 }
+// 获取type类型聊天记录
+export const getMessageType = async (data) => {
+  return request({
+    url: '/app-api/im/im/history/messages',
+    method: 'POST',
+    data,
+    custom: {
+      showLoading: false,
+      auth: true
+    }
+  })
+}
 
 // 求职端-根据邀请人id获取面试邀约列表
 export const getInterviewInviteListByInviteUserId = async (inviteUserId) => {

+ 1 - 1
components/PositionList/index.vue

@@ -196,7 +196,7 @@ const toDetail = (isPosition, item) =>{
 	text-overflow: ellipsis;
 }
 .mList {
-  margin-top: 20rpx;
+  margin-bottom: 20rpx;
 }
 /* 列表触底暂无更多 */
 .noMore{ text-align:center; color:grey; }

+ 1 - 0
hooks/useIM.js

@@ -260,6 +260,7 @@ export function initConnect (callback = () => {}, mounted = () => {}) {
 
   // 消息发送状态监听
   function statusListen (packet) {
+    console.log('发送状态', packet)
     if (packet.reasonCode === 1) {
       // 发送成功
       console.log('发送成功')

+ 168 - 51
layout/components/authModal/login/index.vue

@@ -1,69 +1,133 @@
 <template>
   <view class="ss-p-30 head-box">
-    <view class="head-title">欢迎来到门墩儿</view>
-    <uni-segmented-control class="ss-m-t-30" :current="current" :values="items" style-type="text" active-color="#00897B" @clickItem="onClickItem" />
-    <view class="head-subtitle ss-m-t-10">未注册的手机号,验证后自动注册账号</view>
+    <template v-if="changeType === 'login'">
+      <view class="head-title">欢迎来到门墩儿</view>
+      <uni-segmented-control
+        class="ss-m-t-30"
+        :current="current"
+        :values="items"
+        style-type="text" 
+        active-color="#00897B" 
+        @clickItem="onClickItem"
+      />
+      <!-- <view class="head-subtitle ss-m-t-10">未注册的手机号,验证后自动注册账号</view> -->
+
+      <view class="ss-m-t-30">
+        <!-- 短信验证码登录 -->
+        <uni-forms
+          v-if="current === 0"
+          ref="smsLoginRef"
+          v-model="state.sms"
+          :rules="state.smsRules"
+          validateTrigger="bind"
+          labelWidth="140"
+          labelAlign="center"
+        >
+          <uni-forms-item name="phone" label="手机号">
+            <uni-easyinput placeholder="请输入手机号" v-model="state.sms.phone" :inputBorder="false" type="number">
+              
+            </uni-easyinput>
+          </uni-forms-item>
+
+          <uni-forms-item name="code" label="验证码">
+            <uni-easyinput placeholder="请输入验证码" v-model="state.sms.code" :inputBorder="false" type="number" maxlength="6">
+              <template v-slot:right>
+                <button class="login-code" :disabled="state.isMobileEnd" :class="{ 'code-btn-end': state.isMobileEnd }" @tap="handleCode">
+                  {{ getSmsTimer('smsLogin') }}
+                </button>
+              </template>
+            </uni-easyinput>
+          </uni-forms-item>
+        </uni-forms>
+
+        <!-- 账号密码登录 -->
+        <uni-forms
+          v-else
+          ref="accountLoginRef"
+          v-model="state.account"
+          :rules="state.rules"
+          validateTrigger="bind"
+          labelWidth="140"
+          labelAlign="center"
+        >
+          <uni-forms-item name="phone" label="账号">
+            <uni-easyinput placeholder="请输入账号" v-model="state.account.phone" :inputBorder="false"></uni-easyinput>
+          </uni-forms-item>
+
+          <uni-forms-item name="password" label="密码">
+            <uni-easyinput type="password" placeholder="请输入密码" v-model="state.account.password" :inputBorder="false"></uni-easyinput>
+          </uni-forms-item>
+        </uni-forms>
+        <view class="register" @tap="handleChangeRegister">还没有登录账户?去注册</view>
+        <button class="send-button" @tap="handleLogin"> 登 录  </button>
+        <view class="agreement-box ss-flex ss-row-center">
+          <uni-icons size="20" :type="protocol ? 'checkbox-filled' : 'circle'" :color="protocol ? '#00897B' : '#ccc'" @tap="protocol = !protocol"></uni-icons>
+          <view class="color-999 ss-flex ss-col-center ss-m-l-8 font-size-13">
+            我已阅读并遵守
+            <view class="color-primary" @tap.stop="handleToDetail('user')">
+              《用户协议》
+            </view>
+            <view class="agreement-text">和</view>
+            <view class="color-primary" @tap.stop="handleToDetail('privacy')">
+              《隐私协议》
+            </view>
+          </view>
+        </view>
+      </view>
+    </template>
+    <template v-if="changeType === 'register'">
+      <view class="head-title pb-20">手机号注册</view>
 
-    <view class="ss-m-t-30">
-      <!-- 短信验证码登录 -->
       <uni-forms
-        v-if="current === 0"
-        ref="smsLoginRef"
-        v-model="state.sms"
+        ref="registerForm"
+        v-model="state.register"
         :rules="state.smsRules"
         validateTrigger="bind"
         labelWidth="140"
         labelAlign="center"
       >
+
         <uni-forms-item name="phone" label="手机号">
-          <uni-easyinput placeholder="请输入手机号" v-model="state.sms.phone" :inputBorder="false" type="number">
-            <template v-slot:right>
-              <button class="login-code" :disabled="state.isMobileEnd" :class="{ 'code-btn-end': state.isMobileEnd }" @tap="handleCode">
-                {{ getSmsTimer('smsLogin') }}
-              </button>
-            </template>
+          <uni-easyinput placeholder="请输入手机号" v-model="state.register.phone" :inputBorder="false" type="number">
           </uni-easyinput>
         </uni-forms-item>
 
         <uni-forms-item name="code" label="验证码">
-          <uni-easyinput placeholder="请输入验证码" v-model="state.sms.code" :inputBorder="false" type="number" maxlength="6"></uni-easyinput>
-        </uni-forms-item>
-      </uni-forms>
-
-      <!-- 账号密码登录 -->
-      <uni-forms
-        v-else
-        ref="accountLoginRef"
-        v-model="state.account"
-        :rules="state.rules"
-        validateTrigger="bind"
-        labelWidth="140"
-        labelAlign="center"
-      >
-        <uni-forms-item name="phone" label="账号">
-          <uni-easyinput placeholder="请输入账号" v-model="state.account.phone" :inputBorder="false"></uni-easyinput>
-        </uni-forms-item>
-
-        <uni-forms-item name="password" label="密码">
-          <uni-easyinput type="password" placeholder="请输入密码" v-model="state.account.password" :inputBorder="false"></uni-easyinput>
+          <uni-easyinput
+            placeholder="请输入验证码"
+            v-model="state.register.code"
+            :inputBorder="false"
+            type="number"
+            maxlength="6"
+          >
+            <template v-slot:right>
+              <button
+                class="login-code"
+                :disabled="state.isMobileEnd"
+                :class="{ 'code-btn-end': state.isMobileEnd }"
+                @tap="handleRegisterCode"
+              >
+                {{ getSmsTimer('smsRegister') }}
+              </button>
+            </template>
+          </uni-easyinput>
         </uni-forms-item>
       </uni-forms>
-
-      <button class="send-button" @tap="handleLogin"> 登录/注册 </button>
-      <view class="agreement-box ss-flex ss-row-center">
-        <uni-icons size="20" :type="protocol ? 'checkbox-filled' : 'circle'" :color="protocol ? '#00897B' : '#ccc'" @tap="protocol = !protocol"></uni-icons>
-        <view class="color-999 ss-flex ss-col-center ss-m-l-8 font-size-13">
-          我已阅读并遵守
-          <view class="color-primary" @tap.stop="handleToDetail('user')">
-            《用户协议》
-          </view>
-          <view class="agreement-text">与</view>
-          <view class="color-primary" @tap.stop="handleToDetail('privacy')">
-            《隐私协议》
-          </view>
+      <view class="register login" @tap="handleChangeLogin">已有账户?去登陆</view>
+      <view>
+        <button class="send-button" @tap="handleRegister"> 注 册 </button>
+      </view>
+      <view class="color-999 ss-flex ss-col-center ss-row-center ss-m-l-8 font-size-13">
+        点击注册即代表您同意
+        <view class="color-primary" @tap.stop="handleToDetail('user')">
+          《用户协议》
+        </view>
+        <view class="agreement-text">和</view>
+        <view class="color-primary" @tap.stop="handleToDetail('privacy')">
+          《隐私协议》
         </view>
       </view>
-    </view>
+    </template>
   </view>
 </template>
 
@@ -78,6 +142,7 @@ const items = ['短信登录', '账号登录']
 const current = ref(0)
 const accountLoginRef = ref()
 const smsLoginRef = ref()
+const registerForm = ref()
 const protocol = ref(false)
 const state = ref({
   isMobileEnd: false, // 手机号输入完毕
@@ -86,6 +151,10 @@ const state = ref({
     phone: '',
     code: ''
   },
+  register: {
+    phone: '',
+    code: ''
+  },
   account: {
     phone: '',
     password: ''
@@ -100,6 +169,8 @@ const state = ref({
   }
 })
 
+const changeType = ref('login')
+
 // 登录成功后的返回页面
 // const backUrl = getCurrentPages().length ? getCurrentPages()[getCurrentPages().length - 2].route : ''
 
@@ -120,6 +191,18 @@ const handleCode = () => {
   getSmsCode('smsLogin', state.value.sms.phone)
 }
 
+// 获取验证码
+const handleRegisterCode = () => {
+  if (!state.value.register.phone) {
+    uni.showToast({
+      title: '请输入手机号',
+      icon: 'none',
+      duration: 2000
+    })
+    return
+  }
+  getSmsCode('smsRegister', state.value.register.phone)
+}
 // 查看协议详情
 const handleToDetail = (type) => {
   const url = type === 'user' ? '/pagesB/agreement/user' : '/pagesB/agreement/privacy'
@@ -128,6 +211,27 @@ const handleToDetail = (type) => {
   })
 }
 
+// 注册
+function handleChangeRegister () {
+  changeType.value = 'register'
+}
+
+// 登录
+function handleChangeLogin () {
+  changeType.value = 'login'
+}
+
+async function handleRegister () {
+  const validate = await unref(registerForm).validate()
+  if (!validate) return
+  try {
+    await useUserStore.handleRegister(state.value.register)
+    changeType.value = 'login'
+  } finally {
+
+  }
+}
+
 // 登录
 const handleLogin = async () => {
   if (!protocol.value) return uni.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
@@ -149,8 +253,8 @@ const handleLogin = async () => {
   text-align: center; 
   font-size: 12px; 
   cursor: pointer;
-  border: 1px dashed #00897B;
-  border-radius: 26px;
+  // border: 1px dashed #00897B;
+  // border-radius: 26px;
   padding: 0;
 }
 .head-title {
@@ -159,4 +263,17 @@ const handleLogin = async () => {
   color: #00897B;
   margin-top: 30rpx;
 }
-</style>
+.register {
+  widows: 100%;
+  font-size: .85em;
+  color: red;
+  text-align: right;
+  &.login {
+    color: #00897B;
+  }
+}
+.pb-20 {
+  padding-bottom: 40rpx;
+}
+
+</style>

+ 0 - 1
layout/index.vue

@@ -48,7 +48,6 @@ watch(() => useUserStore.accountInfo.userId, (newVal, oldVal) => {
     position: absolute;
     z-index: 1;
     width: 100%;
-    padding-bottom: 120rpx;
     min-height: 100%;
     display: flex;
     flex-direction: column;

+ 59 - 39
pages/index/communicate.vue

@@ -1,50 +1,53 @@
 <template>
   <layout-page class="ss-m-x-15">
-    <view class="box" v-for="item in items" :key="item.id" @tap="handleTo(item)">
-			<view class="box-header">
-				<template v-if="item.unread === '0'">
-					<image
-						class="enterAvatar"
-						:src="getUserAvatar(item?.userInfoVo?.userInfoResp?.avatar, item?.userInfoVo?.userInfoResp?.sex)"
-					></image>
-				</template>
-				<template v-else>
-					<uni-badge class="uni-badge-left-margin" :text="item.unread" absolute="rightTop" size="small">
-						<image
-							class="enterAvatar"
-							:src="getUserAvatar(item?.userInfoVo?.userInfoResp?.avatar, item?.userInfoVo?.userInfoResp?.sex)"
-						></image>
-					</uni-badge>
-				</template>
-				
-			</view>
-			<view class="box-content">
-				<view class="box-content-names">
-					<view class="name">
-						{{ item.thatName }}
-						<text class="nameSub">{{ item.enterpriseAnotherName }}</text>
-						<span class="line" v-if="item.postNameCn && item.enterpriseAnotherName"></span>
-						<text class="nameSub">{{ item.postNameCn }}</text>
+		<view class="height">
+			<scroll-view class="scrollBox" scroll-y="true" >
+				<view class="box" v-for="item in items" :key="item.id" @tap="handleTo(item)">
+					<view class="box-header">
+						<template v-if="item.unread === '0'">
+							<image
+								class="enterAvatar"
+								:src="getUserAvatar(item?.userInfoVo?.userInfoResp?.avatar, item?.userInfoVo?.userInfoResp?.sex)"
+							></image>
+						</template>
+						<template v-else>
+							<uni-badge class="uni-badge-left-margin" :text="item.unread" absolute="rightTop" size="small">
+								<image
+									class="enterAvatar"
+									:src="getUserAvatar(item?.userInfoVo?.userInfoResp?.avatar, item?.userInfoVo?.userInfoResp?.sex)"
+								></image>
+							</uni-badge>
+						</template>
+					</view>
+					<view class="box-content">
+						<view class="box-content-names">
+							<view class="name">
+								{{ item.thatName }}
+								<text class="nameSub">{{ item.enterpriseAnotherName }}</text>
+								<span class="line" v-if="item.postNameCn && item.enterpriseAnotherName"></span>
+								<text class="nameSub">{{ item.postNameCn }}</text>
+							</view>
+							<!-- <view class="time">{{ item.updateTime }}</view> -->
+						</view>
+						<view class="box-content-text">{{ timesTampChange(+item.timestamp.padEnd(13, '0')) }}</view>
 					</view>
-					<!-- <view class="time">{{ item.updateTime }}</view> -->
 				</view>
-				<view class="box-content-text">{{ timesTampChange(+item.timestamp.padEnd(13, '0')) }}</view>
-			</view>
+				<image
+					v-if=" items.length===0 "
+					src="https://minio.citupro.com/dev/static/nodata.png"
+					mode="widthFix"
+					style="width: 100%;">
+				</image>
+			</scroll-view>
 		</view>
-		<image
-			v-if=" items.length===0 "
-			src="https://minio.citupro.com/dev/static/nodata.png"
-			mode="widthFix"
-			style="width: 100vw;height: 100vh;">
-		</image>
   </layout-page>
 </template>
 
 <script setup>
 import { ref, watch } from 'vue'
 import layoutPage from '@/layout'
-import { getAccessToken } from '@/utils/request'
-import { showAuthModal } from '@/hooks/useModal'
+// import { getAccessToken } from '@/utils/request'
+// import { showAuthModal } from '@/hooks/useModal'
 import { getConversationSync } from '@/api/common'
 import { onShow } from '@dcloudio/uni-app'
 import { getUserAvatar } from '@/utils/avatar'
@@ -57,8 +60,19 @@ const IM = useIMStore()
 const useUserStore = userStore()
 
 const items = ref([])
-watch([() => useUserStore.refreshToken, () => IM.newMsg], () => {  
-	console.log('变了')
+watch([() => useUserStore.refreshToken, () => IM.newMsg], () => {
+	// 检测实例是否存在
+	if (!IM.uid?.value) {
+		return
+	}
+	init()
+})
+
+watch(() => IM.uid, (val) => {
+	if (!val) {
+		return
+	}
+	// 监听uid变化
 	init()
 })
 
@@ -73,7 +87,8 @@ onShow(() => {
 
 
 
-const handleTo = ({ userInfoVo, thatName, postNameCn, enterpriseAnotherName, channel_id }) => {
+const handleTo = (item) => {
+	const { userInfoVo, thatName, postNameCn, enterpriseAnotherName, channel_id } = item
 	const query = {
 		id: userInfoVo?.userInfoResp?.userId,
 		name: thatName,
@@ -178,6 +193,11 @@ async function init () {
 		}
 	}
 }
+.height {
+	height: 100vh;
+	padding-bottom: 120rpx;
+	box-sizing: border-box;
+}
 .enterAvatar{
 	width: 80rpx;
 	height: 80rpx;

+ 38 - 26
pages/index/crowdsourcing.vue

@@ -1,45 +1,48 @@
 <template>
   <layout-page>
-    <scroll-view class="scrollBox" scroll-y="true" @scrolltolower="loadingMore" style="position:relative;">
-			<view class="content defaultBgc">
-				<view class="content-top">
+		<view class="content defaultBgc">
+			<view class="content-top">
 				<view class="content-top-title">
 					<view class="content-top-title-label">
 						<text class="content-top-title-label-l">全员猎聘</text>
 						<text class="content-top-title-label-s">海量岗位 | 推荐有赏</text>
 					</view>
 				</view>
-				<view class="content-top-carousel">
-					<view class="content-top-carousel-box">
-						<SwiperAd :list="swiperAdList"></SwiperAd>
+			</view>
+			<scroll-view class="scrollBox" scroll-y="true" @scrolltolower="loadingMore" style="position:relative;">
+				<view class="content-top">
+					<view class="content-top-carousel">
+						<view class="content-top-carousel-box">
+							<SwiperAd :list="swiperAdList"></SwiperAd>
+						</view>
 					</view>
-				</view>
-				<view class="content-top-recommend">
-					<view class="content-top-recommend-box">
-						<resume-status>
-							<template #header>
-								<view class="content-top-recommend-box-title">
-									<text class="title">我的推荐</text>
-								</view>
-							</template>
-						</resume-status>
+					<view class="content-top-recommend">
+						<view class="content-top-recommend-box">
+							<resume-status>
+								<template #header>
+									<view class="content-top-recommend-box-title">
+										<text class="title">我的推荐</text>
+									</view>
+								</template>
+							</resume-status>
+						</view>
 					</view>
 				</view>
-				</view>
 				<view class="content-main">
-				<view class="content-main-list">
-					<PositionList class="pb-10" :list="items" :noMore="items.length === total"></PositionList>
-				</view>
+					<view class="content-main-list">
+						<PositionList :list="items" :noMore="false"></PositionList>
+						<uni-load-more :status="more" />
+					</view>
 				</view>
-			</view>
-		</scroll-view>
+			</scroll-view>
+		</view>
   </layout-page>
 </template>
 
 <script setup>
 import { ref, reactive } from 'vue'
 import SwiperAd from '@/components/SwiperAd'
-import { showAuthModal } from '@/hooks/useModal'
+// import { showAuthModal } from '@/hooks/useModal'
 import { swiperAdListTest } from '@/utils/testData'
 // import { userStore } from '@/store/user'
 import layoutPage from '@/layout'
@@ -62,13 +65,13 @@ const swiperAdList = ref(swiperAdListTest)
 const items = reactive([])
 const pageInfo = ref({
 	pageNo: 1,
-	pageSize: 10
+	pageSize: 20
 })
 
 const loading = ref(false)
 const total = ref(0)
 
-
+const more = ref('more')
 
 
 const loadingMore = (e) => {
@@ -78,6 +81,7 @@ const loadingMore = (e) => {
 	if (loading.value) {
 		return
 	}
+	more.value = 'loading'
 	pageInfo.value.pageNo++
 	getList()
 }
@@ -106,7 +110,9 @@ async function getList () {
 			}
 		}))
 		total.value = +data.total
+		more.value = items.length === total.value ? 'noMore' : 'more'
 	} catch (error) {
+		more.value = more
 		pageInfo.pageNo--
 	} finally {
 		loading.value = false
@@ -127,6 +133,9 @@ $defaultColor: #999;
 	overflow: hidden;
 }
 .content {
+	height: 100vh;
+	display: flex;
+	flex-direction: column;
 	&-top {		
 		&-title {
 			padding: 24rpx;
@@ -159,6 +168,7 @@ $defaultColor: #999;
 		}
 		&-recommend {
 			padding: 0 24rpx;
+			margin-bottom: 20rpx;
 			&-box {
 				@include box;
 				&-title {
@@ -256,6 +266,8 @@ $defaultColor: #999;
 	}
 }
 .scrollBox {
-	height: 100vh;
+	height: 0;
+	flex: 1;
+	padding-bottom: 120rpx;
 }
 </style>

+ 39 - 25
pages/index/my.vue

@@ -1,37 +1,38 @@
 <template>
   <layout-page>
-		<view class="ss-p-b-30">
+		<view class="pb-120">
 			<view class="text-center" @tap="handleTap">
 				<img :src="getUserAvatar(baseInfo?.avatar, baseInfo?.sex)" alt="" class="img-box">
 				<view v-if="!useUserStore.isLogin" class="font-weight-bold font-size-20">点击登录</view>
 				<view v-else class="font-weight-bold font-size-20">{{ baseInfo?.name || userInfo?.phone }}</view>
 			</view>
-			<view style="padding: 40rpx 0;">
+			<view style="padding: 40rpx 0 0 0;">
 				<resume-status></resume-status>
 			</view>
 			
 			<view class="d-flex">
 				<view v-for="(item, index) in itemList" :key="index" @tap="handleToLink(item)" class="parent">
-					<view class="d-flex justify-space-between">
-						<view>
-							<view class="colors">
-								<span>查看更多</span>
-								<uni-icons color="#c8c5c4" type="right" size="15" class="ml"/>
-							</view>
-							<view class="size-16">{{ item.title }}</view>
-						</view>
-						<view>
-							<uni-icons color="#00897B" :type="item.icon" size="45"/>
-						</view>
+					<view class="d-flex justify-space-around align-center">
+						<uni-icons color="#00897B" :type="item.icon" size="30"/>
+						<text class="itemText">{{ item.title }}</text>
 					</view>
 				</view>
 			</view>
 	
-			<view style="height: 10rpx; background-color: #f8f8fa;"></view>
+			<view style="height: 20rpx; background-color: #f8f8fa;"></view>
 	
 			<view class="card">
 				<uni-list>
-					<uni-list-item v-for="item in list" :clickable="true" :key="item.title" :title="item.title" showArrow :rightText="item.rightTex || ''" @click="handleToLink(item)"></uni-list-item>
+					<uni-list-item
+						v-for="item in list"
+						:clickable="true"
+						:key="item.title"
+						:title="item.title"
+						showArrow
+						:rightText="item.rightTex || ''"
+						@click="handleToLink(item)"
+					>
+					</uni-list-item>
 				</uni-list>
 			</view>
 	
@@ -68,15 +69,15 @@ const baseInfo = computed(() => useUserStore?.baseInfo)
 const userInfo = computed(() => useUserStore?.userInfo)
 const popup = ref()
 const itemList = [
-	{ title: "面试管理", path: "/pagesA/interview/index", icon: "list" },
-	{ title:'谁看过我', path:'/pagesA/seenMe/index', icon:'staff' }
+	{ title: "我的关注", path: "/pagesA/collect/index", icon: "list" },
+	{ title:'关注我的', path:'/pagesA/seenMe/index', icon:'staff' }
 ]
 
 const list = [
-	{	title: '附件简历',	path: '/pagesA/resume/index'	},					
-	{ title: '我的收藏', path: '/pagesA/collect/index' },
-	{ title: '前往门墩甄选商城', appId: 'wx6decdf12f9e7a061' },
-	{ title: '切换为招聘者', rightTex: '我要招人' }
+	{	title: '我的简历',	path: '/pagesA/resume/index'	},					
+	{ title: '面试管理', path: '/pagesA/interview/index' },
+	{ title: '门墩甄选', appId: 'wx6decdf12f9e7a061' },
+	{ title: '我要招聘', key: 'recruit' }
 ]
 
 // 列表跳转
@@ -88,6 +89,12 @@ const handleToLink = (item) => {
 		})
 		return
 	}
+	if (item.key === 'recruit') {
+		uni.showToast({
+			title: '请前往网页版门墩招聘',
+			icon: 'none'
+		})
+	}
 	if (!item.path) return
   if (!getAccessToken()) {
 		uni.showToast({
@@ -126,17 +133,20 @@ const handleLogoutConfirm = () => {
 </script>
 
 <style scoped lang="scss">
+.pb-120 {
+	padding-bottom: 120rpx;
+}
 .img-box {
   width: 150rpx;
   height: 150rpx;
   border: 2rpx solid #ccc;
   border-radius: 50%;
 }
-::v-deep .uni-list-item{
-	height: 140rpx !important;
-	line-height: 140rpx !important;
+:deep(.uni-list-item) {
+	height: 120rpx !important;
+	line-height: 120rpx !important;
 }
-::v-deep .uni-list-item__content-title{
+:deep(.uni-list-item__content-title) {
 	font-size: 32rpx !important;
 	font-weight: 500;
 }
@@ -149,6 +159,10 @@ const handleLogoutConfirm = () => {
 	font-size: 32rpx;
 	margin: 13rpx 0 5rpx 0;
 }
+.itemText {
+	color: #3f424f;
+	font-size: 36rpx;
+}
 .parent{
 	width: 50%;
 	border: 1px solid #f4f4f4;

+ 66 - 29
pages/index/position.vue

@@ -1,26 +1,30 @@
 <template>
+  
   <view class="box defaultBgc">
     <scroll-view class="scrollBox" scroll-y="true" @scrolltolower="loadingMore" style="position:relative;">
-      <view class="white-bgc">
-        <uni-search-bar
-          v-model="query.content"
-          radius="8"
-          placeholder="请输入关键字"
-          cancelButton="none"
-          :focus="false"
-          @confirm="onSearch($event.value)"
-          @clear="query.content = ''; onSearch()"
-        />
-      </view>
-      <view class="white-bgc px-10 mb-10">
+      <view>
+        <view class="white-bgc stick">
+          <uni-search-bar
+            v-model="query.content"
+            radius="8"
+            placeholder="请输入关键字"
+            cancelButton="none"
+            :focus="false"
+            @confirm="onSearch($event.value)"
+            @clear="query.content = ''; onSearch()"
+          />
+        </view>
         <SwiperAd :list="swiperAdList"></SwiperAd>
-        <view class="px-5">
+        <view class="white-bgc px-10 mb-10 stickFilter">
           <FilterList :list="filterList" idValue="label" @change="handleSearch"></FilterList>
         </view>
+        <PositionList :list="positionListData" :noMore="false"></PositionList>
+        <uni-load-more :status="more" />
+        
       </view>
-      <PositionList class="pb-10" :list="positionListData" :noMore="noMore"></PositionList>
     </scroll-view>
   </view>
+  
 </template>
 
 <script setup>
@@ -41,6 +45,7 @@ onShow(() => {
     currentTabBar?.setData({ selected: 0 });
 })
 
+const more = ref('more')
 const swiperAdList = ref(swiperAdListTest)
 const filterList = ref([
   { label: '城市', dictType: 'areaTreeData', key: 'areaIds', map: { text: 'name', value: 'id' } },
@@ -52,9 +57,8 @@ const filterList = ref([
 
 // 
 const positionListData = ref([])
-const noMore = ref(false)
 const query = reactive({ 
-  pageSize: 10, 
+  pageSize: 20, 
   pageNo: 1, 
   content: '',
   areaIds: [],
@@ -65,17 +69,27 @@ const query = reactive({
 })
 //
 const getData = async () => {
-  // console.log('query', query)
-  const res = await getJobAdvertisedSearch(query)
-  const list = res?.data?.list || []
-  if (list?.length) {
-    list.forEach(e => {
-      e.job = { ...e.job, ...dealDictObjData({}, e.job) }
-      e.enterprise = { ...e.enterprise, ...dealDictObjData({}, e.enterprise)}
-    })
-    positionListData.value = positionListData.value.concat(list)
+  try {
+    const res = await getJobAdvertisedSearch(query)
+    const list = res?.data?.list || []
+    positionListData.value.push(...list.map(e => {
+        if (!e) {
+          return e
+        }
+        e.job = { ...e.job, ...dealDictObjData({}, e.job) }
+        e.enterprise = { ...e.enterprise, ...dealDictObjData({}, e.enterprise)}
+        return e
+    }))
+    if (positionListData.value.length === +res.data.total) {
+      more.value = 'noMore'
+      return
+    }
+  } catch (error) {
+    query.pageNo--
+    more.value = 'more'
   }
-  if (list?.length < query.pageSize) noMore.value = true
+  
+  
 }
 getData()
 
@@ -86,12 +100,12 @@ const handleSearch = (key, value) => {
 
 const onSearch = () => {
   query.pageNo = 1
-  noMore.value = false
   positionListData.value = []
   getData()
 }
 
 const loadingMore = () => { // 加载更多
+  more.value = 'loading'
   query.pageNo++
   getData()
 }
@@ -99,8 +113,22 @@ const loadingMore = () => { // 加载更多
 </script>
 
 <style scoped lang="scss">
+.stick {
+  z-index: 1;
+  position: sticky;
+  top: 0;
+}
+.stickFilter {
+  z-index: 1;
+  position: sticky;
+  box-shadow: 0px 10rpx 12rpx 0px rgba(195, 195, 195, .25);
+  top: 112rpx;
+
+}
 .px-0 { padding-left: 0 !important; padding-right: 0 !important; }
-.pb-10 { padding-bottom: 10px; }
+.pb-10 {
+  padding-bottom: 10px;
+}
 .pb-20 { padding-bottom: 20px; }
 .px-5 { padding-left: 5px; padding-right: 5px; }
 .px-10 { padding-left: 10px; padding-right: 10px; }
@@ -110,8 +138,17 @@ const loadingMore = () => { // 加载更多
 .box {
   height: 100vh;
   overflow: hidden;
+  padding-bottom: 120rpx;
+  // box-sizing: border-box;
+  // padding-bottom: 160rpx;
+  box-sizing: border-box;
+  display: flex;
+  flex-direction: column;
 }
 .scrollBox{
-  height: 100%;
+  // height: 100%;
+  flex: 1;
+  height: 0 !important;
+  // padding-bottom: 160rpx;
 }
 </style>

+ 2 - 2
pages/login/index.vue

@@ -3,7 +3,7 @@
   <view class="ss-p-30 head-box">
     <view class="head-title">欢迎来到门墩儿</view>
     <uni-segmented-control class="ss-m-t-60" :current="current" :values="items" style-type="text" active-color="#00897B" @clickItem="onClickItem" />
-    <view class="head-subtitle ss-m-t-10">未注册的手机号,验证后自动注册账号</view>
+    <!-- <view class="head-subtitle ss-m-t-10">未注册的手机号,验证后自动注册账号</view> -->
 
     <view class="ss-m-t-30">
       <!-- 短信验证码登录 -->
@@ -50,7 +50,7 @@
         </uni-forms-item>
       </uni-forms>
 
-      <button class="send-button" @tap="handleLogin"> 登录/注册 </button>
+      <button class="send-button" @tap="handleLogin"> 登 录 </button>
     </view>
   </view>
 </template>

+ 68 - 17
pagesA/chart/index.vue

@@ -147,7 +147,7 @@
     <!-- </view> -->
     <view class="box-bottom">
       <view class="box-bottom-tool">
-        <uni-tag text="发送简历" type="success" @tap="handleFindResume"/>
+        <uni-tag :text="isSendResume ? '简历已投递' : '发送简历'" :disabled="isSendResume" type="success" @tap="handleFindResume"/>
       </view>
       
       <textarea
@@ -208,8 +208,13 @@ import { timesTampChange } from '@/utils/date'
 import { getUserAvatar } from '@/utils/avatar'
 import { preview } from '@/utils/preview'
 import { getPersonResumeCv, saveResume } from '@/api/user'
-import { getInterviewInviteListByInviteUserId } from '@/api/common'
+import { getInterviewInviteListByInviteUserId, getMessageType } from '@/api/common'
 import { userInterviewInviteReject, userInterviewInviteConsent } from '@/api/personalCenter'
+import {
+  jobCvRelSend,
+  jobCvRelCheckSend,
+  jobCvRelHireSend
+} from '@/api/position'
 
 const useUserStore = userStore()
 const IM = useIMStore()
@@ -237,6 +242,10 @@ const chooseInvite = ref(null)
 
 const scrollInto = ref(0)
 
+const isSendResume = ref(false)
+const positionInfo = ref({})
+const isEmployment = ref('-1')
+
 const {
   conversationList,
   // updateConversation,
@@ -340,6 +349,9 @@ function handlePreview (payload) {
 }
 // 获取简历
 async function handleFindResume () {
+  if (isSendResume.value) {
+    return
+  }
   uni.showLoading({
     title: '真正查找简历'
   })
@@ -368,7 +380,7 @@ function handleClose () {
 }
 
 // 发送简历
-function handleSendResume () {
+async function handleSendResume () {
   if (!Object.keys(resumeCheck.value).length) {
     uni.showToast({ title: '请选择要投递的简历', icon: 'none' })
     return
@@ -376,16 +388,34 @@ function handleSendResume () {
   const text = {
     remark: '发送简历',
     query: {
-      src: resumeCheck.url,
-      title: resumeCheck.title,
-      id: resumeCheck.id,
+      src: resumeCheck.value.url,
+      title: resumeCheck.value.title,
+      id: resumeCheck.value.id,
     },
     type: 1
   }
   send (JSON.stringify(text), channelItem.value, 105)
-  // 提交简历
-  // {jobId, title, type, url}
-  popup.value.close()
+  // console.log(isEmployment.value, positionInfo.value)
+  try {
+    if (isEmployment.value !== '-1') {
+      await jobCvRelHireSend({
+        jobId: positionInfo.value.id,
+        url: resumeCheck.value.url,
+        recommendUserId: isEmployment.value
+      })
+    } else {
+      await jobCvRelSend({
+        jobId: positionInfo.value.id,
+        title: resumeCheck.value.title,
+        url: resumeCheck.value.url,
+        type: positionInfo.value.hire ? 1 : 0
+      })
+    }
+    isSendResume.value = true
+    popup.value.close()
+  } catch (error) {
+
+  }
 }
 
 // 拒绝邀请
@@ -471,13 +501,32 @@ function handleUploadResume () {
   })
 }
 
-// 根据id检测是否有发过简历
-async function checkResume (jobId) {
+// 获取职位信息
+async function getMessageTypeSync () {
   try {
-    const { data } = await getJobFavoriteCheck({ jobId })
-    console.log(data)
+    const { data } = await getMessageType({
+      fromUid: IM.uid,
+      channelId: channelItem.value.channelID,
+      type: 102,
+      page: {
+        current: 1,
+        size: 1,
+        orders: [
+          { column: 'message_seq', asc: false }
+        ]
+      }
+    })
+    if (!data.records || !data.records.length) { 
+      return
+    }
+    const _item = data.records.pop()
+    const _itemJSON = JSON.parse(_item.payload)
+    const _content = JSON.parse(_itemJSON.content)
+    positionInfo.value = _content.positionInfo
+    const { data: check } = await jobCvRelCheckSend({ jobId: _content.positionInfo.id })
+    isSendResume.value = check
   } catch (error) {
-    
+    console.log(345, error)
   }
 }
 
@@ -486,9 +535,11 @@ onLoad(async (options) => {
     r[k] = decodeURIComponent(options[k])
     return r
   }, {})
-  // console.log(info.value)
-  // await checkResume(info.value.enterpriseId)
-  await init(options.id, options.enterpriseId)
+  isEmployment.value = info.value.isEmployment
+  await init(info.value.id, info.value.enterpriseId)
+  // 获取最新的职位信息
+  await getMessageTypeSync(info.value.id)
+
   await getStatusList()
   getInterviewInviteList()
   // 清除未读消息

+ 2 - 1
pagesA/interview/index.vue

@@ -61,7 +61,8 @@ const getList = async () => {
     })
     items.value = items.value.concat(list)
   }
-  more.value = list?.length < queryParams.value.pageSize ? 'noMore' : 'more'
+  // more.value = list?.length < queryParams.value.pageSize ? 'noMore' : 'more'
+  more.value = list?.length === +data.total ? 'noMore' : 'more'
 }
 getList()
 

+ 42 - 30
pagesB/positionDetail/index.vue

@@ -212,7 +212,7 @@ import {
 import { getPersonResumeCv, saveResume } from '@/api/user'
 import { dealDictObjData } from '@/utils/position'
 import { getAccessToken } from '@/utils/request'
-import { onLoad,onShareAppMessage,onShareTimeline } from '@dcloudio/uni-app'
+import { onLoad,onShareAppMessage,onShareTimeline, onShow } from '@dcloudio/uni-app'
 import { prologue, defaultText } from '@/hooks/useIM'
 
 const sharePopup = ref()
@@ -229,24 +229,14 @@ const imgSrc = ref('')
 const appInfo = ref({})
 const poster = ref()
 
-const getPositionDetail = async () => {
-  try {
-    loading.value = true
-    const { data } = await getPositionDetails({ id: jobId })
-    info.value = data
-    positionInfo.value = { ...dealDictObjData({}, info.value), ...info.value }
-    loading.value = false
-  } finally {
-  }
-}
-
 let jobId = ''
-onLoad((options) => {  
+onLoad((options) => {
+  console.log(options)  
   // 是否是众聘
-  if (options.userId) {
-    isEmployment.value = options.userId
+  if (options.sharedById) {
+    isEmployment.value = options.sharedById
   }
-  jobId = options?.id || ''
+  jobId = options?.id || options?.jobId || ''
   if (jobId) {
     loading.value = true
     loadingText.value = '加载中 . . . '
@@ -258,9 +248,40 @@ onLoad((options) => {
   }
 })
 
+onShow(() => {
+  if (!jobId) {
+    return
+  }
+  deliveryCheck()
+})
+
+
+//在点击open-type="share"按钮后会触发以下函数,可以在函数中写需要的逻辑,当然函数的返回值必须是一个对象,用于设置分享卡片的展示形式
+//发送给微信好友  
+onShareAppMessage((res) => {
+  let path = `/pagesB/positionDetail/index?jobId=${info.value.id}`
+  if (info.value.hire) {
+    path += `&sharedById=${info.value.userId}`
+  }
+  return {
+    title: '我发现了一个好职位,快来看看吧', //分享的名称
+    path
+  }
+})
+
+async function getPositionDetail () {
+  try {
+    loading.value = true
+    const { data } = await getPositionDetails({ id: jobId })
+    info.value = data
+    positionInfo.value = { ...dealDictObjData({}, info.value), ...info.value }
+    loading.value = false
+  } finally {
+  }
+}
 // 效验是否有投递过简历
 const delivery = ref(false) // 是否已投递简历
-const deliveryCheck = async () => {
+async function deliveryCheck () {
   try {
     if (!getAccessToken()) return delivery.value = false
     const { data } = await jobCvRelCheckSend({ jobId })
@@ -337,13 +358,16 @@ async function handleSend () {
   const enterpriseId = info.value.contact.enterpriseId
   const textObj = {
     text: defaultText,
-    positionInfo: positionInfo.value
+    positionInfo: positionInfo.value,
+    
   }
+  // console.log('textObj', textObj)
   const channel = await prologue({userId, enterpriseId, text: JSON.stringify(textObj)})
   console.log('channel', channel)
   // 跳转
   const query = {
 		id: userId,
+    isEmployment: isEmployment.value ? isEmployment.value : '-1',
 		name: info.value?.contact?.name,
 		postName: info.value?.contact?.postNameCn,
 		enterpriseName: info.value?.enterprise?.anotherName,
@@ -418,18 +442,6 @@ const handleUpload = () => {
 const handleClickShare = () => {
   sharePopup.value.open()
 }
-//在点击open-type="share"按钮后会触发以下函数,可以在函数中写需要的逻辑,当然函数的返回值必须是一个对象,用于设置分享卡片的展示形式
-//发送给微信好友  
-onShareAppMessage((res) => {
-  let path = `/pagesB/positionDetail/index?id=${info.value.id}`
-  if (info.value.hire) {
-    path += `&userId=${info.value.userId}`
-  }
-  return {
-    title: '我发现了一个好职位,快来看看吧', //分享的名称
-    path
-  }
-})
 // 获取设备信息
 function getSystemInfo(){
   return new Promise((resolve, reject) =>{

+ 1 - 0
store/modal.js

@@ -6,6 +6,7 @@ export const modalStore = defineStore({
     auth: '', // 授权弹框 login|resetPassword|changeMobile|changePassword|changeUsername
     lastTimer: {
       // 短信验证码计时器,为了防止刷新请求做了持久化
+      smsRegister: 0,
       smsLogin: 0,
       changeMobile: 0,
       resetPassword: 0,

+ 14 - 1
store/user.js

@@ -1,7 +1,7 @@
 import { defineStore } from 'pinia';
 import { clone, cloneDeep } from 'lodash-es';
 import { getBaseInfo, getUserInfo } from '@/api/user';
-import { smsLogin, passwordLogin, logout } from '@/api/common'
+import { smsLogin, passwordLogin, logout, userRegister } from '@/api/common'
 import { closeAuthModal } from '@/hooks/useModal'
 
 // 默认用户信息
@@ -71,6 +71,19 @@ export const userStore = defineStore({
       //   url: '/pages/index/position'
       // })
     },
+
+    async handleRegister (query) {
+      const { data, code } = await userRegister(query)
+      if (code === 0) {
+        uni.showToast({
+          title: '注册成功'
+        })
+      }
+      this.accountInfo = data
+      this.getInfo()
+      this.getUserInfo()
+      closeAuthModal()
+    },
     // 获取人才信息
     async getInfo() {
       const { code, data } = await getBaseInfo({ userId: this.accountInfo.userId });

+ 2 - 0
utils/code.js

@@ -45,6 +45,8 @@ export const getSmsCode = (event, mobile) => {
       break;
     case 'smsLogin':
       scene = 30; // 对接门墩短信登录
+    case 'smsRegister':
+      scene = 30; // 对接门墩短信登录
       break;
   }
   sendSmsCode({ phone: mobile, scene }).then((res) => {