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 class="content">
<!-- 左侧一级地址列表 -->
<view class="left-panel">
<scroll-view scroll-y class="scroll-view">
<!-- 插槽自定义内容 -->
<slot name="custom-options"></slot>
<view
class="address-item"
: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 {
position: sticky;
bottom: 0;
@ -467,4 +489,4 @@
}
}
}
</style>
</style>

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

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


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

@ -5,8 +5,7 @@
@scrolltolower="loadMoreData">
<view class="bossList">
<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"
v-for="(item, index) in list">
<userItem :item="keyName && item[keyName] ? item[keyName] : item"


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

@ -1,19 +1,31 @@
<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')">
<view class="head">
<view class="headImage">
<image :src="item.hanHaiMember.headImage" mode=""></image>
<image :src="item.hanHaiMember && item.hanHaiMember.headImage" mode=""></image>
</view>
<view class="info">
<view class="name">
<!-- 李老板 -->
{{ item.employAuthenticationPerson.name }}
<view>
{{ item.employAuthenticationPerson && item.employAuthenticationPerson.name }}
<view v-if="item.typeId_dictText">
<!-- 装配电工 -->
{{ item.typeId_dictText }}
</view>
<view>
<view v-if="item.natureId_dictText">
<!-- 装配电工 -->
{{ item.natureId_dictText }}
</view>
@ -79,14 +91,27 @@
},
computed : {
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(){
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: {
callPhone(){
//
if (!this.isDataValid || !this.phone) {
uni.showToast({
title: '联系方式不可用',
icon: 'none'
});
return;
}
uni.makePhoneCall({
phoneNumber: this.phone,
success() {
@ -105,6 +130,39 @@
.boss-item{
background-color: #fff;
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 {
display: flex;
align-items: center;


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

@ -1,5 +1,17 @@
<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 }"
@click="handledClick">
<view class="top">
@ -64,6 +76,8 @@
},
computed : {
lableText(){
if (!this.item) return []
let arr =
this.item.tab ?
this.item.tab.split('、')
@ -80,12 +94,16 @@
},
//
isExpired(){
if(!this.item.deadline) return false
if(!this.item || !this.item.deadline) return false
const now = this.$dayjs()
const deadline = this.$dayjs(this.item.deadline)
return now.isAfter(deadline)
},
//
isDataValid(){
return this.item && this.item.id
}
},
data() {
@ -95,6 +113,15 @@
},
methods: {
callPhone(){
//
if (!this.isDataValid) {
uni.showToast({
title: '职位信息不可用',
icon: 'none'
});
return;
}
//
if(this.isExpired) {
uni.showToast({
@ -104,6 +131,15 @@
return
}
//
if (!this.item.phone) {
uni.showToast({
title: '联系方式不可用',
icon: 'none'
});
return;
}
uni.makePhoneCall({
phoneNumber: this.item.phone,
success() {
@ -115,6 +151,15 @@
})
},
handledClick(){
//
if (!this.isDataValid) {
uni.showToast({
title: '职位信息不可用',
icon: 'none'
});
return;
}
//
if(this.isExpired) {
uni.showToast({
@ -137,6 +182,39 @@
border-radius: 20rpx;
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 {
opacity: 0.6;


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

@ -81,7 +81,14 @@
</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>
</template>
@ -333,7 +340,7 @@
this.result.push({
name: n.type,
label: this.popupSelectedAddress,
value: this.popupSelectedAddress
value: this.popupSelectedAddress == '全部地区' ? 'all' : this.popupSelectedAddress
})
} else {
// 使tag
@ -347,13 +354,14 @@
})
this.result = this.result.filter(item => this.defaultValue.indexOf(item.value) == -1);
this.$emit('clickItem', this.result)
this.$refs.popup.close()
},
//
openAddressPickerInPopup() {
this.activeName = 'areaId'
this.$refs.addressPicker.open()
},
@ -377,12 +385,49 @@
// -
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>
<style scoped lang="scss">
.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{
width: 80vw;
padding: 40rpx;
@ -429,8 +474,10 @@
margin-left: 10rpx;
}
}
}
}
}
}
.btn {
display: flex;
justify-content: center;


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

@ -31,6 +31,16 @@
<view class="name"
@click="$utils.navigateTo('/pages_order/mine/updateUser?back=true')">
{{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>
<uv-icon name="edit-pen" size="40rpx" color="#fff"></uv-icon>
修改资料
@ -42,6 +52,25 @@
<view>
{{ UserExtensionInfo.vipType || '' }}
</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>
</template>
@ -279,13 +308,13 @@
<script>
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(){
return this.userInfo && this.userInfo.id
@ -300,8 +329,32 @@
return this.userInfo.phone || '未绑定手机'
},
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() {
return {
@ -371,7 +424,15 @@
.name {
font-size: 32rpx;
display: flex;
align-items: center;
padding-bottom: 10rpx;
.auth-icon {
width: 40rpx;
height: 40rpx;
margin-left: 10rpx;
}
view{
display: flex;
font-size: 20rpx;
@ -384,6 +445,26 @@
font-size: 26rpx;
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 {


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

@ -44,7 +44,7 @@
<view class="sign-btn"
v-if="(role && item.bossStatus === 0) || (!role && item.employeeStatus === 0)"
@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>
</view>
</view>
@ -87,6 +87,10 @@
methods: {
clickTabs({index}) {
this.type = index
if(index == 0){
delete this.queryParams.status
}
this.queryParams.status = index
this.getData()
},
showPDF(item){


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

@ -105,10 +105,10 @@
imageWidth : graph.w,
positionX : graph.x,
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,
})


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

@ -25,7 +25,7 @@
<view>邀请工友获取积分</view>
</view>
<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>
@ -67,6 +67,9 @@
onLoad() {
this.$store.commit('getUserExtensionInfo')
},
onShow(){
this.$store.commit('initConfig')
},
methods: {
checkin(){
this.$api('addScoreBySign', res => {


+ 20
- 0
store/store.js View File

@ -247,6 +247,26 @@ const store = new Vuex.Store({
setChildAddressList(state, { 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: {
// 获取子级地址列表


Loading…
Cancel
Save