Compare commits
22 Commits
311d234b5c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2df9502640 | ||
|
|
023644da0e | ||
|
|
dcb280042d | ||
|
|
7ad59aeeab | ||
|
|
57b18c0a65 | ||
|
|
6e63f81ede | ||
|
|
aa66011a16 | ||
| 9393e9a624 | |||
|
|
c417b1b86b | ||
|
|
7aa8761ea8 | ||
|
|
af800b4f63 | ||
|
|
e40f0ebab8 | ||
|
|
738e73df70 | ||
| f806ea49cd | |||
|
|
5007c3ca4e | ||
| 264d8c884c | |||
| 1d10f5c75a | |||
|
|
4f590d12a7 | ||
|
|
e7222e93d8 | ||
|
|
4e57363b4a | ||
| 85e5061a02 | |||
|
|
c60119c369 |
@@ -1,4 +1,6 @@
|
||||
import useUserStore from "../stores/useUserStore";
|
||||
import { sm4Encrypt, sm4Decrypt } from '@/utils/crypto';
|
||||
|
||||
import {
|
||||
request,
|
||||
createRequest,
|
||||
@@ -384,6 +386,14 @@ const formatTotal = (total) => {
|
||||
return `${roundedTotal}+`;
|
||||
};
|
||||
|
||||
export function sm2_Decrypt(word, key) {
|
||||
return SM.decrypt(word, key);
|
||||
}
|
||||
|
||||
export function sm2_Encrypt(word, key) {
|
||||
return SM.encrypt(word, key);
|
||||
}
|
||||
|
||||
export function formatDate(isoString) {
|
||||
const date = new Date(isoString);
|
||||
const year = date.getFullYear();
|
||||
@@ -1041,4 +1051,8 @@ export default {
|
||||
insertSortData,
|
||||
isInWechatMiniProgramWebview,
|
||||
isEmptyObject,
|
||||
sm4Decrypt,
|
||||
sm4Encrypt,
|
||||
sm2_Decrypt,
|
||||
sm2_Encrypt,
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ function nextDetail(job) {
|
||||
const recordData = recommedIndexDb.JobParameter(job);
|
||||
recommedIndexDb.addRecord(recordData);
|
||||
}
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}`);
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ function nextDetail(job) {
|
||||
const recordData = recommedIndexDb.JobParameter(job);
|
||||
recommedIndexDb.addRecord(recordData);
|
||||
}
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}`);
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
|
||||
}
|
||||
|
||||
function toggleSelect(jobId) {
|
||||
@@ -122,7 +122,7 @@ function handleCardClick(job, e) {
|
||||
const recordData = recommedIndexDb.JobParameter(job);
|
||||
recommedIndexDb.addRecord(recordData);
|
||||
}
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}`);
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
|
||||
}
|
||||
|
||||
// 新增:提供选中状态和切换方法给父组件
|
||||
|
||||
@@ -88,5 +88,12 @@ export default {
|
||||
title: '找工作,用 AI 更高效|青岛市智能求职平台',
|
||||
desc: '融合海量岗位、智能简历匹配、竞争力分析,助你精准锁定理想职位!',
|
||||
imgUrl: 'https://qd.zhaopinzao8dian.com/file/csn/qd_shareLogo.jpg',
|
||||
}
|
||||
},
|
||||
// SM4 加密配置
|
||||
sm4Config: {
|
||||
key: '86C63180C1306ABC4D8F989E0A0BC9F3',
|
||||
mode: 'ECB',
|
||||
iv: 'UISwD9fW6cFh9SNS',
|
||||
cipherType: 'base64',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -580,6 +580,15 @@ function extractSpeechText(markdown) {
|
||||
console.log('📝 Input markdown length:', markdown ? markdown.length : 0);
|
||||
console.log('📝 Input markdown preview:', markdown ? markdown.substring(0, 200) + '...' : 'No markdown');
|
||||
|
||||
// 过滤AI推理内容(如DeepSeek的<think>标签)
|
||||
// 这些是AI的内部推理过程,不应朗读给用户
|
||||
let cleanedMarkdown = markdown.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
|
||||
console.log('🧹 After removing think tags, length:', cleanedMarkdown.length);
|
||||
if (cleanedMarkdown.length === 0 && markdown.length > 0) {
|
||||
console.warn('⚠️ 所有内容都是think标签,将使用原始文本');
|
||||
cleanedMarkdown = markdown;
|
||||
}
|
||||
|
||||
const jobRegex = /``` job-json\s*({[\s\S]*?})\s*```/g;
|
||||
const jobs = [];
|
||||
let match;
|
||||
@@ -587,7 +596,7 @@ function extractSpeechText(markdown) {
|
||||
let firstJobStartIndex = -1;
|
||||
|
||||
// 提取岗位 json 数据及前后位置
|
||||
while ((match = jobRegex.exec(markdown)) !== null) {
|
||||
while ((match = jobRegex.exec(cleanedMarkdown)) !== null) {
|
||||
const jobStr = match[1];
|
||||
try {
|
||||
const job = JSON.parse(jobStr);
|
||||
@@ -608,12 +617,12 @@ function extractSpeechText(markdown) {
|
||||
|
||||
// 提取引导语(第一个 job-json 之前的文字)
|
||||
const guideText = firstJobStartIndex > 0 ?
|
||||
markdown.slice(0, firstJobStartIndex).trim() :
|
||||
cleanedMarkdown.slice(0, firstJobStartIndex).trim() :
|
||||
'';
|
||||
|
||||
// 提取结束语(最后一个 job-json 之后的文字)
|
||||
const endingText = lastJobEndIndex < markdown.length ?
|
||||
markdown.slice(lastJobEndIndex).trim() :
|
||||
const endingText = lastJobEndIndex < cleanedMarkdown.length ?
|
||||
cleanedMarkdown.slice(lastJobEndIndex).trim() :
|
||||
'';
|
||||
|
||||
console.log('📝 Guide text:', guideText);
|
||||
|
||||
@@ -41,8 +41,8 @@ onReachBottom(() => {
|
||||
getJobList();
|
||||
});
|
||||
|
||||
function navToPost(jobId) {
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(jobId)}`);
|
||||
function navToPost(job) {
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
|
||||
}
|
||||
|
||||
function getJobList(type = 'add') {
|
||||
|
||||
@@ -83,8 +83,8 @@ function toSelectDate() {
|
||||
});
|
||||
}
|
||||
|
||||
function navToPost(jobId) {
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(jobId)}`);
|
||||
function navToPost(job) {
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
|
||||
}
|
||||
|
||||
function searchCollection(e) {
|
||||
|
||||
@@ -47,8 +47,8 @@ onReachBottom(() => {
|
||||
getJobList();
|
||||
});
|
||||
|
||||
function navToPost(jobId) {
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(jobId)}`);
|
||||
function navToPost(job) {
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
|
||||
}
|
||||
|
||||
function getJobList(type = 'add') {
|
||||
|
||||
@@ -673,14 +673,15 @@ const scrollToBottom = throttle(function () {
|
||||
}, 500);
|
||||
|
||||
function getGuess() {
|
||||
// $api.chatRequest('/guest', { sessionId: chatSessionID.value }, 'POST').then((res) => {
|
||||
$api.chatRequest('/guest', undefined, 'POST').then((res) => {
|
||||
$api.chatRequest('/guest', { sessionId: chatSessionID.value }, 'POST').then((res) => {
|
||||
console.log('getGuess ---- res:', res);
|
||||
guessList.value = res.data;
|
||||
showGuess.value = true;
|
||||
nextTick(() => {
|
||||
scrollToBottom();
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.warn('getGuess 请求失败:', err);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -271,6 +271,7 @@ const jobInfo = ref({});
|
||||
const state = reactive({});
|
||||
const mapCovers = ref([]);
|
||||
const jobIdRef = ref();
|
||||
const jobId = ref();
|
||||
// 竞争力分析数据,初始化为包含默认值的完整结构,确保雷达图能正常渲染
|
||||
const raderData = ref({
|
||||
matchScore: 0,
|
||||
@@ -313,6 +314,9 @@ onShow(() => {
|
||||
});
|
||||
function initLoad(option) {
|
||||
const encryptJobId = decodeURIComponent(option.encryptJobId);
|
||||
if (option.jobId) {
|
||||
jobId.value = decodeURIComponent(option.jobId);
|
||||
}
|
||||
if (encryptJobId !== jobIdRef.value) {
|
||||
jobIdRef.value = encryptJobId;
|
||||
getDetail(encryptJobId);
|
||||
@@ -458,7 +462,8 @@ function confirmAction() {
|
||||
const encryptJobId = jobIdRef.value;
|
||||
if (jobInfo.value.isApply === 1) {
|
||||
// 取消投递
|
||||
$api.createRequest(`/app/job/applyJobCencal`, { encryptJobId }, 'DELETE').then((resData) => {
|
||||
const cancelJobId = jobId.value || jobInfo.value.jobId;
|
||||
$api.createRequest(`/app/job/applyJobCencal`, { jobId: cancelJobId }, 'DELETE').then((resData) => {
|
||||
$api.msg('取消投递成功');
|
||||
getDetail(encryptJobId); // 刷新职位信息
|
||||
showConfirmDialog.value = false;
|
||||
@@ -486,8 +491,8 @@ function confirmApply() {
|
||||
|
||||
// 取消投递
|
||||
function cancelApply() {
|
||||
const encryptJobId = jobIdRef.value;
|
||||
$api.createRequest(`/app/job/applyJobCencal`, { encryptJobId }, 'DELETE').then((resData) => {
|
||||
const cancelJobId = jobId.value || jobInfo.value.jobId;
|
||||
$api.createRequest(`/app/job/applyJobCencal`, { jobId: cancelJobId }, 'DELETE').then((resData) => {
|
||||
$api.msg('取消投递成功');
|
||||
showConfirmDialog.value = false;
|
||||
});
|
||||
|
||||
@@ -80,20 +80,20 @@
|
||||
name: ""
|
||||
}
|
||||
}
|
||||
$api.myRequest('/auth/login2/ks',form,'post',10100).then((res) => {
|
||||
if (res.code=='200') {
|
||||
uni.setStorageSync('Padmin-Token', res.data.access_token)
|
||||
uni.navigateBack({
|
||||
delta:2
|
||||
})
|
||||
}
|
||||
}).catch(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: '登录失败,请重试'
|
||||
})
|
||||
})
|
||||
// $api.myRequest('/auth/login2/ks',form,'post',10100).then((res) => {
|
||||
// if (res.code=='200') {
|
||||
// uni.setStorageSync('Padmin-Token', res.data.access_token)
|
||||
// uni.navigateBack({
|
||||
// delta:2
|
||||
// })
|
||||
// }
|
||||
// }).catch(() => {
|
||||
// uni.hideLoading()
|
||||
// uni.showToast({
|
||||
// icon: 'none',
|
||||
// title: '登录失败,请重试'
|
||||
// })
|
||||
// })
|
||||
})
|
||||
|
||||
function register() {
|
||||
|
||||
@@ -1,18 +1,64 @@
|
||||
<template>
|
||||
<AppLayout title="" :use-scroll-view="false">
|
||||
<view class="wrap">
|
||||
<view class="login_index">
|
||||
<input class="input" placeholder="请输入账号" placeholder-class="inputplace" v-model="form.username" />
|
||||
<view class="login_yzm">
|
||||
<input class="input" type="password" placeholder="请输入密码" placeholder-class="inputplace"
|
||||
v-model="form.password" />
|
||||
<view class="login-container">
|
||||
<!-- 顶部装饰 -->
|
||||
<view class="header-decoration">
|
||||
<view class="decoration-circle circle-1"></view>
|
||||
<view class="decoration-circle circle-2"></view>
|
||||
</view>
|
||||
|
||||
<!-- Logo区域 -->
|
||||
<view class="logo-section">
|
||||
<view class="logo-wrapper">
|
||||
<text class="logo-icon">✦</text>
|
||||
</view>
|
||||
<view class="login_yzm">
|
||||
<input class="input" placeholder="请输入验证码" placeholder-class="inputplace" v-model="form.code" />
|
||||
<image class="yzm" :src="codeUrl" @click="getCodeImg"></image>
|
||||
<text class="logo-title">欢迎回来</text>
|
||||
<text class="logo-subtitle">请登录您的账号</text>
|
||||
</view>
|
||||
|
||||
<!-- 登录表单 -->
|
||||
<view class="form-section">
|
||||
<view class="form-item">
|
||||
<view class="form-label">账号</view>
|
||||
<view class="input-wrapper">
|
||||
<text class="input-icon">👤</text>
|
||||
<input class="form-input" placeholder="请输入账号" placeholder-class="inputplace" v-model="form.username" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<button class="com-btn" @click="register">登 录</button>
|
||||
<view class="form-item">
|
||||
<view class="form-label">密码</view>
|
||||
<view class="input-wrapper">
|
||||
<text class="input-icon">🔒</text>
|
||||
<input class="form-input" type="password" placeholder="请输入密码" placeholder-class="inputplace" v-model="form.password" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">验证码</view>
|
||||
<view class="input-wrapper verify-wrapper">
|
||||
<text class="input-icon">✧</text>
|
||||
<input class="form-input verify-input" placeholder="请输入验证码" placeholder-class="inputplace" v-model="form.code" />
|
||||
<image class="verify-code" :src="codeUrl" @click="getCodeImg"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 登录按钮 -->
|
||||
<view class="button-section">
|
||||
<button class="login-btn" @click="register">
|
||||
<text class="btn-text">登 录</text>
|
||||
<text class="btn-arrow">→</text>
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 底部装饰 -->
|
||||
<view class="footer-decoration">
|
||||
<view class="decoration-dots">
|
||||
<view class="dot"></view>
|
||||
<view class="dot dot-active"></view>
|
||||
<view class="dot"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</AppLayout>
|
||||
@@ -49,15 +95,12 @@
|
||||
code: '',
|
||||
uuid: ''
|
||||
})
|
||||
const jumpUrl=ref('')
|
||||
|
||||
onLoad((option) => {
|
||||
console.log("111",option)
|
||||
console.log("111")
|
||||
if(option.flag){
|
||||
flag.value=option.flag
|
||||
}
|
||||
if(option.jump){
|
||||
jumpUrl.value=option.jump
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
@@ -142,13 +185,11 @@
|
||||
})
|
||||
}else if(flag.value=='nw'){
|
||||
$api.myRequest('/auth/login',form,'post',9100).then((res) => {
|
||||
uni.setStorageSync('Padmin-Token', res.data.access_token)
|
||||
// 临时修改,现在有多个跳转页面
|
||||
// uni.reLaunch({
|
||||
// url: '/packageB/priority/helpFilter'
|
||||
// })
|
||||
uni.setStorageSync('inspur-admin-Token', res.data.access_token)
|
||||
uni.setStorageSync('fourLevelLinkage-token', res.data.access_token)
|
||||
|
||||
uni.reLaunch({
|
||||
url:jumpUrl.value
|
||||
url: '/packageB/priority/helpFilter'
|
||||
})
|
||||
codeUrl.value = 'data:image/gif;base64,' + res.img
|
||||
}).catch(() => {
|
||||
@@ -179,130 +220,220 @@
|
||||
</script>
|
||||
|
||||
<style scoped lang="stylus">
|
||||
.wrap {
|
||||
background-color: #ffffff;
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
/* 主题色变量 */
|
||||
$primary-color = #46ca98
|
||||
$primary-light = #e8f8f0
|
||||
$primary-dark = #3ab882
|
||||
$text-primary = #1a1a1a
|
||||
$text-secondary = #666666
|
||||
$text-placeholder = #b5b5b5
|
||||
$bg-light = #f8faf9
|
||||
$border-color = #e8e8e8
|
||||
|
||||
.lg-head {
|
||||
height: 480rpx;
|
||||
background: #46ca98;
|
||||
position: relative;
|
||||
.login-container
|
||||
background: linear-gradient(180deg, #f8faf9 0%, #ffffff 100%)
|
||||
min-height: 100vh
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: center
|
||||
position: relative
|
||||
overflow: hidden
|
||||
|
||||
.view_logo {
|
||||
text-align: center;
|
||||
/* 顶部装饰 */
|
||||
.header-decoration
|
||||
position: absolute
|
||||
top: 0
|
||||
left: 0
|
||||
right: 0
|
||||
height: 400rpx
|
||||
pointer-events: none
|
||||
|
||||
.login_logo {
|
||||
width: 300rpx;
|
||||
height: 300rpx;
|
||||
margin-top: 100rpx;
|
||||
}
|
||||
}
|
||||
.decoration-circle
|
||||
position: absolute
|
||||
border-radius: 50%
|
||||
background: linear-gradient(135deg, rgba(70, 202, 152, 0.1) 0%, rgba(70, 202, 152, 0.05) 100%)
|
||||
|
||||
.bg-cover {
|
||||
position: absolute;
|
||||
bottom: -4rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 30rpx;
|
||||
background-size: 100% 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.circle-1
|
||||
width: 300rpx
|
||||
height: 300rpx
|
||||
top: -100rpx
|
||||
right: -80rpx
|
||||
|
||||
.login_index {
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
width: 596rpx;
|
||||
margin: 0 auto;
|
||||
.circle-2
|
||||
width: 200rpx
|
||||
height: 200rpx
|
||||
top: 60rpx
|
||||
left: -60rpx
|
||||
background: linear-gradient(135deg, rgba(70, 202, 152, 0.08) 0%, rgba(70, 202, 152, 0.02) 100%)
|
||||
|
||||
::v-deep .is-input-border {
|
||||
border: 0;
|
||||
border-bottom: 1px solid #dcdfe6 !important;
|
||||
border-radius: 0;
|
||||
}
|
||||
/* Logo区域 */
|
||||
.logo-section
|
||||
margin-top: 160rpx
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: center
|
||||
animation: fadeInUp 0.6s ease-out
|
||||
|
||||
::v-deep .uni-input-input {
|
||||
font-size: 32rpx;
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
.logo-wrapper
|
||||
width: 140rpx
|
||||
height: 140rpx
|
||||
background: linear-gradient(145deg, $primary-color 0%, $primary-dark 100%)
|
||||
border-radius: 36rpx
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
box-shadow: 0 16rpx 40rpx rgba(70, 202, 152, 0.3)
|
||||
margin-bottom: 40rpx
|
||||
|
||||
::v-deep .uniui-contact-filled:before {
|
||||
color: #46ca98;
|
||||
font-size: 50rpx;
|
||||
}
|
||||
.logo-icon
|
||||
font-size: 60rpx
|
||||
color: #ffffff
|
||||
|
||||
::v-deep .uniui-locked-filled:before {
|
||||
color: #46ca98;
|
||||
font-size: 50rpx;
|
||||
}
|
||||
.logo-title
|
||||
font-size: 48rpx
|
||||
font-weight: 600
|
||||
color: $text-primary
|
||||
letter-spacing: 2rpx
|
||||
margin-bottom: 12rpx
|
||||
|
||||
.login_yzm {
|
||||
margin-top: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.logo-subtitle
|
||||
font-size: 28rpx
|
||||
color: $text-secondary
|
||||
letter-spacing: 1rpx
|
||||
|
||||
.yzm {
|
||||
width: 200rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
}
|
||||
/* 表单区域 */
|
||||
.form-section
|
||||
width: 600rpx
|
||||
margin-top: 80rpx
|
||||
animation: fadeInUp 0.6s ease-out 0.15s backwards
|
||||
|
||||
.com-btn {
|
||||
height: 100rpx;
|
||||
background: #46ca98;
|
||||
border-radius: 50rpx;
|
||||
color: #fff;
|
||||
margin-top: 100rpx;
|
||||
}
|
||||
.form-item
|
||||
margin-bottom: 40rpx
|
||||
|
||||
.login_wt {
|
||||
margin: 0 auto;
|
||||
text-align: right;
|
||||
font-size: 24rpx;
|
||||
color: rgba(134, 134, 136, 1);
|
||||
}
|
||||
}
|
||||
.form-label
|
||||
font-size: 26rpx
|
||||
color: $text-secondary
|
||||
margin-bottom: 16rpx
|
||||
padding-left: 8rpx
|
||||
letter-spacing: 1rpx
|
||||
|
||||
.lg-bottom {
|
||||
position: absolute;
|
||||
bottom: -3px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
.input-wrapper
|
||||
display: flex
|
||||
align-items: center
|
||||
background: #ffffff
|
||||
border-radius: 24rpx
|
||||
padding: 0 32rpx
|
||||
height: 100rpx
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04)
|
||||
border: 2rpx solid transparent
|
||||
transition: all 0.3s ease
|
||||
|
||||
.bottom-svg {
|
||||
position: absolute;
|
||||
bottom: -3px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
&:focus-within
|
||||
border-color: $primary-color
|
||||
box-shadow: 0 4rpx 24rpx rgba(70, 202, 152, 0.15)
|
||||
|
||||
.login_tongyi {
|
||||
.input-icon
|
||||
font-size: 36rpx
|
||||
margin-right: 20rpx
|
||||
opacity: 0.7
|
||||
|
||||
font-size: 26rpx;
|
||||
color: rgba(196, 196, 196, 1);
|
||||
width: 620rpx;
|
||||
margin: 32rpx auto;
|
||||
text-align: center;
|
||||
.form-input
|
||||
flex: 1
|
||||
height: 100%
|
||||
font-size: 30rpx
|
||||
color: $text-primary
|
||||
|
||||
text {
|
||||
color: rgba(86, 176, 236, 1);
|
||||
}
|
||||
}
|
||||
.verify-wrapper
|
||||
padding-right: 16rpx
|
||||
|
||||
.input {
|
||||
padding: 0 30rpx 0 80rpx;
|
||||
height: 80rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 75rpx 75rpx 75rpx 75rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.verify-input
|
||||
flex: 1
|
||||
|
||||
.inputplace {
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #B5B5B5;
|
||||
}
|
||||
.verify-code
|
||||
width: 180rpx
|
||||
height: 72rpx
|
||||
border-radius: 16rpx
|
||||
margin-left: 16rpx
|
||||
cursor: pointer
|
||||
transition: transform 0.2s ease
|
||||
|
||||
&:active
|
||||
transform: scale(0.95)
|
||||
|
||||
/* 输入框占位符 */
|
||||
.inputplace
|
||||
font-weight: 400
|
||||
font-size: 28rpx
|
||||
color: $text-placeholder
|
||||
|
||||
/* 按钮区域 */
|
||||
.button-section
|
||||
width: 600rpx
|
||||
margin-top: 60rpx
|
||||
animation: fadeInUp 0.6s ease-out 0.3s backwards
|
||||
|
||||
.login-btn
|
||||
width: 100%
|
||||
height: 108rpx
|
||||
background: linear-gradient(135deg, $primary-color 0%, $primary-dark 100%)
|
||||
border-radius: 54rpx
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
box-shadow: 0 12rpx 32rpx rgba(70, 202, 152, 0.35)
|
||||
transition: all 0.3s ease
|
||||
border: none
|
||||
|
||||
&:active
|
||||
transform: translateY(2rpx)
|
||||
box-shadow: 0 8rpx 24rpx rgba(70, 202, 152, 0.3)
|
||||
|
||||
.btn-text
|
||||
font-size: 34rpx
|
||||
font-weight: 500
|
||||
color: #ffffff
|
||||
letter-spacing: 8rpx
|
||||
|
||||
.btn-arrow
|
||||
font-size: 32rpx
|
||||
color: #ffffff
|
||||
margin-left: 16rpx
|
||||
transition: transform 0.3s ease
|
||||
|
||||
.login-btn:active .btn-arrow
|
||||
transform: translateX(8rpx)
|
||||
|
||||
/* 底部装饰 */
|
||||
.footer-decoration
|
||||
position: absolute
|
||||
bottom: 60rpx
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: center
|
||||
animation: fadeInUp 0.6s ease-out 0.45s backwards
|
||||
|
||||
.decoration-dots
|
||||
display: flex
|
||||
align-items: center
|
||||
gap: 16rpx
|
||||
|
||||
.dot
|
||||
width: 12rpx
|
||||
height: 12rpx
|
||||
border-radius: 50%
|
||||
background: rgba(70, 202, 152, 0.3)
|
||||
|
||||
.dot-active
|
||||
width: 36rpx
|
||||
border-radius: 6rpx
|
||||
background: $primary-color
|
||||
|
||||
/* 动画 */
|
||||
@keyframes fadeInUp
|
||||
from
|
||||
opacity: 0
|
||||
transform: translateY(30rpx)
|
||||
to
|
||||
opacity: 1
|
||||
transform: translateY(0)
|
||||
</style>
|
||||
@@ -158,7 +158,7 @@
|
||||
<view class="form-btns">
|
||||
<button class="mini-btn form-box-btn detail-btn" size="mini" v-if="false">详情</button>
|
||||
<button class="mini-btn form-box-btn follow-btn" size="mini" @click="goFollow(item)">跟进</button>
|
||||
<button class="mini-btn form-box-btn recommend-btn" size="mini" @click="goRecommend(item)">智能推荐</button>
|
||||
<!-- <button class="mini-btn form-box-btn recommend-btn" size="mini" @click="goRecommend(item)">智能推荐</button> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -267,7 +267,7 @@ function getTaskTypeLabelByValue(value) {
|
||||
// 加载某一级的数据(parentId 为空表示根)
|
||||
async function loadLevelData(parentId,node) {
|
||||
let header = {
|
||||
'Authorization': uni.getStorageSync('fourLevelLinkage-token'),
|
||||
'Authorization': 'Bearer ' + uni.getStorageSync('fourLevelLinkage-token'),
|
||||
'Content-Type': "application/x-www-form-urlencoded"
|
||||
};
|
||||
let params = { parentId };
|
||||
@@ -384,7 +384,7 @@ function getDataList(type = 'add') {
|
||||
}
|
||||
}
|
||||
function goFollow(item) {
|
||||
navTo(`/packageB/priority/helpFollow?task_id=${item.task_id}&person_id=${item.person_id}&&name=${item.name}&&taskType=${getTaskTypeLabelByValue(item.task_type)}`);
|
||||
navTo(`/packageB/priority/helpFollow?task_id=${item.task_id}&person_id=${item.person_id}&goal_person_id=${item.goal_person_id}&name=${item.name}&&taskType=${getTaskTypeLabelByValue(item.task_type)}`);
|
||||
}
|
||||
//智能推荐
|
||||
const goRecommend = (item) => {
|
||||
|
||||
@@ -162,7 +162,7 @@ const onDateChange = ( e) => {
|
||||
}
|
||||
function getFollowList(){
|
||||
let header={
|
||||
'Authorization':uni.getStorageSync('fourLevelLinkage-token'),
|
||||
'Authorization':'Bearer ' + uni.getStorageSync('fourLevelLinkage-token'),
|
||||
'Content-Type': "application/x-www-form-urlencoded"
|
||||
}
|
||||
let params={
|
||||
@@ -211,13 +211,14 @@ const handleSubmit = () => {
|
||||
formRef.value?.validate()
|
||||
.then(() => {
|
||||
let header={
|
||||
'Authorization':uni.getStorageSync('fourLevelLinkage-token')
|
||||
'Authorization':'Bearer ' + uni.getStorageSync('fourLevelLinkage-token')
|
||||
}
|
||||
formData.goalPersonId=personInfo.value.goalPersonId
|
||||
$api.myRequest('/dispatch/assist/records/addRecords', formData,'post',9100,header).then((resData) => {
|
||||
console.log("resData",resData)
|
||||
if(resData && resData.code == 200){
|
||||
handleReset()
|
||||
getFollowList()
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success',
|
||||
@@ -247,6 +248,8 @@ const handleReset = () => {
|
||||
formData.nextContactDate = '';
|
||||
}
|
||||
onLoad((options) => {
|
||||
console.log(options)
|
||||
personInfo.value.goalPersonId=options.goal_person_id
|
||||
personInfo.value.person_id=options.person_id
|
||||
personInfo.value.name=options.name
|
||||
personInfo.value.taskType=options.taskType
|
||||
|
||||
@@ -10,6 +10,12 @@ api.queryAIUrl = (idCard,name) => request.globalRequest(`/Home/QueryAIUrl?userId
|
||||
// 获取个人档案
|
||||
api.queryStudentProfile = () => request.globalRequest(`/StudentResource/QueryStudentProfile`,'GET', {})
|
||||
|
||||
// 保存操作日志
|
||||
api.saveUserOperationLog = (data) => request.globalRequest(`/UserOperationLog/SaveUserOperationLog`,'POST', data)
|
||||
|
||||
// 获取操作日志
|
||||
api.getUserOperationLogList = (data) => request.globalRequest(`/UserOperationLog/GetUserOperationLogList`,'POST', data)
|
||||
|
||||
|
||||
export default api
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
|
||||
<script>
|
||||
import api from "@/packageCa/apiCa/testManage.js"
|
||||
import apiuser from "@/packageCa/apiCa/user.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -179,6 +180,27 @@
|
||||
}, 300)
|
||||
}
|
||||
},
|
||||
// 添加日志
|
||||
postLog(operationType, remarks, beforeData = "", afterData = ""){
|
||||
try {
|
||||
const data = {
|
||||
OperationType: operationType,
|
||||
Remarks: remarks,
|
||||
BeforeOperationJson: beforeData,
|
||||
AfterOperationJson: afterData
|
||||
};
|
||||
console.log(data);
|
||||
// return;
|
||||
// 异步记录日志,不阻塞主流程
|
||||
apiuser.saveUserOperationLog(data).then((res) => {
|
||||
console.log('[Operation Log] 记录成功', res);
|
||||
}).catch((err) => {
|
||||
console.error('[Operation Log] 记录失败', err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[Operation Log] 记录异常', e);
|
||||
}
|
||||
},
|
||||
// 提交题目
|
||||
submitTitle() {
|
||||
let testStr = "";
|
||||
@@ -250,7 +272,11 @@
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
this.postLog(201,`【新增】保存${this.testTitle}`,"",JSON.stringify({
|
||||
TestType: this.testType,
|
||||
TestStr: testStr
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import api from "@/packageCa/apiCa/testManage.js"
|
||||
import apiuser from "@/packageCa/apiCa/user.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -249,6 +250,27 @@
|
||||
},400)
|
||||
|
||||
},
|
||||
// 添加日志
|
||||
postLog(operationType, remarks, beforeData = "", afterData = ""){
|
||||
try {
|
||||
const data = {
|
||||
OperationType: operationType,
|
||||
Remarks: remarks,
|
||||
BeforeOperationJson: beforeData,
|
||||
AfterOperationJson: afterData
|
||||
};
|
||||
console.log(data);
|
||||
// return;
|
||||
// 异步记录日志,不阻塞主流程
|
||||
apiuser.saveUserOperationLog(data).then((res) => {
|
||||
console.log('[Operation Log] 记录成功', res);
|
||||
}).catch((err) => {
|
||||
console.error('[Operation Log] 记录失败', err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[Operation Log] 记录异常', e);
|
||||
}
|
||||
},
|
||||
// 提交题目
|
||||
submitTitle() {
|
||||
let testStr = "";
|
||||
@@ -282,6 +304,10 @@
|
||||
})
|
||||
}
|
||||
})
|
||||
this.postLog(201,`【新增】保存职业兴趣测评`,"",JSON.stringify({
|
||||
TestType: 11,
|
||||
TestStr: testStr
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
<script>
|
||||
import api from "@/packageCa/apiCa/testManage.js"
|
||||
import apiuser from "@/packageCa/apiCa/user.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -142,6 +143,27 @@
|
||||
},400)
|
||||
}
|
||||
},
|
||||
// 添加日志
|
||||
postLog(operationType, remarks, beforeData = "", afterData = ""){
|
||||
try {
|
||||
const data = {
|
||||
OperationType: operationType,
|
||||
Remarks: remarks,
|
||||
BeforeOperationJson: beforeData,
|
||||
AfterOperationJson: afterData
|
||||
};
|
||||
console.log(data);
|
||||
// return;
|
||||
// 异步记录日志,不阻塞主流程
|
||||
apiuser.saveUserOperationLog(data).then((res) => {
|
||||
console.log('[Operation Log] 记录成功', res);
|
||||
}).catch((err) => {
|
||||
console.error('[Operation Log] 记录失败', err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[Operation Log] 记录异常', e);
|
||||
}
|
||||
},
|
||||
// 提交题目
|
||||
submitTitle() {
|
||||
let testStr = "";
|
||||
@@ -195,6 +217,10 @@
|
||||
})
|
||||
}
|
||||
})
|
||||
this.postLog(201,`【新增】保存人格测评`,"",JSON.stringify({
|
||||
TestType: 15,
|
||||
TestStr: testStr
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
<script>
|
||||
import api from "@/packageCa/apiCa/testManage.js"
|
||||
import apiuser from "@/packageCa/apiCa/user.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -145,6 +146,27 @@
|
||||
},300)
|
||||
}
|
||||
},
|
||||
// 添加日志
|
||||
postLog(operationType, remarks, beforeData = "", afterData = ""){
|
||||
try {
|
||||
const data = {
|
||||
OperationType: operationType,
|
||||
Remarks: remarks,
|
||||
BeforeOperationJson: beforeData,
|
||||
AfterOperationJson: afterData
|
||||
};
|
||||
console.log(data);
|
||||
// return;
|
||||
// 异步记录日志,不阻塞主流程
|
||||
apiuser.saveUserOperationLog(data).then((res) => {
|
||||
console.log('[Operation Log] 记录成功', res);
|
||||
}).catch((err) => {
|
||||
console.error('[Operation Log] 记录失败', err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[Operation Log] 记录异常', e);
|
||||
}
|
||||
},
|
||||
// 提交题目
|
||||
submitTitle() {
|
||||
let testStr = "";
|
||||
@@ -197,6 +219,10 @@
|
||||
})
|
||||
}
|
||||
})
|
||||
this.postLog(201,`【新增】保存工作测评`,"",JSON.stringify({
|
||||
TestType: 17,
|
||||
TestStr: testStr
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
<script>
|
||||
import api from "@/packageCa/apiCa/user.js"
|
||||
import apiuser from "@/packageCa/apiCa/user.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -103,7 +104,7 @@
|
||||
url: "/packageCa/userCenter/smartTarget"
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -116,10 +117,32 @@
|
||||
user: res.Data.userInfo
|
||||
};
|
||||
uni.setStorageSync('CAuserInfo',params);
|
||||
this.postLog(101,`【用户登入】【小程序】${res.Data.userInfo}登录成功`,"",JSON.stringify(params))
|
||||
}else {
|
||||
return null
|
||||
}
|
||||
},
|
||||
// 添加日志
|
||||
postLog(operationType, remarks, beforeData = "", afterData = ""){
|
||||
try {
|
||||
const data = {
|
||||
OperationType: operationType,
|
||||
Remarks: remarks,
|
||||
BeforeOperationJson: beforeData,
|
||||
AfterOperationJson: afterData
|
||||
};
|
||||
console.log(data);
|
||||
// return;
|
||||
// 异步记录日志,不阻塞主流程
|
||||
apiuser.saveUserOperationLog(data).then((res) => {
|
||||
console.log('[Operation Log] 记录成功', res);
|
||||
}).catch((err) => {
|
||||
console.error('[Operation Log] 记录失败', err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[Operation Log] 记录异常', e);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -482,6 +505,7 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 55rpx;
|
||||
margin-bottom: 30rpx;
|
||||
&:nth-child(4){
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
|
||||
<script>
|
||||
import api from "@/packageCa/apiCa/studentProfile.js"
|
||||
import apiuser from "@/packageCa/apiCa/user.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -127,6 +128,27 @@
|
||||
url: `/packageCa/pagesTest/testList`
|
||||
})
|
||||
},
|
||||
// 添加日志
|
||||
postLog(operationType, remarks, beforeData = "", afterData = ""){
|
||||
try {
|
||||
const data = {
|
||||
OperationType: operationType,
|
||||
Remarks: remarks,
|
||||
BeforeOperationJson: beforeData,
|
||||
AfterOperationJson: afterData
|
||||
};
|
||||
console.log(data);
|
||||
// return;
|
||||
// 异步记录日志,不阻塞主流程
|
||||
apiuser.saveUserOperationLog(data).then((res) => {
|
||||
console.log('[Operation Log] 记录成功', res);
|
||||
}).catch((err) => {
|
||||
console.error('[Operation Log] 记录失败', err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[Operation Log] 记录异常', e);
|
||||
}
|
||||
},
|
||||
//选中职业添加
|
||||
async checkedJob(ITEM){
|
||||
uni.showLoading({
|
||||
@@ -141,6 +163,7 @@
|
||||
icon: "none"
|
||||
})
|
||||
this.getGXCareerPlanList();
|
||||
this.postLog(304,`【新增】新增了${ITEM.Name}意向职业`,"",JSON.stringify(ITEM))
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.Message,
|
||||
|
||||
@@ -121,6 +121,7 @@
|
||||
|
||||
<script>
|
||||
import api from "@/packageCa/apiCa/studentProfile.js"
|
||||
import apiuser from "@/packageCa/apiCa/user.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -145,6 +146,27 @@
|
||||
this.queryPlanList();
|
||||
},
|
||||
methods: {
|
||||
// 添加日志
|
||||
postLog(operationType, remarks, beforeData = "", afterData = ""){
|
||||
try {
|
||||
const data = {
|
||||
OperationType: operationType,
|
||||
Remarks: remarks,
|
||||
BeforeOperationJson: beforeData,
|
||||
AfterOperationJson: afterData
|
||||
};
|
||||
console.log(data);
|
||||
// return;
|
||||
// 异步记录日志,不阻塞主流程
|
||||
apiuser.saveUserOperationLog(data).then((res) => {
|
||||
console.log('[Operation Log] 记录成功', res);
|
||||
}).catch((err) => {
|
||||
console.error('[Operation Log] 记录失败', err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[Operation Log] 记录异常', e);
|
||||
}
|
||||
},
|
||||
// 切换目标标签
|
||||
changeTarget(ITEM){
|
||||
if(ITEM.EncodeId == this.checkedTargetCode){
|
||||
@@ -221,6 +243,7 @@
|
||||
})
|
||||
this.queryPlanList();
|
||||
this.delIds=[];
|
||||
this.postLog(302,`【新增】新增了学习计划`,"",JSON.stringify(data))
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.Message,
|
||||
|
||||
@@ -127,6 +127,7 @@
|
||||
|
||||
<script>
|
||||
import api from "@/packageCa/apiCa/studentProfile.js"
|
||||
import apiuser from "@/packageCa/apiCa/user.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -192,6 +193,7 @@
|
||||
this.jobSkill = JSON.parse(data.JobSkill).slice(0,5);
|
||||
this.professionalRequire = JSON.parse(data.ProfessionalRequire).slice(0,5);
|
||||
this.isLoadingEnd = true;
|
||||
this.postLog(303,`【新增】查看了${data.Name}的职业发展路径`,"",JSON.stringify(res.Data))
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.Message,
|
||||
@@ -199,6 +201,27 @@
|
||||
})
|
||||
}
|
||||
},
|
||||
// 添加日志
|
||||
postLog(operationType, remarks, beforeData = "", afterData = ""){
|
||||
try {
|
||||
const data = {
|
||||
OperationType: operationType,
|
||||
Remarks: remarks,
|
||||
BeforeOperationJson: beforeData,
|
||||
AfterOperationJson: afterData
|
||||
};
|
||||
console.log(data);
|
||||
// return;
|
||||
// 异步记录日志,不阻塞主流程
|
||||
apiuser.saveUserOperationLog(data).then((res) => {
|
||||
console.log('[Operation Log] 记录成功', res);
|
||||
}).catch((err) => {
|
||||
console.error('[Operation Log] 记录失败', err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[Operation Log] 记录异常', e);
|
||||
}
|
||||
},
|
||||
// 去测评
|
||||
navTest(){
|
||||
uni.navigateTo({
|
||||
|
||||
@@ -175,6 +175,7 @@
|
||||
|
||||
<script>
|
||||
import api from "@/packageCa/apiCa/studentProfile.js"
|
||||
import apiuser from "@/packageCa/apiCa/user.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -199,6 +200,27 @@
|
||||
this.querySmartTargets();
|
||||
},
|
||||
methods: {
|
||||
// 添加日志
|
||||
postLog(operationType, remarks, beforeData = "", afterData = ""){
|
||||
try {
|
||||
const data = {
|
||||
OperationType: operationType,
|
||||
Remarks: remarks,
|
||||
BeforeOperationJson: beforeData,
|
||||
AfterOperationJson: afterData
|
||||
};
|
||||
console.log(data);
|
||||
// return;
|
||||
// 异步记录日志,不阻塞主流程
|
||||
apiuser.saveUserOperationLog(data).then((res) => {
|
||||
console.log('[Operation Log] 记录成功', res);
|
||||
}).catch((err) => {
|
||||
console.error('[Operation Log] 记录失败', err);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[Operation Log] 记录异常', e);
|
||||
}
|
||||
},
|
||||
goPlan(){
|
||||
if(this.targetList.length==0){
|
||||
uni.showToast({
|
||||
@@ -248,6 +270,7 @@
|
||||
icon: "success"
|
||||
})
|
||||
this.querySmartTargets();
|
||||
this.postLog(301,`【新增】保存SMART目标`,"",JSON.stringify(this.targetForm))
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.Message,
|
||||
@@ -300,6 +323,7 @@
|
||||
Timeliness: "",
|
||||
};
|
||||
this.querySmartTargets();
|
||||
this.postLog(301,`【删除】删除SMART目标`,"",JSON.stringify(this.targetForm))
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.Message,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// const baseUrl = "https://localhost:7026/career";
|
||||
// const baseUrl = "https://ksrs.51xuanxiao.com/career";
|
||||
const baseUrl = "https://www.xjksly.cn/career";
|
||||
const request = {}
|
||||
const headers = {}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
-->
|
||||
<template>
|
||||
<!-- @scroll="handleScroll" @scrolltolower="scrollBottom" -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<scroll-view :scroll-y="true" class="container" :class="{'h5-pc-container': isH5}" :show-scrollbar="false" style="background-image: url(../../../packageRc/static/pageBgIndex.png);">
|
||||
<view style="padding: 40rpx 28rpx;">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
@@ -97,6 +98,10 @@
|
||||
</template>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<IndexYtj />
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -226,6 +231,7 @@ function changeJobType(val){
|
||||
}
|
||||
// 登录检查函数
|
||||
import { storeToRefs } from 'pinia';
|
||||
import IndexYtj from './indexYtj.vue';
|
||||
const { userInfo, hasLogin, token } = storeToRefs(useUserStore());
|
||||
const checkLogin = () => {
|
||||
const tokenValue = uni.getStorageSync('token') || '';
|
||||
@@ -240,7 +246,7 @@ const checkLogin = () => {
|
||||
function nextDetail(job) {
|
||||
// 登录检查
|
||||
if (checkLogin()) {
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}`);
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${job.encryptJobId}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
815
packageRc/pages/index/indexYtj.vue
Normal file
815
packageRc/pages/index/indexYtj.vue
Normal file
@@ -0,0 +1,815 @@
|
||||
<!--
|
||||
* @Date: 2025-10-16 15:15:47
|
||||
* @LastEditors: shirlwang
|
||||
* @LastEditTime: 2026-01-27 09:30:18
|
||||
-->
|
||||
<template>
|
||||
<!-- @scroll="handleScroll" @scrolltolower="scrollBottom" -->
|
||||
<scroll-view :scroll-y="true" class="container" :class="{'h5-pc-container': isH5}" :show-scrollbar="false">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="custom-nav" :style="{paddingTop: statusBarHeight + 'px'}">
|
||||
<view class="nav-content">
|
||||
<view class="nav-back" @click="back"><text class="iconfont"><</text></view>
|
||||
<view class="nav-title">高校毕业生智慧就业</view>
|
||||
<view class="nav-placeholder"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="main-content">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="kinggang">
|
||||
<view @click="navTo('/packageA/pages/myResume/myResume')">
|
||||
<image src="../../../packageRc/static/kinggang1.png"/>
|
||||
<view>信息维护</view>
|
||||
</view>
|
||||
<view @click="navTo('/packageA/pages/Intendedposition/Intendedposition')">
|
||||
<image src="../../../packageRc/static/kinggang5.png"/>
|
||||
<view>投递记录</view>
|
||||
</view>
|
||||
<view @click="tiao()">
|
||||
<image src="../../../packageRc/static/kinggang2.png"/>
|
||||
<view>需求上报</view>
|
||||
</view>
|
||||
<view>
|
||||
<image @click="goAiAu" src="../../../packageRc/static/kinggang3.png"/>
|
||||
<view>虚拟面试</view>
|
||||
</view>
|
||||
<view @click="goCa">
|
||||
<image src="../../../packageRc/static/kinggang4.png"/>
|
||||
<view>素质测评</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- 岗位类型切换 -->
|
||||
<view class="tabs">
|
||||
<view class="tab" :class="{active: pageState.type == ''}" @click="changeJobType('')">岗位列表</view>
|
||||
<view class="tab" :class="{active: pageState.type == 2}" @click="changeJobType(2)">实习实训</view>
|
||||
<view class="tab" :class="{active: pageState.type == 3}" @click="changeJobType(3)">社区实践</view>
|
||||
</view>
|
||||
|
||||
<!-- 子选项卡 -->
|
||||
<view class="titles">
|
||||
<view class="title-item" :class="{active: activeTitle == 1}" @click="activeTitle = 1,getJobRecommed()">
|
||||
<view>推荐<text class="accent">岗位</text></view>
|
||||
</view>
|
||||
<view class="title-item" :class="{active: activeTitle == 2}" @click="activeTitle = 2,getJobList()">
|
||||
<view>热门<text class="accent">岗位</text></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 岗位列表(改为网格布局) -->
|
||||
<view class="job-grid">
|
||||
<view v-for="(item, index) in jobList" :key="index" @click="nextDetail(item)" class="job-card-box">
|
||||
<view class="job-top">
|
||||
<view class="job-name">{{ item.jobTitle }}</view>
|
||||
<view class="job-salary">{{item.minSalary}}-{{item.maxSalary}}/月</view>
|
||||
</view>
|
||||
<view class="job-tags">
|
||||
<view v-if="item.jobLocationAreaCode" class="tag"><dict-Label dictType="jobLocationAreaCode" :value="item.jobLocationAreaCode"></dict-Label></view>
|
||||
<view class="tag"><dict-Label dictType="education" :value="item.education"></dict-Label></view>
|
||||
<view class="tag"><dict-Label dictType="experience" :value="item.experience"></dict-Label></view>
|
||||
</view>
|
||||
<view class="job-desc">
|
||||
{{ vacanciesTo(item.vacancies) }} | {{item.jobCategory}} | {{ item.jobCategory }}
|
||||
</view>
|
||||
<view class="company-link">
|
||||
<image class="comp-icon" src="../../../packageRc/static/dmsc/gs.png" />
|
||||
<view class="comp-name">{{ item.companyName }}</view>
|
||||
</view>
|
||||
<view class="delivery-btn" @click.stop="nextDetail(item)">简历投递</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="view-more-btn" @click="viewMore">查看更多内容</view>
|
||||
|
||||
<!-- 政策专区(改为常驻显示) -->
|
||||
<view class="titles section-title" style="justify-content: space-between; margin-top: 36rpx;">
|
||||
<view class="title-item active"><view>政策<text class="accent">专区</text></view></view>
|
||||
<view class="more-link" @click="toPolicyList">{{'查看更多 >'}}</view>
|
||||
</view>
|
||||
|
||||
<view v-for="(item, index) in policyList" :key="index" class="policy-list-card" @click="toPolicyDetail(item)">
|
||||
<view class="card-left">
|
||||
<image class="clock-icon" src="../../../packageRc/static/dmsc/sj.png" />
|
||||
<view class="date-md">{{ formatMD(item.publishTime || item.createTime) }}</view>
|
||||
<view class="date-year">{{ formatYear(item.publishTime || item.createTime) }}</view>
|
||||
</view>
|
||||
<view class="card-right">
|
||||
<view class="card-title">{{ item.zcmc }}</view>
|
||||
<view class="card-infos">
|
||||
<view v-if="item.zcLevel" class="info-tag">{{ item.zcLevel }}</view>
|
||||
<view v-if="item.sourceUnit" class="info-tag">{{ item.sourceUnit }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, inject, watch, ref, onMounted, watchEffect, nextTick } from 'vue';
|
||||
const { $api, navTo, vacanciesTo, formatTotal, config } = inject('globalFunction');
|
||||
|
||||
const isH5 = ref(false);
|
||||
const uniIconSize = ref(18);
|
||||
// #ifdef H5
|
||||
isH5.value = true;
|
||||
uniIconSize.value = 20;
|
||||
// #endif
|
||||
|
||||
// 状态栏高度(用于自定义导航栏)
|
||||
const statusBarHeight = ref(0);
|
||||
try {
|
||||
const sysInfo = uni.getSystemInfoSync();
|
||||
statusBarHeight.value = sysInfo.statusBarHeight || 0;
|
||||
} catch(e) {}
|
||||
|
||||
|
||||
import { getPolicyList } from '@/packageRc/apiRc/policy';
|
||||
let policyList = ref([])
|
||||
function getPolicy() {
|
||||
getPolicyList({pageNum: 1, pageSize: 4,zclx:'1'}).then(res => {
|
||||
if (res.code == 200) {
|
||||
policyList.value = res.rows
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
})
|
||||
}
|
||||
let tabType = ref(1)
|
||||
function changeType(type) {
|
||||
tabType.value = type
|
||||
}
|
||||
function toPolicyList() {
|
||||
navTo(`/packageRc/pages/policy/policyList?zclx=1`)
|
||||
}
|
||||
function toPolicyDetail(item) {
|
||||
navTo(`/packageRc/pages/policy/policyDetail?id=${item.id}`)
|
||||
}
|
||||
let activeTab = ref(1)
|
||||
let activeTitle = ref(1)
|
||||
|
||||
function back() {
|
||||
// uni.navigateBack({
|
||||
// delta: 1
|
||||
// })
|
||||
window.location.href='https://www.xjksly.cn/mechine-single-vue/'
|
||||
|
||||
// uni.reLaunch({
|
||||
// url: '/pages/index/index'
|
||||
// })
|
||||
}
|
||||
onMounted(()=>{
|
||||
getJobRecommed()
|
||||
getPolicy();
|
||||
})
|
||||
|
||||
|
||||
|
||||
function goCa(){
|
||||
if (checkLogin()) {
|
||||
const userInfo = uni.getStorageSync('userInfo')
|
||||
navTo(`/packageCa/search/search?userId=${userInfo.userId}&name=${userInfo.name}`);
|
||||
}
|
||||
}
|
||||
// 跳转AI智能面试
|
||||
function goAiAu(){
|
||||
if (checkLogin()) {
|
||||
const userInfo = uni.getStorageSync('userInfo')
|
||||
navTo(`/packageCa/search/AIAudition?userId=${userInfo.userId}&name=${userInfo.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
function viewMore() {
|
||||
navTo(`/packageRc/pages/jobList/jobList`);
|
||||
}
|
||||
function tiao(){
|
||||
console.log('尝试导航到待办详情页面');
|
||||
// 尝试直接使用uni.navigateTo,使用正确的格式
|
||||
uni.navigateTo({
|
||||
url: `/packageRc/pages/needs/personNeeds`,
|
||||
success: function() {
|
||||
console.log('导航成功');
|
||||
},
|
||||
fail: function(err) {
|
||||
console.error('导航失败:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
import useUserStore from '@/stores/useUserStore';
|
||||
const conditionSearch = ref({});
|
||||
const pageState = reactive({
|
||||
page: 0,
|
||||
total: 0,
|
||||
maxPage: 2,
|
||||
pageSize: 4,
|
||||
search: {
|
||||
order: 0,
|
||||
},
|
||||
type:'',
|
||||
});
|
||||
let jobList = ref([])
|
||||
// 获取推荐岗位
|
||||
function getJobRecommed(){
|
||||
let params = {
|
||||
pageSize: pageState.pageSize,
|
||||
sessionId: useUserStore().seesionId,
|
||||
...pageState.search,
|
||||
...conditionSearch.value,
|
||||
isPublish: 1,
|
||||
type:pageState.type
|
||||
};
|
||||
$api.createRequest('/app/job/recommend', params).then((resData) => {
|
||||
if (resData.code == 200 && resData.data.length) {
|
||||
jobList.value = resData.data
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}).catch(() => {
|
||||
// 造一些测试数据
|
||||
const mock = { jobTitle: '计算机网络运维员', companyName: '新疆天山人才智汇发展有限责任公司', minSalary: '面议', maxSalary: '面议' };
|
||||
jobList.value = [mock, mock, mock, mock];
|
||||
});
|
||||
}
|
||||
|
||||
// 获取岗位列表
|
||||
function getJobList(){
|
||||
let params = {
|
||||
current: pageState.page,
|
||||
pageSize: pageState.pageSize,
|
||||
...pageState.search,
|
||||
// ...conditionSearch.value,
|
||||
type:pageState.type
|
||||
};
|
||||
$api.createRequest('/app/job/list', params).then((resData) => {
|
||||
jobList.value = resData.rows
|
||||
pageState.total = 0;
|
||||
});
|
||||
}
|
||||
// 更改实习实训等
|
||||
function changeJobType(val){
|
||||
pageState.type = val
|
||||
if(activeTitle.value == 1){
|
||||
getJobRecommed()
|
||||
}else{
|
||||
getJobList()
|
||||
}
|
||||
}
|
||||
// 登录检查函数
|
||||
import { storeToRefs } from 'pinia';
|
||||
const { userInfo, hasLogin, token } = storeToRefs(useUserStore());
|
||||
const checkLogin = () => {
|
||||
const tokenValue = uni.getStorageSync('token') || '';
|
||||
if (!tokenValue || !hasLogin.value) {
|
||||
// 未登录,打开授权弹窗
|
||||
wxAuthLoginRef.value?.open();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// 跳转到详情页面
|
||||
function nextDetail(job) {
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${job.encryptJobId}`);
|
||||
// 登录检查
|
||||
// if (checkLogin()) {
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
function formatMD(dateStr) {
|
||||
if (!dateStr) return '--';
|
||||
const parts = dateStr.split('-').length > 1 ? dateStr.split('-') : dateStr.split(' ');
|
||||
// 处理 YYYY-MM-DD 或 YYYY-MM-DD HH:mm:ss
|
||||
let d = parts[0].includes('-') ? parts[0].split('-') : parts;
|
||||
if (d.length >= 3) {
|
||||
return `${d[1]}-${d[2].substring(0,2)}`;
|
||||
}
|
||||
return dateStr;
|
||||
}
|
||||
|
||||
function formatYear(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
const parts = dateStr.split('-');
|
||||
if (parts.length >= 1) {
|
||||
return parts[0].substring(0, 4);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
/* 隐藏滚动条 */
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
-webkit-appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
view{box-sizing: border-box;display: block;}
|
||||
.container{
|
||||
background-color: #FFFFFF;
|
||||
min-height: 1920px;
|
||||
min-width: 1080px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* 自定义导航栏 */
|
||||
.custom-nav {
|
||||
background: #107AFD;
|
||||
width: 100%;
|
||||
.nav-content {
|
||||
height: 120rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 24rpx;
|
||||
.nav-back {
|
||||
width: 72rpx;
|
||||
height: 120rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-weight: 300;
|
||||
.iconfont{
|
||||
|
||||
font-size: 40px!important;
|
||||
}
|
||||
}
|
||||
.nav-title {
|
||||
color: #fff;
|
||||
font-size: 43rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
.nav-placeholder {
|
||||
width: 72rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.main-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
/* 页面全局边距加倍 */
|
||||
padding: 38rpx 29rpx;
|
||||
}
|
||||
.kinggang{
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
padding: 14rpx 10rpx 29rpx 10rpx;
|
||||
font-size: 31rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 19rpx;
|
||||
>view{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
}
|
||||
image{
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
}
|
||||
.tabs{
|
||||
/* 调大上方选项卡的边距 */
|
||||
margin: 38rpx auto 38rpx;
|
||||
border-radius: 72rpx;
|
||||
display: flex;
|
||||
background: #F4F6F9;
|
||||
color: #878787;
|
||||
text-align: center;
|
||||
width: 80%;
|
||||
overflow: hidden;
|
||||
padding: 5rpx;
|
||||
box-sizing: border-box;
|
||||
.tab{
|
||||
flex: 1;
|
||||
line-height: 72rpx;
|
||||
position: relative;
|
||||
font-size: 43rpx;
|
||||
font-weight: 500;
|
||||
transition: all 0.25s;
|
||||
border-radius: 72rpx;
|
||||
&.active{
|
||||
color: #fff;
|
||||
background: #107AFD;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.titles{
|
||||
display: flex;
|
||||
/* 调大标题下边距 */
|
||||
margin-bottom: 43rpx;
|
||||
align-items: flex-end;
|
||||
.title-item{
|
||||
font-size: 72rpx;
|
||||
font-weight: bold;
|
||||
color: #282828;
|
||||
margin-right: 34rpx;
|
||||
position: relative;
|
||||
>view{
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 0 5rpx;
|
||||
.accent {
|
||||
color: #EC7737;
|
||||
margin-left: 2rpx;
|
||||
}
|
||||
}
|
||||
&.active::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: -5rpx;
|
||||
left: 10%;
|
||||
width: 80%;
|
||||
height: 12rpx;
|
||||
border-radius: 50px;
|
||||
background: linear-gradient(90deg, rgba(82, 149, 255, 0.4) 0%, rgba(24, 116, 255, 0) 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.job-list{
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
color: #333333;
|
||||
border-radius: 7rpx;
|
||||
background: #FFFFFF;
|
||||
padding: 19rpx;
|
||||
margin-bottom: 14rpx;
|
||||
position: relative;
|
||||
/* 去掉阴影,保持扁平统一 */
|
||||
.sign{
|
||||
position: absolute;
|
||||
font-size: 17rpx;
|
||||
right: 0;
|
||||
top: 0;
|
||||
padding: 5rpx 12rpx;
|
||||
border: 1rpx solid #EC4827;
|
||||
background: rgba(227, 79, 49, 0.09);
|
||||
border-top-right-radius: 14rpx;
|
||||
border-bottom-left-radius: 14rpx;
|
||||
color: #EC4827;
|
||||
}
|
||||
.top-line{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 14rpx;
|
||||
color: #A2A2A2;
|
||||
margin-bottom: 10rpx;
|
||||
.salary{
|
||||
font-size: 19rpx;
|
||||
color: #4C6EFB;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.title{
|
||||
font-size: 19rpx;
|
||||
font-weight: bold;
|
||||
color: #282828;
|
||||
margin-bottom: 10rpx;
|
||||
display: flex;
|
||||
image{
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-right: 7rpx;
|
||||
}
|
||||
}
|
||||
.infos{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
font-size: 14rpx;
|
||||
margin-bottom: 10rpx;
|
||||
line-height: 25rpx;
|
||||
view{
|
||||
padding: 0 10rpx;
|
||||
margin-right: 6rpx;
|
||||
background: #F2F2F2;
|
||||
}
|
||||
}
|
||||
.bottom-line{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 14rpx;
|
||||
color: #A2A2A2;
|
||||
margin-top: 7rpx;
|
||||
}
|
||||
}
|
||||
.view-more-btn{
|
||||
padding: 6rpx 34rpx;
|
||||
background: #FFFFFF;
|
||||
color: #4C6EFB;
|
||||
border: 1rpx solid #4C6EFB;
|
||||
text-align: center;
|
||||
border-radius: 24rpx;
|
||||
width: fit-content;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
.job-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
/* 列表前边距调大 */
|
||||
margin-top: 29rpx;
|
||||
|
||||
.job-card-box {
|
||||
/* 缩小宽度比例以增加瀑布流列间距 */
|
||||
width: calc(50% - 14rpx);
|
||||
background: #FFFFFF;
|
||||
background-image: url(../../../packageRc/static/dmsc/kpbj.png);
|
||||
background-size: 100% 100%;
|
||||
/* 加大卡片下边距 */
|
||||
margin-bottom: 29rpx;
|
||||
border: 1px solid #D1E5FF;
|
||||
border-radius: 10rpx;
|
||||
/* 加大卡片内边距 */
|
||||
padding: 29rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.job-top {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 14rpx;
|
||||
.job-salary {
|
||||
color: #EC7737;
|
||||
font-weight: bold;
|
||||
font-size: 38rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.job-name {
|
||||
font-size: 43rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
margin-top: 0;
|
||||
margin-right: 7rpx;
|
||||
/* 只保留单行溢出,以适应不同宽度 */
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.job-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 19rpx;
|
||||
.tag {
|
||||
background: #7DA6FF;
|
||||
color: #FFFFFF;
|
||||
font-size: 29rpx;
|
||||
padding: 5rpx 12rpx;
|
||||
border-radius: 7rpx;
|
||||
margin-right: 10rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.job-desc {
|
||||
font-size: 29rpx;
|
||||
color: #4C6EFB;
|
||||
margin-bottom: 26rpx;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.company-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: auto;
|
||||
margin-bottom: 29rpx;
|
||||
.comp-icon {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
margin-right: 10rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.comp-name {
|
||||
font-size: 29rpx;
|
||||
color: #666;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.delivery-btn {
|
||||
width: 75%;
|
||||
margin: 0 auto;
|
||||
height: 58rpx;
|
||||
line-height: 58rpx;
|
||||
background: #2591FF; /* 与设计图一致的亮蓝色 */
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
font-size: 31rpx;
|
||||
font-weight: 500;
|
||||
border-radius: 7rpx;
|
||||
/* 移除阴影以贴合扁平化设计稿 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.policy-list-card {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
color: #333333;
|
||||
/* 政策卡片大边距与内边距 */
|
||||
margin-bottom: 29rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
background: linear-gradient(180deg, #F0F8FF 0%, #FFFFFF 100%);
|
||||
padding: 38rpx 29rpx;
|
||||
border-radius: 10rpx;
|
||||
border: 1px solid #D1E5FF;
|
||||
box-shadow: 0px 2rpx 7rpx 0px rgba(16, 122, 253, 0.05);
|
||||
|
||||
.card-left {
|
||||
/* 加宽左侧保护不再折行 */
|
||||
width: 132rpx;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-right: 1px solid #E5EEFA;
|
||||
/* 增大左右空隙 */
|
||||
margin-right: 29rpx;
|
||||
|
||||
.clock-icon {
|
||||
width: 31rpx;
|
||||
height: 31rpx;
|
||||
margin-bottom: 7rpx;
|
||||
}
|
||||
|
||||
.date-md {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #107afd;
|
||||
line-height: 1;
|
||||
margin-bottom: 7rpx;
|
||||
}
|
||||
|
||||
.date-year {
|
||||
font-size: 24rpx;
|
||||
color: #107afd;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.card-right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.card-title {
|
||||
font-size: 38rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 14rpx;
|
||||
line-height: 1.4;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.card-infos {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.info-tag {
|
||||
font-size: 29rpx;
|
||||
color: #999;
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* #ifdef H5 */
|
||||
.h5-pc-container {
|
||||
& > view {
|
||||
width: 100% !important;
|
||||
margin: 0 auto !important;
|
||||
padding-left: 32px !important;
|
||||
padding-right: 32px !important;
|
||||
padding-top: 0 !important; /* 彻底移除顶部补白 */
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
|
||||
.showtab {
|
||||
margin-top: 0 !important; /* 移除卡片顶部间距 */
|
||||
margin-bottom: 72rpx;
|
||||
height: 204rpx;
|
||||
.tabItem {
|
||||
height: 204rpx !important;
|
||||
image:first-child {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
.activeImg {
|
||||
width: 96rpx !important;
|
||||
height: 12rpx !important;
|
||||
bottom: -24rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs {
|
||||
margin-bottom: 48rpx;
|
||||
background-color: #eee;
|
||||
border-radius: 60px;
|
||||
padding: 10px;
|
||||
.tab {
|
||||
width: 33.3% !important;
|
||||
line-height: 108rpx !important;
|
||||
font-size: 36px !important;
|
||||
border-radius: 60rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.titles {
|
||||
margin-top: 24rpx;
|
||||
margin-bottom: 60px;
|
||||
.title-item {
|
||||
font-size: 40px;
|
||||
font-weight: 600;
|
||||
margin-right: 100px !important;
|
||||
>view {
|
||||
padding: 0 10rpx !important;
|
||||
}
|
||||
&::after {
|
||||
height: 12rpx !important;
|
||||
bottom: -16px !important;
|
||||
width: 20% !important;
|
||||
left: 40% !important;
|
||||
background: orange;
|
||||
border-radius: 0;
|
||||
|
||||
}
|
||||
}
|
||||
.more-link {
|
||||
font-size: 20px !important;
|
||||
color: #A2A2A2;
|
||||
}
|
||||
}
|
||||
|
||||
.job-list {
|
||||
padding: 29rpx 24rpx !important;
|
||||
margin-bottom: 19rpx !important;
|
||||
border-radius: 14rpx !important;
|
||||
border: 1px solid #f0f0f0;
|
||||
box-shadow: 0px 1rpx 6rpx rgba(0, 0, 0, 0.02);
|
||||
.sign {
|
||||
font-size: 20px !important;
|
||||
padding: 5rpx 12rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 24px !important;
|
||||
font-weight: 600;
|
||||
margin-bottom: 14rpx !important;
|
||||
}
|
||||
.infos view {
|
||||
font-size: 20px !important;
|
||||
line-height: 1.5 !important;
|
||||
padding: 6rpx 14rpx !important;
|
||||
margin-bottom: 7rpx;
|
||||
background: #f5f5f5 !important;
|
||||
border-radius: 7rpx !important;
|
||||
}
|
||||
.salary {
|
||||
font-size: 24px !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
.time {
|
||||
font-size: 20px !important; /* 发布日期字号放大 */
|
||||
}
|
||||
.bottom-line {
|
||||
font-size: 20px !important;
|
||||
margin-top: 12rpx !important;
|
||||
}
|
||||
.view-more-btn {
|
||||
font-size: 24px !important; /* 查看更多字号放大 */
|
||||
padding: 12rpx 48rpx !important;
|
||||
border-radius: 36rpx !important;
|
||||
}
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
@@ -400,7 +400,11 @@
|
||||
<!-- 筛选 -->
|
||||
<select-filter ref="selectFilterModel"></select-filter>
|
||||
|
||||
|
||||
<!-- 微信授权登录弹窗 -->
|
||||
<WxAuthLogin
|
||||
ref="wxAuthLoginRef"
|
||||
@success="handleLoginSuccess"
|
||||
></WxAuthLogin>
|
||||
|
||||
<!-- <view class="maskFristEntry" v-if="maskFristEntry">
|
||||
<view class="entry-content">
|
||||
@@ -527,7 +531,7 @@ import {
|
||||
} from "@/stores/useRecommedIndexedDBStore.js";
|
||||
import { useScrollDirection } from "@/hook/useScrollDirection";
|
||||
import { useColumnCount } from "@/hook/useColumnCount";
|
||||
|
||||
import WxAuthLogin from "@/components/WxAuthLogin/WxAuthLogin.vue";
|
||||
import IconfontIcon from "@/components/IconfontIcon/IconfontIcon.vue";
|
||||
// 企业卡片组件已内联到模板中
|
||||
// 滚动状态管理
|
||||
@@ -580,7 +584,7 @@ const loadmoreRef = ref(null);
|
||||
const conditionSearch = ref({});
|
||||
const waterfallcolumn = ref(2);
|
||||
const maskFristEntry = ref(false);
|
||||
|
||||
const wxAuthLoginRef = ref(null);
|
||||
const state = reactive({
|
||||
tabIndex: "all",
|
||||
});
|
||||
@@ -680,7 +684,7 @@ onMounted(() => {
|
||||
|
||||
// 监听退出登录事件,显示微信登录弹窗
|
||||
uni.$on("showLoginModal", () => {
|
||||
uni.navigateTo({ url: '/pages/login/wx-login' });
|
||||
wxAuthLoginRef.value?.open();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -708,8 +712,8 @@ watch(
|
||||
const checkLogin = () => {
|
||||
const tokenValue = uni.getStorageSync("token") || "";
|
||||
if (!tokenValue || !hasLogin.value) {
|
||||
// 未登录,跳转到登录页面
|
||||
uni.navigateTo({ url: '/pages/login/wx-login' });
|
||||
// 未登录,打开授权弹窗
|
||||
wxAuthLoginRef.value?.open();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
2026
packageRc/pages/jobList/jobListYtj.vue
Normal file
2026
packageRc/pages/jobList/jobListYtj.vue
Normal file
File diff suppressed because it is too large
Load Diff
BIN
packageRc/static/dmsc/bj.png
Normal file
BIN
packageRc/static/dmsc/bj.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
BIN
packageRc/static/dmsc/gs.png
Normal file
BIN
packageRc/static/dmsc/gs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 611 B |
BIN
packageRc/static/dmsc/kpbj.png
Normal file
BIN
packageRc/static/dmsc/kpbj.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
packageRc/static/dmsc/sj.png
Normal file
BIN
packageRc/static/dmsc/sj.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 911 B |
BIN
packageRc/static/dmsc/ss.png
Normal file
BIN
packageRc/static/dmsc/ss.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1007 B |
@@ -660,7 +660,10 @@
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "高校毕业生智慧就业"
|
||||
"navigationBarTitleText": "高校毕业生智慧就业",
|
||||
// #ifdef H5
|
||||
"navigationStyle": "custom"
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -161,12 +161,12 @@
|
||||
</view>
|
||||
<view class="service-title">帮扶</view>
|
||||
</view>
|
||||
<view class="service-item press-button" v-if="isFourLevelLinkagePurview" @click="helpTaskClick">
|
||||
<!-- <view class="service-item press-button" v-if="isFourLevelLinkagePurview" @click="helpTaskClick">
|
||||
<view class="service-icon service-icon-1">
|
||||
<uni-icons type="shop" size="32" color="#FFFFFF"></uni-icons>
|
||||
</view>
|
||||
<view class="service-title">帮扶任务</view>
|
||||
</view>
|
||||
</view> -->
|
||||
<view class="service-item press-button" @click="handleNoticeClick">
|
||||
<view class="service-icon service-icon-10">
|
||||
<uni-icons type="sound" size="32" color="#FFFFFF"></uni-icons>
|
||||
@@ -756,7 +756,9 @@ const helpTaskClick = () =>{
|
||||
}
|
||||
//招聘会模块跳转
|
||||
const handleJobFairClick = () => {
|
||||
navTo('/pages/careerfair/careerfair');
|
||||
if (checkLogin()) {
|
||||
navTo('/pages/careerfair/careerfair');
|
||||
}
|
||||
};
|
||||
const list = ref([]);
|
||||
const pageState = reactive({
|
||||
@@ -784,6 +786,7 @@ const rangeOptions = ref([
|
||||
]);
|
||||
const isLoaded = ref(false);
|
||||
const isInitialized = ref(false); // 添加初始化标志
|
||||
const isRecommendLoading = ref(false); // 请求锁,防止重复调用
|
||||
|
||||
const { columnCount, columnSpace } = useColumnCount(() => {
|
||||
pageState.pageSize = 10 * (columnCount.value - 1) + 10;
|
||||
@@ -948,20 +951,27 @@ const handleNearbyClick = (options ) => {
|
||||
// #endif
|
||||
};
|
||||
const handleNoticeClick = () =>{
|
||||
uni.navigateTo({
|
||||
url:'/packageB/notice/index'
|
||||
})
|
||||
}
|
||||
function handleInstitutionClick(type){
|
||||
if(type=='evaluate'){
|
||||
if (checkLogin()) {
|
||||
uni.navigateTo({
|
||||
url:'/packageB/institution/evaluationAgency'
|
||||
})
|
||||
}else if (type=='training'){
|
||||
uni.navigateTo({
|
||||
url:'/packageB/institution/trainingInstitution'
|
||||
url:'/packageB/notice/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
function handleInstitutionClick(type){
|
||||
|
||||
if (checkLogin()) {
|
||||
if(type=='evaluate'){
|
||||
uni.navigateTo({
|
||||
url:'/packageB/institution/evaluationAgency'
|
||||
})
|
||||
}else if (type=='training'){
|
||||
uni.navigateTo({
|
||||
url:'/packageB/institution/trainingInstitution'
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// 处理服务功能点击
|
||||
@@ -1092,7 +1102,7 @@ function clearfindJob(job) {
|
||||
}
|
||||
|
||||
function nextDetail(job) {
|
||||
navTo(`/packageA/pages/post/post?encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
|
||||
}
|
||||
|
||||
function navToService(serviceType) {
|
||||
@@ -1234,10 +1244,12 @@ function handelHostestSearch(val) {
|
||||
}
|
||||
|
||||
function getJobRecommend(type = 'add') {
|
||||
if (isRecommendLoading.value) return;
|
||||
if (type === 'refresh') {
|
||||
list.value = [];
|
||||
if (waterfallsFlowRef.value) waterfallsFlowRef.value.refresh();
|
||||
}
|
||||
isRecommendLoading.value = true;
|
||||
let params = {
|
||||
pageSize: pageState.pageSize + 10,
|
||||
sessionId: useUserStore().seesionId,
|
||||
@@ -1311,6 +1323,8 @@ function getJobRecommend(type = 'add') {
|
||||
if (!data.length) {
|
||||
useUserStore().initSeesionId();
|
||||
}
|
||||
}).finally(() => {
|
||||
isRecommendLoading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<AppLayout back-gorund-color="#F4F4F4">
|
||||
<view class="mine-content">
|
||||
<!-- 自定义tabbar -->
|
||||
<CustomTabBar :currentPage="4" />
|
||||
<!-- 企业用户信息卡片 -->
|
||||
@@ -174,6 +175,7 @@
|
||||
<template #footer>
|
||||
<!-- 统一使用系统tabBar -->
|
||||
</template>
|
||||
</view>
|
||||
</AppLayout>
|
||||
</template>
|
||||
|
||||
@@ -358,6 +360,11 @@ function submitFeedback() {
|
||||
.card-top.tilt {
|
||||
transform: perspective(600px) rotateY(8deg) rotateX(4deg);
|
||||
}
|
||||
.mine-content{
|
||||
padding: 28rpx 28rpx 90rpx 28rpx;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.mini-cards{
|
||||
padding: 28rpx
|
||||
.card-top{
|
||||
|
||||
@@ -134,7 +134,7 @@ function nextDetail(job) {
|
||||
const recordData = recommedIndexDb.JobParameter(job);
|
||||
recommedIndexDb.addRecord(recordData);
|
||||
}
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}`);
|
||||
navTo(`/packageA/pages/post/post?jobId=${encodeURIComponent(job.jobId)}&encryptJobId=${encodeURIComponent(job.encryptJobId)}`);
|
||||
}
|
||||
|
||||
function nextVideo(job) {
|
||||
|
||||
@@ -29,6 +29,7 @@ function buildIndex(tree) {
|
||||
const useDictStore = defineStore("dict", () => {
|
||||
// 定义状态
|
||||
const complete = ref(false)
|
||||
const dictLoading = ref(false)
|
||||
const state = reactive({
|
||||
education: [],
|
||||
experience: [],
|
||||
@@ -43,13 +44,16 @@ const useDictStore = defineStore("dict", () => {
|
||||
})
|
||||
// political_affiliation
|
||||
const getDictData = async (dictType, dictName) => {
|
||||
if (dictType && dictName) {
|
||||
return getDictSelectOption(dictType).then((data) => {
|
||||
state[dictName] = data
|
||||
return data
|
||||
})
|
||||
}
|
||||
if (complete.value) return
|
||||
if (dictLoading.value) return
|
||||
dictLoading.value = true
|
||||
try {
|
||||
if (dictType && dictName) {
|
||||
return getDictSelectOption(dictType).then((data) => {
|
||||
state[dictName] = data
|
||||
return data
|
||||
})
|
||||
}
|
||||
const [education, experience, area, scale, sex, affiliation, nature, noticeType] =
|
||||
await Promise.all([
|
||||
getDictSelectOption('education'),
|
||||
@@ -75,16 +79,16 @@ const useDictStore = defineStore("dict", () => {
|
||||
} catch (error) {
|
||||
console.error('Error fetching dictionary data:', error);
|
||||
// 确保即使出错也能返回空数组
|
||||
if (!dictType && !dictName) {
|
||||
state.education = [];
|
||||
state.experience = [];
|
||||
state.area = [];
|
||||
state.scale = [];
|
||||
state.sex = [];
|
||||
state.affiliation = [];
|
||||
state.nature = [];
|
||||
state.noticeType = [];
|
||||
}
|
||||
state.education = [];
|
||||
state.experience = [];
|
||||
state.area = [];
|
||||
state.scale = [];
|
||||
state.sex = [];
|
||||
state.affiliation = [];
|
||||
state.nature = [];
|
||||
state.noticeType = [];
|
||||
} finally {
|
||||
dictLoading.value = false
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
37
utils/crypto.js
Normal file
37
utils/crypto.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import { sm4 } from 'sm-crypto';
|
||||
|
||||
export function sm4Decrypt(key, value, mode = "hex") {
|
||||
try {
|
||||
if (key.length !== 32) {
|
||||
uni.showToast({ title: '密钥必须是32位16进制字符串(128位)', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const decrypted = sm4.decrypt(value, key, {
|
||||
mode: 'ecb',
|
||||
cipherType: mode === 'hex' ? 'hex' : 'base64',
|
||||
padding: 'pkcs#5'
|
||||
});
|
||||
return decrypted;
|
||||
} catch (e) {
|
||||
console.error('sm4 decrypt error:', e);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
export function sm4Encrypt(key, value, mode = "hex") {
|
||||
try {
|
||||
if (key.length !== 32) {
|
||||
uni.showToast({ title: '密钥必须是32位16进制字符串(128位)', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const encrypted = sm4.encrypt(value, key, {
|
||||
mode: 'ecb',
|
||||
cipherType: mode === 'hex' ? 'hex' : 'base64',
|
||||
padding: 'pkcs#5'
|
||||
});
|
||||
return encrypted;
|
||||
} catch (e) {
|
||||
console.error('sm4 encrypt error:', e);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,80 @@
|
||||
import config from "@/config.js"
|
||||
import { sm4Encrypt, sm4Decrypt } from '@/utils/crypto';
|
||||
import useUserStore from '@/stores/useUserStore';
|
||||
|
||||
const needToEncryptSet = new Set([
|
||||
'POST:/app/login',
|
||||
'GET:/app/user/resume',
|
||||
'POST:/app/user/resume',
|
||||
'POST:/app/user/experience/edit',
|
||||
'POST:/app/user/experience/delete',
|
||||
'GET:/app/user/experience/getSingle',
|
||||
'GET:/app/user/experience/list',
|
||||
'POST:/app/user/cert',
|
||||
'POST:/app/user/getUserArchives',
|
||||
]);
|
||||
|
||||
const encryptPathPrefixes = [
|
||||
// '/app/common/',
|
||||
'/app/chat/',
|
||||
// '/app/speech/',
|
||||
'/app/job/',
|
||||
'/app/company/',
|
||||
'/app/companycontact/',
|
||||
'/app/appskill/',
|
||||
'/app/userworkexperiences/',
|
||||
'/app/appWxphoneSmsCode',
|
||||
'/app/sendSmsAgain',
|
||||
'/app/user/',
|
||||
'/registerUser',
|
||||
'/app/user/resume/',
|
||||
'/cms/job/recommen/',
|
||||
'/app/appLoginPhone',
|
||||
'/app/notice/',
|
||||
'/app/idCardLogin',
|
||||
'/app/phoneLogin',
|
||||
];
|
||||
|
||||
const isEncryptNeeded = (method, url) => {
|
||||
const key = `${method.toUpperCase()}:${url}`;
|
||||
if (needToEncryptSet.has(key)) return true;
|
||||
for (const encryptKey of needToEncryptSet) {
|
||||
const [encryptMethod, encryptUrl] = encryptKey.split(':');
|
||||
if (encryptMethod === method.toUpperCase() && url.startsWith(encryptUrl.split('/{')[0])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const prefix of encryptPathPrefixes) {
|
||||
if (url.startsWith(prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const encryptRequestData = (data) => {
|
||||
const jsonData = JSON.stringify(data);
|
||||
// const jsonData = JSON.stringify({a: '1'});
|
||||
// console.log('[请求] 加密前:', jsonData)
|
||||
return {
|
||||
encrypted: true,
|
||||
encryptedData: sm4Encrypt(config.sm4Config.key, jsonData),
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
};
|
||||
|
||||
const handleResponseData = (resData) => {
|
||||
try {
|
||||
if (resData?.encrypted) {
|
||||
const decrypted = sm4Decrypt(config.sm4Config.key, resData.encryptedData);
|
||||
resData = JSON.parse(decrypted);
|
||||
// console.log('[请求] 解密后数据:', resData);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[请求] 解密失败:', e.message);
|
||||
}
|
||||
return resData;
|
||||
};
|
||||
export function request({
|
||||
url,
|
||||
method = 'GET',
|
||||
@@ -89,25 +164,27 @@ export function createRequest(url, data = {}, method = 'GET', loading = false, h
|
||||
if(needHeader){
|
||||
header["Authorization"] = encodeURIComponent(Authorization);
|
||||
}
|
||||
const requestData = isEncryptNeeded(method, url) ? encryptRequestData(data) : data;
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: config.baseUrl + url,
|
||||
method: method,
|
||||
data: data,
|
||||
data: requestData,
|
||||
header,
|
||||
success: resData => {
|
||||
// 响应拦截
|
||||
if (resData.statusCode === 200) {
|
||||
const responseData = handleResponseData(resData.data)
|
||||
const {
|
||||
code,
|
||||
msg
|
||||
} = resData.data
|
||||
} = responseData
|
||||
if (code === 200) {
|
||||
resolve(resData.data)
|
||||
resolve(responseData)
|
||||
return
|
||||
}
|
||||
// 处理业务错误
|
||||
if (resData.data?.code === 401 || resData.data?.code === 402) {
|
||||
if (responseData?.code === 401 || responseData?.code === 402) {
|
||||
useUserStore().logOut()
|
||||
}
|
||||
// 显示具体的错误信息
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import config from "@/config.js"
|
||||
import useUserStore from '@/stores/useUserStore';
|
||||
import { sm4Encrypt, sm4Decrypt } from '@/utils/crypto';
|
||||
|
||||
/**
|
||||
* @param url String,请求的地址,默认:none
|
||||
@@ -25,14 +26,23 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom
|
||||
const userStore = useUserStore();
|
||||
const Authorization = userStore.token ? encodeURIComponent(userStore.token) : '';
|
||||
|
||||
const requestBody = data && Object.keys(data).length > 0
|
||||
? {
|
||||
encrypted: true,
|
||||
encryptedData: sm4Encrypt(config.sm4Config.key, JSON.stringify(data)),
|
||||
timestamp: Date.now(),
|
||||
}
|
||||
: data;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let buffer = '';
|
||||
let hasReceivedContent = false;
|
||||
let isCompleted = false;
|
||||
|
||||
const requestTask = uni.request({
|
||||
url: config.StreamBaseURl + url,
|
||||
method: 'POST',
|
||||
data: data,
|
||||
data: requestBody,
|
||||
header: {
|
||||
"Authorization": Authorization,
|
||||
"Accept": "text/event-stream",
|
||||
@@ -41,8 +51,11 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom
|
||||
enableChunked: true, // 启用分块传输
|
||||
success: (res) => {
|
||||
console.log('📡 Stream request completed');
|
||||
onComplete && onComplete();
|
||||
resolve();
|
||||
if (!isCompleted) {
|
||||
isCompleted = true;
|
||||
onComplete && onComplete();
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('Stream 请求失败:', err);
|
||||
@@ -172,16 +185,30 @@ function StreamRequestMiniProgram(url, data = {}, onDataReceived, onError, onCom
|
||||
console.log('📄 提取的JSON数据:', jsonData);
|
||||
if (jsonData === "[DONE]") {
|
||||
console.log('✅ 收到结束标记 [DONE]');
|
||||
onComplete && onComplete();
|
||||
resolve();
|
||||
if (!isCompleted) {
|
||||
isCompleted = true;
|
||||
onComplete && onComplete();
|
||||
resolve();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (jsonData && jsonData.trim()) {
|
||||
try {
|
||||
const parsedData = JSON.parse(jsonData);
|
||||
let parsedData = JSON.parse(jsonData);
|
||||
console.log('🔧 解析后的JSON:', parsedData);
|
||||
|
||||
if (parsedData?.encrypted && typeof parsedData?.encryptedData === 'string') {
|
||||
const decryptedStr = sm4Decrypt(config.sm4Config.key, parsedData.encryptedData);
|
||||
if (decryptedStr && decryptedStr !== parsedData.encryptedData) {
|
||||
try {
|
||||
parsedData = JSON.parse(decryptedStr);
|
||||
} catch (e) {
|
||||
console.error('SSE解密数据JSON解析失败:', e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有错误信息
|
||||
const finishReason = parsedData?.choices?.[0]?.finish_reason;
|
||||
if (finishReason === "error") {
|
||||
@@ -279,12 +306,21 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) {
|
||||
"Accept": "text/event-stream",
|
||||
"Content-Type": "application/json;charset=UTF-8"
|
||||
};
|
||||
|
||||
const requestBody = data && Object.keys(data).length > 0
|
||||
? {
|
||||
encrypted: true,
|
||||
encryptedData: sm4Encrypt(config.sm4Config.key, JSON.stringify(data)),
|
||||
timestamp: Date.now(),
|
||||
}
|
||||
: data;
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const response = await fetch(config.StreamBaseURl + url, {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify(data)
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -347,9 +383,21 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) {
|
||||
try {
|
||||
// 检查JSON数据是否完整
|
||||
if (jsonData && jsonData.trim() && jsonData !== "[DONE]") {
|
||||
const parsedData = JSON.parse(jsonData);
|
||||
let parsedData = JSON.parse(jsonData);
|
||||
console.log('🔧 解析后的JSON:', parsedData);
|
||||
|
||||
if (parsedData?.encrypted && typeof parsedData?.encryptedData === 'string') {
|
||||
const decryptedStr = sm4Decrypt(config.sm4Config.key, parsedData.encryptedData);
|
||||
if (decryptedStr && decryptedStr !== parsedData.encryptedData) {
|
||||
try {
|
||||
const decrypted = JSON.parse(decryptedStr);
|
||||
parsedData = decrypted;
|
||||
} catch (e) {
|
||||
console.error('SSE解密数据JSON解析失败:', e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有错误信息
|
||||
const finishReason = parsedData?.choices?.[0]?.finish_reason;
|
||||
if (finishReason === "error") {
|
||||
@@ -458,9 +506,21 @@ function StreamRequestH5(url, data = {}, onDataReceived, onError, onComplete) {
|
||||
console.log('📄 提取的剩余JSON数据:', jsonData);
|
||||
if (jsonData && jsonData !== "[DONE]") {
|
||||
try {
|
||||
const parsedData = JSON.parse(jsonData);
|
||||
let parsedData = JSON.parse(jsonData);
|
||||
console.log('🔧 解析后的剩余JSON:', parsedData);
|
||||
|
||||
if (parsedData?.encrypted && typeof parsedData?.encryptedData === 'string') {
|
||||
const decryptedStr = sm4Decrypt(config.sm4Config.key, parsedData.encryptedData);
|
||||
if (decryptedStr && decryptedStr !== parsedData.encryptedData) {
|
||||
try {
|
||||
const decrypted = JSON.parse(decryptedStr);
|
||||
parsedData = decrypted;
|
||||
} catch (e) {
|
||||
console.error('SSE解密数据JSON解析失败:', e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有错误信息
|
||||
const finishReason = parsedData?.choices?.[0]?.finish_reason;
|
||||
if (finishReason === "error") {
|
||||
@@ -573,33 +633,49 @@ export function chatRequest(url, data = {}, method = 'GET', loading = false, hea
|
||||
|
||||
const header = headers || {};
|
||||
header["Authorization"] = encodeURIComponent(Authorization);
|
||||
|
||||
const isEncryptedMethod = method.toUpperCase() === 'POST' || method.toUpperCase() === 'PUT';
|
||||
const requestData = isEncryptedMethod && data && Object.keys(data).length > 0
|
||||
? {
|
||||
encrypted: true,
|
||||
encryptedData: sm4Encrypt(config.sm4Config.key, JSON.stringify(data)),
|
||||
timestamp: Date.now(),
|
||||
}
|
||||
: data;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: config.StreamBaseURl + url,
|
||||
method: method,
|
||||
data: data,
|
||||
data: requestData,
|
||||
header,
|
||||
success: resData => {
|
||||
// 响应拦截
|
||||
if (resData.statusCode === 200) {
|
||||
let responseData = resData.data;
|
||||
try {
|
||||
if (responseData?.encrypted) {
|
||||
const decrypted = sm4Decrypt(config.sm4Config.key, responseData.encryptedData);
|
||||
responseData = JSON.parse(decrypted);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[chatRequest] 解密失败:', e.message);
|
||||
}
|
||||
const {
|
||||
code,
|
||||
msg
|
||||
} = resData.data
|
||||
} = responseData
|
||||
if (code === 200) {
|
||||
resolve(resData.data)
|
||||
resolve(responseData)
|
||||
return
|
||||
}
|
||||
uni.showToast({
|
||||
title: msg || '请求失败',
|
||||
icon: 'none'
|
||||
})
|
||||
// 拒绝Promise并提供详细错误信息
|
||||
const err = new Error(msg || '请求失败,服务器返回错误码: ' + code)
|
||||
err.error = resData
|
||||
reject(err)
|
||||
} else {
|
||||
// 处理非200状态码
|
||||
const errorMsg = `请求失败,HTTP状态码: ${resData.statusCode}`
|
||||
uni.showToast({
|
||||
title: errorMsg,
|
||||
|
||||
Reference in New Issue
Block a user