feat: 新增index.html文件并更新多个页面样式和结构

This commit is contained in:
pikachu1995@126.com
2026-07-06 13:53:54 +08:00
parent 5f293d929d
commit b1743cefb0
20 changed files with 821 additions and 288 deletions

View File

@@ -58,7 +58,7 @@ LILISHOP 是基于 Spring Boot / Spring Cloud / Vue / Uniapp 开发的 Java 开
### 1. 项目简介
**Lilishop** 是一款功能完善的B2B2C多商户商城系统采用前后端分离架构全端代码开源。
后端基于 **SpringBoot3** 构建,具备高内聚、低耦合的特性,支持分布式部署。
后端基于 **SpringBoot4** 构建,具备高内聚、低耦合的特性,支持分布式部署。
前端覆盖PC、H5、小程序和APP基于 **Vue****uni-app** 开发。
- **官方网站**: <https://pickmall.cn>

View File

@@ -15,12 +15,13 @@
<script>
import config from "@/config/config";
import logoImg from "@/icon.png";
export default {
data() {
return {
config, // 设置工具类
weChat: false, // 是否微信浏览器该项为true时不显示 当前整个页面
logo: require("@/icon.png"), //显示的圆形logo
logo: logoImg, //显示的圆形logo
};
},
mounted() {

View File

@@ -20,13 +20,14 @@
<script>
// 引入绘制插件
import DrawPoster from "@/js_sdk/u-draw-poster";
import logoImg from "@/pages/passport/static/logo-title.png";
export default {
data: () => ({
imgUrl: "", //绘制出来的图片路径
show: false, //是否展示模态框
dp: {}, //绘制的dp对象用于存储绘制等一些方法。
logo: require("@/pages/passport/static/logo-title.png"), //本地logo地址
logo: logoImg, //本地logo地址
}),
props: {

View File

@@ -213,7 +213,8 @@
display: flex;
flex-wrap: wrap;
margin: 10rpx 20rpx 284rpx;
width: 100%;
width: calc(100% - 40rpx);
box-sizing: border-box;
&.goods-list--embedded {
margin-bottom: 20rpx;

View File

@@ -18,14 +18,16 @@
import DrawPoster from "@/js_sdk/u-draw-poster";
// 生成二维码
import uQRCode from '@/components/Sansnn-uQRCode/uqrcode.js';
import logoImg from "@/pages/passport/static/logo-title.png";
import myFaceImg from "@/pages/passport/static/missing-face.png";
export default {
data: () => ({
imgUrl: "", //绘制出来的图片路径
show: false, //是否展示模态框
dp: {}, //绘制的dp对象用于存储绘制等一些方法。
logo: require("@/pages/passport/static/logo-title.png"), // 本地logo地址
myFace: require("@/pages/passport/static/missing-face.png"), // 本地默认头像
logo: logoImg, // 本地logo地址
myFace: myFaceImg, // 本地默认头像
sharingLink: '', // 二维码链接
}),
props: {

View File

@@ -2,10 +2,11 @@
<view class="xt__verify-code">
<!-- 输入框 -->
<input
ref="codeInput"
id="xt__input"
:value="code"
class="xt__input"
:focus="isFocus"
:focus="focused"
:password="isPassword"
:type="inputType"
:maxlength="size"
@@ -23,7 +24,7 @@
></view>
<!-- 输入框 - -->
<view id="xt__input-ground" class="xt__input-ground">
<view id="xt__input-ground" class="xt__input-ground" @click="focusInput">
<template v-for="(item, index) in size" :key="index">
<view
:style="{ borderColor: code.length === index && cursorVisible ? boxActiveColor : boxNormalColor }"
@@ -51,7 +52,12 @@
*/
export default {
name: 'xt-verify-code',
emits: ['update:modelValue', 'input', 'confirm'],
props: {
modelValue: {
type: String,
default: () => ''
},
value: {
type: String,
default: () => ''
@@ -89,12 +95,9 @@ export default {
default: () => '#000000'
}
},
model: {
prop: 'value',
event: 'input'
},
data() {
return {
focused: false,
cursorVisible: false,
cursorHeight: 35,
code: '', // 输入的验证码
@@ -102,12 +105,31 @@ export default {
};
},
created() {
this.code = this.modelValue || this.value || '';
this.focused = this.isFocus;
this.cursorVisible = this.isFocus;
},
mounted() {
this.init();
if (this.isFocus) {
this.$nextTick(() => {
this.focusInput();
});
}
},
methods: {
focusInput() {
this.focused = false;
this.$nextTick(() => {
this.focused = true;
// #ifdef H5
const inputEl = this.$refs.codeInput;
if (inputEl && typeof inputEl.focus === 'function') {
inputEl.focus();
}
// #endif
});
},
/**
* @description 初始化
*/
@@ -159,7 +181,9 @@ export default {
// 输入框输入变化的回调
input(e) {
const value = e.detail.value;
this.code = value;
this.cursorVisible = value.length !== this.size;
this.$emit('update:modelValue', value);
this.$emit('input', value);
this.inputSuccess(value);
},
@@ -187,8 +211,11 @@ export default {
}
},
watch: {
modelValue(val) {
this.code = val || '';
},
value(val) {
this.code = val;
this.code = val || '';
}
}
};
@@ -200,11 +227,13 @@ export default {
box-sizing: border-box;
.xt__input {
height: 100%;
width: 200%;
position: absolute;
left: -100%;
z-index: 1;
top: 0;
left: 0;
height: 100%;
width: 100%;
opacity: 0;
z-index: 2;
}
.xt__cursor {
position: absolute;
@@ -212,6 +241,8 @@ export default {
transform: translateY(-50%);
display: inline-block;
width: 2px;
z-index: 1;
pointer-events: none;
animation-name: cursor;
animation-duration: 0.8s;
animation-iteration-count: infinite;
@@ -223,11 +254,14 @@ export default {
align-items: center;
width: 100%;
box-sizing: border-box;
position: relative;
z-index: 1;
.xt__box {
position: relative;
display: inline-block;
width: 76rpx;
height: 112rpx;
pointer-events: none;
&-bottom {
border-bottom-width: 2px;
border-bottom-style: solid;

View File

@@ -15,7 +15,7 @@ export default {
imWebSrc: "https://im.pickmall.cn", //IM地址
baseWsUrl: "wss://im-api.pickmall.cn/lili/webSocket", // IM WS 地址
enableGetClipboard: false, //是否启用粘贴板获取 scanAuthNavigation 中的链接,如果匹配则会跳转到对应页面
enableMiniBarStartUpApp: true, //是否在h5中右侧浮空按钮点击启动app
enableMiniBarStartUpApp: false, //是否在h5中右侧浮空按钮点击启动app
/**
* 如需更换主题请修改此处以及uni.scss中的全局颜色
*/

17
index.html Normal file
View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
/>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>

View File

@@ -14,17 +14,17 @@
</view>
</view>
<u-cell-group class="cell-group">
<u-cell-group class="cell-group" :border="false">
<!-- #ifdef APP-PLUS -->
<u-cell v-if="IosWhether" isLink title="去评分" @click="checkStar"></u-cell>
<u-cell isLink title="功能介绍" @click="navigateTo('/pages/mine/set/versionFunctionList')"></u-cell>
<u-cell isLink title="检查更新" @click="checkUpdate"></u-cell>
<u-cell v-if="IosWhether" is-link title="去评分" @click="checkStar"></u-cell>
<u-cell is-link title="功能介绍" @click="navigateTo('/pages/mine/set/versionFunctionList')"></u-cell>
<u-cell is-link title="检查更新" @click="checkUpdate"></u-cell>
<!-- #endif -->
<u-cell isLink title="证照信息" @click="navigateTo('/pages/mine/help/tips?type=LICENSE_INFORMATION')"></u-cell>
<u-cell isLink title="服务协议" @click="navigateTo('/pages/mine/help/tips?type=USER_AGREEMENT')"></u-cell>
<u-cell isLink title="隐私协议" @click="navigateTo('/pages/mine/help/tips?type=PRIVACY_POLICY')"></u-cell>
<u-cell isLink title="关于我们" @click="navigateTo('/pages/mine/help/tips?type=ABOUT')"></u-cell>
<u-cell is-link title="证照信息" @click="navigateTo('/pages/mine/help/tips?type=LICENSE_INFORMATION')"></u-cell>
<u-cell is-link title="服务协议" @click="navigateTo('/pages/mine/help/tips?type=USER_AGREEMENT')"></u-cell>
<u-cell is-link title="隐私协议" @click="navigateTo('/pages/mine/help/tips?type=PRIVACY_POLICY')"></u-cell>
<u-cell is-link title="关于我们" @click="navigateTo('/pages/mine/help/tips?type=ABOUT')"></u-cell>
</u-cell-group>
<view class="intro">
@@ -131,21 +131,25 @@ export default {
<style lang="scss" scoped>
page {
background: #fff !important;
background: #f8f8f8 !important;
}
.edition-intro {
width: 100%;
min-height: 100vh;
background: #fff;
box-sizing: border-box;
background: #f8f8f8;
display: flex;
flex-direction: column;
padding-bottom: calc(40rpx + env(safe-area-inset-bottom));
}
.header-block {
display: flex;
flex-direction: column;
align-items: center;
padding: 80rpx 0 48rpx;
padding: 60rpx 0 40rpx;
background: #fff;
}
.logo {
@@ -169,10 +173,20 @@ page {
.cell-group {
width: 100%;
margin-top: 20rpx;
background: #fff;
}
:deep(.u-cell-group) {
width: 100%;
}
:deep(.u-cell) {
padding: 0 30rpx;
width: 100%;
}
:deep(.u-cell__body) {
padding: 28rpx 30rpx;
}
:deep(.u-cell__title-text) {
@@ -184,23 +198,35 @@ page {
color: #ccc !important;
}
:deep(.u-line) {
width: 100% !important;
margin: 0 !important;
}
.intro {
margin-top: auto;
width: 100%;
padding: 48rpx 40rpx 60rpx;
padding: 48rpx 40rpx calc(80rpx + env(safe-area-inset-bottom));
text-align: center;
font-size: 24rpx;
line-height: 1.6;
line-height: 1.8;
color: #666;
letter-spacing: 1rpx;
box-sizing: border-box;
}
.intro-line {
margin-top: 16rpx;
margin-top: 12rpx;
}
.intro-link {
color: #003a8c;
}
</style>
<style lang="scss">
/* #ifdef H5 */
page {
min-height: 100vh;
}
/* #endif */
</style>

View File

@@ -1,36 +1,55 @@
<template>
<div class="feedBack">
<div class="feedBack-box">
<h4>猜你想问</h4>
<div class="feedBack-item" :class="{'active':feedBack.type == item.value }" @click="handleClick(index)" v-for="(item,index) in list" :key="index">
{{item.text}}
</div>
</div>
<view class="feedBack">
<view class="feedBack-box">
<view class="box-title">猜你想问</view>
<view
class="feedBack-item"
:class="{ active: feedBack.type == item.value }"
@click="handleClick(index)"
v-for="(item, index) in list"
:key="index"
>
{{ item.text }}
</view>
</view>
<div class="feedBack-box">
<h4>问题反馈 <span style="margin-left:10rpx;" v-if="feedBack.type">@{{ list.find(item=>{return item.value == feedBack.type }).text }}</span></h4>
<u-input class="field-input" height="500" border="none" v-model="feedBack.context" type="textarea" placeholder="请输入反馈信息">
</u-input>
</div>
<view class="feedBack-box">
<view class="box-title">问题反馈
<text class="box-tag" v-if="feedBack.type">@{{ list.find(item => item.value == feedBack.type).text }}</text>
</view>
<u-textarea
class="field-textarea"
v-model="feedBack.context"
placeholder="请输入反馈信息"
border="none"
height="240"
maxlength="500"
></u-textarea>
</view>
<!-- 上传凭证 -->
<div class="feedBack-box">
<view class="opt-view">
<view class="img-title">上传凭证最多2张</view>
<view class="feedBack-box">
<view class="box-title">上传凭证最多2张</view>
<view class="images-view">
<u-upload :file-list="uploadFileList" :auto-upload="false" width="150" @afterRead="onUploadAfterRead" :max-count="2"></u-upload>
</view>
</view>
</div>
<div class="feedBack-box">
<h4>手机号</h4>
<u-input border="none" v-model="feedBack.mobile" placeholder="请输入您的手机号">
</u-input>
</div>
<view class="feedBack-box">
<view class="box-title">手机号</view>
<u-input
class="field-input"
v-model="feedBack.mobile"
type="number"
maxlength="11"
border="none"
placeholder="请输入您的手机号"
:custom-style="inputStyle"
></u-input>
</view>
<div class="submit" @click="submit()">提交</div>
</div>
<view class="submit" @click="submit()">提交</view>
</view>
</template>
@@ -45,7 +64,15 @@ export default {
storage,
config,
feedBack: {
type: "FUNCTION", //默认反馈问题为 '功能相关'
type: "FUNCTION",
context: "",
mobile: "",
},
inputStyle: {
background: "#fafafa",
borderRadius: "12rpx",
padding: "0 24rpx",
height: "80rpx",
},
uploadFileList: [],
list: [
@@ -116,49 +143,86 @@ export default {
</script>
<style lang="scss" scoped>
page {
background: #f8f8f8;
}
.submit {
text-align: center;
background: $light-color;
height: 70rpx;
line-height: 70rpx;
height: 88rpx;
line-height: 88rpx;
color: #fff;
width: 92%;
margin-bottom: 100rpx;
margin: 0 auto;
margin: 40rpx auto 60rpx;
border-radius: 100px;
font-size: 30rpx;
}
.active{
.active {
color: $light-color !important;
font-weight: bold;
}
.feedBack {
padding-bottom: 100rpx;
width: 100%;
box-sizing: border-box;
padding: 20rpx 24rpx 40rpx;
min-height: 100vh;
background: #f8f8f8;
}
.feedBack-box {
background: #fff;
border-radius: 20rpx;
padding: 32rpx;
margin-bottom: 40rpx;
margin-bottom: 20rpx;
}
::v-deep .u-input__textarea {
padding: 12px;
.box-title {
font-size: 30rpx;
font-weight: 600;
color: #333;
line-height: 1.4;
}
.feedBack-box:nth-of-type(1) {
border-top-left-radius: 0;
border-top-right-radius: 0;
.box-tag {
margin-left: 10rpx;
font-size: 26rpx;
font-weight: normal;
color: $light-color;
}
.feedBack-item {
margin: 20rpx 0;
font-size: 24rpx;
font-size: 28rpx;
color: #666;
}
h4 {
font-size: 30rpx;
.field-textarea {
margin-top: 20rpx;
:deep(.u-textarea) {
background: #fafafa !important;
border-radius: 12rpx;
padding: 20rpx;
box-sizing: border-box;
}
:deep(.u-textarea__field) {
width: 100%;
font-size: 28rpx;
line-height: 1.6;
color: #333;
}
}
.field-input {
margin: 20rpx 0;
padding: 20rpx 0;
background: #fafafa;
border-radius: 0.6em;
margin-top: 20rpx;
width: 100%;
}
.images-view {
margin-top: 20rpx;
}
</style>

View File

@@ -14,21 +14,21 @@
<u-icon color="#ccc" name="arrow-right" size="16"></u-icon>
</view>
<u-cell-group class="cell-group">
<u-cell-group class="cell-group" :border="false">
<!-- #ifdef APP-PLUS -->
<u-cell :isLink="false" title="清除缓存" :value="fileSizeString" @click="clearCache"></u-cell>
<u-cell is-link title="清除缓存" :value="fileSizeString" @click="clearCache"></u-cell>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<u-cell
:isLink="false"
is-link
title="安全中心"
@click="navigateTo('/pages/mine/set/securityCenter/securityCenter')"
></u-cell>
<!-- #endif -->
<u-cell :isLink="false" title="用户注销" v-if="userInfo.id" @click="logoff"></u-cell>
<u-cell :isLink="false" title="意见反馈" @click="navigateTo('/pages/mine/set/feedBack')"></u-cell>
<u-cell is-link title="用户注销" v-if="userInfo.id" @click="logoff"></u-cell>
<u-cell is-link title="意见反馈" @click="navigateTo('/pages/mine/set/feedBack')"></u-cell>
<u-cell
:isLink="false"
is-link
:title="`关于${config.name}`"
@click="navigateTo('/pages/mine/set/editionIntro')"
></u-cell>
@@ -148,12 +148,14 @@ export default {
<style lang="scss" scoped>
page {
background: #fff !important;
background: #f8f8f8 !important;
}
.set-up {
width: 100%;
min-height: 100vh;
background: #fff;
box-sizing: border-box;
background: #f8f8f8;
}
.person {
@@ -161,6 +163,7 @@ page {
align-items: center;
padding: 36rpx 30rpx;
background: #fff;
border-bottom: 1rpx solid #ededed;
}
.user-name {
@@ -176,10 +179,20 @@ page {
.cell-group {
width: 100%;
margin-top: 20rpx;
background: #fff;
}
:deep(.u-cell-group) {
width: 100%;
}
:deep(.u-cell) {
padding: 0 30rpx;
width: 100%;
}
:deep(.u-cell__body) {
padding: 28rpx 30rpx;
}
:deep(.u-cell__title-text) {
@@ -191,6 +204,15 @@ page {
color: #ccc !important;
}
:deep(.u-cell__right-icon-wrap) {
color: #ccc !important;
}
:deep(.u-line) {
width: 100% !important;
margin: 0 !important;
}
.submit {
height: 90rpx;
line-height: 90rpx;

View File

@@ -136,8 +136,9 @@ page {
.scoll-page,
.goods-scroll {
flex: 1;
height: 0;
overflow: auto;
min-height: 0;
height: 100%;
box-sizing: border-box;
}
.search-navbar-wrap {
@@ -170,6 +171,30 @@ page {
flex-direction: column;
}
/* #ifdef H5 */
.content--goods {
height: auto;
min-height: 100vh;
overflow: visible;
}
.goods-content--h5 {
flex: none;
min-height: auto;
overflow: visible;
}
.goods-list-wrap {
padding-bottom: 40rpx;
}
.sort-navbar {
position: sticky;
top: 0;
z-index: 9;
}
/* #endif */
.index-nav-arrow:last-child {
margin-top: -22rpx;
}

View File

@@ -1,5 +1,5 @@
<template>
<view class="content">
<view class="content" :class="{ 'content--goods': isShowSeachGoods }">
<u-navbar
:bg-color="navObj.background"
:auto-back="false"
@@ -75,8 +75,8 @@
</div>
</view>
<!-- 搜索 -->
<view class="goods-content" v-if="isShowSeachGoods">
<view class="navbar">
<view class="goods-content" :class="{ 'goods-content--h5': isShowSeachGoods }" v-if="isShowSeachGoods">
<view class="navbar sort-navbar">
<view class="nav-item" :class="{ current: filterIndex === 0 }" @click="tabClick(0)">综合排序</view>
<view class="nav-item" :class="{ current: filterIndex === 3 }" @click="tabClick(3, 'buyCount')">
<text>销量</text>
@@ -106,23 +106,36 @@
</view>
<view class="nav-item" @click="sortGoods">筛选</view>
</view>
<!-- #ifdef H5 -->
<view v-if="!empty && isSWitch" class="goods-list-wrap">
<goodsList :res="goodsList" type="oneColumns" :keyword="keyword" :tab-bar-gap="false" />
<uni-load-more :status="loadingType" @clickLoadMore="loadmore"></uni-load-more>
</view>
<view v-if="!empty && !isSWitch && goodsList.length" class="goods-list-wrap">
<goodsList :res="goodsList" :keyword="keyword" :tab-bar-gap="false" />
<uni-load-more :status="loadingType" @clickLoadMore="loadmore"></uni-load-more>
</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<!-- 一行一个商品展示 -->
<scroll-view
v-if="!empty && isSWitch"
class="goods-scroll"
:style="goodsScrollStyle"
enableBackToTop="true"
lower-threshold="250"
@scrolltolower="loadmore()"
scroll-with-animation
scroll-y
>
<goodsList :res="goodsList" type="oneColumns" :keyword="keyword" />
<goodsList :res="goodsList" type="oneColumns" :keyword="keyword" :tab-bar-gap="false" />
<uni-load-more :status="loadingType" @loadmore="loadmore()"></uni-load-more>
</scroll-view>
<!-- 一行两个商品展示 -->
<scroll-view
v-if="!empty && !isSWitch && goodsList.length"
class="goods-scroll"
:style="goodsScrollStyle"
scroll-anchoring
enableBackToTop="true"
@scrolltolower="loadmore()"
@@ -130,9 +143,10 @@
scroll-y
lower-threshold="250"
>
<goodsList :res="goodsList" :keyword="keyword" />
<goodsList :res="goodsList" :keyword="keyword" :tab-bar-gap="false" />
<uni-load-more :status="loadingType"></uni-load-more>
</scroll-view>
<!-- #endif -->
<view class="empty" v-if="empty">
<image class="empty-img" src="/static/nodata.png" mode="aspectFit"></image>
@@ -296,6 +310,7 @@ export default {
routerVal: '',
capsuleInsetRight: 0,
searchNavbarWidth: 0,
goodsScrollHeight: 0,
};
},
@@ -310,6 +325,14 @@ export default {
width: '100%',
};
},
goodsScrollStyle() {
if (this.goodsScrollHeight > 0) {
return {
height: `${this.goodsScrollHeight}px`,
};
}
return {};
},
},
onPageScroll(e) {
@@ -352,6 +375,20 @@ export default {
},
onReady() {
this.setSearchNavbarWidth();
this.calcGoodsScrollHeight();
},
onShow() {
this.calcGoodsScrollHeight();
},
mounted() {
// #ifdef H5
window.addEventListener('resize', this.calcGoodsScrollHeight);
// #endif
},
beforeUnmount() {
// #ifdef H5
window.removeEventListener('resize', this.calcGoodsScrollHeight);
// #endif
},
components: {
mSearch,
@@ -374,15 +411,49 @@ export default {
if (val) {
this.selectedWay = { brand: [], categoryId: [], prop: [] };
}
},
isShowSeachGoods(val) {
if (val) {
this.$nextTick(() => {
this.calcGoodsScrollHeight();
});
}
},
isSWitch() {
this.$nextTick(() => {
this.calcGoodsScrollHeight();
});
}
},
onReachBottom() {
this.params.pageNumber++;
this.loadData();
// #ifdef H5
if (!this.isShowSeachGoods || this.loadingType !== 'more') {
return;
}
this.loadmore();
// #endif
},
methods: {
calcGoodsScrollHeight() {
this.$nextTick(() => {
const query = uni.createSelectorQuery().in(this);
query.select('.goods-content').boundingClientRect();
query.select('.goods-content .navbar').boundingClientRect();
query.exec((res) => {
const contentRect = res[0];
const navbarRect = res[1];
if (!contentRect) {
return;
}
const sortBarHeight = navbarRect ? navbarRect.height : uni.upx2px(80);
const { windowHeight } = uni.getWindowInfo();
const height = Math.max(contentRect.height, windowHeight - contentRect.top) - sortBarHeight;
this.goodsScrollHeight = Math.max(height, 0);
});
});
},
setSearchNavbarWidth() {
// #ifdef MP-WEIXIN
try {
@@ -529,6 +600,9 @@ export default {
});
},
loadmore() {
if (this.loadingType !== 'more') {
return;
}
this.params.pageNumber++;
this.loadData();
},
@@ -663,6 +737,9 @@ export default {
this.empty = this.goodsList.length === 0;
this.initSortGoods();
this.$nextTick(() => {
this.calcGoodsScrollHeight();
});
if (this.$store.state.isShowToast){ uni.hideLoading() };
},
@@ -778,3 +855,12 @@ export default {
<style lang="scss" scoped>
@import './search.scss';
</style>
<style lang="scss">
/* #ifdef H5 */
page {
height: auto;
min-height: 100vh;
overflow-y: auto;
}
/* #endif */
</style>

View File

@@ -3,8 +3,8 @@
<!-- 订单状态 -->
<div class="info-view order-view">
<div class="order-status" v-if="orderStatusMap[order.orderStatus]">
{{ orderStatusMap[order.orderStatus].title }}
<div>{{ orderStatusMap[order.orderStatus].value }}</div>
<view class="order-status-title">{{ orderStatusMap[order.orderStatus].title }}</view>
<view class="order-status-desc">{{ orderStatusMap[order.orderStatus].value }}</view>
</div>
</div>
@@ -573,11 +573,14 @@ export default {
color: #fff;
width: 100%;
text-align: center;
font-size: 30rpx;
font-weight: 500;
margin-top: 36rpx;
>div {
.order-status-title {
font-size: 44rpx;
font-weight: 600;
}
.order-status-desc {
font-size: 22rpx;
font-weight: normal;
margin-top: 8rpx;

View File

@@ -1,6 +1,6 @@
<template>
<div class="wrapper">
<div v-if="!wechatLogin">
<div v-if="!wechatLogin" class="login-body">
<u-navbar :auto-back="showBack" :border="false"></u-navbar>
<div>
<div class="title">{{ loginTitleWay[current].title }}</div>
@@ -12,16 +12,34 @@
<!-- 手机号 -->
<div v-show="!enableUserPwdBox">
<div v-show="current == 0">
<u-input :custom-style="inputStyle" :placeholder-style="placeholderStyle" placeholder="请输入手机号 (11位)"
class="mobile" focus v-model="mobile" type="number" maxlength="11" />
<u-input
border="none"
:custom-style="inputStyle"
:placeholder-style="placeholderStyle"
font-size="40rpx"
color="#333"
placeholder="请输入手机号 (11位)"
class="mobile"
focus
v-model="mobile"
type="number"
maxlength="11"
/>
<div :class="!enableFetchCode ? 'disable' : 'fetch'" @click="fetchCode" class="btn">
获取验证码
</div>
</div>
<!-- 输入验证码 -->
<div v-show="current == 1" class="box-code">
<verifyCode type="bottom" @confirm="submit" boxActiveColor="#D8D8D8" v-model="code" isFocus
boxNormalColor="#D8D8D8" cursorColor="#D8D8D8" />
<div v-if="current == 1" class="box-code">
<verifyCode
type="bottom"
@confirm="submit"
boxActiveColor="#D8D8D8"
v-model="code"
:is-focus="true"
boxNormalColor="#D8D8D8"
cursorColor="#D8D8D8"
/>
<div class="fetch-btn">
<u-code change-text="验证码已发送x" end-text="重新获取验证码" unique-key="page-login"
@@ -35,18 +53,44 @@
<!-- 帐号密码登录 -->
<div v-show="enableUserPwdBox">
<u-input :custom-style="inputStyle" :placeholder-style="placeholderStyle" placeholder="请输入用户名"
class="mobile" focus v-model="userData.username" />
<u-input :custom-style="inputStyle" :placeholder-style="placeholderStyle" placeholder="请输入密码"
class="mobile" focus v-model="userData.password" type="password" />
<u-input
border="none"
:custom-style="inputStyle"
:placeholder-style="placeholderStyle"
font-size="40rpx"
color="#333"
placeholder="请输入用户名"
class="mobile"
focus
v-model="userData.username"
/>
<u-input
border="none"
:custom-style="inputStyle"
:placeholder-style="placeholderStyle"
font-size="40rpx"
color="#333"
placeholder="请输入密码"
class="mobile"
focus
v-model="userData.password"
type="password"
/>
<div :class="!enableUserBtnColor ? 'disable' : 'fetch'" @click="passwordLogin" class="btn">
帐号密码登录
</div>
</div>
<div class="flex" v-show="current != 1">
<u-checkbox usedAlone :icon-size="24" shape="circle" v-model:checked="enablePrivacy" active-color="#FF5E00"></u-checkbox>
<div class="privacy-row" v-show="current != 1">
<u-checkbox
class="privacy-check"
usedAlone
shape="circle"
v-model:checked="enablePrivacy"
:active-color="lightColor"
:icon-size="18"
></u-checkbox>
<div class="tips">
未注册的手机号验证后将自动创建用户账号登录即代表您已同意<span @click="navigateToPrivacy('PRIVACY_POLICY')">隐私协议</span>
<span @click="navigateToPrivacy('USER_AGREEMENT')">
@@ -151,9 +195,7 @@
height: "104rpx",
"border-bottom": "1rpx solid #D8D8D8",
"letter-spacing": "1rpx",
"font-size": "40rpx",
"line-height": "40rpx",
color: "#333",
padding: "0",
},
placeholderStyle: "font-size: 32rpx;line-height: 32rpx;color: #999999;",
loginList: [
@@ -311,20 +353,29 @@
async flage(val) {
if (val) {
if (this.$refs.uCode.canGetCode) {
if (this.enableUserPwdBox) {
this.submitUserLogin();
return;
// 执行登录
} else {
// 向后端请求验证码
}
// 首次发送时 uCode 尚未挂载;重新获取时才检查倒计时
const canSendCode = this.current === 0 || this.$refs.uCode?.canGetCode;
if (!canSendCode) {
this.$u.toast("请倒计时结束后再发送");
return;
}
uni.showLoading({});
let res = await sendMobile(this.mobile);
if (this.$store.state.isShowToast){ uni.hideLoading() };
// 这里此提示会被this.start()方法中的提示覆盖
if (this.$store.state.isShowToast) {
uni.hideLoading();
}
if (res.data.success) {
this.code = '';
this.current = 1;
this.$refs.uCode.start();
this.$nextTick(() => {
this.$refs.uCode?.start();
});
} else {
uni.showToast({
title: res.data.message,
@@ -332,14 +383,10 @@
icon: "none",
});
this.flage = false;
this.$refs.verification.getCode();
}
this.$refs.verification?.getCode();
}
} else {
!this.enableUserPwdBox ? this.$u.toast("请倒计时结束后再发送") : "";
}
} else {
this.$refs.verification.hide();
this.$refs.verification?.hide();
}
},
},
@@ -751,8 +798,18 @@
}
</style>
<style lang="scss" scoped>
.login-body {
flex: 1;
display: flex;
flex-direction: column;
}
.wrapper {
padding: 0 80rpx;
min-height: 100vh;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.title {
@@ -813,16 +870,32 @@
}
.tips {
font-size: 12px;
line-height: 20px;
margin-top: 32rpx;
width: 546rpx;
flex: 1;
font-size: 24rpx;
line-height: 36rpx;
margin-top: 0;
color: #666;
>span {
color: $light-color;
}
}
.privacy-row {
display: flex;
align-items: flex-start;
margin-top: 32rpx;
}
.privacy-check {
flex-shrink: 0;
margin-top: 4rpx;
:deep(.u-checkbox) {
margin: 0;
}
}
.fetch-btn {
width: 370rpx;
height: 80rpx;
@@ -839,8 +912,8 @@
.login-list {
display: flex;
width: 590rpx;
position: absolute;
top: 1200rpx;
margin-top: auto;
margin-bottom: 80rpx;
align-items: center;
justify-content: center;
}
@@ -858,7 +931,8 @@
.user-password-tips {
text-align: center;
color: $main-color;
margin: 20px 0;
color: $light-color;
margin: 40rpx 0;
font-size: 28rpx;
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="box">
<view class="box">
<u-navbar
class="navbar"
:border="false"
@@ -30,46 +30,65 @@
:list="tabs"
></u-tabs>
<div class="wrapper">
<!-- 直播中 全部 直播回放 -->
<div class="live-item" :class="{'invalid':item.status == 'END'}" v-for="(item,index) in liveList" :key="index" @click="handleLivePlayer(item)">
<div class="live-cover-img">
<div class="tips">
<div class="live-box">
<image class="live-gif" src="./static/live.gif"></image>
</div>
<span>{{item.status == 'END' ? '已结束' : item.status =='NEW' ? '未开始' : '直播中'}}</span>
</div>
<div class="bg"></div>
<u-image width="326" height="354" :src="item.shareImg" />
</div>
<div class="live-goods">
<div class="live-goods-name">
{{item.name}}
</div>
<div class="live-store">
<span class="wes">lilishop</span>
</div>
<div class="live-goods-list">
<div class="live-goods-item">
<u-image border-radius="20" :src="item.roomGoodsList ? item.roomGoodsList[0] : ''" height="140"></u-image>
</div>
<div class="live-goods-item">
<u-image border-radius="20" :src="item.roomGoodsList ? item.roomGoodsList[1] : ''" height="140"></u-image>
</div>
</div>
</div>
</div>
<u-loadmore v-if="liveList.length > 10" bg-color="#f8f8f8" :status="status" />
</div>
</div>
<view class="wrapper">
<view
class="live-item"
:class="{ invalid: item.status == 'END' }"
v-for="(item, index) in liveList"
:key="item.id || item.roomId || index"
@click="handleLivePlayer(item)"
>
<view class="live-cover-img">
<view class="tips">
<view class="live-box" v-if="item.status === 'START'">
<image class="live-gif" src="/pages/promotion/static/live.gif" mode="aspectFit"></image>
</view>
<text>{{ item.status == 'END' ? '已结束' : item.status == 'NEW' ? '未开始' : '直播中' }}</text>
</view>
<view class="bg"></view>
<u-image
class="cover-image"
width="326rpx"
height="354rpx"
mode="aspectFill"
:src="item.shareImg"
/>
</view>
<view class="live-goods">
<view class="live-goods-name">{{ item.name }}</view>
<view class="live-store">
<text class="wes">{{ config.name }}</text>
</view>
<view class="live-goods-list" v-if="item.roomGoodsList && item.roomGoodsList.length">
<view
class="live-goods-item"
v-for="(goodsImg, goodsIndex) in item.roomGoodsList.slice(0, 2)"
:key="goodsIndex"
>
<u-image
border-radius="20"
:src="goodsImg"
width="100%"
height="140rpx"
mode="aspectFill"
></u-image>
</view>
</view>
</view>
</view>
<u-loadmore v-if="liveList.length > 0" bg-color="#f8f8f8" :status="status" />
<view class="empty-live" v-if="!liveList.length && status === 'noMore'">暂无直播间</view>
</view>
</view>
</template>
<script>
import { getLiveList } from "@/api/promotions.js";
import config from "@/config/config";
export default {
data() {
return {
config,
status: "loadmore",
activeColor: this.$lightColor,
current: 0, // 当前tabs索引
@@ -142,6 +161,7 @@ export default {
* 点击标签栏切换
*/
changeTabs() {
this.params[this.current].pageNumber = 1;
this.init();
},
@@ -185,9 +205,9 @@ export default {
let recommendLives = await getLiveList(this.recommendParams);
if (recommendLives.data.success) {
// 推荐直播间
if (recommendLives.data.result.records.length ) {
if (recommendLives.data.result.records.length) {
this.status = "loadmore";
this.recommendLives = recommendLives.data.result.records;
this.recommendLiveList = recommendLives.data.result.records;
} else {
this.status = "noMore";
}
@@ -198,9 +218,9 @@ export default {
* 2.如果没有直播间设置一个默认图片
*/
if (!this.recommendLives.length) {
if (this.liveList[0].shareImg) {
this["swiperImg"] = [
if (!this.recommendLiveList.length) {
if (this.liveList[0] && this.liveList[0].shareImg) {
this.swiperImg = [
{
image: this.liveList[0].shareImg,
roomId: this.liveList[0].roomId,
@@ -208,10 +228,8 @@ export default {
];
}
} else {
this.recommendLives.forEach((item) => {
this["swiperImg"] = [
{ image: item.shareImg, roomId: item.roomId },
];
this.recommendLiveList.forEach((item) => {
this.swiperImg = [{ image: item.shareImg, roomId: item.roomId }];
});
}
}
@@ -239,8 +257,12 @@ export default {
this.liveList.forEach((item) => {
if (item.roomGoodsList) {
if (item.roomGoodsList && typeof item.roomGoodsList === "string") {
try {
item.roomGoodsList = JSON.parse(item.roomGoodsList);
} catch (e) {
item.roomGoodsList = [];
}
}
});
}
@@ -277,61 +299,97 @@ export default {
</script>
<style lang="scss" scoped>
page {
background: #f8f8f8;
}
.box {
width: 100%;
min-height: 100vh;
background: #f8f8f8;
box-sizing: border-box;
}
.slot-wrap {
display: flex;
align-items: center;
/* 如果您想让slot内容占满整个导航栏的宽度 */
flex: 1;
/* 如果您想让slot内容与导航栏左右有空隙 */
/* padding: 0 30rpx; */
padding-right: 24rpx;
}
.invalid {
filter: grayscale(1);
}
.wrapper {
padding: 0 24rpx;
padding: 0 24rpx 40rpx;
box-sizing: border-box;
}
.live-item {
display: flex;
flex-direction: row;
align-items: stretch;
overflow: hidden;
border-radius: 20rpx;
flex-wrap: wrap;
background: #fff;
margin: 20rpx 0;
}
.live-cover-img {
position: relative;
flex-shrink: 0;
width: 326rpx;
height: 354rpx;
overflow: hidden;
border-radius: 20rpx 0 0 20rpx;
}
.cover-image {
display: block;
width: 100%;
height: 100%;
}
.swiper {
margin: 20rpx 0;
margin: 20rpx 24rpx;
}
.live-goods {
position: relative;
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
padding: 16rpx 24rpx 24rpx;
box-sizing: border-box;
}
.live-goods-name {
height: 84rpx;
min-height: 84rpx;
font-weight: bold;
font-size: 30rpx;
line-height: 1.4;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
color: #333;
}
.live-store {
display: flex;
align-items: center;
margin: 20rpx 0;
margin: 12rpx 0 20rpx;
overflow: hidden;
width: calc(100% - 50rpx);
font-size: 24rpx;
color: #999;
}
.live-gif {
width: 20rpx;
height: 20rpx;
}
.live-box {
display: flex;
align-items: center;
@@ -340,66 +398,53 @@ export default {
width: 40rpx;
margin-right: 10rpx;
height: 40rpx;
flex-shrink: 0;
background: linear-gradient(90deg, #ff6b35, #ff9f28, #ffcc03);
}
.live-goods-list {
display: flex;
align-items: center;
justify-content: space-between;
> .live-goods-item {
flex: 1;
}
> .live-goods-item:nth-of-type(1) {
padding-right: 38rpx;
}
gap: 20rpx;
margin-top: auto;
}
.live-icon,
.zan {
position: absolute;
width: 80rpx;
height: 80rpx;
z-index: 9;
.live-goods-item {
flex: 1;
min-width: 0;
overflow: hidden;
border-radius: 20rpx;
}
.tips {
display: flex;
position: absolute;
z-index: 9;
align-items: center;
top: 20rpx;
right: 0;
padding: 4rpx 12rpx 4rpx 0;
left: 20rpx;
padding: 4rpx 12rpx 4rpx 4rpx;
font-size: 24rpx;
border-radius: 100px;
color: #fff;
background: rgba(0, 0, 0, 0.46);
}
.live-icon {
right: 0;
top: 104rpx;
}
.zan {
bottom: 0;
right: 0;
width: 100rpx;
height: 100rpx;
}
.bg {
position: absolute;
bottom: 4rpx;
width: 100%;
left: 0;
right: 0;
bottom: 0;
height: 100rpx;
z-index: 8;
background-image: -webkit-gradient(
linear,
left bottom,
left top,
from(rgba(0, 0, 0, 0.25)),
color-stop(82%, transparent)
);
pointer-events: none;
background-image: linear-gradient(0deg, rgba(0, 0, 0, 0.25), transparent 82%);
border-bottom-left-radius: 20rpx;
}
.empty-live {
padding: 80rpx 0;
text-align: center;
font-size: 28rpx;
color: #999;
}
</style>

View File

@@ -107,6 +107,10 @@ export default {
this.pointDetail = res.data.result;
}
},
closePopupBuy(val) {
this.maskFlag = val;
},
},
};
</script>

View File

@@ -2,6 +2,22 @@
<view class="index">
<user-point />
<view class="index-head">
<!-- #ifdef H5 -->
<view class="list-scroll-content list-scroll-content-h5">
<view class="index-head-navs">
<view
class="index-head-nav"
v-for="(ele, index) in categoryIndexData"
:key="index"
:class="{ 'index-head-nav-active': tabIndex == index }"
@click="setCat(index)"
>
{{ ele.name }}
</view>
</view>
</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<scroll-view scroll-x class="list-scroll-content" :scroll-left="currentLeft" scroll-with-animation>
<view class="index-head-navs">
<view class="index-head-nav" v-for="(ele, index) in categoryIndexData" :key="index"
@@ -10,11 +26,48 @@
</view>
</view>
</scroll-view>
<!-- #endif -->
</view>
<!-- #ifdef H5 -->
<view class="tab-content-h5">
<view class="index-items">
<view
class="index-item"
v-for="(item, key) in categoryIndexData[tabIndex].goods"
:key="item.id || key"
@click="toGoods(item)"
>
<view class="index-item-img">
<image
class="index-item-image"
:src="item.thumbnail"
mode="aspectFit"
lazy-load
></image>
</view>
<view class="index-item-info">
<view class="index-item-title">{{ item.goodsName || item.promotionName || '' }}</view>
<view class="index-item-price">
<view class="point">
<text class="point-num">{{ item.points != null ? item.points : 0 }}</text>
<text class="point-unit">积分</text>
</view>
<text class="tipsMkt">¥{{ unitPrice(item.originalPrice) }}</text>
</view>
</view>
</view>
</view>
<uni-load-more
:status="categoryIndexData[tabIndex].loadStatus"
@clickLoadMore="loadMore"
></uni-load-more>
</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<swiper :current="tabIndex" class="swiper-box" @change="ontabchange" duration="300">
<swiper-item v-for="(nav, index) in categoryIndexData" :key="index" class="swiper-item">
<scroll-view class="scroll-v" enableBackToTop="true" scroll-with-animation scroll-y @scrolltolower="loadMore">
<view class="index-items">
<view class="index-item" v-for="(item, key) in nav.goods" :key="item.id || key" @click="toGoods(item)">
@@ -42,6 +95,7 @@
</scroll-view>
</swiper-item>
</swiper>
<!-- #endif -->
</view>
</template>
@@ -80,11 +134,14 @@ export default {
},
onLoad() {},
async onPullDownRefresh() {
// #ifndef H5
this.categoryIndexData[this.tabIndex].goods = [];
this.categoryIndexData[this.tabIndex].params.pageNumber = 1;
this.categoryIndexData[this.tabIndex].loadStatus = "more";
this.loadGoods();
// #endif
},
// #ifndef H5
onPageScroll(e) {
if (e.scrollTop < -40 && this.flag) {
this.flag = false;
@@ -95,6 +152,7 @@ export default {
this.loadGoods();
}
},
// #endif
watch: {
tabIndex(val) {
if (
@@ -175,7 +233,9 @@ export default {
}, 3000);
}
// #ifndef H5
uni.stopPullDownRefresh();
// #endif
},
setCat(type) {
this.tabIndex = type;
@@ -189,12 +249,21 @@ export default {
}
},
loadMore() {
if (this.categoryIndexData[this.tabIndex].loadStatus == "more") {
if (this.categoryIndexData[this.tabIndex].loadStatus !== "more") {
return;
}
this.categoryIndexData[this.tabIndex].params.pageNumber++;
this.loadGoods();
},
},
// #ifdef H5
onReachBottom() {
if (this.categoryIndexData[this.tabIndex].loadStatus !== 'more') {
return;
}
this.loadMore();
},
},
// #endif
};
</script>
<style lang="scss" scoped>
@@ -212,15 +281,21 @@ page {
.index {
height: 100vh;
// #ifdef H5
height: calc(100vh - 44px);
// #endif
width: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
// #ifdef H5
height: auto;
min-height: 100vh;
overflow: visible;
// #endif
}
.index-head {
background: #fff;
flex-shrink: 0;
}
.list-scroll-content {
@@ -259,14 +334,25 @@ page {
}
}
.swiper-box {
// #ifdef H5
height: calc(100vh - (100rpx + 300rpx + 44px));
// #endif
// #ifdef H5
.list-scroll-content-h5 {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
// #ifndef H5
height: calc(100vh - 400rpx);
// #endif
.index-head-navs {
display: inline-flex;
min-width: 100%;
}
}
.tab-content-h5 {
padding-bottom: 40rpx;
}
// #endif
.swiper-box {
flex: 1;
min-height: 0;
.scroll-v {
height: 100%;
@@ -355,3 +441,12 @@ page {
}
}
</style>
<style lang="scss">
/* #ifdef H5 */
page {
height: auto;
min-height: 100vh;
overflow-y: auto;
}
/* #endif */
</style>

View File

@@ -35,6 +35,7 @@ export default {
.user-point {
padding: 0 20rpx;
height: 300rpx;
flex-shrink: 0;
background: url("/static/point-bg.png") no-repeat;
background-size: 100%;
display: flex;

View File

@@ -119,24 +119,24 @@
<u-checkbox class="checkout-all" usedAlone shape="circle" :active-color="lightColor" v-model:checked="checkout"
:label-size="12" label="全选" @change="checkOut">
</u-checkbox>
<span class="price checkout-total">
<div class="prices">
<div class="fullPrice">
<span class="number" v-if="cartDetail && cartDetail.priceDetailDTO">
总计:
<span>¥{{ goodsFormatPrice(cartDetail.priceDetailDTO.flowPrice)[0] }}</span>.<span>{{ goodsFormatPrice(cartDetail.priceDetailDTO.flowPrice)[1] }}</span>
</span>
<span class="number" v-else>总计:0.00</span>
</div>
<div
v-if="cartDetail.cartList && cartDetail.cartList.length!=0 && cartDetail.priceDetailDTO && cartDetail.priceDetailDTO.discountPrice!=0 "
class="discountPrice">
<span>优惠减:{{(cartDetail.priceDetailDTO.goodsPrice -unitPrice(cartDetail.priceDetailDTO.flowPrice))}}
</span>
<span class="discount-details" @click="discountDetails">优惠明细</span>
</div>
</div>
</span>
<view class="checkout-total">
<view class="checkout-total-main">
<text class="checkout-total-label">总计:</text>
<text class="checkout-total-price" v-if="cartDetail && cartDetail.priceDetailDTO">
<text class="checkout-total-currency">¥</text>
<text class="checkout-total-int">{{ goodsFormatPrice(cartDetail.priceDetailDTO.flowPrice)[0] }}</text>
<text class="checkout-total-dec">.{{ goodsFormatPrice(cartDetail.priceDetailDTO.flowPrice)[1] }}</text>
</text>
<text class="checkout-total-price" v-else>¥0.00</text>
</view>
<view
v-if="cartDetail.cartList && cartDetail.cartList.length != 0 && cartDetail.priceDetailDTO && cartDetail.priceDetailDTO.discountPrice != 0"
class="checkout-total-discount"
>
<text>优惠减:{{ cartDetail.priceDetailDTO.goodsPrice - unitPrice(cartDetail.priceDetailDTO.flowPrice) }}</text>
<text class="discount-details" @click="discountDetails">优惠明细</text>
</view>
</view>
</view>
<!-- 优惠详情 -->
<u-popup z-index="3" close mode="bottom" height="50%" closeable v-model:show="discountDetailsFlag" border-radius="20">
@@ -851,7 +851,50 @@ page {
}
.checkout-total {
margin-left: 8rpx;
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
justify-content: center;
}
.checkout-total-main {
display: flex;
align-items: baseline;
line-height: 1.2;
}
.checkout-total-label {
font-size: 28rpx;
color: #333;
flex-shrink: 0;
}
.checkout-total-price {
margin-left: 4rpx;
font-size: 30rpx;
font-weight: bold;
color: $main-color;
line-height: 1.2;
}
.checkout-total-int {
font-size: 38rpx;
font-weight: bold;
}
.checkout-total-dec {
font-size: 24rpx;
font-weight: bold;
}
.checkout-total-discount {
display: flex;
align-items: center;
margin-top: 4rpx;
font-size: 24rpx;
color: #c9c7c7;
line-height: 1.2;
}
}
@@ -889,17 +932,6 @@ page {
}
}
.prices {
display: flex;
flex-direction: column;
> .discountPrice {
align-items: center;
display: flex;
font-size: 24rpx;
color: rgb(201, 199, 199);
}
}
.discount-details {
margin-left: 10px;
color: #666;