Commit a9c59ed4 authored by JUNEWIN\Administrator's avatar JUNEWIN\Administrator Committed by June

rebase commit

parent 49a5ea1a
<script>
import { mapActions } from 'vuex'
<script>
import { mapActions, mapState } from 'vuex'
import { login_wx } from '@/utils/modules/login.js'
import dayjs from 'dayjs'
import { removeStorage } from '@/lib/storage/index.js'
export default {
onLaunch: function() {
this.checkUpdate()
this.setSystemInfo()
},
methods: {
...mapActions('systemInfo', ['setSystemInfo']),
// 检查更新
checkUpdate() {
const updateManager = uni.getUpdateManager()
// 请求完新版本信息的回调
// updateManager.onCheckForUpdate(res => {
// console.log(res.hasUpdate)
// })
updateManager.onUpdateReady(() => {
uni.showModal({
title: '是否更新',
content: '新版本已经准备好,是否重启应用?',
success: res => {
if(res.confirm) updateManager.applyUpdate()
}
})
})
// updateManager.applyUpdate()
updateManager.onUpdateFailed(() => {
this.$toast({title: "更新失败,请检查您的网络是否正常"})
})
}
}
onLaunch: async function() {
this.setMobileData() // 获取系统信息和胶囊信息
this.checkUpdate() // 检查更新
const extConfig = wx.getExtConfigSync ? wx.getExtConfigSync(): {}
this.$store.state.user.appid = extConfig.appid
const token = this.$getStorage('token')
this.$store.state.user.token = token
this.getStoreInfo() // 这个接口一定要先获取,因为如果店铺过期
// wx.login
login_wx()
// uni.setEnableDebug({
// enableDebug: true
// })
uni.getStorageInfo({
success: res => {
if(res.currentSize > 5120) {
removeStorage('search-history')
}
}
})
},
globalData: {
backHome: false // 根据分享进入场景,自定义返回是否是返回首页
},
onShow(ops) {
if([1007, 1008, 1154, 1155].includes(ops.scene)) {
this.globalData.backHome = true
}
if(!this.$store.state.systemInfo.menuCalcInfo) {
this.setMobileData()
}
},
methods: {
...mapActions('systemInfo', ['setMobileData']),
...mapActions('user', ['setToken', 'setLoginStatus', 'getStoreInfo']),
// 检查更新
checkUpdate() {
if (wx.canIUse('getUpdateManager')) {
const updateManager = uni.getUpdateManager()
// 请求完新版本信息的回调
// updateManager.onCheckForUpdate(res => {
// console.log(res.hasUpdate)
// })
updateManager.onUpdateReady(() => {
uni.showModal({
title: '是否更新',
content: '新版本已经准备好,是否重启应用?',
success: res => {
if(res.confirm) updateManager.applyUpdate()
}
})
})
// updateManager.applyUpdate()
updateManager.onUpdateFailed(() => {
this.$toast({title: "更新失败,请检查您的网络是否正常"})
})
}
}
}
}
</script>
<style>
<style lang="scss">
@import url("@/styles/layout.css");
/* 隐藏scrollbar 滚动条 */
::-webkit-scrollbar {
display:none;
width:0;
height:0;
color:transparent;
::-webkit-scrollbar {
display:none;
width:0;
height:0;
color:transparent;
}
.primaryColor {
color: $primary!important;
}
.descColor {
color: $desc!important;
}
</style>
......@@ -3,46 +3,43 @@ import { request } from "@/lib/service"
import { baseUrl } from '@/config'
/**
* @desc 获取地址
* @desc 收货地址列表接口
* @param { Number } * 当前页码
* @param { String } 关键字:联系人/联系方式搜索
* @param { pagenum } pagenum 每页条数,默认10条/页
*/
export function addressList() {
export function addressList(params) {
return request({
url: `${baseUrl}/a`
url: 'zsxcx/addressXcx.htm',
method: 'post',
data: params
})
}
/**
* @desc 地址详情
* @desc 新增/编辑地址
* @params { } look docs
*/
export function addressList() {
export function editAddress(params) {
return request({
url: `${baseUrl}/a`
})
}
/**
* @desc 编辑地址
*/
export function editAddress() {
return request({
url: `${baseUrl}/a`
url: 'zsxcx/saveAddressXcx.htm',
method: 'post',
data: params,
needMask: true
})
}
/**
* @desc 删除地址
* @params { Number } address_id
*/
export function delAddress() {
export function delAddress(address_id) {
return request({
url: `${baseUrl}/a`
url: 'zsxcx/delAddressXcx.htm',
method: 'post',
data: {
address_id
},
needMask: true
})
}
/**
* @desc 添加地址
*/
export function addAddress() {
return request({
url: `${baseUrl}/a`
})
}
\ No newline at end of file
......@@ -2,30 +2,68 @@
import { request } from "@/lib/service"
import { baseUrl } from '@/config'
/**
* @desc 获取购物车数量
*/
export function cartCount() {
return request({
url: 'zsxcx/cartCount.htm',
method: 'post'
})
}
/**
* @desc 加入购物车
* @param {int | String} goods_id 商品ID
* @param {int} cart_number 加入商品数量
* @param {int | String} sku_id 规格ID
*/
export function addCart(params) {
return request({
url: 'zsxcx/addcart.htm',
method: 'post',
data: params
})
}
/**
* @desc 获取购物车列表
*/
export function cartsList() {
return request({
url: `${baseUrl}/a`
url: 'zsxcx/cartlist.htm',
method: 'post',
needMask: true
})
}
/**
* @desc 编辑购物车商品
* @param {int | String} 购物车ID
* @param {int | String} 编辑后的购买数量
*/
export function editCart() {
export function editCart({cart_id, cart_number}) {
return request({
url: `${baseUrl}/a`
url: 'zsxcx/editcart.htm',
data: {
cart_id,
cart_number
},
method: 'post',
needMask: true
})
}
/**
* @desc 删除购物车商品
* @param {String} cart_ids // 购物车ids
*/
export function delCart() {
export function delCart(cart_ids) {
return request({
url: `${baseUrl}/a`
url: 'zsxcx/delcarts.htm',
data: { cart_ids },
method: 'post',
needMask: true
})
}
......@@ -3,17 +3,37 @@ import { baseUrl } from '@/config'
/**
* @desc 获取分类列表
* @param { Number } search_type
* @param { Number } search_type_id
*
*/
export function getCatetories(search_type, search_type_id) {
export function getCatetories() {
return request({
url: `${baseUrl}/wxxcx/searchCategory.htm`,
url: 'zsxcx/shopGoodsCategory.htm',
method: 'post'
})
}
/**
* @desc 店铺商品列表接口
* @param { String } keywords 关键字:商品名称
* @param { Number } cat_id * 分类ID
*/
export function cateGoodsList(cat_id, keywords = '') {
return request({
url: 'zsxcx/shopGoods.htm',
method: 'post',
data: {
search_type,
search_type_id
cat_id,
keywords
}
})
}
/**
* @desc 首页展示栏商品接口
*/
export function homeCategory() {
return request({
url: 'zsxcx/indexGoodsXcx.htm',
method: 'post',
needMask: true
})
}
\ No newline at end of file
......@@ -2,15 +2,78 @@ import { request } from "@/lib/service"
import { baseUrl } from '@/config'
/**
* @desc 城市三级联动
* @desc 四级联动-省市区街道
* @param { Number } code // city code => default 1
*/
export function queryCity(code = '1') {
return request({
url: `${baseUrl}/wxxcx/areaLinkXcx.htm`,
url: 'zsxcx/areaLinkXcx.htm',
method: 'post',
data: {
code
}
})
}
/**
* @desc 浏览历史接口
* @param { String } last_time 上一次查询时间(yyyy-MM-dd)
*/
export function historyList(last_time) {
return request({
url: 'zsxcx/browse.htm',
method: 'post',
data: {last_time},
needMask: true
})
}
/**
* @desc 删除一条浏览历史接口
* @param { Number } bro_id 浏览历史ID
* @param { Number } goods_id 商品ID
*/
export function delHistory({bro_id, goods_id}) {
return request({
url: 'zsxcx/delBrowse.htm',
method: 'post',
data: {
bro_id,
goods_id
},
needMask: true
})
}
/**
* @desc 清空全部历史
*/
export function clearAllHistory() {
return request({
url: 'zsxcx/delBrowseAll.htm',
method: 'post',
needMask: true
})
}
/**
* @desc 获取店铺信息
*/
export function getStoreInfo() {
return request({
url: 'zsxcx/shopDetail.htm',
method: 'post'
})
}
export function pay({order_sn, openid}) {
return request({
url: 'zsxcx/orderWxPay.htm',
method: 'post',
data: {
order_sn, openid
},
needMask: true
})
}
\ No newline at end of file
......@@ -8,18 +8,16 @@ import { baseUrl } from '@/config'
* {
page 当前页码
pagenum 每页条数
sort 排序:1综合优先 2销量优先 3价格升序 4价格降序 5推荐 6离我最近
city 城市ID
sort 排序:1综合优先 2销量优先 3价格升序 4价格降序
keywords 关键字
cat_id 分类ID 0默认全部
...
}
*/
export function searchGoods(params) {
return request({
url: `${baseUrl}/wxxcx/searchGoodsXcx.htm`,
url: 'zsxcx/searchGoodsXcx.htm',
method: 'post',
data: params
data: params,
needMask: true
})
}
......@@ -27,14 +25,69 @@ export function searchGoods(params) {
/**
* @desc 商品详情
* @param { goods_id } 商品ID
* @param { shop_id } 当前店铺ID(分销功能使用)
* @param { agent_id } 代理商ID(分销功能使用)
*/
export function goodDetail(params) {
export function goodDetail(goods_id) {
return request({
url: 'zsxcx/goodsDetail.htm',
method: 'post',
data: {
goods_id
}
})
}
/**
* @desc 商品规格选择接口
* goods_id
*/
export function goodsSku(goods_id) {
return request({
url: 'zsxcx/goodsSku.htm',
method: 'post',
data: {
goods_id
}
})
}
/**
* @desc 商品详情页tab动态显示判断接口
* goods_id
*/
// export function goodsDetailTab(goods_id) {
// return request({
// url: 'zsxcx/getTabShow.htm',
// method: 'post',
// data: {
// goods_id
// }
// })
// }
/**
* @desc 商品收藏列表
* @param { Number } page 当前页码
* @param { Number } pagenum 条数
*/
export function collectGoodsList(params) {
return request({
url: `${baseUrl}/wxxcx/goodsDetail.htm`,
url: 'zsxcx/collection.htm',
method: 'post',
needMask: true,
data: params
})
}
/**
* @desc 收藏/取消收藏
*/
export function collectGoods(goods_id) {
return request({
url: 'zsxcx/collectGoods.htm',
method: 'post',
data: {
goods_id
},
needMask: true
})
}
// 订单相关
import { request } from "@/lib/service"
import { baseUrl } from '@/config'
/**
* @desc 提交订单前数据确认接口
* buy_type * 购买类型:0默认加入购物车 1立即购买
* cart_ids 选中的购物车IDs,多个则使用逗号分隔(buy_type=0时必填)
* sku_ids SKUIDs,多个则使用逗号分隔(buy_type=1时必填)
* cart_numbers 购买数量s,多个则使用逗号分隔(buy_type=1时必填)
*/
export function preConfirmOrderData(params) {
return request({
url: 'zsxcx/orderDetail.htm',
method: 'post',
data: params,
needMask: true
})
}
/**
* @desc 提交订单
* look up docs
*/
export function confirmOrder(params) {
return request({
url: 'zsxcx/orderInfoXcx.htm',
method: 'post',
data: params,
needMask: true
})
}
/**
* @desc 获取订单列表
*/
export function orderList() {
export function orderList(params) {
return request({
url: `${baseUrl}/a`
url: 'zsxcx/orderXcx.htm',
method: 'post',
data: params,
needMask: true
})
}
/**
* @desc 订单详情
*/
export function orderDetail() {
export function orderDetail(order_sn) {
return request({
url: `${baseUrl}/a`
url: 'zsxcx/snapshotXcx.htm',
method: 'post',
data: {
order_sn
},
needMask: true
})
}
/**
* @desc 删除订单
* @desc 提醒发货接口
*/
export function delOrder() {
export function remindOrder({order_id, order_sn}) {
return request({
url: `${baseUrl}/a`
url: 'zsxcx/remindXcx.htm',
method: 'post',
data: {
order_sn,
order_id
},
needMask: true
})
}
/**
* @desc 取消订单
*/
export function cancelOrder(order_sn) {
return request({
url: 'zsxcx/orderCancelXcx.htm',
method: 'post',
data: {
order_sn
},
needMask: true
})
}
/**
* @desc 申请退款/退货退款/退货/取消订单等订单操作申请接口
* @param order_sn
* @param {type} apply_type 申请类型:1退款 2退货退款 3取消订单 4退货
*/
export function applyBack({order_sn, apply_type}) {
return request({
url: 'zsxcx/applyRrcXcx.htm',
method: 'post',
data: {
order_sn,
apply_type
},
needMask: true
})
}
/**
* @desc 确认收货
*/
export function recieveOrder(order_sn) {
return request({
url: 'zsxcx/orderConfirmXcx.htm',
method: 'post',
data: {
order_sn
}
})
}
/**
* @desc 撤销XXX
* @param {type} order_sn
* @param {type} cancel_type
*/
export function undoOrder({order_sn, cancel_type}) {
return request({
url: 'zsxcx/cancelRrcApplyXcx.htm',
method: 'post',
data: {
order_sn,
cancel_type
},
needMask: true
})
}
/**
* @desc 签收退款
*/
export function recieveOrderRefund(order_sn) {
return request({
url: 'zsxcx/confirmReceivedRefundXcx.htm',
method: 'post',
data: {
order_sn
},
needMask: true
})
}
/**
* @desc 延长退款时间
*/
export function addRefundTime(order_sn) {
return request({
url: 'zsxcx/extendReceivedRefundXcx.htm',
method: 'post',
data: {
order_sn
},
needMask: true
})
}
/**
* @desc 查询账户管理订单数量信息
*/
export function orderNum() {
return request({
url: 'zsxcx/getOrderCount.htm',
method: 'post'
})
}
\ No newline at end of file
// 用户相关
import { request } from "@/lib/service"
import { baseUrl } from '@/config' // 将请求的baseUrl写这里,为了开发时调试请求地址
import { request, upload } from "@/lib/service"
import md5 from 'md5'
/**
* @desc wx.login 获取openid unionid等信息
* @param { String } code
*/
export function wxLogin(code) {
return request({
url: 'zsxcx/getInfo.htm',
data: {
js_code: code
}
})
}
/**
* @desc 退出登录
*/
export function logout() {
return request({
url: 'zsxcx/loginOut.htm',
method: 'post',
needMask: true
})
}
/**
* @desc 登录
* @param {Object} params
*
* lgtype 必填 登录方式:1微信登录 2短信验证码登录 3账号密码登录
* user 用户名(lgtype!=1时必填)
* pwd 登录密码(lgtype=3时必填)
* yzm 登录验证码(lgtype=2时必填
* encryptedData 加密信息(lgtype=1时必填)
* iv 加密算法的初始向量(lgtype=1时必填)
* session_key 会话密钥(lgtype=1时必填)
*/
export function login(params) {
return request({
url: 'zsxcx/login.htm',
method: 'post',
data: params
})
}
/**
* @desc 忘记密码
* @param { string } f_code 输入验证码
* @param { string } upwd 新密码
* @param { string } upwd2 新密码二次输入
*/
export function login() {
export function forgetPwd(params) {
return request({
url: `${baseUrl}/a`
url: 'zsxcx/forgetPwd.htm',
method: 'post',
data: params
})
}
/**
* @desc 注册
* @desc 发送登录验证码接口
* @param { String } phone
*/
export function register() {
export function loginSms(phone) {
return request({
url:`${baseUrl}/a`
url: 'zsxcx/send_lgmessage.htm',
method: 'post',
data: {
phone,
sign: md5('glsms' + phone)
}
})
}
/**
* @desc 发送忘记密码验证码接口
*/
export function forgetSms(phone) {
return request({
url: 'zsxcx/send_fgmessage.htm',
method: 'post',
data: {
phone,
sign: md5('glsms' + phone)
}
})
}
/**
* @desc 获取用户头像昵称手机号码
* @return { }
*/
export function getUserInfo() {
return request({
url: 'zsxcx/avatarXcx.htm',
method: 'post'
})
}
/**
* @desc 修改头像
* @param { String } tempFile 文件地址
* @return { }
*/
export function editAvatar(tempFile) {
return upload({
url: 'zsxcx/editAvatarXcx.htm',
tempFile
})
}
/**
* @desc 获取手机验证码
* @desc 修改昵称
* @param { String } nickname
*/
export function smsCode() {
export function editNickname(nickname) {
return request({
url:`${baseUrl}/a`
url: 'zsxcx/editNicknameXcx.htm',
method: 'post',
data: {
nickname
}
})
}
\ No newline at end of file
<template>
<view
class="nav-bar"
:style="cNavSty"
>
<view class="title" :style="cTitleStyle">
<view v-if="showBack" class="back-icon" :style="backStyle" @click="handleBack">
<view class="icon"></view>
</view>
<view class="title-inner" :style="{padding: showBack ? ' 0 30px' : 0}">{{title}}</view>
</view>
</view>
</template>
<script>
import { mapState } from 'vuex'
const app = getApp()
export default {
props: {
color: {
type: String,
default: '#333'
},
showBack: {
type: Boolean,
default: false
},
title: {
type: String,
default: ''
},
bg: {
type: String,
default: '#fff'
},
},
computed: {
...mapState(['systemInfo']),
cNavSty() {
const { menuCalcInfo } = this.systemInfo
return `height: ${menuCalcInfo.navH}px;background-color: ${this.bg};color: ${this.color};`
},
backStyle() {
const { systemInfo, menuCalcInfo } = this.systemInfo
const titleH = menuCalcInfo.navH - systemInfo.statusBarHeight
return `height: ${titleH}px;left: ${menuCalcInfo.lrSpace}px;`
},
cTitleStyle() {
const { systemInfo, menuButtonInfo, menuCalcInfo } = this.systemInfo
const titleH = menuCalcInfo.navH - systemInfo.statusBarHeight
const lrSpace = systemInfo.windowWidth - menuButtonInfo.right // 左右间距
const v = systemInfo.platform === 'android' ? 'flex-start' : 'center'
return `height: ${titleH}px;font-size: ${systemInfo.fontSizeSetting}px;padding: 0 ${menuCalcInfo.lrSpace}px;justify-content: ${v};margin-top: ${systemInfo.statusBarHeight}px;`
}
},
methods: {
handleBack() {
const { backHome } = app.globalData
if(backHome) {
uni.switchTab({
url: '/pages/home/index'
})
} else {
uni.navigateBack()
}
}
}
}
</script>
<style lang="scss" scoped>
.nav-bar {
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 998;
width: 100%;
.title {
position: relative;
box-sizing: border-box;
display: flex;
align-items: center;
.back-icon {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 20px;
z-index: 999;
display: flex;
align-items: center;
.icon {
@include backBtn(18rpx, 34rpx)
}
}
.title-inner {
box-sizing: border-box;
max-width: 260px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
</style>
<template>
<view>
<view class="uni-list-cell-db">
<picker mode="multiSelector" @columnchange="cityChange" @change="confirm" :value="cityIndex" :range="cities">
<view class="uni-input">{{cities[0][cityIndex[0]] || ''}}-{{cities[1][cityIndex[1]] || ''}}-{{cities[2][cityIndex[2]] || ''}}</view>
</picker>
</view>
</view>
</template>
<script>
import { queryCity } from '@/apis/common.js'
const cacheList = []
const cityCode = { // 四级联动的城市的code,第一级默认是1
"0": 1,
"1": 0,
"2": 0,
"3": 0
}
export default {
name: 'city-picker',
data() {
return {
code : 1,
cityIndex: [0, 0, 0, 0],
cities: [] ,// 这里是一个二维数组
}
},
created() {
this.getDefault()
},
methods: {
async getDefault() {
try{
await this.get_city(1)
await this.get_city(2)
await this.get_city(3)
await this.get_city(4)
this.$forceUpdate() // 慎用 重新渲染
}catch(e){
this.$toast({title: e.msg || '程序错误'})
}
},
// idx 获取第几列的数据
async get_city(idx) {
try{
const { status, data } = await queryCity(cityCode[idx - 1])
if(status) {
cityCode[idx] = data[0].code
this.cities[idx - 1] = data.map(item => item.area_name)
cacheList[idx - 1] = data
}
}catch(e){
this.$toast({title: e.msg || '程序错误'})
}
},
async cityChange(e) {
const { column, value } = e.detail
this.cityIndex[column] = value
switch (column) {
case 0: //拖动第1列
cityCode[1] = cacheList[0][value].code
await this.get_city(2)
await this.get_city(3)
await this.get_city(4)
// 复位
this.cityIndex.splice(1, 1, 0)
this.cityIndex.splice(2, 1, 0)
this.cityIndex.splice(3, 1, 0)
break;
case 1: //拖动第2列
cityCode[2] = cacheList[1][value].code
await this.get_city(3)
await this.get_city(4)
this.cityIndex.splice(2, 1, 0)
this.cityIndex.splice(3, 1, 0)
break;
case 2:
cityCode[3] = cacheList[2][value].code
await this.get_city(4)
this.cityIndex.splice(3, 1, 0)
break;
}
},
confirm(e) {
const value = e.detail.value
const result = {
province_code: cacheList[0][value[0]].code,
province_name: cacheList[0][value[0]].area_name,
city_code: cacheList[1][value[1]].code,
city_name: cacheList[1][value[1]].area_name,
area_code: cacheList[2][value[2]].code,
area_name: cacheList[2][value[2]].area_name,
detail_code: cacheList[3][value[3]].code,
detail_name: cacheList[3][value[3]].area_name
}
this.$emit('confirmCity', result)
}
}
}
</script>
<style lang="scss" scoped>
</style>
<template>
<view class="empty flex flex-column j-center a-center">
<image
style="width: 360rpx;"
class="mb-4"
v-if="iconSrc"
style="width: 400rpx;"
class="mb-2"
:src="iconSrc"
mode="widthFix"
/>
<text class="font-28">{{text}}</text>
<text class="font-28 font-bold text">{{text}}</text>
</view>
</template>
......@@ -16,7 +15,7 @@ export default {
props: {
iconSrc: {
type: String,
default: ""
default: "/static/images/common/noGoods.png"
},
text: {
type: String,
......@@ -26,9 +25,12 @@ export default {
}
</script>
<style scoped>
<style lang="scss" scoped>
.empty {
width: 100%;
height: 100%;
.text {
color: $desc;
}
}
</style>
import { isArray } from "@/utils/types.js"
// 判断是否符合购买条件
function judgePay(skuData) {
for(let i = 0, j = skuData.length; i < j; i ++) {
if(skuData[i].counts && skuData[i].counts < skuData[i].origin_number_sku) {
return false
}
}
return true
}
export default {
judgePay
}
\ No newline at end of file
<template>
<uni-popup ref="goodsPopup" type="bottom">
<view class="wrap w-100">
<view
class="flex j-start a-center"
v-if="goods"
>
<image
class="goods-cover mr-2"
:src="goods.cover"
mode="aspectFit"
/>
<view class="font-28 font-bold">{{goods.title}}</view>
</view>
<scroll-view scroll-y class="sku-list w-100 font-28">
<view
class="sku-item py-2"
v-for="(item, index) in skuData"
:key="index"
>
<view class="w-100 flex j-between a-center mb-2">
<view class="flex-1">{{item.spec_str}}</view>
<view class="step-wrap">
<input-number
:defaultVal="item.counts"
:params="{
index
}"
:max="~~item.inventory"
:min="0"
@change="numberChange"
/>
</view>
</view>
<view class="w-100 flex j-between a-center">
<view class="flex-1 flex j-start a-center price-txt">
<!-- 如果不是阶梯价 ? 价格 === 0 ? 询价 : 固定售价 -->
<template v-if="goods.is_inquiry === '1'">
<text>询价</text>
</template>
<template v-else>
<text>{{item.price}}</text>
<text class="originPrice ml-1">{{item.original_price || 0}}</text>
</template>
</view>
<view class="flex-1 text-center">
<text v-if="item.inventory > 0">{{'库存:' + item.inventory}}</text>
<text v-else class="primaryColor">库存需咨询商家</text>
</view>
<view class="payCount text-center">
<text v-if="~~item.origin_number_sku">{{item.origin_number_sku + item.unit}}起购</text>
</view>
</view>
<view class="mt-2 w-100 descColor flex j-start a-center flex-wrap font-24" v-if="item.is_tiered === '1'">
<view
class="mr-3 mb-2"
v-for="tiered_pri in item.tiered_pri"
:key="tiered_pri.num"
>
¥{{tiered_pri.price }}<text class="ml-1">≥{{tiered_pri.num + item.unit}}</text>
</view>
</view>
</view>
</scroll-view>
<view class="flex w-100 a-center flex-column font-28 mt-2">
<view class="as-end">
<text class="primaryColor">{{totalCounts}}</text>{{goods.unit || ''}}
<text class=" ml-2 price primaryColor">¥{{~~goods.is_inquiry ? '--' : totalPrice}}</text>
</view>
</view>
<!-- btn -->
<view class="w-100 btn-wrap flex j-between a-center text-center font-32">
<view class="btn-cart flex-1" @click.stop="handleCart">加入购物车</view>
<view class="btn-pay flex-1" @click.stop="handlePay">立即购买</view>
</view>
</view>
</uni-popup>
</template>
<script>
import uniPopup from '@/components/uni-popup/index.vue'
import price from '@/components/price/index.vue'
import inputNumber from '@/components/inputNumber/index.vue'
import { addCart } from '@/apis/carts.js'
import common from './common.js'
import { mapActions } from 'vuex'
export default {
name: 'goods-popup',
data() {
return {
goods: null,
skuData: [],
totalCounts: 0,
totalPrice: 0
}
},
components: {
uniPopup,
inputNumber,
price
},
methods: {
...common,
...mapActions('cart', ['setCount']),
/**
* @param {Object} params
* goodsInfo: {
cover 封面
title
}
goodsSku sku
*/
async show(params) {
try{
this.goods = params.goodsInfo
this.skuData = JSON.parse(JSON.stringify(params.skuData))
this.skuData.forEach(item => {
item.tiered_pri = item.tiered_pri && typeof item.tiered_pri === 'string' ? JSON.parse(item.tiered_pri) : ''
item.counts = 0
})
this.total()
this.$refs.goodsPopup.open()
}catch(e){
console.log(e)
this.$toast({title: e.msg || '程序错误'})
}
},
hide() {
this.$refs.goodsPopup.close()
// this.showSku = false
this.detail = null
this.skuData = []
this.goods = null
},
numberChange(e) {
console.log(e)
const idx = e.params.index
const value = e.val
this.$set(this.skuData[idx], 'counts', value)
this.total()
console.log(this.skuData)
},
total() {
const skuData = this.skuData
this.totalCounts = skuData.reduce((pre, cur) => { return pre + ~~cur.counts}, 0)
this.totalPrice = skuData.reduce((pre, cur) => {
const price = +cur.price
const counts = ~~cur.counts
if(cur.is_tiered === '1') { // 阶梯价 询价不管,不展示,按固定价计算
const tiered_pri = cur.tiered_pri
for(let i = 0, j = tiered_pri.length; i < j; i ++) {
if(counts >= tiered_pri[j-1].num) {
return pre + tiered_pri[j-1].price * counts
} else if(tiered_pri[i].num > counts) {
return pre + (i - 1 >= 0 ? tiered_pri[i - 1].price : price) * counts
}
}
} else {
return pre + price * counts
}
}, 0).toFixed(2)
},
// 加入购物车
handleCart() {
const skuData = this.skuData
if(this.totalCounts === 0) return this.$toast({title: '请选择购买数量'})
// if(!this.judgePay(skuData)) return this.$toast({title: '购买数量不能少于起购数量'})
const fn = []
for(let i = 0, j = skuData.length; i < j; i ++) {
if(skuData[i].counts) {
fn.push(addCart({
goods_id: skuData[i].goods_id,
cart_number: skuData[i].counts,
sku_id: skuData[i].sku_id
}))
}
}
Promise.all(fn)
.then(() => {
this.$toast({title: '加入购物车成功', cb: this.hide})
this.setCount()
})
.catch(err => {
console.log(err)
this.$toast({title: '加入购物车失败'})
})
},
// 下单
handlePay() {
try{
const skuData = this.skuData
console.log(skuData)
if(skuData.length === 0) return
if(this.totalCounts === 0) return this.$toast({title: '请选择购买数量'})
if(!this.judgePay(skuData)) return this.$toast({title: '购买数量不能少于起购数量'})
const sku_ids = []
const cart_numbers = []
for(let i = 0, j = skuData.length; i < j; i ++) {
if(skuData[i].counts) {
sku_ids.push(skuData[i].sku_id)
cart_numbers.push(skuData[i].counts)
}
}
const params = {
buy_type: 1,
sku_ids: sku_ids.join(','),
cart_numbers: cart_numbers.join(',')
}
uni.navigateTo({
url: `/pages/order/confirm-order?params=${encodeURIComponent(JSON.stringify(params))}`
})
this.hide()
}catch(e){
console.log(e)
}
}
}
}
</script>
<style lang="scss" scoped>
.wrap {
position: relative;
@include borderBox(20rpx, 20rpx);
padding-bottom: 118rpx;// 20 + 98
background-color: #fff;
.goods-cover {
width: 160rpx;
height: 160rpx;
}
.sku-list {
height: 372rpx;
@include borderBox(0, 20rpx);
.sku-item {
border-bottom: 1rpx solid $line;
}
.step-wrap {
flex: 0 0 224rpx;
width: 224rpx;
height: 64rpx;
}
.payCount {
flex: 0 0 224rpx;
font-size: 20rpx;
color: $desc;
}
.price-txt {
color: $primary;
.originPrice {
color: $desc;
text-decoration: line-through;
}
}
}
.btn-wrap {
position: absolute;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
height: 98rpx;
.btn-cart, .btn-pay {
color: #fff;
font-weight: bold;
line-height: 98rpx;
}
.btn-cart {
background-color: #FFBB33;
}
.btn-pay {
background-color: $primary;
}
}
}
</style>
@font-face {
font-family: "iconfont"; /* Project id 2637147 */
src: url("data:application/octet-stream;base64,d09GMgABAAAAAALYAAsAAAAABrwAAAKJAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACDBgqBDIEWATYCJAMMCwgABCAFhG0HNxv5BciemjxBBNrAwowJ1TNgRCiCaqzs2d0HIIdogcoDqleAwnFkVIwlIdGYyGi20bnJNc2AOHL4JAfM6TfPbXppxnieXd3YEZzH8+A2N2HXA4v1/1oH0P2fAZfj/y+gQOZZltPamyc9WAkGOtagyEokEO8hXu0gO/GMQL15xby3qxs7QfgdYk6QzJfdHWT1caerCARKEUXBfK1QTV1axD9+pNfpBfAm+n78JUUgSVVmn7RzUWUHz7/xv7MsVjSYPy3N14CnJVQhYxpQiNPuzAkf0cTyUa/xxfJqRUizxp9IYuiq9/zHS0Q1u7YRjGM28SPeExD8mF0hgQyqk9wYYJYxO69Jormp8T5yO3lnqecwJMqjl7dn28cR8OqDZuQviepdj68+itvdvHxaiWrzxH68wtePWE/cfvb+z0egiUvEeC0o3K1fTUTcQNJqQnpmLBgFUHkuIL8A4Ff/45IXgutv8CMRhdWGFPD9v45IQdfVnsET/DYtINIWI0ouTdLO2kA2MHJsQr16VNiBdt/jdV3kWkKtrgxJjSFktYaJwpxGlQbLqFZrDfWm1Kxu0IHyEaUOk9YAodUFkmZfkbV6JQrzC1W6/aFaa/ig3lHEbNlgNPTgCooRw3Zom4K6TJyKa2fBcX07VscsRPPyiN2NqVuPQ5ETyvka7MR0jhnucVViTIEKJQ5YDadhyyLQRYmBZcZpjLnyeV5pehMnEwcItoXCEAazg2ymQDoZ4aQEvZngyufbYaoxFoR2tNSFu2GUm94/JOIIBKJG4yS13MsrbuNUEoZRQAqKcICqYRBmsRCQq3mQAZMxHG1EyiUf79ApVA23vs7xAcViB/bsHClyFPkKkQBDR87IDAAAAAA=")
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-hao:before {
content: "\e616";
}
.icon-jianhao:before {
content: "\e67c";
}
<template>
<view class="wrpper" @click.stop="">
<view class="btn" @click="subtraction">-</view>
<input class="input" type="number" :value="value" @input="inputVal" />
<view class="btn" @click="add">+</view>
<view class="wrpper flex j-between a-center" @touchmove.stop.prevent="clear">
<view
class="btn iconfont icon-jianhao flex j-center a-center"
:class="calVal <= min ? 'disabled' : null"
@click.stop="subtraction"
></view>
<input
class="input"
type="number"
v-model="calVal"
@confirm="inputVal"
@focus="inputFocus"
@blur="inputVal"
/>
<view
class="btn iconfont icon-hao flex j-center a-center"
:class="(max && (calVal >= max)) ? 'disabled' : null"
@click.stop="add"
></view>
</view>
</template>
<script>
import { throttle } from '@/utils/common.js'
export default {
props: {
min: {
type: Number,
default: 1
default: 0
},
value: {
max: {
type: Number,
default: 1
default: 0
},
index: {
defaultVal: {
type: Number,
default: 0
default: 1
},
params: {
type: Object,
default: () => {}
}
},
data() {
return {
calVal: this.value
calVal: this.defaultVal
}
},
watch: {
calVal(newVal) {
// calVal用于内部计算,但是父组件改变了defaultVal的值会不更新calVal(临时解决)
defaultVal(newVal) {
this.calVal = ~~newVal
},
calVal: throttle(function(newVal) {
const max = this.max
const min = this.min
const newVal_number = ~~newVal
if(max && newVal_number >= max) return
if(newVal_number < min) return
this.$emit('change', {
index: this.index,
val: Number(newVal)
params: this.params,
val: newVal_number
})
}
}, 300)
},
methods: {
clear(e) {
// TODO nvue 取消冒泡
e.stopPropagation()
return
},
subtraction() {
const val = this.calVal
if(val === this.min) return this.$toast({title: `数量不能小${this.min}`})
this.calVal = val - 1
if(val <= this.min) return this.$toast({title: `数量不能少${this.min}`})
this.calVal -= 1
},
add() {
const val = this.calVal
const max = this.max
if(max && val >= max) {
this.calVal = max
this.$toast({title: '数量不能大于商品库存'})
return
}
this.calVal += 1
},
inputVal(e) {
this.calVal = e.detail.value
this.$emit('inputBlur')
let inputVal = ~~e.detail.value
const max = this.max
const min = this.min
if(max && inputVal >= max) {
inputVal = max
this.$toast({title: '数量不能大于商品库存'})
} else if(inputVal < min) {
inputVal = min
this.$toast({title: `数量不能少于${min}`})
}
this.calVal = inputVal
},
inputFocus() {
this.$emit('inputFocus')
}
}
}
</script>
<style lang="scss" scoped>
@import "./iconfont.css";
.wrpper {
width: 100%;
height: 100%;
......@@ -63,12 +119,17 @@ export default {
background-color: #fff;
.btn {
display: inline-block;
width: 64rpx;
height: 64rpx;
border: 1px solid #ccc;
width: 34rpx;
height: 100%;
}
.disabled {
color: #ccc!important;
}
.input {
width: 120rpx;
height: 100%;
border-radius: 4rpx;
background-color: $mainBg;
}
}
</style>
<template>
<view class="w-100 content-wrap flex flex-column j-center a-center">
<image
class="mt-4"
style="width: 400rpx;"
src="../../static/images/common/isOverdue.png"
mode="widthFix"
/>
<view class="font-bold my-2">店铺已打烊</view>
<navigator
class="mx-5"
hover-class="none"
open-type="switchTab"
url="/pages/mine/index"
>如需查看历史购买记录,请前往<text class="em_word p-1">【我的】</text>登录查看</navigator>
</view>
</template>
<style lang="scss" scoped>
.content-wrap {
font-size: 20rpx;
color: #desc;
.em_word {
color: $primary;
}
}
</style>
<template>
<view class="price-wrap font-28">
<template v-if="is_inquiry === '1'">
<text class="mr-1">询价</text>
</template>
<template v-else-if="is_tiered === '1'">
<text class="mr-1">{{price}}</text>
<text class="origin-price" v-if="originPrice">{{originPrice || 0}}</text>
<text v-if="goods_unit">/{{goods_unit}}</text>
</template>
<template v-else>
<text class="mr-1">{{price}}</text>
<text class="origin-price" v-if="originPrice">{{originPrice}}</text>
<text v-if="goods_unit">/{{goods_unit}}</text>
</template>
</view>
</template>
<script>
export default {
props: {
is_inquiry: { // 是否开启询价 1开启 0关闭
type: String,
default: '0'
},
is_tiered: { // 是否开启阶梯价 1开启 0关闭
type: String,
default: '0'
},
price: { // 正常显示的价格
type: String | Number,
default: 0
},
originPrice:{ // 文本穿透线的价格
type: String | Number,
default: 0
},
goods_unit: {
type: String,
default: ''
}
}
}
</script>
<style lang="scss" scoped>
.price-wrap {
color: $primary;
.origin-price {
font-size: 20rpx;
color: $desc;
text-decoration: line-through;
}
}
</style>
......@@ -3,15 +3,20 @@
@refresherabort="refresherabort"
@refresherpulling="handlePulling" -->
<scroll-view
class="w-100 scroll-wrapper"
class="scroll-wrapper"
scroll-y
enable-back-to-top
scroll-with-animation
:refresher-enabled="refresherEnabled"
:refresher-threshold="threshold"
:refresher-default-style="refresherStyle"
:refresher-background="refresherBg"
:refresher-triggered="refresherStatus"
:scroll-top="scrollTop"
@scrolltolower="scrolltolower"
@refresherrefresh="refresherrefresh"
@refresherrestore="refresherrestore"
@refresherabort="refresherabort"
>
<slot />
</scroll-view>
......@@ -30,17 +35,23 @@ export default {
},
refresherStyle: { // black,white,none,none 表示不使用默认样式
type: String,
default: 'back'
default: 'black'
},
refresherBg: { // 背景色
type: String,
default: "#FFF"
},
refresherStatus: { // 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
type: Boolean,
default: false
default: "#fff"
}
},
data() {
return {
scrollTop: 0,
refresherStatus: false // 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
}
},
created() {
console.log(this.refresherEnabled)
},
methods: {
// 触底
scrolltolower() {
......@@ -54,18 +65,26 @@ export default {
// 下拉刷新被触发
refresherrefresh() {
this.refresherStatus = true
let timer = setTimeout(() => {
this.refresherStatus = false
}, 800)
this.$emit('refresh')
},
// 下拉刷新被复位(不常用)
// refresherrestore() {
// console.log("下拉刷新被复位")
// },
refresherrestore() {
console.log("下拉刷新被复位")
},
scroll2Top() {
this.scrollTop = Math.random()
},
// 下拉刷新被中止(不常用)
// refresherabort() {
// console.log("下拉刷新被中止")
// }
refresherabort() {
console.log("下拉刷新被中止")
}
}
}
</script>
......
<template>
<view class="w-100 search-bar flex j-center a-center" @click="nav">
<view class="search text-center">
<text class="mr-2">icon</text>
<text class="font-28">搜索商品</text>
<view class="w-100 search-bar flex j-center a-center" :style="{background: bg}" @click="nav">
<view class="my-2 search text-center flex j-center a-center" :style="{background: innerBg}">
<image
class="search-icon mr-2"
src="../../static/images/common/icon-search.png"
mode="aspectFit"
/>
<text class="font-24">搜索商品</text>
</view>
</view>
</template>
<script>
export default {
props: {
bg: {
type: String,
default: "#fff"
},
innerBg: {
type: String,
default: "#f8f8f8"
}
},
methods: {
nav() {
uni.navigateTo({
......@@ -21,14 +35,17 @@ export default {
<style lang="scss" scoped>
.search-bar {
height: 98rpx;
@include borderBox(20rpx, 20rpx);
background-color: yellow;
background-color: $white;
.search {
width: 710rpx;
height: 72rpx;
line-height: 72rpx;
background-color: #fff;
width: 690rpx;
height: 88rpx;
line-height: 88rpx;
color: #7F7F7F;
background-color: #F8F8F8;
.search-icon {
width: 34rpx;
height:34rpx;
}
}
}
</style>
<template>
<view v-if="showPopup" class="uni-popup" @touchmove.stop.prevent="clear">
<view v-show="showPopup" class="uni-popup" @touchmove.stop.prevent="clear">
<uni-transition :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
<view class="uni-popup__wrapper-box" @click.stop="clear">
......
// 详细看文档
export const cOrder_status = {
'os0_osd1': {
text: '待接单',
},
'os1_osd11': {
text: '待付款',
},
'os1_osd12': {
text: '待付款(已支付定金)',
},
'os6_osd61': {
text: '待发货',
},
'os7_osd71': {
text: '待收货',
},
'os10_osd101': {
text: '已收货',
},
'os11_osd111': {
text: '退款审核中',
},
'os11_osd112': {
text: '退款审核中',
},
'os11_osd113': {
text: '退款审核中',
},
'os11_osd114': {
text: '退货审核中',
},
'os11_osd115': {
text: '退货审核中',
},
'os11_osd116': {
text: '退款退货审核中',
},
'os11_osd117': {
text: '退款退货审核中',
},
'os9_osd91': {
text: '退款中',
},
'os9_osd93': {
text: '退货中',
},
'os9_osd92': {
text: '退货退款中',
},
'os5_osd53': {
text: '交易完成',
},
//2是关闭,osd(order_status_d) 看文档吧,2全部关闭
'os2_osd28': {
text: '交易关闭'
},
'os2_osd29': {
text: '交易关闭',
},
'os2_osd21': {
text: '交易关闭'
},
'os2_osd23': {
text: '交易关闭',
},
'os2_osd26': {
text: '交易关闭'
},
'os2_osd210': {
text: '交易关闭',
},
'os2_osd211': {
text: '交易关闭',
},
'os2_osd22': {
text: '交易关闭'
},
'os2_osd25': {
text: '交易关闭',
},
'os2_osd27': {
text: '交易关闭',
},
'os2_osd212': {
text: '交易关闭',
},
'os2_osd213': {
text: '交易关闭'
},
'os2_osd214': {
text: '交易关闭',
},
'os2_osd215': {
text: '交易关闭'
},
'os2_osd216': {
text: '交易关闭',
},
'os2_osd217': {
text: '交易关闭',
},
}
export const pay_type = {
0: '——',
1: '微信',
2: '支付宝',
3: '线下4余额',
6: '格利支付',
7: '现金',
8: '欠款',
9: '转账(私)',
10: '转账(公)',
11: '转账(微信)',
12: '转账(支付宝)',
13: '微信-格利',
14: '支付宝-格利',
15: '企业网银-格利',
16: '个人网银-格利'
}
export const weeks = {
1: '周一',
2: '周二',
3: '周三',
4: '周四',
5: '周五',
6: '周六',
7: '周日',
}
\ No newline at end of file
const env = {
release: 'https://www.gelifood.com/', // 正式版
trial: 'https://d.gelifood.com', // 体验版
develop: 'https://d.gelifood.com' // 开发版
release: 'https://www.gelifood.com', // 正式版
trial: 'https://www.gelifood.com', // 体验版
develop: 'https://www.gelifood.com' // 开发版
}
// 不考虑其他端小程序直接这样配置
......@@ -10,8 +10,3 @@ export const baseUrl = env[__wxConfig.envVersion]
// // #ifndef MP-WEIXIN
// export const baseUrl = process.env.NODE_ENV === 'development' ? env.develop : env.release
// // #endif
// 商品图片的域名地址
export const imgUrl = process.env.NODE_ENV === 'development' ? 'https://d.gelifood.com/' : 'https://www.gelifood.com/'
export const publicKey = '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp3Rit6cNlpOa9dbTx2ddt6ZblmMO04zdY+UIHMvsAnjBHYxEYfm7hx1yNkf1ohZNg47K+Ox/z8WcTRYpGnSka5UHDUTeBEQp4BGD25PsJLkc5YUk0PXjqRq5m+vuB3mEn7r6DaTwCxX5n2G4ky77xhzmZbG7MDP85RQHBVsvqYwIDAQAB-----END PUBLIC KEY-----'
\ No newline at end of file
{
"extEnable": true,
"extAppid": "wx537e892e36fbf79d",
"ext": {
"appid": "wx537e892e36fbf79d"
}
}
\ No newline at end of file
/**
* @desc 事件通讯
*/
class EventBus {
constructor(arg) {
this.events = {}
}
/**
* @desc 事件监听
*/
$on(key, fn) {
if(!this.events[key]) {
this.events[key] = []
}
this.events.push(fn)
}
/**
* @desc 事件派发
*/
$emit() {
const key = Array.prototype.splice.call(arguments)
const curE = this.events[key]
curE.apply(this, arguments)
}
/**
* @desc 取消事件监听
*/
$off(key) {
const events = this.events
for(let i = 0, j = events.length; i++) {
if(events[key]) { // 移除事件的监听
this.events.splice(i, 1)
}
}
}
}
export default EventBus
\ No newline at end of file
export default function Modal(options) {
if(Object.prototype.toString.call(options) !== "[object Object]") return
if(!options.content) {
return uni.showToast({
title: 'content不能为空',
icon: "none"
})
}
uni.showModal({
title: options.title || '提示',
content: options.content,
showCancel: options.showCancel || true,
cancelText: options.cancelText || '取消',
cancelColor: options.cancelColor || '#000000',
confirmText: options.confirmText || '确定',
confirmColor: '#FF661A',
success: res => {
if(res.confirm) {
options.cb && typeof options.cb === 'function' && options.cb()
}
}
})
}
\ No newline at end of file
import { baseUrl } from '@/config'
import Toast from "../toast/index.js"
import { isObeject, isFunction } from "@/utils/types.js"
import Validator from "@/utils/validate.js"
import Validator from "@/utils/validate.js"
import { login_slilen } from '@/utils/modules/login.js'
import store from '@/store/index.js'
/**
* @desc 请求 所有的状态码都在这里处理
* @param { Object } options 参考uni.request参数说明
......@@ -13,8 +17,82 @@ import Validator from "@/utils/validate.js"
function validateOps(options = {}) {
const validator = new Validator()
validator.add(Object.keys(options), [{strategy: 'minLength:1', errorMsg: '参数格式不正确'}])
validator.add(options.url, [{strategy: 'notEmpty', errorMsg: '请求地址不能为空'}, {strategy: 'isHttp', errorMsg: '请求地址不正确'}])
validator.add(options.url, [{strategy: 'notEmpty', errorMsg: '请求地址不能为空'}])
return validator.validate()
}
// 没有考虑到上传,先前没有统一响应处理
async function successRes(res, options, resolve, reject) {
try{
switch(res.statusCode) {
case 200:
options.successCb && typeof options.successCb === 'function' && options.successCb()
// 处理某些接口返回String类型的数据
const data = (res.data && typeof res.data === 'string') ? JSON.parse(res.data) : res.data
if(!data) return Toast({title: '后端没有返回data'})
const status = data.code
switch(status) {
case 10:
if(store.state.user.isOverdue) {
store.state.user.isOverdue = false
}
resolve({
status: true,
data: data.data,
msg: data.rep_msg
})
break;
case -1:
Toast({title: data.rep_msg})
reject({
status: false,
data: data.data,
msg: data.rep_msg
})
break;
case -2:
return Toast({title: data.rep_msg})
break;
case -3:
Toast({
title: '登录已失效,请重新登录',
cb: () => uni.navigateTo({
url: '/pages/login/index'
})
})
break;
case -11: // 购买的服务过期
if(!store.state.user.isOverdue) {
store.state.user.isOverdue = true
}
return Toast({title: data.rep_msg})
break;
default:
Toast({title: data.rep_msg})
reject({
status: false,
code: status, // 正常不返回为了好找 后端调试 -1 => 业务错误(一般失败情况返回此项);-2 => 系统异常; -3 => 请先登录; -4 => 请求失败; -10 => 签名失败
data: data.data,
msg: data.rep_msg
})
break;
}
break;
case 404:
return Toast({title: '请求路径不存在'})
break;
case 500:
return Toast({title: '服务器错误'})
break; // 这里的break可以不写,不会执行到。return直接退出函数了
default:
Toast({title: '网络请求失败'})
return
break;
}
}catch(e){
console.log(e)
Toast({title: e.msg || '程序请求错误'})
}
}
// 请求
......@@ -22,68 +100,34 @@ export function request (options) {
const valite_err = validateOps(options)
if(valite_err) return Toast({title: valite_err})
options.method = options.method ? options.method.toUpperCase() : "GET" // 默认get
options.needMask && uni.showLoading({title: '加载中...', mask: true})
options.url = `${baseUrl}/${options.url}`
if(options.needMask) {
uni.showLoading({title: '加载中...', mask: true})
}
return new Promise((resolve, reject) => {
// const isOverdue = store.state.user.isOverdue
// if(isOverdue) {
// reject({
// status: false,
// data: null,
// msg: '服务已过期'
// })
// return
// }
const token = store.state.user.token || ''
const appid = store.state.user.appid || ''
uni.request({
...options,
header: {
'content-type': 'application/x-www-form-urlencoded',
'cookie': 'JSESSIONID=aaaH_PdwNLO-Oan2L7QNx; path=/'
'token': token,
'appid': appid
},
success: res => {
const statusCode = res.statusCode
// console.log(statusCode)
switch(statusCode) {
case 200:
options.successCb && typeof options.successCb === 'function' && options.successCb()
// 处理某些接口返回String类型的数据
const data = (res.data && typeof res.data === 'string') ? JSON.parse(res.data) : res.data
const status = data.code
switch(status) {
case 10:
resolve({
status: true,
data: res.data.list || res.data.data,
res: res.data,
msg: data.rep_msg
})
break;
case -3:
return Toast({title: 'login', cb: () => {
uni.navigateTo({
url: '/pages/login/index.vue'
})
}})
break;
default:
Toast({title: data.rep_msg})
resolve({
status: false,
code: status, // 正常不返回为了好找 后端调试 -1 => 业务错误(一般失败情况返回此项);-2 => 系统异常; -3 => 请先登录; -4 => 请求失败; -10 => 签名失败
data: data.list,
res: res.data.list || res.data.data,
msg: data.rep_msg
})
break;
}
break;
case 404:
return Toast({title: '请求路径不存在'})
break;
case 500:
return Toast({title: '服务器错误'})
break; // 这里的break可以不写,不会执行到。return直接退出函数了
default:
Toast({title: '网络请求失败'})
return
break;
}
successRes(res, options, resolve, reject)
},
fail: err => {
if(err.errMsg.includes('request:fail ')) {
Toast({title: err.errMsg})
}
Toast({title: '网络开小差了,请检查网络!'})
options.errCb && typeof options.errCb === 'function' && options.errCb();
reject({
status: false,
......@@ -100,10 +144,48 @@ export function request (options) {
}
// 上传文件
// export function upload() {
// return new Promise((resolve, reject) => {
// uni.uploadFile({
// })
// })
// }
export function upload(options) {
const valite_err = validateOps(options)
if(valite_err) return Toast({title: valite_err})
options.url = `${baseUrl}/${options.url}`
uni.showLoading({title: '上传中...', mask: true})
return new Promise((resolve, reject) => {
// const isOverdue = store.state.user.isOverdue
// if(isOverdue) {
// reject({
// status: false,
// data: null,
// msg: '服务已过期'
// })
// return
// }
const token = store.state.user.token || ''
const appid = store.state.user.appid || ''
uni.uploadFile({
url: options.url,
filePath: options.tempFile,
header: {
// "Content-Type": "multipart/form-data",
'token': token,
'appid': appid
},
name: 'file',
success: res =>{
successRes(res, options, resolve, reject)
},
fail: err => {
Toast({title: '网络开小差了,请检查网络!'})
options.errCb && typeof options.errCb === 'function' && options.errCb();
reject({
status: false,
code: 400,
data: err
})
},
complete: () => {
options.completeCb && typeof options.completeCb === 'function' && options.completeCb();
uni.hideLoading()
}
})
})
}
/**
* getStorage
* @desc 获取存储的本地数据
* @param { keyName }
* @param { String } key
* @return { storageVal }
*/
export function getStorage(key){
......@@ -9,6 +9,22 @@ export function getStorage(key){
return val ? JSON.parse(val) : ''
}
/**
* getStorage 异步 用处不大
* @param { String } key
* @param { function } cb
* @return no
*/
// export function getStorageAsync(key, cb) {
// uni.getStorage({
// key,
// success: res => {
// cb && typeOf cb === 'function' && cb()
// console.log(res.data)
// }
// })
// }
/**
* setStorage
* @desc 设置本地存储数据(同步)
......
......@@ -19,4 +19,5 @@ export default function Toast(options) {
}, 500)
}
})
}
\ No newline at end of file
}
......@@ -6,7 +6,13 @@ import "@/utils/vue_extend.js" // 常用方法
// 全局组件
import emptyView from '@/components/empty-view/index.vue'
import uniPopup from '@/components/uni-popup/index.vue'
import cNav_bar from '@/components/c-nav_bar/index.vue'
Vue.component('empty-view', emptyView)
Vue.component('uni-popup', uniPopup)
Vue.component('c-nav_bar' , cNav_bar)
Vue.prototype.$store = store
Vue.config.productionTip = false
......
......@@ -50,14 +50,19 @@
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "wx445b225e03ee51aa",
"appid" : "wxd170058f4ad8fecd",
"setting" : {
"urlCheck" : false,
"es6" : true,
"postcss" : true,
"postcss" : false,
"minified" : true
},
"usingComponents" : true
"usingComponents" : true,
"permission" : {
"scope.userLocation" : {
"desc" : "使用该功能需要获取您的当前位置"
}
}
},
"mp-alipay" : {
"usingComponents" : true
......
import { cancelOrder, remindOrder, applyBack, undoOrder, recieveOrder, recieveOrderRefund, addRefundTime } from "@/apis/order.js"
import createOrder from '@/utils/modules/pay.js'
import { isFunction } from '@/utils/types.js'
import { cOrder_status } from '@/config/global.js'
const order_mixin = {
filters: {
cOrderStatus(key) {
return cOrder_status[key].text || ''
}
},
methods: {
// 取消订单
async orderCancel(order_sn, cb) {
try{
const { status, data } = await cancelOrder(order_sn)
if(status) {
cb && isFunction(cb) && cb()
this.$toast({title: '订单取消成功'})
}
}catch(e){
this.$toast({title: '取消失败'})
//TODO handle the exception
}
},
// 提醒发货
async orderRemind(order_sn, order_id, cb) {
try{
const { status, data } = await remindOrder({order_sn, order_id})
if(status) {
cb && isFunction(cb) && cb()
this.$toast({title: '提醒成功'})
}
}catch(e){
this.$toast({title: e.msg || '提醒失败'})
//TODO handle the exception
}
},
// 申请退款
async applyBack(order_sn, type, cb) {
try{
const { status, data } = await applyBack({order_sn, apply_type: type})
if(status) {
cb && isFunction(cb) && cb()
this.$toast({title: '申请成功'})
}
}catch(e){
console.log(e)
this.$toast({title: '申请失败'})
//TODO handle the exception
}
},
// 支付
async orderPay(order_sn, fn) {
await createOrder({
order_sn,
successCb: () => {
fn && isFunction(fn) && fn()
}
})
},
// 撤销
async orderUndo(order_sn, type, cb) {
try{
const { status, data } = await undoOrder({order_sn, cancel_type: type})
if(status) {
cb && isFunction(cb) && cb()
this.$toast({title: '申请成功'})
}
}catch(e){
console.log(e)
this.$toast({title: e.msg || '申请失败'})
//TODO handle the exception
}
},
// 确认收货
async orderRecieve(order_sn, cb) {
try{
const { status, data } = await recieveOrder(order_sn)
if(status) {
cb && isFunction(cb) && cb()
this.$toast({title: '收货成功'})
}
}catch(e){
console.log(e)
this.$toast({title: e.msg || '申请失败'})
//TODO handle the exception
}
},
// 签收退款
async orderRefund(order_sn, cb) {
try{
const { status, data } = await recieveOrderRefund(order_sn)
if(status) {
cb && isFunction(cb) && cb()
this.$toast({title: '签收成功'})
}
}catch(e){
this.$toast({title:e.msg || '签收失败'})
//TODO handle the exception
}
},
// 签收退款
async orderAddRefund(order_sn, cb) {
try{
const { status, data } = await addRefundTime(order_sn)
if(status) {
cb && isFunction(cb) && cb()
this.$toast({title: '操作成功'})
}
}catch(e){
this.$toast({title: e.msg || '操作失败'})
//TODO handle the exception
}
}
}
}
export default order_mixin
\ No newline at end of file
import { cOrder_status } from '@/config/global.js'
const order_status = {
filters: {
cOrderStatus(key) {
return cOrder_status[key].text || ''
}
},
}
export default order_status
\ No newline at end of file
import { getURLwithArgs } from '@/utils/common.js'
import { mapState } from 'vuex'
import { baseUrl } from '@/config/index.js'
const common_share = {
computed: {
...mapState({
storeInfo: state => state.user.storeInfo
}),
judgePages() {
const path = getURLwithArgs()
let imageUrl = ''
let title = this.storeInfo.shop_name
if(path && path.startsWith('pages/goods/detail')) {
imageUrl = (this.detail && this.detail.goods_thumb) ? `${baseUrl}/${this.detail.goods_thumb}` : ''
title = this.detail ? this.detail.goods_name : ''
}
return {
path, imageUrl, title
}
}
},
onShareAppMessage() {
return this.judgePages
},
onShareTimeline() {
return this.judgePages
}
}
export default common_share
\ No newline at end of file
......@@ -4,10 +4,35 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"charenc": {
"version": "0.0.2",
"resolved": "https://registry.npm.taobao.org/charenc/download/charenc-0.0.2.tgz",
"integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc="
},
"crypt": {
"version": "0.0.2",
"resolved": "https://registry.nlark.com/crypt/download/crypt-0.0.2.tgz",
"integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
},
"dayjs": {
"version": "1.10.5",
"resolved": "https://registry.nlark.com/dayjs/download/dayjs-1.10.5.tgz?cache=0&sync_timestamp=1622012259636&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdayjs%2Fdownload%2Fdayjs-1.10.5.tgz",
"integrity": "sha1-VgDfRUj8JFOz8WPrsqu+llzPuYY="
},
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz?cache=0&sync_timestamp=1604429452232&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-buffer%2Fdownload%2Fis-buffer-1.1.6.tgz",
"integrity": "sha1-76ouqdqg16suoTqXsritUf776L4="
},
"md5": {
"version": "2.3.0",
"resolved": "https://registry.npm.taobao.org/md5/download/md5-2.3.0.tgz",
"integrity": "sha1-w9qaaq46MLRreww0m4exENw72k8=",
"requires": {
"charenc": "0.0.2",
"crypt": "0.0.2",
"is-buffer": "~1.1.6"
}
}
}
}
......@@ -16,6 +16,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"dayjs": "^1.10.5"
"dayjs": "^1.10.5",
"md5": "^2.3.0"
}
}
{
"pages": [
{
"path": "pages/home/index",
"style": {
"navigationBarTitleText": " "
"navigationStyle": "custom",
"navigationBarTextStyle":"white",
"enablePullDownRefresh": true,
"onReachBottomDistance": 45
}
},
{
"path": "pages/login/index",
"style": {
"navigationBarTitleText": "登录"
"navigationBarTitleText": " "
}
},
{
"path": "pages/carts/index",
"style": {
"navigationBarTitleText": "购物车",
"enablePullDownRefresh": true
"enablePullDownRefresh": true,
"onReachBottomDistance": 50
}
},
{
"path": "pages/mine/index",
"style": {
"navigationBarTitleText": "我的"
"navigationStyle": "custom",
"navigationBarTextStyle":"white"
}
},
{
......@@ -31,6 +37,12 @@
"navigationBarTitleText": "分类"
}
},
{
"path": "pages/goods/detail",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/order/order-list",
"style": {
......@@ -38,9 +50,9 @@
}
},
{
"path": "pages/goods/detail",
"path": "pages/order/order-detail",
"style": {
"navigationStyle": "custom"
"navigationBarTitleText": "订单详情"
}
},
{
......@@ -62,56 +74,127 @@
}
}
],
"subPackages": [{
"root": "subPages",
"pages": [
{
"path": "test/index",
"style": {
"navigationBarTitleText": "test"
"subPackages": [
{
"root": "subPages",
"pages": [
{
"path": "resetPwd/index",
"style": {
"navigationBarTitleText": "重置密码"
}
},
{
"path": "userManage/index",
"style": {
"navigationBarTitleText": "账号管理"
}
},
{
"path": "collection/index",
"style": {
"navigationBarTitleText": "收藏历史"
}
},
{
"path": "address/index",
"style": {
"navigationBarTitleText": "地址列表",
"enablePullDownRefresh": true,
"onReachBottomDistance": 50
}
},
{
"path": "address/edit",
"style": {
"navigationBarTitleText": "添加地址"
}
},
{
"path": "web-view/index",
"style": {
"navigationBarTitleText": " "
}
},
{
"path": "storeInfo/index",
"style": {
"navigationBarTitleText": "店铺详情"
}
},
{
"path": "afterSales/apply",
"style": {
"navigationBarTitleText": "申请售后"
}
},
{
"path": "afterSales/detail",
"style": {
"navigationBarTitleText": "申请退款/退货"
}
},
{
"path": "pay_status/index",
"style": {
"navigationBarTitleText": "支付结果"
}
}
}
]
}],
]
},
{
"root": "testA",
"pages":[
{
"path": "pageA/index",
"style": {
"navigationBarTitleText": "收藏历史",
"navigationStyle":"custom"
},
"independent": true
}
]
}
],
"preloadRule": {
"subPages/test/index": {
"pages/home/index": {
"network": "all",
"packages": ["__APP__"]
"packages": ["subPages"]
}
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": " ",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
"navigationBarBackgroundColor": "#fff",
"backgroundColor": "#fff"
},
"tabBar":{
"color": "#707070",
"selectedColor": "#8745FF",
"color": "#333333",
"selectedColor": "#FF661A",
"backgroundColor": "#FFFFFF",
"borderStyle": "black",
"list":[
{
"iconPath": "static/images/tabbar/find.png",
"selectedIconPath": "static/images/tabbar/find-selected.png",
"iconPath": "static/images/tabbar/home.png",
"selectedIconPath": "static/images/tabbar/home-active.png",
"pagePath": "pages/home/index",
"text":"首页"
},
{
"iconPath": "static/images/tabbar/find.png",
"selectedIconPath": "static/images/tabbar/find-selected.png",
"iconPath": "static/images/tabbar/cate.png",
"selectedIconPath": "static/images/tabbar/cate-active.png",
"pagePath": "pages/category/index",
"text":"商品分类"
},
{
"iconPath": "static/images/tabbar/find.png",
"selectedIconPath": "static/images/tabbar/find-selected.png",
"iconPath": "static/images/tabbar/cart.png",
"selectedIconPath": "static/images/tabbar/cart-active.png",
"pagePath": "pages/carts/index",
"text":"购物车"
},
{
"iconPath": "static/images/tabbar/my.png",
"selectedIconPath": "static/images/tabbar/my-selected.png",
"iconPath": "static/images/tabbar/mine.png",
"selectedIconPath": "static/images/tabbar/mine-active.png",
"text": "我的",
"pagePath": "pages/mine/index"
}
......
<template>
<view>addresslist</view>
</template>
<script>
</script>
<style>
</style>
import { cartsList, editCart, delCart } from "@/apis/carts.js"
// 获取购物车列表
async function getCartList() {
try{
const { status, data } = await cartsList()
if(status) {
this.cartList = data ? dealArr(data[0].cart_list2) : []
}
}catch(e){
this.$toast({title: '获取购物车失败'})
//TODO handle the exception
}
}
// 编辑购物车
async function editCartCount() {
try{
}catch(e){
this.$toast({title: '编辑购物车失败'})
//TODO handle the exception
}
}
// 删除购物车
async function deleteCarts() {
try{
}catch(e){
this.$toast({title: '删除购物车失败'})
//TODO handle the exception
}
}
// 给数组的每一项添加checKed, 用于勾选,遍历统计勾选
function dealArr(arr) {
if(!arr) return arr
if(Array.isArray(arr)) {
for(let i = 0, j = arr.length; i < j; i ++) {
arr[i].checked = false
dealArr(arr[i].list)
}
}
return arr
}
export default {
getCartList,
editCartCount,
deleteCarts
}
\ No newline at end of file
This diff is collapsed.
import { isArray } from "@/utils/types.js"
// 递归添加一个选中状态
function dealCate (list) {
if(list && !isArray(list)) return list
for(let i = 0; i < list.length; i ++) {
list[i].checked = false
if(isArray(list[i].list)) {
dealCate(list[i].list)
}
}
return list
}
export default {
dealCate
}
\ No newline at end of file
This diff is collapsed.
<template>
<view class="menu-wrap" :style="menuSty">
<view class="menu-main p-2 flex j-between a-center w-100">
<view @click.stop="back">返回</view>
<view @click.stop="showMenu = !showMenu">菜单</view>
</view>
<view
v-show="showMenu"
class="mt-2 menu-item_wrap font-28"
:style="{ width: menuButtonInfo.width + 'px' }"
>
<view class="menu-item p-2" @click="handleMenu('index')">首页</view>
<view class="menu-item p-2" @click="handleMenu('index')">商品搜索</view>
<view class="menu-item p-2" @click="handleMenu('index')">订单列表</view>
<view class="menu-item p-2" @click="handleMenu('index')">购物车</view>
<view class="menu-item p-2" @click="handleMenu('index')">运单列表</view>
<view class="menu-item p-2" @click="handleMenu('index')">收藏列表</view>
</view>
</view>
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
showMenu: false
}
},
computed: {
...mapState({
menuButtonInfo: state => state.systemInfo.menuButtonInfo,
systemInfo: state => state.systemInfo.systemInfo
}),
menuSty() {
const menuButtonInfo = this.menuButtonInfo
const systemInfo = this.systemInfo
const left = systemInfo.windowWidth - menuButtonInfo.right
const top = menuButtonInfo.bottom - menuButtonInfo.height
return `width: ${menuButtonInfo.width}px;height: ${menuButtonInfo.height}px;left: ${left}px;top: ${top}px;`
}
},
created() {
console.log(this.menuButtonInfo)
console.log(this.systemInfo)
},
methods: {
back() {
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.menu-wrap {
position: fixed;
z-index: 999;
border-radius: 48rpx;
border: 2rpx solid #fff;
background-color: red;
transform: scale(0.8);
.menu-main {
box-sizing: border-box;
height: 100%;
}
.menu-item_wrap {
position: relative;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 15rpx 0rpx rgba(148, 148, 148, 0.21);
border-radius: 10rpx;
// margin-left: 30rpx;
&::before {
content: '';
position: absolute;
width: 0;
height: 0;
border-right: 15rpx solid transparent;
border-left: 15rpx solid transparent;
border-bottom: 15rpx solid #FFFFFF;
left: 75%;
transform: translateX(-75%);
top: -14rpx;
border-right-width: 8px;
border-right-style: solid;
border-right-color: transparent;
border-left-width: 8px;
border-left-style: solid;
border-left-color: transparent;
border-bottom-width: 8px;
border-bottom-style: solid;
border-bottom-color: #fff;
}
.menu-item {
border-bottom: 1rpx solid red;
&:last-child{
border-bottom: none;
}
}
}
}
</style>
This diff is collapsed.
<template>
<view class="w-100">
<view class="font-bold font-36 p-2">{{title}}</view>
<view class="w-100 flex j-start a-center flex-wrap">
<view
class="item mr-2"
v-for="item in list"
:key="item"
<view class="font-bold font-36 px-3 pb-2">{{title}}</view>
<view class="list-wrap w-100 flex j-start a-center flex-wrap">
<navigator
class="list-item mb-3 ml-3"
hover-class="none"
v-for="(item, idx) in list"
:key="idx"
:url="'/pages/goods/detail?goods_id=' + item.goods_id"
>
111
</view>
<image
class="goods_cover w-100"
:src="baseUrl + '/' + item.goods_thumb"
mode="aspectFit"
/>
<view class="goods-info flex flex-column j-between">
<view class="title font-28 my-1">{{item.goods_name}}</view>
<view class="w-100 flex j-between a-center mt-1 mb-2">
<view class="flex j-start a-center">
<price
:is_inquiry="item.is_inquiry"
:price="item.shop_price"
/>
<text class="primaryColor font-28">{{item.least_str}}</text>
</view>
<image
class="cart-btn"
@click.stop="handlePop(item)"
src="/static/images/common/icon-cart.png"
mode="aspectFit"
/>
</view>
</view>
</navigator>
</view>
</view>
</template>
<script>
import price from '@/components/price/index.vue'
import { goodsSku } from '@/apis/goods.js'
import { baseUrl } from '@/config/index.js'
export default {
props: {
title: {
......@@ -24,15 +51,75 @@ export default {
type: Array,
default: () => []
}
},
components: {
price
},
data() {
return {
baseUrl
}
},
methods: {
async handlePop(goods) {
try{
uni.showLoading({
title: '加载中...',
mask: true
})
const { status, data } = await goodsSku(goods.goods_id)
if(status) {
console.log(data)
if(!data) return this.$toast({title: '该商品没有规格'})
const params = {
goodsInfo: {
cover: `${this.baseUrl}/${goods.goods_thumb}`,
title: goods.goods_name,
is_inquiry: goods.is_inquiry,
unit: goods.goods_unit
},
skuData: data
}
this.$emit('purchase', params)
}
uni.hideLoading()
}catch(e){
console.log(e)
uni.hideLoading()
//TODO handle the exception
}
}
}
}
</script>
<style lang="scss" scoped>
.item {
box-sizing: border-box;
width: 320rpx;
height: 375rpx;
border: 1rpx solid #ccc;
.list-wrap {
.list-item {
box-sizing: border-box;
width: 330rpx;
height: 490rpx;
background-color: $white;
border-radius: 8rpx;
.goods_cover {
height: 330rpx;
}
.goods-info {
@include borderBox(0, 20rpx);
height: 160rpx;
.title {
@include text-ellipsis(2)
}
.cart-btn {
width: 34rpx;
height: 32rpx;
padding: 0 20rpx;
}
}
}
}
</style>
import { searchGoods } from '@/apis/goods.js'
import { homeCategory } from '@/apis/category.js'
const searchParams = {
sort: 1, // 1综合优先 2销量优先 3价格升序 4价格降序
keywords: ''
}
/**
* @desc 除几个推荐商品外,其他商品使用搜索接口综合(sort = 1, keywords='')查询
* searchList 是一个二维数组,插入下一页的时候不合并数组,只会插入数组
* 进入页面不会请求这个函数,只会在第一次触底的时候发送第一次请求
*/
async function searchData () {
try{
const searchRes = await this.loadmore.getList(searchParams, searchGoods)
if(searchRes.status) {
if(!searchRes.data.length) return
this.$set(this.searchList, this.searchList.length, searchRes.data)
}
}catch(e){
console.log(e)
}
}
async function getHomeCate() {
try{
const { status, data } = await homeCategory()
if(status) {
this.cate_data = data
if(this.checkShowAll(data)) {
this.searchData()
}
}
}catch(e){
console.log(e)
//TODO handle the exception
}
}
/**
* @desc 检查是否需要加载全部商品(综合商品);当有推荐的几个分类时,不加载这个综合商品
* @param {Object} Obj (cate_data)
*/
function checkShowAll(Obj) {
if(Obj === null) return true
const keysArr = Object.keys(Obj)
if(keysArr.length > 0 && keysArr.some(item => Obj[item] && Obj[item].length > 0)) {
return false
} else {
return true
}
}
export default {
searchData,
getHomeCate,
checkShowAll
}
\ No newline at end of file
This diff is collapsed.
import Validator from "@/utils/validate.js"
function phoneValidate() {
const phoneValidator = new Validator()
const form = this.form
phoneValidator.add(form.user, [{strategy: 'notEmpty', errorMsg: '手机号码不能为空'}, {strategy: 'isMobile', errorMsg: '手机号码格式不正确'}])
return phoneValidator.validate()
}
function smsValidate() {
const smsValidator = new Validator()
const form = this.form
smsValidator.add(form.phone, [{strategy: 'notEmpty', errorMsg: '手机号码不能为空'}, {strategy: 'isMobile', errorMsg: '手机号码格式不正确'}])
smsValidator.add(form.smsCode, [{strategy: 'notEmpty', errorMsg: '验证码不能为空'}])
smsValidator.add(form.user, [{strategy: 'notEmpty', errorMsg: '手机号码不能为空'}, {strategy: 'isMobile', errorMsg: '手机号码格式不正确'}])
smsValidator.add(form.yzm, [{strategy: 'notEmpty', errorMsg: '验证码不能为空'}])
return smsValidator.validate()
}
function accoutValidate() {
const smsValidator = new Validator()
const form = this.form
smsValidator.add(form.phone, [{strategy: 'notEmpty', errorMsg: '手机号码不能为空'}, {strategy: 'isMobile', errorMsg: '手机号码格式不正确'}])
smsValidator.add(form.password, [{strategy: 'notEmpty', errorMsg: '密码不能为空'}])
// 用户名不检验手机号码
if(form.lgtype === 2) {
smsValidator.add(form.user, [{strategy: 'notEmpty', errorMsg: '手机号码不能为空'}, {strategy: 'isMobile', errorMsg: '手机号码格式不正确'}])
} else if(form.lgtype === 3) {
smsValidator.add(form.user, [{strategy: 'notEmpty', errorMsg: '用户名不能为空'}])
}
smsValidator.add(form.pwd, [{strategy: 'notEmpty', errorMsg: '密码不能为空'}])
return smsValidator.validate()
}
async function loginCommon(params) {
params.openid = this.openid
this.login(params)
}
export default {
smsValidate,
accoutValidate
accoutValidate,
phoneValidate,
loginCommon
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<template>
<text class="text">立即支付剩余时间:{{time_text}}</text>
</template>
<script>
/**
* warning: 我没有通过页面生命周期处理onHide停止计时器
* 符合渲染的条件 一:在线支付 二: 订单待支付状态 通过改变这两个状态卸载组件
* 在列表页表页计时可能数组会很大,因为利用组件的方法,开启多个计时器,一般待支付我猜不会有很多,因此计时器不会有很多
*/
export default {
props: {
countdownNum: {
type: Number,
required: true
},
pauseTimer: { // 停止计时器 用在控制在onHide和onShow生命周期
type: Boolean,
default: false
},
params: {
type: Object,
default: () => {}
}
},
data() {
return {
time_text: '00:00:00'
}
},
created () {
if(this.countdownNum <= 0) return console.log("倒计时时间小于0")
this.start()
this.$once('hook:beforeDestroy', () => {
this.timer && clearInterval(this.timer)
this.timer = null
})
},
methods: {
start() {
let countdownNum = this.countdownNum
let h = 0
let m = 0
let s = 0
this.timer && clearInterval(this.timer)
this.timer = setInterval(() => {
if(countdownNum === 0) {
clearInterval(this.timer)
this.timer = null
this.$emit('timerEnd', this.params)
return
}
h = Math.floor(countdownNum/(60*60)%24) m = Math.floor(countdownNum/(60)%60) s = Math.floor(countdownNum%60) this.time_text = `${h > 9 ? h : '0' + h }:${m > 9 ? m : '0' + m }:${s > 9 ? s : '0' + s }`
countdownNum --
}, 1000)
}
}
}
</script>
<style lang="scss" scoped>
.text {
font-size: 20rpx;
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
.clear-btn::after {
display: inline-block;
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 48rpx;
height: 48rpx;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEQAAAAsCAMAAADrau63AAAA/FBMVEUAAAD/gID/gED/gCv/gED/cTn/ZjPuZjPvcDDyayjyZibzaC70byzrbCfsaC/wbCfwaS3rZyfsZSbsZiruaCfuZibsaCfrZSftZiftaCfuZSnuZyjrZijraCfsZynsZijtZSfsZibsZyjtZifsZifsZijtZiftZSbtZibtZibrZSjsZyfsZifrZSbrZifsZifsZSbsZifsZifrZSbrZibrZSfsZibsZSfrZSbsZifsZSbrZifrZSfsZSbrZifrZibrZSfsZifsZifsZibsZSbrZSbrZifsZifsZifsZSbsZibsZibsZSfrZSfrZifrZibsZSfsZifsZSbrZSbIJ2ATAAAAU3RSTlMAAgQGCAkKDxATFBYXGhshIjQ1Nzs8Qk5VVlhZWlteX2JrbXB2en1+f4yNlZaam56ho6Wmp6mtsLW5usPEyc3O0d/h4uPo6+zu7/Dx8vT19vn7/gAR9X4AAAHHSURBVEjHvVZnc8IwDIWyy96zYRQItEDZe4e9wf//v7QQQgA5Trjz9X2T9PxyViRLKpUk9L5MudUf73bjfqvM+vSql+HO9o7oAcde1v2KgiE+RFgM4waFErb8Dklil7cpkNClt4iIbVonpxHmkCy4MFHC2ECK0DBKa7hGSCFGLimNxAEpxiGBlVAX0EsoqKHGWxlD3NQYj93uYWobTLD89qyhqUPWOnUrdX1qDeN1zaOGtgk5Xcs9w9KFjKb2QaQKGZWn72gqkFO9J7Aw3tGAG3cgixXDgROILs0w9+YloJ0CQtC5h59ICgcj39mY6WokIW/vvNb6BMYW15QFVmdrzlzTv4DMCd8BRUwNlPhTjGAHebuEoRbPAT+uHEOXM6aZYK/4FIVwXP8fcYoL8Df9FB0ffPZw3KlJVcM2hvVy5kd05C4OK5ZcI4rkREeWKEK6TkR0xIjXISXWvBLsmYmYWOIvDgo2I/OLicXGzC89EJAtNmLZv8e+chGzfNnTaUA6TwGdR4nO80jloZYcGVGvw+GNKhwZdIYXnTFKaaDTWS3O3a9kyYnIrlus3LrF6v5n8aO0glJahm9reaU94PZ7btCuZEhr+S9R2SzMt+mqIQAAAABJRU5ErkJggg==);
background-position: 0 0;
background-size: 100% 100%;
}
\ No newline at end of file
@font-face {
font-family: "iconfont"; /* Project id 2637147 */
src: url('data:application/octet-stream;base64,d09GMgABAAAAAAKAAAsAAAAABnQAAAI0AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACCfgo4SgE2AiQDDAsIAAQgBYRtB0obuAURFYxLsh8FbuwMKzUP5495tVrkFKXq/zmC59fSefsXLkyuSBIIFBGrKoFCkk6FSyuBXKovADY3Q4MxEYolOV/8L18gKaHzQn77/N87/iOgLJrXspzW2vZ/+s/DwIomUIB7UlFkJZJ5KtM1wEzsW58RaDTHYtlKs3Gn1jP2yjmDcmFn0PDjDB8/qGbk5HI0a0K5dWf5OsYLspfZKF4V348/5kWNTJGEd209tuqIj99bv7elB/UH9qQxD64T4L4MBRJmICd2L9e2SmJKnDTGchMwORd8b6vXv7dmAfFpSUb8dTG3GUxBPeN7a6Ii+N62RwYSKLuNEt1CwJPHIqWb/1u3b95a6sHS3AMsTVUAzA4+D46P7m9b+L/W7OwZq5sVRbX+oCbBUXs2FjCjpoaM4OVJ+ZQu4QgkTlTIMDRGUl2Y6vTtuKNncyuhpudAojLSIKmZQOWiGSg0WYBSzRI0mm7N/iZdLkkib8A0Twmh3XtkWn1A0u4LlYu+otDrH0rtkdBod3Sd2AQwKbhxxSW0ihssX+A1J4qDWpf8C7pnsNI2FtIHyslFGNq+35wxoVyx5ny5UZWAJEcwdB+GkKFIPnDVdlctU9fR1JvaNceqtkLQKm5g+QJec6Ksu9aDz1/QPYOVBaKr/kA5eXwwaPUbqNmWNhG/8sr5ciNVAiQ5AkPTMIQMyvS0A1dt7QcqZdJF7WirrX3eEf/vCDQKf5oiixS5zss2HWzzh5NbkAnT0PS9VQUAAA==');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-sanjiaoxingbeifen1:before {
content: "\e60e";
}
.icon-sanjiaoxing:before {
content: "\e60f";
}
This diff is collapsed.
This diff is collapsed.
......@@ -20,8 +20,17 @@
```
+ 小程序和vue页面生命周期顺序
- created => onLoad => onShow => mounted => onReady => onUnload => destroyed
+ 关于zIndex层级<font color="red">为防止层级规范</font>
- 一般层级(普通层级,如展示一些普通信息) zIndex范围 1-98
- 当前页面最高层级,如遮罩 zIndex 99
- 仅次于小程序原生弹窗 zIndex 100
#### 未完成
+ 请求状态码
+ 分页封装未处理页数
+ 封装数量递增/递减 分类树形递归 首页
\ No newline at end of file
#### warning
+ 2021/6/29,本日起的代码可能会引起不适,but all can run(效率和质量不会成正比关系)
#### unFinish, but not important
+ 自定义的导航栏的样式计算可以在vuex中处理(wxs计算)
+ 详情有个深拷贝的问题。暂时通过JSON.stringify()处理
+ 所有的价格都是通过toFixed会可能出现精度问题。一般发现不了
+ 确认订单页面要跳到地址列表页面选择
// wx537e892e36fbf79d
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment