Browse Source

feat: 添加数据有效性检查及认证状态显示

fix(contract): 修复合同签署按钮颜色问题
refactor(config): 将环境配置改为开发环境
feat(workItem): 添加职位不存在时的友好提示
feat(userItem): 添加用户数据不存在时的友好提示
feat(center): 添加个人和企业认证状态及到期提醒
feat(AddressPicker): 添加自定义插槽支持全部地区选择
fix(configPopup): 修复配置查询参数传递问题
feat(store): 添加查看次数检查功能
master
前端-胡立永 1 month ago
parent
commit
7cbdb8cce3
11 changed files with 345 additions and 33 deletions
  1. +23
    -1
      components/AddressPicker.vue
  2. +1
    -1
      components/config/configPopup.vue
  3. +1
    -2
      components/list/userList/index.vue
  4. +65
    -7
      components/list/userList/userItem.vue
  5. +80
    -2
      components/list/workList/workItem.vue
  6. +52
    -5
      components/screen/screenWork.vue
  7. +90
    -9
      pages/index/center.vue
  8. +5
    -1
      pages_order/contract/contract.vue
  9. +4
    -4
      pages_order/contract/electronicSignature.vue
  10. +4
    -1
      pages_order/mine/GainPoints.vue
  11. +20
    -0
      store/store.js

+ 23
- 1
components/AddressPicker.vue View File

@ -9,10 +9,15 @@
</view> </view>
</view> </view>
<view class="content"> <view class="content">
<!-- 左侧一级地址列表 --> <!-- 左侧一级地址列表 -->
<view class="left-panel"> <view class="left-panel">
<scroll-view scroll-y class="scroll-view"> <scroll-view scroll-y class="scroll-view">
<!-- 插槽自定义内容 -->
<slot name="custom-options"></slot>
<view <view
class="address-item" class="address-item"
:class="{ active: selectedProvince && selectedProvince.id === item.id }" :class="{ active: selectedProvince && selectedProvince.id === item.id }"
@ -448,6 +453,23 @@
} }
} }
.left-panel {
.select-all-item {
display: flex;
align-items: center;
color: #3796F8;
background: rgba(#3796F8, 0.1);
font-weight: bold;
padding: 30rpx 20rpx;
font-size: 28rpx;
border-bottom: 1px solid #f0f0f0;
uv-icon {
margin-right: 10rpx;
}
}
}
.confirm-btn { .confirm-btn {
position: sticky; position: sticky;
bottom: 0; bottom: 0;
@ -467,4 +489,4 @@
} }
} }
} }
</style>
</style>

+ 1
- 1
components/config/configPopup.vue View File

@ -23,7 +23,7 @@
// //
open(key){ open(key){
this.$api('queryConfig', { this.$api('queryConfig', {
paramCode : 'config_vip_service',
paramCode : key,
}) })
.then(res => { .then(res => {
// this.content = this.configList[key] // this.content = this.configList[key]


+ 1
- 2
components/list/userList/index.vue View File

@ -5,8 +5,7 @@
@scrolltolower="loadMoreData"> @scrolltolower="loadMoreData">
<view class="bossList"> <view class="bossList">
<view <view
@click="$utils.navigateTo('/pages_order/work/userDetail?id=' +
(keyName ? item[keyName] : item).id)"
@click="$store.commit('checkViewCount', (keyName ? item[keyName] : item).id)"
:key="index" :key="index"
v-for="(item, index) in list"> v-for="(item, index) in list">
<userItem :item="keyName && item[keyName] ? item[keyName] : item" <userItem :item="keyName && item[keyName] ? item[keyName] : item"


+ 65
- 7
components/list/userList/userItem.vue View File

@ -1,19 +1,31 @@
<template> <template>
<view class="boss-item"
<!-- 数据不存在时的友好提示 -->
<view v-if="!item || !item.id" class="boss-item deleted-item">
<view class="deleted-content">
<view class="deleted-icon"></view>
<view class="deleted-text">
<view class="deleted-title">数据已被删除</view>
<view class="deleted-desc">该用户信息可能已被删除或不存在</view>
</view>
</view>
</view>
<!-- 正常数据显示 -->
<view v-else class="boss-item"
@click="$emit('click')"> @click="$emit('click')">
<view class="head"> <view class="head">
<view class="headImage"> <view class="headImage">
<image :src="item.hanHaiMember.headImage" mode=""></image>
<image :src="item.hanHaiMember && item.hanHaiMember.headImage" mode=""></image>
</view> </view>
<view class="info"> <view class="info">
<view class="name"> <view class="name">
<!-- 李老板 --> <!-- 李老板 -->
{{ item.employAuthenticationPerson.name }}
<view>
{{ item.employAuthenticationPerson && item.employAuthenticationPerson.name }}
<view v-if="item.typeId_dictText">
<!-- 装配电工 --> <!-- 装配电工 -->
{{ item.typeId_dictText }} {{ item.typeId_dictText }}
</view> </view>
<view>
<view v-if="item.natureId_dictText">
<!-- 装配电工 --> <!-- 装配电工 -->
{{ item.natureId_dictText }} {{ item.natureId_dictText }}
</view> </view>
@ -79,14 +91,27 @@
}, },
computed : { computed : {
headImage(){ headImage(){
return this.image || this.item.headImage || '/static/image/center/headImage.png'
return this.image || (this.item && this.item.headImage) || '/static/image/center/headImage.png'
}, },
phone(){ phone(){
return this.item.hanHaiMember && this.item.hanHaiMember.phone
return this.item && this.item.hanHaiMember && this.item.hanHaiMember.phone
}, },
//
isDataValid(){
return this.item && this.item.id
}
}, },
methods: { methods: {
callPhone(){ callPhone(){
//
if (!this.isDataValid || !this.phone) {
uni.showToast({
title: '联系方式不可用',
icon: 'none'
});
return;
}
uni.makePhoneCall({ uni.makePhoneCall({
phoneNumber: this.phone, phoneNumber: this.phone,
success() { success() {
@ -105,6 +130,39 @@
.boss-item{ .boss-item{
background-color: #fff; background-color: #fff;
border-radius: 20rpx; border-radius: 20rpx;
&.deleted-item {
background-color: #f5f5f5;
border: 2rpx dashed #ccc;
padding: 40rpx 20rpx;
.deleted-content {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
text-align: center;
.deleted-icon {
font-size: 60rpx;
margin-bottom: 20rpx;
}
.deleted-text {
.deleted-title {
font-size: 32rpx;
color: #666;
font-weight: bold;
margin-bottom: 10rpx;
}
.deleted-desc {
font-size: 24rpx;
color: #999;
}
}
}
}
.head { .head {
display: flex; display: flex;
align-items: center; align-items: center;


+ 80
- 2
components/list/workList/workItem.vue View File

@ -1,5 +1,17 @@
<template> <template>
<view class="work-item"
<!-- 数据不存在时的友好提示 -->
<view v-if="!item || !item.id" class="work-item deleted-item">
<view class="deleted-content">
<view class="deleted-icon"></view>
<view class="deleted-text">
<view class="deleted-title">职位已被删除</view>
<view class="deleted-desc">该职位信息可能已被删除或不存在</view>
</view>
</view>
</view>
<!-- 正常数据显示 -->
<view v-else class="work-item"
:class="{ 'expired': isExpired }" :class="{ 'expired': isExpired }"
@click="handledClick"> @click="handledClick">
<view class="top"> <view class="top">
@ -64,6 +76,8 @@
}, },
computed : { computed : {
lableText(){ lableText(){
if (!this.item) return []
let arr = let arr =
this.item.tab ? this.item.tab ?
this.item.tab.split('、') this.item.tab.split('、')
@ -80,12 +94,16 @@
}, },
// //
isExpired(){ isExpired(){
if(!this.item.deadline) return false
if(!this.item || !this.item.deadline) return false
const now = this.$dayjs() const now = this.$dayjs()
const deadline = this.$dayjs(this.item.deadline) const deadline = this.$dayjs(this.item.deadline)
return now.isAfter(deadline) return now.isAfter(deadline)
},
//
isDataValid(){
return this.item && this.item.id
} }
}, },
data() { data() {
@ -95,6 +113,15 @@
}, },
methods: { methods: {
callPhone(){ callPhone(){
//
if (!this.isDataValid) {
uni.showToast({
title: '职位信息不可用',
icon: 'none'
});
return;
}
// //
if(this.isExpired) { if(this.isExpired) {
uni.showToast({ uni.showToast({
@ -104,6 +131,15 @@
return return
} }
//
if (!this.item.phone) {
uni.showToast({
title: '联系方式不可用',
icon: 'none'
});
return;
}
uni.makePhoneCall({ uni.makePhoneCall({
phoneNumber: this.item.phone, phoneNumber: this.item.phone,
success() { success() {
@ -115,6 +151,15 @@
}) })
}, },
handledClick(){ handledClick(){
//
if (!this.isDataValid) {
uni.showToast({
title: '职位信息不可用',
icon: 'none'
});
return;
}
// //
if(this.isExpired) { if(this.isExpired) {
uni.showToast({ uni.showToast({
@ -137,6 +182,39 @@
border-radius: 20rpx; border-radius: 20rpx;
position: relative; position: relative;
&.deleted-item {
background-color: #f5f5f5;
border: 2rpx dashed #ccc;
padding: 40rpx 20rpx;
.deleted-content {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
text-align: center;
.deleted-icon {
font-size: 60rpx;
margin-bottom: 20rpx;
}
.deleted-text {
.deleted-title {
font-size: 32rpx;
color: #666;
font-weight: bold;
margin-bottom: 10rpx;
}
.deleted-desc {
font-size: 24rpx;
color: #999;
}
}
}
}
// //
&.expired { &.expired {
opacity: 0.6; opacity: 0.6;


+ 52
- 5
components/screen/screenWork.vue View File

@ -81,7 +81,14 @@
</uv-popup> </uv-popup>
<!-- 地址选择组件 --> <!-- 地址选择组件 -->
<AddressPicker ref="addressPicker" @confirm="onAddressConfirm" />
<AddressPicker ref="addressPicker" showSelectWholeCity @confirm="onAddressConfirm">
<template #custom-options>
<view class="address-item select-all-item" @click="selectAllAreas">
<uv-icon name="checkmark-circle" size="30rpx" color="#3796F8"></uv-icon>
选择全部地区
</view>
</template>
</AddressPicker>
</view> </view>
</template> </template>
@ -333,7 +340,7 @@
this.result.push({ this.result.push({
name: n.type, name: n.type,
label: this.popupSelectedAddress, label: this.popupSelectedAddress,
value: this.popupSelectedAddress
value: this.popupSelectedAddress == '全部地区' ? 'all' : this.popupSelectedAddress
}) })
} else { } else {
// 使tag // 使tag
@ -347,13 +354,14 @@
}) })
this.result = this.result.filter(item => this.defaultValue.indexOf(item.value) == -1); this.result = this.result.filter(item => this.defaultValue.indexOf(item.value) == -1);
this.$emit('clickItem', this.result) this.$emit('clickItem', this.result)
this.$refs.popup.close() this.$refs.popup.close()
}, },
// //
openAddressPickerInPopup() { openAddressPickerInPopup() {
this.activeName = 'areaId'
this.$refs.addressPicker.open() this.$refs.addressPicker.open()
}, },
@ -377,12 +385,49 @@
// - // -
uni.$emit(`${this.sign}_CLOSEPOPUP`) uni.$emit(`${this.sign}_CLOSEPOPUP`)
}, },
//
selectAllAreas() {
//
this.popupSelectedAddress = '全部地区'
// areaId
this.areaId.label = '全部地区'
this.areaId.value = 'all'
// clickItemresult
this.clickItem({
label: '全部地区',
value: 'all',
})
//
this.$refs.addressPicker.close()
//
uni.$emit(`${this.sign}_CLOSEPOPUP`)
},
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.page{ .page{
//
::v-deep .select-all-item {
display: flex;
align-items: center;
color: #3796F8;
background: rgba(#3796F8, 0.1);
font-weight: bold;
padding: 30rpx 20rpx;
font-size: 28rpx;
border-bottom: 1px solid #f0f0f0;
uv-icon {
margin-right: 10rpx;
}
}
.popup{ .popup{
width: 80vw; width: 80vw;
padding: 40rpx; padding: 40rpx;
@ -429,8 +474,10 @@
margin-left: 10rpx; margin-left: 10rpx;
} }
} }
}
}
}
}
.btn { .btn {
display: flex; display: flex;
justify-content: center; justify-content: center;


+ 90
- 9
pages/index/center.vue View File

@ -31,6 +31,16 @@
<view class="name" <view class="name"
@click="$utils.navigateTo('/pages_order/mine/updateUser?back=true')"> @click="$utils.navigateTo('/pages_order/mine/updateUser?back=true')">
{{username}} {{username}}
<!-- 个人实名认证图标 -->
<image v-if="UserExtensionInfo.personAuthenticationStatus == '1'"
:src="configList.config_person_icon"
class="auth-icon"
mode="aspectFit"></image>
<!-- 企业认证图标 -->
<image v-if="UserExtensionInfo.companyAuthenticationStatus == '1'"
:src="configList.config_person_icon"
class="auth-icon"
mode="aspectFit"></image>
<view> <view>
<uv-icon name="edit-pen" size="40rpx" color="#fff"></uv-icon> <uv-icon name="edit-pen" size="40rpx" color="#fff"></uv-icon>
修改资料 修改资料
@ -42,6 +52,25 @@
<view> <view>
{{ UserExtensionInfo.vipType || '' }} {{ UserExtensionInfo.vipType || '' }}
</view> </view>
<!-- 个人实名认证到期提醒 -->
<view v-if="personAuthDaysLeft" :class="personAuthDaysLeft === 'expired' ? 'auth-expired' : 'auth-warning'">
<template v-if="personAuthDaysLeft === 'expired'">
个人实名认证已过期
</template>
<template v-else>
个人实名认证还有{{personAuthDaysLeft}}天到期
</template>
</view>
<!-- 企业认证到期提醒 -->
<view v-if="companyAuthDaysLeft" :class="companyAuthDaysLeft === 'expired' ? 'auth-expired' : 'auth-warning'">
<template v-if="companyAuthDaysLeft === 'expired'">
企业认证已过期
</template>
<template v-else>
企业认证还有{{companyAuthDaysLeft}}天到期
</template>
</view>
</view> </view>
</template> </template>
@ -279,13 +308,13 @@
<script> <script>
import tabber from '@/components/base/tabbar.vue' import tabber from '@/components/base/tabbar.vue'
import { mapState } from 'vuex'
export default {
components: {
tabber,
},
computed: {
...mapState(['userInfo', 'role','banner', 'UserExtensionInfo']),
import { mapState } from 'vuex'
export default {
components: {
tabber,
},
computed: {
...mapState(['userInfo', 'role','banner', 'UserExtensionInfo']),
// //
isLoggedIn(){ isLoggedIn(){
return this.userInfo && this.userInfo.id return this.userInfo && this.userInfo.id
@ -300,8 +329,32 @@
return this.userInfo.phone || '未绑定手机' return this.userInfo.phone || '未绑定手机'
}, },
bannerList(){ bannerList(){
return this.banner.filter(n => n.type == 1)
},
return this.banner.filter(n => n.type == 1)
},
//
personAuthDaysLeft(){
if(!this.UserExtensionInfo.personAuthenticationValidTime) return null
const validTime = new Date(this.UserExtensionInfo.personAuthenticationValidTime)
const now = new Date()
const diffTime = validTime.getTime() - now.getTime()
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
//
if(diffDays <= 0) return 'expired'
// 7
return diffDays <= 7 ? diffDays : null
},
//
companyAuthDaysLeft(){
if(!this.UserExtensionInfo.companyAuthenticationValidTime) return null
const validTime = new Date(this.UserExtensionInfo.companyAuthenticationValidTime)
const now = new Date()
const diffTime = validTime.getTime() - now.getTime()
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
//
if(diffDays <= 0) return 'expired'
// 7
return diffDays <= 7 ? diffDays : null
},
}, },
data() { data() {
return { return {
@ -371,7 +424,15 @@
.name { .name {
font-size: 32rpx; font-size: 32rpx;
display: flex; display: flex;
align-items: center;
padding-bottom: 10rpx; padding-bottom: 10rpx;
.auth-icon {
width: 40rpx;
height: 40rpx;
margin-left: 10rpx;
}
view{ view{
display: flex; display: flex;
font-size: 20rpx; font-size: 20rpx;
@ -384,6 +445,26 @@
font-size: 26rpx; font-size: 26rpx;
color: #fff; color: #fff;
} }
.auth-warning {
font-size: 24rpx;
color: #FFD700;
background: rgba(255, 215, 0, 0.2);
padding: 8rpx 16rpx;
border-radius: 8rpx;
margin-top: 8rpx;
border: 1rpx solid rgba(255, 215, 0, 0.5);
}
.auth-expired {
font-size: 24rpx;
color: #FF4444;
background: rgba(255, 68, 68, 0.2);
padding: 8rpx 16rpx;
border-radius: 8rpx;
margin-top: 8rpx;
border: 1rpx solid rgba(255, 68, 68, 0.5);
}
} }
.loginBtn { .loginBtn {


+ 5
- 1
pages_order/contract/contract.vue View File

@ -44,7 +44,7 @@
<view class="sign-btn" <view class="sign-btn"
v-if="(role && item.bossStatus === 0) || (!role && item.employeeStatus === 0)" v-if="(role && item.bossStatus === 0) || (!role && item.employeeStatus === 0)"
@click.stop="$utils.navigateTo('/pages_order/contract/electronicSignature?id=' + item.id)"> @click.stop="$utils.navigateTo('/pages_order/contract/electronicSignature?id=' + item.id)">
<uv-icon name="edit-pen" color="#2979ff" size="30rpx"></uv-icon>
<uv-icon name="edit-pen" color="#fff" size="30rpx"></uv-icon>
<text>签署</text> <text>签署</text>
</view> </view>
</view> </view>
@ -87,6 +87,10 @@
methods: { methods: {
clickTabs({index}) { clickTabs({index}) {
this.type = index this.type = index
if(index == 0){
delete this.queryParams.status
}
this.queryParams.status = index
this.getData() this.getData()
}, },
showPDF(item){ showPDF(item){


+ 4
- 4
pages_order/contract/electronicSignature.vue View File

@ -105,10 +105,10 @@
imageWidth : graph.w, imageWidth : graph.w,
positionX : graph.x, positionX : graph.x,
positonY : graph.y, positonY : graph.y,
// pdfPath : this.detail.contract,
// imagePath,
pdfPath : 'https://augcl.oss-cn-guangzhou.aliyuncs.com/test/mytest.pdf',
imagePath : 'https://augcl.oss-cn-guangzhou.aliyuncs.com/test/image.png',
pdfPath : this.detail.contract,
imagePath,
// pdfPath : 'https://augcl.oss-cn-guangzhou.aliyuncs.com/test/mytest.pdf',
// imagePath : 'https://augcl.oss-cn-guangzhou.aliyuncs.com/test/image.png',
pageNo : parseInt(pageNo) + 1, pageNo : parseInt(pageNo) + 1,
}) })


+ 4
- 1
pages_order/mine/GainPoints.vue View File

@ -25,7 +25,7 @@
<view>邀请工友获取积分</view> <view>邀请工友获取积分</view>
</view> </view>
<view class="txt">成功邀请一名新好友注册最高可获得 <view class="txt">成功邀请一名新好友注册最高可获得
<text style="color: red;font-size: 32rpx;">2</text>
<text style="color: red;font-size: 32rpx;">{{ configList.config_share_score }}</text>
个正式积分 个正式积分
<view style="color: red;">多邀多得可叠加</view> <view style="color: red;">多邀多得可叠加</view>
</view> </view>
@ -67,6 +67,9 @@
onLoad() { onLoad() {
this.$store.commit('getUserExtensionInfo') this.$store.commit('getUserExtensionInfo')
}, },
onShow(){
this.$store.commit('initConfig')
},
methods: { methods: {
checkin(){ checkin(){
this.$api('addScoreBySign', res => { this.$api('addScoreBySign', res => {


+ 20
- 0
store/store.js View File

@ -247,6 +247,26 @@ const store = new Vuex.Store({
setChildAddressList(state, { pid, list }){ setChildAddressList(state, { pid, list }){
state.addressTreeMap[pid] = list state.addressTreeMap[pid] = list
}, },
// 检查当前查看次数,在进入简历页面
checkViewCount(state, id){
api('getUserCenterData', res =>{
if(res.code == 200){
state.UserExtensionInfo = res.result
if (state.UserExtensionInfo.checkNum > 0) {
return uni.navigateTo({
url: '/pages_order/work/userDetail?id=' + id
})
}
uni.showToast({
title: '您的查看次数已用完,无法继续查看',
icon: 'none'
})
}
})
}
}, },
actions: { actions: {
// 获取子级地址列表 // 获取子级地址列表


Loading…
Cancel
Save