This commit is contained in:
2025-12-25 15:09:11 +08:00
6 changed files with 317 additions and 75 deletions

View File

@@ -64,7 +64,7 @@
<view v-if="hasLogin" :class="{ 'match-move-top': isMachineEnv }" class="match-card-out">
<view class="match-card">
<image class="match-card-bg" src="@/static/icon/match-card-bg.png" />
<view class="title">简历匹配职位</view>
<view class="title">为您匹配职位</view>
<view class="match-item-container">
<AIMatch :tags="matchTags" :loading="matchLoading" @tag-click="handleTagClick"></AIMatch>
</view>

View File

@@ -1,15 +1,8 @@
<template>
<AppLayout title="就业服务程序">
<AppLayout :title="pageTitle">
<view v-if="isMachineEnv && !hasLogin" class="alipay-login-container">
<!-- 切换 -->
<view class="login-method-switch">
<view
class="method-item"
:class="{ active: loginMethod === 'face' }"
@click="switchLoginMethod('face')"
>
扫脸登录
</view>
<view
class="method-item"
:class="{ active: loginMethod === 'qrcode' }"
@@ -17,6 +10,13 @@
>
扫码登录
</view>
<view
class="method-item"
:class="{ active: loginMethod === 'face' }"
@click="switchLoginMethod('face')"
>
扫脸登录
</view>
</view>
<view class="login-scan-area">
@@ -64,7 +64,8 @@
</view>
<view class="countdown-container">
<view class="countdown-wrapper">
<!-- 刷脸不限时间 -->
<view class="countdown-wrapper" v-if="loginMethod === 'qrcode'">
<text class="countdown-number">{{ countdown }}</text>
<text class="countdown-text">秒后自动返回</text>
</view>
@@ -236,7 +237,7 @@ let scanInterval = null;
const countdown = ref(60);
let countdownTimer = null;
const loginMethod = ref('qrcode'); // 'qrcode' / 'face'
const pageTitle = ref('就享家服务程序');
onLoad((parmas) => {
getTreeselect();
if (!isMachineEnv.value) {
@@ -264,6 +265,7 @@ onMounted(() => {
}, 1000);
}
});
onUnmounted(() => {
stopScanAnimation();
stopCountdown();
@@ -274,7 +276,7 @@ const startCountdown = () => {
countdown.value = 60;
countdownTimer = setInterval(() => {
countdown.value--;
if (countdown.value <= 0) {
if (countdown.value <= 0 && loginMethod.value === 'qrcode') {
returnToHome();
}
}, 1000);
@@ -316,6 +318,7 @@ const switchLoginMethod = (method) => {
faceService.close();
qrHandler.start();
playTextDirectly('扫码登录');
resetCountdown();
break;
case 'face':
qrHandler.close();
@@ -323,15 +326,32 @@ const switchLoginMethod = (method) => {
playTextDirectly('扫脸登录');
break;
}
resetCountdown();
}
};
async function handleFaceLogin() {
try {
const authCode = await faceService.startFaceLogin();
console.log('拿到 AuthCode:', authCode);
// 调用后端登录接口...
console.log('authCode获取:', authCode);
if (authCode.name) {
pageTitle.value = `就享家服务程序(${authCode.name})`;
}
$api.createRequest('/app/alipay/scanLogin', authCode, 'POST').then((resData) => {
loginSetToken(resData.token).then((resume) => {
if (resume.data.jobTitleId) {
useUserStore().initSeesionId();
uni.reLaunch({
url: '/pages/index/index',
});
} else {
if (resume.data.sex) {
pageTitle.value = `就享家服务程序(${name})`;
fromValue.sex = resume.data.sex === '男' ? 0 : 1;
}
playTextDirectly('登录成功,请完善简历信息');
}
});
});
} catch (err) {
this.$api.msg(err.message);
}

View File

@@ -1,6 +1,6 @@
<template>
<view class="container">
<view v-show="searchFocus" class="search-mask" ></view>
<view v-show="searchFocus" class="search-mask"></view>
<view>
<view class="top">
<image
@@ -12,15 +12,15 @@
<view class="search-box">
<!-- 修改为左右布局的切换按钮 -->
<view class="search-type-tabs">
<view
class="type-tab button-click"
<view
class="type-tab button-click"
:class="{ active: searchType === 'job' }"
@click="setSearchType('job')"
>
职位
</view>
<view
class="type-tab button-click"
<view
class="type-tab button-click"
:class="{ active: searchType === 'major' }"
@click="setSearchType('major')"
>
@@ -40,8 +40,12 @@
@confirm="searchBtn"
/>
<!-- 联想搜索下拉列表 -->
<scroll-view scroll-y class="search-suggestions" v-show="showSuggestions && filteredSuggestions.length">
<view
<scroll-view
scroll-y
class="search-suggestions"
v-show="showSuggestions && filteredSuggestions.length"
>
<view
class="suggestion-item"
v-for="(item, index) in filteredSuggestions"
:key="index"
@@ -144,13 +148,10 @@ const filteredSuggestions = computed(() => {
const searchText = searchValue.value.toLowerCase();
try {
return majorDataSource.value.filter(item =>
item.toLowerCase().includes(searchText)
);
return majorDataSource.value.filter((item) => item.toLowerCase().includes(searchText));
} catch (error) {
return []
return [];
}
});
const pageState = reactive({
@@ -207,48 +208,50 @@ const { columnCount, columnSpace } = useColumnCount(() => {
});
onLoad((options) => {
if(options.keyWord){
searchValue.value = decodeURIComponent(options.keyWord)
searchBtn()
if (options.keyWord) {
searchValue.value = decodeURIComponent(options.keyWord);
searchBtn();
}
let arr = uni.getStorageSync('searchList');
if (arr) {
historyList.value = uni.getStorageSync('searchList');
}
getMajorDataSource()
getMajorDataSource();
});
function getMajorDataSource() {
const LoadCache = (resData) => {
if (resData.code === 200) {
majorDataSource.value = resData.data;
console.log(majorDataSource.value)
console.log(majorDataSource.value);
}
};
$api.createRequestWithCache('/app/common/majorManagement/getMajorList', {}, 'GET', false, LoadCache).then(LoadCache);
$api.createRequestWithCache('/app/common/majorManagement/getMajorList', {}, 'GET', false, LoadCache).then(
LoadCache
);
}
// 设置搜索类型并触发搜索
function setSearchType(type) {
if (searchType.value === type) return;
searchType.value = type;
// 如果输入框有值且当前是专业搜索,显示联想列表
if (searchValue.value && searchType.value === 'major' && searchFocus.value) {
showSuggestions.value = true;
} else {
showSuggestions.value = false;
}
// 如果有搜索值,触发搜索
if (searchValue.value) {
// 重置页码
pageState.page = 0;
// 触发搜索
playTextDirectly('正在为您查找岗位')
playTextDirectly('正在为您查找岗位');
// 根据搜索类型设置不同的参数
if (searchType.value === 'job') {
searchParams.value = {
@@ -259,14 +262,14 @@ function setSearchType(type) {
majorTitle: searchValue.value,
};
}
if (currentTab.value === 0) {
getJobList('refresh');
} else {
refresh();
waterfallsFlowRef.value?.refresh?.();
}
// 隐藏联想列表
showSuggestions.value = false;
}
@@ -295,7 +298,7 @@ function searchFn(item) {
function handleInputChange(e) {
const val = e.detail.value;
searchValue.value = val;
// 如果是专业搜索且输入框有值,显示联想列表
if (searchType.value === 'major' && val && searchFocus.value) {
showSuggestions.value = true;
@@ -332,13 +335,13 @@ function searchBtn() {
if (!searchValue.value) {
return;
}
playTextDirectly('正在为您查找岗位')
playTextDirectly('正在为您查找岗位');
// 保存到历史记录(仅当搜索成功时保存)
historyList.value.unshift(searchValue.value);
historyList.value = unique(historyList.value);
uni.setStorageSync('searchList', historyList.value);
// 根据搜索类型设置不同的参数
if (searchType.value === 'job') {
// 职位搜索
@@ -351,17 +354,17 @@ function searchBtn() {
majorTitle: searchValue.value,
};
}
// 重置页码
pageState.page = 0;
if (currentTab.value === 0) {
getJobList('refresh');
} else {
refresh();
waterfallsFlowRef.value?.refresh?.();
}
// 隐藏联想列表
showSuggestions.value = false;
}
@@ -414,14 +417,14 @@ function getJobList(type = 'add') {
pageState.page = 1;
pageState.maxPage = 2;
}
// 根据搜索类型构建参数
let params = {
current: pageState.page,
pageSize: pageState.pageSize,
...pageState.search,
};
// 移除之前的搜索参数,根据当前搜索类型添加
if (searchType.value === 'job') {
params.jobTitle = searchValue.value;
@@ -443,6 +446,16 @@ function getJobList(type = 'add') {
listCom.value = [...listCom.value, ...reslist];
} else {
listCom.value = [...rows];
// 一体机语音提示
if (searchType.value === 'major') {
if (rows.length) {
$api.msg('为您找到相关专业的职位');
playTextDirectly(`为您找到相关专业的职位`);
} else {
$api.msg('未找到相关专业的职位,请尝试其他关键词');
playTextDirectly(`未找到相关专业的职位,请尝试其他关键词`);
}
}
}
pageState.total = resData.total;
pageState.maxPage = Math.ceil(pageState.total / pageState.pageSize);
@@ -589,13 +602,13 @@ function dataToImg(data) {
font-weight: 400;
line-height: 36rpx;
color: #666666;
padding: 0 30rpx 0 230rpx;
padding: 0 30rpx 0 230rpx;
box-sizing: border-box;
height: 80rpx;
background: #F5F5F5;
border-radius: 73rpx;
}
.search-suggestions {
position: absolute;
top: 105%;
@@ -614,18 +627,18 @@ function dataToImg(data) {
align-items: center;
justify-items: flex-start;
border-top: 2rpx dashed #e3e3e3;
.item-txt {
font-size: 28rpx;
color: #333333;
width: 100%;
}
}
.suggestion-item:hover {
background: #e5e5e5;
}
.suggestion-item:first-child {
border-top: none;
}