fix:微信一键登录+积分转换元
parent
134154715a
commit
15b9d11157
|
|
@ -24,14 +24,15 @@ export function login(data) {
|
|||
/**
|
||||
* 小程序一键授权手机号登录
|
||||
* @param {Object} data 登录数据
|
||||
* @param {String} data.code 微信授权code
|
||||
* @param {String} data.encryptedData 加密数据
|
||||
* @param {String} data.iv 初始向量
|
||||
* @param {String} data.phoneCode 手机 code, 小程序通过 wx.getPhoneNumber 方法获得
|
||||
* @param {String} data.loginCode 登录 code, 小程序通过 wx.login 方法获得
|
||||
* @param {String} data.state state 参数,必填,用于回调的随机值
|
||||
* @param {String} data.inviteCode 邀请码,可选(第一位是类型第二位是用户id,例如:1-1, 0-1)
|
||||
* @returns {Promise} 返回登录结果(包含token等)
|
||||
*/
|
||||
export function loginByPhone(data) {
|
||||
return request({
|
||||
url: '/app-api/member/auth/login',
|
||||
url: '/app-api/member/auth/weixin-mini-app-login',
|
||||
method: 'POST',
|
||||
data: data,
|
||||
showLoading: true,
|
||||
|
|
|
|||
|
|
@ -38,3 +38,12 @@ export function getGuildCoupon(params = {}) {
|
|||
data: params,
|
||||
})
|
||||
}
|
||||
|
||||
// 获得图文消息分页
|
||||
export function getMessagePage(params = {}) {
|
||||
return request({
|
||||
url: '/app-api/member/labor-union-message/page',
|
||||
method: 'GET',
|
||||
data: params,
|
||||
})
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name" : "demo",
|
||||
"appid" : "__UNI__B358CDA",
|
||||
"appid" : "wxa3c0e1381f643f59",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
|
|
@ -50,7 +50,7 @@
|
|||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "",
|
||||
"appid" : "wxa3c0e1381f643f59",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
},
|
||||
|
|
|
|||
51
pages.json
51
pages.json
|
|
@ -1,12 +1,5 @@
|
|||
{
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/login/login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
|
|
@ -14,6 +7,13 @@
|
|||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/service/service",
|
||||
"style": {
|
||||
|
|
@ -29,16 +29,9 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/profile/realNameAuth",
|
||||
"path": "pages/webview/webview",
|
||||
"style": {
|
||||
"navigationBarTitleText": "实名认证",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/profile/serviceRecords",
|
||||
"style": {
|
||||
"navigationBarTitleText": "服务记录",
|
||||
"navigationBarTitleText": "网页",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
|
|
@ -67,6 +60,13 @@
|
|||
"navigationBarTitleText": "地图",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "richTextDetail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -102,6 +102,25 @@
|
|||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/profileSub",
|
||||
"pages": [
|
||||
{
|
||||
"path": "realNameAuth",
|
||||
"style": {
|
||||
"navigationBarTitleText": "实名认证",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "serviceRecords",
|
||||
"style": {
|
||||
"navigationBarTitleText": "服务记录",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ export default {
|
|||
const res = await getHomeData({
|
||||
page: this.page,
|
||||
pageSize: this.pageSize,
|
||||
noticeType: 2, // 活动类型
|
||||
noticeType: 21, // 活动类型
|
||||
});
|
||||
|
||||
if (res) {
|
||||
|
|
@ -159,10 +159,10 @@ export default {
|
|||
|
||||
// 活动项点击
|
||||
handleActivityClick(item) {
|
||||
// 后续可以跳转到活动详情页
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/activities/detail?id=${item.id}`
|
||||
// })
|
||||
// 点击活动项跳转到详情页
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/activitiesDetail?id=${item.id}`
|
||||
});
|
||||
},
|
||||
|
||||
// 参与活动
|
||||
|
|
|
|||
|
|
@ -10,9 +10,21 @@
|
|||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 富文本内容 -->
|
||||
<view class="content-wrapper" v-else-if="activityDetail && activityDetail.content">
|
||||
<rich-text :nodes="activityDetail.content"></rich-text>
|
||||
<!-- 富文本内容 - 混合渲染 -->
|
||||
<view class="content-wrapper" v-else-if="parsedContent && parsedContent.length > 0">
|
||||
<block v-for="(item, index) in parsedContent" :key="index">
|
||||
<!-- 如果是图片,使用原生 image 组件 -->
|
||||
<view v-if="item.type === 'image'" class="rich-text-image-wrapper">
|
||||
<image
|
||||
class="rich-text-image"
|
||||
:src="item.src"
|
||||
mode="widthFix"
|
||||
:lazy-load="true"
|
||||
></image>
|
||||
</view>
|
||||
<!-- 如果是文本内容,使用 rich-text -->
|
||||
<rich-text v-else-if="item.type === 'text'" :nodes="item.html" class="rich-text-content"></rich-text>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!-- 空数据提示 -->
|
||||
|
|
@ -40,6 +52,7 @@ export default {
|
|||
return {
|
||||
activityId: null,
|
||||
activityDetail: null,
|
||||
parsedContent: [], // 解析后的内容数组
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
|
|
@ -69,6 +82,10 @@ export default {
|
|||
const res = await getGuildDetail(this.activityId);
|
||||
if (res) {
|
||||
this.activityDetail = res;
|
||||
// 解析 HTML,分离图片和文本
|
||||
if (res.content) {
|
||||
this.parsedContent = this.parseHtmlContent(res.content);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("加载活动详情失败:", error);
|
||||
|
|
@ -80,6 +97,64 @@ export default {
|
|||
this.loading = false;
|
||||
}
|
||||
},
|
||||
// 解析 HTML 内容,将图片和文本分离
|
||||
parseHtmlContent(html) {
|
||||
if (!html) return [];
|
||||
|
||||
const result = [];
|
||||
let currentIndex = 0;
|
||||
|
||||
// 匹配所有 img 标签
|
||||
const imgRegex = /<img([^>]*)>/gi;
|
||||
let match;
|
||||
let lastIndex = 0;
|
||||
|
||||
while ((match = imgRegex.exec(html)) !== null) {
|
||||
// 添加图片之前的文本内容
|
||||
if (match.index > lastIndex) {
|
||||
const textContent = html.substring(lastIndex, match.index);
|
||||
if (textContent.trim()) {
|
||||
result.push({
|
||||
type: 'text',
|
||||
html: textContent
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 提取图片 src
|
||||
const imgAttrs = match[1];
|
||||
const srcMatch = imgAttrs.match(/src=["']([^"']+)["']/i);
|
||||
if (srcMatch && srcMatch[1]) {
|
||||
result.push({
|
||||
type: 'image',
|
||||
src: srcMatch[1]
|
||||
});
|
||||
}
|
||||
|
||||
lastIndex = match.index + match[0].length;
|
||||
}
|
||||
|
||||
// 添加最后剩余的文本内容
|
||||
if (lastIndex < html.length) {
|
||||
const textContent = html.substring(lastIndex);
|
||||
if (textContent.trim()) {
|
||||
result.push({
|
||||
type: 'text',
|
||||
html: textContent
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有匹配到图片,直接返回整个内容作为文本
|
||||
if (result.length === 0 && html.trim()) {
|
||||
result.push({
|
||||
type: 'text',
|
||||
html: html
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -106,60 +181,40 @@ export default {
|
|||
border-radius: 20rpx;
|
||||
min-height: 200rpx;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
overflow-x: hidden;
|
||||
overflow-y: visible;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
|
||||
// 富文本内容样式
|
||||
:deep(rich-text) {
|
||||
// 图片容器样式
|
||||
.rich-text-image-wrapper {
|
||||
width: 100%;
|
||||
margin: 20rpx 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
.rich-text-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// 文本内容样式
|
||||
.rich-text-content {
|
||||
width: 100%;
|
||||
display: block;
|
||||
font-family: PingFang-SC, PingFang-SC;
|
||||
font-size: 28rpx;
|
||||
line-height: 1.8;
|
||||
color: #333333;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
display: block;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// 富文本内容中的元素样式
|
||||
:deep(img) {
|
||||
max-width: 100% !important;
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
display: block;
|
||||
margin: 20rpx auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:deep(p) {
|
||||
margin: 20rpx 0;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
:deep(h1),
|
||||
:deep(h2),
|
||||
:deep(h3),
|
||||
:deep(h4),
|
||||
:deep(h5),
|
||||
:deep(h6) {
|
||||
margin: 30rpx 0 20rpx 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
:deep(ul),
|
||||
:deep(ol) {
|
||||
margin: 20rpx 0;
|
||||
padding-left: 40rpx;
|
||||
}
|
||||
|
||||
:deep(li) {
|
||||
margin: 10rpx 0;
|
||||
}
|
||||
|
||||
:deep(a) {
|
||||
color: #004294;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
/* 加载状态 */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,239 @@
|
|||
<template>
|
||||
<view class="rich-text-detail-page">
|
||||
<!-- 顶部导航栏 -->
|
||||
<NavHeader :title="title || '详情'" />
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<scroll-view class="content-scroll" scroll-y="true">
|
||||
<!-- 加载中 -->
|
||||
<view class="loading-state" v-if="loading">
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 富文本内容 - 混合渲染 -->
|
||||
<view class="content-wrapper" v-else-if="parsedContent && parsedContent.length > 0">
|
||||
<block v-for="(item, index) in parsedContent" :key="index">
|
||||
<!-- 如果是图片,使用原生 image 组件 -->
|
||||
<view v-if="item.type === 'image'" class="rich-text-image-wrapper">
|
||||
<image
|
||||
class="rich-text-image"
|
||||
:src="item.src"
|
||||
mode="widthFix"
|
||||
:lazy-load="true"
|
||||
></image>
|
||||
</view>
|
||||
<!-- 如果是文本内容,使用 rich-text -->
|
||||
<rich-text v-else-if="item.type === 'text'" :nodes="item.html" class="rich-text-content"></rich-text>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!-- 空数据提示 -->
|
||||
<view class="empty-state" v-else>
|
||||
<image
|
||||
class="empty-icon"
|
||||
src="/static/home/entry_icon.png"
|
||||
mode="aspectFit"
|
||||
></image>
|
||||
<text class="empty-text">暂无内容</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NavHeader from "@/components/NavHeader/NavHeader.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NavHeader
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: '',
|
||||
content: '',
|
||||
parsedContent: [], // 解析后的内容数组
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
// 从路由参数获取标题和内容
|
||||
if (options.title) {
|
||||
this.title = decodeURIComponent(options.title);
|
||||
}
|
||||
|
||||
if (options.content) {
|
||||
let content = decodeURIComponent(options.content);
|
||||
// 解析 HTML,分离图片和文本
|
||||
this.parsedContent = this.parseHtmlContent(content);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "缺少内容",
|
||||
icon: "none",
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 解析 HTML 内容,将图片和文本分离
|
||||
parseHtmlContent(html) {
|
||||
if (!html) return [];
|
||||
|
||||
const result = [];
|
||||
let currentIndex = 0;
|
||||
|
||||
// 匹配所有 img 标签
|
||||
const imgRegex = /<img([^>]*)>/gi;
|
||||
let match;
|
||||
let lastIndex = 0;
|
||||
|
||||
while ((match = imgRegex.exec(html)) !== null) {
|
||||
// 添加图片之前的文本内容
|
||||
if (match.index > lastIndex) {
|
||||
const textContent = html.substring(lastIndex, match.index);
|
||||
if (textContent.trim()) {
|
||||
result.push({
|
||||
type: 'text',
|
||||
html: textContent
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 提取图片 src
|
||||
const imgAttrs = match[1];
|
||||
const srcMatch = imgAttrs.match(/src=["']([^"']+)["']/i);
|
||||
if (srcMatch && srcMatch[1]) {
|
||||
result.push({
|
||||
type: 'image',
|
||||
src: srcMatch[1]
|
||||
});
|
||||
}
|
||||
|
||||
lastIndex = match.index + match[0].length;
|
||||
}
|
||||
|
||||
// 添加最后剩余的文本内容
|
||||
if (lastIndex < html.length) {
|
||||
const textContent = html.substring(lastIndex);
|
||||
if (textContent.trim()) {
|
||||
result.push({
|
||||
type: 'text',
|
||||
html: textContent
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有匹配到图片,直接返回整个内容作为文本
|
||||
if (result.length === 0 && html.trim()) {
|
||||
result.push({
|
||||
type: 'text',
|
||||
html: html
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.rich-text-detail-page {
|
||||
height: 100vh;
|
||||
background-color: #e2e8f1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 内容区域 */
|
||||
.content-scroll {
|
||||
flex: 1;
|
||||
height: 0; // 配合 flex: 1 使用,让 scroll-view 可以滚动
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
padding: 30rpx 20rpx;
|
||||
background-color: #ffffff;
|
||||
margin: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
min-height: 200rpx;
|
||||
box-sizing: border-box;
|
||||
overflow-x: hidden;
|
||||
overflow-y: visible;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
|
||||
// 图片容器样式
|
||||
.rich-text-image-wrapper {
|
||||
width: 100%;
|
||||
margin: 20rpx 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
.rich-text-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// 文本内容样式
|
||||
.rich-text-content {
|
||||
width: 100%;
|
||||
display: block;
|
||||
font-family: PingFang-SC, PingFang-SC;
|
||||
font-size: 28rpx;
|
||||
line-height: 1.8;
|
||||
color: #333333;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
/* 加载状态 */
|
||||
.loading-state {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 200rpx 0;
|
||||
min-height: 500rpx;
|
||||
|
||||
.loading-text {
|
||||
font-family: PingFang-SC, PingFang-SC;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
/* 空数据提示 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 200rpx 0;
|
||||
min-height: 500rpx;
|
||||
|
||||
.empty-icon {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-bottom: 40rpx;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-family: PingFang-SC, PingFang-SC;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -65,10 +65,10 @@
|
|||
<view class="menu-price-row">
|
||||
<view class="current-price">
|
||||
<view class="price-label">现价¥</view>
|
||||
<view class="price-text">{{ item.salePrice || 0 }}</view>
|
||||
<view class="price-text">{{ formatPrice(item.salePrice) }}</view>
|
||||
</view>
|
||||
<text class="original-price" v-if="item.originalPrice"
|
||||
>原价¥{{ item.originalPrice }}</text
|
||||
>原价¥{{ formatPrice(item.originalPrice) }}</text
|
||||
>
|
||||
<view class="quantity-control">
|
||||
<view
|
||||
|
|
@ -139,7 +139,8 @@ export default {
|
|||
totalAmount() {
|
||||
return this.menuList.reduce((total, item) => {
|
||||
if (item.selected && item.quantity > 0) {
|
||||
const price = item.salePrice || item.currentPrice || item.price || 0;
|
||||
// 价格是以分为单位,需要转换为元
|
||||
const price = (item.salePrice || item.currentPrice || item.price || 0) / 100;
|
||||
return total + price * item.quantity;
|
||||
}
|
||||
return total;
|
||||
|
|
@ -253,6 +254,17 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
// 格式化价格:将分转换为元(除以100,保留两位小数)
|
||||
formatPrice(price) {
|
||||
if (!price && price !== 0) {
|
||||
return '0.00';
|
||||
}
|
||||
// 将分转换为元
|
||||
const yuan = price / 100;
|
||||
// 保留两位小数
|
||||
return yuan.toFixed(2);
|
||||
},
|
||||
|
||||
// 去结算
|
||||
handleCheckout() {
|
||||
if (this.totalAmount <= 0) {
|
||||
|
|
@ -272,14 +284,9 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: 跳转到结算页面或提交订单
|
||||
console.log("结算商品:", selectedItems);
|
||||
console.log("总金额:", this.totalAmount);
|
||||
|
||||
uni.showToast({
|
||||
title: `结算金额:¥${this.totalAmount.toFixed(2)}`,
|
||||
title: "该功能正在开发中",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
},
|
||||
},
|
||||
|
|
@ -487,7 +494,7 @@ export default {
|
|||
.price-text {
|
||||
font-family: PingFang-SC, PingFang-SC;
|
||||
font-weight: bold;
|
||||
font-size: 50rpx;
|
||||
font-size: 48rpx;
|
||||
color: #d51c3c;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,12 +157,55 @@ export default {
|
|||
this.getSystemInfo();
|
||||
this.loadHomeData();
|
||||
this.loadActivities();
|
||||
|
||||
// 启用分享功能
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.showShareMenu({
|
||||
withShareTicket: true,
|
||||
menus: ['shareAppMessage', 'shareTimeline']
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
onShow() {
|
||||
// 每次显示页面时刷新数据
|
||||
this.loadHomeData();
|
||||
this.loadActivities();
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.loadHomeData().finally(() => {
|
||||
uni.stopPullDownRefresh();
|
||||
});
|
||||
},
|
||||
|
||||
// 分享给朋友
|
||||
onShareAppMessage() {
|
||||
// 使用第一个banner作为分享图片,如果没有则使用默认logo
|
||||
const shareImage = this.bannerList && this.bannerList.length > 0
|
||||
? this.bannerList[0].coverUrl
|
||||
: '/static/home/logo.png';
|
||||
|
||||
return {
|
||||
title: '广厦千万间司机公会 - 加入工会,权益保障,福利升级',
|
||||
path: '/pages/index/index',
|
||||
imageUrl: shareImage
|
||||
};
|
||||
},
|
||||
|
||||
// 分享到朋友圈(微信小程序)
|
||||
// #ifdef MP-WEIXIN
|
||||
onShareTimeline() {
|
||||
// 使用第一个banner作为分享图片,如果没有则使用默认logo
|
||||
const shareImage = this.bannerList && this.bannerList.length > 0
|
||||
? this.bannerList[0].coverUrl
|
||||
: '/static/home/logo.png';
|
||||
|
||||
return {
|
||||
title: '广厦千万间司机公会 - 加入工会,权益保障,福利升级',
|
||||
query: '',
|
||||
imageUrl: shareImage
|
||||
};
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
// 获取系统信息
|
||||
getSystemInfo() {
|
||||
|
|
@ -179,7 +222,7 @@ export default {
|
|||
async loadHomeData() {
|
||||
try {
|
||||
// 获取首页banner
|
||||
const res = await getHomeData({ noticeType: 1 });
|
||||
const res = await getHomeData({ noticeType: 22 });
|
||||
if (res) {
|
||||
this.bannerList = res.list || [];
|
||||
}
|
||||
|
|
@ -209,7 +252,7 @@ export default {
|
|||
async loadActivities() {
|
||||
try {
|
||||
// 后续补充接口调用
|
||||
const res = await getHomeData({ page: 1, pageSize: 3, noticeType: 2 });
|
||||
const res = await getHomeData({ page: 1, pageSize: 3, noticeType: 21 });
|
||||
if (res) {
|
||||
this.activitiesList = res.list || [];
|
||||
}
|
||||
|
|
@ -221,24 +264,10 @@ export default {
|
|||
// 格式化时间戳
|
||||
formatTime,
|
||||
|
||||
// 菜单点击
|
||||
handleMenuClick() {
|
||||
uni.showToast({
|
||||
title: "菜单功能",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
|
||||
// 聚焦/关注点击
|
||||
handleFocusClick() {
|
||||
uni.showToast({
|
||||
title: "关注功能",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
|
||||
// banner点击跳转
|
||||
handleBannerClick(item) {
|
||||
console.log(item, 222);
|
||||
if (item.jumpUrl) {
|
||||
// 判断跳转类型
|
||||
if (
|
||||
|
|
@ -265,31 +294,21 @@ export default {
|
|||
url: item.jumpUrl,
|
||||
});
|
||||
}
|
||||
} else if (item.content) {
|
||||
// 如果 jumpUrl 为空但有 content,展示富文本内容
|
||||
const title = item.title || '详情';
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/richTextDetail?title=${encodeURIComponent(title)}&content=${encodeURIComponent(item.content)}`
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 加入工会
|
||||
async handleJoinGuild() {
|
||||
try {
|
||||
// 后续补充接口调用
|
||||
// const res = await joinGuild()
|
||||
// if (res.statusCode === 200) {
|
||||
// uni.showToast({
|
||||
// title: '加入成功',
|
||||
// icon: 'success'
|
||||
// })
|
||||
// }
|
||||
uni.showToast({
|
||||
title: "加入工会",
|
||||
title: "该功能正在开发中",
|
||||
icon: "none",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("加入工会失败:", error);
|
||||
uni.showToast({
|
||||
title: "操作失败,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 查看全部福利
|
||||
|
|
@ -340,10 +359,10 @@ export default {
|
|||
|
||||
// 活动项点击
|
||||
handleActivityClick(item) {
|
||||
// 后续可以跳转到活动详情页
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/activities/detail?id=${item.id}`
|
||||
// })
|
||||
// 点击活动项跳转到详情页
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/activitiesDetail?id=${item.id}`
|
||||
});
|
||||
},
|
||||
|
||||
// 参与活动
|
||||
|
|
|
|||
|
|
@ -1,27 +1,20 @@
|
|||
<template>
|
||||
<view class="login-page">
|
||||
<!-- 状态栏占位 -->
|
||||
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
|
||||
<!-- <view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view> -->
|
||||
|
||||
<!-- 头部区域 -->
|
||||
<view class="header">
|
||||
<view class="back-btn" @click="handleBack" v-if="showBack">
|
||||
<text class="back-icon">‹</text>
|
||||
</view>
|
||||
<view class="header-title">登录</view>
|
||||
</view>
|
||||
<NavHeader title="登录" />
|
||||
|
||||
<!-- 登录内容区 -->
|
||||
<view class="login-content">
|
||||
<!-- Logo区域 -->
|
||||
<!-- <view class="logo-section">
|
||||
<image class="logo" src="/static/logo.png" mode="aspectFit"></image>
|
||||
</view> -->
|
||||
<view class="logo-section">
|
||||
<image class="logo" src="/static/home/logo.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
|
||||
<!-- 登录表单 -->
|
||||
<view class="login-form">
|
||||
<!-- 手机号输入 -->
|
||||
<view class="form-item">
|
||||
<!-- <view class="form-item">
|
||||
<view class="input-wrapper">
|
||||
<text class="input-label">手机号</text>
|
||||
<input
|
||||
|
|
@ -32,10 +25,9 @@
|
|||
maxlength="11"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 密码输入 -->
|
||||
<view class="form-item">
|
||||
<!-- <view class="form-item">
|
||||
<view class="input-wrapper">
|
||||
<text class="input-label">密码</text>
|
||||
<input
|
||||
|
|
@ -48,24 +40,24 @@
|
|||
<text class="toggle-icon">{{ showPassword ? '👁️' : '👁️🗨️' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 登录按钮 -->
|
||||
<button
|
||||
<!-- <button
|
||||
class="login-btn"
|
||||
:class="{ disabled: !canLogin }"
|
||||
:disabled="!canLogin || loading"
|
||||
@click="handleLogin"
|
||||
>
|
||||
{{ loading ? '登录中...' : '登录' }}
|
||||
</button>
|
||||
</button> -->
|
||||
|
||||
<!-- 分割线 -->
|
||||
<view class="divider">
|
||||
<!-- <view class="divider">
|
||||
<view class="divider-line"></view>
|
||||
<text class="divider-text">或</text>
|
||||
<view class="divider-line"></view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 小程序一键授权登录 -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
|
|
@ -103,7 +95,10 @@ export default {
|
|||
formData: {
|
||||
mobile: '',
|
||||
password: ''
|
||||
}
|
||||
},
|
||||
// 登录相关参数
|
||||
state: '', // state 参数
|
||||
inviteCode: '' // 邀请码
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -131,6 +126,14 @@ export default {
|
|||
return
|
||||
}
|
||||
|
||||
// 保存页面参数(state 和 inviteCode)
|
||||
if (options.state) {
|
||||
this.state = options.state
|
||||
}
|
||||
if (options.inviteCode) {
|
||||
this.inviteCode = options.inviteCode
|
||||
}
|
||||
|
||||
// 判断是否显示返回按钮(从其他页面跳转过来时显示)
|
||||
const pages = getCurrentPages()
|
||||
if (pages.length > 1) {
|
||||
|
|
@ -261,7 +264,7 @@ export default {
|
|||
if (e.detail.errMsg === 'getPhoneNumber:ok') {
|
||||
this.loading = true
|
||||
try {
|
||||
// 获取微信登录code(用于后端解密手机号)
|
||||
// 1. 获取微信临时登录code
|
||||
const loginRes = await new Promise((resolve, reject) => {
|
||||
uni.login({
|
||||
provider: 'weixin',
|
||||
|
|
@ -270,25 +273,51 @@ export default {
|
|||
})
|
||||
})
|
||||
|
||||
// 调用登录接口
|
||||
// 注意:这里需要根据后端实际接口要求传递参数
|
||||
// 通常需要传递 code、encryptedData、iv 等参数
|
||||
const res = await loginByPhone({
|
||||
code: loginRes.code,
|
||||
encryptedData: e.detail.encryptedData,
|
||||
iv: e.detail.iv
|
||||
if (loginRes.errMsg !== 'login:ok') {
|
||||
uni.showToast({
|
||||
title: '获取登录凭证失败',
|
||||
icon: 'none'
|
||||
})
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
|
||||
// 登录成功,保存token(兼容不同的响应格式)
|
||||
const token = res?.token || res?.data?.token || res?.accessToken || res?.access_token
|
||||
// 2. 调用登录接口
|
||||
// 根据接口文档:/app-api/member/auth/weixin-mini-app-login
|
||||
// 参数:phoneCode(手机code)、loginCode(登录code)、state(必填,回调用的随机值)、inviteCode(可选)
|
||||
// 生成随机 state 值(用于回调)
|
||||
const state = this.generateState()
|
||||
|
||||
const loginParams = {
|
||||
phoneCode: e.detail.code, // 手机 code, 通过 wx.getPhoneNumber 获得
|
||||
loginCode: loginRes.code, // 登录 code, 通过 wx.login 获得
|
||||
state: state, // state 是必填项,用于回调的随机值
|
||||
}
|
||||
|
||||
// 如果有邀请码(例如从页面参数或存储中获取)
|
||||
const inviteCode = this.getInviteCode()
|
||||
if (inviteCode) {
|
||||
loginParams.inviteCode = inviteCode
|
||||
}
|
||||
|
||||
const res = await loginByPhone(loginParams)
|
||||
|
||||
// 登录成功,保存token
|
||||
// 根据接口返回:{ code: 0, data: { accessToken, refreshToken, expiresTime, userId, ... } }
|
||||
// request 函数在 code === 0 时返回 res.data.data || res.data,所以 res 就是 data 对象
|
||||
const token = res?.accessToken || res?.data?.accessToken || res?.token || res?.data?.token
|
||||
if (token) {
|
||||
uni.setStorageSync('token', token)
|
||||
console.log('Token 已保存:', token)
|
||||
} else {
|
||||
console.error('未找到 token,返回数据:', res)
|
||||
}
|
||||
|
||||
// 保存refreshToken(用于刷新accessToken)
|
||||
const refreshToken = res?.refreshToken || res?.data?.refreshToken
|
||||
if (refreshToken) {
|
||||
uni.setStorageSync('refreshToken', refreshToken)
|
||||
console.log('RefreshToken 已保存:', refreshToken)
|
||||
}
|
||||
|
||||
// 保存token过期时间
|
||||
|
|
@ -303,18 +332,25 @@ export default {
|
|||
uni.setStorageSync('userId', userId)
|
||||
}
|
||||
|
||||
// 保存用户信息(如果有)
|
||||
const userInfo = res?.userInfo || res?.data?.userInfo || res?.user || res?.data?.user
|
||||
if (userInfo) {
|
||||
uni.setStorageSync('userInfo', userInfo)
|
||||
// 保存 openid(如果有)
|
||||
const openid = res?.openid || res?.data?.openid
|
||||
if (openid) {
|
||||
uni.setStorageSync('openid', openid)
|
||||
}
|
||||
|
||||
// 登录成功后,调用个人信息接口获取完整用户信息
|
||||
try {
|
||||
const userInfoRes = await getUserInfo()
|
||||
if (userInfoRes && userInfoRes.data) {
|
||||
// 根据接口返回的数据结构,保存 res.data
|
||||
uni.setStorageSync('userInfo', userInfoRes.data)
|
||||
} else if (userInfoRes) {
|
||||
// 兼容直接返回数据的情况
|
||||
uni.setStorageSync('userInfo', userInfoRes)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
// 获取用户信息失败不影响登录流程,继续执行
|
||||
}
|
||||
|
||||
uni.showToast({
|
||||
|
|
@ -345,6 +381,45 @@ export default {
|
|||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// 生成随机 state 值(用于回调)
|
||||
generateState() {
|
||||
// 生成 UUID 格式的随机字符串(类似:9b2ffbc1-7425-4155-9894-9d5c08541d62)
|
||||
// 格式:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
const generateUUID = () => {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
const r = Math.random() * 16 | 0
|
||||
const v = c === 'x' ? r : (r & 0x3 | 0x8)
|
||||
return v.toString(16)
|
||||
})
|
||||
}
|
||||
|
||||
const state = generateUUID()
|
||||
|
||||
// 保存 state 到本地存储,以便后续回调时使用
|
||||
uni.setStorageSync('loginState', state)
|
||||
|
||||
return state
|
||||
},
|
||||
|
||||
// 获取邀请码
|
||||
getInviteCode() {
|
||||
// 优先从页面参数获取
|
||||
if (this.inviteCode) {
|
||||
return this.inviteCode
|
||||
}
|
||||
// 也可以从本地存储获取
|
||||
const storedInviteCode = uni.getStorageSync('inviteCode')
|
||||
if (storedInviteCode) {
|
||||
return storedInviteCode
|
||||
}
|
||||
// 也可以从全局变量获取
|
||||
const app = getApp()
|
||||
if (app && app.globalData && app.globalData.inviteCode) {
|
||||
return app.globalData.inviteCode
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -399,11 +474,13 @@ export default {
|
|||
.logo-section {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 80rpx;
|
||||
align-items: center;
|
||||
margin-bottom: 120rpx;
|
||||
margin-top: 80rpx;
|
||||
|
||||
.logo {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
width: 306rpx;
|
||||
height: 72rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,24 @@
|
|||
}"
|
||||
>
|
||||
<view class="user-info">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button class="avatar-btn" open-type="chooseAvatar" @chooseavatar="handleChooseAvatar">
|
||||
<image
|
||||
class="avatar"
|
||||
:src="userInfo.avatar || '/static/logo.png'"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<view class="avatar-wrapper" @click="handleChooseAvatar">
|
||||
<image
|
||||
class="avatar"
|
||||
:src="userInfo.avatar || '/static/logo.png'"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<image
|
||||
src="/static/profile/avatar-hg.png"
|
||||
mode="aspectFill"
|
||||
|
|
@ -42,13 +55,13 @@
|
|||
|
||||
<!-- 功能卡片 -->
|
||||
<view class="action-cards">
|
||||
<view class="action-card real-name-auth" @click="goToRealNameAuth">
|
||||
<view class="action-card real-name-auth" @tap="goToRealNameAuth">
|
||||
<view class="card-content">
|
||||
<text class="card-title">实名认证</text>
|
||||
<text class="card-desc">请完善身份信息></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="action-card service-records" @click="goToServiceRecords">
|
||||
<view class="action-card service-records" @tap="goToServiceRecords">
|
||||
<view class="card-content">
|
||||
<text class="card-title">服务记录</text>
|
||||
<text class="card-desc">查看服务记录></text>
|
||||
|
|
@ -58,7 +71,7 @@
|
|||
|
||||
<!-- 菜单列表 -->
|
||||
<view class="menu-list">
|
||||
<view class="menu-item" @click="goToFavorites">
|
||||
<view class="menu-item" @tap="goToFavorites">
|
||||
<view class="menu-icon"
|
||||
><image
|
||||
src="/static/profile/my-favorite.png"
|
||||
|
|
@ -68,14 +81,14 @@
|
|||
<text class="menu-text">我的收藏</text>
|
||||
<text class="menu-arrow">›</text>
|
||||
</view>
|
||||
<view class="menu-item" @click="goToComplaints">
|
||||
<view class="menu-item" @tap="goToComplaints">
|
||||
<view class="menu-icon"
|
||||
><image src="/static/profile/complaints.png" mode="aspectFill"></image
|
||||
></view>
|
||||
<text class="menu-text">投诉建议</text>
|
||||
<text class="menu-arrow">›</text>
|
||||
</view>
|
||||
<view class="menu-item" @click="goToPostMessage">
|
||||
<view class="menu-item" @tap="goToPostMessage">
|
||||
<view class="menu-icon"
|
||||
><image
|
||||
src="/static/profile/publish-message.png"
|
||||
|
|
@ -103,19 +116,22 @@ export default {
|
|||
statusBarHeight: 0,
|
||||
navBarHeight: 0,
|
||||
currentTime: "10:55",
|
||||
userInfo: {},
|
||||
userInfo: {
|
||||
level: {} // 防止 level 未定义时报错
|
||||
},
|
||||
noticeNum: 3,
|
||||
uploading: false, // 是否正在上传头像
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.getSystemInfo();
|
||||
this.updateTime();
|
||||
// 先加载本地存储的用户信息,然后刷新
|
||||
this.loadUserInfo();
|
||||
// this.loadUserInfo();
|
||||
},
|
||||
onShow() {
|
||||
// 页面显示时刷新用户信息(可选,如果不需要每次都刷新可以注释掉)
|
||||
// this.loadUserInfo();
|
||||
// 每次显示页面时刷新用户信息
|
||||
this.loadUserInfo();
|
||||
},
|
||||
methods: {
|
||||
// 获取系统信息
|
||||
|
|
@ -191,18 +207,18 @@ export default {
|
|||
},
|
||||
goToMemberBenefits() {
|
||||
uni.showToast({
|
||||
title: "会员权益",
|
||||
title: "该功能正在开发中",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
goToRealNameAuth() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/profile/realNameAuth",
|
||||
url: "/pages/profileSub/realNameAuth",
|
||||
});
|
||||
},
|
||||
goToServiceRecords() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/profile/serviceRecords",
|
||||
url: "/pages/profileSub/serviceRecords",
|
||||
});
|
||||
},
|
||||
goToFavorites() {
|
||||
|
|
@ -239,6 +255,136 @@ export default {
|
|||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 选择头像(微信小程序使用 chooseAvatar,其他平台使用 chooseImage)
|
||||
handleChooseAvatar(e) {
|
||||
// #ifdef MP-WEIXIN
|
||||
// 微信小程序新版本使用 chooseAvatar
|
||||
if (e.detail && e.detail.avatarUrl) {
|
||||
const avatarUrl = e.detail.avatarUrl;
|
||||
// 先显示本地预览
|
||||
this.userInfo.avatar = avatarUrl;
|
||||
// 上传头像
|
||||
this.uploadAvatar(avatarUrl);
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
// 其他平台使用 chooseImage
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: (res) => {
|
||||
const tempFilePath = res.tempFilePaths[0];
|
||||
// 先显示本地预览
|
||||
this.userInfo.avatar = tempFilePath;
|
||||
// 上传头像
|
||||
this.uploadAvatar(tempFilePath);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('选择图片失败:', err);
|
||||
uni.showToast({
|
||||
title: '选择图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
|
||||
// 上传头像
|
||||
uploadAvatar(filePath) {
|
||||
if (this.uploading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.uploading = true;
|
||||
uni.showLoading({
|
||||
title: '上传中...',
|
||||
mask: true
|
||||
});
|
||||
|
||||
// 获取token
|
||||
const token = uni.getStorageSync('token');
|
||||
const BASE_URL = 'https://guangsh.manage.hschengtai.com';
|
||||
|
||||
uni.uploadFile({
|
||||
url: `${BASE_URL}/app-api/infra/file/upload`,
|
||||
filePath: filePath,
|
||||
name: 'file',
|
||||
formData: {
|
||||
directory: 'avatar' // 头像目录
|
||||
},
|
||||
header: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'tenant-id': '1'
|
||||
},
|
||||
success: (res) => {
|
||||
uni.hideLoading();
|
||||
try {
|
||||
const data = JSON.parse(res.data);
|
||||
if (data.code === 200 || data.code === 0) {
|
||||
// 上传成功,获取图片URL
|
||||
const imageUrl = data.data?.url || data.data || data.url;
|
||||
if (imageUrl) {
|
||||
// 更新用户信息中的头像
|
||||
this.userInfo.avatar = imageUrl;
|
||||
// 保存到本地存储
|
||||
uni.setStorageSync('userInfo', this.userInfo);
|
||||
|
||||
// 调用更新用户信息接口(如果有的话)
|
||||
this.updateUserAvatar(imageUrl);
|
||||
|
||||
uni.showToast({
|
||||
title: '头像上传成功',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
});
|
||||
} else {
|
||||
throw new Error('上传成功但未返回图片地址');
|
||||
}
|
||||
} else {
|
||||
throw new Error(data.message || data.msg || '上传失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('解析上传结果失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '上传失败,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
// 上传失败,恢复原头像
|
||||
this.loadUserInfo();
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.hideLoading();
|
||||
console.error('上传头像失败:', err);
|
||||
uni.showToast({
|
||||
title: '上传失败,请检查网络',
|
||||
icon: 'none'
|
||||
});
|
||||
// 上传失败,恢复原头像
|
||||
this.loadUserInfo();
|
||||
},
|
||||
complete: () => {
|
||||
this.uploading = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 更新用户头像(如果有更新用户信息的接口)
|
||||
async updateUserAvatar(avatarUrl) {
|
||||
try {
|
||||
// 这里可以调用更新用户信息的接口
|
||||
// 例如:await updateUserInfo({ avatar: avatarUrl });
|
||||
// 暂时只更新本地存储,如果后端有更新接口可以在这里调用
|
||||
console.log('头像已更新:', avatarUrl);
|
||||
} catch (error) {
|
||||
console.error('更新用户头像失败:', error);
|
||||
// 即使更新失败,本地已经保存了,不影响使用
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -280,10 +426,44 @@ export default {
|
|||
align-items: center;
|
||||
padding-top: 89rpx;
|
||||
padding-left: 23rpx;
|
||||
|
||||
.avatar-btn {
|
||||
width: 109rpx;
|
||||
height: 108rpx;
|
||||
margin-right: 24rpx;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
line-height: 1;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
width: 109rpx;
|
||||
height: 108rpx;
|
||||
margin-right: 24rpx;
|
||||
|
||||
.avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 109rpx;
|
||||
height: 108rpx;
|
||||
margin-right: 24rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.avatar-hg {
|
||||
width: 51rpx;
|
||||
|
|
|
|||
|
|
@ -166,114 +166,114 @@ export default {
|
|||
pageSize: 10,
|
||||
// 假数据
|
||||
mockData: {
|
||||
pending_payment: [
|
||||
{
|
||||
id: 1,
|
||||
orderNo: "ORD20250101001",
|
||||
serviceName: "汽车维修保养",
|
||||
serviceType: "维修服务",
|
||||
storeName: "XX汽车维修中心",
|
||||
amount: "299.00",
|
||||
createTime: "2025-01-15 10:30:00",
|
||||
status: "pending_payment",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
orderNo: "ORD20250101002",
|
||||
serviceName: "家电清洗服务",
|
||||
serviceType: "清洗服务",
|
||||
storeName: "XX家电清洗店",
|
||||
amount: "158.00",
|
||||
createTime: "2025-01-14 15:20:00",
|
||||
status: "pending_payment",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
orderNo: "ORD20250101003",
|
||||
serviceName: "手机维修",
|
||||
serviceType: "维修服务",
|
||||
storeName: "XX手机维修店",
|
||||
amount: "199.00",
|
||||
createTime: "2025-01-13 09:15:00",
|
||||
status: "pending_payment",
|
||||
},
|
||||
],
|
||||
pending_verification: [
|
||||
{
|
||||
id: 4,
|
||||
orderNo: "ORD20250101004",
|
||||
serviceName: "汽车维修保养",
|
||||
serviceType: "维修服务",
|
||||
storeName: "XX汽车维修中心",
|
||||
amount: "299.00",
|
||||
createTime: "2025-01-10 14:30:00",
|
||||
status: "pending_verification",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
orderNo: "ORD20250101005",
|
||||
serviceName: "家电清洗服务",
|
||||
serviceType: "清洗服务",
|
||||
storeName: "XX家电清洗店",
|
||||
amount: "158.00",
|
||||
createTime: "2025-01-09 11:20:00",
|
||||
status: "pending_verification",
|
||||
},
|
||||
],
|
||||
completed: [
|
||||
{
|
||||
id: 6,
|
||||
orderNo: "ORD20250101006",
|
||||
serviceName: "汽车维修保养",
|
||||
serviceType: "维修服务",
|
||||
storeName: "XX汽车维修中心",
|
||||
amount: "299.00",
|
||||
createTime: "2025-01-05 16:30:00",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
orderNo: "ORD20250101007",
|
||||
serviceName: "家电清洗服务",
|
||||
serviceType: "清洗服务",
|
||||
storeName: "XX家电清洗店",
|
||||
amount: "158.00",
|
||||
createTime: "2025-01-04 10:20:00",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
orderNo: "ORD20250101008",
|
||||
serviceName: "手机维修",
|
||||
serviceType: "维修服务",
|
||||
storeName: "XX手机维修店",
|
||||
amount: "199.00",
|
||||
createTime: "2025-01-03 08:15:00",
|
||||
status: "completed",
|
||||
},
|
||||
],
|
||||
cancelled: [
|
||||
{
|
||||
id: 9,
|
||||
orderNo: "ORD20250101009",
|
||||
serviceName: "汽车维修保养",
|
||||
serviceType: "维修服务",
|
||||
storeName: "XX汽车维修中心",
|
||||
amount: "299.00",
|
||||
createTime: "2025-01-02 14:30:00",
|
||||
status: "cancelled",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
orderNo: "ORD20250101010",
|
||||
serviceName: "家电清洗服务",
|
||||
serviceType: "清洗服务",
|
||||
storeName: "XX家电清洗店",
|
||||
amount: "158.00",
|
||||
createTime: "2025-01-01 11:20:00",
|
||||
status: "cancelled",
|
||||
},
|
||||
],
|
||||
// pending_payment: [
|
||||
// {
|
||||
// id: 1,
|
||||
// orderNo: "ORD20250101001",
|
||||
// serviceName: "汽车维修保养",
|
||||
// serviceType: "维修服务",
|
||||
// storeName: "XX汽车维修中心",
|
||||
// amount: "299.00",
|
||||
// createTime: "2025-01-15 10:30:00",
|
||||
// status: "pending_payment",
|
||||
// },
|
||||
// {
|
||||
// id: 2,
|
||||
// orderNo: "ORD20250101002",
|
||||
// serviceName: "家电清洗服务",
|
||||
// serviceType: "清洗服务",
|
||||
// storeName: "XX家电清洗店",
|
||||
// amount: "158.00",
|
||||
// createTime: "2025-01-14 15:20:00",
|
||||
// status: "pending_payment",
|
||||
// },
|
||||
// {
|
||||
// id: 3,
|
||||
// orderNo: "ORD20250101003",
|
||||
// serviceName: "手机维修",
|
||||
// serviceType: "维修服务",
|
||||
// storeName: "XX手机维修店",
|
||||
// amount: "199.00",
|
||||
// createTime: "2025-01-13 09:15:00",
|
||||
// status: "pending_payment",
|
||||
// },
|
||||
// ],
|
||||
// pending_verification: [
|
||||
// {
|
||||
// id: 4,
|
||||
// orderNo: "ORD20250101004",
|
||||
// serviceName: "汽车维修保养",
|
||||
// serviceType: "维修服务",
|
||||
// storeName: "XX汽车维修中心",
|
||||
// amount: "299.00",
|
||||
// createTime: "2025-01-10 14:30:00",
|
||||
// status: "pending_verification",
|
||||
// },
|
||||
// {
|
||||
// id: 5,
|
||||
// orderNo: "ORD20250101005",
|
||||
// serviceName: "家电清洗服务",
|
||||
// serviceType: "清洗服务",
|
||||
// storeName: "XX家电清洗店",
|
||||
// amount: "158.00",
|
||||
// createTime: "2025-01-09 11:20:00",
|
||||
// status: "pending_verification",
|
||||
// },
|
||||
// ],
|
||||
// completed: [
|
||||
// {
|
||||
// id: 6,
|
||||
// orderNo: "ORD20250101006",
|
||||
// serviceName: "汽车维修保养",
|
||||
// serviceType: "维修服务",
|
||||
// storeName: "XX汽车维修中心",
|
||||
// amount: "299.00",
|
||||
// createTime: "2025-01-05 16:30:00",
|
||||
// status: "completed",
|
||||
// },
|
||||
// {
|
||||
// id: 7,
|
||||
// orderNo: "ORD20250101007",
|
||||
// serviceName: "家电清洗服务",
|
||||
// serviceType: "清洗服务",
|
||||
// storeName: "XX家电清洗店",
|
||||
// amount: "158.00",
|
||||
// createTime: "2025-01-04 10:20:00",
|
||||
// status: "completed",
|
||||
// },
|
||||
// {
|
||||
// id: 8,
|
||||
// orderNo: "ORD20250101008",
|
||||
// serviceName: "手机维修",
|
||||
// serviceType: "维修服务",
|
||||
// storeName: "XX手机维修店",
|
||||
// amount: "199.00",
|
||||
// createTime: "2025-01-03 08:15:00",
|
||||
// status: "completed",
|
||||
// },
|
||||
// ],
|
||||
// cancelled: [
|
||||
// {
|
||||
// id: 9,
|
||||
// orderNo: "ORD20250101009",
|
||||
// serviceName: "汽车维修保养",
|
||||
// serviceType: "维修服务",
|
||||
// storeName: "XX汽车维修中心",
|
||||
// amount: "299.00",
|
||||
// createTime: "2025-01-02 14:30:00",
|
||||
// status: "cancelled",
|
||||
// },
|
||||
// {
|
||||
// id: 10,
|
||||
// orderNo: "ORD20250101010",
|
||||
// serviceName: "家电清洗服务",
|
||||
// serviceType: "清洗服务",
|
||||
// storeName: "XX家电清洗店",
|
||||
// amount: "158.00",
|
||||
// createTime: "2025-01-01 11:20:00",
|
||||
// status: "cancelled",
|
||||
// },
|
||||
// ],
|
||||
},
|
||||
};
|
||||
},
|
||||
|
|
@ -391,35 +391,23 @@ export default {
|
|||
// 立即支付
|
||||
handlePay(item) {
|
||||
uni.showToast({
|
||||
title: "跳转支付页面",
|
||||
title: "该功能正在开发中",
|
||||
icon: "none",
|
||||
});
|
||||
// 这里应该跳转到支付页面
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/payment/payment?orderNo=${item.orderNo}&amount=${item.amount}`
|
||||
// });
|
||||
},
|
||||
// 查看详情
|
||||
handleViewDetail(item) {
|
||||
uni.showToast({
|
||||
title: "查看详情",
|
||||
title: "该功能正在开发中",
|
||||
icon: "none",
|
||||
});
|
||||
// 这里应该跳转到详情页面
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/order/detail?orderNo=${item.orderNo}`
|
||||
// });
|
||||
},
|
||||
// 评价
|
||||
handleReview(item) {
|
||||
uni.showToast({
|
||||
title: "跳转评价页面",
|
||||
title: "该功能正在开发中",
|
||||
icon: "none",
|
||||
});
|
||||
// 这里应该跳转到评价页面
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/order/review?orderNo=${item.orderNo}`
|
||||
// });
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -25,7 +25,8 @@
|
|||
|
||||
<!-- 分类标签栏 -->
|
||||
<view class="category-bar">
|
||||
<view class="location-selector" @click="handleLocationSelect">
|
||||
<!-- 只有店铺类型(美食、维修)才显示距离选择器 -->
|
||||
<view class="location-selector" v-if="isStoreCategory()" @click="handleLocationSelect">
|
||||
<text class="location-text">{{ selectedDistance ? `附近${selectedDistance}km` : '附近' }}</text>
|
||||
<image
|
||||
class="location-arrow"
|
||||
|
|
@ -95,8 +96,9 @@
|
|||
<!-- 右侧信息 -->
|
||||
<view class="service-info">
|
||||
<view class="service-title-row">
|
||||
<text class="service-title">{{ item.name }}</text>
|
||||
<view class="distance-info">
|
||||
<text class="service-title">{{ item.name || item.title }}</text>
|
||||
<!-- 只有店铺类型才显示距离 -->
|
||||
<view class="distance-info" v-if="isStoreCategory()">
|
||||
<image
|
||||
class="location-icon"
|
||||
src="/static/service/location-icon.png"
|
||||
|
|
@ -106,6 +108,8 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 店铺类型显示门店信息 -->
|
||||
<template v-if="isStoreCategory()">
|
||||
<view class="service-detail">
|
||||
<text class="detail-label">门店地址:</text>
|
||||
<text class="detail-value">{{ item.address }}</text>
|
||||
|
|
@ -115,10 +119,18 @@
|
|||
<text class="detail-label">联系电话:</text>
|
||||
<text class="detail-value">{{ item.phone }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 消息类型显示摘要 -->
|
||||
<template v-else>
|
||||
<view class="service-detail" v-if="item.summary">
|
||||
<text class="detail-value">{{ item.summary }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<view class="service-tags-row">
|
||||
<view class="service-tags">
|
||||
<view class="tag-item tag-pink"> 会员特惠 </view>
|
||||
<view class="tag-item tag-pink"> {{ item.publishUserName || '会员特惠' }} </view>
|
||||
<view class="tag-item tag-orange">{{
|
||||
currentCategoryLabel
|
||||
}}</view>
|
||||
|
|
@ -126,7 +138,8 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<view class="enter-btn" @click.stop="handleEnterStore(item)">
|
||||
<!-- 只有店铺类型才显示"进店"按钮 -->
|
||||
<view class="enter-btn" v-if="isStoreCategory()" @click.stop="handleEnterStore(item)">
|
||||
进店
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -182,7 +195,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { getDictDataByType, getGuildStorePage } from "@/api/service";
|
||||
import { getDictDataByType, getGuildStorePage,getMessagePage } from "@/api/service";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -209,12 +222,23 @@ export default {
|
|||
onLoad() {
|
||||
this.getSystemInfo();
|
||||
this.getServiceCategoryFun(); // 获取服务分类
|
||||
this.checkAndRequestLocation(); // 检查并请求位置权限
|
||||
// this.checkAndRequestLocation(); // 检查并请求位置权限
|
||||
},
|
||||
onShow() {
|
||||
// 每次显示页面时刷新数据
|
||||
// 如果分类列表已经加载,检查是否有需要高亮的分类
|
||||
if (this.categoryList && this.categoryList.length > 0) {
|
||||
this.checkAndSetCategory();
|
||||
// 如果当前有选中的分类,刷新服务列表
|
||||
if (this.currentCategory !== null) {
|
||||
this.pageNo = 1;
|
||||
this.serviceList = [];
|
||||
this.hasMore = true;
|
||||
this.loadServiceList();
|
||||
}
|
||||
} else {
|
||||
// 如果分类列表还没加载,先加载分类(分类加载完成后会自动调用 checkAndSetCategory)
|
||||
this.getServiceCategoryFun();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -227,14 +251,28 @@ export default {
|
|||
getServiceCategoryFun() {
|
||||
getDictDataByType({ type: "member_labor_service_type" }).then((res) => {
|
||||
if (res) {
|
||||
this.categoryList = res || [];
|
||||
const dictList = res || [];
|
||||
// 固定添加"美食"和"维修"两个分类到列表前面
|
||||
const fixedCategories = [
|
||||
{ id: 'food', label: '美食', value: 'food', isStore: true }, // isStore: true 表示使用店铺接口
|
||||
{ id: 'repair', label: '维修', value: 'repair', isStore: true }
|
||||
];
|
||||
// 将固定分类添加到前面,其他分类添加到后面
|
||||
this.categoryList = [...fixedCategories, ...dictList];
|
||||
// 分类列表加载完成后,检查是否有需要高亮的分类
|
||||
this.checkAndSetCategory();
|
||||
// 如果当前有选中的分类,加载服务列表
|
||||
if (this.currentCategory !== null) {
|
||||
this.pageNo = 1;
|
||||
this.serviceList = [];
|
||||
this.hasMore = true;
|
||||
this.loadServiceList();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 检查并设置需要高亮的分类
|
||||
// 检查并设置需要高亮的分类(不触发数据刷新,由 onShow 统一处理)
|
||||
checkAndSetCategory() {
|
||||
const app = getApp();
|
||||
if (app && app.globalData && app.globalData.serviceCategory) {
|
||||
|
|
@ -242,20 +280,23 @@ export default {
|
|||
// 清除 globalData 中的分类信息
|
||||
app.globalData.serviceCategory = null;
|
||||
|
||||
// 处理首页跳转过来的分类值映射('0' -> 'food', '1' -> 'repair')
|
||||
let mappedValue = categoryValue;
|
||||
if (categoryValue === '0') {
|
||||
mappedValue = 'food';
|
||||
} else if (categoryValue === '1') {
|
||||
mappedValue = 'repair';
|
||||
}
|
||||
|
||||
// 在分类列表中查找匹配的分类(通过 value 匹配)
|
||||
const matchedCategory = this.categoryList.find(
|
||||
item => item.value === categoryValue
|
||||
item => item.value === mappedValue || item.value === categoryValue
|
||||
);
|
||||
|
||||
if (matchedCategory) {
|
||||
// 设置当前分类并高亮
|
||||
this.currentCategory = matchedCategory.value;
|
||||
this.currentCategoryLabel = matchedCategory.label;
|
||||
// 重置分页,重新加载数据
|
||||
this.pageNo = 1;
|
||||
this.serviceList = [];
|
||||
this.hasMore = true;
|
||||
this.loadServiceList();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -265,11 +306,6 @@ export default {
|
|||
const firstCategory = this.categoryList[0];
|
||||
this.currentCategory = firstCategory.value;
|
||||
this.currentCategoryLabel = firstCategory.label;
|
||||
// 重置分页,重新加载数据
|
||||
this.pageNo = 1;
|
||||
this.serviceList = [];
|
||||
this.hasMore = true;
|
||||
this.loadServiceList();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -371,6 +407,10 @@ export default {
|
|||
handleCategoryClick(item) {
|
||||
this.currentCategory = item.value;
|
||||
this.currentCategoryLabel = item.label;
|
||||
// 如果切换到消息类型,清除距离筛选(消息类型不支持距离筛选)
|
||||
if (!this.isStoreCategory()) {
|
||||
this.selectedDistance = null;
|
||||
}
|
||||
// 重置分页,重新加载
|
||||
this.pageNo = 1;
|
||||
this.serviceList = [];
|
||||
|
|
@ -378,12 +418,34 @@ export default {
|
|||
this.loadServiceList();
|
||||
},
|
||||
|
||||
// 判断当前分类是否是店铺类型(美食、维修)
|
||||
isStoreCategory() {
|
||||
return this.currentCategory === 'food' || this.currentCategory === 'repair';
|
||||
},
|
||||
|
||||
// 进店按钮点击
|
||||
handleServiceItemClick(item) {
|
||||
// 跳转到店铺详情页面
|
||||
// 判断是店铺类型还是消息类型
|
||||
if (this.isStoreCategory()) {
|
||||
// 美食和维修跳转到店铺详情页面
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/serviceDetail?id=${item.id}&categoryLabel=${this.currentCategoryLabel}`,
|
||||
});
|
||||
} else {
|
||||
// 其他分类跳转到富文本详情页面
|
||||
const title = '详情';
|
||||
const content = item.content || '';
|
||||
if (content) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/richTextDetail?title=${encodeURIComponent(title)}&content=${encodeURIComponent(content)}`
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '暂无内容',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 进店按钮点击 - 跳转到地图详情页
|
||||
|
|
@ -407,11 +469,15 @@ export default {
|
|||
this.loading = true;
|
||||
}
|
||||
|
||||
// 构建请求参数
|
||||
let res;
|
||||
|
||||
// 判断是店铺类型还是消息类型
|
||||
if (this.isStoreCategory()) {
|
||||
// 美食和维修使用店铺接口
|
||||
const params = {
|
||||
pageNo: this.pageNo,
|
||||
pageSize: this.pageSize,
|
||||
type: this.currentCategory,
|
||||
type: this.currentCategory === 'food' ? '0' : '1', // 美食: '0', 维修: '1'
|
||||
name: this.searchKeyword,
|
||||
};
|
||||
|
||||
|
|
@ -420,7 +486,18 @@ export default {
|
|||
params.distance = this.selectedDistance;
|
||||
}
|
||||
|
||||
const res = await getGuildStorePage(params);
|
||||
res = await getGuildStorePage(params);
|
||||
} else {
|
||||
// 其他分类使用消息接口
|
||||
const params = {
|
||||
pageNo: this.pageNo,
|
||||
pageSize: this.pageSize,
|
||||
messageType: this.currentCategory, // 使用分类的 value 作为 messageType
|
||||
title: this.searchKeyword, // 消息接口可能使用 title 作为搜索字段
|
||||
};
|
||||
|
||||
res = await getMessagePage(params);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
const newList = res.list || [];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
<template>
|
||||
<view class="webview-page">
|
||||
<!-- 头部导航栏 -->
|
||||
<NavHeader title="网页" />
|
||||
|
||||
<!-- WebView 容器 -->
|
||||
<view class="webview-container">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<web-view :src="webviewUrl"></web-view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<view class="unsupported-tip">
|
||||
<text>当前平台不支持 WebView</text>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NavHeader from "@/components/NavHeader/NavHeader.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NavHeader
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
webviewUrl: ''
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
// 从路由参数获取要加载的 URL
|
||||
if (options.url) {
|
||||
this.webviewUrl = decodeURIComponent(options.url);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '缺少网页地址',
|
||||
icon: 'none'
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.webview-page {
|
||||
height: 100vh;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.webview-container {
|
||||
flex: 1;
|
||||
height: 0; // 配合 flex: 1 使用
|
||||
|
||||
.unsupported-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
|
||||
text {
|
||||
font-family: PingFang-SC, PingFang-SC;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 MiB |
BIN
static/logo.png
BIN
static/logo.png
Binary file not shown.
|
Before Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 112 KiB |
Loading…
Reference in New Issue