commit 33a32482d016af6d2580b34888859c992f8d4191 Author: wk Date: Fri Dec 19 20:27:55 2025 +0800 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a6bc614 --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +# 依赖 +node_modules/ +package-lock.json +yarn.lock + +# 编译输出 +unpackage/ +dist/ + +# 系统文件 +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# 历史记录 +.history/ + +# 日志 +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# 环境变量 +.env +.env.local +.env.*.local + +# 临时文件 +*.tmp +*.temp diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..935025d --- /dev/null +++ b/App.vue @@ -0,0 +1,52 @@ + + + diff --git a/api/auth.js b/api/auth.js new file mode 100644 index 0000000..86fcdef --- /dev/null +++ b/api/auth.js @@ -0,0 +1,55 @@ +/** + * 认证相关接口 + */ + +import { request } from './index.js' + +/** + * 账户密码登录 + * @param {Object} data 登录数据 + * @param {String} data.mobile 手机号 + * @param {String} data.password 密码 + * @returns {Promise} 返回登录结果(包含token等) + */ +export function login(data) { + return request({ + url: '/app-api/member/auth/login', + method: 'POST', + data: data, + showLoading: true, + needAuth: false // 登录接口不需要token认证 + }) +} + +/** + * 小程序一键授权手机号登录 + * @param {Object} data 登录数据 + * @param {String} data.code 微信授权code + * @param {String} data.encryptedData 加密数据 + * @param {String} data.iv 初始向量 + * @returns {Promise} 返回登录结果(包含token等) + */ +export function loginByPhone(data) { + return request({ + url: '/app-api/member/auth/login', + method: 'POST', + data: data, + showLoading: true, + needAuth: false // 登录接口不需要token认证 + }) +} + +/** + * 刷新token + * @param {String} refreshToken 刷新令牌 + * @returns {Promise} 返回新的token信息 + */ +export function refreshToken(refreshToken) { + return request({ + url: '/app-api/member/auth/refresh', // 根据实际接口调整 + method: 'POST', + data: { refreshToken }, + showLoading: false, + needAuth: false // 刷新token接口不需要accessToken认证 + }) +} diff --git a/api/home.js b/api/home.js new file mode 100644 index 0000000..6acb4c1 --- /dev/null +++ b/api/home.js @@ -0,0 +1,102 @@ +/** + * 首页相关接口 + */ + +import { request } from './index.js' + +/** + * 获取首页数据 + * @param {Object} params 查询参数 + * @param {Number} params.noticeType 通知类型 + * @returns {Promise} 返回首页数据(招募信息、公会福利、公会活动等) + */ +export function getHomeData(params = {}) { + return request({ + url: '/app-api/member/labor-union-notice/page', + method: 'GET', + data: params, + showLoading: true + }) +} + +/** + * 获取公会福利列表 + * @param {Object} params 查询参数 + * @returns {Promise} 返回公会福利列表 + */ +export function getGuildBenefits(params = {}) { + return request({ + url: '/api/guild/benefits', + method: 'GET', + data: params + }) +} + +/** + * 获取公会活动列表 + * @param {Object} params 查询参数 + * @param {Number} params.page 页码 + * @param {Number} params.pageSize 每页数量 + * @returns {Promise} 返回公会活动列表 + */ +export function getGuildActivities(params = {}) { + return request({ + url: '/api/guild/activities', + method: 'GET', + data: { + page: params.page || 1, + pageSize: params.pageSize || 10, + ...params + } + }) +} + +/** + * 获取工会详情 + * @param {Number} id 工会ID + * @returns {Promise} 返回工会详情 + */ +export function getGuildDetail(id) { + return request({ + url: '/app-api/member/labor-union-notice/get', + method: 'GET', + data: { + id: id + } + }) +} + +/** + * 加入工会 + * @param {Object} data 加入工会的数据 + * @returns {Promise} 返回加入结果 + */ +export function joinGuild(data = {}) { + return request({ + url: '/api/guild/join', + method: 'POST', + data: data, + showLoading: true, + needAuth: true + }) +} + +/** + * 参与活动 + * @param {String|Object} activityIdOrData 活动ID或包含活动ID的对象 + * @returns {Promise} 返回参与结果 + */ +export function joinActivity(activityIdOrData) { + // 兼容传入字符串ID或对象的情况 + const data = typeof activityIdOrData === 'string' + ? { activityId: activityIdOrData } + : activityIdOrData + + return request({ + url: '/api/activity/join', + method: 'POST', + data: data, + showLoading: true, + needAuth: true + }) +} \ No newline at end of file diff --git a/api/index.js b/api/index.js new file mode 100644 index 0000000..cab1196 --- /dev/null +++ b/api/index.js @@ -0,0 +1,319 @@ +/** + * 接口请求封装 + * 统一处理请求拦截、响应拦截、错误处理、token管理等 + */ + +// 基础URL配置(注意:末尾不要加斜杠) +const BASE_URL = 'https://siji.chenjuncn.top' + +// 是否正在刷新token(防止并发刷新) +let isRefreshing = false +// 等待刷新完成的请求队列 +let refreshSubscribers = [] + +/** + * 刷新token + * @param {String} refreshToken 刷新令牌 + * @returns {Promise} 返回刷新结果 + */ +function refreshAccessToken(refreshToken) { + if (isRefreshing) { + // 如果正在刷新,返回一个Promise,等待刷新完成 + return new Promise((resolve, reject) => { + refreshSubscribers.push({ resolve, reject }) + }) + } + + isRefreshing = true + + return new Promise((resolve, reject) => { + // 构建完整URL + const fullUrl = `${BASE_URL}/app-api/member/auth/refresh` + + // 构建请求头 + const requestHeader = { + 'Content-Type': 'application/json', + 'tenant-id': '1' + } + + // 发起刷新请求 + uni.request({ + url: fullUrl, + method: 'POST', + data: { refreshToken }, + header: requestHeader, + success: (res) => { + if (res.statusCode === 200 && res.data) { + // 处理响应数据 + const responseData = res.data + if (responseData.code === 0 || responseData.code === 200) { + const data = responseData.data || responseData + + // 保存新的token + const token = data?.accessToken || data?.token || data?.access_token + if (token) { + uni.setStorageSync('token', token) + } + + // 保存新的refreshToken(如果有) + const newRefreshToken = data?.refreshToken + if (newRefreshToken) { + uni.setStorageSync('refreshToken', newRefreshToken) + } + + // 保存新的过期时间 + const expiresTime = data?.expiresTime + if (expiresTime) { + uni.setStorageSync('tokenExpiresTime', expiresTime) + } + + // 通知所有等待的请求 + refreshSubscribers.forEach(subscriber => subscriber.resolve()) + refreshSubscribers = [] + isRefreshing = false + + resolve(data) + } else { + // 刷新失败 + const errorMsg = responseData.message || responseData.msg || '刷新token失败' + refreshSubscribers.forEach(subscriber => subscriber.reject(new Error(errorMsg))) + refreshSubscribers = [] + isRefreshing = false + reject(new Error(errorMsg)) + } + } else { + // 刷新失败 + refreshSubscribers.forEach(subscriber => subscriber.reject(new Error('刷新token失败'))) + refreshSubscribers = [] + isRefreshing = false + reject(new Error('刷新token失败')) + } + }, + fail: (err) => { + // 刷新失败 + refreshSubscribers.forEach(subscriber => subscriber.reject(err)) + refreshSubscribers = [] + isRefreshing = false + reject(err) + } + }) + }) +} + +/** + * 统一请求方法 + * @param {Object} options 请求配置 + * @param {String} options.url 请求地址(相对路径,会自动拼接BASE_URL) + * @param {String} options.method 请求方法,默认GET + * @param {Object} options.data 请求参数 + * @param {Object} options.header 请求头 + * @param {Boolean} options.showLoading 是否显示loading,默认false + * @param {Boolean} options.needAuth 是否需要token认证,默认true + * @returns {Promise} 返回处理后的响应数据 + */ +export function request(options = {}) { + return new Promise((resolve, reject) => { + const { + url, + method = 'GET', + data = {}, + header = {}, + showLoading = false, + needAuth = true + } = options + + // 显示loading + if (showLoading) { + uni.showLoading({ + title: '加载中...', + mask: true + }) + } + + // 构建完整URL(处理BASE_URL末尾斜杠问题) + const fullUrl = url.startsWith('http') ? url : `${BASE_URL}${url.startsWith('/') ? url : '/' + url}` + + // 构建请求头 + const requestHeader = { + 'Content-Type': 'application/json', + 'tenant-id': '1', // 统一添加租户ID + ...header + } + + // 添加token(如果需要认证) + if (needAuth) { + const token = uni.getStorageSync('token') + if (token) { + requestHeader['Authorization'] = `Bearer ${token}` + } + } + + // 发起请求 + uni.request({ + url: fullUrl, + method: method.toUpperCase(), + data: data, + header: requestHeader, + success: (res) => { + // 隐藏loading + if (showLoading) { + uni.hideLoading() + } + + // 统一处理响应 + if (res.statusCode === 200) { + // 根据实际后端返回的数据结构处理 + // 如果后端返回格式为 { code: 200, data: {}, message: '' } + if (res.data && typeof res.data === 'object') { + // 如果后端有统一的code字段 + if (res.data.code !== undefined) { + // 处理业务错误码401(账号未登录) + if (res.data.code === 401) { + // 显示登录弹窗 + uni.showModal({ + title: '提示', + content: res.data.msg || res.data.message || '账号未登录,请前往登录', + showCancel: false, + confirmText: '去登录', + success: (modalRes) => { + if (modalRes.confirm) { + // 清除本地存储的登录信息 + uni.removeStorageSync('token') + uni.removeStorageSync('refreshToken') + uni.removeStorageSync('tokenExpiresTime') + uni.removeStorageSync('userId') + uni.removeStorageSync('userInfo') + // 跳转到登录页面 + uni.navigateTo({ + url: '/pages/login/login' + }) + } + } + }) + reject(new Error('未授权')) + return + } + if (res.data.code === 200 || res.data.code === 0) { + resolve(res.data.data || res.data) + } else { + // 业务错误 + const errorMsg = res.data.message || res.data.msg || '请求失败' + uni.showToast({ + title: errorMsg, + icon: 'none', + duration: 2000 + }) + reject(new Error(errorMsg)) + } + } else { + // 没有code字段,直接返回data + resolve(res.data) + } + } else { + resolve(res.data) + } + } else if (res.statusCode === 401) { + // token过期或未登录,尝试使用refreshToken刷新 + const refreshToken = uni.getStorageSync('refreshToken') + if (refreshToken) { + // 尝试刷新token + refreshAccessToken(refreshToken) + .then(() => { + // 刷新成功,重新发起原请求 + return request(options) + }) + .then(resolve) + .catch(() => { + // 刷新失败,显示登录弹窗 + const errorMsg = res.data?.msg || res.data?.message || '账号未登录,请前往登录' + uni.showModal({ + title: '提示', + content: errorMsg, + showCancel: false, + confirmText: '去登录', + success: (modalRes) => { + if (modalRes.confirm) { + // 清除token,跳转到登录页 + uni.removeStorageSync('token') + uni.removeStorageSync('refreshToken') + uni.removeStorageSync('tokenExpiresTime') + uni.removeStorageSync('userId') + uni.removeStorageSync('userInfo') + uni.navigateTo({ + url: '/pages/login/login' + }) + } + } + }) + reject(new Error('未授权')) + }) + } else { + // 没有refreshToken,显示登录弹窗 + const errorMsg = res.data?.msg || res.data?.message || '账号未登录,请前往登录' + uni.showModal({ + title: '提示', + content: errorMsg, + showCancel: false, + confirmText: '去登录', + success: (modalRes) => { + if (modalRes.confirm) { + // 清除token,跳转到登录页 + uni.removeStorageSync('token') + uni.removeStorageSync('refreshToken') + uni.removeStorageSync('tokenExpiresTime') + uni.removeStorageSync('userId') + uni.removeStorageSync('userInfo') + uni.navigateTo({ + url: '/pages/login/login' + }) + } + } + }) + reject(new Error('未授权')) + } + } else if (res.statusCode >= 500) { + // 服务器错误 + uni.showToast({ + title: '服务器错误,请稍后重试', + icon: 'none' + }) + reject(new Error('服务器错误')) + } else { + // 其他错误 + const errorMsg = res.data?.message || res.data?.msg || `请求失败(${res.statusCode})` + uni.showToast({ + title: errorMsg, + icon: 'none' + }) + reject(new Error(errorMsg)) + } + }, + fail: (err) => { + // 隐藏loading + if (showLoading) { + uni.hideLoading() + } + + // 网络错误处理 + let errorMsg = '网络请求失败' + if (err.errMsg) { + if (err.errMsg.includes('timeout')) { + errorMsg = '请求超时,请检查网络' + } else if (err.errMsg.includes('fail')) { + errorMsg = '网络连接失败,请检查网络设置' + } + } + + uni.showToast({ + title: errorMsg, + icon: 'none', + duration: 2000 + }) + + reject(err) + } + }) + }) +} + + diff --git a/api/profile.js b/api/profile.js new file mode 100644 index 0000000..bf87b24 --- /dev/null +++ b/api/profile.js @@ -0,0 +1,62 @@ +/** + * 个人中心相关接口 + */ + +import { request } from './index.js' + +/** + * 获取个人信息 + * @returns {Promise} 返回用户信息 + */ +export function getUserInfo() { + return request({ + url: '/app-api/member/user/get', + method: 'GET', + showLoading: false, + needAuth: true // 需要token认证 + }) +} + +// 创建实名信息 +export function createRealNameInfo(data) { + return request({ + url: '/app-api/member/user-real-name/addAndUpdate', + method: 'POST', + data: data, + showLoading: false, + needAuth: true // 需要token认证 + }) +} + +// 我的收藏 +export function getMyCollect(data) { + return request({ + url: '/app-api/member/labor-union-collect/page', + method: 'GET', + data: data, + showLoading: false, + needAuth: true // 需要token认证 + }) +} + +// 创建会员建议 +export function createLaborUnionSuggest(data) { + return request({ + url: '/app-api/member/labor-union-suggest/create', + method: 'POST', + data: data, + showLoading: false, + needAuth: true // 需要token认证 + }) +} + +// 发布消息 +export function createLaborUnionMessage(data) { + return request({ + url: '/app-api/member/labor-union-message/create', + method: 'POST', + data: data, + showLoading: false, + needAuth: true // 需要token认证 + }) +} \ No newline at end of file diff --git a/api/service.js b/api/service.js new file mode 100644 index 0000000..66d8a22 --- /dev/null +++ b/api/service.js @@ -0,0 +1,40 @@ +import { request } from './index.js' + +// 司机工会服务分类 -- 字典 +export function getDictDataByType(params = {}) { + return request({ + url: '/app-api/system/dict-data/type', + method: 'GET', + data: params, + }) +} + +// 获得工会商店分页 +export function getGuildStorePage(params = {}) { + return request({ + url: '/app-api/member/labor-union-shop/page', + method: 'GET', + data: params, + }) +} + + +// 获得工会商店详情 +export function getGuildStoreDetail(id) { + return request({ + url: `/app-api/member/labor-union-shop/get`, + method: 'GET', + data: { + id: id, + }, + }) +} + +// 获得工会优惠券 +export function getGuildCoupon(params = {}) { + return request({ + url: '/app-api/member/labor-union-coupon/page', + method: 'GET', + data: params, + }) +} \ No newline at end of file diff --git a/components/NavHeader/NavHeader.vue b/components/NavHeader/NavHeader.vue new file mode 100644 index 0000000..f2990ce --- /dev/null +++ b/components/NavHeader/NavHeader.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..c3ff205 --- /dev/null +++ b/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + +
+ + + diff --git a/main.js b/main.js new file mode 100644 index 0000000..c1caf36 --- /dev/null +++ b/main.js @@ -0,0 +1,22 @@ +import App from './App' + +// #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) + return { + app + } +} +// #endif \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..3a78ffa --- /dev/null +++ b/manifest.json @@ -0,0 +1,75 @@ +{ + "name" : "demo", + "appid" : "__UNI__B358CDA", + "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" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : {}, + /* SDK配置 */ + "sdkConfigs" : {} + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true, + "requiredPrivateInfos" : [ + "getLocation" + ] + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "3" +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..7d91f20 --- /dev/null +++ b/pages.json @@ -0,0 +1,141 @@ +{ + "pages": [ + { + "path": "pages/login/login", + "style": { + "navigationBarTitleText": "登录", + "navigationStyle": "custom" + } + }, + { + "path": "pages/index/index", + "style": { + "navigationBarTitleText": "首页", + "navigationStyle": "custom" + } + }, + { + "path": "pages/service/service", + "style": { + "navigationBarTitleText": "服务", + "navigationStyle": "custom" + } + }, + { + "path": "pages/profile/profile", + "style": { + "navigationBarTitleText": "个人中心", + "navigationStyle": "custom" + } + }, + { + "path": "pages/profile/realNameAuth", + "style": { + "navigationBarTitleText": "实名认证", + "navigationStyle": "custom" + } + }, + { + "path": "pages/profile/serviceRecords", + "style": { + "navigationBarTitleText": "服务记录", + "navigationStyle": "custom" + } + } + ], + "subPackages": [ + { + "root": "pages/detail", + "pages": [ + { + "path": "serviceDetail", + "style": { + "navigationBarTitleText": "店铺详情", + "navigationStyle": "custom" + } + }, + { + "path": "activitiesDetail", + "style": { + "navigationBarTitleText": "工会详情", + "navigationStyle": "custom" + } + }, + { + "path": "mapDetail", + "style": { + "navigationBarTitleText": "地图", + "navigationStyle": "custom" + } + } + ] + }, + { + "root": "pages/activities", + "pages": [ + { + "path": "list", + "style": { + "navigationBarTitleText": "工会活动", + "navigationStyle": "custom" + } + }, + { + "path": "myCollect", + "style": { + "navigationBarTitleText": "我的收藏", + "navigationStyle": "custom" + } + }, + { + "path": "complaints", + "style": { + "navigationBarTitleText": "投诉建议", + "navigationStyle": "custom" + } + }, + { + "path": "postMessage", + "style": { + "navigationBarTitleText": "发布消息", + "navigationStyle": "custom" + } + } + ] + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "uni-app", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + }, + "tabBar": { + "color": "#7A7E83", + "selectedColor": "#004294", + "borderStyle": "black", + "backgroundColor": "#ffffff", + "iconWidth": "41rpx", + "list": [ + { + "pagePath": "pages/index/index", + "iconPath": "static/tabbar/home.png", + "selectedIconPath": "static/tabbar/home-active.png", + "text": "首页" + }, + { + "pagePath": "pages/service/service", + "iconPath": "static/tabbar/service.png", + "selectedIconPath": "static/tabbar/service-active.png", + "text": "服务" + }, + { + "pagePath": "pages/profile/profile", + "iconPath": "static/tabbar/profile.png", + "selectedIconPath": "static/tabbar/profile-active.png", + "text": "我的" + } + ] + }, + "uniIdRouter": {} +} diff --git a/pages/activities/complaints.vue b/pages/activities/complaints.vue new file mode 100644 index 0000000..38d2c77 --- /dev/null +++ b/pages/activities/complaints.vue @@ -0,0 +1,263 @@ + + + + + diff --git a/pages/activities/list.vue b/pages/activities/list.vue new file mode 100644 index 0000000..5530e70 --- /dev/null +++ b/pages/activities/list.vue @@ -0,0 +1,332 @@ + + + + + diff --git a/pages/activities/myCollect.vue b/pages/activities/myCollect.vue new file mode 100644 index 0000000..30c3cac --- /dev/null +++ b/pages/activities/myCollect.vue @@ -0,0 +1,317 @@ + + + + + diff --git a/pages/activities/postMessage.vue b/pages/activities/postMessage.vue new file mode 100644 index 0000000..b49b9c6 --- /dev/null +++ b/pages/activities/postMessage.vue @@ -0,0 +1,617 @@ + + + + + diff --git a/pages/detail/activitiesDetail.vue b/pages/detail/activitiesDetail.vue new file mode 100644 index 0000000..cf11e0f --- /dev/null +++ b/pages/detail/activitiesDetail.vue @@ -0,0 +1,204 @@ + + + + + diff --git a/pages/detail/mapDetail.vue b/pages/detail/mapDetail.vue new file mode 100644 index 0000000..8435892 --- /dev/null +++ b/pages/detail/mapDetail.vue @@ -0,0 +1,492 @@ + + + + + diff --git a/pages/detail/serviceDetail.vue b/pages/detail/serviceDetail.vue new file mode 100644 index 0000000..dc0af5d --- /dev/null +++ b/pages/detail/serviceDetail.vue @@ -0,0 +1,607 @@ + + + + + + \ No newline at end of file diff --git a/pages/index/index.vue b/pages/index/index.vue new file mode 100644 index 0000000..d2b2113 --- /dev/null +++ b/pages/index/index.vue @@ -0,0 +1,577 @@ + + + + + diff --git a/pages/login/login.vue b/pages/login/login.vue new file mode 100644 index 0000000..67f1eca --- /dev/null +++ b/pages/login/login.vue @@ -0,0 +1,523 @@ + + + + + diff --git a/pages/profile/profile.vue b/pages/profile/profile.vue new file mode 100644 index 0000000..cf39331 --- /dev/null +++ b/pages/profile/profile.vue @@ -0,0 +1,456 @@ + + + + + + diff --git a/pages/profile/realNameAuth.vue b/pages/profile/realNameAuth.vue new file mode 100644 index 0000000..e9edddb --- /dev/null +++ b/pages/profile/realNameAuth.vue @@ -0,0 +1,579 @@ + + + + + diff --git a/pages/profile/serviceRecords.vue b/pages/profile/serviceRecords.vue new file mode 100644 index 0000000..c2bdd11 --- /dev/null +++ b/pages/profile/serviceRecords.vue @@ -0,0 +1,684 @@ + + + + + diff --git a/pages/service/service.vue b/pages/service/service.vue new file mode 100644 index 0000000..7a7beb7 --- /dev/null +++ b/pages/service/service.vue @@ -0,0 +1,861 @@ + + + + + \ No newline at end of file diff --git a/static/home/activity_icon.png b/static/home/activity_icon.png new file mode 100644 index 0000000..3197c1e Binary files /dev/null and b/static/home/activity_icon.png differ diff --git a/static/home/banner.png b/static/home/banner.png new file mode 100644 index 0000000..f0b5190 Binary files /dev/null and b/static/home/banner.png differ diff --git a/static/home/car_insurance.png b/static/home/car_insurance.png new file mode 100644 index 0000000..cc8b2d6 Binary files /dev/null and b/static/home/car_insurance.png differ diff --git a/static/home/entry_icon.png b/static/home/entry_icon.png new file mode 100644 index 0000000..be3d991 Binary files /dev/null and b/static/home/entry_icon.png differ diff --git a/static/home/food_menu.png b/static/home/food_menu.png new file mode 100644 index 0000000..103e1d7 Binary files /dev/null and b/static/home/food_menu.png differ diff --git a/static/home/gift_icon.png b/static/home/gift_icon.png new file mode 100644 index 0000000..1b7a9ed Binary files /dev/null and b/static/home/gift_icon.png differ diff --git a/static/home/health.png b/static/home/health.png new file mode 100644 index 0000000..a135b76 Binary files /dev/null and b/static/home/health.png differ diff --git a/static/home/logo.png b/static/home/logo.png new file mode 100644 index 0000000..a42a3cd Binary files /dev/null and b/static/home/logo.png differ diff --git a/static/home/repair.png b/static/home/repair.png new file mode 100644 index 0000000..0a3b10c Binary files /dev/null and b/static/home/repair.png differ diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..b5771e2 Binary files /dev/null and b/static/logo.png differ diff --git a/static/profile/action-card-bg.png b/static/profile/action-card-bg.png new file mode 100644 index 0000000..b06b47a Binary files /dev/null and b/static/profile/action-card-bg.png differ diff --git a/static/profile/avatar-hg.png b/static/profile/avatar-hg.png new file mode 100644 index 0000000..20ad71a Binary files /dev/null and b/static/profile/avatar-hg.png differ diff --git a/static/profile/complaints.png b/static/profile/complaints.png new file mode 100644 index 0000000..3d313d2 Binary files /dev/null and b/static/profile/complaints.png differ diff --git a/static/profile/member-card-bg.png b/static/profile/member-card-bg.png new file mode 100644 index 0000000..8776747 Binary files /dev/null and b/static/profile/member-card-bg.png differ diff --git a/static/profile/my-favorite.png b/static/profile/my-favorite.png new file mode 100644 index 0000000..131dcb6 Binary files /dev/null and b/static/profile/my-favorite.png differ diff --git a/static/profile/publish-message.png b/static/profile/publish-message.png new file mode 100644 index 0000000..4ed9bff Binary files /dev/null and b/static/profile/publish-message.png differ diff --git a/static/profile/user-notice.png b/static/profile/user-notice.png new file mode 100644 index 0000000..ca1d5a6 Binary files /dev/null and b/static/profile/user-notice.png differ diff --git a/static/profile/二维码 (1)@2x.png b/static/profile/二维码 (1)@2x.png new file mode 100644 index 0000000..797fa8c Binary files /dev/null and b/static/profile/二维码 (1)@2x.png differ diff --git a/static/profile/会员权益@2x.png b/static/profile/会员权益@2x.png new file mode 100644 index 0000000..9ebee58 Binary files /dev/null and b/static/profile/会员权益@2x.png differ diff --git a/static/profile/服务记录@2x.png b/static/profile/服务记录@2x.png new file mode 100644 index 0000000..7ad3207 Binary files /dev/null and b/static/profile/服务记录@2x.png differ diff --git a/static/service/crown-icon.png b/static/service/crown-icon.png new file mode 100644 index 0000000..052fa5a Binary files /dev/null and b/static/service/crown-icon.png differ diff --git a/static/service/goBack_icon.png b/static/service/goBack_icon.png new file mode 100644 index 0000000..e444b11 Binary files /dev/null and b/static/service/goBack_icon.png differ diff --git a/static/service/location-arrow.png b/static/service/location-arrow.png new file mode 100644 index 0000000..ed47000 Binary files /dev/null and b/static/service/location-arrow.png differ diff --git a/static/service/location-icon.png b/static/service/location-icon.png new file mode 100644 index 0000000..165883a Binary files /dev/null and b/static/service/location-icon.png differ diff --git a/static/service/search_icon.png b/static/service/search_icon.png new file mode 100644 index 0000000..dee482a Binary files /dev/null and b/static/service/search_icon.png differ diff --git a/static/tabbar/home-active.png b/static/tabbar/home-active.png new file mode 100644 index 0000000..6ab6ec6 Binary files /dev/null and b/static/tabbar/home-active.png differ diff --git a/static/tabbar/home.png b/static/tabbar/home.png new file mode 100644 index 0000000..86b8d5b Binary files /dev/null and b/static/tabbar/home.png differ diff --git a/static/tabbar/profile-active.png b/static/tabbar/profile-active.png new file mode 100644 index 0000000..cebefa8 Binary files /dev/null and b/static/tabbar/profile-active.png differ diff --git a/static/tabbar/profile.png b/static/tabbar/profile.png new file mode 100644 index 0000000..cd5fcd4 Binary files /dev/null and b/static/tabbar/profile.png differ diff --git a/static/tabbar/service-active.png b/static/tabbar/service-active.png new file mode 100644 index 0000000..71e290a Binary files /dev/null and b/static/tabbar/service-active.png differ diff --git a/static/tabbar/service.png b/static/tabbar/service.png new file mode 100644 index 0000000..0d36b73 Binary files /dev/null and b/static/tabbar/service.png differ diff --git a/uni.promisify.adaptor.js b/uni.promisify.adaptor.js new file mode 100644 index 0000000..5fec4f3 --- /dev/null +++ b/uni.promisify.adaptor.js @@ -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]) + }); + }); + }, +}); \ No newline at end of file diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..62eb87b --- /dev/null +++ b/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$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; diff --git a/utils/date.js b/utils/date.js new file mode 100644 index 0000000..f3967fb --- /dev/null +++ b/utils/date.js @@ -0,0 +1,55 @@ +/** + * 时间戳转换工具 + */ + +/** + * 格式化时间戳 + * @param {Number|String} timestamp 时间戳(秒或毫秒) + * @param {String} format 格式化模板,默认 'YYYY.MM.DD HH:mm' + * @returns {String} 格式化后的时间字符串 + */ +export function formatTime(timestamp, format = 'YYYY.MM.DD HH:mm') { + if (!timestamp) { + return ''; + } + + // 将时间戳转换为数字 + let ts = Number(timestamp); + + // 判断是秒级还是毫秒级时间戳(大于10位数是毫秒级) + if (ts.toString().length === 10) { + ts = ts * 1000; + } + + const date = new Date(ts); + + // 检查日期是否有效 + if (isNaN(date.getTime())) { + return ''; + } + + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + + return format + .replace('YYYY', year) + .replace('MM', month) + .replace('DD', day) + .replace('HH', hours) + .replace('mm', minutes) + .replace('ss', seconds); +} + +/** + * 格式化时间戳为默认格式 YYYY.MM.DD HH:mm + * @param {Number|String} timestamp 时间戳 + * @returns {String} 格式化后的时间字符串 + */ +export function formatDateTime(timestamp) { + return formatTime(timestamp, 'YYYY.MM.DD HH:mm'); +} +