添加魔法,添加商品卡片分类,会员bug

This commit is contained in:
77 2024-10-29 11:14:45 +08:00
parent df5dddb424
commit 09b02ede34
20 changed files with 2046 additions and 1085 deletions

View File

@ -0,0 +1,165 @@
export default {
"addressbook":"\ue80c",
"addfriends-fill": "\ue80a",
"addfriends": "\ue80b",
"backspace-fill": "\ue808",
"backspace": "\ue809",
"bankcard-fill": "\ue806",
"bankcard": "\ue807",
"camera-fill": "\ue804",
"camera": "\ue805",
"captcha-fill": "\ue802",
"captcha": "\ue803",
"cart-fill": "\ue800",
"cart": "\ue801",
"classify": "\ue7fe",
"classify-fill": "\ue7ff",
"comment-fill": "\ue7fc",
"comment": "\ue7fd",
"community-fill": "\ue7fa",
"community": "\ue7fb",
"coupon-fill": "\ue7f8",
"coupon": "\ue7f9",
"delete": "\ue7f6",
"delete-fill": "\ue7f7",
"edit": "\ue7f4",
"edit-fill": "\ue7f5",
"fabulous-fill": "\ue7f2",
"fabulous": "\ue7f3",
"find": "\ue7f0",
"find-fill": "\ue7f1",
"help-fill": "\ue7ee",
"help": "\ue7ef",
"home-fill": "\ue7ec",
"home": "\ue7ed",
"idcard-fill": "\ue7ea",
"idcard": "\ue7eb",
"info": "\ue7e8",
"info-fill": "\ue7e9",
"invite-fill": "\ue7e6",
"invite": "\ue7e7",
"kefu-fill": "\ue7e4",
"kefu": "\ue7e5",
"like-fill": "\ue7e2",
"like": "\ue7e3",
"location": "\ue7e0",
"location-fill": "\ue7e1",
"lock": "\ue7de",
"lock-fill": "\ue7df",
"mail-fill": "\ue7dc",
"mail": "\ue7dd",
"message": "\ue7da",
"message-fill": "\ue7db",
"mobile-fill": "\ue7d8",
"mobile": "\ue7d9",
"more": "\ue7d6",
"more-fill": "\ue7d7",
"my-fill": "\ue7d4",
"my": "\ue7d5",
"principal":"\ue80d",
"notice-fill": "\ue7d2",
"notice": "\ue7d3",
"order": "\ue7d0",
"order-fill": "\ue7d1",
"picture": "\ue7ce",
"picture-fill": "\ue7cf",
"setup-fill": "\ue7cc",
"setup": "\ue7cd",
"share": "\ue7ca",
"share-fill": "\ue7cb",
"shop": "\ue7c8",
"shop-fill": "\ue7c9",
"star-fill": "\ue7c5",
"star": "\ue7c6",
"starhalf": "\ue7c7",
"stepon-fill": "\ue7c3",
"stepon": "\ue7c4",
"wait-fill": "\ue7c1",
"wait": "\ue7c2",
"warning": "\ue7bf",
"warning-fill": "\ue7c0",
"plus": "\ue7bc",
"plussign-fill": "\ue7bd",
"plussign": "\ue7be",
"minus": "\ue7b9",
"minussign": "\ue7ba",
"minussign-fill": "\ue7bb",
"close": "\ue7b8",
"clear": "\ue7b6",
"clear-fill": "\ue7b7",
"checkbox-fill": "\ue7b5",
"checkround": "\ue7b4",
"checkbox": "\ue7b3",
"check": "\ue7b2",
"pulldown-fill": "\ue7ae",
"pullup": "\ue7af",
"pullup-fill": "\ue7b0",
"pulldown": "\ue7b1",
"roundright-fill": "\ue7ac",
"roundright": "\ue7ad",
"arrowright": "\ue7a9",
"arrowleft": "\ue7aa",
"arrowdown": "\ue7ab",
"left": "\ue7a6",
"up": "\ue7a7",
"right": "\ue7a8",
"back": "\ue7a3",
"top": "\ue7a4",
"dropdown": "\ue7a5",
"turningleft": "\ue79f",
"turningup": "\ue7a0",
"turningright": "\ue7a1",
"turningdown": "\ue7a2",
"refresh": "\ue79c",
"loading": "\ue79d",
"search": "\ue79e",
"rotate": "\ue79b",
"screen": "\ue79a",
"signin": "\ue799",
"calendar": "\ue798",
"scan": "\ue797",
"qrcode": "\ue796",
"wallet": "\ue795",
"telephone": "\ue794",
"visible": "\ue793",
"invisible": "\ue792",
"menu": "\ue78e",
"operate": "\ue78f",
"slide": "\ue790",
"list": "\ue791",
"nonetwork": "\ue78d",
"partake": "\ue78c",
"qa": "\ue78b",
"barchart": "\ue788",
"piechart": "\ue789",
"linechart": "\ue78a",
"at": "\ue787",
"face": "\ue77f",
"redpacket": "\ue780",
"suspend": "\ue781",
"link": "\ue782",
"keyboard": "\ue783",
"play": "\ue784",
"video": "\ue785",
"voice": "\ue786",
"sina": "\ue77a",
"browser": "\ue77b",
"moments": "\ue77c",
"qq": "\ue77d",
"wechat": "\ue77e",
"balance": "\ue779",
"bankcardpay": "\ue778",
"wxpay": "\ue777",
"alipay": "\ue776",
"payment":"\ue818",
"receive":"\ue817",
"sendout":"\ue816",
"evaluate":"\ue815",
"aftersale":"\ue814",
"warehouse":"\ue813",
"transport":"\ue812",
"delivery":"\ue811",
"switch":"\ue810",
"goods":"\ue80f",
"goods-fill":"\ue80e"
}

Binary file not shown.

View File

@ -0,0 +1,150 @@
<template>
<!-- #ifndef APP-NVUE -->
<text :style="{ color:getColor, fontSize: getSize, fontWeight: fontWeight}" class="fui-icon"
:class="[!getColor && !primary?'fui-icon__color':'',primary && (!color || color===true)?'fui-icon__active-color':'',disabled?'fui-icon__not-allowed':'',customPrefix && customPrefix!==true?customPrefix:'',customPrefix && customPrefix!==true?name:'']"
@click="handleClick">{{ icons[name] || '' }}</text>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<text
:style="{ color: primary && (!color || color===true)?primaryColor:getColor, fontSize: getSize,lineHeight:getSize, fontWeight: fontWeight}"
class="fui-icon" :class="[customPrefix && customPrefix!==true?customPrefix:'']"
@click="handleClick">{{ customPrefix && customPrefix!==true?name:icons[name] }}</text>
<!-- #endif -->
</template>
<script>
import icons from './fui-icon.js';
// #ifdef APP-NVUE
var domModule = weex.requireModule('dom');
import fuiicons from './fui-icon.ttf'
domModule.addRule('fontFace', {
'fontFamily': 'fuiFont',
'src': "url('" + fuiicons + "')"
});
// #endif
export default {
name: "fui-icon",
emits: ['click'],
// #ifdef MP-WEIXIN
options: {
addGlobalClass: true
},
// #endif
props: {
name: {
type: String,
default: ''
},
size: {
type: [Number, String],
default: 0
},
//rpx | px
unit: {
type: String,
default: ''
},
color: {
type: String,
default: ''
},
//
fontWeight: {
type: [Number, String],
default: 'normal'
},
//
disabled: {
type: Boolean,
default: false
},
params: {
type: [Number, String],
default: 0
},
customPrefix: {
type: String,
default: ''
},
//color使
primary: {
type: Boolean,
default: false
}
},
computed: {
getSize() {
const size = (uni.$fui && uni.$fui.fuiIcon && uni.$fui.fuiIcon.size) || 64
const unit = (uni.$fui && uni.$fui.fuiIcon && uni.$fui.fuiIcon.unit) || 'rpx'
return (this.size || size) + (this.unit || unit)
},
primaryColor() {
const app = uni && uni.$fui && uni.$fui.color;
return (app && app.primary) || '#465CFF';
},
getColor() {
const app = uni && uni.$fui && uni.$fui.fuiIcon;
let color = this.color;
if (!color || (color && color === true)) {
color = (app && app.color)
}
// #ifdef APP-NVUE
if (!color || color === true) {
color = '#333333'
}
// #endif
return color;
}
},
data() {
return {
icons: icons
};
},
methods: {
handleClick() {
if (this.disabled) return;
this.$emit('click', {
params: this.params
});
}
}
}
</script>
<style scoped>
/* #ifndef APP-NVUE */
/* 头条小程序组件内不能引入字体,需要在父级页面引入字体文件*/
@font-face {
font-family: fuiFont;
src: url("./fui-icon.ttf") format("truetype");
}
/* #endif */
.fui-icon {
font-family: fuiFont;
text-decoration: none;
text-align: center;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
/* #ifndef APP-NVUE */
.fui-icon__color {
color: var(--fui-color-section, #333333) !important;
}
.fui-icon__active-color {
color: var(--fui-color-primary, #465CFF) !important;
}
/* #endif */
.fui-icon__not-allowed {
/* #ifdef H5 */
cursor: not-allowed !important;
/* #endif */
}
</style>

View File

@ -0,0 +1,206 @@
<template>
<view class="fui-toast__wrap" :class="{'fui-toast__show':visible}" v-if="visible || !isNvue" ref="fui_toast_ani">
<view class="fui-toast__inner"
:style="{paddingTop:padding[0] || 0,paddingRight:padding[1] || 0,paddingBottom:padding[2] || padding[0] || 0,paddingLeft:padding[3] || padding[1] || 0,background:background,zIndex:zIndex}">
<slot></slot>
<view class="fui-toast__icon-box" v-if="src" :style="{width:width+'rpx',height:width+'rpx'}">
<image class="fui-toast__icon" :src="src" :style="{width:width+'rpx',height:width+'rpx'}">
</image>
</view>
<text class="fui-toast__text" :style="{fontSize:size+'rpx',color:color}" v-if="text">{{text}}</text>
</view>
</view>
</template>
<script>
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation');
// #endif
export default {
name: "fui-toast",
props: {
padding: {
type: Array,
default () {
return ['32rpx', '32rpx']
}
},
background: {
type: String,
default: 'rgba(0,0,0,.6)'
},
//rpx
width: {
type: [Number, String],
default: 64
},
size: {
type: [Number, String],
default: 30
},
color: {
type: String,
default: '#fff'
},
zIndex: {
type: Number,
default: 1001
}
},
data() {
let isNvue = false;
// #ifdef APP-NVUE
isNvue = true;
// #endif
return {
timer: null,
visible: false,
src: '',
text: '',
isNvue: isNvue
};
},
// #ifndef VUE3
beforeDestroy() {
clearTimeout(this.timer);
this.timer = null;
},
// #endif
// #ifdef VUE3
beforeUnmount() {
clearTimeout(this.timer);
this.timer = null;
},
// #endif
methods: {
// #ifdef APP-NVUE
_animation(type, duration = 2000) {
if (!this.$refs['fui_toast_ani']) return;
animation.transition(
this.$refs['fui_toast_ani'].ref, {
styles: {
opacity: type ? 1 : 0
},
duration: 300, //ms
timingFunction: 'ease-in-out',
needLayout: false,
delay: 0 //ms
},
() => {
if (!type) {
this.visible = false;
} else {
this.timer = setTimeout(() => {
this._animation(false)
clearTimeout(this.timer);
this.timer = null;
}, duration);
}
}
);
},
// #endif
show: function(options) {
clearTimeout(this.timer);
let {
duration = 2000,
src = '',
text = ''
} = options;
this.text = text;
this.src = src;
// #ifdef APP-NVUE
this.visible = true;
// #endif
this.$nextTick(() => {
setTimeout(() => {
// #ifdef APP-NVUE
this._animation(true, duration)
// #endif
// #ifndef APP-NVUE
this.visible = true;
this.timer = setTimeout(() => {
this.visible = false;
clearTimeout(this.timer);
this.timer = null;
}, duration);
// #endif
}, 50);
});
}
}
}
</script>
<style scoped>
.fui-toast__wrap {
position: fixed;
/* #ifdef APP-NVUE */
left: 64rpx;
right: 64rpx;
top: 0;
bottom: 0;
/* #endif */
/* #ifndef APP-NVUE */
left: 15%;
right: 15%;
top: 50%;
transform: translateY(-50%);
/* #endif */
background-color: rgba(0, 0, 0, 0);
z-index: 1002;
/* #ifndef APP-NVUE */
display: flex;
visibility: hidden;
/* #endif */
align-items: center;
justify-content: center;
/* #ifndef APP-NVUE */
transition-property: opacity, visibility;
transition-timing-function: ease-in-out;
transition-duration: 0.3s;
/* #endif */
opacity: 0;
}
.fui-toast__inner {
/* #ifndef APP-NVUE */
display: flex;
box-sizing: border-box;
/* #endif */
align-items: center;
justify-content: center;
flex-direction: column;
border-radius: 16rpx;
}
/* #ifndef APP-NVUE */
.fui-toast__show {
visibility: visible;
opacity: 1;
}
/* #endif */
.fui-toast__icon-box {
padding-bottom: 20rpx;
/* #ifndef APP-NVUE */
box-sizing: content-box;
flex-shrink: 0;
/* #endif */
}
/* #ifndef APP-NVUE */
.fui-toast__icon {
display: block;
flex-shrink: 0;
}
/* #endif */
.fui-toast__text {
font-weight: 400;
text-align: center;
/* #ifndef APP-NVUE */
word-break: break-all;
/* #endif */
}
</style>

View File

@ -1,105 +1,20 @@
{ {
"id": "shopro", "id": "fui-toast",
"name": "shopro", "name": "Toast 轻提示fui-toast",
"displayName": "芋道商城", "version": "v2.3.0",
"version": "2.1.0", "description": "FirstUI Toast 轻提示,一种轻量级反馈/提示,适合用于页面转场、数据交互的等场景中。",
"description": "芋道商城一套代码同时发行到iOS、Android、H5、微信小程序多个平台请使用手机扫码快速体验强大功能", "keywords": [
"scripts": { "Toast",
"prettier": "prettier --write \"{pages,sheep}/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"", "轻提示",
"build:prod": "vue-cli-service build --mode prod", "组件",
"build:dev": "vue-cli-service build --mode dev" "FirstUI",
}, "Nvue"
"repository": "https://github.com/sheepjs/shop.git",
"keywords": [
"商城",
"B2C",
"商城模板"
],
"author": "",
"license": "MIT",
"bugs": {
"url": "https://github.com/sheepjs/shop/issues"
},
"homepage": "https://github.com/dcloudio/hello-uniapp#readme",
"dcloudext": {
"category": [
"前端页面模板",
"uni-app前端项目模板"
], ],
"sale": { "dcloudext": {
"regular": { "category": [
"price": "0.00" "前端组件",
}, "通用组件"
"sourcecode": { ]
"price": "0.00"
}
}, },
"contact": { "displayName": "Toast 轻提示fui-toast"
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "u",
"aliyun": "u"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "u",
"vue3": "y"
}
}
}
},
"dependencies": {
"dayjs": "^1.11.7",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"luch-request": "^3.0.8",
"pinia": "^2.0.33",
"pinia-plugin-persist-uni": "^1.2.0",
"weixin-js-sdk": "^1.6.0"
},
"devDependencies": {
"prettier": "^2.8.7",
"vconsole": "^3.15.0"
}
} }

View File

@ -46,6 +46,19 @@
"group": "商城" "group": "商城"
} }
}, },
{
"path": "pages/subscribe/success_tolse",
"style": {
"navigationBarTitleText": "预约成功",
"enablePullDownRefresh": true
},
"meta": {
"auth": false,
"sync": true,
"title": "预约成功",
"group": "商城"
}
},
{ {
"path": "pages/reservation_record/reservation_record", "path": "pages/reservation_record/reservation_record",
"style": { "style": {
@ -366,6 +379,18 @@
"group": "用户中心" "group": "用户中心"
} }
}, },
{
"path": "user_vip/agreement",
"style": {
"navigationBarTitleText": "会员协议"
},
"meta": {
"auth": true,
"sync": true,
"title": "会员协议",
"group": "用户中心"
}
},
{ {
"path": "user_vip/index", "path": "user_vip/index",
"style": { "style": {

View File

@ -1,419 +1,426 @@
<!-- 秒杀活动列表 --> <!-- 秒杀活动列表 -->
<template> <template>
<s-layout title="秒杀列表" navbar="normal" :bgStyle="{ color: 'rgb(245,28,19)' }"> <s-layout title="秒杀列表" navbar="normal" :bgStyle="{ color: 'rgb(245,28,19)' }">
<!--顶部背景图--> <!--顶部背景图-->
<!-- <view <!-- <view
class="page-bg" class="page-bg"
:style="[{ marginTop: '-' + Number(statusBarHeight + 88) + 'rpx' }]" :style="[{ marginTop: '-' + Number(statusBarHeight + 88) + 'rpx' }]"
></view> --> ></view> -->
<!-- 时间段轮播图 --> <!-- 时间段轮播图 -->
<view class="header" v-if="activeTimeConfig?.sliderPicUrls?.length > 0"> <view class="header" v-if="activeTimeConfig?.sliderPicUrls?.length > 0">
<swiper <swiper indicator-dots="true" autoplay="true" :circular="true" interval="3000" duration="1500"
indicator-dots="true" indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff">
autoplay="true" <block v-for="(picUrl, index) in activeTimeConfig.sliderPicUrls" :key="index">
:circular="true" <swiper-item class="borRadius14">
interval="3000" <image :src="picUrl" class="slide-image borRadius14" lazy-load />
duration="1500" </swiper-item>
indicator-color="rgba(255,255,255,0.6)" </block>
indicator-active-color="#fff" </swiper>
> </view>
<block v-for="(picUrl, index) in activeTimeConfig.sliderPicUrls" :key="index"> <!-- 时间段列表 -->
<swiper-item class="borRadius14"> <view class="flex align-center justify-between ss-p-25">
<image :src="picUrl" class="slide-image borRadius14" lazy-load /> <!-- 左侧图标 -->
</swiper-item> <view class="time-icon">
</block> <!-- TODO 芋艿图片统一维护 -->
</swiper> <image class="ss-w-100 ss-h-100" src="http://mall.yudao.iocoder.cn/static/images/priceTag.png" />
</view> </view>
<!-- 时间段列表 --> <scroll-view class="time-list" :scroll-into-view="activeTimeElId" scroll-x scroll-with-animation>
<view class="flex align-center justify-between ss-p-25"> <view v-for="(config, index) in timeConfigList" :key="index"
<!-- 左侧图标 --> :class="['item', { active: activeTimeIndex === index }]" :id="`timeItem${index}`"
<view class="time-icon"> @tap="handleChangeTimeConfig(index,config.id)">
<!-- TODO 芋艿图片统一维护 --> <!-- 活动起始时间 -->
<image <view class="time">{{ config.startTime }}</view>
class="ss-w-100 ss-h-100" <!-- 活动状态 -->
src="http://mall.yudao.iocoder.cn/static/images/priceTag.png" <view class="status">{{ config.status }}</view>
/> </view>
</view> </scroll-view>
<scroll-view </view>
class="time-list"
:scroll-into-view="activeTimeElId"
scroll-x
scroll-with-animation
>
<view
v-for="(config, index) in timeConfigList"
:key="index"
:class="['item', { active: activeTimeIndex === index }]"
:id="`timeItem${index}`"
@tap="handleChangeTimeConfig(index,config.id)"
>
<!-- 活动起始时间 -->
<view class="time">{{ config.startTime }}</view>
<!-- 活动状态 -->
<view class="status">{{ config.status }}</view>
</view>
</scroll-view>
</view>
<!-- 内容区 --> <!-- 内容区 -->
<view class="list-content"> <view class="list-content">
<!-- 活动倒计时 --> <!-- 活动倒计时 -->
<!-- <view class="content-header ss-flex-col ss-col-center ss-row-center"> <!-- <view class="content-header ss-flex-col ss-col-center ss-row-center">
<view class="content-header-box ss-flex ss-row-center"> <view class="content-header-box ss-flex ss-row-center">
<view <view
class="countdown-box ss-flex" class="countdown-box ss-flex"
v-if="activeTimeConfig?.status === TimeStatusEnum.STARTED" v-if="activeTimeConfig?.status === TimeStatusEnum.STARTED"
> >
<view class="countdown-title ss-m-r-12">距结束</view> <view class="countdown-title ss-m-r-12">距结束</view>
<view class="ss-flex countdown-time"> <view class="ss-flex countdown-time">
<view class="ss-flex countdown-h">{{ countDown.h }}</view> <view class="ss-flex countdown-h">{{ countDown.h }}</view>
<view class="ss-m-x-4">:</view> <view class="ss-m-x-4">:</view>
<view class="countdown-num ss-flex ss-row-center">{{ countDown.m }}</view> <view class="countdown-num ss-flex ss-row-center">{{ countDown.m }}</view>
<view class="ss-m-x-4">:</view> <view class="ss-m-x-4">:</view>
<view class="countdown-num ss-flex ss-row-center">{{ countDown.s }}</view> <view class="countdown-num ss-flex ss-row-center">{{ countDown.s }}</view>
</view> </view>
</view> </view>
<view v-else> {{ activeTimeConfig?.status }} </view> <view v-else> {{ activeTimeConfig?.status }} </view>
</view> </view>
</view> --> </view> -->
<!-- 活动列表 --> <!-- 活动列表 -->
<scroll-view <scroll-view class="scroll-box" :style="{ height: pageHeight + 'rpx' }" scroll-y="true"
class="scroll-box" :scroll-with-animation="false" :enable-back-to-top="true">
:style="{ height: pageHeight + 'rpx' }" <view class="goods-box ss-m-b-20" v-for="activity in activityList" :key="activity.id">
scroll-y="true" <s-goods-column size="lg" :data="{ ...activity, price: activity.seckillPrice }"
:scroll-with-animation="false" :goodsFields="goodsFields" :seckillTag="true"
:enable-back-to-top="true" @click="sheep.$router.go('/pages/goods/seckill', { id: activity.id })">
> <!-- 抢购进度 -->
<view class="goods-box ss-m-b-20" v-for="activity in activityList" :key="activity.id"> <template #activity>
<s-goods-column <view class="limit">限量
size="lg" <text class="ss-m-l-5">{{ activity.stock }} {{ activity.unitName }}</text>
:data="{ ...activity, price: activity.seckillPrice }" </view>
:goodsFields="goodsFields" <su-progress :percentage="activity.percent" strokeWidth="10" textInside isAnimate />
:seckillTag="true" </template>
@click="sheep.$router.go('/pages/goods/seckill', { id: activity.id })" <!-- 抢购按钮 -->
> <template #cart>
<!-- 抢购进度 --> <button :class="[
<template #activity>
<view class="limit"
>限量
<text class="ss-m-l-5">{{ activity.stock }} {{ activity.unitName }}</text></view
>
<su-progress :percentage="activity.percent" strokeWidth="10" textInside isAnimate />
</template>
<!-- 抢购按钮 -->
<template #cart>
<button
:class="[
'ss-reset-button cart-btn', 'ss-reset-button cart-btn',
{ disabled: activeTimeConfig.status === TimeStatusEnum.END }, { disabled: activeTimeConfig.status === TimeStatusEnum.END },
]" ]">
> <span v-if="activeTimeConfig?.status === TimeStatusEnum.WAIT_START">未开始</span>
<span v-if="activeTimeConfig?.status === TimeStatusEnum.WAIT_START">未开始</span> <span v-else-if="activeTimeConfig?.status === TimeStatusEnum.STARTED">马上抢</span>
<span v-else-if="activeTimeConfig?.status === TimeStatusEnum.STARTED">马上抢</span> <span v-else>已结束</span>
<span v-else>已结束</span> </button>
</button> </template>
</template> </s-goods-column>
</s-goods-column> </view>
</view> <uni-load-more v-if="activityTotal > 0" :status="loadStatus" :content-text="{
<uni-load-more
v-if="activityTotal > 0"
:status="loadStatus"
:content-text="{
contentdown: '上拉加载更多', contentdown: '上拉加载更多',
}" }" @tap="loadMore" />
@tap="loadMore" </scroll-view>
/> </view>
</scroll-view> </s-layout>
</view>
</s-layout>
</template> </template>
<script setup> <script setup>
import { reactive, computed, ref, nextTick } from 'vue'; import {
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; reactive,
import sheep from '@/sheep'; computed,
import { useDurationTime } from '@/sheep/hooks/useGoods'; ref,
import SeckillApi from '@/sheep/api/promotion/seckill'; nextTick
import dayjs from 'dayjs'; } from 'vue';
import { TimeStatusEnum } from '@/sheep/util/const'; import {
onLoad,
onReachBottom
} from '@dcloudio/uni-app';
import sheep from '@/sheep';
import {
useDurationTime
} from '@/sheep/hooks/useGoods';
import SeckillApi from '@/sheep/api/promotion/seckill';
import dayjs from 'dayjs';
import {
TimeStatusEnum
} from '@/sheep/util/const';
// //
const { safeAreaInsets, safeArea } = sheep.$platform.device; const {
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2; safeAreaInsets,
const pageHeight = safeArea
(safeArea.height + safeAreaInsets.bottom) * 2 + statusBarHeight - sheep.$platform.navbar - 350; } = sheep.$platform.device;
const headerBg = sheep.$url.css('/static/img/shop/goods/seckill-header.png'); const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
const pageHeight =
(safeArea.height + safeAreaInsets.bottom) * 2 + statusBarHeight - sheep.$platform.navbar - 350;
const headerBg = sheep.$url.css('/static/img/shop/goods/seckill-header.png');
// //
const goodsFields = { const goodsFields = {
name: { show: true }, name: {
introduction: { show: true }, show: true
price: { show: true }, },
marketPrice: { show: true }, introduction: {
}; show: true
},
price: {
show: true
},
marketPrice: {
show: true
},
};
//#region //#region
// //
const timeConfigList = ref([]); const timeConfigList = ref([]);
// //
const getSeckillConfigList = async () => { const getSeckillConfigList = async () => {
const { data } = await SeckillApi.getSeckillConfigList(); const {
const now = dayjs(); data
const today = now.format('YYYY-MM-DD'); } = await SeckillApi.getSeckillConfigList();
// const now = dayjs();
data.forEach((config, index) => { const today = now.format('YYYY-MM-DD');
const startTime = dayjs(`${today} ${config.startTime}`); //
const endTime = dayjs(`${today} ${config.endTime}`); data.forEach((config, index) => {
if (now.isBefore(startTime)) { const startTime = dayjs(`${today} ${config.startTime}`);
config.status = TimeStatusEnum.WAIT_START; const endTime = dayjs(`${today} ${config.endTime}`);
} else if (now.isAfter(endTime)) { if (now.isBefore(startTime)) {
config.status = TimeStatusEnum.END; config.status = TimeStatusEnum.WAIT_START;
} else { } else if (now.isAfter(endTime)) {
config.status = TimeStatusEnum.STARTED; config.status = TimeStatusEnum.END;
activeTimeIndex.value = index; } else {
} config.status = TimeStatusEnum.STARTED;
}); activeTimeIndex.value = index;
timeConfigList.value = data; }
console.log(timeConfigList.value[0]?.id,"timeConfigList.value[0]?.id"); });
// timeConfigList.value = data;
handleChangeTimeConfig(activeTimeIndex.value, timeConfigList.value[0]?.id); console.log(timeConfigList.value[0]?.id, "timeConfigList.value[0]?.id");
// //
scrollToTimeConfig(activeTimeIndex.value); handleChangeTimeConfig(activeTimeIndex.value, timeConfigList.value[0]?.id);
}; //
scrollToTimeConfig(activeTimeIndex.value);
};
// //
const activeTimeElId = ref(''); // ID const activeTimeElId = ref(''); // ID
const scrollToTimeConfig = (index) => { const scrollToTimeConfig = (index) => {
nextTick(() => (activeTimeElId.value = `timeItem${index}`)); nextTick(() => (activeTimeElId.value = `timeItem${index}`));
}; };
// //
const activeTimeIndex = ref(0); // const activeTimeIndex = ref(0); //
const activeTimeConfig = computed(() => timeConfigList.value[activeTimeIndex.value]); // const activeTimeConfig = computed(() => timeConfigList.value[activeTimeIndex.value]); //
const handleChangeTimeConfig = (index, config) => { const handleChangeTimeConfig = (index, config) => {
activeTimeIndex.value = index; activeTimeIndex.value = index;
console.log(config,'config') console.log(config, 'config')
// //
activityPageParams.pageNo = 1; activityPageParams.pageNo = 1;
activityList.value = []; activityList.value = [];
getActivityList(config); getActivityList(config);
}; };
// //
const countDown = computed(() => { const countDown = computed(() => {
const endTime = activeTimeConfig.value?.endTime; const endTime = activeTimeConfig.value?.endTime;
if (endTime) { if (endTime) {
return useDurationTime(`${dayjs().format('YYYY-MM-DD')} ${endTime}`); return useDurationTime(`${dayjs().format('YYYY-MM-DD')} ${endTime}`);
} }
}); });
//#endregion //#endregion
//#region //#region
// //
const activityPageParams = reactive({ const activityPageParams = reactive({
configId: 0, // ID configId: 0, // ID
pageNo: 1, // pageNo: 1, //
pageSize: 5, // pageSize: 5, //
}); });
const activityTotal = ref(0); // const activityTotal = ref(0); //
const activityList = ref([]); // const activityList = ref([]); //
const loadStatus = ref(''); // const loadStatus = ref(''); //
async function getActivityList(id) { async function getActivityList(id) {
loadStatus.value = 'loading'; loadStatus.value = 'loading';
activityPageParams.configId= id; activityPageParams.configId = id;
const { data } = await SeckillApi.getSeckillActivityPage(activityPageParams); const {
data.list.forEach((activity) => { data
// } = await SeckillApi.getSeckillActivityPage(activityPageParams);
activity.percent = parseInt( data.list.forEach((activity) => {
(100 * (activity.totalStock - activity.stock)) / activity.totalStock, //
); activity.percent = parseInt(
}); (100 * (activity.totalStock - activity.stock)) / activity.totalStock,
activityList.value = activityList.value.concat(...data.list); );
activityTotal.value = data.total; });
activityList.value = activityList.value.concat(...data.list);
activityTotal.value = data.total;
loadStatus.value = activityList.value.length < activityTotal.value ? 'more' : 'noMore'; loadStatus.value = activityList.value.length < activityTotal.value ? 'more' : 'noMore';
} }
// //
function loadMore() { function loadMore() {
if (loadStatus.value !== 'noMore') { if (loadStatus.value !== 'noMore') {
activityPageParams.pageNo += 1; activityPageParams.pageNo += 1;
getActivityList(); getActivityList();
} }
} }
// //
onReachBottom(() => loadMore()); onReachBottom(() => loadMore());
//#endregion //#endregion
// //
onLoad(async () => { onLoad(async () => {
await getSeckillConfigList(); await getSeckillConfigList();
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// //
.page-bg { .page-bg {
width: 100%; width: 100%;
height: 458rpx; height: 458rpx;
background: v-bind(headerBg) no-repeat; background: v-bind(headerBg) no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
} }
// //
.header { .header {
width: 100%; width: 100%;
height: 330rpx; height: 330rpx;
margin: 0 auto 0 auto; margin: 0 auto 0 auto;
border-radius: 14rpx; border-radius: 14rpx;
overflow: hidden; overflow: hidden;
swiper {
height: 330rpx !important;
border-radius: 14rpx;
overflow: hidden;
}
image { swiper {
width: 100%; height: 330rpx !important;
height: 100%; border-radius: 14rpx;
border-radius: 14rpx; overflow: hidden;
overflow: hidden; }
img {
border-radius: 14rpx;
}
}
}
// image {
.time-icon { width: 100%;
width: 75rpx; height: 100%;
height: 70rpx; border-radius: 14rpx;
} overflow: hidden;
//
.time-list {
width: 596rpx;
white-space: nowrap;
//
.item {
display: inline-block;
font-size: 20rpx;
color: #666;
text-align: center;
box-sizing: border-box;
margin-right: 30rpx;
width: 130rpx;
//
.time {
font-size: 36rpx;
font-weight: 600;
color: #333;
}
//
&.active {
.time {
color: var(--ui-BG-Main);
}
//
.status {
height: 30rpx;
line-height: 30rpx;
border-radius: 15rpx;
width: 128rpx;
background: linear-gradient(90deg, var(--ui-BG-Main) 0%, var(--ui-BG-Main-gradient) 100%);
color: #fff;
}
}
}
}
// img {
.list-content { border-radius: 14rpx;
position: relative; }
z-index: 3; }
margin: 0 20rpx 0 20rpx; }
// background: #fff;
border-radius: 20rpx 20rpx 0 0;
.content-header {
width: 100%;
border-radius: 20rpx 20rpx 0 0;
height: 150rpx;
background: linear-gradient(180deg, #fff4f7, #ffe6ec);
.content-header-box { //
width: 678rpx; .time-icon {
height: 64rpx; width: 75rpx;
background: rgba($color: #fff, $alpha: 0.66); height: 70rpx;
border-radius: 32px; }
//
.countdown-title {
font-size: 28rpx;
font-weight: 500;
color: #333333;
line-height: 28rpx;
}
//
.countdown-time {
font-size: 28rpx;
color: rgba(#ed3c30, 0.23);
//
.countdown-h {
font-size: 24rpx;
font-family: OPPOSANS;
font-weight: 500;
color: #ffffff;
padding: 0 4rpx;
height: 40rpx;
background: rgba(#ed3c30, 0.23);
border-radius: 6rpx;
}
//
.countdown-num {
font-size: 24rpx;
font-family: OPPOSANS;
font-weight: 500;
color: #ffffff;
width: 40rpx;
height: 40rpx;
background: rgba(#ed3c30, 0.23);
border-radius: 6rpx;
}
}
}
}
//
.scroll-box {
height: 900rpx;
//
.goods-box {
position: relative;
//
.cart-btn {
position: absolute;
bottom: 10rpx;
right: 20rpx;
z-index: 11;
height: 44rpx;
line-height: 50rpx;
padding: 0 20rpx;
border-radius: 25rpx;
font-size: 24rpx;
color: #fff;
background: linear-gradient(90deg, #ff6600 0%, #fe832a 100%);
&.disabled { //
background: $gray-b; .time-list {
color: #fff; width: 596rpx;
} white-space: nowrap;
}
// //
.limit { .item {
font-size: 22rpx; display: inline-block;
color: $dark-9; font-size: 20rpx;
margin-bottom: 5rpx; color: #666;
} text-align: center;
} box-sizing: border-box;
} margin-right: 30rpx;
} width: 130rpx;
//
.time {
font-size: 36rpx;
font-weight: 600;
color: #333;
}
//
&.active {
.time {
color: var(--ui-BG-Main);
}
//
.status {
height: 30rpx;
line-height: 30rpx;
border-radius: 15rpx;
width: 128rpx;
background: linear-gradient(90deg, var(--ui-BG-Main) 0%, var(--ui-BG-Main-gradient) 100%);
color: #fff;
}
}
}
}
//
.list-content {
position: relative;
z-index: 3;
margin: 0 20rpx 0 20rpx;
// background: #fff;
border-radius: 20rpx 20rpx 0 0;
.content-header {
width: 100%;
border-radius: 20rpx 20rpx 0 0;
height: 150rpx;
background: linear-gradient(180deg, #fff4f7, #ffe6ec);
.content-header-box {
width: 678rpx;
height: 64rpx;
background: rgba($color: #fff, $alpha: 0.66);
border-radius: 32px;
//
.countdown-title {
font-size: 28rpx;
font-weight: 500;
color: #333333;
line-height: 28rpx;
}
//
.countdown-time {
font-size: 28rpx;
color: rgba(#ed3c30, 0.23);
//
.countdown-h {
font-size: 24rpx;
font-family: OPPOSANS;
font-weight: 500;
color: #ffffff;
padding: 0 4rpx;
height: 40rpx;
background: rgba(#ed3c30, 0.23);
border-radius: 6rpx;
}
//
.countdown-num {
font-size: 24rpx;
font-family: OPPOSANS;
font-weight: 500;
color: #ffffff;
width: 40rpx;
height: 40rpx;
background: rgba(#ed3c30, 0.23);
border-radius: 6rpx;
}
}
}
}
//
.scroll-box {
height: 900rpx;
//
.goods-box {
position: relative;
//
.cart-btn {
position: absolute;
bottom: 10rpx;
right: 20rpx;
z-index: 11;
height: 44rpx;
line-height: 50rpx;
padding: 0 20rpx;
border-radius: 25rpx;
font-size: 24rpx;
color: #fff;
background: linear-gradient(90deg, #ff6600 0%, #fe832a 100%);
&.disabled {
background: $gray-b;
color: #fff;
}
}
//
.limit {
font-size: 22rpx;
color: $dark-9;
margin-bottom: 5rpx;
}
}
}
}
</style> </style>

View File

@ -32,7 +32,7 @@
> >
<image <image
class="item-icon" class="item-icon"
src="/static/images/service.png" src="https://zysc.fjptzykj.com:3000/shangcheng/2f8b9d197059eb62e9dc212392a42fb481275b31f2af9c35033070ea15b71167.png"
mode="aspectFit" mode="aspectFit"
/> />
<view class="item-title">客服</view> <view class="item-title">客服</view>

View File

@ -1,236 +1,272 @@
<!-- 商品分类列表 --> <!-- 商品分类列表 -->
<template> <template>
<s-layout title="分类" tabbar="/pages/index/category" :bgStyle="{ color: '#fff' }"> <s-layout title="分类" tabbar="/pages/index/category" :bgStyle="{ color: '#fff' }">
<view class="s-category"> <view class="s-category">
<view class="three-level-wrap ss-flex ss-col-top" :style="[{ height: pageHeight + 'px' }]"> <view class="three-level-wrap ss-flex ss-col-top" :style="[{ height: pageHeight + 'px' }]">
<!-- 商品分类 --> <!-- 商品分类 -->
<scroll-view class="side-menu-wrap" scroll-y :style="[{ height: pageHeight + 'px' }]"> <scroll-view class="side-menu-wrap" scroll-y :style="[{ height: pageHeight + 'px' }]">
<view <view class="menu-item ss-flex" v-for="(item, index) in state.categoryList" :key="item.id"
class="menu-item ss-flex" :class="[{ 'menu-item-active': index === state.activeMenu }]" @tap="onMenu(index)">
v-for="(item, index) in state.categoryList" <view class="menu-title ss-line-1">
:key="item.id" {{ item.name }}
:class="[{ 'menu-item-active': index === state.activeMenu }]" </view>
@tap="onMenu(index)" </view>
> </scroll-view>
<view class="menu-title ss-line-1"> <!-- 商品分类 -->
{{ item.name }} <scroll-view class="goods-list-box" scroll-y :style="[{ height: pageHeight + 'px' }]"
</view> v-if="state.categoryList?.length">
</view>
</scroll-view> <view class="top_class">
<!-- 商品分类 --> <scroll-view scroll-x class="scroll">
<scroll-view <view class="list on" v-for="(item, index) in 6" :key="index">sss</view>
class="goods-list-box" <view class="list" style="width:0;"> </view> <!-- 为了不让标按钮覆盖按钮 -->
scroll-y
:style="[{ height: pageHeight + 'px' }]" </scroll-view>
v-if="state.categoryList?.length" <view class="rit">
> <image src="https://zysc.fjptzykj.com:3000/shangcheng/475ffa1c11d2bdb4997efb0ba4dfab0b971630ca9e140fa90686c7206db53c82.png" class="img"></image>
<!-- <image </view>
v-if="state.categoryList[state.activeMenu].picUrl" </view>
class="banner-img" <!-- <image v-if="state.categoryList[state.activeMenu].picUrl" class="banner-img" :src="sheep.$url.cdn(state.categoryList[state.activeMenu].picUrl)" mode="widthFix"/> -->
:src="sheep.$url.cdn(state.categoryList[state.activeMenu].picUrl)" <first-one v-if="state.style === 'first_one'" :pagination="state.pagination" />
mode="widthFix" <first-two v-if="state.style === 'first_two'" :pagination="state.pagination" />
/> --> <second-one v-if="state.style === 'second_one'" :data="state.categoryList"
<first-one v-if="state.style === 'first_one'" :pagination="state.pagination" /> :activeMenu="state.activeMenu" />
<first-two v-if="state.style === 'first_two'" :pagination="state.pagination" /> <uni-load-more v-if="
<second-one (state.style === 'first_one' || state.style === 'first_two') &&
v-if="state.style === 'second_one'" state.pagination.total > 0
:data="state.categoryList" " :status="state.loadStatus" :content-text="{
:activeMenu="state.activeMenu" contentdown: '点击查看更多',
/> }" @tap="loadMore" />
<uni-load-more </scroll-view>
v-if=" </view>
(state.style === 'first_one' || state.style === 'first_two') && </view>
state.pagination.total > 0 </s-layout>
"
:status="state.loadStatus"
:content-text="{
contentdown: '点击查看更多',
}"
@tap="loadMore"
/>
</scroll-view>
</view>
</view>
</s-layout>
</template> </template>
<script setup> <script setup>
import secondOne from './components/second-one.vue'; import secondOne from './components/second-one.vue';
import firstOne from './components/first-one.vue'; import firstOne from './components/first-one.vue';
import firstTwo from './components/first-two.vue'; import firstTwo from './components/first-two.vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import CategoryApi from '@/sheep/api/product/category'; import CategoryApi from '@/sheep/api/product/category';
import SpuApi from '@/sheep/api/product/spu'; import SpuApi from '@/sheep/api/product/spu';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import {
import { computed, reactive } from 'vue'; onLoad,
import _ from 'lodash'; onReachBottom
import { handleTree } from '@/sheep/util'; } from '@dcloudio/uni-app';
import {
computed,
reactive
} from 'vue';
import _ from 'lodash';
import {
handleTree
} from '@/sheep/util';
const state = reactive({ const state = reactive({
style: 'second_one', // first_one - , first_two - , second_one style: 'second_one', // first_one - , first_two - , second_one
categoryList: [], // categoryList: [], //
activeMenu: 0, // categoryList activeMenu: 0, // categoryList
pagination: { pagination: {
// //
list: [], // list: [], //
total: [], // total: [], //
pageNo: 1, pageNo: 1,
pageSize: 6, pageSize: 6,
}, },
loadStatus: '', loadStatus: '',
}); });
const { safeArea } = sheep.$platform.device; const {
const pageHeight = computed(() => safeArea.height - 44 - 50); safeArea
} = sheep.$platform.device;
const pageHeight = computed(() => safeArea.height - 44 - 50);
// //
async function getList() { async function getList() {
const { code, data } = await CategoryApi.getCategoryList(); const {
if (code !== 0) { code,
return; data
} } = await CategoryApi.getCategoryList();
state.categoryList = handleTree(data); if (code !== 0) {
} return;
}
state.categoryList = handleTree(data);
}
// //
const onMenu = (val) => { const onMenu = (val) => {
state.activeMenu = val; state.activeMenu = val;
if (state.style === 'first_one' || state.style === 'first_two') { if (state.style === 'first_one' || state.style === 'first_two') {
state.pagination.pageNo = 1; state.pagination.pageNo = 1;
state.pagination.list = []; state.pagination.list = [];
state.pagination.total = 0; state.pagination.total = 0;
getGoodsList(); getGoodsList();
} }
}; };
// //
async function getGoodsList() { async function getGoodsList() {
// //
state.loadStatus = 'loading'; state.loadStatus = 'loading';
const res = await SpuApi.getSpuPage({ const res = await SpuApi.getSpuPage({
categoryId: state.categoryList[state.activeMenu].id, categoryId: state.categoryList[state.activeMenu].id,
pageNo: state.pagination.pageNo, pageNo: state.pagination.pageNo,
pageSize: state.pagination.pageSize, pageSize: state.pagination.pageSize,
}); });
if (res.code !== 0) { if (res.code !== 0) {
return; return;
} }
// //
state.pagination.list = _.concat(state.pagination.list, res.data.list); state.pagination.list = _.concat(state.pagination.list, res.data.list);
state.pagination.total = res.data.total; state.pagination.total = res.data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore'; state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
} }
// //
function loadMore() { function loadMore() {
if (state.loadStatus === 'noMore') { if (state.loadStatus === 'noMore') {
return; return;
} }
state.pagination.pageNo++; state.pagination.pageNo++;
getGoodsList(); getGoodsList();
} }
onLoad(async () => { onLoad(async () => {
await getList(); await getList();
// first // first
if (state.style === 'first_one' || state.style === 'first_two') { if (state.style === 'first_one' || state.style === 'first_two') {
onMenu(0); onMenu(0);
} }
}); });
onReachBottom(() => { onReachBottom(() => {
loadMore(); loadMore();
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.s-category { .s-category {
:deep() { :deep() {
.side-menu-wrap { .side-menu-wrap {
width: 200rpx; width: 200rpx;
height: 100%; height: 100%;
// padding-left: 12rpx; // padding-left: 12rpx;
background-color: #f6f6f6; background-color: #f6f6f6;
.menu-item { .menu-item {
width: 100%; width: 100%;
height: 88rpx; height: 88rpx;
position: relative; position: relative;
transition: all linear 0.2s; transition: all linear 0.2s;
.menu-title { .menu-title {
line-height: 32rpx; line-height: 32rpx;
font-size: 23rpx; font-size: 14px;
font-weight: 400; font-weight: 400;
color: #333; color: #333;
margin-left: 28rpx; margin-left: 28rpx;
position: relative; position: relative;
z-index: 0; z-index: 0;
&::before { &::before {
content: ''; content: '';
width: 64rpx; width: 64rpx;
height: 12rpx; height: 12rpx;
background: linear-gradient( background: linear-gradient(90deg,
90deg, var(--ui-BG-Main-gradient),
var(--ui-BG-Main-gradient), var(--ui-BG-Main-light)) !important;
var(--ui-BG-Main-light) position: absolute;
) !important; left: -64rpx;
position: absolute; bottom: 0;
left: -64rpx; z-index: -1;
bottom: 0; transition: all linear 0.2s;
z-index: -1; }
transition: all linear 0.2s; }
}
}
&.menu-item-active { &.menu-item-active {
background-color: #fff; background-color: #fff;
// border-radius: 20rpx 0 0 20rpx;
&::before {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 2px;
height: 100%;
// background: radial-gradient(circle at 0 100%, transparent 20rpx, #fff 0);
background: rgba(236,72,29);
}
&::after { // border-radius: 20rpx 0 0 20rpx;
content: ''; &::before {
position: absolute; content: '';
top: -20rpx; position: absolute;
right: 0; left: 0;
width: 20rpx; bottom: 0;
height: 20rpx; width: 2px;
background: radial-gradient(circle at 0% 0%, transparent 20rpx, #fff 0); height: 100%;
} // background: radial-gradient(circle at 0 100%, transparent 20rpx, #fff 0);
background: rgba(236, 72, 29);
}
.menu-title { &::after {
font-weight: 600; content: '';
color:rgba(236,72,29); position: absolute;
// &::before { top: -20rpx;
// left: 0; right: 0;
// } width: 20rpx;
} height: 20rpx;
} background: radial-gradient(circle at 0% 0%, transparent 20rpx, #fff 0);
} }
}
.goods-list-box { .menu-title {
background-color: #fff; font-weight: 600;
width: calc(100vw - 100px); color: rgba(236, 72, 29);
padding: 10px; // &::before {
} // left: 0;
// }
}
}
}
}
.banner-img { .goods-list-box {
width: calc(100vw - 130px); background-color: #fff;
border-radius: 5px; width: calc(100vw - 100px);
margin-bottom: 20rpx; padding: 10px;
} .top_class{
} position:relative;
} .scroll{
white-space: nowrap;
margin-bottom: 10px;
.list{
padding:3px 15px;
background:rgba(248,248,248);
color:rgba(179,179,179);
display: inline-block;
border-radius: 13px;
margin-right:10px;
&.on{
background:rgba(255,235,234);
color:rgba(223,47,41);
}
}
}
.rit{
position:absolute;
right:0;
top:0;
width:40px;
height:100%;
background-color: white;
display: flex;
align-items: center;
text-align: center;
justify-content: center;
.img{
width:15px;
height:15px;
}
}
}
}
.banner-img {
width: calc(100vw - 130px);
border-radius: 5px;
margin-bottom: 20rpx;
}
}
}
</style> </style>

View File

@ -1,106 +1,100 @@
<!-- 首页支持店铺装修 --> <!-- 首页支持店铺装修 -->
<template> <template>
<view v-if="template"> <view v-if="template">
<s-layout <s-layout title="首页" navbar="normal" tools="search" tabbar="/pages/index/index" :bgStyle="template.page"
title="首页" :navbarStyle="template.navigationBar" onShareAppMessage @search="(e) => { console.log(e,'eeeeeeeeeeee') }"
navbar="normal" headerBtns='headerBtns' backgroundColor="rgba(248,83,42)" opacityBgUi='ll' :navBg="true">
tools="search" <view class="new-bg"></view>
tabbar="/pages/index/index"
:bgStyle="template.page" <s-block v-for="(item, index) in template.components" :key="index" :styles="item.property.style">
:navbarStyle="template.navigationBar" <s-block-item :type="item.id" :data="item.property" :styles="item.property.style" :fl="true" />
onShareAppMessage </s-block>
@search="(e) => { console.log(e,'eeeeeeeeeeee') }" </s-layout>
headerBtns='headerBtns' </view>
backgroundColor="rgba(248,83,42)"
opacityBgUi='ll'
:navBg="true"
>
<view class="new-bg"></view>
<s-block
v-for="(item, index) in template.components"
:key="index"
:styles="item.property.style"
>
<s-block-item :type="item.id" :data="item.property" :styles="item.property.style" />
</s-block>
</s-layout>
</view>
</template> </template>
<script setup> <script setup>
import { computed } from 'vue'; import {
import { onLoad, onPageScroll, onPullDownRefresh } from '@dcloudio/uni-app'; computed
import sheep from '@/sheep'; } from 'vue';
import $share from '@/sheep/platform/share'; import {
// tabBar onLoad,
uni.hideTabBar(); onPageScroll,
onPullDownRefresh
} from '@dcloudio/uni-app';
import sheep from '@/sheep';
import $share from '@/sheep/platform/share';
// tabBar
uni.hideTabBar();
const template = computed(() => sheep.$store('app').template?.home); const template = computed(() => sheep.$store('app').template?.home);
// //
// (async function() { // (async function() {
// console.log('',template) // console.log('',template)
// let { // let {
// data // data
// } = await index2Api.decorate(); // } = await index2Api.decorate();
// console.log('',JSON.parse(data[1].value)) // console.log('',JSON.parse(data[1].value))
// id // id
// let { // let {
// data: datas // data: datas
// } = await index2Api.spids(); // } = await index2Api.spids();
// template.value.data[9].data.goodsIds = datas.list.map(item => item.id); // template.value.data[9].data.goodsIds = datas.list.map(item => item.id);
// template.value.data[0].data.list = JSON.parse(data[0].value).map(item => { // template.value.data[0].data.list = JSON.parse(data[0].value).map(item => {
// return { // return {
// src: item.picUrl, // src: item.picUrl,
// url: item.url, // url: item.url,
// title: item.name, // title: item.name,
// type: "image" // type: "image"
// } // }
// }) // })
// }()) // }())
onLoad((options) => { onLoad((options) => {
// #ifdef MP // #ifdef MP
// //
if (options.scene) { if (options.scene) {
const sceneParams = decodeURIComponent(options.scene).split('='); const sceneParams = decodeURIComponent(options.scene).split('=');
console.log('sceneParams=>', sceneParams); console.log('sceneParams=>', sceneParams);
options[sceneParams[0]] = sceneParams[1]; options[sceneParams[0]] = sceneParams[1];
} }
// #endif // #endif
// //
if (options.templateId) { if (options.templateId) {
sheep.$store('app').init(options.templateId); sheep.$store('app').init(options.templateId);
} }
// //
if (options.spm) { if (options.spm) {
$share.decryptSpm(options.spm); $share.decryptSpm(options.spm);
} }
// () // ()
if (options.page) { if (options.page) {
sheep.$router.go(decodeURIComponent(options.page)); sheep.$router.go(decodeURIComponent(options.page));
} }
}); });
// //
onPullDownRefresh(() => { onPullDownRefresh(() => {
sheep.$store('app').init(); sheep.$store('app').init();
setTimeout(function () { setTimeout(function() {
uni.stopPullDownRefresh(); uni.stopPullDownRefresh();
}, 800); }, 800);
}); });
onPageScroll(() => {}); onPageScroll(() => {});
</script> </script>
<style lang="scss"> <style lang="scss">
.new-bg{ .new-bg {
background:rgba(248,83,42); background: rgba(248, 83, 42);
width:100%; width: 100%;
height:50px; height: 50px;
position: absolute; position: absolute;
} }
</style> </style>

View File

@ -59,11 +59,11 @@
<!-- TODO 芋艿订阅 --> <!-- TODO 芋艿订阅 -->
<!-- #ifdef MP --> <!-- #ifdef MP -->
<view class="subscribe-box ss-flex ss-m-t-44"> <!-- <view class="subscribe-box ss-flex ss-m-t-44">
<image class="subscribe-img" :src="sheep.$url.static('/static/img/shop/order/cargo.png')" /> <image class="subscribe-img" :src="sheep.$url.static('/static/img/shop/order/cargo.png')" />
<view class="subscribe-title ss-m-r-48 ss-m-l-16">获取实时发货信息与订单状态</view> <view class="subscribe-title ss-m-r-48 ss-m-l-16">获取实时发货信息与订单状态</view>
<view class="subscribe-start" @tap="subscribeMessage">立即订阅</view> <view class="subscribe-start" @tap="subscribeMessage">立即订阅</view>
</view> </view> -->
<!-- #endif --> <!-- #endif -->
</view> </view>
</s-layout> </s-layout>

View File

@ -11,7 +11,7 @@
<text class="address">预约姓名<text class="title">{{ item.name }}</text></text> <text class="address">预约姓名<text class="title">{{ item.name }}</text></text>
<text class="address">预约电话<text class="title">{{ item.phone }}</text></text> <text class="address">预约电话<text class="title">{{ item.phone }}</text></text>
<text class="address">预约时间<text <text class="address">预约时间<text
class="title">{{ item.days }}</text></text> class="title">{{ item.timeQuantum }}</text></text>
<text class="address">项目名称<text class="title">{{ item.projectName }}</text> </text> <text class="address">项目名称<text class="title">{{ item.projectName }}</text> </text>
<text class="address">项目套餐<text class="title">{{ item.technicianName }}</text> </text> <text class="address">项目套餐<text class="title">{{ item.technicianName }}</text> </text>
<!-- <div class="address-container"> <!-- <div class="address-container">

View File

@ -110,7 +110,7 @@
立即预约 立即预约
</view> </view>
</view> </view>
<fui-toast ref="toast"></fui-toast>
</s-layout> </s-layout>
</template> </template>
@ -174,6 +174,8 @@
ll: '请选择', ll: '请选择',
ll2: '请选择', ll2: '请选择',
ll3: '请选择', ll3: '请选择',
ll5: '请选择', //
ll6: '请选择', //
gg: '请选择', gg: '请选择',
dateIndex: '', // dateIndex: '', //
name: '', name: '',
@ -211,6 +213,16 @@
}, },
onClinicChange2(event) { onClinicChange2(event) {
this.brandId3 = ''
this.brandId4 = ''
this.brandId5 = ''
this.name = ''
this.phone = ''
this.ll3 = '请选择'
this.brandNameList3 = []
this.dateList = []
this.brandList3 = []
const selectedClinicIndex = event.detail.value; const selectedClinicIndex = event.detail.value;
this.selectedClinicIndex2 = selectedClinicIndex; this.selectedClinicIndex2 = selectedClinicIndex;
this.ll2 = this.brandList2[selectedClinicIndex].name this.ll2 = this.brandList2[selectedClinicIndex].name
@ -301,8 +313,6 @@
if (res) { if (res) {
} }
console.log(this.brandList3, "------brandList3---------");
console.log(res, "------brandList3---------");
this.brandList3 = res.data this.brandList3 = res.data
for (var i = 0; i < this.brandList3.length; i++) { for (var i = 0; i < this.brandList3.length; i++) {
this.brandNameList3.push(this.brandList3[i].name) this.brandNameList3.push(this.brandList3[i].name)
@ -359,8 +369,29 @@
}, },
}).then((res) => { }).then((res) => {
if (res.code == 0) { if (res.code == 0) {
sheep.$helper.toast('提交成功');
sheep.$router.go('/pages/index/user')
sheep.$router.go('/pages/subscribe/success_tolse', {
brandId: this.ll, //
projectId: this.ll2, //
technicianId: this.ll3, //
projectdayId: this.ll5, //
timeId: this.ll6, //
name: this.name, //
phone: this.phone //
})
// let options = {}
//
// options.text = '';
//
// options.src = "https://zysc.fjptzykj.com:3000/shangcheng/44252dee36b3ba686967c33e911b15c565f5ccc4c7b2a9f56e43418da949b7c2.png";
// this.$refs.toast.show(options)
// setTimeout(()=>{
// sheep.$router.go('/pages/index/user')
// },1000)
} }
}); });
@ -372,24 +403,24 @@
delete(val) {}, delete(val) {},
// //
selectDate(index) { selectDate(index) {
console.log(this.brandList3, "brandList3")
if (this.brandId3 == '') { if (this.brandId3 == '') {
sheep.$helper.toast('请先选择套餐') sheep.$helper.toast('请先选择套餐')
return; return;
} }
this.dateIndex = index; this.dateIndex = index;
this.brandId4 = this.dateList[index].id; this.brandId4 = this.dateList[index].id;
this.ll5 = this.dateList[index].days;
this.brandlists4(); this.brandlists4();
}, },
selecthsstr(index, status) { selecthsstr(index, status) {
console.log(this.brandList4[index].timeQuantum, "查看时段")
if (status == 0) { if (status == 0) {
this.brandId5 = ''; this.brandId5 = '';
console.log('this.brandId5', this.brandId5);
sheep.$helper.toast('该时间段已约满') sheep.$helper.toast('该时间段已约满')
return; return;
} }
this.brandId5 = this.brandList4[index].id; this.brandId5 = this.brandList4[index].id;
console.log('this.brandId5', this.brandId5); this.ll6 = this.brandList4[index].timeQuantum;
} }
}, },
}; };

View File

@ -0,0 +1,177 @@
<template>
<s-layout title="预约成功" :bgStyle="{ color: '#fff' }">
<view class="main">
<view class="main-t">
<view class="img-t">
<image
src="https://zysc.fjptzykj.com:3000/shangcheng/ab5eb1046be1b2d98fbab61cd1925301725b7a6d2d263fc22ea1a788e39df38d.png"
class="img"></image>
</view>
<view class="img-b">
预约成功
</view>
</view>
<view class="main-b">
<view class="list">
<view class="name">姓名</view>
<view class="name-value">{{ item.name }}</view>
</view>
<view class="list">
<view class="name">电话</view>
<view class="name-value">{{ item.phone }}</view>
</view>
<view class="list">
<view class="name">预约门店</view>
<view class="name-value">{{item.brandId}}</view>
</view>
<view class="list">
<view class="name">项目套餐</view>
<view class="name-value">{{item.projectId}} {{ item.technicianId }}</view>
</view>
<view class="list">
<view class="name">预约时间</view>
<view class="name-value">{{ item.projectdayId }} {{item.timeId}}</view>
</view>
</view>
</view>
<view class="btn" @click="sheep.$router.go('/pages/index/user')">
确认
</view>
</s-layout>
</template>
<script>
import {
ref,
computed,
onMounted
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app';
import request from '@/sheep/request';
import {
baseUrl,
apiPath
} from '@/sheep/config';
import sheep from '@/sheep';
export default {
setup() {
// 使 ref
const memberId = ref(null);
const reservationList = ref([]);
const page = ref(1);
const limit = ref(10);
const totalPages = ref(1);
const item = ref({});
// 使 computed
const userInfo = computed(() => sheep.$store('user').userInfo);
memberId.value = userInfo.value.id;
// 使 onMounted
onMounted(() => {
getList();
});
onLoad((options) => {
if (options) {
item.value = options;
console.log(item.value,"-------------------")
}
});
//
function getList() {
request({
url: `${baseUrl}${apiPath}/h5/reservation/reservationInfo`,
method: 'GET',
custom: {
showLoading: false,
},
}).then((res) => {
reservationList.value = res.data;
});
}
//
return {
memberId,
reservationList,
page,
limit,
totalPages,
getList,
sheep,
item
};
},
};
</script>
<style scope lang="scss">
.main {
background: white;
margin: 15px 15px;
border-radius: 12px;
padding-bottom: 10px;
.main-t {
.img-t {
padding-bottom: 20px;
.img {
width: 143px;
height: 106px;
display: block;
margin: 10px auto;
padding-top: 25px;
}
}
.img-b {
text-align: center;
font-size: 24px;
font-weight: 700;
width: 90%;
margin: 0 auto;
border-bottom: 1px solid rgba(233, 233, 233);
padding-bottom: 15px;
}
}
.main-b {
margin: 10px auto;
width: 90%;
margin-top: 40px;
.list {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
margin:10px 0;
.name {
font-size: 17px;
color: rgba(101, 101, 101);
}
.name-value {
font-size: 17px;
}
}
}
}
.btn {
position: absolute;
bottom: 60px;
left: 50%;
transform: translateX(-50%);
border-radius: 16px;
background: rgba(0, 149, 248);
text-align: center;
color: white;
width: 89%;
padding: 10px 0;
}
</style>

View File

@ -0,0 +1,45 @@
<!-- 会员信息 -->
<template>
<s-layout navbar="normal" title="会员协议">
<view class="main" v-html="data">
</view>
</s-layout>
</template>
<script setup>
import {
computed,
reactive,
onBeforeMount,
onMounted,
ref
} from 'vue';
import request from '@/sheep/request';
import {
baseUrl,
apiPath
} from '@/sheep/config';
import sheep from '@/sheep';
const data = ref([]);
request({
url: `${baseUrl}${apiPath}/member/paid-member-agree/get`,
method: 'GET',
params: {
},
custom: {
showLoading: false,
},
}).then((res) => {
data.value = res.data.content
});
// 使 onMounted
onMounted(() => {
});
</script>
<style lang="scss" scoped>
.main{
width: 93%;
margin:10px auto;
}
</style>

View File

@ -17,7 +17,7 @@
</view> </view>
<view class="c" v-if="!userInfo.activate">您与众悦e家商场的第101天</view> <view class="c" v-if="!userInfo.activate">您与众悦e家商场的第101天</view>
<view class="b" v-if="!userInfo.activate">开通即享会员权益</view> <view class="b" v-if="!userInfo.activate">开通即享会员权益</view>
<view class="b" v-if="userInfo.activate">SVIP会员 {{userInfo.cardExpirationTime}} 到期</view> <view class="b" v-if="userInfo.activate">SVIP会员 {{ sheep.$helper.timeFormat(userInfo.cardExpirationTime, 'yyyy-mm-dd') }} 到期</view>
</view> </view>
</view> </view>
<view class="r" v-if="!userInfo.activate"> <view class="r" v-if="!userInfo.activate">
@ -60,7 +60,7 @@
<!-- <text class="t1" v-if="userInfo.activate == 1">试用会员</text> --> <!-- <text class="t1" v-if="userInfo.activate == 1">试用会员</text> -->
<text class="t1" v-if="!userInfo.activate">开通会员</text> <text class="t1" v-if="!userInfo.activate">开通会员</text>
<text class="t2" v-if="userInfo.activate">有效期至</text> <text class="t2" v-if="userInfo.activate">有效期至</text>
<text class="t3" v-if="userInfo.activate">{{userInfo.cardExpirationTime}}</text> <text class="t3" v-if="userInfo.activate">{{ sheep.$helper.timeFormat(userInfo.cardExpirationTime, 'yyyy-mm-dd') }}</text>
</view> </view>
<scroll-view class="scroll-view_H" scroll-x="true" @scroll="scroll" scroll-left="120"> <scroll-view class="scroll-view_H" scroll-x="true" @scroll="scroll" scroll-left="120">
<view id="demo1" @click="vipFun(index,item.name)" class="scroll-view-item_H uni-bg-red" <view id="demo1" @click="vipFun(index,item.name)" class="scroll-view-item_H uni-bg-red"
@ -74,7 +74,7 @@
</view> </view>
<view class="vip-text"> <view class="vip-text">
购买即视为同意<text class="ts">会员用户协议</text> 购买即视为同意<text class="ts" @click="sheep.$router.redirect('/pages/user/user_vip/agreement')">会员用户协议</text>
</view> </view>
<!-- <view class="vip-btn" @click="beclick()" v-if="!userInfo.activate"> <!-- <view class="vip-btn" @click="beclick()" v-if="!userInfo.activate">
立即试用 立即试用
@ -115,7 +115,6 @@
showLoading: false, showLoading: false,
}, },
}).then((res) => { }).then((res) => {
console.log(res, "sss")
vipList.value = res.data; vipList.value = res.data;
}); });
} }
@ -128,12 +127,14 @@
function vipFun(index, name) { function vipFun(index, name) {
valVip.value = index valVip.value = index
data.cardName = name data.cardName = name
console.log(index, name, "name")
} }
// beclick // beclick
function beclick() { function beclick() {
console.log(data.cardName, "nameVip.value") if( data.cardName == '' ) {
sheep.$helper.toast('请选择')
return;
};
request({ request({
url: `${baseUrl}${apiPath}/pay/member/create`, url: `${baseUrl}${apiPath}/pay/member/create`,
method: 'post', method: 'post',
@ -142,11 +143,10 @@
showLoading: false, showLoading: false,
}, },
}).then((res) => { }).then((res) => {
console.log(res, "-----------试用---------------")
if (res.code == 0) { if (res.code == 0) {
if (data.cardName == "试用") { if (data.cardName == "试用") {
sheep.$helper.toast('试用开通成功'); sheep.$helper.toast('试用开通成功');
sheep.$router.go('/pages/index/user') // sheep.$router.go('/pages/index/user')
} else { } else {
sheep.$router.go('/pages/pay/index', { sheep.$router.go('/pages/pay/index', {
id: res.data.payOrderId, id: res.data.payOrderId,
@ -173,7 +173,6 @@
showLoading: false, showLoading: false,
}, },
}).then((res) => { }).then((res) => {
console.log(res, "sss")
vipList2.value = res.data; vipList2.value = res.data;
}); });
} }

View File

@ -33,11 +33,11 @@
<view class="new-point"> <view class="new-point">
<view class="l"> <view class="l">
<view class="b">{{state.pointData.addUp}}</view> <view class="b">{{state.pointData?.addUp}}</view>
<view class="c">累计积分</view> <view class="c">累计积分</view>
</view> </view>
<view class="l"> <view class="l">
<view class="b">{{state.pointData.reduce}}</view> <view class="b">{{state.pointData?.reduce}}</view>
<view class="c">累计消费</view> <view class="c">累计消费</view>
</view> </view>
<view class="l"> <view class="l">

View File

@ -31,7 +31,7 @@
<s-hotzone-block v-if="type === 'HotZone'" :data="data" :styles="styles" /> <s-hotzone-block v-if="type === 'HotZone'" :data="data" :styles="styles" />
<!-- 商品组件商品卡片 --> <!-- 商品组件商品卡片 -->
<s-goods-card v-if="type === 'ProductCard'" :data="data" :styles="styles" /> <s-goods-card v-if="type === 'ProductCard'" :data="data" :styles="styles" :fl="fl" />
<!-- 商品组件商品栏 --> <!-- 商品组件商品栏 -->
<s-goods-shelves v-if="type === 'ProductList'" :data="data" :styles="styles" /> <s-goods-shelves v-if="type === 'ProductList'" :data="data" :styles="styles" />
@ -45,6 +45,8 @@
<s-live-block v-if="type === 'MpLive'" :data="data" :styles="styles" /> <s-live-block v-if="type === 'MpLive'" :data="data" :styles="styles" />
<!-- 营销组件优惠券 --> <!-- 营销组件优惠券 -->
<s-coupon-block v-if="type === 'CouponCard'" :data="data" :styles="styles" /> <s-coupon-block v-if="type === 'CouponCard'" :data="data" :styles="styles" />
<!-- 营销组件魔方 -->
<s-mof-block v-if="type === 'CouponCard'" :data="data" :styles="styles" />
<!-- 营销组件文章 --> <!-- 营销组件文章 -->
<!-- <s-richtext-block v-if="type === 'PromotionArticle'" :data="data" :styles="styles" /> --> <!-- <s-richtext-block v-if="type === 'PromotionArticle'" :data="data" :styles="styles" /> -->
<view class="floxt" v-if="type === 'PromotionArticle'"> <view class="floxt" v-if="type === 'PromotionArticle'">
@ -121,6 +123,10 @@
type: Object, type: Object,
default () {}, default () {},
}, },
fl: {
type: Boolean,
default: false,
}
}); });
function path(id) { function path(id) {

View File

@ -1,292 +1,300 @@
<!-- 装修商品组件商品卡片 --> <!-- 装修商品组件商品卡片 -->
<template> <template>
<!-- 商品卡片 --> <!-- 商品卡片 -->
<view> <view>
<!-- 布局1. 单列大图上图下内容--> <view class="new-fenlei" v-if="fl">
<view <view class="list on">
v-if="layoutType === LayoutTypeEnum.ONE_COL_BIG_IMG && state.goodsList.length" <view class="t">首页新品</view>
class="goods-sl-box" <view class="b">最新出炉</view>
> </view>
<view <view class="list" v-for="(item, index) in 3" :key="index">
class="goods-box" <view class="t">首页新品</view>
v-for="item in state.goodsList" <view class="b">最新出炉</view>
:key="item.id" </view>
:style="[{ marginBottom: data.space * 2 + 'rpx' }]" </view>
> <!-- 布局1. 单列大图上图下内容-->
<s-goods-column <view v-if="layoutType === LayoutTypeEnum.ONE_COL_BIG_IMG && state.goodsList.length" class="goods-sl-box">
class=""
size="sl"
:goodsFields="data.fields"
:tagStyle="data.badge"
:data="item"
:titleColor="data.fields.name?.color"
:subTitleColor="data.fields.introduction.color"
:topRadius="data.borderRadiusTop"
:bottomRadius="data.borderRadiusBottom"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
>
<!-- 购买按钮 -->
<template v-slot:cart>
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
</button>
</template>
</s-goods-column>
</view>
</view>
<!-- 布局2. 双列每一列上图下内容--> <view class="goods-box" v-for="item in state.goodsList" :key="item.id"
<view :style="[{ marginBottom: data.space * 2 + 'rpx' }]">
v-if="layoutType === LayoutTypeEnum.TWO_COL && state.goodsList.length" <s-goods-column class="" size="sl" :goodsFields="data.fields" :tagStyle="data.badge" :data="item"
class="goods-md-wrap ss-flex ss-flex-wrap ss-col-top" :titleColor="data.fields.name?.color" :subTitleColor="data.fields.introduction.color"
> :topRadius="data.borderRadiusTop" :bottomRadius="data.borderRadiusBottom"
<view class="goods-list-box"> @click="sheep.$router.go('/pages/goods/index', { id: item.id })">
<view <!-- 购买按钮 -->
class="left-list" <template v-slot:cart>
:style="[{ paddingRight: data.space + 'rpx', marginBottom: data.space + 'px' }]" <button class="ss-reset-button cart-btn" :style="[buyStyle]">
v-for="item in state.leftGoodsList" {{ btnBuy.type === 'text' ? btnBuy.text : '' }}
:key="item.id" </button>
> </template>
<s-goods-column </s-goods-column>
class="goods-md-box" </view>
size="md" </view>
:goodsFields="data.fields"
:tagStyle="data.badge"
:data="item"
:titleColor="data.fields.name?.color"
:subTitleColor="data.fields.introduction.color"
:topRadius="data.borderRadiusTop"
:bottomRadius="data.borderRadiusBottom"
:titleWidth="330 - marginLeft - marginRight"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
@getHeight="calculateGoodsColumn($event, 'left')"
>
<!-- 购买按钮 -->
<template v-slot:cart>
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
</button>
</template>
</s-goods-column>
</view>
</view>
<view class="goods-list-box">
<view
class="right-list"
:style="[{ paddingLeft: data.space + 'rpx', marginBottom: data.space + 'px' }]"
v-for="item in state.rightGoodsList"
:key="item.id"
>
<s-goods-column
class="goods-md-box"
size="md"
:goodsFields="data.fields"
:tagStyle="data.badge"
:data="item"
:titleColor="data.fields.name?.color"
:subTitleColor="data.fields.introduction.color"
:topRadius="data.borderRadiusTop"
:bottomRadius="data.borderRadiusBottom"
:titleWidth="330 - marginLeft - marginRight"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
@getHeight="calculateGoodsColumn($event, 'right')"
>
<!-- 购买按钮 -->
<template v-slot:cart>
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
</button>
</template>
</s-goods-column>
</view>
</view>
</view>
<!-- 布局3. 单列小图左图右内容 --> <!-- 布局2. 双列每一列上图下内容-->
<view <view v-if="layoutType === LayoutTypeEnum.TWO_COL && state.goodsList.length"
v-if="layoutType === LayoutTypeEnum.ONE_COL_SMALL_IMG && state.goodsList.length" class="goods-md-wrap ss-flex ss-flex-wrap ss-col-top">
class="goods-lg-box" <view class="goods-list-box">
> <view class="left-list" :style="[{ paddingRight: data.space + 'rpx', marginBottom: data.space + 'px' }]"
<view v-for="item in state.leftGoodsList" :key="item.id">
class="goods-box" <s-goods-column class="goods-md-box" size="md" :goodsFields="data.fields" :tagStyle="data.badge"
:style="[{ marginBottom: data.space + 'px' }]" :data="item" :titleColor="data.fields.name?.color"
v-for="item in state.goodsList" :subTitleColor="data.fields.introduction.color" :topRadius="data.borderRadiusTop"
:key="item.id" :bottomRadius="data.borderRadiusBottom" :titleWidth="330 - marginLeft - marginRight"
> @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
<s-goods-column @getHeight="calculateGoodsColumn($event, 'left')">
class="goods-card" <!-- 购买按钮 -->
size="lg" <template v-slot:cart>
:goodsFields="data.fields" <button class="ss-reset-button cart-btn" :style="[buyStyle]">
:data="item" {{ btnBuy.type === 'text' ? btnBuy.text : '' }}
:tagStyle="data.badge" </button>
:titleColor="data.fields.name?.color" </template>
:subTitleColor="data.fields.introduction.color" </s-goods-column>
:topRadius="data.borderRadiusTop" </view>
:bottomRadius="data.borderRadiusBottom" </view>
@tap="sheep.$router.go('/pages/goods/index', { id: item.id })" <view class="goods-list-box">
> <view class="right-list" :style="[{ paddingLeft: data.space + 'rpx', marginBottom: data.space + 'px' }]"
<!-- 购买按钮 --> v-for="item in state.rightGoodsList" :key="item.id">
<template v-slot:cart> <s-goods-column class="goods-md-box" size="md" :goodsFields="data.fields" :tagStyle="data.badge"
<button class="ss-reset-button cart-btn" :style="[buyStyle]"> :data="item" :titleColor="data.fields.name?.color"
{{ btnBuy.type === 'text' ? btnBuy.text : '' }} :subTitleColor="data.fields.introduction.color" :topRadius="data.borderRadiusTop"
</button> :bottomRadius="data.borderRadiusBottom" :titleWidth="330 - marginLeft - marginRight"
</template> @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
</s-goods-column> @getHeight="calculateGoodsColumn($event, 'right')">
</view> <!-- 购买按钮 -->
</view> <template v-slot:cart>
</view> <button class="ss-reset-button cart-btn" :style="[buyStyle]">
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
</button>
</template>
</s-goods-column>
</view>
</view>
</view>
<!-- 布局3. 单列小图左图右内容 -->
<view v-if="layoutType === LayoutTypeEnum.ONE_COL_SMALL_IMG && state.goodsList.length" class="goods-lg-box">
<view class="goods-box" :style="[{ marginBottom: data.space + 'px' }]" v-for="item in state.goodsList"
:key="item.id">
<s-goods-column class="goods-card" size="lg" :goodsFields="data.fields" :data="item"
:tagStyle="data.badge" :titleColor="data.fields.name?.color"
:subTitleColor="data.fields.introduction.color" :topRadius="data.borderRadiusTop"
:bottomRadius="data.borderRadiusBottom"
@tap="sheep.$router.go('/pages/goods/index', { id: item.id })">
<!-- 购买按钮 -->
<template v-slot:cart>
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
</button>
</template>
</s-goods-column>
</view>
</view>
</view>
</template> </template>
<script setup> <script setup>
/** /**
* 商品卡片 * 商品卡片
*/ */
import { computed, reactive, onMounted } from 'vue'; import {
import sheep from '@/sheep'; computed,
import SpuApi from '@/sheep/api/product/spu'; reactive,
onMounted
} from 'vue';
import sheep from '@/sheep';
import SpuApi from '@/sheep/api/product/spu';
// //
const LayoutTypeEnum = { const LayoutTypeEnum = {
// //
ONE_COL_BIG_IMG: 'oneColBigImg', ONE_COL_BIG_IMG: 'oneColBigImg',
// //
TWO_COL: 'twoCol', TWO_COL: 'twoCol',
// //
ONE_COL_SMALL_IMG: 'oneColSmallImg', ONE_COL_SMALL_IMG: 'oneColSmallImg',
}; };
const state = reactive({ const state = reactive({
goodsList: [], goodsList: [],
leftGoodsList: [], leftGoodsList: [],
rightGoodsList: [], rightGoodsList: [],
}); });
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object, type: Object,
default() {}, default () {},
}, },
styles: { styles: {
type: Object, type: Object,
default() {}, default () {},
}, },
}); fl: {
type: Boolean,
default: false,
},
});
const { layoutType, btnBuy, spuIds } = props.data ?? {}; const {
const { marginLeft, marginRight } = props.styles ?? {}; layoutType,
btnBuy,
spuIds
} = props.data ?? {};
const {
marginLeft,
marginRight
} = props.styles ?? {};
// //
const buyStyle = computed(() => { const buyStyle = computed(() => {
if (btnBuy.type === 'text') { if (btnBuy.type === 'text') {
// 线 // 线
return { return {
background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`, background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
}; };
} }
if (btnBuy.type === 'img') { if (btnBuy.type === 'img') {
// //
return { return {
width: '54rpx', width: '54rpx',
height: '54rpx', height: '54rpx',
background: `url(${sheep.$url.cdn(btnBuy.imgUrl)}) no-repeat`, background: `url(${sheep.$url.cdn(btnBuy.imgUrl)}) no-repeat`,
backgroundSize: '100% 100%', backgroundSize: '100% 100%',
}; };
} }
}); });
//region //region
// //
let count = 0; let count = 0;
// //
let leftHeight = 0; let leftHeight = 0;
// //
let rightHeight = 0; let rightHeight = 0;
/** /**
* 计算商品在左列还是右列 * 计算商品在左列还是右列
* @param height 商品的高度 * @param height 商品的高度
* @param where 添加到哪一列 * @param where 添加到哪一列
*/ */
function calculateGoodsColumn(height = 0, where = 'left') { function calculateGoodsColumn(height = 0, where = 'left') {
// //
if (!state.goodsList[count]) return; if (!state.goodsList[count]) return;
// //
if (where === 'left') leftHeight += height; if (where === 'left') leftHeight += height;
if (where === 'right') rightHeight += height; if (where === 'right') rightHeight += height;
// //
if (leftHeight <= rightHeight) { if (leftHeight <= rightHeight) {
state.leftGoodsList.push(state.goodsList[count]); state.leftGoodsList.push(state.goodsList[count]);
} else { } else {
state.rightGoodsList.push(state.goodsList[count]); state.rightGoodsList.push(state.goodsList[count]);
} }
// //
count++; count++;
} }
//endregion //endregion
/** /**
* 根据商品编号列表获取商品列表 * 根据商品编号列表获取商品列表
* @param ids 商品编号列表 * @param ids 商品编号列表
* @return {Promise<undefined>} 商品列表 * @return {Promise<undefined>} 商品列表
*/ */
async function getGoodsListByIds(ids) { async function getGoodsListByIds(ids) {
const { data } = await SpuApi.getSpuListByIds(ids); const {
return data; data
} } = await SpuApi.getSpuListByIds(ids);
return data;
}
// //
onMounted(async () => { onMounted(async () => {
// //
state.goodsList = await getGoodsListByIds(spuIds.join(',')); state.goodsList = await getGoodsListByIds(spuIds.join(','));
// //
if (layoutType === LayoutTypeEnum.TWO_COL) { if (layoutType === LayoutTypeEnum.TWO_COL) {
// //
calculateGoodsColumn(); calculateGoodsColumn();
} }
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.goods-md-wrap { .new-fenlei {
width: 100%; width: 100%;
} display: flex;
margin:10px 0;
.list {
width: 24%;
&.on{
.t {
color: rgba(255, 102, 7);
}
.goods-list-box { .b {
width: 50%; background: rgba(255, 102, 7);
box-sizing: border-box; color:white;
.left-list { }
&:nth-last-child(1) { }
margin-bottom: 0 !important; .t {
} text-align: center;
} }
.right-list {
&:nth-last-child(1) {
margin-bottom: 0 !important;
}
}
}
.goods-box { .b {
&:nth-last-of-type(1) { // background: rgba(255, 102, 7);
margin-bottom: 0 !important; text-align: center;
} color: rgba(153,153,153);
} border-radius: 15px;
width: 63%;
margin: 0 auto;
font-size: 11px;
margin-top:5px;
}
}
}
.goods-md-box, .goods-md-wrap {
.goods-sl-box, width: 100%;
.goods-lg-box { }
position: relative;
.cart-btn { .goods-list-box {
position: absolute; width: 50%;
bottom: 18rpx; box-sizing: border-box;
right: 20rpx;
z-index: 11; .left-list {
height: 50rpx; &:nth-last-child(1) {
line-height: 50rpx; margin-bottom: 0 !important;
padding: 0 20rpx; }
border-radius: 25rpx; }
font-size: 24rpx;
color: #fff; .right-list {
} &:nth-last-child(1) {
} margin-bottom: 0 !important;
}
}
}
.goods-box {
&:nth-last-of-type(1) {
margin-bottom: 0 !important;
}
}
.goods-md-box,
.goods-sl-box,
.goods-lg-box {
position: relative;
.cart-btn {
position: absolute;
bottom: 18rpx;
right: 20rpx;
z-index: 11;
height: 50rpx;
line-height: 50rpx;
padding: 0 20rpx;
border-radius: 25rpx;
font-size: 24rpx;
color: #fff;
}
}
</style> </style>

View File

@ -0,0 +1,197 @@
<!-- 全局 - 快捷入口 -->
<template>
<view class='new_czbk'>
<view class="t">
<text class="left-font">超值爆款</text>
<view class="sub">美好生活由此开始</view>
</view>
<view class="new-list">
<view class="item" v-for="(item , index) in 4" :key="index">
<view class="nei">
<view class="l">
<view class="t">今日推荐</view>
<view class="c">店主诚意推荐品质商品</view>
<view class="b">
GO!
<image
src="https://zysc.fjptzykj.com:3000/shangcheng/0790eb9a90d70762e7663d2bf3d04d7427947b535dda1e98712e08d1628b52a0.png"
class="img" />
</view>
</view>
<view class="r">
<image
src="https://zysc.fjptzykj.com:3000/shangcheng/034b7091b1194d9c2853d7c17a0c1e59f0c6cdfebfcf8f7a732002e2784ead35.png"
class="img"></image>
</view>
</view>
</view>
<view style="clear:both;"></view>
</view>
</view>
</template>
<script setup>
import {
reactive,
computed
} from 'vue';
import sheep from '@/sheep';
import {
showMenuTools,
closeMenuTools
} from '@/sheep/hooks/useModal';
const show = computed(() => sheep.$store('modal').menu);
function onClick(item) {
closeMenuTools();
if (item.url) sheep.$router.go(item.url);
}
const list = [{
url: '/pages/index/index',
icon: 'https://zysc.fjptzykj.com:3000/shangcheng/f4e03230b5cb9b2bf789b67df43125af1b3cef9c2abf4d8bca8f6fa5ded16a20.png',
title: '首页',
},
{
url: '/pages/index/search',
icon: 'https://zysc.fjptzykj.com:3000/shangcheng/96a288f2a0043c8defaa37e922828b3092ba785e1c191bf18f20dbd462261f7a.png',
title: '搜索',
},
{
url: '/pages/index/user',
icon: 'https://zysc.fjptzykj.com:3000/shangcheng/227699332b8ae736e220852e60215072eb2805478dab4909e085f89aeb3604cf.png',
title: '个人中心',
},
{
url: '/pages/index/cart',
icon: 'https://zysc.fjptzykj.com:3000/shangcheng/a45981116198a65db5f28ffd070f0078cfa66ac932a0136bf45ba7e8f401a1d0.png',
title: '购物车',
},
{
url: '/pages/user/goods-log',
icon: 'https://zysc.fjptzykj.com:3000/shangcheng/7e5ecfb841f2d89b778e1070ef867c17ccda48a5fea14a149f8eb1ce6aa26a87.png',
title: '浏览记录',
},
{
url: '/pages/user/goods-collect',
icon: 'https://zysc.fjptzykj.com:3000/shangcheng/9f83f4dc3cbf8b1e8e747f8dd79a260feaf65fa9ef3f2e2224015779f85119a1.png',
title: '我的收藏',
},
{
url: '/pages/chat/index',
icon: 'https://zysc.fjptzykj.com:3000/shangcheng/739f3165045b1552b71176297dab45eda2e192b976e25b1a458a8781a61b7557.png',
title: '客服',
},
];
</script>
<style lang="scss" scoped>
.new_czbk {
width: 92%;
background: rgba(255, 229, 227);
border-radius: 20px;
margin: 0 auto;
padding: 20px 10px;
margin-top: 10px;
.t {
display: flex;
align-items: center;
.left-font {
color: rgba(252, 60, 62);
font-size: 22px;
font-weight: 700;
}
.sub {
background: rgba(248, 79, 43);
color: white;
border-radius: 20px 0px 20px 0px;
padding: 0 13px;
margin-left: 10px;
}
}
.new-list {
width: 100%;
margin-top: 20px;
.item {
float: left;
width: 47.5%;
padding: 5px;
.nei {
background: white;
border-radius: 10px;
padding: 15px 10px;
display: flex;
.l {
width: 51%;
.t {}
.c {
color: rgba(153, 153, 153);
font-size: 13px;
margin: 10px 0;
}
.b {
display: flex;
align-items: center;
justify-content: space-around;
background: #329cff;
margin: 0 3px;
border-radius: 15px;
color: white;
font-weight: 700;
padding: 0px 9px;
font-style: oblique;
.img {
width: 20px;
height: 20px;
}
}
}
.r {
width: 49%;
.img {
width: 100%;
height: 100%;
}
}
}
}
}
}
@media (max-width: 435px) {
.new_czbk {
.new-list {
.item {
width: 47%;
}
}
}
}
@media (max-width: 379px) {
.new_czbk {
.new-list {
.item {
width: 46%;
}
}
}
}
</style>