代码提交
This commit is contained in:
47
.gitignore
vendored
Normal file
47
.gitignore
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
/unpackage/dist/dev
|
||||
/unpackage/dist/static
|
||||
/unpackage/dist/build/mp-alipay/
|
||||
/unpackage/dist/build/mp-weixin/
|
||||
/unpackage/dist/build/app-plus/
|
||||
/unpackage/dist/build/.automator
|
||||
/unpackage/cache/
|
||||
/unpackage/cache/apk
|
||||
/unpackage/release
|
||||
/unpackage/res
|
||||
/unpackage/resources
|
||||
# misc
|
||||
.DS_Store
|
||||
.cache
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
.tmp*
|
||||
.svn
|
||||
.tags
|
||||
*.sublime-*
|
||||
sftp-config.json
|
||||
logs
|
||||
*.log
|
||||
.idea*
|
||||
.yo-rc.json
|
||||
*.swo
|
||||
*.swp
|
||||
/deps
|
||||
yarn.lock
|
||||
dev-stats.json
|
||||
.vscode
|
||||
.idea
|
||||
*.hbuilderx
|
||||
.history
|
18
api/api.js
18
api/api.js
@ -144,3 +144,21 @@ const request = ['post', 'put', 'patch'].reduce((request, method) => {
|
||||
})
|
||||
|
||||
export default request
|
||||
|
||||
export const upload = (options)=>{
|
||||
const token = cookie.get('accessToken')
|
||||
return new Promise((resolve, reject)=>{
|
||||
uni.showLoading({title:'上传中'})
|
||||
uni.uploadFile({
|
||||
...options,
|
||||
header:{
|
||||
...options.headers,
|
||||
Authorization: 'Bearer ' + token.accessToken,
|
||||
},
|
||||
url:options.url?`${VUE_APP_API_URL}${options.url}`:VUE_APP_API_URL+'/member/user/update-avatar',
|
||||
success:(res)=>resolve(res),
|
||||
fail:(err)=>reject(err),
|
||||
complete:()=>uni.hideLoading()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -149,8 +149,8 @@ export function orderExpress(data) {
|
||||
export const wechatPay = (data) => api.post(`/order/pay`, data)
|
||||
|
||||
/**
|
||||
* 检查h5支付
|
||||
* 检查支付
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const checkH5Pay = (data) => api.post(`/order/pay/orderQuery`, data)
|
||||
export const checkPay = (data) => api.post(`/order/pay/orderQuery`, data)
|
||||
|
@ -41,3 +41,4 @@ export function updateMobile(data) {
|
||||
* @returns {*}
|
||||
*/
|
||||
export const updateUserInfo = (data) => api.put(`/member/user/update-nickname?nickname=${ data.nickname }&birthday=${ data.birthday }&sex=${ data.sex }`)
|
||||
|
||||
|
@ -10,6 +10,7 @@ import { computed, defineProps, ref, toRefs, unref, watch } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import { createAnimation } from "@/utils/utils";
|
||||
import { useScroll } from "@/hooks/useScroll";
|
||||
|
||||
const HEADER_HEIGHT = 40 // header高度
|
||||
|
||||
@ -66,10 +67,6 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: () => '#fff'
|
||||
},
|
||||
scrollTop: {
|
||||
type: Number,
|
||||
default: () => 0
|
||||
},
|
||||
propUp: {
|
||||
type: Boolean,
|
||||
default: () => true
|
||||
@ -94,7 +91,6 @@ const {
|
||||
textShadow,
|
||||
bgChangeByScroll,
|
||||
bgChangeColor,
|
||||
scrollTop,
|
||||
propUp,
|
||||
showRight,
|
||||
leftWidth
|
||||
@ -146,7 +142,7 @@ function getMenuInfo() {
|
||||
// scss全局变量
|
||||
const scssVarStyle = computed(() => {
|
||||
return {
|
||||
'--header-height': `${ HEADER_HEIGHT * 2 }rpx`
|
||||
'--header-height': `${ HEADER_HEIGHT }px`
|
||||
}
|
||||
})
|
||||
|
||||
@ -154,7 +150,7 @@ const scssVarStyle = computed(() => {
|
||||
const systemBarAreaStyle = computed(() => {
|
||||
return {
|
||||
width: '100%',
|
||||
height: `${ unref(heightInfo).safeAreaInsets.top * 2 }rpx`,
|
||||
height: `${ unref(heightInfo).statusBarHeight * 2 }rpx`,
|
||||
background: unref(systemBarAreaBg)
|
||||
}
|
||||
})
|
||||
@ -163,7 +159,7 @@ const systemBarAreaStyle = computed(() => {
|
||||
const headerAreaStyle = computed(() => {
|
||||
// 计算margin top
|
||||
// margin-top (导航条高度 - 胶囊高度) / 2 永远确保胶囊在header中央
|
||||
const marginTop = unref(menuInfo).height > 0 ? `-${ ((HEADER_HEIGHT - (unref(menuInfo).height)) / 2) * 2 }rpx` : 0
|
||||
const marginTop = unref(menuInfo).height > 0 ? `-${((HEADER_HEIGHT - unref(menuInfo).height))/2}px` : 0
|
||||
return {
|
||||
width: '100%',
|
||||
background: unref(headerAreaBg),
|
||||
@ -202,7 +198,7 @@ const scrollMaskStyle = computed(() => {
|
||||
|
||||
// 总高度
|
||||
const containerHeight = computed(() => {
|
||||
return (unref(heightInfo).safeAreaInsets.top + HEADER_HEIGHT) * 2
|
||||
return (unref(heightInfo).statusBarHeight + HEADER_HEIGHT)
|
||||
})
|
||||
|
||||
let animation
|
||||
@ -212,6 +208,7 @@ function doCreateAnimation() {
|
||||
animation = createAnimation(0, scrollEnd, 0, 1)
|
||||
}
|
||||
|
||||
const {scrollTop} = useScroll();
|
||||
watch(scrollTop, () => {
|
||||
if (!bgChangeByScroll.value) return
|
||||
if (!animation) doCreateAnimation()
|
||||
@ -289,7 +286,7 @@ onLoad(() => {
|
||||
<!-- 撑起 -->
|
||||
<view
|
||||
class="prop-up"
|
||||
:style="{height:`${containerHeight}rpx`}"
|
||||
:style="{height:`${containerHeight}px`}"
|
||||
v-if="propUp"
|
||||
></view>
|
||||
</view>
|
||||
|
@ -126,7 +126,7 @@ defineExpose({show, close})
|
||||
text-align: center;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border: 1rpx solid #ee6d46;
|
||||
border: 1px solid #ee6d46;
|
||||
background: #ee6d46;
|
||||
color: #fff;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ async function handleSubmit() {
|
||||
close()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
push({url: '/pages/payStatus/index?type=2'})
|
||||
push({url: '/pages/payStatus/index'},{data:{type:2}})
|
||||
toast({title: '支付失败了'})
|
||||
close()
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import { nextTick, ref, toRefs } from "vue";
|
||||
import UniPopup from "@/components/uniComponents/UPopup/uni-popup/uni-popup.vue";
|
||||
|
||||
/** some javascript code in here */
|
||||
const emit = defineEmits(['open', 'close'])
|
||||
const emit = defineEmits(['open', 'close', 'maskClick'])
|
||||
/**
|
||||
* @property {String} title 标题
|
||||
* @property {String} mode 模式
|
||||
@ -73,6 +73,10 @@ const handlePopupChange = (e) => {
|
||||
if (!e.show) emit('close')
|
||||
}
|
||||
|
||||
const handleMaskClick = (e) => {
|
||||
emit('maskClick')
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
close
|
||||
@ -86,6 +90,7 @@ defineExpose({
|
||||
:is-mask-click="isMaskClick"
|
||||
background-color="#fff"
|
||||
@change="handlePopupChange"
|
||||
@maskClick="handleMaskClick"
|
||||
class="y-popup"
|
||||
>
|
||||
<view class="popup_inner">
|
||||
|
192
components/Recommend/index.vue
Normal file
192
components/Recommend/index.vue
Normal file
@ -0,0 +1,192 @@
|
||||
<!--
|
||||
@name: 新品首发
|
||||
@author: kahu4
|
||||
@date: 2023-10-27 14:42
|
||||
@description:index
|
||||
@update: 2023-10-27 14:42
|
||||
-->
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { usePage } from "@/hooks";
|
||||
import { getProductList } from "@/api/product";
|
||||
import Empty from "@/components/Empty/index.vue"
|
||||
import ListLoadOver from "@/components/ListLoadOver/index.vue"
|
||||
import ListLoadLoading from "@/components/ListLoadLoading/index.vue"
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import emptyIcon from "@/static/icon/empty/收藏.png";
|
||||
import Goods from "@/components/goodsComponents/Goods.vue";
|
||||
import { computed, toRefs } from "vue";
|
||||
|
||||
const {refresh, dataList, loadend, loading, listEmpty} = usePage(getProductList)
|
||||
const {push} = useRouter()
|
||||
onLoad(() => {
|
||||
refresh()
|
||||
})
|
||||
const props = defineProps({
|
||||
more:{
|
||||
type:Boolean,
|
||||
default:()=>true
|
||||
}
|
||||
})
|
||||
const { more } = toRefs(props)
|
||||
|
||||
|
||||
const colList = computed(() => [
|
||||
{
|
||||
name: 'all',
|
||||
data: dataList.value.filter((item,index)=>index%2===0)
|
||||
},
|
||||
{
|
||||
name:'right',
|
||||
data: dataList.value.filter((item,index)=>index%2!==0)
|
||||
}
|
||||
])
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!--push({ url: '/pages/goodsList/goodsList' }-->
|
||||
<view class="recommend-container">
|
||||
<slot name="head">
|
||||
<view class="title-row">
|
||||
商品推荐
|
||||
</view>
|
||||
</slot>
|
||||
<view
|
||||
class="product-box"
|
||||
v-if="!listEmpty"
|
||||
>
|
||||
<!-- 分两列 后期瀑布流 -->
|
||||
<template
|
||||
v-for="col in colList"
|
||||
:key="col.name"
|
||||
>
|
||||
<view class="goods-col">
|
||||
<template
|
||||
v-for="item in col.data"
|
||||
:key="item.id"
|
||||
>
|
||||
<view class="product">
|
||||
<Goods
|
||||
:ratio="true"
|
||||
:goods="item"
|
||||
infoPadding="30rpx 10rpx"
|
||||
>
|
||||
<template #options>
|
||||
<view class="good-bottom">
|
||||
<view class="price">
|
||||
¥{{ item.price }}
|
||||
</view>
|
||||
<view class="sale">
|
||||
仅剩{{ item.stock }}件
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</Goods>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<Empty
|
||||
v-else
|
||||
:iconSrc="emptyIcon"
|
||||
>
|
||||
暂时没有商品推荐哦~
|
||||
</Empty>
|
||||
<!-- 加载中 -->
|
||||
<ListLoadLoading v-if="loading" />
|
||||
<!-- 加载完毕-->
|
||||
<ListLoadOver v-if="loadend" >
|
||||
<template v-if="more">
|
||||
<span @click="push({ url: '/pages/goodsList/goodsList' })">
|
||||
浏览更多商品
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
到底了~
|
||||
</template>
|
||||
</ListLoadOver>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<style
|
||||
scoped
|
||||
lang="scss"
|
||||
>
|
||||
.recommend-container{
|
||||
@include usePadding(30, 20);
|
||||
width: 100%;
|
||||
.title-row{
|
||||
width: 100%;
|
||||
font-size:32rpx;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
&::before,&::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 10%;
|
||||
height: 3rpx;
|
||||
border-radius: 5rpx;
|
||||
background: #333;
|
||||
top: 50%;
|
||||
transform: translate(0,50%);
|
||||
}
|
||||
&::before{
|
||||
left: 25%;
|
||||
}
|
||||
&::after{
|
||||
right: 25%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.product-box {
|
||||
margin-top: 30rpx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
//display: flex;
|
||||
//gap: 20rpx;
|
||||
|
||||
.goods-col {
|
||||
width: 49%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
flex-grow: 0;
|
||||
float: left;
|
||||
&:nth-child(2){
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
.product {
|
||||
flex-grow: 0;
|
||||
width: 100%;
|
||||
background: $white-color;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.good-bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 20rpx;
|
||||
|
||||
.price {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.sale {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -9,6 +9,7 @@
|
||||
import { toRefs } from "vue";
|
||||
import { GOODS_ITEM_TYPE } from "@/components/goodsComponents/utils/index.type";
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import { getRandom } from "@/utils/utils";
|
||||
|
||||
const props = defineProps({
|
||||
goods: {
|
||||
@ -21,17 +22,17 @@ const props = defineProps({
|
||||
},
|
||||
/** 图片比例 */
|
||||
ratio: {
|
||||
type: String,
|
||||
default: () => "1/1"
|
||||
type: [String,Boolean],
|
||||
default: () => '1/1'
|
||||
},
|
||||
infoPadding: {
|
||||
type: String,
|
||||
default: () => "0 0"
|
||||
},
|
||||
/** title是否换行 */
|
||||
titleNowrap: {
|
||||
titleWrap: {
|
||||
type: Boolean,
|
||||
default: () => true
|
||||
default: () => false
|
||||
},
|
||||
/** title 文字大小 rpx */
|
||||
titleSize: {
|
||||
@ -53,7 +54,7 @@ const {
|
||||
imgWidth,
|
||||
ratio,
|
||||
infoPadding,
|
||||
titleNowrap,
|
||||
titleWrap,
|
||||
titleSize,
|
||||
row,
|
||||
} = toRefs(props)
|
||||
@ -63,6 +64,7 @@ const {push} = useRouter()
|
||||
function toDetail() {
|
||||
push({url: '/pages/goodsDetail/goodsDetail'}, {data: {id: goods.value.id}})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -75,13 +77,13 @@ function toDetail() {
|
||||
class="goods-image"
|
||||
:style="{
|
||||
'width':imgWidth,
|
||||
'aspect-ratio':ratio
|
||||
'aspect-ratio': ratio===true?`${1/getRandom(1,1.3)}`:ratio
|
||||
}"
|
||||
>
|
||||
<image
|
||||
:src="goods.image"
|
||||
class="image"
|
||||
mode="aspectFill"
|
||||
:mode="ratio===true?'aspectFit':'aspectFill'"
|
||||
/>
|
||||
</view>
|
||||
<!-- good info -->
|
||||
@ -96,7 +98,7 @@ function toDetail() {
|
||||
<view
|
||||
:class="{
|
||||
'title-row':true,
|
||||
'nowrap': titleNowrap
|
||||
'nowrap': !titleWrap
|
||||
}"
|
||||
:style="{
|
||||
'font-size':`${titleSize}rpx`
|
||||
@ -136,7 +138,7 @@ function toDetail() {
|
||||
.title-row {
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
//padding: 14rpx 0;
|
||||
padding-bottom: 15rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<view>
|
||||
<view
|
||||
:class="['order', className]"
|
||||
:class="['order']"
|
||||
v-if="data"
|
||||
>
|
||||
|
||||
@ -119,7 +118,6 @@
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
@ -39,10 +39,10 @@
|
||||
</view>
|
||||
<view
|
||||
class="reply-pic flex flex-ai__center"
|
||||
v-if="data.pics && data.pics.length>0"
|
||||
v-if="data.pics && data.pics.filter(item=>!!item).length>0"
|
||||
>
|
||||
<template
|
||||
v-for="(pic,index) in data.pics"
|
||||
v-for="(pic,index) in data.pics.filter(item=>!!item)"
|
||||
:key="index"
|
||||
>
|
||||
<image
|
||||
@ -154,11 +154,12 @@ function doPreviewImage(current, urls) {
|
||||
|
||||
.reply-pic {
|
||||
gap: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
margin: 20rpx 0;
|
||||
flex-wrap: wrap;
|
||||
padding: 0;
|
||||
.image {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
width: 212rpx;
|
||||
height: 212rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -18,6 +18,9 @@ export const usePage = getPage => {
|
||||
// 分类ID
|
||||
const sid = ref('')
|
||||
|
||||
// 优惠券ID
|
||||
const couponId = ref('')
|
||||
|
||||
// 是否新品,不为空的字符串即可
|
||||
const news = ref('')
|
||||
|
||||
@ -45,6 +48,7 @@ export const usePage = getPage => {
|
||||
keyword: keyword.value,
|
||||
type: type.value,
|
||||
sid: sid.value,
|
||||
couponId: couponId.value,
|
||||
news: news.value,
|
||||
isIntegral: isIntegral.value,
|
||||
})
|
||||
@ -92,6 +96,7 @@ export const usePage = getPage => {
|
||||
listEmpty,
|
||||
news,
|
||||
sid,
|
||||
couponId,
|
||||
refresh: handleRefresh,
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +127,9 @@ export const useRouter = () => {
|
||||
function getParams(options) {
|
||||
if (typeof options !== 'object') return {}
|
||||
if (!options[PARAMS_KEY]) return {}
|
||||
// #ifdef MP-WEIXIN
|
||||
console.log(typeof options[PARAMS_KEY],options[PARAMS_KEY],decodeURIComponent(options[PARAMS_KEY]))
|
||||
// #endif
|
||||
return JSON.parse(decodeURIComponent(options[PARAMS_KEY]));
|
||||
}
|
||||
|
||||
|
15
hooks/useScroll.js
Normal file
15
hooks/useScroll.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { onPageScroll } from "@dcloudio/uni-app";
|
||||
import { onBeforeUnmount, ref } from "vue";
|
||||
const scrollTop = ref(0)
|
||||
|
||||
export function useScroll(){
|
||||
onPageScroll((e)=>{
|
||||
scrollTop.value = e.scrollTop
|
||||
})
|
||||
onBeforeUnmount(()=>{
|
||||
scrollTop.value = 0
|
||||
})
|
||||
return {
|
||||
scrollTop
|
||||
}
|
||||
}
|
@ -1,11 +1,9 @@
|
||||
<template>
|
||||
<layout>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="goBack"
|
||||
/>
|
||||
|
||||
<Header>
|
||||
{{ title }}
|
||||
</Header>
|
||||
|
||||
<view class="addressList">
|
||||
<template v-if=" main.address.length>0">
|
||||
@ -65,16 +63,18 @@
|
||||
您还没有新增地址~
|
||||
</Empty>
|
||||
</view>
|
||||
<div class="form-buttons">
|
||||
<uv-button
|
||||
round
|
||||
block
|
||||
type="primary"
|
||||
@tap="goCreateAddress"
|
||||
>
|
||||
新增地址
|
||||
</uv-button>
|
||||
</div>
|
||||
<view class="form-buttons">
|
||||
<view class="btn">
|
||||
<uv-button
|
||||
round
|
||||
block
|
||||
type="primary"
|
||||
@tap="goCreateAddress"
|
||||
>
|
||||
新增地址
|
||||
</uv-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</layout>
|
||||
</template>
|
||||
@ -87,6 +87,7 @@ import Empty from '@/components/Empty/index.vue'
|
||||
import emptyIcon from '@/static/icon/empty/地址.png'
|
||||
import { getAddressDel, } from '@/api/address'
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import Header from "@/components/Header/index.vue"
|
||||
|
||||
const {push, goBack} = useRouter()
|
||||
|
||||
@ -156,6 +157,8 @@ onLoad((option) => {
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
const handleAddressClick = async ({index}, data) => {
|
||||
if (index == 0) {
|
||||
uni.showModal({
|
||||
@ -302,12 +305,13 @@ const handleAddressClick = async ({index}, data) => {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.form-buttons :deep(.uv-button) {
|
||||
.form-buttons .btn {
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.address-default :deep(.uv-tags) {
|
||||
justify-content: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
@ -221,6 +221,7 @@ async function handleUnCollectSingle() {
|
||||
await unCollectSingle(toDeleteItem)
|
||||
await refresh()
|
||||
await toast({title: '删除成功'})
|
||||
toDeleteItem = undefined
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,14 +13,19 @@
|
||||
<view class="list-label w-158">
|
||||
收货地址
|
||||
</view>
|
||||
<view class="list-content">
|
||||
<city-select
|
||||
ref="cityselect"
|
||||
:defaultValue="defaultAddress"
|
||||
@callback="result"
|
||||
:items="main.areaList"
|
||||
></city-select>
|
||||
|
||||
<view
|
||||
class="list-content"
|
||||
@click="handleChooseAddress"
|
||||
>
|
||||
<template v-if="addressData.address.cityId">
|
||||
{{ addressData.address.province }} {{ addressData.address.city }} {{ addressData.address.district }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="chooise">
|
||||
点击选择
|
||||
<uv-icon name="arrow-right"></uv-icon>
|
||||
</span>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -34,7 +39,7 @@
|
||||
type="text"
|
||||
placeholder="请输入详细地址"
|
||||
v-model="addressData.detail"
|
||||
>
|
||||
/>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
@ -49,7 +54,7 @@
|
||||
type="text"
|
||||
placeholder="请输入姓名"
|
||||
v-model="addressData.realName"
|
||||
>
|
||||
/>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
@ -64,7 +69,7 @@
|
||||
type="number"
|
||||
placeholder="请输入电话"
|
||||
v-model="addressData.phone"
|
||||
>
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -89,37 +94,45 @@
|
||||
@click="onSave"
|
||||
></uv-button>
|
||||
</view>
|
||||
|
||||
<uv-picker
|
||||
ref="addressPickerRef"
|
||||
:columns="columns"
|
||||
keyName="name"
|
||||
@change="handlePickerChange"
|
||||
@confirm="handlePickerConfirm"
|
||||
></uv-picker>
|
||||
</layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { computed, nextTick, onMounted, ref, unref, watch } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { getAddressAddAndEdit, getAddressDel, } from '@/api/address'
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import { storeToRefs } from "pinia";
|
||||
import UvPicker from "@/uni_modules/uv-picker/components/uv-picker/uv-picker.vue";
|
||||
|
||||
const main = useMainStore()
|
||||
const {getParams, push, goBack} = useRouter()
|
||||
|
||||
|
||||
const areaList = ref(main.areaList)
|
||||
const {areaList, address} = storeToRefs(main)
|
||||
// const areaList = ref(main.areaList)
|
||||
const title = ref('')
|
||||
|
||||
const editId = ref('')
|
||||
const defaultAddress = ref('')
|
||||
|
||||
const addressData = ref({
|
||||
"realName": '',
|
||||
"postCode": '',
|
||||
"isDefault": false,
|
||||
"detail": '',
|
||||
"phone": '',
|
||||
"cityId": '',
|
||||
"city": '',
|
||||
"district": '',
|
||||
"province": '',
|
||||
realName: undefined,
|
||||
phone: undefined,
|
||||
detail: undefined,
|
||||
isDefault: undefined,
|
||||
address: {
|
||||
cityId: undefined,
|
||||
city: undefined,
|
||||
district: undefined,
|
||||
province: undefined,
|
||||
}
|
||||
});
|
||||
|
||||
const isDefaultList = ref([])
|
||||
@ -188,9 +201,9 @@ const onSave = async () => {
|
||||
uni.hideLoading()
|
||||
main.restAddress()
|
||||
if (actionType.value == 'select') {
|
||||
push({url: '/pages/address/address'}, {data: {type: 'select'}})
|
||||
push({url: '/pages/address/address'}, {data: {type: 'select'},type:'redirectTo'})
|
||||
} else {
|
||||
push({url: '/pages/address/address'})
|
||||
goBack()
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error, 'err')
|
||||
@ -218,38 +231,72 @@ const result = (values) => {
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => main.areaList, (next) => {
|
||||
areaList.value = next
|
||||
const addressPickerRef = ref()
|
||||
const provinces = ref([])
|
||||
const citys = ref([])
|
||||
const areas = ref([])
|
||||
const pickerValue = ref([0, 0, 0])
|
||||
const defaultValue = ref([0, 0, 0])
|
||||
|
||||
const columns = computed(() => {
|
||||
return [
|
||||
provinces.value, citys.value, areas.value
|
||||
]
|
||||
})
|
||||
|
||||
watch(() => main.address, (next) => {
|
||||
let data = next.filter(item => item.id == editId.value)[0]
|
||||
if (!data) return
|
||||
addressData.value = {
|
||||
realName: data.realName,
|
||||
phone: data.phone,
|
||||
detail: data.detail,
|
||||
isDefault: data.isDefault ? 1 : 0,
|
||||
address: {
|
||||
cityId: data.cityId,
|
||||
district: data.district,
|
||||
province: data.province,
|
||||
city: data.city
|
||||
}
|
||||
function handleSetDefaultColumns() {
|
||||
console.log(addressPickerRef.value)
|
||||
pickerValue.value[0] = provinces.value.findIndex((item, index) => index === defaultValue.value[0])
|
||||
citys.value = provinces.value[pickerValue.value[0]].children || []
|
||||
pickerValue.value[1] = citys.value.findIndex((item, index) => index === defaultValue.value[1])
|
||||
areas.value = citys.value[pickerValue.value[1]].children || []
|
||||
pickerValue.value[2] = areas.value.findIndex((item, index) => index === defaultValue.value[2])
|
||||
// 重置下位置
|
||||
// addressPickerRef.value.setColumnValues(0,provinces.value)
|
||||
// addressPickerRef.value.setColumnValues(1,citys.value)
|
||||
// addressPickerRef.value.setColumnValues(2,areas.value)
|
||||
nextTick(() => {
|
||||
addressPickerRef.value.setIndexs([pickerValue.value[0], pickerValue.value[1], pickerValue.value[2]], true);
|
||||
console.log('设置完毕')
|
||||
})
|
||||
}
|
||||
|
||||
function handlePickerChange(e) {
|
||||
const {columnIndex, index, indexs} = e
|
||||
// 改变了省
|
||||
if (columnIndex === 0) {
|
||||
citys.value = provinces.value[index]?.children || []
|
||||
areas.value = citys.value[0]?.children || []
|
||||
addressPickerRef.value.setIndexs([index, 0, 0], true)
|
||||
} else if (columnIndex === 1) {
|
||||
areas.value = citys.value[index]?.children || []
|
||||
addressPickerRef.value.setIndexs(indexs, true)
|
||||
}
|
||||
isDefaultList.value = data.isDefault ? ['isDefault'] : [],
|
||||
defaultAddress.value = {
|
||||
province: {
|
||||
name: data.province
|
||||
},
|
||||
city: {
|
||||
name: data.city
|
||||
},
|
||||
district: {
|
||||
name: data.district
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function handlePickerConfirm(e) {
|
||||
const {indexs, value} = e
|
||||
defaultValue.value = indexs
|
||||
addressData.value.address = {
|
||||
province: value[0].name || '',
|
||||
city: value[1].name || '',
|
||||
district: value[2].name || '',
|
||||
cityId: value[1].id,
|
||||
}
|
||||
}
|
||||
|
||||
function handleFindDefault(data) {
|
||||
const provinceIndex = areaList.value.findIndex(item => item.name === data.province);
|
||||
const cityIndex = areaList.value[provinceIndex].children.findIndex(item => item.name === data.city);
|
||||
const areasIndex = areaList.value[provinceIndex].children[cityIndex].children.findIndex(item => item.name === data.district);
|
||||
defaultValue.value = [provinceIndex, cityIndex, areasIndex]
|
||||
}
|
||||
|
||||
function handleChooseAddress() {
|
||||
provinces.value = areaList.value
|
||||
handleSetDefaultColumns()
|
||||
unref(addressPickerRef).open()
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
const params = getParams(options)
|
||||
@ -260,7 +307,7 @@ onLoad(async (options) => {
|
||||
if (id) {
|
||||
editId.value = id
|
||||
title.value = '编辑地址'
|
||||
let data = main.address.filter(item => item.id == id)[0]
|
||||
let data = address.value.filter(item => item.id == id)[0]
|
||||
if (!data) return
|
||||
addressData.value = {
|
||||
realName: data.realName,
|
||||
@ -274,24 +321,15 @@ onLoad(async (options) => {
|
||||
province: data.province,
|
||||
}
|
||||
}
|
||||
defaultAddress.value = {
|
||||
province: {
|
||||
name: data.province
|
||||
},
|
||||
city: {
|
||||
name: data.city
|
||||
},
|
||||
district: {
|
||||
name: data.district
|
||||
}
|
||||
}
|
||||
// 设置默认选择
|
||||
handleFindDefault(data)
|
||||
isDefaultList.value = data.isDefault ? ['isDefault'] : []
|
||||
} else {
|
||||
title.value = '新增地址'
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@ -306,4 +344,9 @@ onLoad(async (options) => {
|
||||
.w-158 {
|
||||
flex: 0 0 158rpx;
|
||||
}
|
||||
|
||||
.chooise {
|
||||
@include useFlex(space-between, center);
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
|
@ -39,10 +39,8 @@ const getCoupon = async () => {
|
||||
});
|
||||
}
|
||||
|
||||
const goToProduct = () => {
|
||||
push({
|
||||
url: '/pages/goodsList/goodsList'
|
||||
})
|
||||
const goToProduct = (coupons) => {
|
||||
push({url: '/pages/goodsList/goodsList'},{data: {couponId: coupons.id}})
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -71,7 +69,7 @@ const goToProduct = () => {
|
||||
<!-- button -->
|
||||
<view v-if="type === 'select'">
|
||||
<view class="button" v-if="tabType === 0">
|
||||
<span @click="goToProduct">去使用</span>
|
||||
<span @click="goToProduct(coupons)">去使用</span>
|
||||
</view>
|
||||
<view class="button disable" v-if="tabType === 1">
|
||||
<span>已使用</span>
|
||||
@ -90,8 +88,7 @@ const goToProduct = () => {
|
||||
scoped
|
||||
lang="scss"
|
||||
>
|
||||
.coupon-item{
|
||||
margin-bottom: 30rpx;
|
||||
.coupon-item {
|
||||
width: 100%;
|
||||
aspect-ratio: 682/176;
|
||||
background: url("@/static/background/coupon-bg.png") no-repeat ;
|
||||
|
@ -17,6 +17,7 @@
|
||||
<uv-line color="#E6E6E6"></uv-line>
|
||||
<view class="evaluate-content">
|
||||
<uv-textarea
|
||||
border="none"
|
||||
v-model="comment"
|
||||
placeholder="请填写您遇到的问题,这将帮助我们为您提供更好的服务"
|
||||
></uv-textarea>
|
||||
|
@ -223,6 +223,7 @@ async function handleUnCollectSingle() {
|
||||
await unFootprintSingle(toDeleteItem)
|
||||
await refresh()
|
||||
await toast({title: '删除成功'})
|
||||
toDeleteItem = undefined
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,7 @@
|
||||
>
|
||||
<uv-vtabs
|
||||
:list="categoryData"
|
||||
:hdHeight="`${headerRef&&headerRef.containerHeight || 0}rpx`"
|
||||
:hdHeight="`${headerRef&&headerRef.containerHeight || 0}px`"
|
||||
>
|
||||
<template
|
||||
v-for="(item, index) in categoryData"
|
||||
|
@ -1,17 +1,10 @@
|
||||
<template>
|
||||
<layout class="goodsDetail">
|
||||
<!-- <uv-navbar-->
|
||||
<!-- fixed-->
|
||||
<!-- :safeAreaInsetTop="true"-->
|
||||
<!-- title=""-->
|
||||
<!-- bg-color="transparent"-->
|
||||
<!-- @leftClick="goBack"-->
|
||||
<!-- />-->
|
||||
<view :style="computedHeightStyle"></view>
|
||||
<Header
|
||||
ref="headerRef"
|
||||
:propUp="false"
|
||||
:scrollTop="scrollTop"
|
||||
>
|
||||
|
||||
</Header>
|
||||
<view v-if="detailData">
|
||||
<swiper
|
||||
@ -28,7 +21,7 @@
|
||||
<image
|
||||
class="image"
|
||||
:src="item"
|
||||
mode="widthFix"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
</swiper-item>
|
||||
@ -44,9 +37,9 @@
|
||||
</view>
|
||||
<view
|
||||
class="goodsDetail-price goodsDetail-price-original"
|
||||
v-if="(storeAttr&& storeAttr.otPrice) || (storeInfo&&storeInfo.otPrice)"
|
||||
v-if="storeAttr && storeInfo"
|
||||
>
|
||||
¥{{ storeAttr.otPrice || storeInfo.otPrice }}
|
||||
¥{{ storeAttr&&storeAttr.otPrice || storeInfo&&storeInfo.otPrice }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="goodsDetail-storeName">{{ storeInfo.storeName }}</view>
|
||||
@ -115,7 +108,10 @@
|
||||
|
||||
|
||||
<view class="card full">
|
||||
<view class="card-head" :style="{borderBottom:detailData.replyCount<=0?'none':'1rpx solid #e6e6e6'}">
|
||||
<view
|
||||
class="card-head"
|
||||
:style="{borderBottom:detailData.replyCount<=0?'none':'1rpx solid #e6e6e6'}"
|
||||
>
|
||||
<view class="card-title">商品评价({{ detailData.replyCount }})</view>
|
||||
<view
|
||||
class="card-more"
|
||||
@ -256,7 +252,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, unref } from 'vue'
|
||||
import { computed, onMounted, ref, unref } from 'vue'
|
||||
import { collectSingle, getProductDetail, unCollectSingle } from '@/api/product'
|
||||
import { getCartAdd, getCartCount } from '@/api/cart'
|
||||
import { onLoad, onPageScroll } from '@dcloudio/uni-app'
|
||||
@ -265,6 +261,7 @@ import { useInterface } from "@/hooks/useInterface";
|
||||
import Header from '@/components/Header/index.vue'
|
||||
import GoodCouponSelect from "@/components/good-coupon-select/good-coupon-select.vue";
|
||||
import UvIcon from "@/uni_modules/uv-icon/components/uv-icon/uv-icon.vue";
|
||||
import { useScroll } from "@/hooks/useScroll";
|
||||
|
||||
const {push, getParams, pushToTab, goBack} = useRouter();
|
||||
const {toast} = useInterface()
|
||||
@ -279,6 +276,16 @@ const cardCount = ref(null)
|
||||
const selectAttrPanel = ref(false)
|
||||
const selectCouponPanel = ref(false)
|
||||
const selectCoupon = ref(false)
|
||||
const headerRef = ref()
|
||||
|
||||
const computedHeightStyle = computed(() => {
|
||||
const style = {width: '100 %', height: 0,background:'#f5f5f5'}
|
||||
if (!headerRef.value || !headerRef.value.heightInfo) return style
|
||||
return {...style, height: `${ headerRef.value.heightInfo.statusBarHeight }px`}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
})
|
||||
|
||||
const handleGetDetail = async (id) => {
|
||||
try {
|
||||
@ -312,7 +319,7 @@ onLoad((options) => {
|
||||
handleGetDetail(params.id)
|
||||
handleGetCartCount(params.id)
|
||||
})
|
||||
|
||||
useScroll()
|
||||
const goToService = () => {
|
||||
toast({title: '😒敬请期待😒'})
|
||||
}
|
||||
@ -407,10 +414,7 @@ const handleGetCartCount = async () => {
|
||||
cardCount.value = count.count
|
||||
}
|
||||
|
||||
const scrollTop = ref(0)
|
||||
onPageScroll((e) => {
|
||||
scrollTop.value = e.scrollTop
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
@ -743,7 +747,9 @@ onPageScroll((e) => {
|
||||
|
||||
// ======================= 👇 kahu ===
|
||||
.row-context {
|
||||
margin: 30rpx 0 ;
|
||||
margin: 30rpx 0;
|
||||
|
||||
|
||||
.label-row {
|
||||
@include useFlex(space-between, center);
|
||||
@include usePadding(30, 20);
|
||||
@ -775,6 +781,20 @@ onPageScroll((e) => {
|
||||
.value {
|
||||
@include useFlex(flex-end, center);
|
||||
flex-shrink: 0;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
.swiper-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.image {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,13 +76,14 @@ import ListLoadLoading from "@/components/ListLoadLoading/index.vue"
|
||||
import emptyIcon from "@/static/icon/empty/收藏.png"
|
||||
|
||||
const {getParams, goBack} = useRouter()
|
||||
const {keyword, refresh, sid, dataList, loadend, loading, listEmpty} = usePage(getProductList)
|
||||
const {keyword, refresh, sid, couponId, dataList, loadend, loading, listEmpty} = usePage(getProductList)
|
||||
|
||||
|
||||
onLoad((options) => {
|
||||
const params = getParams(options)
|
||||
keyword.value = params.keyword || ''
|
||||
sid.value = params.sid || ''
|
||||
couponId.value = params.couponId || ''
|
||||
refresh()
|
||||
})
|
||||
|
||||
|
@ -6,83 +6,39 @@
|
||||
@update: 2023-10-27 14:42
|
||||
-->
|
||||
<script setup>
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { usePage } from "@/hooks";
|
||||
import { getProductList } from "@/api/product";
|
||||
import Empty from "@/components/Empty/index.vue"
|
||||
import ListLoadOver from "@/components/ListLoadOver/index.vue"
|
||||
import ListLoadLoading from "@/components/ListLoadLoading/index.vue"
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
|
||||
const {refresh, dataList, loadend, loading, listEmpty} = usePage(getProductList)
|
||||
const {push} = useRouter()
|
||||
onLoad(() => {
|
||||
refresh()
|
||||
})
|
||||
|
||||
|
||||
import Recommend from "@/components/Recommend/index.vue";
|
||||
import UvIcon from "@/uni_modules/uv-icon/components/uv-icon/uv-icon.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<blank size="15"></blank>
|
||||
|
||||
<activity
|
||||
title="商品推荐"
|
||||
more="查看更多"
|
||||
@moreClick="push({ url: '/pages/goodsList/goodsList' })"
|
||||
>
|
||||
<view class="card goods-row">
|
||||
<template v-if="!listEmpty">
|
||||
<uv-grid
|
||||
:border="false"
|
||||
:col="2"
|
||||
:gutter="10"
|
||||
>
|
||||
<uv-grid-item
|
||||
v-for="(item, index) in dataList"
|
||||
:key="index"
|
||||
>
|
||||
<goods
|
||||
class="item"
|
||||
link
|
||||
card
|
||||
:data="item"
|
||||
:storeName="item.storeName"
|
||||
:price="item.price"
|
||||
:stock="true"
|
||||
>
|
||||
</goods>
|
||||
</uv-grid-item>
|
||||
</uv-grid>
|
||||
</template>
|
||||
<Empty
|
||||
v-else
|
||||
:iconSrc="emptyIcon"
|
||||
>
|
||||
这里空空如也~
|
||||
</Empty>
|
||||
<!-- 加载中 -->
|
||||
<ListLoadLoading v-if="loading" />
|
||||
<!-- 加载完毕-->
|
||||
<ListLoadOver v-if="loadend" />
|
||||
</view>
|
||||
|
||||
</activity>
|
||||
<Recommend ref="recommendRef" :more="false">
|
||||
<template #head>
|
||||
<view class="head flex flex-ai__center flex-jc__sb">
|
||||
<view class="left">
|
||||
商品推荐
|
||||
</view>
|
||||
<view class="right flex flex-ai__center flex-jc__end">
|
||||
查看更多
|
||||
<uv-icon name="arrow-right" color="#999" size="14" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</Recommend>
|
||||
</template>
|
||||
|
||||
<style
|
||||
scoped
|
||||
lang="scss"
|
||||
>
|
||||
@import "@/style/main.scss";
|
||||
|
||||
.goods-row {
|
||||
@include usePadding(20, 20);
|
||||
border-radius: 15rpx;
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
margin: 0 10rpx;
|
||||
.head{
|
||||
margin-top: 20rpx;
|
||||
.left{
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.right{
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -2,7 +2,6 @@
|
||||
<view class="home-container">
|
||||
<view class="header-row">
|
||||
<Header
|
||||
:scroll-top="scrollTop"
|
||||
:left-width="140"
|
||||
@animation="handleHeaderAnimation"
|
||||
>
|
||||
@ -19,19 +18,14 @@
|
||||
<view
|
||||
class="search-col"
|
||||
:style="searchShadow"
|
||||
@click="toSearch"
|
||||
@tap="toSearch"
|
||||
>
|
||||
<uv-icon
|
||||
name="search"
|
||||
size="26"
|
||||
size="40rpx"
|
||||
/>
|
||||
<view class="search-input">
|
||||
<input
|
||||
type="text"
|
||||
disabled
|
||||
placeholder="搜索商品"
|
||||
@click="toSearch"
|
||||
/>
|
||||
搜索商品
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@ -68,7 +62,7 @@
|
||||
|
||||
<!-- 热门直播 -->
|
||||
<Live v-if="false" />
|
||||
<Recommend ref="recommendRef" />
|
||||
<Recommend />
|
||||
</template>
|
||||
<!-- h5 tabbar 底部 -->
|
||||
<view class="h5-tabbar-height"></view>
|
||||
@ -89,8 +83,9 @@ import Group from './components/Group/index.vue'
|
||||
import Live from './components/Live/index.vue'
|
||||
import NewProduct from './components/NewProduct/index.vue'
|
||||
import Seckill from './components/Seckill/index.vue'
|
||||
import Recommend from './components/Recommend/index.vue'
|
||||
import Recommend from "./components/Recommend/index.vue";
|
||||
import UvIcon from "@/uni_modules/uv-icon/components/uv-icon/uv-icon.vue";
|
||||
import { useScroll } from "@/hooks/useScroll";
|
||||
|
||||
const main = useMainStore()
|
||||
const {push} = useRouter()
|
||||
@ -118,19 +113,18 @@ function handleHeaderAnimation(numericalValue) {
|
||||
}
|
||||
}
|
||||
|
||||
const scrollTop = ref(0)
|
||||
/*const scrollTop = ref(0)
|
||||
onPageScroll((e) => {
|
||||
scrollTop.value = e.scrollTop
|
||||
})
|
||||
})*/
|
||||
|
||||
onLoad(() => {
|
||||
main.init()
|
||||
doGetHomeData()
|
||||
})
|
||||
|
||||
onReachBottom(() => {
|
||||
unref(recommendRef).onReachBottom && unref(recommendRef).onReachBottom();
|
||||
})
|
||||
useScroll()
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@ -153,13 +147,16 @@ onReachBottom(() => {
|
||||
.search-col {
|
||||
@include useFlex(flex-start, center);
|
||||
@include usePadding(30, 15);
|
||||
width: 100%;
|
||||
width: 320rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 50rpx;
|
||||
background: $white-color;
|
||||
margin-left: 50rpx;
|
||||
|
||||
.search-input {
|
||||
margin-left: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,4 +166,6 @@ onReachBottom(() => {
|
||||
.goods-row {
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
@ -6,19 +6,96 @@
|
||||
@update: 2023-11-08 16:20
|
||||
-->
|
||||
<script setup>
|
||||
import wechat from '@/static/icon/login/wechat.png'
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import { loginMethods } from "@/pages/login/index.data";
|
||||
import { wxLogin } from "@/utils/wechatUtils";
|
||||
import { error } from "@/uni_modules/uv-ui-tools/libs/function";
|
||||
import { nextTick, ref } from "vue";
|
||||
import { useInterface } from "@/hooks/useInterface";
|
||||
import { privacyAgreementUrl, userAgreementUrl, weixinLogin } from "@/api/auth";
|
||||
import { useMainStore } from "@/store/store";
|
||||
import { afterLogin } from "@/utils";
|
||||
|
||||
const {toast, loading, hideLoading} = useInterface()
|
||||
const {goBack, push} = useRouter()
|
||||
const mainStore = useMainStore()
|
||||
|
||||
function toLogin(loginMethod) {
|
||||
if (loginMethod.type === 0) {
|
||||
// 微信登录
|
||||
console.log('微信登录')
|
||||
} else {
|
||||
async function toLogin(loginMethod) {
|
||||
push({url: '/pages/login/index', animationType: 'slide-in-right'}, {data: {...loginMethod}})
|
||||
}
|
||||
|
||||
// ============================= 微信登录相关
|
||||
const code = ref('') // logingCode必须比getPhoneNumber的code先获取
|
||||
|
||||
async function getCode() {
|
||||
loading({
|
||||
title: '登陆中...'
|
||||
})
|
||||
try {
|
||||
code.value = await wxLogin();
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
toast('获取code失败')
|
||||
hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
async function getPhoneNumber(e) {
|
||||
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
||||
console.error(e)
|
||||
hideLoading()
|
||||
toast({title: '登录失败'})
|
||||
}
|
||||
try {
|
||||
const phoneCode = e.detail.code
|
||||
const res = await weixinLogin({
|
||||
phoneCode,
|
||||
loginCode: code.value
|
||||
});
|
||||
if (res) {
|
||||
await mainStore.setAccessToken(res)
|
||||
afterLogin()
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
toast({title: '登录失败'})
|
||||
} finally {
|
||||
hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const privacyPolicy = ref([]) // 协议双向绑定
|
||||
|
||||
const isPrivacyError = ref(false) // 未勾选协议
|
||||
|
||||
/**
|
||||
* 检查是否勾选协议
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function checkPrivacy() {
|
||||
const flag = privacyPolicy.value.length > 0
|
||||
if (!flag) {
|
||||
toast({title: '请先阅读并同意用户协议和隐私政策'})
|
||||
isPrivacyError.value = true
|
||||
setTimeout(() => {
|
||||
isPrivacyError.value = false
|
||||
}, 1000)
|
||||
}
|
||||
return flag
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转协议
|
||||
* @param type
|
||||
*/
|
||||
function toAgreement(type) {
|
||||
const urls = [userAgreementUrl, privacyAgreementUrl]
|
||||
push({url: '/pages/webview/index'}, {data: {src: urls[type]}})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -37,6 +114,32 @@ function toLogin(loginMethod) {
|
||||
</view>
|
||||
|
||||
<view class="button-group">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view
|
||||
v-if="privacyPolicy.length<=0"
|
||||
class="button animation-button disabled"
|
||||
@click="checkPrivacy"
|
||||
>
|
||||
<image
|
||||
class="icon"
|
||||
:src="wechat"
|
||||
/>
|
||||
微信快捷登录
|
||||
</view>
|
||||
<button
|
||||
v-else
|
||||
class="button animation-button"
|
||||
open-type="getPhoneNumber"
|
||||
@getphonenumber="getPhoneNumber"
|
||||
@click="getCode"
|
||||
>
|
||||
<image
|
||||
class="icon"
|
||||
:src="wechat"
|
||||
/>
|
||||
微信快捷登录
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<template
|
||||
v-for="(loginMethod) in loginMethods"
|
||||
:key="loginMethod.type"
|
||||
@ -55,8 +158,34 @@ function toLogin(loginMethod) {
|
||||
|
||||
</view>
|
||||
|
||||
<view class="tips-row">
|
||||
为了给您提供更好的服务 我们需要您的授权哦~
|
||||
<view
|
||||
class="agreement-box"
|
||||
:class="{'error-animation':isPrivacyError}"
|
||||
>
|
||||
<uv-checkbox-group
|
||||
v-model="privacyPolicy"
|
||||
shape="circle"
|
||||
activeColor="#ec6e47"
|
||||
>
|
||||
<uv-checkbox :name="1">
|
||||
<view class="agreement-text">
|
||||
阅读并同意
|
||||
<span
|
||||
class="color"
|
||||
@click="toAgreement(0)"
|
||||
>
|
||||
《YSHOP商城用户协议》
|
||||
</span>
|
||||
和
|
||||
<span
|
||||
class="color"
|
||||
@click="toAgreement(1)"
|
||||
>
|
||||
《YSHOP商城隐私协议》
|
||||
</span>
|
||||
</view>
|
||||
</uv-checkbox>
|
||||
</uv-checkbox-group>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -112,14 +241,54 @@ function toLogin(loginMethod) {
|
||||
}
|
||||
}
|
||||
|
||||
.tips-row {
|
||||
position: absolute;
|
||||
bottom: 5%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
color: $tips-color;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.agreement-box {
|
||||
@include usePadding(30, 0);
|
||||
position: fixed;
|
||||
bottom: 5%;
|
||||
width: 100%;
|
||||
font-size: 24rpx;
|
||||
color: $tips-color;
|
||||
transition: all .3s;
|
||||
|
||||
|
||||
.agreement-text {
|
||||
text-align: center;
|
||||
|
||||
.color {
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.uv-checkbox ) {
|
||||
width: 100%;
|
||||
align-items: flex-start;
|
||||
|
||||
.uv-checkbox__icon-wrap {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error-animation {
|
||||
animation: error-text 0.8s 1;
|
||||
}
|
||||
|
||||
@keyframes error-text {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
5%, 25%, 45%, 65%, 85% {
|
||||
transform: translateX(-10rpx);
|
||||
}
|
||||
10%, 30%, 50%, 70%, 90% {
|
||||
transform: translateX(10rpx);
|
||||
}
|
||||
15%, 35%, 55%, 75%, 95% {
|
||||
transform: translateX(20rpx);
|
||||
}
|
||||
20%, 40%, 60%, 80%, 100% {
|
||||
transform: translateX(-20rpx);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -13,12 +13,7 @@ import phone from '@/static/icon/login/phone.png'
|
||||
* @type {[{icon: *, label: string},{icon: *, label: string}]}
|
||||
*/
|
||||
export const loginMethods = [
|
||||
{
|
||||
type: 0,
|
||||
label: '微信快捷登录',
|
||||
icon: wechat,
|
||||
classNames: []
|
||||
},
|
||||
|
||||
{
|
||||
type: 1,
|
||||
label: '手机号快捷登录',
|
||||
|
@ -4,7 +4,7 @@
|
||||
:fixed="false"
|
||||
title="订单详情"
|
||||
left-arrow
|
||||
@leftClick="goList"
|
||||
@leftClick="goBack"
|
||||
/>
|
||||
<view v-if="orderInfoData">
|
||||
<view class="orderInfo-header background-warp">
|
||||
@ -70,6 +70,7 @@
|
||||
>
|
||||
<goods
|
||||
list
|
||||
link
|
||||
interval
|
||||
desc="3"
|
||||
showAction
|
||||
@ -407,14 +408,16 @@ const handleOrderTake = async () => {
|
||||
uni: orderInfoData.value.orderId,
|
||||
}
|
||||
const res = await orderTake(option)
|
||||
toast({
|
||||
title: '收货成功'
|
||||
})
|
||||
uni.showToast({
|
||||
title: '收货成功',
|
||||
duration: 2000
|
||||
});
|
||||
handleOrderInfo({
|
||||
key: option.uni
|
||||
})
|
||||
|
||||
} else if (res.cancel) {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -434,9 +437,23 @@ const handlePay = () => {
|
||||
|
||||
// 返回列表
|
||||
const goList = ()=>{
|
||||
let status = 0
|
||||
switch (orderInfoData.value.status){
|
||||
case -1:
|
||||
status = -1
|
||||
break
|
||||
case 0:
|
||||
status = 0
|
||||
break
|
||||
case 99:
|
||||
status = 1
|
||||
break
|
||||
default:
|
||||
status = orderInfoData.value.status +1
|
||||
}
|
||||
push({url: '/pages/orderList/orderList'}, {
|
||||
data: {
|
||||
type: orderInfoData.value.status === 99?1:orderInfoData.value.status+1,
|
||||
type: status
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -494,13 +511,15 @@ const handleCancel = async () => {
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
await orderCancel({
|
||||
id: data.value.orderId
|
||||
id: orderInfoData.value.orderId
|
||||
})
|
||||
data.value = null
|
||||
uni.showToast({
|
||||
title: '已取消',
|
||||
duration: 2000
|
||||
});
|
||||
setTimeout(()=>{
|
||||
goList()
|
||||
},2000)
|
||||
} else if (res.cancel) {
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
>
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
title="全部订单"
|
||||
:title="title"
|
||||
@leftClick="goBack"
|
||||
/>
|
||||
<uv-tabs
|
||||
@ -18,6 +18,7 @@
|
||||
>
|
||||
</uv-tabs>
|
||||
</uv-sticky>
|
||||
|
||||
<view class="orderList">
|
||||
<template v-if="!listEmpty">
|
||||
<order
|
||||
@ -40,23 +41,26 @@
|
||||
<ListLoadOver v-if="loadend" />
|
||||
</view>
|
||||
</layout>
|
||||
<!-- 支付弹窗 -->
|
||||
<PayPopup
|
||||
ref="payPopupRef"
|
||||
@confirm="paySuccess"
|
||||
/>
|
||||
</view>
|
||||
<!-- 支付弹窗 -->
|
||||
<PayPopup
|
||||
ref="payPopupRef"
|
||||
@confirm="paySuccess"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, unref } from 'vue'
|
||||
import { computed, ref, unref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { orderList } from '@/api/order'
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import ListLoadOver from "@/components/ListLoadOver/index.vue"
|
||||
import ListLoadLoading from "@/components/ListLoadLoading/index.vue"
|
||||
import Empty from '@/components/Empty/index.vue'
|
||||
import emptyIcon from '@/static/icon/empty/订单.png'
|
||||
import PayPopup from '@/components/PayPopup/index.vue'
|
||||
import { usePage } from "@/hooks";
|
||||
import Header from "@/components/Header/index.vue"
|
||||
import { getProductList } from "@/api/product";
|
||||
|
||||
const {type, refresh, dataList, loadend, loading, listEmpty} = usePage(orderList)
|
||||
@ -78,6 +82,11 @@ const navList = ref([
|
||||
// { name: "退款", value: 7, },
|
||||
])
|
||||
|
||||
const title = computed(()=>{
|
||||
const find = navList.value.find(item=>item.value === type.value);
|
||||
return find?`${find.name}订单`:'订单'
|
||||
})
|
||||
|
||||
|
||||
// const handleOrderList = async (option) => {
|
||||
// orderListData.value = []
|
||||
@ -110,7 +119,7 @@ function openPay(orderId) {
|
||||
}
|
||||
|
||||
function paySuccess() {
|
||||
// push({url: '/pages/payStatus/index?type=1'})
|
||||
push({url: '/pages/payStatus/index'},{})
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,14 +8,18 @@
|
||||
<script setup>
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import { computed, ref, unref } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { checkH5Pay } from "@/api/order";
|
||||
import { onLoad, onPageScroll, onReachBottom } from "@dcloudio/uni-app";
|
||||
import { checkPay } from "@/api/order";
|
||||
import { CacheKey } from "@/utils/config";
|
||||
import Header from '@/components/Header/index.vue'
|
||||
import Recommend from '@/components/Recommend/index.vue'
|
||||
import { useInterface } from "@/hooks/useInterface";
|
||||
import { useScroll } from "@/hooks/useScroll";
|
||||
|
||||
const {getParams, goBack, push, pushToTab} = useRouter()
|
||||
|
||||
const {loading,hideLoading} = useInterface()
|
||||
const type = ref(0) // 支付状态 : 0支付中 1支付成功 2支付失败
|
||||
|
||||
useScroll()
|
||||
const title = computed(() => {
|
||||
if (type.value === 0) return '支付中...'
|
||||
if (type.value === 1) return '支付成功'
|
||||
@ -36,23 +40,48 @@ function toBackHome() {
|
||||
pushToTab({url: '/pages/index/index'})
|
||||
}
|
||||
|
||||
const retryTime = ref(3)
|
||||
|
||||
/**
|
||||
* 查询服务端支付状态
|
||||
*/
|
||||
async function queryOrderStatus() {
|
||||
const payInfoStr = uni.getStorageSync(CacheKey.PAY_INFO);
|
||||
if (payInfoStr) {
|
||||
const parse = JSON.parse(payInfoStr);
|
||||
const res = await checkH5Pay(parse);
|
||||
type.value = res ? 1 : 2
|
||||
uni.removeStorageSync(CacheKey.PAY_INFO)
|
||||
} else {
|
||||
// 没有订单缓存直接跳到订单页面
|
||||
toOrderList(0)
|
||||
}
|
||||
loading({title: '查询中...'})
|
||||
// 异步去查,有可能接口比微信快
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
const payInfoStr = uni.getStorageSync(CacheKey.PAY_INFO);
|
||||
// 没有订单缓存直接跳到订单页面
|
||||
if (!payInfoStr) return toOrderList(0)
|
||||
|
||||
const parse = JSON.parse(payInfoStr);
|
||||
const res = await checkPay(parse);
|
||||
if (!res) {
|
||||
// 支付失败重新查询
|
||||
if (retryTime.value > 0) {
|
||||
retryTime.value--
|
||||
await queryOrderStatus()
|
||||
} else {
|
||||
type.value = 2
|
||||
uni.removeStorageSync(CacheKey.PAY_INFO)
|
||||
}
|
||||
return
|
||||
}
|
||||
type.value = 1
|
||||
uni.removeStorageSync(CacheKey.PAY_INFO)
|
||||
} finally {
|
||||
hideLoading()
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const recommendRef = ref(null)
|
||||
onReachBottom(() => {
|
||||
unref(recommendRef).onReachBottom && unref(recommendRef).onReachBottom();
|
||||
})
|
||||
|
||||
onLoad(async (options) => {
|
||||
// H5 和 APP 需要弹窗去确认
|
||||
// #ifdef H5
|
||||
uni.showModal({
|
||||
content: '请确认支付是否完成',
|
||||
@ -61,23 +90,15 @@ onLoad(async (options) => {
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
const params = getParams(options);
|
||||
if (params && params.type === 1) {
|
||||
type.value = 1
|
||||
} else {
|
||||
type.value = 2
|
||||
}
|
||||
await queryOrderStatus()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="pay-status">
|
||||
<uv-navbar
|
||||
:fixed="false"
|
||||
:title="title"
|
||||
left-arrow
|
||||
@leftClick="goBack"
|
||||
/>
|
||||
<Header>
|
||||
{{ title }}
|
||||
</Header>
|
||||
<view class="status-main flex flex-column flex-ai__center">
|
||||
<image
|
||||
class="icon"
|
||||
@ -123,6 +144,8 @@ onLoad(async (options) => {
|
||||
重新支付
|
||||
</view>
|
||||
</view>
|
||||
<!-- 商品推荐 -->
|
||||
<Recommend ref="recommendRef" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
@ -230,15 +230,17 @@ const handleOrderInfo = async (option) => {
|
||||
|
||||
let price = 0
|
||||
let productParamList = []
|
||||
|
||||
let productAttrUnique = []
|
||||
goodsList.value.forEach(item => {
|
||||
price += item.cartInfo.truePrice * item.cartInfo.cartNum
|
||||
productParamList.push({
|
||||
productId: item.productId
|
||||
productId: item.productId,
|
||||
productAttrUnique: item.cartInfo.productAttrUnique
|
||||
})
|
||||
})
|
||||
|
||||
totalPrice.value = price
|
||||
|
||||
totalPrice.value = price.toFixed(2)
|
||||
data.value.orderId = res[0].orderId
|
||||
data.value.serviceType = refundType.value
|
||||
data.value.productParamList = productParamList
|
||||
@ -281,9 +283,10 @@ const handleApplyForAfterSales = async () => {
|
||||
title: '申请成功,请等待审核'
|
||||
})
|
||||
push({url: '/pages/refundInfo/refundInfo'}, {
|
||||
type:'redirectTo',
|
||||
data: {
|
||||
id: res,
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,7 @@
|
||||
model
|
||||
:purchase="item.cartNum"
|
||||
:data="item.productInfo"
|
||||
:price="item.truePrice"
|
||||
v-for="(item, index) in orderInfoData.cartInfo"
|
||||
>
|
||||
</goods>
|
||||
@ -133,7 +134,7 @@
|
||||
</view>
|
||||
<view class="info-cell ">
|
||||
<view class="info-cell-label">总计:</view>
|
||||
<view class="info-cell-value">¥{{ orderInfoData.refundAmount }}</view>
|
||||
<view class="info-cell-value">¥{{ orderInfoData.payPrice.toFixed(2) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -160,7 +161,7 @@
|
||||
服务类型
|
||||
</view>
|
||||
<view class="info-cell-value">
|
||||
{{ orderInfoData.serviceType }}
|
||||
{{ orderInfoData.serviceType===0?'仅退款':'退货退款' }}
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
@ -321,8 +322,8 @@ const handleDelete = async () => {
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
await afterSalesOrderDelete({
|
||||
id: orderInfoData.value.id,
|
||||
orderCode: orderInfoData.value.orderCode
|
||||
id: orderId.value,
|
||||
orderCode: orderInfoData.value.orderId
|
||||
})
|
||||
uni.showToast({
|
||||
title: '已删除',
|
||||
|
@ -20,21 +20,43 @@
|
||||
<card class="shopping-checkbox">
|
||||
<view
|
||||
v-for="(item, index) in goodsList"
|
||||
class="shopping-checkbox-cell"
|
||||
:key="item.id"
|
||||
class="goods-row"
|
||||
>
|
||||
<uv-checkbox
|
||||
:name="item.cartInfo.productAttrUnique"
|
||||
:disabled="item.isAfterSales != 1"
|
||||
/>
|
||||
<goods
|
||||
list
|
||||
interval
|
||||
showAction
|
||||
model
|
||||
:price="item.cartInfo.truePrice"
|
||||
:data="item.cartInfo.productInfo"
|
||||
>
|
||||
</goods>
|
||||
<view class="goods-col">
|
||||
<Goods
|
||||
row
|
||||
imgWidth="200rpx"
|
||||
info-padding="10rpx 40rpx"
|
||||
:goods="item.cartInfo.productInfo"
|
||||
>
|
||||
<template #options>
|
||||
<view class="goods-options">
|
||||
<!-- sku select -->
|
||||
<view class="sku-row flex">
|
||||
<view
|
||||
class="sku-info flex flex-jc__sb flex-ai__center"
|
||||
>
|
||||
<view class="info">
|
||||
{{ item.cartInfo.productInfo &&item.cartInfo.productInfo.attrInfo && item.cartInfo.productInfo.attrInfo.sku }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- bottom -->
|
||||
<view class="price-row flex flex-ai__center flex-jc__sb">
|
||||
<!-- price -->
|
||||
<view class="price-box flex flex-ai__end">
|
||||
¥{{item.cartInfo.truePrice }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</Goods>
|
||||
</view>
|
||||
</view>
|
||||
</card>
|
||||
</space>
|
||||
@ -87,6 +109,7 @@ import { ref, watch } from 'vue'
|
||||
import { applyForAfterSalesInfo } from '@/api/order'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import Goods from "@/components/goodsComponents/Goods.vue";
|
||||
|
||||
const {getParams, push, goBack} = useRouter()
|
||||
const goodsList = ref([])
|
||||
@ -118,7 +141,7 @@ watch(goodsSelect, (goodsSelect) => {
|
||||
price += item.cartInfo.truePrice * item.cartInfo.cartNum
|
||||
})
|
||||
|
||||
totalPrice.value = price
|
||||
totalPrice.value = price.toFixed(2)
|
||||
})
|
||||
|
||||
const handleOrderInfo = async (option) => {
|
||||
@ -140,7 +163,8 @@ const toRefund = (type) => {
|
||||
goods: goodsSelect.value.toString(),
|
||||
orderId: orderId.value,
|
||||
id: id.value
|
||||
}
|
||||
},
|
||||
type:'redirectTo'
|
||||
})
|
||||
}
|
||||
|
||||
@ -205,4 +229,95 @@ onLoad((options) => {
|
||||
background: $white-color;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-row{
|
||||
@include useFlex(space-between,center);
|
||||
@include usePadding(20,10);
|
||||
width: 100%;
|
||||
.goods-col{
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
// 商品SKU 数量等操作条
|
||||
.goods-options {
|
||||
width: 100%;
|
||||
|
||||
.sku-row {
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.sku-info {
|
||||
@include usePadding(10, 4);
|
||||
border: 1rpx solid #ccc;
|
||||
border-radius: 5rpx;
|
||||
font-size: 24rpx;
|
||||
transition: all .3s;
|
||||
max-width: 100%;
|
||||
|
||||
|
||||
.info {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&:active {
|
||||
scale: 1.1;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-left: 15rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.price-row {
|
||||
width: 100%;
|
||||
|
||||
.price-box {
|
||||
font-size: 30rpx;
|
||||
color:$primary-color;
|
||||
|
||||
.old-price {
|
||||
font-size: 20rpx;
|
||||
color: $tips-color;
|
||||
text-decoration: line-through;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.cart-num {
|
||||
font-size: 24rpx;
|
||||
|
||||
.input {
|
||||
width: 120rpx;
|
||||
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
font-size: 32rpx;
|
||||
width: 34rpx;
|
||||
aspect-ratio: 1/1;
|
||||
border-radius: 5rpx;
|
||||
border: 2rpx solid #cccccc;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all .3s;
|
||||
|
||||
&:active {
|
||||
scale: 1.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -2,7 +2,6 @@
|
||||
<Header
|
||||
system-bar-area-bg="#fff"
|
||||
header-area-bg="#fff"
|
||||
:scroll-top="scrollTop"
|
||||
bg-change-by-scroll
|
||||
>
|
||||
购物车
|
||||
@ -27,6 +26,7 @@
|
||||
<!-- 购物车信息 -->
|
||||
<view
|
||||
v-for="(item) in cartList"
|
||||
:key="item.id"
|
||||
class="shopping-item"
|
||||
>
|
||||
<uv-checkbox
|
||||
@ -164,13 +164,17 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="action-height"></view>
|
||||
<view class="h5-tabbar-height"></view>
|
||||
|
||||
</view>
|
||||
<!-- null data -->
|
||||
<CartEmpty v-else />
|
||||
<!-- 商品推荐 -->
|
||||
<Recommend />
|
||||
<view class="action-height"></view>
|
||||
<view class="h5-tabbar-height"></view>
|
||||
<!-- sku select -->
|
||||
<GoodAttrSelect
|
||||
style="z-index: 999"
|
||||
:id="openSkuProductId"
|
||||
ref="goodsAttrSelectRef"
|
||||
@close="handleCloseSkuSelect"
|
||||
@ -194,7 +198,9 @@ import { settleFields } from "@/pages/shoppingCart/index.data";
|
||||
import { useCartData, useCartNumber, useCartOption, useSku } from "@/pages/shoppingCart/index.utils";
|
||||
import CartEmpty from "@/pages/shoppingCart/components/CartEmpty.vue";
|
||||
import Header from "@/components/Header/index.vue"
|
||||
import { onHide, onPageScroll } from "@dcloudio/uni-app";
|
||||
import { onHide, onPageScroll, onReachBottom } from "@dcloudio/uni-app";
|
||||
import Recommend from "@/components/Recommend/index.vue";
|
||||
import { useScroll } from "@/hooks/useScroll";
|
||||
|
||||
const modalRef = ref() // 删除弹窗
|
||||
const goodsAttrSelectRef = ref() // 更改sku
|
||||
@ -233,15 +239,14 @@ const {
|
||||
} = useCartNumber({afterChange: computeSelectInfoByShoppingSelect})
|
||||
|
||||
|
||||
|
||||
|
||||
onHide(() => {
|
||||
modalRef.value?.close()
|
||||
goodsAttrSelectRef.value?.close()
|
||||
})
|
||||
|
||||
const scrollTop = ref(0)
|
||||
onPageScroll((e) => {
|
||||
scrollTop.value = e.scrollTop
|
||||
})
|
||||
useScroll()
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
@ -3,6 +3,7 @@
|
||||
ref="popupRef"
|
||||
:showCloseable="false"
|
||||
@close="emit('close')"
|
||||
@maskClick="clickMask"
|
||||
>
|
||||
<template v-if="couponList.length>0">
|
||||
<view
|
||||
@ -22,6 +23,7 @@
|
||||
@change="radioChage"
|
||||
>
|
||||
<CouponItem
|
||||
class="select-coupon"
|
||||
:coupons="item"
|
||||
:type="'noType'"
|
||||
/>
|
||||
@ -39,6 +41,7 @@
|
||||
>
|
||||
暂无可用的优惠券
|
||||
</Empty>
|
||||
<view class="action-height"></view>
|
||||
<view class="button-action">
|
||||
<view
|
||||
class="animation-button"
|
||||
@ -71,6 +74,7 @@ const popupRef = ref(false)
|
||||
const currentCoupon = ref({})
|
||||
const visible = ref(false)
|
||||
const couponItem = ref(props.currentCouponId ? props.currentCouponId : -1)
|
||||
const oldCoupon = ref(props.currentCouponId ? props.currentCouponId : -1)
|
||||
const num = ref(0)
|
||||
const radioValue = ref('')
|
||||
const selectCouponPanel = ref(false)
|
||||
@ -86,6 +90,7 @@ const handleSubmit = () => {
|
||||
close()
|
||||
return
|
||||
}
|
||||
oldCoupon.value = couponItem.value
|
||||
emit('submitCoupon', {
|
||||
couponId: couponItem.value
|
||||
})
|
||||
@ -100,6 +105,12 @@ const groupChange = (n) => {
|
||||
}
|
||||
}
|
||||
|
||||
const clickMask = () => {
|
||||
if (oldCoupon.value !== couponItem.value) {
|
||||
couponItem.value = oldCoupon.value
|
||||
}
|
||||
}
|
||||
|
||||
const radioChage = (n) => {
|
||||
radioValue.value = n
|
||||
num.value = 0
|
||||
@ -142,8 +153,7 @@ defineExpose({
|
||||
|
||||
.select-box {
|
||||
width: 100%;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
margin-bottom: 30rpx;
|
||||
.select-icon {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
@ -153,15 +163,26 @@ defineExpose({
|
||||
margin-bottom: 0 !important;
|
||||
padding: 0 60rpx;
|
||||
}
|
||||
.select-coupon {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-height{
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.button-action {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
.animation-button {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 80rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import UvRadio from "@/uni_modules/uv-radio/components/uv-radio/uv-radio.vue";
|
||||
import { doPayment, PayType } from "@/utils/paymentUtils";
|
||||
import CouponSelect from "@/pages/submitOrder/components/coupon-select.vue";
|
||||
import Header from "@/components/Header/index.vue"
|
||||
import { useScroll } from "@/hooks/useScroll";
|
||||
|
||||
const {getParams, push, goBack} = useRouter()
|
||||
const {toast, loading, hideLoading} = useInterface();
|
||||
@ -117,16 +118,15 @@ async function handleConfirm() {
|
||||
subLoading.value = true
|
||||
try {
|
||||
const payInfo = await doCreateServiceOrder()
|
||||
debugger
|
||||
// 去拉取支付
|
||||
await doPayment({type: payType.value, payInfo})
|
||||
// #ifndef H5
|
||||
push({url: '/pages/payStatus/index?type=1'}, {type: 'redirectTo'})
|
||||
push({url: '/pages/payStatus/index'}, {type: 'redirectTo'})
|
||||
// #endif
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
toast({title: '支付失败'})
|
||||
push({url: '/pages/payStatus/index?type=2'}, {type: 'redirectTo'})
|
||||
push({url: '/pages/payStatus/index'}, {type: 'redirectTo'})
|
||||
} finally {
|
||||
subLoading.value = false
|
||||
mainStore.cartId = null
|
||||
@ -159,12 +159,7 @@ async function doCreateServiceOrder() {
|
||||
}
|
||||
}
|
||||
|
||||
const scrollTop = ref(0)
|
||||
|
||||
onPageScroll(e => {
|
||||
scrollTop.value = e.scrollTop
|
||||
})
|
||||
|
||||
useScroll()
|
||||
|
||||
/**
|
||||
* 检查路由参数
|
||||
@ -192,7 +187,7 @@ onLoad(async options => {
|
||||
<template>
|
||||
<view class="order-confirm">
|
||||
<!-- header -->
|
||||
<Header :scroll-top="scrollTop">
|
||||
<Header>
|
||||
提交订单
|
||||
</Header>
|
||||
<!-- 地址 -->
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { useMainStore } from "@/store/store";
|
||||
import { useInterface } from "@/hooks/useInterface";
|
||||
import { updateAvatar, updateUserInfo } from "@/api/user";
|
||||
import { upload } from "@/api/api";
|
||||
|
||||
export function useRequest() {
|
||||
const {loading, hideLoading, toast} = useInterface()
|
||||
@ -12,12 +13,15 @@ export function useRequest() {
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function doUpdateAvatar(file) {
|
||||
let data = new FormData()
|
||||
data.append('avatarFile', file)
|
||||
loading({title: '上传中...'})
|
||||
await updateAvatar(data)
|
||||
await userStore.getUserInfo()
|
||||
hideLoading()
|
||||
try {
|
||||
await upload({
|
||||
filePath: file.url,
|
||||
name: 'avatarFile'
|
||||
});
|
||||
await userStore.getUserInfo()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
async function doUpdateUserInfo() {
|
||||
|
@ -44,8 +44,7 @@ const modelRef = ref()
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function afterChooseFile(event) {
|
||||
const imgObj = await objectURLToBlob(event.file.url)
|
||||
await doUpdateAvatar(new File([imgObj], '', {type: imgObj.type}))
|
||||
await doUpdateAvatar(event.file)
|
||||
}
|
||||
|
||||
function sexChange(event) {
|
||||
|
@ -48,8 +48,7 @@ export const useMainStore = defineStore('main', {
|
||||
// console.log('--> % getUserInfo % res:\n', res)
|
||||
},
|
||||
async getAddressCityList() {
|
||||
let res = await getAddressCityList()
|
||||
this.areaList = res
|
||||
this.areaList = await getAddressCityList()
|
||||
},
|
||||
init() {
|
||||
let accessToken = cookie.get('accessToken')
|
||||
|
@ -16,12 +16,19 @@ const {loading, hideLoading} = useInterface()
|
||||
export const WechatProvider = 'wxpay'
|
||||
|
||||
// 支付类型(后端用)
|
||||
export const ServicePayType = {
|
||||
0: 'weixin_h5', // H5(微信内h5、微信外H5)
|
||||
1: 'weixin_applet', // 微信小程序
|
||||
2: 'weixin_app' // 微信APP
|
||||
export const ServiceFrom = {
|
||||
'h5': 'weixin_h5', // H5(微信内h5、微信外H5)
|
||||
'weixin': 'weixin_applet', // 微信小程序
|
||||
'app': 'weixin_app' // 微信APP
|
||||
}
|
||||
|
||||
export const ServicePayType = {
|
||||
'h5': 'weixin_h5', // H5(微信内h5、微信外H5)
|
||||
'weixin': 'weixin_applet', // 微信小程序
|
||||
'app': 'weixin_app' // 微信APP
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 支付类型(前端用)
|
||||
export const PayType = {
|
||||
@ -116,12 +123,15 @@ async function _chooseEnvToPayment(options) {
|
||||
*/
|
||||
function _appWechatPay(payInfo) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
// 请求线上获取 res:{ appId,timeStamp,nonceStr,paySign,package,signType,mwebUrl,codeUrl,merchant_id,out_trade_no }
|
||||
const res = await _doWechatPayRequest({
|
||||
from: ServicePayType['2'],
|
||||
paytype: ServicePayType['2'],
|
||||
const payData = {
|
||||
from: ServiceFrom['app'],
|
||||
paytype: ServicePayType['app'],
|
||||
uni: payInfo.orderId
|
||||
})
|
||||
}
|
||||
// 请求线上获取 res:{ appId,timeStamp,nonceStr,paySign,package,signType,mwebUrl,codeUrl,merchant_id,out_trade_no }
|
||||
const res = await _doWechatPayRequest(payData)
|
||||
// 兼容性写法:防止电脑端用户支付后马上关闭支付弹窗导致失败
|
||||
uni.setStorageSync(CacheKey.PAY_INFO, JSON.stringify(payData))
|
||||
const orderInfo = {
|
||||
appid: res.appId, // 微信开放平台审核通过的移动应用AppID 。
|
||||
prepayid: res.merchant_id, // 请填写商户号mchid对应的值。
|
||||
@ -148,13 +158,15 @@ function _appWechatPay(payInfo) {
|
||||
*/
|
||||
function _miniProgramPay(payInfo) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
// 请求线上获取 res:{ appId,timeStamp,nonceStr,paySign,package,signType,mwebUrl,codeUrl,merchant_id,out_trade_no }
|
||||
const res = await _doWechatPayRequest({
|
||||
from: ServicePayType['1'],
|
||||
paytype: ServicePayType['1'],
|
||||
const payData = {
|
||||
from: ServiceFrom['weixin'],
|
||||
paytype: ServiceFrom['weixin'],
|
||||
uni: payInfo.orderId
|
||||
})
|
||||
|
||||
}
|
||||
// 请求线上获取 res:{ appId,timeStamp,nonceStr,paySign,package,signType,mwebUrl,codeUrl,merchant_id,out_trade_no }
|
||||
const res = await _doWechatPayRequest(payData)
|
||||
// 兼容性写法:防止电脑端用户支付后马上关闭支付弹窗导致失败
|
||||
uni.setStorageSync(CacheKey.PAY_INFO, JSON.stringify(payData))
|
||||
uni.requestPayment({
|
||||
timeStamp: res.timeStamp,
|
||||
nonceStr: res.nonceStr,
|
||||
@ -177,12 +189,13 @@ function _miniProgramPay(payInfo) {
|
||||
*/
|
||||
async function _h5InWechatPay(payInfo) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
// 请求线上获取 res:{ appId,timeStamp,nonceStr,paySign,package,signType,mwebUrl,codeUrl,merchant_id,out_trade_no }
|
||||
const res = await _doWechatPayRequest({
|
||||
from: 'h5',
|
||||
paytype: ServicePayType['0'],
|
||||
const payData = {
|
||||
from: ServiceFrom['h5'],
|
||||
paytype: ServicePayType['h5'],
|
||||
uni: payInfo.orderId
|
||||
})
|
||||
}
|
||||
// 请求线上获取 res:{ appId,timeStamp,nonceStr,paySign,package,signType,mwebUrl,codeUrl,merchant_id,out_trade_no }
|
||||
const res = await _doWechatPayRequest(payData)
|
||||
/** 注册JS SDK */
|
||||
jweixin.config({
|
||||
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
|
||||
@ -203,6 +216,7 @@ async function _h5InWechatPay(payInfo) {
|
||||
return reject(createMessage('微信版本过低,请升级微信版本', error))
|
||||
}
|
||||
});
|
||||
uni.setStorageSync(CacheKey.PAY_INFO, JSON.stringify(payData))
|
||||
/** 去拉起微信支付 */
|
||||
jweixin.chooseWXPay({
|
||||
timestamp: res.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
|
||||
@ -212,16 +226,6 @@ async function _h5InWechatPay(payInfo) {
|
||||
paySign: res.paySign, // 支付签名
|
||||
success: (res) => {
|
||||
// 支付成功后的回调函数
|
||||
uni.setStorageSync(CacheKey.PAY_INFO, JSON.stringify(
|
||||
{
|
||||
from: 'h5',
|
||||
paytype: ServicePayType['0'],
|
||||
uni: payInfo.orderId
|
||||
}
|
||||
))
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({url: '/pages/payStatus/index'})
|
||||
}, 3000)
|
||||
return resolve(createMessage('用户支付成功', res))
|
||||
},
|
||||
cancel: (r) => {
|
||||
@ -246,20 +250,15 @@ async function _h5InWechatPay(payInfo) {
|
||||
* @private
|
||||
*/
|
||||
async function _h5OutWechatPay(payInfo) {
|
||||
const res = await _doWechatPayRequest({
|
||||
from: 'h5',
|
||||
paytype: ServicePayType['0'],
|
||||
const payData = {
|
||||
from: ServiceFrom['h5'],
|
||||
paytype: ServicePayType['h5'],
|
||||
uni: payInfo.orderId
|
||||
})
|
||||
}
|
||||
const res = await _doWechatPayRequest(payData)
|
||||
if (res && res.mwebUrl) {
|
||||
// 缓存支付订单数据
|
||||
uni.setStorageSync(CacheKey.PAY_INFO, JSON.stringify(
|
||||
{
|
||||
from: 'h5',
|
||||
paytype: ServicePayType['0'],
|
||||
uni: payInfo.orderId
|
||||
}
|
||||
))
|
||||
uni.setStorageSync(CacheKey.PAY_INFO, JSON.stringify(payData))
|
||||
location.replace(res.mwebUrl)
|
||||
return Promise.resolve(createMessage('用户支付成功', {type: 'h5'}))
|
||||
} else {
|
||||
|
@ -146,3 +146,12 @@ export function hasNetWork() {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两数之间的随机数
|
||||
* @param min
|
||||
* @param max
|
||||
*/
|
||||
export function getRandom(min, max) {
|
||||
return (Math.random() * (max - min) + min).toFixed(2);
|
||||
}
|
||||
|
206
utils/wechatUtils.js
Normal file
206
utils/wechatUtils.js
Normal file
@ -0,0 +1,206 @@
|
||||
/**
|
||||
* @FileDescription: 微信工具类
|
||||
* @Author: kahu
|
||||
* @Date: 2023/6/29
|
||||
* @LastEditors: kahu
|
||||
* @LastEditTime: 2023/6/29
|
||||
*/
|
||||
|
||||
/**
|
||||
* 拍摄或从手机相册中选择图片或视频
|
||||
* @param options
|
||||
* @param options.count 数量 最大选取数量 最多可以选择的文件个数,基础库2.25.0前,最多可支持9个文件,2.25.0及以后最多可支持20个文件
|
||||
* @param options.mediaType 选取类型 image图片 video视频
|
||||
* @param options.sourceType 选取的方式 album相册 camera相机
|
||||
* @param options.maxDuration 录取视频的最大秒数,时间范围为 3s 至 60s 之间。不限制相册
|
||||
* @param options.sizeType 是否压缩所选内容,基础库2.25.0前仅对 mediaType 为 image 时有效,2.25.0及以后对全量 mediaType 有效
|
||||
* @param options.camera 拍摄时候的摄像头,仅在 sourceType 为 camera 时生效,使用前置或后置摄像头
|
||||
*/
|
||||
export function wxChooseMedia(options={}){
|
||||
return new Promise((resolve, reject) => {
|
||||
const mergeOptions = {
|
||||
count:9,
|
||||
mediaType:['image','video'],
|
||||
sourceType:['album','camera'],
|
||||
maxDuration:10,
|
||||
sizeType:['original','compressed'],
|
||||
camera:'back',
|
||||
...options,
|
||||
success:(res)=>{
|
||||
resolve(res)
|
||||
},
|
||||
fail:(err)=>{
|
||||
reject(err)
|
||||
}
|
||||
}
|
||||
wx.chooseMedia(mergeOptions)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用微信接口编辑图片
|
||||
* @param src 被编辑图片的临时路径
|
||||
*/
|
||||
export function wxEditImage(src){
|
||||
return new Promise((resolve, reject)=>{
|
||||
wx.editImage({
|
||||
src,
|
||||
success:(res)=>{
|
||||
resolve(res.tempFilePath)
|
||||
},
|
||||
fail:(err)=>{
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用微信接口裁剪图片
|
||||
* @param options
|
||||
* @param options.src 被裁剪图片的临时路径
|
||||
* @param options.cropScale 裁剪比例
|
||||
*/
|
||||
export function wxCropImage(options){
|
||||
return new Promise((resolve, reject) => {
|
||||
const mergeOptions = {
|
||||
cropScale:'1:1',
|
||||
...options,
|
||||
success:(res)=>{
|
||||
resolve(res.tempFilePath)
|
||||
},
|
||||
fail:(err)=>{
|
||||
reject(err)
|
||||
}
|
||||
}
|
||||
wx.cropImage(mergeOptions)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用微信接口处理视频
|
||||
* @param options
|
||||
* @param options.filePath 视频的本地路径
|
||||
* @param options.minDuration 视频的最小长度
|
||||
* @param options.maxDuration 视频的最大长度
|
||||
* @return { Promise<{duration:number,size:number,tempFilePath:string,tempThumbPath:string}> }
|
||||
*/
|
||||
export function wxEditVideo(options){
|
||||
return new Promise((resolve, reject)=>{
|
||||
if(options.minDuration>=options.maxDuration)return reject('MaxDuration Must Greater Than MinDuration')
|
||||
wx.openVideoEditor({
|
||||
...options,
|
||||
success:(res)=>{
|
||||
resolve(res)
|
||||
},
|
||||
fail:(err)=>{
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取视频的详情
|
||||
* @param src
|
||||
*/
|
||||
export function wxGetVideoInfo(src){
|
||||
return new Promise((resolve, reject)=>{
|
||||
wx.getVideoInfo({
|
||||
src,
|
||||
success:(res)=>{
|
||||
resolve(res)
|
||||
},
|
||||
fail:(err)=>{
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取照片的详情
|
||||
* @param src
|
||||
*/
|
||||
export function wxGetImageInfo(src){
|
||||
return new Promise((resolve, reject)=>{
|
||||
wx.getImageInfo({
|
||||
src,
|
||||
success:(res)=>{
|
||||
resolve(res)
|
||||
},
|
||||
fail:(err)=>{
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用微信login获取code
|
||||
*/
|
||||
export function wxLogin(){
|
||||
return new Promise((resolve, reject)=>{
|
||||
uni.login({
|
||||
provider: 'weixin',
|
||||
success: (res) => {
|
||||
resolve(res.code)
|
||||
},
|
||||
fail: (err) => {
|
||||
reject({
|
||||
message:'微信login方法出现错误',
|
||||
data:err
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用微信getUserProfile获取encryptedData、iv
|
||||
*/
|
||||
export function wxGetUserProfile(){
|
||||
return new Promise((resolve, reject)=> {
|
||||
uni.getUserProfile({
|
||||
desc: '用于完善用户信息',
|
||||
success: ({ encryptedData, iv }) => {
|
||||
resolve({encryptedData,iv})
|
||||
},
|
||||
fail:(err)=>{
|
||||
console.log(err)
|
||||
reject({
|
||||
message:'微信getUserProfile方法出现错误',
|
||||
data:err
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 调用地图获取位置信息
|
||||
* @param params
|
||||
*/
|
||||
export function wxChooseLocation(params){
|
||||
return new Promise((resolve, reject)=>{
|
||||
const obj = {
|
||||
success(e){
|
||||
resolve(e)
|
||||
},
|
||||
fail(err){
|
||||
console.log(err)
|
||||
reject({
|
||||
message:'微信ChooseLocation方法出现错误',
|
||||
data:err
|
||||
})
|
||||
}
|
||||
}
|
||||
Object.keys(params).forEach(key=>{
|
||||
// @ts-ignore
|
||||
obj[key] = params[key]
|
||||
})
|
||||
uni.chooseLocation(obj)
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user