wew
This commit is contained in:
parent
ce44170338
commit
b2ac8a0e1a
51
api/request.js
Normal file
51
api/request.js
Normal file
@ -0,0 +1,51 @@
|
||||
const baseUrl = 'http://scrm.1024tool.vip/api/';
|
||||
|
||||
function request(url, method = 'GET', data = {}) {
|
||||
|
||||
const header = {
|
||||
'content-type': 'application/json',
|
||||
// 有其他content-type需求加点逻辑判断处理即可
|
||||
};
|
||||
// 获取token,有就丢进请求头
|
||||
const tokenString = wx.getStorageSync('access_token');
|
||||
if (tokenString) {
|
||||
header.Authorization = `${tokenString}`;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.request({
|
||||
url: baseUrl + url,
|
||||
method,
|
||||
data,
|
||||
dataType: 'json', // 微信官方文档中介绍会对数据进行一次JSON.parse
|
||||
header,
|
||||
success(res) {
|
||||
if (res.data.code) {
|
||||
if (res.data.code == 10103) {
|
||||
wx.removeStorageSync('access_token');
|
||||
// wx.navigateTo({
|
||||
// url: '/pages/login/login',
|
||||
// });
|
||||
reject(res.data);
|
||||
return;
|
||||
}
|
||||
wx.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none'
|
||||
});
|
||||
reject(res.data);
|
||||
} else {
|
||||
resolve(res.data);
|
||||
}
|
||||
|
||||
},
|
||||
fail(err) {
|
||||
console.log(err)
|
||||
// 断网、服务器挂了都会fail回调,直接reject即可
|
||||
reject(err);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 导出请求和服务地址
|
||||
export default request;
|
||||
31
api/upload.js
Normal file
31
api/upload.js
Normal file
@ -0,0 +1,31 @@
|
||||
function uploadFile(filePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!filePath) {
|
||||
const err = new Error('uploadFile requires a filePath parameter');
|
||||
console.error('上传失败:未提供文件路径', err);
|
||||
return reject(err);
|
||||
}
|
||||
// 获取token,有就丢进请求头
|
||||
const tokenString = wx.getStorageSync('access_token');
|
||||
const header = {
|
||||
'Authorization': `${tokenString}`
|
||||
};
|
||||
wx.uploadFile({
|
||||
filePath: filePath,
|
||||
name: 'file',
|
||||
header: header,
|
||||
url: 'http://scrm.1024tool.vip/api/xcx/upload/image',
|
||||
success: (res) => {
|
||||
const data = JSON.parse(res.data);
|
||||
resolve('http://scrm.1024tool.vip/' + data.preview_image_url);
|
||||
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('上传失败', err);
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
export default uploadFile;
|
||||
9
api/user.js
Normal file
9
api/user.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from "./request";
|
||||
|
||||
export const login = (data) => {
|
||||
return request(
|
||||
'api/user/login', // 根据实际后端接口路径修改
|
||||
'POST',
|
||||
data
|
||||
);
|
||||
};
|
||||
@ -36,6 +36,12 @@
|
||||
"style": {
|
||||
"navigationBarTitleText": "编辑信息"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "用户登录"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
|
||||
@ -26,39 +26,39 @@
|
||||
<view class="container">
|
||||
<view class="search flex justify-between">
|
||||
<view class="search-left flex">
|
||||
<view class="recommend" :class="{active: searchType == 1}" @click="changeSearch(1)">
|
||||
<view class="recommend" :class="{ active: searchType == 1 }" @click="changeSearch(1)">
|
||||
<text class="iconfont icon-tubiaoshangshengqushi"></text>
|
||||
推荐产品
|
||||
</view>
|
||||
<view class="group-buying" :class="{active: searchType == 2}" @click="changeSearch(2)">
|
||||
<view class="group-buying" :class="{ active: searchType == 2 }" @click="changeSearch(2)">
|
||||
<text class="iconfont icon-aixin"></text>
|
||||
拼团活动
|
||||
</view>
|
||||
</view>
|
||||
<view class="search-right flex">
|
||||
<view :class="{active: searchType2 == 1}" @click="changeSearch2(1)">
|
||||
<view :class="{ active: searchType2 == 1 }" @click="changeSearch2(1)">
|
||||
<text class="iconfont icon-wanggeshezhi">
|
||||
|
||||
|
||||
</text>
|
||||
</view>
|
||||
<view :class="{active: searchType2 == 2}" @click="changeSearch2(2)">
|
||||
<view :class="{ active: searchType2 == 2 }" @click="changeSearch2(2)">
|
||||
<text class="iconfont icon-caidan">
|
||||
|
||||
|
||||
</text>
|
||||
</view>
|
||||
<view :class="{active: searchType2 == 3}" @click="changeSearch2(3)">
|
||||
<view :class="{ active: searchType2 == 3 }" @click="changeSearch2(3)">
|
||||
<text class="iconfont icon-shaixuan1">
|
||||
|
||||
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="shop-list" v-if="searchType == 1">
|
||||
<view class="shop-item">
|
||||
<view class="shop-item" v-for="(item, index) in shopList">
|
||||
<view class="shop-image">
|
||||
<image src=""></image>
|
||||
<image :src="item.main_image_url"></image>
|
||||
<view class="shop-tag flex">
|
||||
<view class="tag danger">
|
||||
<view class="tag danger" v-if="item.is_hot_selling == 1">
|
||||
<text class="iconfont icon-tubiaoshangshengqushi"></text>热销
|
||||
</view>
|
||||
<view class="tag warning">
|
||||
@ -67,33 +67,34 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="shop-container">
|
||||
<view class="shop-tags flex">
|
||||
<!-- <view class="shop-tags flex">
|
||||
<view class="tag">
|
||||
热销
|
||||
</view>
|
||||
<view class="tag">
|
||||
热销
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
<view class="sku-title">
|
||||
薰衣草助眠香氛
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="sku-description">
|
||||
天然薰衣草精油,助眠好伴侣,舒缓身心
|
||||
{{item.description}}
|
||||
</view>
|
||||
<view class="sku-rating">
|
||||
<text class="iconfont icon-xingxing"></text>
|
||||
<text class="sku-rating-num">4.6</text>
|
||||
<text class="sku-rating-num">{{item.rating}}</text>
|
||||
<text class="sku-rating-text">(156条评价) </text>
|
||||
<text class="sku-rating-text"> 423 人喜欢</text>
|
||||
<text class="sku-rating-text"> {{item.like_count}} 人喜欢</text>
|
||||
</view>
|
||||
<view class="sku-price">
|
||||
<text>¥89</text>
|
||||
<text class="original-price">¥129</text>
|
||||
<view class="sku-price" v-if=" item.skus && item.skus.length > 0">
|
||||
<text>¥{{ item.skus[0].price }}</text>
|
||||
<text class="original-price">¥{{ item.skus[0].original_price }}</text>
|
||||
</view>
|
||||
<view class="sku-operation flex">
|
||||
<view class="sku-num">
|
||||
<text class="iconfont icon-aixin"></text> 423
|
||||
<view class="sku-num" @click="handelLike(item)">
|
||||
<text v-if="item.is_liked" class="iconfont icon-xin heart-filled"></text>
|
||||
<text v-else class="iconfont icon-xin1 heart-outline"></text> {{item.like_count}}
|
||||
</view>
|
||||
<view class="">
|
||||
<text class="iconfont icon-zhifeiji1"></text>
|
||||
@ -124,11 +125,11 @@
|
||||
<view class="tag danger">
|
||||
<text class="iconfont icon-shijian"></text>即将结束
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="shop-container">
|
||||
|
||||
|
||||
<view class="sku-title">
|
||||
3人拼团 玫瑰香水
|
||||
</view>
|
||||
@ -154,7 +155,7 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="sku-group-price flex justify-between">
|
||||
<view class="group-price">
|
||||
<view class="group-price-num">
|
||||
@ -177,14 +178,15 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="group-progress">
|
||||
<view class="group-progress-num flex justify-between">
|
||||
<text class="group-progress-text">拼团进度</text>
|
||||
<text class="number">2/3 人</text>
|
||||
</view>
|
||||
<view class="group-progress-width">
|
||||
<progress :percent="50" stroke-width="20rpx" border-radius="20" activeColor="#9810fa" />
|
||||
<progress :percent="50" stroke-width="20rpx" border-radius="20"
|
||||
activeColor="#9810fa" />
|
||||
</view>
|
||||
<view class="group-progress-num font-text flex justify-between">
|
||||
<text class="group-progress-text">已参团2人</text>
|
||||
@ -209,375 +211,475 @@
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
searchType: 1,
|
||||
searchType2: 2,
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
import request from '/api/request';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
searchType: 1,
|
||||
searchType2: 2,
|
||||
page: 1,
|
||||
page_size: 10,
|
||||
category_id: '',
|
||||
name: '',
|
||||
is_hot_selling: '',
|
||||
is_limited: '',
|
||||
shopList: '',
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.getShopList()
|
||||
},
|
||||
methods: {
|
||||
|
||||
getShopList(){
|
||||
request('xcx/products', 'get', {
|
||||
page: this.page,
|
||||
page_size: this.page_size
|
||||
}).then((res) => {
|
||||
this.shopList = res.list
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
changeSearch(index) {
|
||||
this.searchType = index
|
||||
},
|
||||
changeSearch2(index) {
|
||||
this.searchType2 = index
|
||||
}
|
||||
changeSearch(index) {
|
||||
this.searchType = index
|
||||
},
|
||||
changeSearch2(index) {
|
||||
this.searchType2 = index
|
||||
},
|
||||
handelLike(row) {
|
||||
request('xcx/product/like', 'post', {
|
||||
product_id: row.id,
|
||||
type: row.is_liked ? 2 : 1
|
||||
}).then((res) => {
|
||||
row.is_liked = !row.is_liked
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 2rpx 6rpx 0 rgb(0 0 0 / 0.1), 0 2rpx 4rpx -2rpx rgb(0 0 0 / 0.1);
|
||||
.header {
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 2rpx 6rpx 0 rgb(0 0 0 / 0.1), 0 2rpx 4rpx -2rpx rgb(0 0 0 / 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
.icon {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
vertical-align: middle;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
.icon {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
vertical-align: middle;
|
||||
margin-right: 20rpx;
|
||||
text {
|
||||
font-size: 30rpx;
|
||||
color: #9810fa;
|
||||
}
|
||||
}
|
||||
|
||||
.header-right {
|
||||
view {
|
||||
box-shadow: none;
|
||||
padding: 10rpx 10rpx;
|
||||
height: 40rpx;
|
||||
border: 0 solid transparent;
|
||||
}
|
||||
|
||||
view+view {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 40rpx 32rpx;
|
||||
|
||||
.search {
|
||||
.search-left {
|
||||
padding: 6rpx;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 2rpx 6rpx 0 rgb(0 0 0 / 0.1), 0 2rpx 4rpx -2rpx rgb(0 0 0 / 0.1);
|
||||
|
||||
view {
|
||||
border-radius: 20rpx;
|
||||
padding: 12rpx 12rpx;
|
||||
font-size: 28rpx;
|
||||
|
||||
text {
|
||||
margin: 0 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.recommend {
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.group-buying {}
|
||||
|
||||
.active {
|
||||
background-image: var(--background-linear-gradient);
|
||||
color: #fff;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 30rpx;
|
||||
color: #9810fa;
|
||||
.search-right {
|
||||
padding-top: 10rpx;
|
||||
|
||||
view {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 20rpx;
|
||||
line-height: 60rpx;
|
||||
text-align: center;
|
||||
font-size: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
view+view {
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: #f3e8ff;
|
||||
color: #9810fa;
|
||||
}
|
||||
}
|
||||
}
|
||||
.header-right{
|
||||
view{
|
||||
box-shadow: none;
|
||||
padding: 10rpx 10rpx;
|
||||
height: 40rpx;
|
||||
border: 0 solid transparent;
|
||||
}
|
||||
view+view{
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
}
|
||||
.container{
|
||||
padding: 40rpx 32rpx;
|
||||
.search{
|
||||
.search-left{
|
||||
padding: 6rpx;
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 2rpx 6rpx 0 rgb(0 0 0 / 0.1), 0 2rpx 4rpx -2rpx rgb(0 0 0 / 0.1);
|
||||
view{
|
||||
border-radius: 20rpx;
|
||||
padding: 12rpx 12rpx;
|
||||
|
||||
.shop-list {
|
||||
margin-top: 60rpx;
|
||||
|
||||
.shop-item {
|
||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
border-radius: 0 0 36rpx 36rpx;
|
||||
|
||||
image {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
}
|
||||
|
||||
.shop-container {
|
||||
padding: 80rpx 32rpx;
|
||||
|
||||
.shop-tags {
|
||||
.tag {
|
||||
font-size: 20rpx;
|
||||
color: #9810fa;
|
||||
border: 2rpx solid #e9d4ff;
|
||||
padding: 4rpx 10rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.tag+.tag {
|
||||
margin-left: 14rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.sku-title {
|
||||
margin-top: 20rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sku-description {
|
||||
margin-top: 12rpx;
|
||||
font-size: 28rpx;
|
||||
text{
|
||||
margin: 0 6rpx;
|
||||
color: #4a5565;
|
||||
}
|
||||
|
||||
.sku-rating {
|
||||
margin-top: 40rpx;
|
||||
|
||||
.iconfont {
|
||||
font-size: 32rpx;
|
||||
color: #f0b100;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.recommend{
|
||||
image{
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
.group-buying{
|
||||
|
||||
}
|
||||
.active{
|
||||
background-image: var(--background-linear-gradient);
|
||||
color: #fff;
|
||||
|
||||
}
|
||||
}
|
||||
.search-right{
|
||||
padding-top: 10rpx;
|
||||
view{
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 20rpx;
|
||||
line-height: 60rpx;
|
||||
text-align: center;
|
||||
font-size: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
view+view{
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
.active{
|
||||
background-color: #f3e8ff;
|
||||
color: #9810fa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shop-list{
|
||||
margin-top: 60rpx;
|
||||
.shop-item{
|
||||
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
border-radius: 0 0 36rpx 36rpx;
|
||||
image{
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
}
|
||||
.shop-container{
|
||||
padding: 80rpx 32rpx;
|
||||
.shop-tags{
|
||||
.tag{
|
||||
font-size: 20rpx;
|
||||
color: #9810fa;
|
||||
border: 2rpx solid #e9d4ff;
|
||||
padding: 4rpx 10rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
.tag+.tag{
|
||||
margin-left: 14rpx;
|
||||
}
|
||||
}
|
||||
.sku-title{
|
||||
margin-top: 20rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
.sku-description{
|
||||
margin-top: 12rpx;
|
||||
|
||||
.sku-rating-text {
|
||||
font-size: 28rpx;
|
||||
color: #4a5565;
|
||||
}
|
||||
.sku-rating{
|
||||
margin-top: 40rpx;
|
||||
.iconfont{
|
||||
font-size: 32rpx;
|
||||
color: #f0b100;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.sku-price {
|
||||
margin-top: 30rpx;
|
||||
font-size: 48rpx;
|
||||
color: #e7000b;
|
||||
font-weight: bold;
|
||||
|
||||
.original-price {
|
||||
margin-left: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #99a1af;
|
||||
font-weight: 400;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
.sku-operation {
|
||||
margin-top: 40rpx;
|
||||
justify-content: space-between;
|
||||
|
||||
view {
|
||||
flex: 1;
|
||||
border-radius: 12rpx;
|
||||
text-align: center;
|
||||
border: 2rpx solid rgb(0 0 0 / 0.1);
|
||||
box-shadow: 0 2rpx 4rpx 0 rgb(0 0 0 / 0.05);
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.sku-num {
|
||||
flex: 3;
|
||||
margin-right: 30rpx;
|
||||
|
||||
.iconfont {
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
.sku-rating-text{
|
||||
font-size: 28rpx;
|
||||
color: #4a5565;
|
||||
|
||||
.heart-filled {
|
||||
color: #e7000b;
|
||||
// font-size: 28rpx;
|
||||
}
|
||||
|
||||
.heart-outline {
|
||||
color: #ccc;
|
||||
// font-size: 24rpx;
|
||||
// opacity: 0.8;
|
||||
}
|
||||
}
|
||||
.sku-price{
|
||||
margin-top: 30rpx;
|
||||
font-size: 48rpx;
|
||||
color: #e7000b;
|
||||
font-weight: bold;
|
||||
.original-price{
|
||||
margin-left: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #99a1af;
|
||||
font-weight: 400;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
.sku-operation{
|
||||
margin-top: 40rpx;
|
||||
justify-content: space-between;
|
||||
view{
|
||||
flex: 1;
|
||||
border-radius: 12rpx;
|
||||
text-align: center;
|
||||
border: 2rpx solid rgb(0 0 0 / 0.1);
|
||||
box-shadow: 0 2rpx 4rpx 0 rgb(0 0 0 / 0.05);
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.sku-num{
|
||||
flex: 3;
|
||||
margin-right: 30rpx;
|
||||
.iconfont{
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
.shop-cart{
|
||||
flex: 3;
|
||||
margin-left: 30rpx;
|
||||
// color: #fff;
|
||||
background-image: var(--background-linear-gradient);
|
||||
.iconfont{
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sku-operation2{
|
||||
|
||||
view{
|
||||
flex: auto;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
.sku-num{
|
||||
flex: auto;
|
||||
|
||||
}
|
||||
.shop-cart{
|
||||
flex: auto;
|
||||
background-image: none;
|
||||
background-color: var(--color-danger);
|
||||
color: #fff;
|
||||
border-radius: 60rpx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.shop-image{
|
||||
position: relative;
|
||||
image{
|
||||
z-index: 0;
|
||||
}
|
||||
.shop-tag{
|
||||
position: absolute;
|
||||
top: 40rpx;
|
||||
left: 32rpx;
|
||||
z-index: 1;
|
||||
.tag{
|
||||
color: #fff;
|
||||
height: 48rpx;
|
||||
line-height: 48rpx;
|
||||
font-size: 20rpx;
|
||||
border-radius: 48rpx;
|
||||
padding: 0 16rpx;
|
||||
box-shadow: var(--tw-shadow);
|
||||
text{
|
||||
vertical-align: middle;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
.tag+.tag{
|
||||
|
||||
margin-left: 14rpx;
|
||||
}
|
||||
.danger{
|
||||
background-color: var(--color-danger);
|
||||
}
|
||||
.warning{
|
||||
background-color: var(--color-warning);
|
||||
}
|
||||
.success{
|
||||
background-color: var(--color-success);
|
||||
}
|
||||
}
|
||||
.buttom{
|
||||
top: auto;
|
||||
buttom: 40rpx;
|
||||
text{
|
||||
font-size: 28rpx;
|
||||
|
||||
.shop-cart {
|
||||
flex: 3;
|
||||
margin-left: 30rpx;
|
||||
// color: #fff;
|
||||
background-image: var(--background-linear-gradient);
|
||||
|
||||
.iconfont {
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.sku-group-buying{
|
||||
margin-top: 16rpx;
|
||||
padding: 24rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #fbf9fa;
|
||||
.group-img{
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 70rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
background-image: var(--background-linear-gradient);
|
||||
}
|
||||
.group-name{
|
||||
font-weight: bold;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.group-text{
|
||||
margin-top: 4rpx;
|
||||
font-size: 24rpx;
|
||||
color: #6a7282;
|
||||
text{
|
||||
margin-right: 8rpx;
|
||||
font-size: 28rpx;
|
||||
|
||||
.sku-operation2 {
|
||||
|
||||
view {
|
||||
flex: auto;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.sku-num {
|
||||
flex: auto;
|
||||
|
||||
}
|
||||
|
||||
.shop-cart {
|
||||
flex: auto;
|
||||
background-image: none;
|
||||
background-color: var(--color-danger);
|
||||
color: #fff;
|
||||
border-radius: 60rpx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.group-rating{
|
||||
font-size: 28rpx;
|
||||
color: #f0b100;
|
||||
margin-right: 20rpx;
|
||||
font-weight: bold;
|
||||
text{
|
||||
margin-right: 8rpx;
|
||||
|
||||
.shop-image {
|
||||
position: relative;
|
||||
|
||||
image {
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sku-group-price{
|
||||
margin-top: 32rpx;
|
||||
padding: 24rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #fff7ed;
|
||||
.group-price-num{
|
||||
font-size: 48rpx;
|
||||
color: #e7000b;
|
||||
font-weight: bold;
|
||||
.original-price{
|
||||
margin-left: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #99a1af;
|
||||
font-weight: 400;
|
||||
text-decoration: line-through;
|
||||
|
||||
.shop-tag {
|
||||
position: absolute;
|
||||
top: 40rpx;
|
||||
left: 32rpx;
|
||||
z-index: 1;
|
||||
|
||||
.tag {
|
||||
color: #fff;
|
||||
height: 48rpx;
|
||||
line-height: 48rpx;
|
||||
font-size: 20rpx;
|
||||
border-radius: 48rpx;
|
||||
padding: 0 16rpx;
|
||||
box-shadow: var(--tw-shadow);
|
||||
|
||||
text {
|
||||
vertical-align: middle;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tag+.tag {
|
||||
|
||||
margin-left: 14rpx;
|
||||
}
|
||||
|
||||
.danger {
|
||||
background-color: var(--color-danger);
|
||||
}
|
||||
|
||||
.warning {
|
||||
background-color: var(--color-warning);
|
||||
}
|
||||
|
||||
.success {
|
||||
background-color: var(--color-success);
|
||||
}
|
||||
}
|
||||
}
|
||||
.group-price{
|
||||
flex: 2;
|
||||
}
|
||||
.group-price-save{
|
||||
flex: 1;
|
||||
}
|
||||
.group-price-text{
|
||||
font-size: 24rpx;
|
||||
color: #4a5565;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
.save-tag{
|
||||
// display: inline-block;
|
||||
background-color: var(--color-danger);
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
.iconfont{
|
||||
margin-right: 6rpx;
|
||||
display: inline-block;
|
||||
|
||||
.buttom {
|
||||
top: auto;
|
||||
buttom: 40rpx;
|
||||
|
||||
text {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
height: 48rpx;
|
||||
line-height: 48rpx;
|
||||
padding-left: 40rpx;
|
||||
padding-right: 10rpx;
|
||||
border-radius: 48rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.save-num{
|
||||
margin-top: 16rpx;
|
||||
font-size: 24rpx;
|
||||
color: #4a5565;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.group-progress{
|
||||
margin-top: 32rpx;
|
||||
font-size: 28rpx;
|
||||
.group-progress-text{
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.number{
|
||||
color: #9810fa;
|
||||
font-weight: bold;
|
||||
}
|
||||
.group-progress-width{
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: 26rpx;
|
||||
}
|
||||
.font-text{
|
||||
color: #6a7282;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sku-group-buying {
|
||||
margin-top: 16rpx;
|
||||
padding: 24rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #fbf9fa;
|
||||
|
||||
.group-img {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 70rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
background-image: var(--background-linear-gradient);
|
||||
}
|
||||
|
||||
.group-name {
|
||||
font-weight: bold;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.group-text {
|
||||
margin-top: 4rpx;
|
||||
font-size: 24rpx;
|
||||
color: #6a7282;
|
||||
|
||||
text {
|
||||
margin-right: 8rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.group-rating {
|
||||
font-size: 28rpx;
|
||||
color: #f0b100;
|
||||
margin-right: 20rpx;
|
||||
font-weight: bold;
|
||||
|
||||
text {
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sku-group-price {
|
||||
margin-top: 32rpx;
|
||||
padding: 24rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #fff7ed;
|
||||
|
||||
.group-price-num {
|
||||
font-size: 48rpx;
|
||||
color: #e7000b;
|
||||
font-weight: bold;
|
||||
|
||||
.original-price {
|
||||
margin-left: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #99a1af;
|
||||
font-weight: 400;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
.group-price {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.group-price-save {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.group-price-text {
|
||||
font-size: 24rpx;
|
||||
color: #4a5565;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.save-tag {
|
||||
// display: inline-block;
|
||||
background-color: var(--color-danger);
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
|
||||
.iconfont {
|
||||
margin-right: 6rpx;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
height: 48rpx;
|
||||
line-height: 48rpx;
|
||||
padding-left: 40rpx;
|
||||
padding-right: 10rpx;
|
||||
border-radius: 48rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.save-num {
|
||||
margin-top: 16rpx;
|
||||
font-size: 24rpx;
|
||||
color: #4a5565;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.group-progress {
|
||||
margin-top: 32rpx;
|
||||
font-size: 28rpx;
|
||||
|
||||
.group-progress-text {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.number {
|
||||
color: #9810fa;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.group-progress-width {
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: 26rpx;
|
||||
}
|
||||
|
||||
.font-text {
|
||||
color: #6a7282;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
261
pages/login/index.vue
Normal file
261
pages/login/index.vue
Normal file
@ -0,0 +1,261 @@
|
||||
<template>
|
||||
<view class="login-page">
|
||||
<view class="login-container">
|
||||
<view class="logo-section">
|
||||
<text class="app-name">香水有毒</text>
|
||||
<text class="welcome-text">欢迎使用</text>
|
||||
</view>
|
||||
|
||||
<view class="login-form">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button class="login-btn quick-login-btn" open-type="getPhoneNumber"
|
||||
@getphonenumber="handleGetPhoneNumber" :loading="loading">
|
||||
<text class="btn-text">快捷登录</text>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<button class="login-btn quick-login-btn" @click="handleQuickLogin" :loading="loading">
|
||||
<text class="btn-text">快捷登录</text>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
|
||||
<view class="tips-section">
|
||||
<text class="tips-text">点击快捷登录,即表示您同意</text>
|
||||
<text class="link-text">《用户协议》</text>
|
||||
<text class="tips-text">和</text>
|
||||
<text class="link-text">《隐私政策》</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from '@/api/request.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 处理获取手机号授权
|
||||
async handleGetPhoneNumber(e) {
|
||||
console.log('获取手机号授权结果:', e);
|
||||
|
||||
if (e.detail.errMsg === 'getPhoneNumber:ok') {
|
||||
// 用户同意授权
|
||||
this.loading = true;
|
||||
try {
|
||||
// 先获取微信登录code
|
||||
const loginRes = await this.wxLogin();
|
||||
if (!loginRes.code) {
|
||||
throw new Error('获取微信登录code失败');
|
||||
}
|
||||
|
||||
// 调用登录接口,传递code和加密数据
|
||||
const loginData = {
|
||||
code: e.detail.code,
|
||||
invitation_code: e.detail.encryptedData,
|
||||
// iv: e.detail.iv
|
||||
};
|
||||
|
||||
const result = await request('xcx/quick_login', 'POST', loginData);
|
||||
await wx.setStorageSync('access_token', result.token);
|
||||
await wx.setStorageSync('is_personal_information_complete', result.result.is_personal_information_complete);
|
||||
if (result.is_personal_information_complete) {
|
||||
wx.navigateBack();
|
||||
} else {
|
||||
wx.navigateTo({
|
||||
url: `/pages/my/editInfo/index`,
|
||||
});
|
||||
}
|
||||
// 保存token
|
||||
// if (result.token) {
|
||||
// wx.setStorageSync('access_token', result.token);
|
||||
// } else if (result.data && result.data.token) {
|
||||
// wx.setStorageSync('access_token', result.data.token);
|
||||
// }
|
||||
|
||||
// // 保存用户信息(如果有)
|
||||
// if (result.userInfo) {
|
||||
// wx.setStorageSync('userInfo', result.userInfo);
|
||||
// } else if (result.data && result.data.userInfo) {
|
||||
// wx.setStorageSync('userInfo', result.data.userInfo);
|
||||
// }
|
||||
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
|
||||
// 登录成功后跳转
|
||||
// setTimeout(() => {
|
||||
// // 检查是否有返回路径,否则跳转到首页
|
||||
// const pages = getCurrentPages();
|
||||
// if (pages.length > 1) {
|
||||
// uni.navigateBack();
|
||||
// } else {
|
||||
// uni.switchTab({
|
||||
// url: '/pages/index/index'
|
||||
// });
|
||||
// }
|
||||
// }, 1500);
|
||||
|
||||
} catch (error) {
|
||||
console.error('登录失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '登录失败,请重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
} else {
|
||||
// 用户拒绝授权
|
||||
uni.showToast({
|
||||
title: '需要授权手机号才能登录',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 微信登录获取code
|
||||
wxLogin() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef MP-WEIXIN
|
||||
wx.login({
|
||||
success: (res) => {
|
||||
if (res.code) {
|
||||
resolve(res);
|
||||
} else {
|
||||
reject(new Error('获取code失败'));
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
// 非微信小程序环境,使用uni.login
|
||||
uni.login({
|
||||
provider: 'weixin',
|
||||
success: (res) => {
|
||||
resolve(res);
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
});
|
||||
},
|
||||
|
||||
// 非微信环境的快捷登录(用于其他平台)
|
||||
handleQuickLogin() {
|
||||
uni.showToast({
|
||||
title: '当前平台不支持快捷登录',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.login-page {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, #9810fa 0%, #f5f5f5 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40rpx 32rpx;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
width: 100%;
|
||||
max-width: 600rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 32rpx;
|
||||
padding: 80rpx 60rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(152, 16, 250, 0.15);
|
||||
}
|
||||
|
||||
.logo-section {
|
||||
text-align: center;
|
||||
margin-bottom: 80rpx;
|
||||
}
|
||||
|
||||
.app-name {
|
||||
display: block;
|
||||
font-size: 56rpx;
|
||||
font-weight: bold;
|
||||
color: #1A1A1A;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.welcome-text {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: #6a7282;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
margin-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
width: 100%;
|
||||
height: 96rpx;
|
||||
background: linear-gradient(135deg, #9810fa 0%, #7a0bc7 100%);
|
||||
border-radius: 48rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
box-shadow: 0 8rpx 24rpx rgba(152, 16, 250, 0.3);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.login-btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.login-btn:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 4rpx 12rpx rgba(152, 16, 250, 0.3);
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
color: #ffffff;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.quick-login-btn {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.tips-section {
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #9ca3af;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.tips-text {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.link-text {
|
||||
color: #9810fa;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
</style>
|
||||
@ -8,26 +8,27 @@
|
||||
<view class="form-card">
|
||||
<view class="form-item">
|
||||
<text class="form-label">姓名</text>
|
||||
<input
|
||||
class="form-input"
|
||||
v-model="form.name"
|
||||
type="text"
|
||||
placeholder="请输入您的姓名"
|
||||
placeholder-class="form-placeholder"
|
||||
/>
|
||||
<input class="form-input" v-model="form.username" type="text" placeholder="请输入您的姓名"
|
||||
placeholder-class="form-placeholder" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="form-label">性别</text>
|
||||
<picker mode="selector" :range="genderOptions" range-key="label" :value="genderIndex"
|
||||
@change="handleGenderChange">
|
||||
<view class="form-picker">
|
||||
<text :class="form.sex ? '' : 'form-placeholder'">
|
||||
{{ genderText || '请选择性别' }}
|
||||
</text>
|
||||
<text class="picker-arrow">›</text>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="form-label">手机号</text>
|
||||
<input
|
||||
class="form-input"
|
||||
v-model="form.phone"
|
||||
type="number"
|
||||
maxlength="11"
|
||||
placeholder="请输入常用手机号"
|
||||
placeholder-class="form-placeholder"
|
||||
/>
|
||||
<input class="form-input" v-model="form.mobile" type="number" maxlength="11" placeholder="请输入常用手机号"
|
||||
placeholder-class="form-placeholder" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<!-- <view class="form-item">
|
||||
<text class="form-label">邮箱</text>
|
||||
<input
|
||||
class="form-input"
|
||||
@ -36,8 +37,8 @@
|
||||
placeholder="请输入联系邮箱"
|
||||
placeholder-class="form-placeholder"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
</view> -->
|
||||
<!-- <view class="form-item">
|
||||
<text class="form-label">地址</text>
|
||||
<textarea
|
||||
class="form-textarea"
|
||||
@ -46,7 +47,7 @@
|
||||
placeholder-class="form-placeholder"
|
||||
auto-height="true"
|
||||
/>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<view class="tips-card">
|
||||
@ -64,34 +65,58 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from '@/api/request.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
address: ''
|
||||
}
|
||||
username: '',
|
||||
sex: null,
|
||||
mobile: '',
|
||||
// email: '',
|
||||
// address: ''
|
||||
},
|
||||
genderOptions: [
|
||||
{ label: '男', value: 1 },
|
||||
{ label: '女', value: 2 }
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
genderIndex() {
|
||||
if (!this.form.sex) return 0;
|
||||
const option = this.genderOptions.find(item => item.value === this.form.sex);
|
||||
return option ? this.genderOptions.indexOf(option) : 0;
|
||||
},
|
||||
genderText() {
|
||||
if (!this.form.sex) return '';
|
||||
const option = this.genderOptions.find(item => item.value === this.form.sex);
|
||||
return option ? option.label : '';
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.loadProfile();
|
||||
},
|
||||
methods: {
|
||||
loadProfile() {
|
||||
try {
|
||||
const stored = uni.getStorageSync('userProfile');
|
||||
if (stored) {
|
||||
this.form = {
|
||||
...this.form,
|
||||
...stored
|
||||
};
|
||||
const is_personal_information_complete = uni.getStorageSync('is_personal_information_complete');
|
||||
if (is_personal_information_complete) {
|
||||
request('xcx/get_user_info', 'GET').then(res => {
|
||||
this.form = {
|
||||
...this.form,
|
||||
...res
|
||||
};
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('加载个人信息失败', error);
|
||||
}
|
||||
},
|
||||
handleGenderChange(e) {
|
||||
const index = e.detail.value;
|
||||
this.form.sex = this.genderOptions[index].value;
|
||||
},
|
||||
validatePhone(phone) {
|
||||
const phoneReg = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/;
|
||||
return phoneReg.test(phone);
|
||||
@ -102,32 +127,48 @@ export default {
|
||||
return emailReg.test(email);
|
||||
},
|
||||
handleCancel() {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
|
||||
const is_personal_information_complete = uni.getStorageSync('is_personal_information_complete');
|
||||
if (is_personal_information_complete) {
|
||||
wx.navigateBack();
|
||||
} else {
|
||||
uni.setStorageSync('is_personal_information_complete', true);
|
||||
wx.navigateTo({
|
||||
url: `/pages/my/editInfo/index`,
|
||||
});
|
||||
}
|
||||
},
|
||||
handleSubmit() {
|
||||
if (!this.form.name.trim()) {
|
||||
if (!this.form.username.trim()) {
|
||||
return this.showToast('请填写姓名');
|
||||
}
|
||||
if (!this.form.phone.trim() || !this.validatePhone(this.form.phone.trim())) {
|
||||
if (!this.form.sex || (this.form.sex !== 1 && this.form.sex !== 2)) {
|
||||
return this.showToast('请选择性别');
|
||||
}
|
||||
if (!this.form.mobile.trim() || !this.validatePhone(this.form.mobile.trim())) {
|
||||
return this.showToast('请填写有效的手机号');
|
||||
}
|
||||
if (this.form.email.trim() && !this.validateEmail(this.form.email.trim())) {
|
||||
return this.showToast('请填写有效的邮箱');
|
||||
}
|
||||
if (!this.form.address.trim()) {
|
||||
return this.showToast('请填写联系地址');
|
||||
}
|
||||
// if (this.form.email.trim() && !this.validateEmail(this.form.email.trim())) {
|
||||
// return this.showToast('请填写有效的邮箱');
|
||||
// }
|
||||
// if (!this.form.address.trim()) {
|
||||
// return this.showToast('请填写联系地址');
|
||||
// }
|
||||
|
||||
try {
|
||||
uni.setStorageSync('userProfile', { ...this.form });
|
||||
this.showToast('保存成功', 'success');
|
||||
setTimeout(() => {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
}, 800);
|
||||
request('xcx/set_user_info', 'POST', this.form).then(res => {
|
||||
this.showToast('保存成功', 'success');
|
||||
const is_personal_information_complete = uni.getStorageSync('is_personal_information_complete');
|
||||
if (is_personal_information_complete) {
|
||||
wx.navigateBack();
|
||||
} else {
|
||||
uni.setStorageSync('is_personal_information_complete', true);
|
||||
wx.navigateTo({
|
||||
url: `/pages/my/editInfo/index`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
this.showToast('信息保存失败,请稍后重试');
|
||||
console.error('保存个人信息失败', error);
|
||||
@ -192,8 +233,10 @@ export default {
|
||||
color: #1a1a1a;
|
||||
font-weight: 500;
|
||||
}
|
||||
.form-input{
|
||||
|
||||
.form-input {
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
}
|
||||
|
||||
.form-input,
|
||||
@ -201,10 +244,29 @@ export default {
|
||||
width: 100%;
|
||||
background: #f5f7fb;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 28rpx;
|
||||
font-size: 28rpx;
|
||||
color: #1a1a1a;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-picker {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background: #f5f7fb;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx 28rpx;
|
||||
font-size: 28rpx;
|
||||
color: #1a1a1a;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.picker-arrow {
|
||||
font-size: 32rpx;
|
||||
color: #b0b3ba;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
|
||||
@ -2,13 +2,15 @@
|
||||
<view class="page">
|
||||
<view class="profile-card">
|
||||
<view class="profile-header">
|
||||
<view class="avatar-wrapper">
|
||||
<view class="avatar">100x100</view>
|
||||
<view class="avatar-wrapper" @click="uploadAvatar">
|
||||
<view class="avatar">
|
||||
<image :src="avatarUrl" mode="aspectFill" @error="handleImageError"></image>
|
||||
</view>
|
||||
<view class="avatar-upload">📷</view>
|
||||
</view>
|
||||
<view class="profile-info">
|
||||
<view class="title-row">
|
||||
<text class="name">香香公主</text>
|
||||
<text class="name">{{ userInfo.username }}</text>
|
||||
<view class="vip-badge">
|
||||
<text>品鉴会员</text>
|
||||
</view>
|
||||
@ -32,13 +34,8 @@
|
||||
</view>
|
||||
|
||||
<view class="tabs">
|
||||
<view
|
||||
class="tab-item"
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="tab"
|
||||
:class="{ active: index === currentTab }"
|
||||
@click="handleTabClick(index)"
|
||||
>
|
||||
<view class="tab-item" v-for="(tab, index) in tabs" :key="tab" :class="{ active: index === currentTab }"
|
||||
@click="handleTabClick(index)">
|
||||
{{ tab }}
|
||||
</view>
|
||||
</view>
|
||||
@ -48,10 +45,7 @@
|
||||
<view class="monthly-list">
|
||||
<view class="monthly-item" v-for="item in monthlyData" :key="item.label">
|
||||
<text class="monthly-label">{{ item.label }}</text>
|
||||
<text
|
||||
class="monthly-value"
|
||||
:style="{ color: item.color || '#1A1A1A' }"
|
||||
>
|
||||
<text class="monthly-value" :style="{ color: item.color || '#1A1A1A' }">
|
||||
{{ item.value }}
|
||||
</text>
|
||||
</view>
|
||||
@ -85,11 +79,7 @@
|
||||
<text class="amount-value">{{ order.amount }}</text>
|
||||
</view>
|
||||
<view class="order-actions">
|
||||
<view
|
||||
class="order-action"
|
||||
v-for="action in order.actions"
|
||||
:key="action.label"
|
||||
>
|
||||
<view class="order-action" v-for="action in order.actions" :key="action.label">
|
||||
{{ action.label }}
|
||||
</view>
|
||||
</view>
|
||||
@ -119,12 +109,8 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="achievements-card" v-if="currentTab === 3">
|
||||
<view
|
||||
class="achievement-item"
|
||||
v-for="achievement in achievements"
|
||||
:key="achievement.title"
|
||||
:class="{ highlight: achievement.highlight }"
|
||||
>
|
||||
<view class="achievement-item" v-for="achievement in achievements" :key="achievement.title"
|
||||
:class="{ highlight: achievement.highlight }">
|
||||
<view class="achievement-left">
|
||||
<view class="achievement-icon" :style="{ backgroundColor: achievement.iconBg }">
|
||||
<text class="achievement-icon-text">{{ achievement.icon }}</text>
|
||||
@ -132,15 +118,10 @@
|
||||
<view class="achievement-info">
|
||||
<text class="achievement-title">{{ achievement.title }}</text>
|
||||
<text class="achievement-desc">{{ achievement.desc }}</text>
|
||||
<view
|
||||
class="achievement-progress"
|
||||
v-if="achievement.progressText"
|
||||
>
|
||||
<view class="achievement-progress" v-if="achievement.progressText">
|
||||
<view class="achievement-progress-bar">
|
||||
<view
|
||||
class="achievement-progress-fill"
|
||||
:style="{ width: achievement.progress + '%' }"
|
||||
></view>
|
||||
<view class="achievement-progress-fill"
|
||||
:style="{ width: achievement.progress + '%' }"></view>
|
||||
</view>
|
||||
<text class="achievement-progress-text">{{ achievement.progressText }}</text>
|
||||
</view>
|
||||
@ -186,25 +167,24 @@
|
||||
<view class="quick-card">
|
||||
<view class="quick-title">快捷功能</view>
|
||||
<view class="quick-grid">
|
||||
<view
|
||||
class="quick-item"
|
||||
v-for="action in quickActions"
|
||||
:key="action.label"
|
||||
>
|
||||
<view class="quick-item" v-for="action in quickActions" :key="action.label">
|
||||
<view class="quick-icon">{{ action.icon }}</view>
|
||||
<text class="quick-label">{{ action.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from '@/api/request.js';
|
||||
import uploadFile from '@/api/upload.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
userInfo: {},
|
||||
currentTab: 0,
|
||||
stats: [
|
||||
{ icon: '🎁', value: '1280', label: '当前积分', color: '#7B43FF' },
|
||||
@ -315,7 +295,87 @@ export default {
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
avatarUrl() {
|
||||
// 如果有头像URL且不为空,则使用头像URL,否则使用默认头像
|
||||
if (this.userInfo && this.userInfo.avatar_url && this.userInfo.avatar_url.trim() !== '') {
|
||||
return this.userInfo.avatar_url;
|
||||
}
|
||||
// 默认头像:使用base64编码的SVG头像占位符(预编码,兼容所有平台)
|
||||
// 这是一个圆形灰色背景,带有用户图标的默认头像
|
||||
return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYwIiBoZWlnaHQ9IjE2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSI4MCIgY3k9IjgwIiByPSI4MCIgZmlsbD0iI2U1ZTdlYSIvPjxjaXJjbGUgY3g9IjgwIiBjeT0iNjUiIHI9IjI1IiBmaWxsPSIjOWZhMGFmIi8+PHBhdGggZD0iTSA4MCAxMDAgUSA1MCAxMDAgNTAgMTMwIEwgNTAgMTYwIEwgMTEwIDE2MCBMIDExMCAxMzAgUSAxMTAgMTAwIDgwIDEwMCBaIiBmaWxsPSIjOWZhMGFmIi8+PC9zdmc+';
|
||||
}
|
||||
},
|
||||
onShow: function () {
|
||||
const token = wx.getStorageSync('access_token');
|
||||
if (!token) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/login/index'
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
this.loadProfile();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleImageError(e) {
|
||||
// 图片加载失败时,使用默认头像
|
||||
console.log('头像加载失败,使用默认头像', e);
|
||||
},
|
||||
loadProfile() {
|
||||
try {
|
||||
request('xcx/get_user_info', 'GET').then(res => {
|
||||
this.userInfo = res
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('加载个人信息失败', error);
|
||||
}
|
||||
},
|
||||
uploadAvatar() {
|
||||
console.log('uploadAvatar 被点击');
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
mediaType: ['image'],
|
||||
sizeType: ['compressed', 'original'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: (res) => {
|
||||
console.log('选择图片成功', res);
|
||||
const tempFilePaths = res.tempFilePaths;
|
||||
if (tempFilePaths && tempFilePaths.length > 0) {
|
||||
uni.showLoading({
|
||||
title: '上传中...'
|
||||
});
|
||||
uploadFile(tempFilePaths[0]).then((res) => {
|
||||
console.log('上传成功', res);
|
||||
this.userInfo.avatar_url = res;
|
||||
request('xcx/set_user_info', 'POST', {
|
||||
avatar_url: res,
|
||||
username: this.userInfo.username,
|
||||
sex: this.userInfo.sex,
|
||||
mobile: this.userInfo.mobile,
|
||||
}).then(res => {
|
||||
uni.hideLoading({
|
||||
title: '上传成功...'
|
||||
});
|
||||
console.log('设置头像成功', res);
|
||||
}).catch((err) => {
|
||||
uni.hideLoading({
|
||||
title: '上传失败...'
|
||||
});
|
||||
console.error('设置头像失败', err);
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('选择图片失败', err);
|
||||
uni.showToast({
|
||||
title: '选择图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
handleTabClick(index) {
|
||||
this.currentTab = index;
|
||||
},
|
||||
@ -328,7 +388,7 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style scoped lang="scss">
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
/* padding: 24rpx; */
|
||||
@ -342,7 +402,7 @@ export default {
|
||||
.profile-card {
|
||||
background-color: #ffffff;
|
||||
/* border-radius: 24rpx; */
|
||||
|
||||
|
||||
padding-bottom: 24rpx;
|
||||
}
|
||||
|
||||
@ -372,6 +432,13 @@ export default {
|
||||
font-size: 26rpx;
|
||||
color: #ffffff;
|
||||
border: 4rpx solid rgba(255, 255, 255, 0.4);
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-upload {
|
||||
@ -384,10 +451,13 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
font-size: 32rpx;
|
||||
box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.1);
|
||||
pointer-events: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.profile-info {
|
||||
@ -450,7 +520,7 @@ export default {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 24rpx;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 5057334 */
|
||||
src: url('//at.alicdn.com/t/c/font_5057334_yrkd6oeyr39.woff2?t=1762676246439') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_5057334_yrkd6oeyr39.woff?t=1762676246439') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_5057334_yrkd6oeyr39.ttf?t=1762676246439') format('truetype');
|
||||
src: url('//at.alicdn.com/t/c/font_5057334_7ak9qra77f.woff2?t=1763287992869') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_5057334_7ak9qra77f.woff?t=1763287992869') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_5057334_7ak9qra77f.ttf?t=1763287992869') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -13,6 +13,14 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-xin:before {
|
||||
content: "\e641";
|
||||
}
|
||||
|
||||
.icon-xin1:before {
|
||||
content: "\e6cd";
|
||||
}
|
||||
|
||||
.icon-lihe:before {
|
||||
content: "\11c33";
|
||||
}
|
||||
@ -60,7 +68,3 @@
|
||||
.icon-sousuo:before {
|
||||
content: "\e61f";
|
||||
}
|
||||
|
||||
.icon-aixin:before {
|
||||
content: "\e8ab";
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user