首页卡片开发

This commit is contained in:
冯辉
2025-10-24 16:54:52 +08:00
parent 92ee5c5311
commit 2d6370b796
22 changed files with 896 additions and 205 deletions

View File

@@ -85,17 +85,22 @@
</view>
<!-- 自定义tabbar -->
<CustomTabBar :currentPage="1" />
<!-- 微信授权登录弹窗 -->
<WxAuthLogin ref="wxAuthLoginRef" @success="handleLoginSuccess"></WxAuthLogin>
</view>
</view>
</template>
<script setup>
import { reactive, inject, watch, ref, onMounted } from 'vue';
import { reactive, inject, watch, ref, onMounted, onUnmounted } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import useLocationStore from '@/stores/useLocationStore';
import { storeToRefs } from 'pinia';
import { tabbarManager } from '@/utils/tabbarManager';
import WxAuthLogin from '@/components/WxAuthLogin/WxAuthLogin.vue';
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
const wxAuthLoginRef = ref(null);
const { $api, navTo, cloneDeep } = inject('globalFunction');
const weekList = ref([]);
const fairList = ref([]);
@@ -131,6 +136,23 @@ onShow(() => {
tabbarManager.updateSelected(1);
});
onMounted(() => {
// 监听退出登录事件,显示微信登录弹窗
uni.$on('showLoginModal', () => {
wxAuthLoginRef.value?.open();
});
});
onUnmounted(() => {
uni.$off('showLoginModal');
});
// 登录成功回调
const handleLoginSuccess = () => {
console.log('登录成功');
// 可以在这里添加登录成功后的处理逻辑
};
function toSelectDate() {
navTo('/packageA/pages/selectDate/selectDate', {
query: {

View File

@@ -2,6 +2,9 @@
<view class="container">
<!-- 自定义tabbar -->
<CustomTabBar :currentPage="2" />
<!-- 微信授权登录弹窗 -->
<WxAuthLogin ref="wxAuthLoginRef" @success="handleLoginSuccess"></WxAuthLogin>
<!-- 抽屉遮罩层 -->
<view v-if="isDrawerOpen" class="overlay" @click="toggleDrawer"></view>
@@ -73,7 +76,7 @@
</template>
<script setup>
import { ref, inject, nextTick, computed } from 'vue';
import { ref, inject, nextTick, computed, onMounted, onUnmounted } from 'vue';
const { $api, navTo, insertSortData, config } = inject('globalFunction');
import { onLoad, onShow, onHide } from '@dcloudio/uni-app';
import useChatGroupDBStore from '@/stores/userChatGroupStore';
@@ -81,6 +84,7 @@ import useUserStore from '@/stores/useUserStore';
import { tabbarManager } from '@/utils/tabbarManager';
import aiPaging from './components/ai-paging.vue';
import { storeToRefs } from 'pinia';
import WxAuthLogin from '@/components/WxAuthLogin/WxAuthLogin.vue';
const { isTyping, tabeList, chatSessionID } = storeToRefs(useChatGroupDBStore());
const { userInfo } = storeToRefs(useUserStore());
const isDrawerOpen = ref(false);
@@ -88,6 +92,7 @@ const scrollIntoView = ref(false);
const searchText = ref('');
const paging = ref(null);
const wxAuthLoginRef = ref(null);
// 实时过滤
const filteredList = computed(() => {
@@ -110,6 +115,23 @@ onShow(() => {
tabbarManager.updateSelected(2);
});
onMounted(() => {
// 监听退出登录事件,显示微信登录弹窗
uni.$on('showLoginModal', () => {
wxAuthLoginRef.value?.open();
});
});
onUnmounted(() => {
uni.$off('showLoginModal');
});
// 登录成功回调
const handleLoginSuccess = () => {
console.log('登录成功');
// 可以在这里添加登录成功后的处理逻辑
};
onHide(() => {
paging.value?.handleTouchCancel();
if (isDrawerOpen.value) {

View File

@@ -1,11 +1,7 @@
<template>
<view class="chat-container">
<!-- #ifdef MP-WEIXIN -->
<view class="chat-background">
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<view class="chat-background" v-fade:600="!messages.length">
<!-- #endif -->
<view class="chat-background" v-if="!messages.length">
<image class="backlogo" src="/static/icon/backAI.png"></image>
<view class="back-rowTitle">欢迎使用{{ config.appInfo.areaName }}AI智能求职</view>
<view class="back-rowText">
@@ -24,6 +20,28 @@
<view class="message">{{ recognizedText }} {{ lastFinalText }}</view>
</view>
</view>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<view class="chat-background" v-if="!messages.length">
<image class="backlogo" src="/static/icon/backAI.png"></image>
<view class="back-rowTitle">欢迎使用{{ config.appInfo.areaName }}AI智能求职</view>
<view class="back-rowText">
我可以根据您的简历和求职需求帮你精准匹配{{ config.appInfo.areaName }}互联网招聘信息对比招聘信息的优缺点提供面试指导等请把你的任务交给我吧~
</view>
<view class="back-rowh3">猜你所想</view>
<view
class="back-rowmsg button-click"
v-for="(item, index) in queries"
:key="index"
@click="sendMessageGuess(item)"
>
{{ item }}
</view>
<view class="chat-item self" v-if="isRecording">
<view class="message">{{ recognizedText }} {{ lastFinalText }}</view>
</view>
</view>
<!-- #endif -->
<scroll-view class="chat-list scrollView" :scroll-top="scrollTop" :scroll-y="true" scroll-with-animation>
<!-- #ifdef MP-WEIXIN -->
<view class="chat-list list-content">
@@ -946,19 +964,19 @@ image-margin-top = 40rpx
white-space: pre-wrap;
}
.list-content {
padding: 0 44rpx 44rpx 44rpx;
padding: 0 44rpx 10rpx 44rpx;
}
.chat-item {
display: flex;
align-items: flex-start;
margin-bottom: 20rpx;
margin-bottom: 10rpx;
width: 100%;
}
.chat-item.self {
justify-content: flex-end;
}
.message
margin-top: 40rpx
margin-top: 0rpx
// max-width: 80%;
width: 100%;
word-break: break-word;
@@ -1003,10 +1021,12 @@ image-margin-top = 40rpx
}
.input-area {
padding: 32rpx 28rpx 24rpx 28rpx;
padding-bottom: calc(24rpx + env(safe-area-inset-bottom) + 40rpx - 40rpx);
position: relative;
background: #FFFFFF;
box-shadow: 0rpx -4rpx 10rpx 0rpx rgba(11,44,112,0.06);
transition: height 2s ease-in-out;
z-index: 1001;
}
.input-area::after
position: absolute

View File

@@ -1,5 +1,5 @@
<template>
<AppLayout title="企业信息">
<AppLayout>
<view class="company-info-container">
<!-- 头部信息 -->
<view class="header-info">
@@ -131,6 +131,15 @@
</view>
</view>
<!-- 企业规模 -->
<view class="form-item clickable" @click="selectScale">
<view class="label">企业规模</view>
<view class="input-content">
<input class="input-con" v-model="formData.scaleText" disabled placeholder="请选择企业规模" />
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
</view>
</view>
<!-- 联系人信息列表 -->
<view class="contact-section">
<view class="section-title">联系人信息</view>
@@ -225,9 +234,11 @@ import { onLoad } from '@dcloudio/uni-app'
import AreaCascadePicker from '@/components/area-cascade-picker/area-cascade-picker.vue'
import SelectPopup from '@/components/selectPopup/selectPopup.vue'
import useDictStore from '@/stores/useDictStore'
import useUserStore from '@/stores/useUserStore'
const { $api } = inject('globalFunction')
const dictStore = useDictStore()
const userStore = useUserStore()
// 表单数据
const formData = reactive({
@@ -246,6 +257,8 @@ const formData = reactive({
legalPhone: '', // 法人联系方式
industryType: '', // 是否是本地重点发展产业
isLocalCompany: null, // 是否是本地企业 (true/false/null)
scale: '', // 企业规模
scaleText: '', // 企业规模显示文本
companyContactList: [
{ contactPerson: '', contactPersonPhone: '' }
]
@@ -311,7 +324,8 @@ const completionPercentage = computed(() => {
formData.legalIdCard,
formData.legalPhone,
formData.industryType,
formData.isLocalCompany !== null ? 'filled' : ''
formData.isLocalCompany !== null ? 'filled' : '',
formData.scale
]
// 检查联系人信息
@@ -464,6 +478,73 @@ const selectLocalCompany = () => {
})
}
// 企业规模选项数据从字典中获取
const scaleOptions = computed(() => {
const scaleData = dictStore.state?.scale || []
console.log('企业规模选项数据:', scaleData)
return scaleData
})
// 选择企业规模
const selectScale = () => {
console.log('点击企业规模,当前数据:', scaleOptions.value)
console.log('字典store状态:', dictStore.state.scale)
// 获取企业规模选项,优先使用字典数据,失败时使用备用数据
let options = scaleOptions.value
if (!options || !options.length) {
console.log('企业规模数据为空,尝试重新加载')
// 尝试重新加载字典数据
dictStore.getDictData().then(() => {
if (dictStore.state.scale && dictStore.state.scale.length > 0) {
selectScale() // 递归调用
} else {
// 使用备用数据
console.log('使用备用企业规模数据')
options = fallbackScaleOptions
showScaleSelector(options)
}
}).catch(() => {
// 使用备用数据
console.log('字典加载失败,使用备用企业规模数据')
options = fallbackScaleOptions
showScaleSelector(options)
})
return
}
showScaleSelector(options)
}
// 备用企业规模选项(当字典数据加载失败时使用)
const fallbackScaleOptions = [
{ label: '1-10人', value: '1' },
{ label: '11-50人', value: '2' },
{ label: '51-100人', value: '3' },
{ label: '101-500人', value: '4' },
{ label: '501-1000人', value: '5' },
{ label: '1000人以上', value: '6' }
]
// 显示企业规模选择器
const showScaleSelector = (options) => {
console.log('企业规模选项列表:', options)
openSelectPopup({
title: '企业规模',
maskClick: true,
data: [options],
success: (_, [value]) => {
console.log('选择的企业规模:', value)
formData.scale = value.value
formData.scaleText = value.label
updateCompletion()
$api.msg('企业规模选择成功')
}
})
}
// 添加联系人
const addContact = () => {
@@ -573,6 +654,11 @@ const confirm = () => {
return
}
if (!formData.scale.trim()) {
$api.msg('请选择企业规模')
return
}
// 验证身份证号格式
const idCardRegex = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
if (!idCardRegex.test(formData.legalIdCard)) {
@@ -623,6 +709,7 @@ const confirm = () => {
legalPhone: formData.legalPhone,
industryType: formData.industryType,
isLocalCompany: formData.isLocalCompany,
scale: formData.scaleText,
companyContactList: formData.companyContactList.filter(contact => contact.contactPerson.trim() && contact.contactPersonPhone.trim())
}
@@ -632,10 +719,19 @@ const confirm = () => {
}
$api.createRequest('/app/user/registerUser', submitData, 'post')
.then((resData) => {
.then(async (resData) => {
uni.hideLoading()
$api.msg('企业信息保存成功')
// 保存成功后,重新获取用户信息并更新缓存
try {
await userStore.getUserResume()
console.log('用户信息已更新到缓存')
} catch (error) {
console.error('获取用户信息失败:', error)
// 即使获取用户信息失败,也不影响页面跳转
}
// 跳转到首页或企业相关页面
uni.reLaunch({
url: '/pages/index/index'

View File

@@ -5,11 +5,39 @@
<image class="mp-background" src="/static/icon/background2.png" mode="aspectFill"></image>
<!-- #endif -->
<!-- 企业账号显示卡片 -->
<view class="enterprise-card btn-feel" v-if="shouldShowCompanyCard" @click="goToCompanyInfo">
<view class="card-content">
<!-- 企业图标 -->
<view class="company-icon">
<image
v-if="companyInfo.avatar"
:src="companyInfo.avatar"
class="logo-image"
mode="aspectFit"
/>
<view v-else class="default-logo">
<uni-icons type="home-filled" size="32" color="#256BFA"></uni-icons>
</view>
</view>
<!-- 企业信息 -->
<view class="company-info">
<view class="company-name">{{ companyInfo.name || '企业名称' }}</view>
<view class="company-details">
<text class="industry">{{ companyInfo.industry || '互联网' }}</text>
<text class="separator">·</text>
<text class="size">{{ companyInfo.scale || '100-999人' }}</text>
</view>
</view>
</view>
</view>
<view
class="nav-hidden hidden-animation"
:class="{ 'hidden-height': shouldHideTop }"
>
<view class="container-search">
<view class="container-search" v-if="shouldShowJobSeekerContent">
<view class="search-input button-click" @click="navTo('/pages/search/search')">
<uni-icons class="iconsearch" color="#666666" type="search" size="18"></uni-icons>
<text class="inpute">职位名称薪资要求等</text>
@@ -93,7 +121,7 @@
</view>
<!-- 企业用户内容 -->
<view class="company-content" v-if="shouldShowCompanyContent">
<!-- <view class="company-content" v-if="shouldShowCompanyContent">
<view class="company-header">
<text class="company-title">企业服务</text>
<text class="company-subtitle">为您提供专业的企业招聘服务</text>
@@ -125,7 +153,7 @@
<view class="company-title">人才库</view>
</view>
</view>
</view>
</view> -->
<!-- 吸顶筛选区域占位 -->
<view class="filter-placeholder" v-if="shouldStickyFilter && shouldShowJobSeekerContent"></view>
@@ -378,20 +406,71 @@ const shouldShowJobSeekerContent = computed(() => {
if (!hasLogin.value) {
return true;
}
// 登录后根据用户类型判断
const userType = userInfo.value?.isCompanyUser;
// 优先从store获取如果为空则从缓存获取
const storeIsCompanyUser = userInfo.value?.isCompanyUser;
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
const cachedIsCompanyUser = cachedUserInfo.isCompanyUser;
// 获取用户类型优先使用store中的isCompanyUser如果store中没有使用缓存中的isCompanyUser
// 缓存中的值可能是字符串,需要转换为数值类型
const userType = storeIsCompanyUser !== undefined ? Number(storeIsCompanyUser) : Number(cachedIsCompanyUser);
// 企业用户(isCompanyUser=0)不显示求职者内容,其他用户类型显示
return userType !== 0;
});
// 企业信息数据
const companyInfo = reactive({
name: '',
avatar: '',
industry: '',
size: '',
isVerified: false
});
// 计算是否显示企业卡片
const shouldShowCompanyCard = computed(() => {
// 未登录时不显示
if (!hasLogin.value) {
return false;
}
// 优先从store获取如果为空则从缓存获取
const storeIsCompanyUser = userInfo.value?.isCompanyUser;
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
const cachedIsCompanyUser = cachedUserInfo.isCompanyUser;
// 获取用户类型优先使用store中的isCompanyUser如果store中没有使用缓存中的isCompanyUser
// 缓存中的值可能是字符串,需要转换为数值类型
const userType = storeIsCompanyUser !== undefined ? Number(storeIsCompanyUser) : Number(cachedIsCompanyUser);
// 只有企业用户(isCompanyUser=0)才显示企业卡片
if (userType !== 0) {
return false;
}
// 检查企业信息是否已完善
return companyInfo.name && companyInfo.name.trim() !== '';
});
// 计算是否显示企业用户内容
const shouldShowCompanyContent = computed(() => {
// 未登录时不显示企业内容
if (!hasLogin.value) {
return false;
}
// 优先从store获取如果为空则从缓存获取
const storeIsCompanyUser = userInfo.value?.isCompanyUser;
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
const cachedIsCompanyUser = cachedUserInfo.isCompanyUser;
// 获取用户类型优先使用store中的isCompanyUser如果store中没有使用缓存中的isCompanyUser
// 缓存中的值可能是字符串,需要转换为数值类型
const userType = storeIsCompanyUser !== undefined ? Number(storeIsCompanyUser) : Number(cachedIsCompanyUser);
// 只有企业用户(isCompanyUser=0)才显示企业内容
const userType = userInfo.value?.isCompanyUser;
return userType === 0;
});
@@ -404,6 +483,7 @@ import { useScrollDirection } from '@/hook/useScrollDirection';
import { useColumnCount } from '@/hook/useColumnCount';
import WxAuthLogin from '@/components/WxAuthLogin/WxAuthLogin.vue';
import IconfontIcon from '@/components/IconfontIcon/IconfontIcon.vue'
// 企业卡片组件已内联到模板中
// 滚动状态管理
const shouldHideTop = ref(false);
const shouldStickyFilter = ref(false);
@@ -489,9 +569,66 @@ const { columnCount, columnSpace } = useColumnCount(() => {
});
});
// 获取企业信息
const getCompanyInfo = () => {
try {
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
console.log('缓存中的userInfo:', cachedUserInfo);
// 检查是否有company字段
if (cachedUserInfo.company) {
const company = cachedUserInfo.company;
// 基本信息
companyInfo.name = company.name || '';
companyInfo.avatar = company.avatar || '';
companyInfo.industry = company.industryType || '互联网';
companyInfo.size = company.companySize || '100-999人';
// 判断是否实名legalIdCard字段有值则表示已实名
companyInfo.isVerified = !!(company.legalIdCard && company.legalIdCard.trim());
console.log('企业信息:', {
name: companyInfo.name,
industry: companyInfo.industry,
size: companyInfo.size,
isVerified: companyInfo.isVerified
});
} else {
console.log('缓存中没有company字段');
// 保持默认值
}
} catch (error) {
console.error('获取企业信息失败:', error);
// 保持默认值
}
};
// 跳转到企业信息详情页面
const goToCompanyInfo = () => {
navTo('/pages/mine/company-info');
};
// 组件初始化时加载数据
onMounted(() => {
getJobRecommend('refresh');
// 获取企业信息
getCompanyInfo();
// 监听退出登录事件,显示微信登录弹窗
uni.$on('showLoginModal', () => {
wxAuthLoginRef.value?.open();
});
});
onUnmounted(() => {
uni.$off('showLoginModal');
});
onShow(() => {
// 获取最新的企业信息
getCompanyInfo();
});
// 登录检查函数
@@ -1548,4 +1685,133 @@ defineExpose({ loadData });
.isBut{
filter: grayscale(100%);
}
// 企业账号显示卡片样式
.enterprise-card
margin: 20rpx 28rpx
padding: 28rpx
background: rgba(255, 255, 255, 0.9)
backdrop-filter: blur(20rpx)
-webkit-backdrop-filter: blur(20rpx)
border-radius: 24rpx
border: 1rpx solid rgba(255, 255, 255, 0.4)
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.08), 0 2rpx 8rpx rgba(0, 0, 0, 0.04)
position: relative
overflow: hidden
cursor: pointer
transition: all 0.3s ease
&:active
transform: scale(0.98)
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.12), 0 1rpx 4rpx rgba(0, 0, 0, 0.08)
// 玻璃态效果 - 更强烈的渐变
&::before
content: ''
position: absolute
top: 0
left: 0
right: 0
bottom: 0
background: linear-gradient(135deg,
rgba(255, 255, 255, 0.2) 0%,
rgba(255, 255, 255, 0.1) 50%,
rgba(255, 255, 255, 0.05) 100%)
border-radius: 24rpx
pointer-events: none
z-index: 0
// 添加微妙的边框高光
&::after
content: ''
position: absolute
top: 0
left: 0
right: 0
bottom: 0
border-radius: 24rpx
padding: 1rpx
background: linear-gradient(135deg,
rgba(255, 255, 255, 0.6) 0%,
rgba(255, 255, 255, 0.2) 100%)
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)
mask-composite: xor
-webkit-mask-composite: xor
pointer-events: none
z-index: 1
.card-content
display: flex
align-items: center
position: relative
z-index: 2
.company-icon
width: 88rpx
height: 88rpx
border-radius: 18rpx
background: linear-gradient(135deg, #256BFA 0%, #4A90E2 100%)
display: flex
align-items: center
justify-content: center
margin-right: 28rpx
flex-shrink: 0
box-shadow: 0 6rpx 16rpx rgba(37, 107, 250, 0.25)
position: relative
// 添加图标内部高光
&::before
content: ''
position: absolute
top: 4rpx
left: 4rpx
right: 4rpx
height: 20rpx
background: linear-gradient(180deg, rgba(255, 255, 255, 0.3) 0%, transparent 100%)
border-radius: 18rpx 18rpx 0 0
pointer-events: none
.default-logo
display: flex
align-items: center
justify-content: center
color: #ffffff
.company-info
flex: 1
min-width: 0
z-index: 2
position: relative
.company-name
font-size: 34rpx
font-weight: 600
color: #000000
line-height: 1.3
margin-bottom: 10rpx
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif
.company-details
display: flex
align-items: center
font-size: 26rpx
color: #666666
line-height: 1.2
.industry
color: #666666
font-weight: 400
.separator
margin: 0 10rpx
color: #CCCCCC
font-weight: 300
.size
color: #666666
font-weight: 400
</style>

View File

@@ -2,11 +2,7 @@
<view class="publish-job-page">
<!-- 头部导航 -->
<view class="header">
<view class="header-left" @click="goBack">
<image src="@/static/icon/back.png" class="back-icon"></image>
</view>
<view class="header-title">发布岗位</view>
<view class="header-right"></view>
</view>
<!-- 主要内容 -->
@@ -216,10 +212,12 @@
<!-- 底部操作按钮 -->
<view class="footer">
<view class="btn-group">
<button class="btn btn-cancel" @click="goBack">取消</button>
<button class="btn btn-publish" @click="publishJob">发布岗位</button>
</view>
</view>
<!-- 自定义tabbar -->
<CustomTabBar :currentPage="1" />
</view>
</template>
@@ -282,7 +280,9 @@ const calculateScrollViewHeight = () => {
const windowHeight = systemInfo.windowHeight;
const headerHeight = 100; // 头部高度
const footerHeight = 120; // 底部按钮高度
const scrollHeight = windowHeight - headerHeight - footerHeight;
const tabbarHeight = 88; // 自定义tabbar高度
const extraPadding = 50; // 额外间距,确保内容不被遮挡
const scrollHeight = windowHeight - headerHeight - footerHeight - tabbarHeight - extraPadding;
scrollViewHeight.value = `${scrollHeight}px`;
};
const userType = ref(Number(userStore.userInfo.isCompanyUser));
@@ -417,10 +417,6 @@ const handleCompanySelected = (company) => {
formData.companyId = company.id;
};
// 返回上一页
const goBack = () => {
uni.navigateBack();
};
// 发布岗位
const publishJob = async () => {
@@ -464,10 +460,10 @@ const publishJob = async () => {
icon: 'success'
});
// 延迟返回
setTimeout(() => {
goBack();
}, 1500);
uni.redirectTo({
url: '/pages/index/index'
});
} else {
uni.showToast({
title: response.msg || '发布失败',
@@ -565,18 +561,6 @@ const validateForm = () => {
background: #fff;
border-bottom: 1rpx solid #eee;
.header-left {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
.back-icon {
width: 40rpx;
height: 40rpx;
}
}
.header-title {
font-size: 36rpx;
@@ -864,23 +848,22 @@ const validateForm = () => {
}
.bottom-safe-area {
height: 120rpx;
height: 250rpx;
background: transparent;
}
.footer {
position: fixed;
bottom: 0;
bottom: 140rpx;
left: 0;
right: 0;
background: #fff;
padding: 20rpx 30rpx;
padding: 25rpx 30rpx;
border-top: 1rpx solid #eee;
z-index: 100;
.btn-group {
display: flex;
gap: 20rpx;
.btn {
flex: 1;
@@ -890,11 +873,6 @@ const validateForm = () => {
font-weight: 500;
border: none;
&.btn-cancel {
background: #f5f5f5;
color: #666;
}
&.btn-publish {
background: #256BFA;
color: #fff;

View File

@@ -1,15 +1,10 @@
<template>
<AppLayout title="企业信息" back-gorund-color="#F4F4F4">
<!-- 头部进度显示 -->
<view class="header-progress">
<text class="progress-text">{{ companyInfo.completeness || '100%' }}</text>
</view>
<AppLayout back-gorund-color="#F4F4F4">
<!-- 编辑头像 -->
<view class="avatar-section btn-feel" @click="editAvatar">
<view class="avatar-label">编辑头像</view>
<view class="avatar-container">
<image class="company-avatar" :src="companyInfo.avatar || '/static/icon/company-avatar.png'"></image>
<image class="company-avatar" :src="companyInfo.avatar || '/static/imgs/avatar.jpg'"></image>
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
</view>
</view>
@@ -19,7 +14,7 @@
<view class="info-item btn-feel" @click="editInfo('name')">
<view class="info-label">企业名称</view>
<view class="info-content">
<text class="info-value">{{ companyInfo.name || '科里(北京)科技有限公司(喀什分公司)' }}</text>
<text class="info-value">{{ companyInfo.name || '暂无公司名称' }}</text>
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
</view>
</view>
@@ -27,7 +22,7 @@
<view class="info-item btn-feel" @click="editInfo('code')">
<view class="info-label">统一社会代码</view>
<view class="info-content">
<text class="info-value">{{ companyInfo.socialCode || '6217171301012562295' }}</text>
<text class="info-value">{{ companyInfo.socialCode || '暂无统一社会代码' }}</text>
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
</view>
</view>
@@ -35,7 +30,7 @@
<view class="info-item btn-feel" @click="editInfo('location')">
<view class="info-label">企业注册地点</view>
<view class="info-content">
<text class="info-value">{{ companyInfo.location || '北京' }}</text>
<text class="info-value">{{ companyInfo.location || '暂无注册地点' }}</text>
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
</view>
</view>
@@ -43,7 +38,7 @@
<view class="info-item btn-feel" @click="editInfo('description')">
<view class="info-label">企业信息介绍</view>
<view class="info-content">
<text class="info-value">{{ companyInfo.description || '公司成立于2003年01月27日,位于北京市大兴区经济技术产业开发区天泰一路3号一号楼南四、五楼,目前处于开业状态,经营范围包括信息技术咨询服务;科技中介服务;人工智能等。' }}</text>
<text class="info-value">{{ companyInfo.description || '暂无企业介绍' }}</text>
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
</view>
</view>
@@ -51,7 +46,7 @@
<view class="info-item btn-feel" @click="editInfo('legalPerson')">
<view class="info-label">企业法人姓名</view>
<view class="info-content">
<text class="info-value">{{ companyInfo.legalPerson || '孙正云' }}</text>
<text class="info-value">{{ companyInfo.legalPerson || '暂无法人信息' }}</text>
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
</view>
</view>
@@ -59,7 +54,7 @@
<view class="info-item btn-feel" @click="editInfo('contact1')">
<view class="info-label">企业联系人名称</view>
<view class="info-content">
<text class="info-value">{{ companyInfo.contact1Name || '吴宣萱' }}</text>
<text class="info-value">{{ companyInfo.contact1Name || '暂无联系人' }}</text>
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
</view>
</view>
@@ -67,7 +62,7 @@
<view class="info-item btn-feel" @click="editInfo('contact1Phone')">
<view class="info-label">企业联系人电话</view>
<view class="info-content">
<text class="info-value">{{ companyInfo.contact1Phone || '15547143804' }}</text>
<text class="info-value">{{ companyInfo.contact1Phone || '暂无联系电话' }}</text>
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
</view>
</view>
@@ -75,7 +70,7 @@
<view class="info-item btn-feel" @click="editInfo('contact2')">
<view class="info-label">企业联系人名称</view>
<view class="info-content">
<text class="info-value">{{ companyInfo.contact2Name || '李杰' }}</text>
<text class="info-value">{{ companyInfo.contact2Name || '暂无联系人' }}</text>
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
</view>
</view>
@@ -83,7 +78,7 @@
<view class="info-item btn-feel" @click="editInfo('contact2Phone')">
<view class="info-label">企业联系人电话</view>
<view class="info-content">
<text class="info-value">{{ companyInfo.contact2Phone || '10700010700' }}</text>
<text class="info-value">{{ companyInfo.contact2Phone || '暂无联系电话' }}</text>
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
</view>
</view>
@@ -94,22 +89,24 @@
<script setup>
import { reactive, inject, onMounted } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import AppLayout from '@/components/AppLayout/AppLayout.vue';
const { $api, navTo } = inject('globalFunction');
// 企业信息数据
const companyInfo = reactive({
name: '科里(北京)科技有限公司(喀什分公司)',
avatar: '/static/icon/company-avatar.png',
name: '',
avatar: '/static/imgs/avatar.jpg',
completeness: '100%',
socialCode: '6217171301012562295',
location: '北京',
description: '公司成立于2003年01月27日,位于北京市大兴区经济技术产业开发区天泰一路3号一号楼南四、五楼,目前处于开业状态,经营范围包括信息技术咨询服务;科技中介服务;人工智能等。',
legalPerson: '孙正云',
contact1Name: '吴宣萱',
contact1Phone: '15547143804',
contact2Name: '李杰',
contact2Phone: '10700010700'
socialCode: '',
location: '',
description: '',
legalPerson: '',
contact1Name: '',
contact1Phone: '',
contact2Name: '',
contact2Phone: '',
isVerified: false // 实名状态
});
function editAvatar() {
@@ -166,24 +163,56 @@ onShow(() => {
getCompanyInfo();
});
// 从缓存获取公司信息
function getCompanyInfo() {
// 这里可以调用API获取企业信息
// $api.createRequest('/app/company/info').then((resData) => {
// Object.assign(companyInfo, resData.data);
// });
try {
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
console.log('缓存中的userInfo:', cachedUserInfo);
// 检查是否有company字段
if (cachedUserInfo.company) {
const company = cachedUserInfo.company;
// 基本信息
companyInfo.name = company.name || '';
companyInfo.socialCode = company.code || '';
companyInfo.location = company.registeredAddress || '';
companyInfo.description = company.description || '';
companyInfo.legalPerson = company.legalPerson || '';
// 联系人信息
if (company.companyContactList && company.companyContactList.length > 0) {
const contacts = company.companyContactList;
companyInfo.contact1Name = contacts[0]?.contactPerson || '';
companyInfo.contact1Phone = contacts[0]?.contactPersonPhone || '';
if (contacts.length > 1) {
companyInfo.contact2Name = contacts[1]?.contactPerson || '';
companyInfo.contact2Phone = contacts[1]?.contactPersonPhone || '';
}
}
// 判断是否实名legalIdCard字段有值则表示已实名
companyInfo.isVerified = !!(company.legalIdCard && company.legalIdCard.trim());
console.log('公司名称:', companyInfo.name);
console.log('实名状态:', companyInfo.isVerified);
console.log('legalIdCard值:', company.legalIdCard);
} else {
console.log('缓存中没有company字段');
// 保持默认值
}
} catch (error) {
console.error('获取公司信息失败:', error);
// 保持默认值
}
}
function goBack() {
uni.navigateBack();
}
</script>
<style lang="stylus" scoped>
.header-progress {
text-align: center;
padding: 20rpx 0;
.progress-text {
font-size: 28rpx;
color: #6C7282;
}
}
.avatar-section {
display: flex;

View File

@@ -1,16 +1,21 @@
<template>
<AppLayout title="我的" back-gorund-color="#F4F4F4">
<AppLayout back-gorund-color="#F4F4F4">
<!-- 自定义tabbar -->
<CustomTabBar :currentPage="4" />
<!-- 企业信息卡片 -->
<view class="company-info-card btn-feel" @click="goToCompanyInfo">
<view class="company-avatar">
<image class="company-avatar-img" :src="companyInfo.avatar || '/static/icon/company-default.png'"></image>
<image class="company-avatar-img" :src="companyInfo.avatar || '/static/imgs/avatar.jpg'"></image>
</view>
<view class="company-details">
<view class="company-name">{{ companyInfo.name || '科里喀什分公司' }}</view>
<view class="company-completeness">信息完整度 {{ companyInfo.completeness || '100%' }}</view>
<view class="company-name">{{ companyInfo.name || '暂无公司名称' }}</view>
<view class="company-completeness">
信息完整度 {{ companyInfo.completeness || '100%' }}
<text class="verification-status" :class="{ 'verified': companyInfo.isVerified, 'unverified': !companyInfo.isVerified }">
{{ companyInfo.isVerified ? '已实名' : '未实名' }}
</text>
</view>
</view>
<view class="company-arrow">
<uni-icons color="#A2A2A2" type="right" size="16"></uni-icons>
@@ -22,14 +27,16 @@
<view class="service-title">服务专区</view>
<view class="service-item btn-feel">
<view class="service-left">
<image class="service-icon" src="/static/icon/real-name-auth.png"></image>
<uni-icons type="contact" size="20" color="#256BFA"></uni-icons>
<text class="service-text">实名认证</text>
</view>
<view class="service-status">已通过</view>
<view class="service-status" :class="{ 'verified': companyInfo.isVerified, 'unverified': !companyInfo.isVerified }">
{{ companyInfo.isVerified ? '已通过' : '未认证' }}
</view>
</view>
<view class="service-item btn-feel">
<view class="service-left">
<image class="service-icon" src="/static/icon/notification.png"></image>
<uni-icons type="notification" size="20" color="#256BFA"></uni-icons>
<text class="service-text">通知与提醒</text>
</view>
<view class="service-status">已开启</view>
@@ -57,17 +64,19 @@
</template>
<script setup>
import { reactive, inject, ref, onMounted } from 'vue';
import { reactive, inject, ref, onMounted, onUnmounted } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import useUserStore from '@/stores/useUserStore';
const { $api, navTo } = inject('globalFunction');
const popup = ref(null);
// 企业信息数据
const companyInfo = reactive({
name: '科里喀什分公司',
avatar: '/static/icon/company-avatar.png',
completeness: '100%'
name: '',
avatar: '/static/imgs/avatar.jpg',
completeness: '100%',
isVerified: false // 实名状态
});
function goToCompanyInfo() {
@@ -83,9 +92,11 @@ function close() {
}
function confirm() {
// 这里可以调用退出登录的API
console.log('退出登录');
// 跳转到登录页面或首页
// 调用退出登录
useUserStore().logOut();
// 关闭弹窗
popup.value.close();
// 跳转到首页
uni.reLaunch({
url: '/pages/index/index'
});
@@ -96,11 +107,45 @@ onShow(() => {
getCompanyInfo();
});
// 监听退出登录事件,显示微信登录弹窗
onMounted(() => {
uni.$on('showLoginModal', () => {
// 这里可以显示微信登录弹窗
// 由于这个页面没有 WxAuthLogin 组件,我们跳转到首页让首页处理
uni.reLaunch({
url: '/pages/index/index'
});
});
});
onUnmounted(() => {
uni.$off('showLoginModal');
});
// 从缓存获取公司信息
function getCompanyInfo() {
// 这里可以调用API获取企业信息
// $api.createRequest('/app/company/info').then((resData) => {
// Object.assign(companyInfo, resData.data);
// });
try {
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
console.log('缓存中的userInfo:', cachedUserInfo);
// 检查是否有company字段
if (cachedUserInfo.company) {
companyInfo.name = cachedUserInfo.company.name || '';
// 判断是否实名legalIdCard字段有值则表示已实名
companyInfo.isVerified = !!(cachedUserInfo.company.legalIdCard && cachedUserInfo.company.legalIdCard.trim());
console.log('公司名称:', companyInfo.name);
console.log('实名状态:', companyInfo.isVerified);
console.log('legalIdCard值:', cachedUserInfo.company.legalIdCard);
} else {
console.log('缓存中没有company字段');
companyInfo.name = '';
companyInfo.isVerified = false;
}
} catch (error) {
console.error('获取公司信息失败:', error);
companyInfo.name = '';
companyInfo.isVerified = false;
}
}
</script>
@@ -140,6 +185,25 @@ function getCompanyInfo() {
.company-completeness {
font-size: 28rpx;
color: #6C7282;
display: flex;
align-items: center;
gap: 16rpx;
.verification-status {
font-size: 24rpx;
padding: 4rpx 12rpx;
border-radius: 12rpx;
&.verified {
background-color: #E8F5E8;
color: #52C41A;
}
&.unverified {
background-color: #FFF2E8;
color: #FA8C16;
}
}
}
}
@@ -177,21 +241,24 @@ function getCompanyInfo() {
display: flex;
align-items: center;
.service-icon {
width: 44rpx;
height: 44rpx;
margin-right: 16rpx;
}
.service-text {
font-size: 28rpx;
color: #333333;
margin-left: 16rpx;
}
}
.service-status {
font-size: 28rpx;
color: #6E6E6E;
&.verified {
color: #52C41A;
}
&.unverified {
color: #FA8C16;
}
}
}
}

View File

@@ -120,7 +120,7 @@
</template>
<script setup>
import { reactive, inject, watch, ref, onMounted } from 'vue';
import { reactive, inject, watch, ref, onMounted, onUnmounted } from 'vue';
import { storeToRefs } from 'pinia';
import { onLoad, onShow } from '@dcloudio/uni-app';
const { $api, navTo } = inject('globalFunction');
@@ -145,6 +145,21 @@ onShow(() => {
tabbarManager.updateSelected(4);
});
// 监听退出登录事件,显示微信登录弹窗
onMounted(() => {
uni.$on('showLoginModal', () => {
// 这里可以显示微信登录弹窗
// 由于这个页面没有 WxAuthLogin 组件,我们跳转到首页让首页处理
uni.reLaunch({
url: '/pages/index/index'
});
});
});
onUnmounted(() => {
uni.$off('showLoginModal');
});
function close() {
popup.value.close();
}

View File

@@ -21,8 +21,8 @@
<component :is="components[index]" :ref="(el) => handelComponentsRef(el, index)" />
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<ReadComponent v-show="currentIndex === 0" :ref="(el) => handelComponentsRef(el, index)" />
<UnreadComponent v-show="currentIndex === 1" :ref="(el) => handelComponentsRef(el, index)" />
<ReadComponent v-show="state.current === 0" :ref="(el) => handelComponentsRef(el, index)" />
<UnreadComponent v-show="state.current === 1" :ref="(el) => handelComponentsRef(el, index)" />
<!-- #endif -->
</swiper-item>
</swiper>
@@ -30,6 +30,9 @@
<!-- 自定义tabbar -->
<CustomTabBar :currentPage="3" />
<!-- 微信授权登录弹窗 -->
<WxAuthLogin ref="wxAuthLoginRef" @success="handleLoginSuccess"></WxAuthLogin>
<!-- 统一使用系统tabBar -->
</view>
@@ -37,18 +40,20 @@
</template>
<script setup>
import { reactive, inject, watch, ref, onMounted } from 'vue';
import { reactive, inject, watch, ref, onMounted, onUnmounted } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import Tabbar from '@/components/tabbar/midell-box.vue';
import ReadComponent from './read.vue';
import UnreadComponent from './unread.vue';
import { tabbarManager } from '@/utils/tabbarManager';
import WxAuthLogin from '@/components/WxAuthLogin/WxAuthLogin.vue';
const loadedMap = reactive([false, false]);
const swiperRefs = [ref(null), ref(null)];
const components = [ReadComponent, UnreadComponent];
import { storeToRefs } from 'pinia';
import { useReadMsg } from '@/stores/useReadMsg';
const { unreadCount } = storeToRefs(useReadMsg());
const wxAuthLoginRef = ref(null);
onShow(() => {
// 获取消息列表
@@ -63,8 +68,23 @@ const state = reactive({
onMounted(() => {
handleTabChange(state.current);
// 监听退出登录事件,显示微信登录弹窗
uni.$on('showLoginModal', () => {
wxAuthLoginRef.value?.open();
});
});
onUnmounted(() => {
uni.$off('showLoginModal');
});
// 登录成功回调
const handleLoginSuccess = () => {
console.log('登录成功');
// 可以在这里添加登录成功后的处理逻辑
};
const handelComponentsRef = (el, index) => {
if (el) {
swiperRefs[index].value = el;

View File

@@ -1,6 +1,7 @@
<template>
<scroll-view scroll-y class="main-scroll">
<view class="scrollmain">
<!-- 消息列表 -->
<view
class="list-card press-button"
v-for="(item, index) in msgList"
@@ -35,6 +36,13 @@
<view class="info-text line_2">{{ item.subTitle || '消息' }}</view>
</view>
</view>
<!-- 暂无消息提示 -->
<view class="empty-state" v-if="msgList.length === 0">
<image class="empty-icon" src="/static/icon/empty.png" mode="aspectFit"></image>
<text class="empty-text">暂无消息</text>
<text class="empty-desc">您还没有收到任何消息</text>
</view>
</view>
</scroll-view>
</template>
@@ -146,4 +154,26 @@ defineExpose({ loadData });
font-size: 28rpx;
color: #6C7282;
margin-top: 4rpx;
// 空状态样式
.empty-state
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 40rpx;
.empty-icon
width: 200rpx;
height: 200rpx;
margin-bottom: 40rpx;
opacity: 0.6;
.empty-text
font-size: 32rpx;
color: #999999;
font-weight: 500;
margin-bottom: 16rpx;
.empty-desc
font-size: 28rpx;
color: #CCCCCC;
font-weight: 400;
</style>

View File

@@ -1,6 +1,7 @@
<template>
<scroll-view scroll-y class="main-scroll">
<view class="scrollmain">
<!-- 未读消息列表 -->
<view
class="list-card press-button"
v-for="(item, index) in unreadMsgList"
@@ -33,6 +34,13 @@
<view class="info-text line_2">{{ item.subTitle || '消息' }}</view>
</view>
</view>
<!-- 暂无未读消息提示 -->
<view class="empty-state" v-if="unreadMsgList.length === 0">
<image class="empty-icon" src="/static/icon/empty.png" mode="aspectFit"></image>
<text class="empty-text">暂无未读消息</text>
<text class="empty-desc">您没有未读的消息</text>
</view>
</view>
</scroll-view>
</template>
@@ -132,4 +140,26 @@ defineExpose({ loadData });
font-size: 28rpx;
color: #6C7282;
margin-top: 4rpx;
// 空状态样式
.empty-state
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 40rpx;
.empty-icon
width: 200rpx;
height: 200rpx;
margin-bottom: 40rpx;
opacity: 0.6;
.empty-text
font-size: 32rpx;
color: #999999;
font-weight: 500;
margin-bottom: 16rpx;
.empty-desc
font-size: 28rpx;
color: #CCCCCC;
font-weight: 400;
</style>