forked from zhongyuanhaiju/uniapp
秒杀商品详情页面完成
This commit is contained in:
parent
0ddf87dd7f
commit
2cf76eb3e7
|
|
@ -0,0 +1,128 @@
|
||||||
|
// const defaultOption = {
|
||||||
|
// duration: 300,
|
||||||
|
// timingFunction: 'linear',
|
||||||
|
// delay: 0,
|
||||||
|
// transformOrigin: '50% 50% 0'
|
||||||
|
// }
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
const nvueAnimation = uni.requireNativePlugin('animation')
|
||||||
|
// #endif
|
||||||
|
class MPAnimation {
|
||||||
|
constructor(options, _this) {
|
||||||
|
this.options = options
|
||||||
|
this.animation = uni.createAnimation(options)
|
||||||
|
this.currentStepAnimates = {}
|
||||||
|
this.next = 0
|
||||||
|
this.$ = _this
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_nvuePushAnimates(type, args) {
|
||||||
|
let aniObj = this.currentStepAnimates[this.next]
|
||||||
|
let styles = {}
|
||||||
|
if (!aniObj) {
|
||||||
|
styles = {
|
||||||
|
styles: {},
|
||||||
|
config: {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
styles = aniObj
|
||||||
|
}
|
||||||
|
if (animateTypes1.includes(type)) {
|
||||||
|
if (!styles.styles.transform) {
|
||||||
|
styles.styles.transform = ''
|
||||||
|
}
|
||||||
|
let unit = ''
|
||||||
|
if(type === 'rotate'){
|
||||||
|
unit = 'deg'
|
||||||
|
}
|
||||||
|
styles.styles.transform += `${type}(${args+unit}) `
|
||||||
|
} else {
|
||||||
|
styles.styles[type] = `${args}`
|
||||||
|
}
|
||||||
|
this.currentStepAnimates[this.next] = styles
|
||||||
|
}
|
||||||
|
_animateRun(styles = {}, config = {}) {
|
||||||
|
let ref = this.$.$refs['ani'].ref
|
||||||
|
if (!ref) return
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
nvueAnimation.transition(ref, {
|
||||||
|
styles,
|
||||||
|
...config
|
||||||
|
}, res => {
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_nvueNextAnimate(animates, step = 0, fn) {
|
||||||
|
let obj = animates[step]
|
||||||
|
if (obj) {
|
||||||
|
let {
|
||||||
|
styles,
|
||||||
|
config
|
||||||
|
} = obj
|
||||||
|
this._animateRun(styles, config).then(() => {
|
||||||
|
step += 1
|
||||||
|
this._nvueNextAnimate(animates, step, fn)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.currentStepAnimates = {}
|
||||||
|
typeof fn === 'function' && fn()
|
||||||
|
this.isEnd = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
step(config = {}) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.animation.step(config)
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
|
||||||
|
this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
|
||||||
|
this.next++
|
||||||
|
// #endif
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
run(fn) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.$.animationData = this.animation.export()
|
||||||
|
this.$.timer = setTimeout(() => {
|
||||||
|
typeof fn === 'function' && fn()
|
||||||
|
}, this.$.durationTime)
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.isEnd = false
|
||||||
|
let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
|
||||||
|
if(!ref) return
|
||||||
|
this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
|
||||||
|
this.next = 0
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
|
||||||
|
'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
|
||||||
|
'translateZ'
|
||||||
|
]
|
||||||
|
const animateTypes2 = ['opacity', 'backgroundColor']
|
||||||
|
const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
|
||||||
|
animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
|
||||||
|
MPAnimation.prototype[type] = function(...args) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.animation[type](...args)
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this._nvuePushAnimates(type, args)
|
||||||
|
// #endif
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export function createAnimation(option, _this) {
|
||||||
|
if(!_this) return
|
||||||
|
clearTimeout(_this.timer)
|
||||||
|
return new MPAnimation(option, _this)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,277 @@
|
||||||
|
<template>
|
||||||
|
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { createAnimation } from './createAnimation'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition 过渡动画
|
||||||
|
* @description 简单过渡动画组件
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
|
||||||
|
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
|
||||||
|
* @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
|
||||||
|
* @value fade 渐隐渐出过渡
|
||||||
|
* @value slide-top 由上至下过渡
|
||||||
|
* @value slide-right 由右至左过渡
|
||||||
|
* @value slide-bottom 由下至上过渡
|
||||||
|
* @value slide-left 由左至右过渡
|
||||||
|
* @value zoom-in 由小到大过渡
|
||||||
|
* @value zoom-out 由大到小过渡
|
||||||
|
* @property {Number} duration 过渡动画持续时间
|
||||||
|
* @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'uniTransition',
|
||||||
|
emits:['click','change'],
|
||||||
|
props: {
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
modeClass: {
|
||||||
|
type: [Array, String],
|
||||||
|
default() {
|
||||||
|
return 'fade'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
type: Number,
|
||||||
|
default: 300
|
||||||
|
},
|
||||||
|
styles: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
customClass:{
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isShow: false,
|
||||||
|
transform: '',
|
||||||
|
opacity: 1,
|
||||||
|
animationData: {},
|
||||||
|
durationTime: 300,
|
||||||
|
config: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
show: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.open()
|
||||||
|
} else {
|
||||||
|
// 避免上来就执行 close,导致动画错乱
|
||||||
|
if (this.isShow) {
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 生成样式数据
|
||||||
|
stylesObject() {
|
||||||
|
let styles = {
|
||||||
|
...this.styles,
|
||||||
|
'transition-duration': this.duration / 1000 + 's'
|
||||||
|
}
|
||||||
|
let transform = ''
|
||||||
|
for (let i in styles) {
|
||||||
|
let line = this.toLine(i)
|
||||||
|
transform += line + ':' + styles[i] + ';'
|
||||||
|
}
|
||||||
|
return transform
|
||||||
|
},
|
||||||
|
// 初始化动画条件
|
||||||
|
transformStyles() {
|
||||||
|
return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 动画默认配置
|
||||||
|
this.config = {
|
||||||
|
duration: this.duration,
|
||||||
|
timingFunction: 'ease',
|
||||||
|
transformOrigin: '50% 50%',
|
||||||
|
delay: 0
|
||||||
|
}
|
||||||
|
this.durationTime = this.duration
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* ref 触发 初始化动画
|
||||||
|
*/
|
||||||
|
init(obj = {}) {
|
||||||
|
if (obj.duration) {
|
||||||
|
this.durationTime = obj.duration
|
||||||
|
}
|
||||||
|
this.animation = createAnimation(Object.assign(this.config, obj),this)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 点击组件触发回调
|
||||||
|
*/
|
||||||
|
onClick() {
|
||||||
|
this.$emit('click', {
|
||||||
|
detail: this.isShow
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* ref 触发 动画分组
|
||||||
|
* @param {Object} obj
|
||||||
|
*/
|
||||||
|
step(obj, config = {}) {
|
||||||
|
if (!this.animation) return
|
||||||
|
for (let i in obj) {
|
||||||
|
try {
|
||||||
|
if(typeof obj[i] === 'object'){
|
||||||
|
this.animation[i](...obj[i])
|
||||||
|
}else{
|
||||||
|
this.animation[i](obj[i])
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`方法 ${i} 不存在`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.animation.step(config)
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* ref 触发 执行动画
|
||||||
|
*/
|
||||||
|
run(fn) {
|
||||||
|
if (!this.animation) return
|
||||||
|
this.animation.run(fn)
|
||||||
|
},
|
||||||
|
// 开始过度动画
|
||||||
|
open() {
|
||||||
|
clearTimeout(this.timer)
|
||||||
|
this.transform = ''
|
||||||
|
this.isShow = true
|
||||||
|
let { opacity, transform } = this.styleInit(false)
|
||||||
|
if (typeof opacity !== 'undefined') {
|
||||||
|
this.opacity = opacity
|
||||||
|
}
|
||||||
|
this.transform = transform
|
||||||
|
// 确保动态样式已经生效后,执行动画,如果不加 nextTick ,会导致 wx 动画执行异常
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// TODO 定时器保证动画完全执行,目前有些问题,后面会取消定时器
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
|
this.animation = createAnimation(this.config, this)
|
||||||
|
this.tranfromInit(false).step()
|
||||||
|
this.animation.run()
|
||||||
|
this.$emit('change', {
|
||||||
|
detail: this.isShow
|
||||||
|
})
|
||||||
|
}, 20)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 关闭过度动画
|
||||||
|
close(type) {
|
||||||
|
if (!this.animation) return
|
||||||
|
this.tranfromInit(true)
|
||||||
|
.step()
|
||||||
|
.run(() => {
|
||||||
|
this.isShow = false
|
||||||
|
this.animationData = null
|
||||||
|
this.animation = null
|
||||||
|
let { opacity, transform } = this.styleInit(false)
|
||||||
|
this.opacity = opacity || 1
|
||||||
|
this.transform = transform
|
||||||
|
this.$emit('change', {
|
||||||
|
detail: this.isShow
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 处理动画开始前的默认样式
|
||||||
|
styleInit(type) {
|
||||||
|
let styles = {
|
||||||
|
transform: ''
|
||||||
|
}
|
||||||
|
let buildStyle = (type, mode) => {
|
||||||
|
if (mode === 'fade') {
|
||||||
|
styles.opacity = this.animationType(type)[mode]
|
||||||
|
} else {
|
||||||
|
styles.transform += this.animationType(type)[mode] + ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof this.modeClass === 'string') {
|
||||||
|
buildStyle(type, this.modeClass)
|
||||||
|
} else {
|
||||||
|
this.modeClass.forEach(mode => {
|
||||||
|
buildStyle(type, mode)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return styles
|
||||||
|
},
|
||||||
|
// 处理内置组合动画
|
||||||
|
tranfromInit(type) {
|
||||||
|
let buildTranfrom = (type, mode) => {
|
||||||
|
let aniNum = null
|
||||||
|
if (mode === 'fade') {
|
||||||
|
aniNum = type ? 0 : 1
|
||||||
|
} else {
|
||||||
|
aniNum = type ? '-100%' : '0'
|
||||||
|
if (mode === 'zoom-in') {
|
||||||
|
aniNum = type ? 0.8 : 1
|
||||||
|
}
|
||||||
|
if (mode === 'zoom-out') {
|
||||||
|
aniNum = type ? 1.2 : 1
|
||||||
|
}
|
||||||
|
if (mode === 'slide-right') {
|
||||||
|
aniNum = type ? '100%' : '0'
|
||||||
|
}
|
||||||
|
if (mode === 'slide-bottom') {
|
||||||
|
aniNum = type ? '100%' : '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.animation[this.animationMode()[mode]](aniNum)
|
||||||
|
}
|
||||||
|
if (typeof this.modeClass === 'string') {
|
||||||
|
buildTranfrom(type, this.modeClass)
|
||||||
|
} else {
|
||||||
|
this.modeClass.forEach(mode => {
|
||||||
|
buildTranfrom(type, mode)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.animation
|
||||||
|
},
|
||||||
|
animationType(type) {
|
||||||
|
return {
|
||||||
|
fade: type ? 1 : 0,
|
||||||
|
'slide-top': `translateY(${type ? '0' : '-100%'})`,
|
||||||
|
'slide-right': `translateX(${type ? '0' : '100%'})`,
|
||||||
|
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
|
||||||
|
'slide-left': `translateX(${type ? '0' : '-100%'})`,
|
||||||
|
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
|
||||||
|
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 内置动画类型与实际动画对应字典
|
||||||
|
animationMode() {
|
||||||
|
return {
|
||||||
|
fade: 'opacity',
|
||||||
|
'slide-top': 'translateY',
|
||||||
|
'slide-right': 'translateX',
|
||||||
|
'slide-bottom': 'translateY',
|
||||||
|
'slide-left': 'translateX',
|
||||||
|
'zoom-in': 'scale',
|
||||||
|
'zoom-out': 'scale'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 驼峰转中横线
|
||||||
|
toLine(name) {
|
||||||
|
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
||||||
19
pages.json
19
pages.json
|
|
@ -1003,6 +1003,24 @@
|
||||||
// #endif
|
// #endif
|
||||||
"navigationBarTitleText": "限时秒杀"
|
"navigationBarTitleText": "限时秒杀"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "futures/details",
|
||||||
|
"style": {
|
||||||
|
// #ifdef H5
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
// #endif
|
||||||
|
"navigationBarTitleText": "商品详情"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "futures/my_shop",
|
||||||
|
"style": {
|
||||||
|
// #ifdef H5
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
// #endif
|
||||||
|
"navigationBarTitleText": "我的小店"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1010,7 +1028,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,334 @@
|
||||||
|
<template>
|
||||||
|
<page-meta :page-style="themeColor"></page-meta>
|
||||||
|
<view class="details">
|
||||||
|
<!--顶部内容-->
|
||||||
|
<view class="top">
|
||||||
|
<image class="top-image" :src="$util.img('upload/1/common/images/20230216/20230216050332167653821225076.png')" mode="widthFix"></image>
|
||||||
|
<view class="top-count-down">
|
||||||
|
<image class="top-down-image" :src="$util.img('public/static/img/futures/details_down_bg.png')" mode="widthFix"></image>
|
||||||
|
<view class="top-down-text">
|
||||||
|
<image class="top-down-text-image" :src="$util.img('public/static/img/futures/details_down_icon.png')" mode="widthFix"></image>
|
||||||
|
正在销售
|
||||||
|
</view>
|
||||||
|
<view class="top-count-down-time">
|
||||||
|
<text class="count-down-time">{{ h }}</text>:
|
||||||
|
<text class="count-down-time">{{ i }}</text>:
|
||||||
|
<text class="count-down-time">{{ s }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!--参数信息-->
|
||||||
|
<view class="params-info">
|
||||||
|
<view class="title">脑黄金为智慧加分 澳大利亚进口保健品 适合中老年人长期熬夜人群使用</view>
|
||||||
|
<view class="info-item">
|
||||||
|
售卖价格:<text class="info-num"><text class="unit">¥</text>1200/件</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
采购价格:<text class="buy-price"><text class="unit">¥</text>600.34</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item">
|
||||||
|
<view class="info-block">
|
||||||
|
采购数量:<text class="info-num">12件</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-block">
|
||||||
|
销售商:<text class="info-num">一颗柚子</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!--商品详情富文本-->
|
||||||
|
<view class="goods-detail">
|
||||||
|
<view class="detail-top">
|
||||||
|
<view class="left">采购商品详情</view>
|
||||||
|
<view class="right" @click="details_show = !details_show">
|
||||||
|
展开
|
||||||
|
<i v-if="details_show" class="icondiy icon-system-jiantoushang"></i>
|
||||||
|
<i v-else class="icondiy icon-system-jiantouxia"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="goods-detail-content">
|
||||||
|
<uni-transition
|
||||||
|
id="goodsDetailContent"
|
||||||
|
ref="detail"
|
||||||
|
:show="details_show"
|
||||||
|
mode-class="slide-top"
|
||||||
|
:duration="2000"
|
||||||
|
>
|
||||||
|
这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />
|
||||||
|
这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />
|
||||||
|
这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />
|
||||||
|
这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />
|
||||||
|
这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />
|
||||||
|
这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />
|
||||||
|
这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />
|
||||||
|
这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />
|
||||||
|
这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />这里是富文本的监听内容<br />
|
||||||
|
</uni-transition>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!--按钮-->
|
||||||
|
<view class="bottom-buttons">
|
||||||
|
<view class="button-item">添加备注</view>
|
||||||
|
<view class="button-item">立即采购</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<!--加载动画-->
|
||||||
|
<loading-cover ref="loadingCover"></loading-cover>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import uniTransition from '@/components/uni-transition/uni-transition.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 倒计时
|
||||||
|
end_time: 1680170346,// 结束时间 时间戳
|
||||||
|
diff_time: 0,
|
||||||
|
h: '00',
|
||||||
|
i: '00',
|
||||||
|
s: '00',
|
||||||
|
interval: '',
|
||||||
|
// 商品详情是否显示
|
||||||
|
details_show: false,
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
uniTransition
|
||||||
|
},
|
||||||
|
mixins: [],
|
||||||
|
onLoad(option) {},
|
||||||
|
onShow() {},
|
||||||
|
onReady(){
|
||||||
|
// 判断是否登录
|
||||||
|
if (!uni.getStorageSync('token')) this.$refs.login.open('/pages_promotion/futures/seckill');
|
||||||
|
// 开启倒计时
|
||||||
|
this.countDown();
|
||||||
|
|
||||||
|
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 倒计时
|
||||||
|
countDown(){
|
||||||
|
this.interval = setInterval(() => {
|
||||||
|
// 获取距离结束时间的毫秒数
|
||||||
|
let nowTime = Math.ceil((new Date()).getTime() / 1000);
|
||||||
|
this.diff_time = this.end_time - nowTime;
|
||||||
|
// 计算时间
|
||||||
|
let result = this.$util.countDown(this.diff_time);
|
||||||
|
this.h = (parseInt(result.d) * 24) + parseInt(result.h);
|
||||||
|
this.i = parseInt(result.i);
|
||||||
|
this.s = parseInt(result.s);
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
onBackPress(options) {
|
||||||
|
if (options.from === 'navigateBack') return false;
|
||||||
|
this.$util.redirectTo('/pages/member/index');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.details{
|
||||||
|
background: #f5f5f5;// #f5f5f5
|
||||||
|
min-height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
.top{
|
||||||
|
height: 100vw;
|
||||||
|
position: relative;
|
||||||
|
.top-image{
|
||||||
|
width: 100vw;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
.top-count-down{
|
||||||
|
--count-down-size--: 96rpx;
|
||||||
|
--top-count-down-time-width--: 230rpx;
|
||||||
|
height: var(--count-down-size--);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
.top-down-image{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.top-down-text{
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: var(--top-count-down-time-width--);
|
||||||
|
height: var(--count-down-size--);
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-right: 55rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fe6276;
|
||||||
|
.top-down-text-image{
|
||||||
|
width: 36rpx!important;
|
||||||
|
margin-right: 15rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.top-count-down-time{
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
height: var(--count-down-size--);
|
||||||
|
width: var(--top-count-down-time-width--);
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.count-down-time{
|
||||||
|
--size--: 50rpx;
|
||||||
|
background: #313131;
|
||||||
|
color: #c6c7ca;
|
||||||
|
min-width: calc(var(--size--) - 20rpx);
|
||||||
|
height: var(--size--);
|
||||||
|
border-radius: 10rpx;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0 6rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
padding: 0 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.params-info{
|
||||||
|
padding: 20rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
.title{
|
||||||
|
width: 100%;
|
||||||
|
height: 60rpx;
|
||||||
|
line-height: 50rpx;
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.info-item{
|
||||||
|
height: 50rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #747474;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 100%;
|
||||||
|
.unit{
|
||||||
|
font-size: 24rpx;
|
||||||
|
display: inline-block;
|
||||||
|
width: 22rpx;
|
||||||
|
}
|
||||||
|
.info-num{
|
||||||
|
font-weight: bold;
|
||||||
|
color: #040404;
|
||||||
|
}
|
||||||
|
.buy-price{
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fe5572;
|
||||||
|
}
|
||||||
|
.info-block{
|
||||||
|
width: 50%;
|
||||||
|
float: left;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #747474;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.goods-detail{
|
||||||
|
background: #fcfcfc;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
|
||||||
|
.detail-top{
|
||||||
|
width: 100%;
|
||||||
|
height: 70rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
.left{
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #3e3e3e;
|
||||||
|
}
|
||||||
|
.right{
|
||||||
|
font-size: 13px;
|
||||||
|
color: #838383;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
height: 70rpx;
|
||||||
|
i{
|
||||||
|
margin-left: 20rpx;
|
||||||
|
color: #838383;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.goods-detail-content{
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bottom-buttons{
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
height: 100rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
.button-item{
|
||||||
|
height: 80rpx;
|
||||||
|
line-height: 80rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
width: 240rpx;
|
||||||
|
border-radius: 100vw;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.button-item:nth-of-type(1){
|
||||||
|
background: #FFFFFF;
|
||||||
|
border: 2rpx solid #dfdfdf;
|
||||||
|
color: #838383;
|
||||||
|
}
|
||||||
|
.button-item:nth-of-type(2){
|
||||||
|
background: #ff4546;
|
||||||
|
color: #fee6e6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
<template>
|
||||||
|
<page-meta :page-style="themeColor"></page-meta>
|
||||||
|
<view class="apply">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--加载动画-->
|
||||||
|
<loading-cover ref="loadingCover"></loading-cover>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {},
|
||||||
|
mixins: [],
|
||||||
|
onLoad(option) {
|
||||||
|
|
||||||
|
},
|
||||||
|
async onShow() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
onBackPress(options) {
|
||||||
|
if (options.from === 'navigateBack') return false;
|
||||||
|
this.$util.redirectTo('/pages/member/index');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
<view class="price-item">采购价:<text class="purchase_price">¥1199.99</text></view>
|
<view class="price-item">采购价:<text class="purchase_price">¥1199.99</text></view>
|
||||||
</view>
|
</view>
|
||||||
<view class="buy-button">
|
<view class="buy-button">
|
||||||
<view class="buy-btn">前去采购</view>
|
<view class="buy-btn" @click="$util.redirectTo('/pages_promotion/futures/details', { id: item.id }, 'redirectTo');">前去采购</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -58,9 +58,9 @@ export default {
|
||||||
// 倒计时
|
// 倒计时
|
||||||
end_time: 1680170346,// 结束时间 时间戳
|
end_time: 1680170346,// 结束时间 时间戳
|
||||||
diff_time: 0,
|
diff_time: 0,
|
||||||
h: 0,
|
h: '00',
|
||||||
i: 0,
|
i: '00',
|
||||||
s: 0,
|
s: '00',
|
||||||
interval: '',
|
interval: '',
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -119,10 +119,6 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
onBackPress(options) {
|
onBackPress(options) {
|
||||||
if (options.from === 'navigateBack') return false;
|
if (options.from === 'navigateBack') return false;
|
||||||
|
|
@ -162,7 +158,7 @@ export default {
|
||||||
--size--: 45rpx;
|
--size--: 45rpx;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
color: #fe7671;
|
color: #fe7671;
|
||||||
max-width: var(--size--);
|
min-width: calc(var(--size--) - 20rpx);
|
||||||
height: var(--size--);
|
height: var(--size--);
|
||||||
border-radius: 10rpx;
|
border-radius: 10rpx;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue