17 changed files with 1031 additions and 51 deletions
-
2colorui/main.css
-
BINcomponents/amount/DINPro-Medium.ttf
-
220components/amount/_util/animate.js
-
22components/amount/_util/dom.js
-
18components/amount/_util/env.js
-
76components/amount/_util/formate-value.js
-
2components/amount/_util/index.js
-
139components/amount/index.vue
-
110components/amount/number-capital.js
-
24components/me-tabs/me-tabs.vue
-
52components/my-uni-modal-bottom/my-uni-modal-bottom.vue
-
70components/my-uni-modal/my-uni-modal.vue
-
6main.js
-
6pages.json
-
105pages/order/index.vue
-
162pages/order/order-item.vue
-
68project.config.json
@ -0,0 +1,220 @@ |
|||
import {root} from './env' |
|||
|
|||
/* istanbul ignore file */ |
|||
const Animate = (global => { |
|||
/* istanbul ignore next */ |
|||
const time = |
|||
Date.now || |
|||
(() => { |
|||
return +new Date() |
|||
}) |
|||
const desiredFrames = 60 |
|||
const millisecondsPerSecond = 1000 |
|||
|
|||
let running = {} |
|||
let counter = 1 |
|||
|
|||
return { |
|||
/** |
|||
* A requestAnimationFrame wrapper / polyfill. |
|||
* |
|||
* @param callback {Function} The callback to be invoked before the next repaint. |
|||
* @param root {HTMLElement} The root element for the repaint |
|||
*/ |
|||
requestAnimationFrame: (() => { |
|||
// Check for request animation Frame support
|
|||
const requestFrame = |
|||
global.requestAnimationFrame || |
|||
global.webkitRequestAnimationFrame || |
|||
global.mozRequestAnimationFrame || |
|||
global.oRequestAnimationFrame |
|||
let isNative = !!requestFrame |
|||
|
|||
if (requestFrame && !/requestAnimationFrame\(\)\s*\{\s*\[native code\]\s*\}/i.test(requestFrame.toString())) { |
|||
isNative = false |
|||
} |
|||
|
|||
if (isNative) { |
|||
return (callback, root) => { |
|||
requestFrame(callback, root) |
|||
} |
|||
} |
|||
|
|||
const TARGET_FPS = 60 |
|||
let requests = {} |
|||
let requestCount = 0 |
|||
let rafHandle = 1 |
|||
let intervalHandle = null |
|||
let lastActive = +new Date() |
|||
|
|||
return callback => { |
|||
const callbackHandle = rafHandle++ |
|||
|
|||
// Store callback
|
|||
requests[callbackHandle] = callback |
|||
requestCount++ |
|||
|
|||
// Create timeout at first request
|
|||
if (intervalHandle === null) { |
|||
intervalHandle = setInterval(() => { |
|||
const time = +new Date() |
|||
const currentRequests = requests |
|||
|
|||
// Reset data structure before executing callbacks
|
|||
requests = {} |
|||
requestCount = 0 |
|||
|
|||
for (const key in currentRequests) { |
|||
if (currentRequests.hasOwnProperty(key)) { |
|||
currentRequests[key](time) |
|||
lastActive = time |
|||
} |
|||
} |
|||
|
|||
// Disable the timeout when nothing happens for a certain
|
|||
// period of time
|
|||
if (time - lastActive > 2500) { |
|||
clearInterval(intervalHandle) |
|||
intervalHandle = null |
|||
} |
|||
}, 1000 / TARGET_FPS) |
|||
} |
|||
|
|||
return callbackHandle |
|||
} |
|||
})(), |
|||
|
|||
/** |
|||
* Stops the given animation. |
|||
* |
|||
* @param id {Integer} Unique animation ID |
|||
* @return {Boolean} Whether the animation was stopped (aka, was running before) |
|||
*/ |
|||
stop(id) { |
|||
const cleared = running[id] != null |
|||
cleared && (running[id] = null) |
|||
return cleared |
|||
}, |
|||
|
|||
/** |
|||
* Whether the given animation is still running. |
|||
* |
|||
* @param id {Integer} Unique animation ID |
|||
* @return {Boolean} Whether the animation is still running |
|||
*/ |
|||
isRunning(id) { |
|||
return running[id] != null |
|||
}, |
|||
|
|||
/** |
|||
* Start the animation. |
|||
* |
|||
* @param stepCallback {Function} Pointer to function which is executed on every step. |
|||
* Signature of the method should be `function(percent, now, virtual) { return continueWithAnimation; }` |
|||
* @param verifyCallback {Function} Executed before every animation step. |
|||
* Signature of the method should be `function() { return continueWithAnimation; }` |
|||
* @param completedCallback {Function} |
|||
* Signature of the method should be `function(droppedFrames, finishedAnimation) {}` |
|||
* @param duration {Integer} Milliseconds to run the animation |
|||
* @param easingMethod {Function} Pointer to easing function |
|||
* Signature of the method should be `function(percent) { return modifiedValue; }` |
|||
* @param root {Element ? document.body} Render root, when available. Used for internal |
|||
* usage of requestAnimationFrame. |
|||
* @return {Integer} Identifier of animation. Can be used to stop it any time. |
|||
*/ |
|||
start(stepCallback, verifyCallback, completedCallback, duration, easingMethod, root) { |
|||
const start = time() |
|||
let lastFrame = start |
|||
let percent = 0 |
|||
let dropCounter = 0 |
|||
const id = counter++ |
|||
|
|||
if (!root) { |
|||
// root = document.body
|
|||
} |
|||
|
|||
// Compacting running db automatically every few new animations
|
|||
if (id % 20 === 0) { |
|||
const newRunning = {} |
|||
for (const usedId in running) { |
|||
newRunning[usedId] = true |
|||
} |
|||
running = newRunning |
|||
} |
|||
|
|||
// This is the internal step method which is called every few milliseconds
|
|||
const step = virtual => { |
|||
// Normalize virtual value
|
|||
const render = virtual !== true |
|||
|
|||
// Get current time
|
|||
const now = time() |
|||
|
|||
// Verification is executed before next animation step
|
|||
if (!running[id] || (verifyCallback && !verifyCallback(id))) { |
|||
running[id] = null |
|||
completedCallback && |
|||
completedCallback(desiredFrames - dropCounter / ((now - start) / millisecondsPerSecond), id, false) |
|||
return |
|||
} |
|||
|
|||
// For the current rendering to apply let's update omitted steps in memory.
|
|||
// This is important to bring internal state variables up-to-date with progress in time.
|
|||
if (render) { |
|||
const droppedFrames = Math.round((now - lastFrame) / (millisecondsPerSecond / desiredFrames)) - 1 |
|||
for (let j = 0; j < Math.min(droppedFrames, 4); j++) { |
|||
step(true) |
|||
dropCounter++ |
|||
} |
|||
} |
|||
|
|||
// Compute percent value
|
|||
if (duration) { |
|||
percent = (now - start) / duration |
|||
if (percent > 1) { |
|||
percent = 1 |
|||
} |
|||
} |
|||
|
|||
// Execute step callback, then...
|
|||
let value = easingMethod ? easingMethod(percent) : percent |
|||
value = isNaN(value) ? 0 : value |
|||
if ((stepCallback(value, now, render) === false || percent === 1) && render) { |
|||
running[id] = null |
|||
completedCallback && |
|||
completedCallback( |
|||
desiredFrames - dropCounter / ((now - start) / millisecondsPerSecond), |
|||
id, |
|||
percent === 1 || duration == null, |
|||
) |
|||
} else if (render) { |
|||
lastFrame = now |
|||
this.requestAnimationFrame(step, root) |
|||
} |
|||
} |
|||
|
|||
// Mark as running
|
|||
running[id] = true |
|||
|
|||
// Init first step
|
|||
this.requestAnimationFrame(step, root) |
|||
|
|||
// Return unique animation ID
|
|||
return id |
|||
}, |
|||
} |
|||
})(root) |
|||
|
|||
export const easeOutCubic = pos => { |
|||
return Math.pow(pos - 1, 3) + 1 |
|||
} |
|||
|
|||
export const easeInOutCubic = pos => { |
|||
if ((pos /= 0.5) < 1) { |
|||
return 0.5 * Math.pow(pos, 3) |
|||
} |
|||
|
|||
return 0.5 * (Math.pow(pos - 2, 3) + 2) |
|||
} |
|||
|
|||
export default Animate |
|||
@ -0,0 +1,22 @@ |
|||
import {inBrowser} from './env' |
|||
|
|||
class Dom { |
|||
appendChild() {} |
|||
removeChild() {} |
|||
querySelector() {} |
|||
addEventListener() {} |
|||
removeEventListener() {} |
|||
} |
|||
|
|||
const dom = new Dom() |
|||
let mdDocument = dom |
|||
let mdBody = dom |
|||
|
|||
mdDocument.body = mdBody |
|||
|
|||
if (inBrowser) { |
|||
// mdDocument = window.document
|
|||
// mdBody = document.body
|
|||
} |
|||
|
|||
export {mdDocument, mdBody, dom} |
|||
@ -0,0 +1,18 @@ |
|||
import Vue from 'vue' |
|||
|
|||
// Development environment
|
|||
export const isProd = process.env.NODE_ENV === 'production' |
|||
|
|||
// Browser environment sniffing
|
|||
export const inBrowser = !Vue.prototype.$isServer |
|||
export const UA = inBrowser |
|||
export const isAndroid = UA |
|||
export const isIOS = UA |
|||
export const root = typeof window !== 'undefined' ? window : global |
|||
|
|||
|
|||
// export const inBrowser = !Vue.prototype.$isServer || typeof window !== 'undefined'
|
|||
// export const UA = inBrowser && window.navigator.userAgent.toLowerCase()
|
|||
// export const isAndroid = UA && UA.indexOf('android') > 0
|
|||
// export const isIOS = UA && /iphone|ipad|ipod|ios/.test(UA)
|
|||
// export const root = typeof window !== 'undefined' ? window : global
|
|||
@ -0,0 +1,76 @@ |
|||
export function formatValueByGapRule(gapRule, value, gap = ' ', range, isAdd = 1) { |
|||
const arr = value ? value.split('') : [] |
|||
let showValue = '' |
|||
const rule = [] |
|||
gapRule.split('|').some((n, j) => { |
|||
rule[j] = +n + (rule[j - 1] ? +rule[j - 1] : 0) |
|||
}) |
|||
let j = 0 |
|||
arr.some((n, i) => { |
|||
// Remove the excess part
|
|||
if (i > rule[rule.length - 1] - 1) { |
|||
return |
|||
} |
|||
if (i > 0 && i === rule[j]) { |
|||
showValue = showValue + gap + n |
|||
j++ |
|||
} else { |
|||
showValue = showValue + '' + n |
|||
} |
|||
}) |
|||
let adapt = 0 |
|||
rule.some((n, j) => { |
|||
if (range === +n + 1 + j) { |
|||
adapt = 1 * isAdd |
|||
} |
|||
}) |
|||
range = typeof range !== 'undefined' ? (range === 0 ? 0 : range + adapt) : showValue.length |
|||
return {value: showValue, range: range} |
|||
} |
|||
|
|||
export function formatValueByGapStep(step, value, gap = ' ', direction = 'right', range, isAdd = 1, oldValue = '') { |
|||
if (value.length === 0) { |
|||
return {value, range} |
|||
} |
|||
|
|||
const arr = value && value.split('') |
|||
let _range = range |
|||
let showValue = '' |
|||
|
|||
if (direction === 'right') { |
|||
for (let j = arr.length - 1, k = 0; j >= 0; j--, k++) { |
|||
const m = arr[j] |
|||
showValue = k > 0 && k % step === 0 ? m + gap + showValue : m + '' + showValue |
|||
} |
|||
if (isAdd === 1) { |
|||
// 在添加的情况下,如果添加前字符串的长度减去新的字符串的长度为2,说明多了一个间隔符,需要调整range
|
|||
if (oldValue.length - showValue.length === -2) { |
|||
_range = range + 1 |
|||
} |
|||
} else { |
|||
// 在删除情况下,如果删除前字符串的长度减去新的字符串的长度为2,说明少了一个间隔符,需要调整range
|
|||
if (oldValue.length - showValue.length === 2) { |
|||
_range = range - 1 |
|||
} |
|||
// 删除到最开始,range 保持 0
|
|||
if (_range <= 0) { |
|||
_range = 0 |
|||
} |
|||
} |
|||
} else { |
|||
arr.some((n, i) => { |
|||
showValue = i > 0 && i % step === 0 ? showValue + gap + n : showValue + '' + n |
|||
}) |
|||
const adapt = range % (step + 1) === 0 ? 1 * isAdd : 0 |
|||
_range = typeof range !== 'undefined' ? (range === 0 ? 0 : range + adapt) : showValue.length |
|||
} |
|||
|
|||
return {value: showValue, range: _range} |
|||
} |
|||
|
|||
export function trimValue(value, gap = ' ') { |
|||
value = typeof value === 'undefined' ? '' : value |
|||
const reg = new RegExp(gap, 'g') |
|||
value = value.toString().replace(reg, '') |
|||
return value |
|||
} |
|||
@ -0,0 +1,2 @@ |
|||
export * from './env' |
|||
export * from './dom' |
|||
@ -0,0 +1,139 @@ |
|||
<template> |
|||
<text class="md-amount" :class="{numerical: !isCapital}"> |
|||
<text v-if="!isCapital">{{ formatValue | doPrecision(legalPrecision, isRoundUp) | doFormat(hasSeparator, separator) }}</text> |
|||
<text v-else> {{ formatValue | doPrecision(4, isRoundUp) | doCapital }} </text> |
|||
</text> |
|||
</template> |
|||
|
|||
<script>
import {noop, inBrowser} from './_util' |
|||
import Animate from './_util/animate' |
|||
|
|||
import {formatValueByGapStep} from './_util/formate-value' |
|||
import numberCapital from './number-capital' |
|||
|
|||
export default { |
|||
name: 'md-amount', |
|||
|
|||
filters: { |
|||
doPrecision(value, precision, isRoundUp) { |
|||
const exponentialForm = Number(`${value}e${precision}`) |
|||
const rounded = isRoundUp ? Math.round(exponentialForm) : Math.floor(exponentialForm) |
|||
return Number(`${rounded}e-${precision}`).toFixed(precision) |
|||
}, |
|||
doFormat(value, hasSeparator, separator) { |
|||
if (!hasSeparator) { |
|||
return value |
|||
} |
|||
|
|||
const numberParts = value.split('.') |
|||
const integerValue = numberParts[0] |
|||
const decimalValue = numberParts[1] || '' |
|||
const formateValue = formatValueByGapStep(3, integerValue, separator, 'right', 0, 1) |
|||
return decimalValue ? `${formateValue.value}.${decimalValue}` : `${formateValue.value}` |
|||
}, |
|||
doCapital(value) { |
|||
return numberCapital(value) |
|||
}, |
|||
}, |
|||
|
|||
props: { |
|||
value: { |
|||
type: Number, |
|||
default: 0, |
|||
}, |
|||
precision: { |
|||
type: Number, |
|||
default: 2, |
|||
}, |
|||
isRoundUp: { |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
hasSeparator: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
separator: { |
|||
type: String, |
|||
default: ',', |
|||
}, |
|||
isAnimated: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
transition: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
isCapital: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
duration: { |
|||
type: Number, |
|||
default: 1000, |
|||
}, |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
formatValue: 0, |
|||
isMounted: false, |
|||
} |
|||
}, |
|||
|
|||
watch: { |
|||
value: { |
|||
handler(val, oldVal) { |
|||
/* istanbul ignore if */ |
|||
if (!inBrowser && !this.isMounted) { |
|||
this.formatValue = val |
|||
return |
|||
} |
|||
if (this.isAnimated || this.transition) { |
|||
this.$_doAnimateDisplay(oldVal, val) |
|||
} else { |
|||
this.formatValue = val |
|||
} |
|||
}, |
|||
immediate: true, |
|||
}, |
|||
}, |
|||
|
|||
computed: { |
|||
legalPrecision() { |
|||
return this.precision > 0 ? this.precision : 0 |
|||
}, |
|||
}, |
|||
|
|||
mounted() { |
|||
this.isMounted = true |
|||
}, |
|||
|
|||
methods: { |
|||
// MARK: private methods |
|||
$_doAnimateDisplay(fromValue = 0, toValue = 0) { |
|||
/* istanbul ignore next */ |
|||
const step = percent => { |
|||
if (percent === 1) { |
|||
this.formatValue = toValue |
|||
return |
|||
} |
|||
this.formatValue = fromValue + (toValue - fromValue) * percent |
|||
} |
|||
|
|||
/* istanbul ignore next */ |
|||
const verify = id => id |
|||
Animate.start(step, verify, noop, this.duration) |
|||
}, |
|||
}, |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.md-amount{ |
|||
&.numerical{ |
|||
font-family: font-family-number |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,110 @@ |
|||
const cnNums = ['\u96f6', '\u58f9', '\u8d30', '\u53c1', '\u8086', '\u4f0d', '\u9646', '\u67d2', '\u634c', '\u7396'] |
|||
|
|||
// 拾 \u62fe 佰 \u4f70 仟 \u4edf
|
|||
const cnIntRadice = ['', '\u62fe', '\u4f70', '\u4edf'] |
|||
|
|||
// 万 \u4e07 亿 \u4ebf 兆 \u5146
|
|||
const cnIntUnits = ['', '\u4e07', '\u4ebf', '兆'] |
|||
|
|||
// 角 \u89d2 分 \u5206 毫 \u6beb 厘 \u5398
|
|||
const cnDecUnits = ['\u89d2', '\u5206', '\u6beb', '\u5398'] |
|||
const cnInteger = '\u6574' // 整 \u6574
|
|||
const cnIntLast = '\u5143' // 元 \u5143
|
|||
|
|||
const cnNegative = '\u8d1f' // 负
|
|||
|
|||
// Maximum number
|
|||
const maxNum = 999999999999999.9999 |
|||
|
|||
export default function(number) { |
|||
let negative |
|||
// Integral part
|
|||
let integerNum |
|||
// Decimal part
|
|||
let decimalNum |
|||
// Capital number
|
|||
let capitalStr = '' |
|||
|
|||
let parts |
|||
|
|||
/* istanbul ignore if */ |
|||
if (number === '') { |
|||
return '' |
|||
} |
|||
|
|||
number = parseFloat(number) |
|||
|
|||
if (number < 0) { |
|||
negative = true |
|||
number = Math.abs(number) |
|||
} |
|||
|
|||
/* istanbul ignore if */ |
|||
if (number >= maxNum) { |
|||
return '' |
|||
} |
|||
|
|||
/* istanbul ignore if */ |
|||
if (number === 0) { |
|||
capitalStr = cnNums[0] + cnIntLast + cnInteger |
|||
return capitalStr |
|||
} |
|||
|
|||
// Convert to String
|
|||
number += '' |
|||
|
|||
if (number.indexOf('.') === -1) { |
|||
integerNum = number |
|||
decimalNum = '' |
|||
} else { |
|||
parts = number.split('.') |
|||
integerNum = parts[0] |
|||
decimalNum = parts[1].substr(0, 4) |
|||
} |
|||
|
|||
// Convert integer part
|
|||
if (parseInt(integerNum, 10) > 0) { |
|||
let zeroCount = 0 |
|||
for (let i = 0, IntLen = integerNum.length; i < IntLen; i++) { |
|||
const n = integerNum.substr(i, 1) |
|||
const p = IntLen - i - 1 |
|||
const q = p / 4 |
|||
const m = p % 4 |
|||
if (n === '0') { |
|||
zeroCount++ |
|||
} else { |
|||
if (zeroCount > 0) { |
|||
capitalStr += cnNums[0] |
|||
} |
|||
zeroCount = 0 |
|||
capitalStr += cnNums[parseInt(n)] + cnIntRadice[m] |
|||
} |
|||
if (m === 0 && zeroCount < 4) { |
|||
capitalStr += cnIntUnits[q] |
|||
} |
|||
} |
|||
capitalStr += cnIntLast |
|||
} |
|||
|
|||
// Convert decimal part
|
|||
if (decimalNum !== '') { |
|||
for (let i = 0, decLen = decimalNum.length; i < decLen; i++) { |
|||
const n = decimalNum.substr(i, 1) |
|||
if (n !== '0') { |
|||
capitalStr += cnNums[Number(n)] + cnDecUnits[i] |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* istanbul ignore if */ |
|||
if (capitalStr === '') { |
|||
capitalStr += cnNums[0] + cnIntLast + cnInteger |
|||
} else if (decimalNum === '') { |
|||
capitalStr += cnInteger |
|||
} |
|||
|
|||
if (negative) { |
|||
capitalStr = `${cnNegative}${capitalStr}` |
|||
} |
|||
return capitalStr |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
<template> |
|||
<!-- 底部弹窗 --> |
|||
<view class="cu-modal bottom-modal" :class="modalShow?'show':''" @tap="hideModal"> |
|||
<view class="cu-dialog"> |
|||
<view> |
|||
<view v-for="(item,index) in content" :key="index" class="solid-bottom padding-tb text-black" @tap="BtnClick(index)"> |
|||
{{item.text}} |
|||
</view> |
|||
<view style="background-color: #efefef; height: 10rpx;"></view> |
|||
<view class="text-gray padding-tb" @tap="hideModal">取消</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
content: { |
|||
type: Array, |
|||
|
|||
default: () => { |
|||
return [] |
|||
}, |
|||
}, |
|||
modalShow: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
|
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
//确认 |
|||
BtnClick(index) { |
|||
this.$emit('determine', index) |
|||
}, |
|||
//隐藏弹窗 |
|||
hideModal() { |
|||
this.$emit('hideModal') |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
|
|||
</style> |
|||
@ -0,0 +1,70 @@ |
|||
<template> |
|||
<!-- 弹窗 --> |
|||
<view class="cu-modal" :class="modalShow?'show':''"> |
|||
<view class="cu-dialog"> |
|||
<view class="cu-bar bg-white justify-end"> |
|||
<view class="content">{{title}}</view> |
|||
<view class="action" @tap="hideModal"> |
|||
<text class="cuIcon-close text-red"></text> |
|||
</view> |
|||
</view> |
|||
<view class="padding-xl text-gray"> |
|||
{{content}} |
|||
</view> |
|||
<view class="cu-bar bg-white justify-end"> |
|||
<view class="action"> |
|||
<button class="cu-btn line-gray text-orange" @tap="hideModal" v-if="isSancel">取消</button> |
|||
<button class="cu-btn bg-gradual-red margin-left text-white" @tap="BtnClick">{{btnText}}</button> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
default: '温馨提示', |
|||
}, |
|||
content: { |
|||
type: String, |
|||
default: '', |
|||
}, |
|||
btnText: { |
|||
type: String, |
|||
default: '确定', |
|||
}, |
|||
modalShow: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
//是否显示取消按钮 |
|||
isSancel: { |
|||
type: Boolean, |
|||
default: true |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
|
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
//确认 |
|||
BtnClick() { |
|||
this.$emit('determine') |
|||
}, |
|||
//隐藏弹窗 |
|||
hideModal() { |
|||
this.$emit('hideModal') |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
|
|||
</style> |
|||
@ -1,58 +1,85 @@ |
|||
<template> |
|||
<view class="content"> |
|||
<view> |
|||
|
|||
<!-- 当设置tab-width,指定每个tab宽度时,则不使用flex布局,改用水平滑动 --> |
|||
<view class="padding-lr"> |
|||
<me-tabs style="border-top: 1px solid #f7f7f7;box-sizing:content-box;border-radius: 10px;" v-model="tabIndex" :tabs="tabs" :fixed="true"></me-tabs> |
|||
</view> |
|||
<swiper :style="{height: height}" :current="tabIndex" @change="swiperChange"> |
|||
<swiper-item v-for="(tab,i) in tabs" :key="i"> |
|||
<mescroll-item :i="i" :index="tabIndex" :tabs="tabs"></mescroll-item> |
|||
</swiper-item> |
|||
</swiper> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import MescrollItem from "./order-item.vue"; |
|||
export default { |
|||
components: { |
|||
MescrollItem |
|||
}, |
|||
data() { |
|||
return { |
|||
title: 'Hello' |
|||
height: "400px", // 需要固定swiper的高度 |
|||
tabs: [{ |
|||
name: '全部', |
|||
type: 'all' |
|||
}, { |
|||
name: '待付款', |
|||
type: 'delivered' |
|||
}, { |
|||
name: '已付款', |
|||
type: 'receiving' |
|||
}, |
|||
{ |
|||
name: '已完成', |
|||
type: 'complete' |
|||
}], |
|||
tabIndex: 0, // 当前tab的下标 |
|||
assetsType: '' //账户类型 |
|||
} |
|||
}, |
|||
onLoad() { |
|||
|
|||
onLoad(e) { |
|||
this.assetsType = e.type |
|||
this.tabIndex = this.assetsType === 'all' ? 0 : this.assetsType === 'delivered' ? 1 : this.assetsType === 'receiving' ? 2 : 0 |
|||
// 需要固定swiper的高度 |
|||
this.height = (uni.getSystemInfoSync().windowHeight -30) + 'px' |
|||
}, |
|||
methods: { |
|||
|
|||
methods: { |
|||
// 轮播菜单 |
|||
swiperChange(e) { |
|||
this.tabIndex = e.detail.current |
|||
}, |
|||
//返回 |
|||
back() { |
|||
if (this.assetsType === 'all2') { |
|||
// #ifdef H5 |
|||
window.history.go(-2) |
|||
// #endif |
|||
|
|||
// #ifndef H5 |
|||
uni.navigateBack({ |
|||
delta: 2 |
|||
}); |
|||
// #endif |
|||
} else { |
|||
// #ifdef H5 |
|||
window.history.go(-1) |
|||
// #endif |
|||
|
|||
// #ifndef H5 |
|||
uni.navigateBack({ |
|||
delta: 1 |
|||
}); |
|||
// #endif |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.content { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: center; |
|||
padding: 40rpx; |
|||
} |
|||
|
|||
.logo { |
|||
height: 200rpx; |
|||
width: 200rpx; |
|||
margin-top: 100rpx; |
|||
margin-left: auto; |
|||
margin-right: auto; |
|||
margin-bottom: 50rpx; |
|||
} |
|||
<style> |
|||
|
|||
.text-area { |
|||
display: flex; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 28rpx; |
|||
color: $u-content-color; |
|||
} |
|||
|
|||
.button-demo { |
|||
margin-top: 80rpx; |
|||
} |
|||
|
|||
.link-demo { |
|||
margin-top: 80rpx; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,162 @@ |
|||
<template> |
|||
<view> |
|||
<mescroll-uni ref="mescrollRef" @init="mescrollInit" height="100%" top="0" :down="downOption" @down="downCallback" |
|||
:up="upOption" @up="upCallback"> |
|||
<!-- 数据列表 --> |
|||
<view class="padding-bottom-xl"> |
|||
|
|||
<block v-for="(item, index) in assetsFlow" :key="index"> |
|||
<view class="margin-top bg-white"> |
|||
<view class="flex justify-between align-start solid-bottom padding-tb-sm padding-lr"> |
|||
<image src="@/static/tu.png" mode="aspectFill" style="width: 150rpx; height: 150rpx;"></image> |
|||
<view class="flex-sub padding-left-sm"> |
|||
<view class="bref-box margin-top-xs"> |
|||
网红辣椒棒 魔鬼辣椒挑战全网第一辣 网红优惠季 |
|||
</view> |
|||
<text class="block margin-top-sm text-gray text-sm">网红辣椒棒 500g <text class="margin-left text-gray">x1</text></text> |
|||
|
|||
<view class="flex justify-between margin-top-sm"> |
|||
<view class="text-red text-price text-lg"> |
|||
<amount :value="Number(19.90 || 0)" :is-round-up="false" :precision="2" :duration="800" transition></amount> |
|||
</view> |
|||
<view> |
|||
<button v-if="i==1" class="cu-btn line-gray round margin-left-sm" @tap="orderClick(item,'modalShowCancel')">取消订单</button> |
|||
<button v-if="i==2" class="cu-btn line-red round margin-left-sm" @tap="$routerGo('/pages/shop/returngoods?id=1')">我要退货</button> |
|||
<button v-if="i==2" class="cu-btn line-black round margin-left-sm" @tap="orderClick(item,'modalShowConfirm')">确认收货</button> |
|||
<button v-if="i !=1 && i != 2" class="cu-btn line-orange round margin-left-sm" @tap="orderClick(item,'modalShowDel')">立即付款</button> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class="padding-lr padding-tb-sm order-bottom"> |
|||
<text class="cuIcon-fold bg-white order-ico"></text> |
|||
<view class="flex justify-between align-center"> |
|||
<view style="color: #777777;">2021-6-17 12:37:54</view> |
|||
<view class="flex align-center justify-end"> |
|||
实付: |
|||
<view class="text-price text-red text-xl"> |
|||
<amount :value="Number(19.90 || 0)" :is-round-up="false" :precision="2" :duration="800" transition></amount> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</block> |
|||
</view> |
|||
|
|||
</mescroll-uni> |
|||
|
|||
<!-- 取消订单 --> |
|||
<my-uni-modal title="取消订单" content="您确定要取消该订单吗?" btnText="取消订单" :modalShow="modalShowCancel" @determine="cancelDetermine" |
|||
@hideModal="modalShowCancel=false" /> |
|||
|
|||
<!-- 删除订单 --> |
|||
<my-uni-modal title="删除订单" content="您确定要删除该订单吗?" btnText="删除订单" :modalShow="modalShowDel" @determine="delDetermine" |
|||
@hideModal="modalShowDel=false" /> |
|||
|
|||
<!-- 确认收货 --> |
|||
<my-uni-modal title="确认收货" content="请确认您已经收到商品在点击确认收货,以免造成损失." btnText="确认收货" :modalShow="modalShowConfirm" |
|||
@determine="confirmDetermine" @hideModal="modalShowConfirm=false" /> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js"; |
|||
import MescrollMoreItemMixin from "@/components/mescroll-uni/mixins/mescroll-more-item.js"; |
|||
export default { |
|||
mixins: [MescrollMixin, MescrollMoreItemMixin], // 注意此处还需使用MescrollMoreItemMixin (必须写在MescrollMixin后面) |
|||
data() { |
|||
return { |
|||
modalShowCancel: false, //取消订单 |
|||
modalShowDel: false, //删除订单 |
|||
modalShowConfirm: false, //确认收货 |
|||
|
|||
orderItem: {}, |
|||
|
|||
downOption: { |
|||
auto: false |
|||
}, |
|||
upOption: { |
|||
auto: false |
|||
}, |
|||
assetsFlow: 10 |
|||
} |
|||
}, |
|||
props: { |
|||
i: Number, // 每个tab页的专属下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义) |
|||
index: { // 当前tab的下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义) |
|||
type: Number, |
|||
default () { |
|||
return 0 |
|||
} |
|||
}, |
|||
tabs: { // 为了请求数据,演示用,可根据自己的项目判断是否要传 |
|||
type: Array, |
|||
default () { |
|||
return [] |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
orderClick(item, type) { |
|||
this.orderItem = item |
|||
this[type] = true |
|||
}, |
|||
|
|||
//取消订单 |
|||
cancelDetermine() { |
|||
|
|||
}, |
|||
|
|||
//删除订单 |
|||
delDetermine() { |
|||
|
|||
}, |
|||
|
|||
//确认收货 |
|||
confirmDetermine() { |
|||
this.$toast('已成功收货') |
|||
}, |
|||
//资产流水 |
|||
getAssetsFlow(pageNum) { |
|||
setTimeout(() => { |
|||
this.mescroll.endBySize(10, 10); |
|||
}, 1000) |
|||
|
|||
}, |
|||
|
|||
/*下拉刷新的回调 */ |
|||
downCallback() { |
|||
// 下拉刷新的回调,默认重置上拉加载列表为第一页 (自动执行 page.num=1, 再触发upCallback方法 ) |
|||
this.mescroll.resetUpScroll() |
|||
}, |
|||
/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */ |
|||
upCallback(page) { |
|||
this.getAssetsFlow(page.num); |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.bref-box { |
|||
text-overflow: -o-ellipsis-lastline; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
display: -webkit-box; |
|||
-webkit-line-clamp: 2; |
|||
-webkit-box-orient: vertical; |
|||
} |
|||
|
|||
.order-bottom { |
|||
position: relative; |
|||
|
|||
.order-ico { |
|||
position: absolute; |
|||
right: 50rpx; |
|||
top: -19rpx; |
|||
color: rgba(0, 0, 0, 0.1) |
|||
} |
|||
} |
|||
|
|||
</style> |
|||
@ -0,0 +1,68 @@ |
|||
{ |
|||
"description": "项目配置文件", |
|||
"packOptions": { |
|||
"ignore": [] |
|||
}, |
|||
"setting": { |
|||
"bundle": false, |
|||
"userConfirmedBundleSwitch": false, |
|||
"urlCheck": true, |
|||
"scopeDataCheck": false, |
|||
"coverView": true, |
|||
"es6": true, |
|||
"postcss": true, |
|||
"compileHotReLoad": false, |
|||
"preloadBackgroundData": false, |
|||
"minified": true, |
|||
"autoAudits": false, |
|||
"newFeature": false, |
|||
"uglifyFileName": false, |
|||
"uploadWithSourceMap": true, |
|||
"useIsolateContext": true, |
|||
"nodeModules": false, |
|||
"enhance": false, |
|||
"useCompilerModule": true, |
|||
"userConfirmedUseCompilerModuleSwitch": false, |
|||
"useMultiFrameRuntime": true, |
|||
"useApiHook": true, |
|||
"useApiHostProcess": true, |
|||
"showShadowRootInWxmlPanel": true, |
|||
"packNpmManually": false, |
|||
"enableEngineNative": false, |
|||
"packNpmRelationList": [], |
|||
"minifyWXSS": true |
|||
}, |
|||
"compileType": "miniprogram", |
|||
"libVersion": "2.17.3", |
|||
"appid": "wx8f7c9e12f8fb8c14", |
|||
"projectname": "miniprogram-1", |
|||
"debugOptions": { |
|||
"hidedInDevtools": [] |
|||
}, |
|||
"scripts": {}, |
|||
"staticServerOptions": { |
|||
"baseURL": "", |
|||
"servePath": "" |
|||
}, |
|||
"isGameTourist": false, |
|||
"condition": { |
|||
"search": { |
|||
"list": [] |
|||
}, |
|||
"conversation": { |
|||
"list": [] |
|||
}, |
|||
"game": { |
|||
"list": [] |
|||
}, |
|||
"plugin": { |
|||
"list": [] |
|||
}, |
|||
"gamePlugin": { |
|||
"list": [] |
|||
}, |
|||
"miniprogram": { |
|||
"list": [] |
|||
} |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue