@ -0,0 +1,23 @@ |
|||||
|
.DS_Store |
||||
|
node_modules/ |
||||
|
unpackage/ |
||||
|
dist/ |
||||
|
|
||||
|
# local env files |
||||
|
.env.local |
||||
|
.env.*.local |
||||
|
|
||||
|
# Log files |
||||
|
npm-debug.log* |
||||
|
yarn-debug.log* |
||||
|
yarn-error.log* |
||||
|
|
||||
|
# Editor directories and files |
||||
|
.project |
||||
|
.idea |
||||
|
.vscode |
||||
|
*.suo |
||||
|
*.ntvs* |
||||
|
*.njsproj |
||||
|
*.sln |
||||
|
*.sw* |
||||
@ -0,0 +1,23 @@ |
|||||
|
<script> |
||||
|
export default { |
||||
|
onLaunch: function() { |
||||
|
console.log('App Launch') |
||||
|
}, |
||||
|
onShow: function() { |
||||
|
console.log('App Show') |
||||
|
console.log(uni.getStorageSync('loginRes')) |
||||
|
if(!uni.getStorageSync('loginRes') || !uni.getStorageSync('loginRes').accessToken){ |
||||
|
uni.navigateTo({ |
||||
|
url:'/pages/login/login' |
||||
|
}) |
||||
|
} |
||||
|
}, |
||||
|
onHide: function() { |
||||
|
console.log('App Hide') |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
/*每个页面公共css */ |
||||
|
</style> |
||||
@ -0,0 +1,91 @@ |
|||||
|
// api.js
|
||||
|
|
||||
|
// 基础URL,可以根据环境来设置
|
||||
|
// uEnvDev
|
||||
|
const accountInfo = wx.getAccountInfoSync(); |
||||
|
// env类型 develop:开发版、trial:体验版、release:正式版
|
||||
|
export const env = accountInfo.miniProgram.envVersion; |
||||
|
if (!env) { |
||||
|
console.error("获取运行环境失败!"); |
||||
|
} |
||||
|
const baseApi = { |
||||
|
// 开发版
|
||||
|
develop: "http://110.40.156.216:30005/api", |
||||
|
// 体验版
|
||||
|
trial: "http://110.40.156.216:30005/api", |
||||
|
// 正式版
|
||||
|
release: "http://110.40.156.216:30005/api" |
||||
|
}; |
||||
|
console.log(env, 'env') |
||||
|
// request请求baseURL
|
||||
|
const BASE_URL = baseApi[env] || 'http://110.40.156.216:30005/api'; |
||||
|
|
||||
|
|
||||
|
function request(url, method, data = {}) { |
||||
|
const userInfo = uni.getStorageSync('loginInfo') || {}; |
||||
|
const UTCOffset = new Date().getTimezoneOffset(); |
||||
|
return new Promise((resolve, reject) => { |
||||
|
uni.request({ |
||||
|
url: BASE_URL + url, // 完整的URL
|
||||
|
method: method, |
||||
|
data: data, |
||||
|
header: { |
||||
|
'AccessToken': userInfo.accessToken || '-1', // 请求头,可根据需要调整
|
||||
|
'UserId': userInfo.userId || '1', // 请求头,可根据需要调整
|
||||
|
'LanguageType': 0, |
||||
|
'LoginName': userInfo.loginName || '', |
||||
|
'CompanyId': userInfo.companyId || '', |
||||
|
'UTCOffset': UTCOffset, |
||||
|
}, |
||||
|
success: (res) => { |
||||
|
if (res.statusCode === 200) { |
||||
|
console.log(res) |
||||
|
if (res.data.code === 200 | res.data.code === 0) { |
||||
|
resolve(res.data) |
||||
|
} else { |
||||
|
reject(res.data) |
||||
|
} |
||||
|
/* if (res.data.code === 500) { |
||||
|
uni.showToast({ |
||||
|
title: '系统错误', // 提示的文本内容
|
||||
|
icon: 'none', // 提示的图标,可选值:'success' | 'loading' | 'none'
|
||||
|
duration: 2000 // 提示框的显示时间,单位为毫秒,默认1500ms
|
||||
|
}); |
||||
|
} |
||||
|
if (res.data.code === 401) { |
||||
|
uni.showToast({ |
||||
|
title: '登录过期,重新登录中', // 提示的文本内容
|
||||
|
icon: 'none', // 提示的图标,可选值:'success' | 'loading' | 'none'
|
||||
|
duration: 2000 // 提示框的显示时间,单位为毫秒,默认1500ms
|
||||
|
}); |
||||
|
} |
||||
|
if (res.data.code === 20001) { |
||||
|
reject(res.data); |
||||
|
} |
||||
|
resolve(res.data) */ |
||||
|
} else { |
||||
|
reject(res); |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
fail: (err) => { |
||||
|
uni.showToast({ |
||||
|
title: '请求错误', // 提示的文本内容
|
||||
|
icon: 'none', // 提示的图标,可选值:'success' | 'loading' | 'none'
|
||||
|
duration: 2000 // 提示框的显示时间,单位为毫秒,默认1500ms
|
||||
|
}); |
||||
|
reject(err); // 请求失败
|
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// GET 请求
|
||||
|
export function get(url, params = {}) { |
||||
|
return request(url, 'GET', params); |
||||
|
} |
||||
|
|
||||
|
// POST 请求
|
||||
|
export function post(url, data = {}) { |
||||
|
return request(url, 'POST', data); |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
import { get, post } from "./httpSetting"; |
||||
|
|
||||
|
/** |
||||
|
* 登录 |
||||
|
*/ |
||||
|
export const userLogin = (params ={}) => post('/app/auth/login', params); |
||||
|
|
||||
|
export const getAppJobVO = (params ={}) => get('/app/job/getAppJobVO', params); |
||||
@ -0,0 +1,246 @@ |
|||||
|
<template> |
||||
|
<view class="recruitment-card"> |
||||
|
<!-- 卡片头部信息 --> |
||||
|
<view class="card-head"> |
||||
|
<div class="factory-info"> |
||||
|
<h3 class="factory-name">{{dataSource.factoryName || '默认工厂'}}</h3> |
||||
|
<span class="factory-type">{{dataSource.factoryType || '电子厂'}}</span> |
||||
|
</div> |
||||
|
<div class="card-actions"> |
||||
|
<!-- <view class="favorite-btn" @click="toggleFavorite"> |
||||
|
<text class="heart-icon">{{isFavorite ? '♥' : '♡'}}</text> |
||||
|
</view> --> |
||||
|
<button class="call-btn" @click="makeCall">拨打电话</button> |
||||
|
<button class="review-btn" @click.stop="handleGoToDetail">查看详情</button> |
||||
|
<view class="more-btn" @click.stop> |
||||
|
<text>···</text> |
||||
|
</view> |
||||
|
</div> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 工作时间和内容 --> |
||||
|
<view class="work-info"> |
||||
|
<text class="work-time">{{dataSource.workTime || '8:00-20:00'}}</text> |
||||
|
<text class="work-type">{{dataSource.workType || '两班倒'}}</text> |
||||
|
<text class="work-content">{{dataSource.workContent || '主营汽车线束'}}</text> |
||||
|
<span class="distance">{{dataSource.distance || '距你2.5km'}}</span> |
||||
|
</view> |
||||
|
|
||||
|
<view class="card-bm"> |
||||
|
<template v-for="(item, index) in processedCompanyData" :key="item.label"> |
||||
|
<view class="item-info-swiper"> |
||||
|
<view class="label">{{item.label}}</view> |
||||
|
<view class="value"> |
||||
|
{{item.value}}<text class="label-two">{{item.unit}}</text> |
||||
|
</view> |
||||
|
<view class="label-two"> |
||||
|
{{item.exLabel}} |
||||
|
</view> |
||||
|
</view> |
||||
|
<view v-if="index < processedCompanyData.length - 1" class="divider"></view> |
||||
|
</template> |
||||
|
|
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: "recruitment", |
||||
|
props: { |
||||
|
dataSource: { |
||||
|
type: Object, |
||||
|
default: () => ({}) |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
isFavorite: false, |
||||
|
companyData: [{ |
||||
|
label: '薪资', |
||||
|
value: '20', |
||||
|
unit: '', |
||||
|
exLabel: '元/小时' |
||||
|
}, |
||||
|
{ |
||||
|
label: '年龄', |
||||
|
value: '20-42', |
||||
|
unit: '', |
||||
|
exLabel: '元/小时' |
||||
|
}, |
||||
|
{ |
||||
|
label: '吃饭', |
||||
|
value: '2', |
||||
|
unit: '餐', |
||||
|
exLabel: '白-夜' |
||||
|
}, |
||||
|
{ |
||||
|
label: '住宿', |
||||
|
value: '20', |
||||
|
unit: '', |
||||
|
exLabel: '人间' |
||||
|
}, |
||||
|
], |
||||
|
|
||||
|
}; |
||||
|
}, |
||||
|
computed: { |
||||
|
processedCompanyData() { |
||||
|
return this.dataSource.companyData || this.companyData; |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
// 拨打电话 |
||||
|
makeCall(e) { |
||||
|
e.stopPropagation(); |
||||
|
uni.makePhoneCall({ |
||||
|
phoneNumber: '400-123-4567' |
||||
|
}); |
||||
|
}, |
||||
|
// 切换收藏状态 |
||||
|
toggleFavorite(e) { |
||||
|
e.stopPropagation(); |
||||
|
this.isFavorite = !this.isFavorite; |
||||
|
}, |
||||
|
handleGoToDetail(e) { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/positionDetail/positionDetail' |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.recruitment-card { |
||||
|
background-color: #fff; |
||||
|
padding: 8px 16px; |
||||
|
z-index: 10; |
||||
|
|
||||
|
.card-head { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
margin-bottom: 8px; |
||||
|
flex-wrap: wrap; |
||||
|
.factory-info { |
||||
|
width: 100%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 8px; |
||||
|
margin-bottom: 8px; |
||||
|
.factory-name { |
||||
|
font-size: 18px; |
||||
|
font-weight: 700; |
||||
|
color: #333; |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
.factory-type { |
||||
|
background-color: #f0f0f0; |
||||
|
color: #666; |
||||
|
padding: 2px 8px; |
||||
|
border-radius: 4px; |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.distance { |
||||
|
color: #999; |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.card-actions { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 8px; |
||||
|
|
||||
|
.favorite-btn { |
||||
|
font-size: 20px; |
||||
|
color: #ff4757; |
||||
|
padding: 4px; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.call-btn { |
||||
|
background-color: #ff4757; |
||||
|
color: white; |
||||
|
border: none; |
||||
|
padding: 6px 12px; |
||||
|
border-radius: 4px; |
||||
|
font-size: 14px; |
||||
|
line-height: 1.4; |
||||
|
} |
||||
|
|
||||
|
.review-btn { |
||||
|
background-color: transparent; |
||||
|
color: #666; |
||||
|
border: 1px solid #ddd; |
||||
|
padding: 6px 12px; |
||||
|
border-radius: 4px; |
||||
|
font-size: 14px; |
||||
|
line-height: 1.4; |
||||
|
} |
||||
|
|
||||
|
.more-btn { |
||||
|
color: #999; |
||||
|
font-size: 18px; |
||||
|
cursor: pointer; |
||||
|
padding: 4px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.work-info { |
||||
|
display: flex; |
||||
|
gap: 12px; |
||||
|
font-size: 12px; |
||||
|
color: #666; |
||||
|
margin-bottom: 12px; |
||||
|
} |
||||
|
|
||||
|
.card-bm { |
||||
|
display: flex; |
||||
|
padding: 0; |
||||
|
justify-content: space-around; |
||||
|
|
||||
|
.item-wrapper { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.item-info-swiper { |
||||
|
padding: 0; |
||||
|
display: inline-block; |
||||
|
text-align: center; |
||||
|
flex: 1; |
||||
|
|
||||
|
.label { |
||||
|
font-weight: 700; |
||||
|
font-size: 14px; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.value { |
||||
|
font-size: 24px; |
||||
|
margin-top: 4px; |
||||
|
margin-bottom: 4px; |
||||
|
color: $uni-color-primary; |
||||
|
} |
||||
|
|
||||
|
.label-two { |
||||
|
font-size: 12px; |
||||
|
color: #666; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.divider { |
||||
|
width: 1px; |
||||
|
height: 60px; |
||||
|
background-color: #e5e5e5; |
||||
|
margin: 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,20 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="zh-CN"> |
||||
|
<head> |
||||
|
<meta charset="UTF-8" /> |
||||
|
<script> |
||||
|
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || |
||||
|
CSS.supports('top: constant(a)')) |
||||
|
document.write( |
||||
|
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + |
||||
|
(coverSupport ? ', viewport-fit=cover' : '') + '" />') |
||||
|
</script> |
||||
|
<title></title> |
||||
|
<!--preload-links--> |
||||
|
<!--app-context--> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div id="app"><!--app-html--></div> |
||||
|
<script type="module" src="/main.js"></script> |
||||
|
</body> |
||||
|
</html> |
||||
@ -0,0 +1,25 @@ |
|||||
|
import App from './App' |
||||
|
import * as Pinia from 'pinia'; |
||||
|
|
||||
|
// #ifndef VUE3
|
||||
|
import Vue from 'vue' |
||||
|
import './uni.promisify.adaptor' |
||||
|
Vue.config.productionTip = false |
||||
|
App.mpType = 'app' |
||||
|
const app = new Vue({ |
||||
|
...App |
||||
|
}) |
||||
|
app.$mount() |
||||
|
// #endif
|
||||
|
|
||||
|
// #ifdef VUE3
|
||||
|
import { createSSRApp } from 'vue' |
||||
|
export function createApp() { |
||||
|
const app = createSSRApp(App) |
||||
|
app.use(Pinia.createPinia()); |
||||
|
return { |
||||
|
app, |
||||
|
Pinia |
||||
|
} |
||||
|
} |
||||
|
// #endif
|
||||
@ -0,0 +1,78 @@ |
|||||
|
{ |
||||
|
"name" : "laowumap", |
||||
|
"appid" : "__UNI__3F7EFE0", |
||||
|
"description" : "", |
||||
|
"versionName" : "1.0.0", |
||||
|
"versionCode" : "100", |
||||
|
"transformPx" : false, |
||||
|
/* 5+App特有相关 */ |
||||
|
"app-plus" : { |
||||
|
"usingComponents" : true, |
||||
|
"nvueStyleCompiler" : "uni-app", |
||||
|
"compilerVersion" : 3, |
||||
|
"splashscreen" : { |
||||
|
"alwaysShowBeforeRender" : true, |
||||
|
"waiting" : true, |
||||
|
"autoclose" : true, |
||||
|
"delay" : 0 |
||||
|
}, |
||||
|
/* 模块配置 */ |
||||
|
"modules" : {}, |
||||
|
/* 应用发布信息 */ |
||||
|
"distribute" : { |
||||
|
/* android打包配置 */ |
||||
|
"android" : { |
||||
|
"permissions" : [ |
||||
|
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.VIBRATE\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", |
||||
|
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.CAMERA\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", |
||||
|
"<uses-feature android:name=\"android.hardware.camera\"/>", |
||||
|
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" |
||||
|
] |
||||
|
}, |
||||
|
/* ios打包配置 */ |
||||
|
"ios" : {}, |
||||
|
/* SDK配置 */ |
||||
|
"sdkConfigs" : {} |
||||
|
} |
||||
|
}, |
||||
|
/* 快应用特有相关 */ |
||||
|
"quickapp" : {}, |
||||
|
/* 小程序特有相关 */ |
||||
|
"mp-weixin" : { |
||||
|
"appid" : "wx6b37987f8de3af0f", |
||||
|
"setting" : { |
||||
|
"urlCheck" : false |
||||
|
}, |
||||
|
"usingComponents" : true, |
||||
|
"permission" : { |
||||
|
"scope.userLocation" : { |
||||
|
"desc" : "您的位置信息将用于地图定位和附近地点展示" |
||||
|
} |
||||
|
}, |
||||
|
"lazyCodeLoading" : "requiredComponents" |
||||
|
}, |
||||
|
"mp-alipay" : { |
||||
|
"usingComponents" : true |
||||
|
}, |
||||
|
"mp-baidu" : { |
||||
|
"usingComponents" : true |
||||
|
}, |
||||
|
"mp-toutiao" : { |
||||
|
"usingComponents" : true |
||||
|
}, |
||||
|
"uniStatistics" : { |
||||
|
"enable" : false |
||||
|
}, |
||||
|
"vueVersion" : "3" |
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
{ |
||||
|
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages |
||||
|
{ |
||||
|
"path": "pages/index/index", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "挑好厂|找周边工作" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "pages/searchPositions/searchPositions", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "岗位搜索" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path": "pages/my/my", |
||||
|
"style": { |
||||
|
"navigationBarTitleText": "个人中心" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path" : "pages/map/map", |
||||
|
"style" : |
||||
|
{ |
||||
|
"navigationBarTitleText" : "地图" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path" : "pages/positionDetail/positionDetail", |
||||
|
"style" : |
||||
|
{ |
||||
|
"navigationBarTitleText" : "岗位详情" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"path" : "pages/login/login", |
||||
|
"style" : |
||||
|
{ |
||||
|
"navigationBarTitleText" : "登录" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
], |
||||
|
"globalStyle": { |
||||
|
"navigationBarTextStyle": "black", |
||||
|
"navigationBarTitleText": "uni-app", |
||||
|
"navigationBarBackgroundColor": "#F8F8F8", |
||||
|
"backgroundColor": "#F8F8F8" |
||||
|
}, |
||||
|
"tabBar": { |
||||
|
"list": [ |
||||
|
{ |
||||
|
"text": "首页", |
||||
|
"pagePath": "pages/index/index", |
||||
|
"iconPath": "/static/tabbarIcon/home.png", |
||||
|
"selectedIconPath": "/static/tabbarIcon/home-select.png" |
||||
|
}, |
||||
|
{ |
||||
|
"text": "搜岗位", |
||||
|
"pagePath": "pages/searchPositions/searchPositions", |
||||
|
"iconPath": "/static/tabbarIcon/searchPositions.png", |
||||
|
"selectedIconPath": "/static/tabbarIcon/searchPositions-select.png" |
||||
|
}, |
||||
|
{ |
||||
|
"text": "我的", |
||||
|
"pagePath": "pages/my/my", |
||||
|
"iconPath": "/static/tabbarIcon/my.png", |
||||
|
"selectedIconPath": "/static/tabbarIcon/my-select.png" |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
"uniIdRouter": {} |
||||
|
} |
||||
@ -0,0 +1,111 @@ |
|||||
|
<template> |
||||
|
<view class="index-page"> |
||||
|
<map style="height: 100vh; width: 100vw;" id="myMap" :markers="markers" show-location show-compass |
||||
|
@updated="handleMapLoad"></map> |
||||
|
<view class="rec-swiper"> |
||||
|
<recruitment></recruitment> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
companyData: [{ |
||||
|
label: '薪资', |
||||
|
value: '20', |
||||
|
unit: '', |
||||
|
exLabel: '元/小时' |
||||
|
}, |
||||
|
{ |
||||
|
label: '年龄', |
||||
|
value: '20-42', |
||||
|
unit: '', |
||||
|
exLabel: '元/小时' |
||||
|
}, |
||||
|
{ |
||||
|
label: '吃饭', |
||||
|
value: '2', |
||||
|
unit: '餐', |
||||
|
exLabel: '白-夜' |
||||
|
}, |
||||
|
{ |
||||
|
label: '住宿', |
||||
|
value: '20', |
||||
|
unit: '', |
||||
|
exLabel: '人间' |
||||
|
}, |
||||
|
], |
||||
|
markers: [{ |
||||
|
id: 1, |
||||
|
latitude: 39.90923, |
||||
|
longitude: 116.397428, |
||||
|
title: '模拟点位1', |
||||
|
iconPath: '/static/position-icon.png', |
||||
|
width: 30, |
||||
|
height: 30, |
||||
|
label: { |
||||
|
content: '模拟点位1', |
||||
|
textAlign: 'center', |
||||
|
fontSize: 18, |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
id: 2, |
||||
|
latitude: 39.8, |
||||
|
longitude: 116.3, |
||||
|
title: '模拟点位1', |
||||
|
iconPath: '/static/position-icon.png', |
||||
|
width: 30, |
||||
|
height: 30, |
||||
|
label: { |
||||
|
content: '模拟点位1', |
||||
|
textAlign: 'center', |
||||
|
fontSize: 18, |
||||
|
} |
||||
|
}, |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
onLoad() { |
||||
|
// 页面加载时的初始化逻辑 |
||||
|
}, |
||||
|
methods: { |
||||
|
handleMapLoad() { |
||||
|
console.log('地图加载完成'); |
||||
|
// 获取地图上下文 |
||||
|
const mapContext = uni.createMapContext('myMap'); |
||||
|
// 设置地图中心点到第一个标记点 |
||||
|
mapContext.includePoints({ |
||||
|
points: this.markers.map(marker => ({ |
||||
|
latitude: marker.latitude, |
||||
|
longitude: marker.longitude |
||||
|
})), |
||||
|
padding: [50, 50, 200, 50] // 边距设置 |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
.index-page { |
||||
|
height: 100vh; |
||||
|
overflow: hidden; |
||||
|
position: relative; |
||||
|
|
||||
|
.rec-swiper { |
||||
|
width: calc(100% - 16px); |
||||
|
// height: 200px; |
||||
|
// background-color: red; |
||||
|
background-color: #FFF; |
||||
|
margin: 0 8px; |
||||
|
position: absolute; |
||||
|
left: 0px; |
||||
|
bottom: 8px; |
||||
|
border-radius: 16px; |
||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,275 @@ |
|||||
|
<template> |
||||
|
<view class="login-page"> |
||||
|
<!-- 顶部装饰元素 --> |
||||
|
<view class="top-decoration"> |
||||
|
<view class="circle circle-1"></view> |
||||
|
<view class="circle circle-2"></view> |
||||
|
<view class="circle circle-3"></view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- Logo区域 --> |
||||
|
<view class="logo-section"> |
||||
|
<image class="logo" src="/static/logo.png" mode="aspectFit"></image> |
||||
|
<text class="app-title">劳务地图</text> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 登录按钮区域 --> |
||||
|
<view class="login-section"> |
||||
|
<button class="wechat-login-btn" open-type="getPhoneNumber" @getphonenumber="onWechatLogin"> |
||||
|
<image class="wechat-icon" src="/static/wechat-icon.png" mode="aspectFit"></image> |
||||
|
<text class="btn-text">微信一键登录</text> |
||||
|
</button> |
||||
|
{{ loginRes }} |
||||
|
<view class="agreement-section"> |
||||
|
<label class="checkbox-wrapper"> |
||||
|
<checkbox :checked="agreeChecked" @tap="toggleAgreement" color="#07c160" /> |
||||
|
<text class="agreement-text">我已阅读并同意</text> |
||||
|
</label> |
||||
|
<text class="agreement-link" @tap="showAgreement">《用户协议》</text> |
||||
|
<text class="agreement-text">和</text> |
||||
|
<text class="agreement-link" @tap="showPrivacyPolicy">《隐私政策》</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 底部装饰 --> |
||||
|
<view class="bottom-decoration"></view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { computed, ref } from 'vue'; |
||||
|
import { userLogin } from '../../api'; |
||||
|
import { useUserStore } from '../../stores/user.js'; |
||||
|
// 用户协议勾选状态 |
||||
|
const agreeChecked = ref(false); |
||||
|
|
||||
|
// 获取用户 store 实例 |
||||
|
const userStore = useUserStore(); |
||||
|
const loginRes = computed(() => userStore.loginRes); |
||||
|
|
||||
|
// 微信登录处理 |
||||
|
const onWechatLogin = (e) => { |
||||
|
// 检查用户是否同意协议 |
||||
|
if (!agreeChecked.value) { |
||||
|
uni.showToast({ |
||||
|
title: '请先同意用户协议和隐私政策', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 显示加载提示 |
||||
|
uni.showLoading({ |
||||
|
title: '登录中...' |
||||
|
}); |
||||
|
|
||||
|
// 获取微信登录凭证 |
||||
|
uni.login({ |
||||
|
provider: 'weixin', |
||||
|
success: async (wxLoginRes) => { |
||||
|
try { |
||||
|
console.log('微信登录成功', wxLoginRes); |
||||
|
const code = wxLoginRes.code; |
||||
|
const loginRes = await userLogin({ code }); |
||||
|
console.log('登录接口返回:', loginRes); |
||||
|
|
||||
|
// 隐藏加载提示 |
||||
|
uni.hideLoading(); |
||||
|
|
||||
|
// 使用 Pinia 存储 loginRes 数据 |
||||
|
userStore.setLoginRes(loginRes.data); |
||||
|
console.log('loginRes 已存储到 Pinia:', loginRes.data); |
||||
|
// 登录成功提示 |
||||
|
uni.showToast({ |
||||
|
title: '登录成功', |
||||
|
icon: 'success' |
||||
|
}); |
||||
|
|
||||
|
// 跳转到首页 |
||||
|
setTimeout(() => { |
||||
|
uni.switchTab({ |
||||
|
url: '/pages/index/index' |
||||
|
}); |
||||
|
}, 1000); |
||||
|
} catch (error) { |
||||
|
// 隐藏加载提示 |
||||
|
uni.hideLoading(); |
||||
|
|
||||
|
console.error('登录过程出错', error); |
||||
|
uni.showToast({ |
||||
|
title: '登录过程出错,请重试', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
fail: (err) => { |
||||
|
// 隐藏加载提示 |
||||
|
uni.hideLoading(); |
||||
|
|
||||
|
console.error('微信登录失败', err); |
||||
|
uni.showToast({ |
||||
|
title: '微信登录失败,请重试', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 切换用户协议勾选状态 |
||||
|
const toggleAgreement = () => { |
||||
|
agreeChecked.value = !agreeChecked.value; |
||||
|
}; |
||||
|
|
||||
|
// 显示用户协议 |
||||
|
const showAgreement = () => { |
||||
|
uni.showToast({ |
||||
|
title: '用户协议', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 显示隐私政策 |
||||
|
const showPrivacyPolicy = () => { |
||||
|
uni.showToast({ |
||||
|
title: '隐私政策', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
.login-page { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
min-height: 100vh; |
||||
|
background: linear-gradient(135deg, #f5f7fa 0%, #e4edf9 100%); |
||||
|
padding: 20px; |
||||
|
|
||||
|
// 顶部装饰 |
||||
|
.top-decoration { |
||||
|
position: relative; |
||||
|
height: 120px; |
||||
|
margin-bottom: 40px; |
||||
|
|
||||
|
.circle { |
||||
|
position: absolute; |
||||
|
border-radius: 50%; |
||||
|
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); |
||||
|
opacity: 0.1; |
||||
|
|
||||
|
&.circle-1 { |
||||
|
width: 80px; |
||||
|
height: 80px; |
||||
|
top: 0; |
||||
|
right: 10%; |
||||
|
} |
||||
|
|
||||
|
&.circle-2 { |
||||
|
width: 120px; |
||||
|
height: 120px; |
||||
|
top: -20px; |
||||
|
left: 5%; |
||||
|
} |
||||
|
|
||||
|
&.circle-3 { |
||||
|
width: 60px; |
||||
|
height: 60px; |
||||
|
bottom: 0; |
||||
|
right: 25%; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Logo区域 |
||||
|
.logo-section { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
margin-bottom: 60px; |
||||
|
|
||||
|
.logo { |
||||
|
width: 100px; |
||||
|
height: 100px; |
||||
|
margin-bottom: 20px; |
||||
|
} |
||||
|
|
||||
|
.app-title { |
||||
|
font-size: 24px; |
||||
|
font-weight: bold; |
||||
|
color: #333; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 登录区域 |
||||
|
.login-section { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
|
||||
|
.wechat-login-btn { |
||||
|
width: 80%; |
||||
|
height: 50px; |
||||
|
background: #07c160; |
||||
|
border-radius: 25px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
margin-bottom: 30px; |
||||
|
box-shadow: 0 4px 10px rgba(7, 193, 96, 0.3); |
||||
|
|
||||
|
.wechat-icon { |
||||
|
width: 24px; |
||||
|
height: 24px; |
||||
|
margin-right: 10px; |
||||
|
} |
||||
|
|
||||
|
.btn-text { |
||||
|
color: white; |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
&::after { |
||||
|
border: none; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 协议区域 |
||||
|
.agreement-section { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
flex-wrap: wrap; |
||||
|
justify-content: center; |
||||
|
padding: 0 20px; |
||||
|
|
||||
|
.checkbox-wrapper { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-right: 5px; |
||||
|
|
||||
|
.agreement-text { |
||||
|
margin-left: 5px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.agreement-text { |
||||
|
font-size: 12px; |
||||
|
color: #999; |
||||
|
margin: 0 2px; |
||||
|
} |
||||
|
|
||||
|
.agreement-link { |
||||
|
font-size: 12px; |
||||
|
color: #07c160; |
||||
|
text-decoration: underline; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 底部装饰 |
||||
|
.bottom-decoration { |
||||
|
height: 60px; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,238 @@ |
|||||
|
<template> |
||||
|
<view class="container"> |
||||
|
<!-- 悬浮卡片 --> |
||||
|
<view v-if="showCard" class="float-card"> |
||||
|
<view class="card-title">{{ selectedMarker.title }}</view> |
||||
|
<view class="card-info"> |
||||
|
<text>纬度:{{ selectedMarker.latitude }}</text> |
||||
|
<text>经度:{{ selectedMarker.longitude }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 地图中心经纬度信息 --> |
||||
|
<view class="map-center-info"> |
||||
|
<text>地图中心:</text> |
||||
|
<text>纬度:{{ mapCenter.latitude.toFixed(6) }}</text> |
||||
|
<text>经度:{{ mapCenter.longitude.toFixed(6) }}</text> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 地图组件 --> |
||||
|
<map style="height: 100vh; width: 100vw;" |
||||
|
id="myMap" |
||||
|
name="" |
||||
|
@updated="handleMapLoad" |
||||
|
@markertap="handleMarkerTap" |
||||
|
@regionchange="handleRegionChange" |
||||
|
show-compass |
||||
|
:markers="markers" |
||||
|
show-location></map> |
||||
|
|
||||
|
<!-- 添加Marker表单 --> |
||||
|
<view class="form-container"> |
||||
|
<view class="form-title">添加新标记</view> |
||||
|
<view class="form-item"> |
||||
|
<text>位置名称:</text> |
||||
|
<input v-model="newMarker.title" type="text" placeholder="请输入位置名称"/> |
||||
|
</view> |
||||
|
<view class="form-item"> |
||||
|
<text>纬度:</text> |
||||
|
<input v-model.number="newMarker.latitude" type="digit" placeholder="请输入纬度"/> |
||||
|
</view> |
||||
|
<view class="form-item"> |
||||
|
<text>经度:</text> |
||||
|
<input v-model.number="newMarker.longitude" type="digit" placeholder="请输入经度"/> |
||||
|
</view> |
||||
|
<button @click="addMarker" type="primary">添加标记</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
markers: [{ |
||||
|
id: 1, |
||||
|
latitude: 39.90923, |
||||
|
longitude: 116.397428, |
||||
|
title: '北京天安门', |
||||
|
iconPath: '/static/logo.png', |
||||
|
width: 30, |
||||
|
height: 30 |
||||
|
}], |
||||
|
showCard: false, |
||||
|
selectedMarker: {}, |
||||
|
newMarker: { |
||||
|
title: '', |
||||
|
latitude: 0, |
||||
|
longitude: 0 |
||||
|
}, |
||||
|
mapCenter: { |
||||
|
latitude: 39.90923, |
||||
|
longitude: 116.397428 |
||||
|
}, |
||||
|
mapContext: null |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
handleMapLoad() { |
||||
|
console.log("地图加载完成!") |
||||
|
// 获取地图上下文 |
||||
|
this.mapContext = uni.createMapContext('myMap'); |
||||
|
// 获取初始地图中心经纬度 |
||||
|
this.getMapCenter(); |
||||
|
}, |
||||
|
// 处理地图区域变化事件 |
||||
|
handleRegionChange(e) { |
||||
|
// 当用户拖动地图结束时获取地图中心经纬度 |
||||
|
if (e.type === 'end') { |
||||
|
this.getMapCenter(); |
||||
|
} |
||||
|
}, |
||||
|
// 获取地图中心经纬度 |
||||
|
getMapCenter() { |
||||
|
if (this.mapContext) { |
||||
|
this.mapContext.getCenterLocation({ |
||||
|
success: (res) => { |
||||
|
this.mapCenter = { |
||||
|
latitude: res.latitude, |
||||
|
longitude: res.longitude |
||||
|
}; |
||||
|
console.log('当前地图中心经纬度:', this.mapCenter); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
// 处理Marker点击事件 |
||||
|
handleMarkerTap(e) { |
||||
|
const markerId = e.markerId; |
||||
|
const marker = this.markers.find(item => item.id === markerId); |
||||
|
if (marker) { |
||||
|
this.selectedMarker = { ...marker }; |
||||
|
this.showCard = true; |
||||
|
} |
||||
|
}, |
||||
|
// 添加新的Marker |
||||
|
addMarker() { |
||||
|
if (!this.newMarker.title || !this.newMarker.latitude || !this.newMarker.longitude) { |
||||
|
uni.showToast({ |
||||
|
title: '请填写完整信息', |
||||
|
icon: 'none' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const newMarker = { |
||||
|
id: this.markers.length + 1, |
||||
|
title: this.newMarker.title, |
||||
|
latitude: this.newMarker.latitude, |
||||
|
longitude: this.newMarker.longitude, |
||||
|
iconPath: '/static/logo.png', |
||||
|
width: 30, |
||||
|
height: 30 |
||||
|
}; |
||||
|
|
||||
|
this.markers.push(newMarker); |
||||
|
|
||||
|
// 重置表单 |
||||
|
this.newMarker = { |
||||
|
title: '', |
||||
|
latitude: 0, |
||||
|
longitude: 0 |
||||
|
}; |
||||
|
|
||||
|
uni.showToast({ |
||||
|
title: '添加成功', |
||||
|
icon: 'success' |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.container { |
||||
|
position: relative; |
||||
|
height: 100vh; |
||||
|
} |
||||
|
/* 悬浮卡片样式 */ |
||||
|
.float-card { |
||||
|
position: absolute; |
||||
|
top: 20px; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
width: 80%; |
||||
|
max-width: 400px; |
||||
|
background: rgba(255, 255, 255, 0.9); |
||||
|
border-radius: 10px; |
||||
|
padding: 15px; |
||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
||||
|
z-index: 999; |
||||
|
} |
||||
|
.card-title { |
||||
|
font-size: 18px; |
||||
|
font-weight: bold; |
||||
|
margin-bottom: 10px; |
||||
|
} |
||||
|
.card-info { |
||||
|
font-size: 14px; |
||||
|
color: #666; |
||||
|
} |
||||
|
.card-info text { |
||||
|
display: block; |
||||
|
margin: 5px 0; |
||||
|
} |
||||
|
/* 表单样式 */ |
||||
|
.form-container { |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
background: rgba(255, 255, 255, 0.95); |
||||
|
padding: 20px; |
||||
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
.form-title { |
||||
|
font-size: 18px; |
||||
|
font-weight: bold; |
||||
|
margin-bottom: 15px; |
||||
|
text-align: center; |
||||
|
} |
||||
|
.form-item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-bottom: 15px; |
||||
|
} |
||||
|
.form-item text { |
||||
|
width: 80px; |
||||
|
} |
||||
|
.form-item input { |
||||
|
flex: 1; |
||||
|
height: 40px; |
||||
|
border: 1px solid #ddd; |
||||
|
border-radius: 5px; |
||||
|
padding: 0 10px; |
||||
|
} |
||||
|
button { |
||||
|
margin-top: 10px; |
||||
|
} |
||||
|
/* 地图中心经纬度信息样式 */ |
||||
|
.map-center-info { |
||||
|
position: absolute; |
||||
|
top: 100px; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
width: 80%; |
||||
|
max-width: 400px; |
||||
|
background: rgba(255, 255, 255, 0.9); |
||||
|
border-radius: 10px; |
||||
|
padding: 10px 15px; |
||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
||||
|
z-index: 998; |
||||
|
} |
||||
|
.map-center-info text { |
||||
|
display: inline-block; |
||||
|
font-size: 14px; |
||||
|
margin-right: 10px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,151 @@ |
|||||
|
<template> |
||||
|
<view class="my-page"> |
||||
|
<!-- 登录区域 --> |
||||
|
<view class="login-section" @click="loginRegister"> |
||||
|
<view class="avatar"> |
||||
|
<text class="avatar-icon">😊</text> |
||||
|
</view> |
||||
|
<view class="login-text"> |
||||
|
<text class="login-title">点击登录/注册</text> |
||||
|
<text class="login-subtitle">登录查看更多消息</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 功能区域 --> |
||||
|
<view class="features-section"> |
||||
|
<view class="feature-item" @click="myComments"> |
||||
|
<view class="feature-icon"> |
||||
|
<text class="icon-content">📝</text> |
||||
|
</view> |
||||
|
<text class="feature-name">我的评价</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="feature-item" @click="myFavorites"> |
||||
|
<view class="feature-icon"> |
||||
|
<text class="icon-content">❤️</text> |
||||
|
</view> |
||||
|
<text class="feature-name">收藏岗位</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="feature-item" @click="contactService"> |
||||
|
<view class="feature-icon"> |
||||
|
<text class="icon-content">📞</text> |
||||
|
</view> |
||||
|
<text class="feature-name">咨询客服</text> |
||||
|
</view> |
||||
|
</view>123 |
||||
|
{{loginRes}} |
||||
|
<!-- 底部占位,避免内容被底部导航栏遮挡 --> |
||||
|
<view class="bottom-space"></view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { computed } from 'vue'; |
||||
|
import { useUserStore } from '../../stores/user.js'; |
||||
|
const userStore = useUserStore(); |
||||
|
const loginRes = computed(() => userStore.loginRes); |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
.my-page { |
||||
|
background-color: #fff; |
||||
|
min-height: 100vh; |
||||
|
padding-top: 12px; // 增加顶部内边距,避免内容紧贴导航栏 |
||||
|
|
||||
|
// 登录区域 |
||||
|
.login-section { |
||||
|
background-color: #fff; |
||||
|
padding: 20px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
tap-highlight-color: transparent; |
||||
|
|
||||
|
.avatar { |
||||
|
width: 60px; |
||||
|
height: 60px; |
||||
|
border-radius: 30px; |
||||
|
background-color: #e6f7ff; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
margin-right: 16px; |
||||
|
|
||||
|
.avatar-icon { |
||||
|
font-size: 30px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.login-text { |
||||
|
.login-title { |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
color: #333; |
||||
|
display: block; |
||||
|
margin-bottom: 4px; |
||||
|
} |
||||
|
|
||||
|
.login-subtitle { |
||||
|
font-size: 14px; |
||||
|
color: #999; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 功能区域 |
||||
|
.features-section { |
||||
|
background-color: #fff; |
||||
|
padding: 16px 0; |
||||
|
display: flex; |
||||
|
justify-content: space-around; |
||||
|
|
||||
|
.feature-item { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
padding: 8px; |
||||
|
tap-highlight-color: transparent; |
||||
|
|
||||
|
.feature-icon { |
||||
|
width: 50px; |
||||
|
height: 50px; |
||||
|
border-radius: 12px; |
||||
|
background-color: #f0f9ff; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
margin-bottom: 8px; |
||||
|
|
||||
|
.icon-content { |
||||
|
font-size: 24px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.feature-name { |
||||
|
font-size: 14px; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
// 为不同的功能图标设置不同的背景色 |
||||
|
&:nth-child(1) .feature-icon { |
||||
|
background-color: #e6f7ff; |
||||
|
} |
||||
|
|
||||
|
&:nth-child(2) .feature-icon { |
||||
|
background-color: #fff1f0; |
||||
|
} |
||||
|
|
||||
|
&:nth-child(3) .feature-icon { |
||||
|
background-color: #f0f9ff; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 底部占位,避免内容被底部导航栏遮挡 |
||||
|
.bottom-space { |
||||
|
height: 60px; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,419 @@ |
|||||
|
<template> |
||||
|
<view class="position-detail-page"> |
||||
|
<!-- 主内容区域 - 可滚动 --> |
||||
|
<view class="content-wrapper"> |
||||
|
<!-- 顶部信息区域 --> |
||||
|
<view class="header-section"> |
||||
|
<view class="factory-info"> |
||||
|
<text class="factory-name">安费诺</text> |
||||
|
<text class="factory-type">电子厂</text> |
||||
|
<text class="distance">距你2.5km</text> |
||||
|
</view> |
||||
|
<button class="call-btn" @click="makeCall">拨打电话</button> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 工作时间区域 --> |
||||
|
<view class="work-time-section"> |
||||
|
<text class="time">8:00-20:00 两班倒</text> |
||||
|
<text class="business">主营汽车线束</text> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 薪资信息区域 --> |
||||
|
<view class="salary-section"> |
||||
|
<view class="salary-item"> |
||||
|
<text class="item-title">小时工</text> |
||||
|
<text class="salary-content">工资: 20+1元/小时(含1元满勤)+绩效奖金高达500,月薪6500-7500</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="salary-item"> |
||||
|
<text class="item-title">正式工</text> |
||||
|
<text class="salary-content">工资2490元/月+夜班补贴10元/晚+"表现佳有绩效+超产奖金" 平时加班1.5倍,双休日2倍,国假日3倍等,月收入5700-6800/月</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 福利信息区域 --> |
||||
|
<view class="benefits-section"> |
||||
|
<text class="benefits-content">转正满2个月体检费196元企业报销(凭发票)</text> |
||||
|
<text class="benefits-content">有部分为显微镜工作,显微镜工作额外有0-300的岗位补贴(具体以厂区发放为准抱拳)</text> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 分隔线 --> |
||||
|
<view class="divider"></view> |
||||
|
|
||||
|
<!-- 用户评价区域 --> |
||||
|
<view class="comments-section"> |
||||
|
<view class="section-title">用户评价</view> |
||||
|
|
||||
|
<!-- 动态渲染评价列表 --> |
||||
|
<view class="comment-item" v-for="(comment, index) in comments" :key="comment.id"> |
||||
|
<view class="user-info"> |
||||
|
<view class="avatar"></view> |
||||
|
<text class="username">{{ comment.username }}</text> |
||||
|
</view> |
||||
|
<text class="comment-content">{{ comment.content }}</text> |
||||
|
<view class="image-container"> |
||||
|
<view class="comment-image"></view> |
||||
|
<view class="comment-image"></view> |
||||
|
<view class="comment-image"></view> |
||||
|
</view> |
||||
|
<view class="like-section"> |
||||
|
<text class="like-count">{{ comment.likes }}</text> |
||||
|
<text class="like-icon" :class="{ active: comment.isLiked }" @click="toggleLike(index)">👍</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 如果评价数量大于1,显示分隔线 --> |
||||
|
<view class="comment-divider" v-if="comments.length > 1"></view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 底部空间,确保内容不被底部按钮遮挡 --> |
||||
|
<view class="bottom-space"></view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 底部固定操作按钮 --> |
||||
|
<view class="bottom-action"> |
||||
|
<button class="apply-btn" @click="applyJob">立即申请</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
// 职位数据 |
||||
|
comments: [ |
||||
|
{ |
||||
|
id: 1, |
||||
|
username: '网友120489', |
||||
|
content: '工作很轻松,基本都是手上的活', |
||||
|
likes: 6, |
||||
|
isLiked: false |
||||
|
}, |
||||
|
{ |
||||
|
id: 2, |
||||
|
username: '网友120489', |
||||
|
content: '工作很轻松,基本都是手上的活', |
||||
|
likes: 6, |
||||
|
isLiked: true |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
// 返回上一页 |
||||
|
goBack() { |
||||
|
uni.navigateBack(); |
||||
|
}, |
||||
|
// 拨打电话功能 |
||||
|
makeCall() { |
||||
|
uni.makePhoneCall({ |
||||
|
phoneNumber: '400-123-4567' |
||||
|
}); |
||||
|
}, |
||||
|
// 点赞/取消点赞 |
||||
|
toggleLike(index) { |
||||
|
if (this.comments[index].isLiked) { |
||||
|
// 取消点赞 |
||||
|
this.comments[index].likes--; |
||||
|
} else { |
||||
|
// 点赞 |
||||
|
this.comments[index].likes++; |
||||
|
} |
||||
|
// 切换点赞状态 |
||||
|
this.comments[index].isLiked = !this.comments[index].isLiked; |
||||
|
}, |
||||
|
// 申请职位 |
||||
|
applyJob() { |
||||
|
uni.showToast({ |
||||
|
title: '申请成功,请保持电话畅通', |
||||
|
icon: 'success' |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
.position-detail-page { |
||||
|
// 页面背景色 |
||||
|
background-color: #f5f5f5; |
||||
|
height: 100vh; |
||||
|
overflow: hidden; |
||||
|
|
||||
|
// 导航栏 |
||||
|
.nav-bar { |
||||
|
height: 44px; |
||||
|
background-color: #fff; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
padding: 0 16px; |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
z-index: 100; |
||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); |
||||
|
|
||||
|
.back-btn { |
||||
|
width: 40px; |
||||
|
height: 40px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
font-size: 20px; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.nav-title { |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.nav-right { |
||||
|
width: 40px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 内容包装器 |
||||
|
.content-wrapper { |
||||
|
overflow-y: auto; |
||||
|
max-height: calc(100vh); |
||||
|
padding-bottom: 70px; // 为底部操作按钮留出空间 |
||||
|
} |
||||
|
|
||||
|
// 底部空间,确保内容不被底部按钮遮挡 |
||||
|
.bottom-space { |
||||
|
height: 20px; |
||||
|
} |
||||
|
|
||||
|
// 头部信息区域 |
||||
|
.header-section { |
||||
|
background-color: #fff; |
||||
|
padding: 16px; |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
|
||||
|
.factory-info { |
||||
|
.factory-name { |
||||
|
font-size: 18px; |
||||
|
font-weight: 600; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.factory-type { |
||||
|
font-size: 14px; |
||||
|
color: #0099ff; |
||||
|
background-color: #e6f7ff; |
||||
|
padding: 2px 6px; |
||||
|
border-radius: 4px; |
||||
|
margin-left: 8px; |
||||
|
} |
||||
|
|
||||
|
.distance { |
||||
|
font-size: 14px; |
||||
|
color: #999; |
||||
|
margin-left: 12px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.call-btn { |
||||
|
height: 36px; |
||||
|
padding: 0 16px; |
||||
|
background-color: #ff4757; |
||||
|
color: white; |
||||
|
font-size: 14px; |
||||
|
border: none; |
||||
|
border-radius: 18px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 工作时间区域 |
||||
|
.work-time-section { |
||||
|
background-color: #fff; |
||||
|
padding: 12px 16px; |
||||
|
margin-top: 8px; |
||||
|
|
||||
|
.time, |
||||
|
.business { |
||||
|
font-size: 14px; |
||||
|
color: #666; |
||||
|
margin-right: 16px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 薪资信息区域 |
||||
|
.salary-section { |
||||
|
background-color: #fff; |
||||
|
padding: 16px; |
||||
|
margin-top: 8px; |
||||
|
|
||||
|
.salary-item { |
||||
|
margin-bottom: 16px; |
||||
|
|
||||
|
&:last-child { |
||||
|
margin-bottom: 0; |
||||
|
} |
||||
|
|
||||
|
.item-title { |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
color: #333; |
||||
|
margin-bottom: 8px; |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
.salary-content { |
||||
|
font-size: 14px; |
||||
|
color: #666; |
||||
|
line-height: 1.6; |
||||
|
white-space: pre-wrap; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 福利信息区域 |
||||
|
.benefits-section { |
||||
|
background-color: #fff; |
||||
|
padding: 16px; |
||||
|
margin-top: 8px; |
||||
|
|
||||
|
.benefits-content { |
||||
|
font-size: 14px; |
||||
|
color: #666; |
||||
|
line-height: 1.6; |
||||
|
margin-bottom: 8px; |
||||
|
display: block; |
||||
|
|
||||
|
&:last-child { |
||||
|
margin-bottom: 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 分隔线 |
||||
|
.divider { |
||||
|
height: 12px; |
||||
|
background-color: #f5f5f5; |
||||
|
margin-top: 8px; |
||||
|
} |
||||
|
|
||||
|
// 用户评价区域 |
||||
|
.comments-section { |
||||
|
background-color: #fff; |
||||
|
padding-top: 12px; |
||||
|
|
||||
|
.section-title { |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
color: #333; |
||||
|
padding: 0 16px 12px; |
||||
|
} |
||||
|
|
||||
|
.comment-item { |
||||
|
padding: 16px; |
||||
|
|
||||
|
.user-info { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-bottom: 12px; |
||||
|
|
||||
|
.avatar { |
||||
|
width: 36px; |
||||
|
height: 36px; |
||||
|
border-radius: 50%; |
||||
|
background-color: #ddd; |
||||
|
margin-right: 12px; |
||||
|
} |
||||
|
|
||||
|
.username { |
||||
|
font-size: 14px; |
||||
|
color: #333; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.comment-content { |
||||
|
font-size: 15px; |
||||
|
color: #333; |
||||
|
line-height: 1.6; |
||||
|
margin-bottom: 12px; |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
.image-container { |
||||
|
display: flex; |
||||
|
margin-bottom: 12px; |
||||
|
|
||||
|
.comment-image { |
||||
|
width: 80px; |
||||
|
height: 80px; |
||||
|
background-color: #eee; |
||||
|
border-radius: 4px; |
||||
|
margin-right: 12px; |
||||
|
|
||||
|
&:last-child { |
||||
|
margin-right: 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.like-section { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: flex-end; |
||||
|
|
||||
|
.like-count { |
||||
|
font-size: 14px; |
||||
|
color: #999; |
||||
|
margin-right: 4px; |
||||
|
} |
||||
|
|
||||
|
.like-icon { |
||||
|
font-size: 16px; |
||||
|
cursor: pointer; |
||||
|
|
||||
|
&.active { |
||||
|
color: #ff4757; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.comment-divider { |
||||
|
height: 1px; |
||||
|
background-color: #eee; |
||||
|
margin: 0 16px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 底部固定操作按钮 |
||||
|
.bottom-action { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
height: 50px; |
||||
|
background-color: #fff; |
||||
|
padding: 8px 16px; |
||||
|
box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1); |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
z-index: 99; |
||||
|
|
||||
|
.apply-btn { |
||||
|
height: 40px; |
||||
|
width: 100%; |
||||
|
background-color: #ff4757; |
||||
|
color: white; |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
border: none; |
||||
|
border-radius: 20px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,262 @@ |
|||||
|
<template> |
||||
|
<view class="search-positions-page"> |
||||
|
<!-- 搜索区域 --> |
||||
|
<view class="search-header"> |
||||
|
<view class="search-input-wrapper"> |
||||
|
<input type="text" v-model="searchKeyword" placeholder="请输入关键词" class="search-input" /> |
||||
|
<button class="search-btn" @click="onSearch">搜索</button> |
||||
|
</view> |
||||
|
<!-- 搜索标签 --> |
||||
|
<view class="search-tags"> |
||||
|
<view class="tag" :class="{ active: activeTag === '长白班' }" @click="onTagClick('长白班')">长白班</view> |
||||
|
<view class="tag" :class="{ active: activeTag === '高工资' }" @click="onTagClick('高工资')">高工资</view> |
||||
|
<view class="tag" :class="{ active: activeTag === '包吃住' }" @click="onTagClick('包吃住')">包吃住</view> |
||||
|
<view class="tag" :class="{ active: activeTag === '日结' }" @click="onTagClick('日结')">日结</view> |
||||
|
<view class="tag" :class="{ active: activeTag === '大龄工' }" @click="onTagClick('大龄工')">大龄工</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="search-list" :refresher-enabled="true" :refresher-triggered="refreshing" @refresherrefresh="onRefresh" @scrolltolower="onLoadMore"> |
||||
|
<template v-for="item in list.records" :key="item.jobId"> |
||||
|
<recruitment :dataSource="item"></recruitment> |
||||
|
<view class="driver"></view> |
||||
|
</template> |
||||
|
<view class="loading-more"> |
||||
|
<text v-if="loadingMore">加载中...</text> |
||||
|
<text v-else-if="noMoreData">没有更多数据了</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
onLoad |
||||
|
} from '@dcloudio/uni-app' |
||||
|
import { |
||||
|
getAppJobVO |
||||
|
} from '../../api'; |
||||
|
import { |
||||
|
ref |
||||
|
} from 'vue'; |
||||
|
const list = ref([]) |
||||
|
const searchKeyword = ref('') |
||||
|
const refreshing = ref(false) |
||||
|
const loadingMore = ref(false) |
||||
|
const noMoreData = ref(false) |
||||
|
const currentPage = ref(1) |
||||
|
const pageSize = ref(10) |
||||
|
|
||||
|
const hanleGetJobList = async (params = {}) => { |
||||
|
const res = await getAppJobVO({ |
||||
|
pageNum: currentPage.value, |
||||
|
pageSize: pageSize.value, |
||||
|
...params |
||||
|
}) |
||||
|
console.log(res) |
||||
|
|
||||
|
if (currentPage.value === 1) { |
||||
|
// 刷新或首次加载 |
||||
|
list.value = res.data |
||||
|
} else { |
||||
|
// 加载更多 |
||||
|
list.value.records = [...list.value.records, ...res.data.records] |
||||
|
} |
||||
|
|
||||
|
// 检查是否还有更多数据 |
||||
|
if (res.data.records.length < pageSize.value) { |
||||
|
noMoreData.value = true |
||||
|
} else { |
||||
|
noMoreData.value = false |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
onLoad(() => { |
||||
|
currentPage.value = 1 |
||||
|
hanleGetJobList() |
||||
|
}) |
||||
|
|
||||
|
const onRefresh = async () => { |
||||
|
refreshing.value = true |
||||
|
currentPage.value = 1 |
||||
|
noMoreData.value = false |
||||
|
try { |
||||
|
await hanleGetJobList() |
||||
|
uni.showToast({ |
||||
|
title: '刷新成功', |
||||
|
icon: 'success' |
||||
|
}) |
||||
|
} catch (error) { |
||||
|
uni.showToast({ |
||||
|
title: '刷新失败', |
||||
|
icon: 'none' |
||||
|
}) |
||||
|
} finally { |
||||
|
refreshing.value = false |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const onLoadMore = async () => { |
||||
|
// 如果已经在加载或没有更多数据,则不执行 |
||||
|
if (loadingMore.value || noMoreData.value) return |
||||
|
|
||||
|
loadingMore.value = true |
||||
|
currentPage.value++ |
||||
|
|
||||
|
try { |
||||
|
await hanleGetJobList() |
||||
|
} catch (error) { |
||||
|
uni.showToast({ |
||||
|
title: '加载失败', |
||||
|
icon: 'none' |
||||
|
}) |
||||
|
currentPage.value-- |
||||
|
} finally { |
||||
|
loadingMore.value = false |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const onSearch = () => { |
||||
|
console.log(searchKeyword.value) |
||||
|
const params = { |
||||
|
jobName: searchKeyword.value |
||||
|
} |
||||
|
// 搜索时重置到第一页 |
||||
|
currentPage.value = 1 |
||||
|
noMoreData.value = false |
||||
|
hanleGetJobList(params) |
||||
|
} |
||||
|
/* // 导入recruitment组件 |
||||
|
import recruitment from '@/components/recruitment/recruitment.vue'; |
||||
|
export default { |
||||
|
// 注册组件 |
||||
|
components: { |
||||
|
recruitment |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
searchKeyword: '', |
||||
|
activeTag: '' |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
// 搜索方法 |
||||
|
onSearch() { |
||||
|
// 实现搜索逻辑 |
||||
|
console.log('搜索关键词:', this.searchKeyword); |
||||
|
}, |
||||
|
// 标签点击方法 |
||||
|
onTagClick(tag) { |
||||
|
this.activeTag = this.activeTag === tag ? '' : tag; |
||||
|
console.log('点击标签:', tag); |
||||
|
} |
||||
|
} |
||||
|
} */ |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
.search-positions-page { |
||||
|
// 页面容器设置 |
||||
|
height: 100vh; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
background-color: #f8f8f8; |
||||
|
|
||||
|
// 搜索头部样式 - 固定在顶部 |
||||
|
.search-header { |
||||
|
padding: 12px 16px; |
||||
|
background-color: #fff; |
||||
|
z-index: 10; |
||||
|
|
||||
|
// 搜索框包装器 |
||||
|
.search-input-wrapper { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-bottom: 12px; |
||||
|
|
||||
|
// 搜索输入框 |
||||
|
.search-input { |
||||
|
flex: 1; |
||||
|
height: 32px; |
||||
|
background-color: #f5f5f5; |
||||
|
border-radius: 20px 0 0 20px; |
||||
|
padding: 0 16px; |
||||
|
border: none; |
||||
|
font-size: 14px; |
||||
|
color: #333; |
||||
|
outline: none; |
||||
|
|
||||
|
&::placeholder { |
||||
|
color: #999; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 搜索按钮 |
||||
|
.search-btn { |
||||
|
height: 32px; |
||||
|
width: 80px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
background-color: #ff4757; |
||||
|
color: white; |
||||
|
border: none; |
||||
|
border-radius: 0 20px 20px 0; |
||||
|
font-size: 14px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 搜索标签区域 |
||||
|
.search-tags { |
||||
|
display: flex; |
||||
|
gap: 12px; |
||||
|
flex-wrap: wrap; |
||||
|
|
||||
|
// 标签样式 |
||||
|
.tag { |
||||
|
padding: 4px 8px; |
||||
|
border: 1px solid #ddd; |
||||
|
border-radius: 8px; |
||||
|
font-size: 12px; |
||||
|
color: #666; |
||||
|
background-color: white; |
||||
|
|
||||
|
// 选中状态 |
||||
|
&.active { |
||||
|
color: #ff4757; |
||||
|
border-color: #ff4757; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 列表样式 - 可滚动区域 |
||||
|
.search-list { |
||||
|
padding: 4px; |
||||
|
flex: 1; |
||||
|
overflow-y: auto; |
||||
|
|
||||
|
// 隐藏滚动条但保留滚动功能 |
||||
|
::-webkit-scrollbar { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
-ms-overflow-style: none; |
||||
|
scrollbar-width: none; |
||||
|
} |
||||
|
|
||||
|
.driver { |
||||
|
width: 100%; |
||||
|
height: 1px; |
||||
|
background-color: #eee; |
||||
|
} |
||||
|
|
||||
|
.loading-more { |
||||
|
text-align: center; |
||||
|
padding: 16px 0; |
||||
|
font-size: 14px; |
||||
|
color: #999; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 894 B |
|
After Width: | Height: | Size: 845 B |
|
After Width: | Height: | Size: 516 B |
|
After Width: | Height: | Size: 505 B |
|
After Width: | Height: | Size: 629 B |
|
After Width: | Height: | Size: 610 B |
|
After Width: | Height: | Size: 873 B |
@ -0,0 +1,64 @@ |
|||||
|
import { defineStore } from 'pinia'; |
||||
|
|
||||
|
export const useUserStore = defineStore('user', { |
||||
|
state: () => ({ |
||||
|
loginRes: uni.getStorageSync('loginRes') || null, // 存储登录响应数据
|
||||
|
userInfo: uni.getStorageSync('userInfo') || null, // 用户信息
|
||||
|
token: uni.getStorageSync('token') || null // 认证令牌
|
||||
|
}), |
||||
|
|
||||
|
getters: { |
||||
|
isLoggedIn: (state) => !!state.token, |
||||
|
userId: (state) => state.userInfo?.userId || null |
||||
|
}, |
||||
|
|
||||
|
actions: { |
||||
|
/** |
||||
|
* 设置登录响应数据 |
||||
|
* @param {Object} data - 登录响应数据 |
||||
|
*/ |
||||
|
setLoginRes(data) { |
||||
|
this.loginRes = data; |
||||
|
uni.setStorageSync('loginRes', data); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 设置用户信息 |
||||
|
* @param {Object} userInfo - 用户信息 |
||||
|
*/ |
||||
|
setUserInfo(userInfo) { |
||||
|
this.userInfo = userInfo; |
||||
|
uni.setStorageSync('userInfo', userInfo); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 设置认证令牌 |
||||
|
* @param {String} token - 认证令牌 |
||||
|
*/ |
||||
|
setToken(token) { |
||||
|
this.token = token; |
||||
|
uni.setStorageSync('token', token); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 清除所有用户数据 |
||||
|
*/ |
||||
|
clearUserData() { |
||||
|
this.loginRes = null; |
||||
|
this.userInfo = null; |
||||
|
this.token = null; |
||||
|
uni.removeStorageSync('loginRes'); |
||||
|
uni.removeStorageSync('userInfo'); |
||||
|
uni.removeStorageSync('token'); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 更新用户信息 |
||||
|
* @param {Object} updates - 要更新的用户信息字段 |
||||
|
*/ |
||||
|
updateUserInfo(updates) { |
||||
|
this.userInfo = { ...this.userInfo, ...updates }; |
||||
|
uni.setStorageSync('userInfo', this.userInfo); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
@ -0,0 +1,13 @@ |
|||||
|
uni.addInterceptor({ |
||||
|
returnValue (res) { |
||||
|
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { |
||||
|
return res; |
||||
|
} |
||||
|
return new Promise((resolve, reject) => { |
||||
|
res.then((res) => { |
||||
|
if (!res) return resolve(res) |
||||
|
return res[0] ? reject(res[0]) : resolve(res[1]) |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
}); |
||||
@ -0,0 +1,76 @@ |
|||||
|
/** |
||||
|
* 这里是uni-app内置的常用样式变量 |
||||
|
* |
||||
|
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 |
||||
|
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App |
||||
|
* |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 |
||||
|
* |
||||
|
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 |
||||
|
*/ |
||||
|
|
||||
|
/* 颜色变量 */ |
||||
|
|
||||
|
/* 行为相关颜色 */ |
||||
|
$uni-color-primary: #6DC2AA; |
||||
|
$uni-color-success: #4cd964; |
||||
|
$uni-color-warning: #f0ad4e; |
||||
|
$uni-color-error: #dd524d; |
||||
|
|
||||
|
/* 文字基本颜色 */ |
||||
|
$uni-text-color:#333;//基本色 |
||||
|
$uni-text-color-inverse:#fff;//反色 |
||||
|
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 |
||||
|
$uni-text-color-placeholder: #808080; |
||||
|
$uni-text-color-disable:#c0c0c0; |
||||
|
|
||||
|
/* 背景颜色 */ |
||||
|
$uni-bg-color:#ffffff; |
||||
|
$uni-bg-color-grey:#f8f8f8; |
||||
|
$uni-bg-color-hover:#f1f1f1;//点击状态颜色 |
||||
|
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 |
||||
|
|
||||
|
/* 边框颜色 */ |
||||
|
$uni-border-color:#c8c7cc; |
||||
|
|
||||
|
/* 尺寸变量 */ |
||||
|
|
||||
|
/* 文字尺寸 */ |
||||
|
$uni-font-size-sm:12px; |
||||
|
$uni-font-size-base:14px; |
||||
|
$uni-font-size-lg:16px; |
||||
|
|
||||
|
/* 图片尺寸 */ |
||||
|
$uni-img-size-sm:20px; |
||||
|
$uni-img-size-base:26px; |
||||
|
$uni-img-size-lg:40px; |
||||
|
|
||||
|
/* Border Radius */ |
||||
|
$uni-border-radius-sm: 2px; |
||||
|
$uni-border-radius-base: 3px; |
||||
|
$uni-border-radius-lg: 6px; |
||||
|
$uni-border-radius-circle: 50%; |
||||
|
|
||||
|
/* 水平间距 */ |
||||
|
$uni-spacing-row-sm: 5px; |
||||
|
$uni-spacing-row-base: 10px; |
||||
|
$uni-spacing-row-lg: 15px; |
||||
|
|
||||
|
/* 垂直间距 */ |
||||
|
$uni-spacing-col-sm: 4px; |
||||
|
$uni-spacing-col-base: 8px; |
||||
|
$uni-spacing-col-lg: 12px; |
||||
|
|
||||
|
/* 透明度 */ |
||||
|
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 |
||||
|
|
||||
|
/* 文章场景相关 */ |
||||
|
$uni-color-title: #2C405A; // 文章标题颜色 |
||||
|
$uni-font-size-title:20px; |
||||
|
$uni-color-subtitle: #555555; // 二级标题颜色 |
||||
|
$uni-font-size-subtitle:26px; |
||||
|
$uni-color-paragraph: #3F536E; // 文章段落颜色 |
||||
|
$uni-font-size-paragraph:15px; |
||||