mirror of
https://gitee.com/niucloud-team/niucloud-admin.git
synced 2026-03-13 07:15:53 +00:00
update
This commit is contained in:
parent
4890be9b9a
commit
4aaf885ef0
@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
|
||||
import { launchInterceptor } from '@/utils/interceptor'
|
||||
import { getToken, isWeixinBrowser } from '@/utils/common'
|
||||
import { getToken, isWeixinBrowser, currRoute } from '@/utils/common'
|
||||
import useMemberStore from '@/stores/member'
|
||||
import useConfigStore from '@/stores/config'
|
||||
import useSystemStore from '@/stores/system'
|
||||
@ -48,13 +48,37 @@
|
||||
wechatInit()
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
const updateManager = uni.getUpdateManager();
|
||||
updateManager.onCheckForUpdate(function(res) {
|
||||
// 请求完新版本信息的回调
|
||||
});
|
||||
|
||||
updateManager.onUpdateReady(function(res) {
|
||||
uni.showModal({
|
||||
title: '更新提示',
|
||||
content: '新版本已经准备好,是否重启应用?',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
||||
updateManager.applyUpdate();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
updateManager.onUpdateFailed(function(res) {
|
||||
// 新的版本下载失败
|
||||
});
|
||||
// #endif
|
||||
|
||||
const configStore = useConfigStore()
|
||||
await configStore.getTabbarConfig()
|
||||
await configStore.getLoginConfig()
|
||||
|
||||
useSystemStore().getMapFn()
|
||||
useSystemStore().getSiteInfoFn()
|
||||
useMemberStore().getMemberLevel()
|
||||
useMemberStore().getMemberLevel()
|
||||
try {
|
||||
// 隐藏tabbar
|
||||
uni.hideTabBar()
|
||||
@ -62,6 +86,12 @@
|
||||
|
||||
}
|
||||
|
||||
// 判断在登录注册页面账号锁定后不进行请求三方登录注册
|
||||
let url = currRoute()
|
||||
if ((url == 'app/pages/auth/login' || url == 'app/pages/auth/register') && (configStore.login.is_username || configStore.login.is_mobile || configStore.login.is_bind_mobile)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 判断是否已登录
|
||||
if (getToken()) {
|
||||
const memberStore = useMemberStore()
|
||||
@ -70,27 +100,54 @@
|
||||
setTimeout(() => {
|
||||
if (!uni.getStorageSync('openid')) {
|
||||
const memberInfo = useMemberStore().info
|
||||
const login = useLogin()
|
||||
// #ifdef MP-WEIXIN
|
||||
memberInfo && memberInfo.weapp_openid && uni.setStorageSync('openid', memberInfo.weapp_openid)
|
||||
if (memberInfo && memberInfo.weapp_openid) {
|
||||
uni.setStorageSync('openid', memberInfo.weapp_openid)
|
||||
} else {
|
||||
login.getAuthCode('', true)
|
||||
}
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
isWeixinBrowser() && memberInfo && memberInfo.wx_openid && uni.setStorageSync('openid', memberInfo.wx_openid)
|
||||
if (isWeixinBrowser()) {
|
||||
if (memberInfo && memberInfo.wx_openid) {
|
||||
uni.setStorageSync('openid', memberInfo.wx_openid)
|
||||
} else {
|
||||
data.query.code ? login.updateOpenid(data.query.code) : login.getAuthCode('snsapi_userinfo')
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
// 开启强制绑定手机号
|
||||
if (uni.getStorageSync('isbindmobile')) {
|
||||
uni.removeStorageSync('isbindmobile');
|
||||
}
|
||||
if (configStore.login.is_bind_mobile && !memberStore.info.mobile) {
|
||||
// 强制绑定手机号
|
||||
uni.setStorageSync('isbindmobile', true)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
if (!getToken()) {
|
||||
const login = useLogin()
|
||||
// 第三方平台自动登录
|
||||
// todo 退出后不进行自动登录
|
||||
// #ifdef MP
|
||||
login.getAuthCode()
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
if (isWeixinBrowser()) {
|
||||
data.query.code ? login.authLogin(data.query.code) : login.getAuthCode('snsapi_userinfo')
|
||||
if(uni.getStorageSync('autoLoginLock')){
|
||||
return false
|
||||
}
|
||||
// #endif
|
||||
// 判断是否开启第三方自动注册登录
|
||||
if (configStore.login.is_auth_register) {
|
||||
const login = useLogin()
|
||||
// 第三方平台自动登录
|
||||
// #ifdef MP
|
||||
login.getAuthCode()
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
if (isWeixinBrowser()) {
|
||||
data.query.code ? login.authLogin(data.query.code) : login.getAuthCode('snsapi_userinfo')
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -102,7 +159,7 @@
|
||||
</script>
|
||||
|
||||
<style>
|
||||
uni-page-head {
|
||||
display: none !important;
|
||||
}
|
||||
uni-page-head {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
.draggable-element,.ignore-draggable-element {
|
||||
&.decorate {
|
||||
&:hover:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border: 4rpx dotted $u-primary;
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
cursor: move;
|
||||
}
|
||||
.draggable-element {
|
||||
&.decorate {
|
||||
&:hover:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border: 4rpx dotted $u-primary;
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
&.selected:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border: 4rpx solid $u-primary;
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
&.selected:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border: 4rpx solid $u-primary;
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<view class="diy-group" id="componentList">
|
||||
<top-tabbar :scrollTop="topTabbarScrollBool" v-if="data.global && Object.keys(data.global).length && data.global.topStatusBar && data.global.topStatusBar.isShow" ref="topTabbarRef" :data="data.global" />
|
||||
<view v-for="(component, index) in data.value" :key="component.id" @click="diyStore.changeCurrentIndex(index, component)" :class="getComponentClass(index,component)" :style="component.pageStyle">
|
||||
<top-tabbar v-if="data.global && Object.keys(data.global).length && data.global.topStatusBar && data.global.topStatusBar.isShow" :scrollBool="diyGroup.componentsScrollBool.TopTabbar" ref="topTabbarRef" :data="data.global" />
|
||||
<view v-for="(component, index) in data.value" :key="component.id" @click="diyStore.changeCurrentIndex(index, component)" :class="diyGroup.getComponentClass(index,component)" :style="component.pageStyle">
|
||||
<view class="relative" :style="{ marginTop : component.margin.top < 0 ? (component.margin.top * 2) + 'rpx' : '0' }">
|
||||
|
||||
<!-- 装修模式下,设置负上边距后超出的内容,禁止选中设置 -->
|
||||
<view v-if="isShowPlaceHolder(index,component)" class="absolute w-full z-1" :style="{ height : (component.margin.top * 2 * -1) + 'rpx' }" @click.stop="placeholderEvent"></view>
|
||||
<view v-if="diyGroup.isShowPlaceHolder(index,component)" class="absolute w-full z-1" :style="{ height : (component.margin.top * 2 * -1) + 'rpx' }" @click.stop="diyGroup.placeholderEvent"></view>
|
||||
|
||||
<template v-if="component.componentName == 'GraphicNav'">
|
||||
<diy-graphic-nav :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
@ -47,180 +47,47 @@
|
||||
<diy-float-btn :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount"/>
|
||||
</template>
|
||||
<template v-if="component.componentName == 'CarouselSearch'">
|
||||
<diy-carousel-search ref="carouselSearchRef" :scrollTop="carouselSearchScrollBool" :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-carousel-search :scrollBool="diyGroup.componentsScrollBool.CarouselSearch" :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
<template v-if="diyStore.mode == '' && data.global.bottomTabBarSwitch">
|
||||
<view class="pt-[20rpx]"></view>
|
||||
<tabbar :addon="tabbarAddonName" />
|
||||
<tabbar />
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import topTabbar from '@/components/top-tabbar/top-tabbar.vue'
|
||||
import topTabbar from '@/components/top-tabbar/top-tabbar.vue'
|
||||
|
||||
import useDiyStore from '@/app/stores/diy';
|
||||
import { ref, onMounted, nextTick, computed, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { getLocation } from '@/utils/common';
|
||||
import Sortable from 'sortablejs';
|
||||
import { range } from 'lodash-es';
|
||||
import { onPageScroll } from '@dcloudio/uni-app'
|
||||
import useConfigStore from '@/stores/config'
|
||||
import { useDiyGroup } from './useDiyGroup'
|
||||
import useDiyStore from '@/app/stores/diy';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const props = defineProps(['data','pullDownRefreshCount']);
|
||||
const diyStore = useDiyStore();
|
||||
const router = useRouter();
|
||||
const data = computed(()=>{
|
||||
if (diyStore.mode == 'decorate') {
|
||||
return diyStore;
|
||||
} else {
|
||||
return props.data;
|
||||
}
|
||||
})
|
||||
|
||||
let carouselSearchRef = ref(null)
|
||||
let carouselSearchScrollValue = 0
|
||||
let topTabbarRef = ref(null)
|
||||
let topTabbarScrollValue = 0
|
||||
|
||||
// 兼容轮播搜索组件-切换分类时,导致个人中心白屏 - start
|
||||
// #ifdef H5
|
||||
watch(() => router.currentRoute.value, (newRoute) => {
|
||||
if(newRoute.path != "/addon/shop/pages/index"){
|
||||
diyStore.topFixedStatus = 'home'
|
||||
}
|
||||
});
|
||||
const props = defineProps(['data', 'pullDownRefreshCount']);
|
||||
|
||||
// #endif
|
||||
const topTabbarRef = ref(null);
|
||||
const diyStore = useDiyStore();
|
||||
const diyGroup = useDiyGroup({
|
||||
...props,
|
||||
getFormRef() {
|
||||
return {
|
||||
topTabbarRef: topTabbarRef.value
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// #ifdef MP
|
||||
wx.onAppRoute(function(res) {
|
||||
if(res.path != "addon/shop/pages/index"){
|
||||
diyStore.topFixedStatus = 'home'
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
// 兼容轮播搜索组件-切换分类时,导致个人中心白屏 - end
|
||||
const data = ref(diyGroup.data)
|
||||
|
||||
const tabbarAddonName = computed(() => {
|
||||
return useConfigStore().addon;
|
||||
})
|
||||
// 监听页面加载完成
|
||||
diyGroup.onMounted()
|
||||
|
||||
const positionFixed = ref(['fixed', 'top_fixed','right_fixed','bottom_fixed','left_fixed']);
|
||||
// 监听滚动事件
|
||||
diyGroup.onPageScroll()
|
||||
|
||||
const getComponentClass = (index:any,component:any) => {
|
||||
let obj: any = {
|
||||
relative: true,
|
||||
selected: diyStore.currentIndex == index,
|
||||
decorate: diyStore.mode == 'decorate'
|
||||
}
|
||||
obj['top-fixed-' + diyStore.topFixedStatus] = true;
|
||||
|
||||
if (component.position && positionFixed.value.indexOf(component.position) != -1) {
|
||||
// 找出置顶组件,设置禁止拖动
|
||||
obj['ignore-draggable-element'] = true;
|
||||
} else {
|
||||
obj['draggable-element'] = true;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// #ifdef H5
|
||||
if (diyStore.mode == 'decorate') {
|
||||
var el = document.getElementById('componentList');
|
||||
const sortable = Sortable.create(el, {
|
||||
draggable: '.draggable-element',
|
||||
animation: 200,
|
||||
// 结束拖拽
|
||||
onEnd: event => {
|
||||
let temp = diyStore.value[event.oldIndex!];
|
||||
diyStore.value.splice(event.oldIndex!, 1);
|
||||
diyStore.value.splice(event.newIndex!, 0, temp);
|
||||
|
||||
nextTick(() => {
|
||||
sortable.sort(range(diyStore.value.length).map(value => {
|
||||
return value.toString();
|
||||
}));
|
||||
|
||||
diyStore.postMessage(event.newIndex, diyStore.value[event.newIndex]);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
if (data.value.global && data.value.global.topStatusBar && data.value.global.topStatusBar.style == 'style-4') {
|
||||
// 第一次获取经纬度
|
||||
getLocation()
|
||||
}
|
||||
// 获取轮播搜索的滚动值
|
||||
carouselSearchScrollValue = carouselSearchRef.value ? carouselSearchRef.value[0].scrollValue : 0;
|
||||
// 获取top-tabbar的滚动值
|
||||
topTabbarScrollValue = topTabbarRef.value ? topTabbarRef.value.scrollValue : 0;
|
||||
}, 500)
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// 是否显示占位区域,用于禁止选中负上边距的内容
|
||||
const isShowPlaceHolder = (index: any, component: any) => {
|
||||
// #ifdef H5
|
||||
if (diyStore.mode == 'decorate') {
|
||||
let el: any = document.getElementById('componentList');
|
||||
if (el && el.children.length && el.children[index]) {
|
||||
let height = el.children[index].offsetHeight;
|
||||
let top = 0;
|
||||
if (component.margin.top < 0) {
|
||||
top = component.margin.top * 2 * -1;
|
||||
// 若负上边距大于组件的高度,则允许选中进行装修
|
||||
if (top > height) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// #endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// 空函数,禁止选中
|
||||
const placeholderEvent = ()=>{}
|
||||
|
||||
// 页面onShow调用时,也会触发改方法
|
||||
const refresh = ()=>{
|
||||
nextTick(()=>{
|
||||
topTabbarRef.value?.refresh();
|
||||
})
|
||||
}
|
||||
|
||||
// 当页面滚动值超出轮播搜索滚动值时,carouselSearchScrollBool会变成true,触发相对应变化
|
||||
let carouselSearchScrollBool = ref(false)
|
||||
// 当页面滚动值超出轮播搜索滚动值时,top-tabbar会变成true,触发相对应变化
|
||||
let topTabbarScrollBool = ref(false)
|
||||
onPageScroll((e)=>{
|
||||
// 轮播搜索
|
||||
if(e.scrollTop > carouselSearchScrollValue){
|
||||
carouselSearchScrollBool.value = true
|
||||
}else{
|
||||
carouselSearchScrollBool.value = false
|
||||
}
|
||||
// top-tabbar
|
||||
if(e.scrollTop > topTabbarScrollValue){
|
||||
topTabbarScrollBool.value = true
|
||||
}else{
|
||||
topTabbarScrollBool.value = false
|
||||
}
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
refresh
|
||||
})
|
||||
defineExpose({
|
||||
refresh: diyGroup.refresh
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
|
||||
163
uni-app/src/addon/components/diy/group/useDiyGroup.ts
Normal file
163
uni-app/src/addon/components/diy/group/useDiyGroup.ts
Normal file
@ -0,0 +1,163 @@
|
||||
import { ref, reactive, onMounted, nextTick, computed } from 'vue';
|
||||
import Sortable from 'sortablejs';
|
||||
import { range } from 'lodash-es';
|
||||
import { onPageScroll, onHide, onShow } from '@dcloudio/uni-app';
|
||||
import useDiyStore from '@/app/stores/diy';
|
||||
import { getLocation } from '@/utils/common';
|
||||
|
||||
export function useDiyGroup(params: any = {}) {
|
||||
|
||||
let scrollVal = ""; //组件滚动值集合
|
||||
const componentsScrollBool = ref({}); //组件是否根据滚动进行相应改变
|
||||
const diyStore = useDiyStore();
|
||||
|
||||
const positionFixed = ref(['fixed', 'top_fixed', 'right_fixed', 'bottom_fixed', 'left_fixed']);
|
||||
|
||||
const data = computed(() => {
|
||||
if (diyStore.mode == 'decorate') {
|
||||
return diyStore;
|
||||
} else {
|
||||
return params.data;
|
||||
}
|
||||
})
|
||||
|
||||
const getComponentClass = (index: any, component: any) => {
|
||||
let obj: any = {
|
||||
relative: true,
|
||||
selected: diyStore.currentIndex == index,
|
||||
decorate: diyStore.mode == 'decorate'
|
||||
}
|
||||
obj['top-fixed-' + diyStore.topFixedStatus] = true;
|
||||
|
||||
if (component.position && positionFixed.value.indexOf(component.position) != -1) {
|
||||
// 找出置顶组件,设置禁止拖动
|
||||
obj['ignore-draggable-element'] = true;
|
||||
} else {
|
||||
obj['draggable-element'] = true;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
// 是否显示占位区域,用于禁止选中负上边距的内容
|
||||
const isShowPlaceHolder = (index: any, component: any) => {
|
||||
// #ifdef H5
|
||||
if (diyStore.mode == 'decorate') {
|
||||
let el: any = document.getElementById('componentList');
|
||||
if (el && el.children.length && el.children[index]) {
|
||||
let height = el.children[index].offsetHeight;
|
||||
let top = 0;
|
||||
if (component.margin.top < 0) {
|
||||
top = component.margin.top * 2 * -1;
|
||||
// 若负上边距大于组件的高度,则允许选中进行装修
|
||||
if (top > height) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// #endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 监听页面加载完成
|
||||
const onMountedLifeCycle = () => {
|
||||
onMounted(() => {
|
||||
// #ifdef H5
|
||||
if (diyStore.mode == 'decorate') {
|
||||
var el = document.getElementById('componentList');
|
||||
const sortable = Sortable.create(el, {
|
||||
draggable: '.draggable-element',
|
||||
animation: 200,
|
||||
// 结束拖拽
|
||||
onEnd: event => {
|
||||
let temp = diyStore.value[event.oldIndex!];
|
||||
diyStore.value.splice(event.oldIndex!, 1);
|
||||
diyStore.value.splice(event.newIndex!, 0, temp);
|
||||
|
||||
nextTick(() => {
|
||||
sortable.sort(range(diyStore.value.length).map(value => {
|
||||
return value.toString();
|
||||
}));
|
||||
|
||||
diyStore.postMessage(event.newIndex, diyStore.value[event.newIndex]);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
if (data.value.global && data.value.global.topStatusBar && data.value.global.topStatusBar.style == 'style-4') {
|
||||
// 第一次获取经纬度
|
||||
getLocation()
|
||||
}
|
||||
}, 500)
|
||||
|
||||
// 初始化组件滚动值
|
||||
scrollVal = uni.getStorageSync('componentsScrollValGroup');
|
||||
if (scrollVal) {
|
||||
for (let key in scrollVal) {
|
||||
componentsScrollBool.value[key] = -1;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// 页面onShow调用时,也会触发改方法
|
||||
const refresh = () => {
|
||||
|
||||
nextTick(() => {
|
||||
params.getFormRef().topTabbarRef?.refresh();
|
||||
})
|
||||
}
|
||||
|
||||
// 空函数,禁止选中
|
||||
const placeholderEvent = () => {
|
||||
}
|
||||
|
||||
let isPagesHide = ref(false)
|
||||
onShow(() => {
|
||||
isPagesHide.value = false;
|
||||
})
|
||||
onHide(() => {
|
||||
isPagesHide.value = true;
|
||||
})
|
||||
|
||||
// 监听滚动事件
|
||||
let scrollValStr = ref()
|
||||
const onPageScrollLifeCycle = () => {
|
||||
onPageScroll((e) => {
|
||||
if (scrollVal && !isPagesHide.value) {
|
||||
for (let key in scrollVal) {
|
||||
if (e.scrollTop <= 0) {
|
||||
// -1 表示页面滚动值小于零,组件随页面下拉而下来
|
||||
componentsScrollBool.value[key] = -1;
|
||||
} else if (e.scrollTop > scrollVal[key]) {
|
||||
// 1 表示页面滚动值大于传入滚动值,组件随页面上拉背景、文字颜色等采用滚动后的变量
|
||||
componentsScrollBool.value[key] = 1;
|
||||
} else {
|
||||
// 2 表示页面滚动值小于传入滚动值,组件随页面下拉背景、文字颜色等采用滚动前的变量
|
||||
componentsScrollBool.value[key] = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
scrollV: scrollValStr.value,
|
||||
data: data.value,
|
||||
componentsScrollBool: componentsScrollBool.value,
|
||||
placeholderEvent,
|
||||
refresh,
|
||||
isShowPlaceHolder,
|
||||
getComponentClass,
|
||||
onPageScroll: onPageScrollLifeCycle,
|
||||
onMounted: onMountedLifeCycle
|
||||
}
|
||||
}
|
||||
@ -61,6 +61,9 @@ export function wechatUser(data : AnyObject) {
|
||||
* 微信公众号授权信息登录(openid)
|
||||
*/
|
||||
export function wechatUserLogin(data : AnyObject) {
|
||||
if(uni.getStorageSync('pid')){
|
||||
data.pid = uni.getStorageSync('pid');
|
||||
}
|
||||
return request.post('wechat/userlogin', data, { showErrorMessage: true })
|
||||
}
|
||||
|
||||
@ -68,16 +71,34 @@ export function wechatUserLogin(data : AnyObject) {
|
||||
* 微信公众号授权登录
|
||||
*/
|
||||
export function wechatLogin(data : AnyObject) {
|
||||
if(uni.getStorageSync('pid')){
|
||||
data.pid = uni.getStorageSync('pid');
|
||||
}
|
||||
return request.post('wechat/login', data, { showErrorMessage: false })
|
||||
}
|
||||
/**
|
||||
* 微信公众号号修改openid
|
||||
*/
|
||||
export function updateWechatOpenid(data : AnyObject) {
|
||||
return request.put('wechat/update_openid', data, { showErrorMessage: false })
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信小程序授权登录
|
||||
*/
|
||||
export function weappLogin(data : AnyObject) {
|
||||
if(uni.getStorageSync('pid')){
|
||||
data.pid = uni.getStorageSync('pid');
|
||||
}
|
||||
return request.post('weapp/login', data, { showErrorMessage: false })
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信小程序修改openid
|
||||
*/
|
||||
export function updateWeappOpenid(data : AnyObject) {
|
||||
return request.put('weapp/update_openid', data, { showErrorMessage: false })
|
||||
}
|
||||
/**
|
||||
* 绑定手机号
|
||||
*/
|
||||
|
||||
@ -10,7 +10,12 @@ export function getMemberInfo() {
|
||||
export function getPointList(data : AnyObject) {
|
||||
return request.get('member/account/point', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分来源用途
|
||||
*/
|
||||
export function getPointType(account_type : string) {
|
||||
return request.get(`member/account/fromtype/${account_type}`)
|
||||
}
|
||||
/**
|
||||
* 获取不可提现余额流水
|
||||
*/
|
||||
|
||||
@ -11,7 +11,7 @@ export function getCaptcha() {
|
||||
* 获取微信公众号授权码
|
||||
*/
|
||||
export function getWechatAuthCode(data: AnyObject) {
|
||||
return request.get('wechat/codeurl', data, {showErrorMessage: false})
|
||||
return request.get('wechat/codeurl', data, {showErrorMessage: false })
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,13 +116,6 @@ export function getAddressByLatlng(params: Record<string, any>) {
|
||||
return request.get(`area/address_by_latlng`, params, {showErrorMessage: true})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取手机端首页列表
|
||||
*/
|
||||
export function getWapIndexList(data: AnyObject) {
|
||||
return request.get('wap_index', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取海报
|
||||
* @returns
|
||||
|
||||
@ -3,45 +3,41 @@ import request from '@/utils/request'
|
||||
/**
|
||||
* 获取核销信息
|
||||
*/
|
||||
export function getVerifyCode(type: string ,params: AnyObject) {
|
||||
return request.get('verify', {type, data: params})
|
||||
export function getVerifyCode(type: string, params: AnyObject) {
|
||||
return request.get('verify', { type, data: params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取核销记录
|
||||
*/
|
||||
export function getVerifyRecords(params: Record<string, any>) {
|
||||
return request.get('verify_records', params)
|
||||
return request.get('verify_records', params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是核销员
|
||||
*/
|
||||
export function getCheckVerifier() {
|
||||
return request.get('check_verifier')
|
||||
return request.get('check_verifier')
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取核销信息
|
||||
*/
|
||||
export function getVerifierInfo(code: string) {
|
||||
return request.get(`get_verify_by_code/${code}`)
|
||||
return request.get(`get_verify_by_code/${ code }`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销
|
||||
*/
|
||||
export function verify(code: string) {
|
||||
return request.post(`verify/${code}`,{}, { showSuccessMessage: true, showErrorMessage: true })
|
||||
return request.post(`verify/${ code }`, {}, { showErrorMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取核销详情
|
||||
*/
|
||||
export function getVerifyDetail(code: string) {
|
||||
return request.get(`verify_detail/${code}`,{}, { showErrorMessage: true })
|
||||
}
|
||||
|
||||
|
||||
|
||||
return request.get(`verify_detail/${ code }`, {}, { showErrorMessage: true })
|
||||
}
|
||||
@ -167,7 +167,7 @@
|
||||
uni.createSelectorQuery().in(instance).select('#item0'+diyComponent.value.id).boundingClientRect((data:any) => {
|
||||
itemStyle3.value = `margin-right:${(res.width - data.width*4)/3}px;`
|
||||
}).exec()
|
||||
}).exec()
|
||||
}).exec()
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
itemStyle3.value= 'margin-right:14rpx;'
|
||||
@ -182,7 +182,7 @@
|
||||
itemStyle4.value = `margin-right:${(res.width - data.width*4)/3}px;`
|
||||
|
||||
}).exec()
|
||||
}).exec()
|
||||
}).exec()
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
itemStyle4.value= 'margin-right:14rpx;'
|
||||
|
||||
@ -6,14 +6,13 @@
|
||||
<view v-else class="w-full h-full bg-[#ccc]"></view>
|
||||
<view class="bg-img-box" :style="bgImgBoxStyle"></view>
|
||||
</view>
|
||||
|
||||
<view class="fixed-wrap" :class="[ diyStore.mode != 'decorate' ? diyComponent.positionWay : '' ]" :style="fixedStyle">
|
||||
<view class="fixed-wrap" :style="fixedStyle">
|
||||
<view class="diy-search-wrap relative z-10" @click="diyStore.toRedirect(diyComponent.search.link)" :style="navbarInnerStyle">
|
||||
<view class="img-wrap" v-if="diyComponent.search.logo">
|
||||
<image :src="img(diyComponent.search.logo)" mode="aspectFit"/>
|
||||
</view>
|
||||
<view class="search-content">
|
||||
<input type="text" class="uni-input" placeholder-style="color:#fff" placeholder-class="!text-[#fff] text-[24rpx] leading-[68rpx]" :placeholder="isShowSearchPlaceholder ? diyComponent.search.text : ''" disabled="true"/>
|
||||
<view class="search-content" @click="diyStore.toRedirect(diyComponent.search.link)">
|
||||
<text class="input-content text-[#fff] text-[24rpx] leading-[68rpx]">{{isShowSearchPlaceholder ? diyComponent.search.text : ''}}</text>
|
||||
<text class="nc-iconfont nc-icon-sousuo-duanV6xx1"></text>
|
||||
|
||||
<swiper class="swiper-wrap" :interval="diyComponent.search.hotWord.interval * 1000" autoplay="true" vertical="true" circular="true" v-if="!isShowSearchPlaceholder">
|
||||
@ -47,7 +46,7 @@
|
||||
|
||||
<!-- 解决fixed定位后导航栏塌陷的问题 -->
|
||||
<template v-if="diyStore.mode != 'decorate'">
|
||||
<view v-if="diyComponent.positionWay == 'fixed'" class="u-navbar-placeholder" :style="{ width: '100%', paddingTop: moduleHeight }"></view>
|
||||
<view v-if="diyComponent.positionWay == 'fixed' && props.scrollBool != -1" class="u-navbar-placeholder" :style="{ width: '100%', paddingTop: moduleHeight }"></view>
|
||||
</template>
|
||||
|
||||
<!-- 轮播图 -->
|
||||
@ -118,8 +117,7 @@
|
||||
import { getDiyInfo } from '@/app/api/diy';
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount', 'global','scrollTop']);
|
||||
|
||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount', 'global', 'scrollBool']);
|
||||
const diyStore = useDiyStore();
|
||||
|
||||
const diyComponent = computed(() => {
|
||||
@ -172,7 +170,12 @@
|
||||
style += 'top:' + diyStore.topTabarHeight + 'px;';
|
||||
}
|
||||
// #endif
|
||||
|
||||
if(diyComponent.value.positionWay == 'fixed') {
|
||||
if (props.scrollBool != -1) {
|
||||
style += 'position: fixed;z-index: 10;left: 0;right: 0;';
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
||||
if(props.global.topStatusBar.isShow) {
|
||||
@ -181,7 +184,7 @@
|
||||
// #endif
|
||||
|
||||
fixedStyleBg.value = false;
|
||||
if (props.scrollTop) {
|
||||
if (props.scrollBool == 1) {
|
||||
let str = diyComponent.value.fixedBgColor;
|
||||
let arr = str.split(',');
|
||||
let num = diyComponent.value.fixedBgColor ? parseInt(arr[arr.length-1]) : 0;
|
||||
@ -200,12 +203,12 @@
|
||||
let color = '';
|
||||
if(flag){
|
||||
color = diyComponent.value.tab.selectColor;
|
||||
if(diyComponent.value.positionWay == 'fixed' && props.scrollTop) {
|
||||
if(diyComponent.value.positionWay == 'fixed' && props.scrollBool == 1) {
|
||||
color = diyComponent.value.tab.fixedSelectColor;
|
||||
}
|
||||
}else{
|
||||
color = diyComponent.value.tab.noColor;
|
||||
if(diyComponent.value.positionWay == 'fixed' && props.scrollTop) {
|
||||
if(diyComponent.value.positionWay == 'fixed' && props.scrollBool == 1) {
|
||||
color = diyComponent.value.tab.fixedNoColor;
|
||||
}
|
||||
}
|
||||
@ -288,9 +291,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
let tabAllPopup = ref(false);
|
||||
const tabAllPopup = ref(false);
|
||||
let menuButtonInfo:any = {};
|
||||
let navbarInnerStyle = ref('')
|
||||
const navbarInnerStyle = ref('')
|
||||
|
||||
onMounted(() => {
|
||||
refresh();
|
||||
@ -397,10 +400,19 @@
|
||||
isShowDots.value = false;
|
||||
// #endif
|
||||
|
||||
// 表示轮播搜素组件,需要判断滚动超出20时,需要做相对应反应
|
||||
defineExpose({
|
||||
scrollValue: 20
|
||||
})
|
||||
/******************************* 存储滚动值-start ***********************/
|
||||
// 键名和组件名一致即可
|
||||
let componentsScrollVal = uni.getStorageSync('componentsScrollValGroup')
|
||||
if(componentsScrollVal && (typeof componentsScrollVal == "object")){
|
||||
componentsScrollVal.CarouselSearch = 20
|
||||
uni.setStorageSync('componentsScrollValGroup', componentsScrollVal);
|
||||
}else{
|
||||
let obj = {
|
||||
CarouselSearch: 20
|
||||
}
|
||||
uni.setStorageSync('componentsScrollValGroup', obj);
|
||||
}
|
||||
/******************************* 存储滚动值-end ***********************/
|
||||
|
||||
</script>
|
||||
|
||||
@ -463,12 +475,12 @@
|
||||
.search-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 40rpx;
|
||||
padding: 0 32rpx;
|
||||
border-radius: 50rpx;
|
||||
background-color: rgba(255,255,255,.2);
|
||||
flex: 1;
|
||||
position: relative;
|
||||
input, .uni-input {
|
||||
.input-content, .uni-input {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
height: 64rpx;
|
||||
|
||||
@ -1,17 +1,34 @@
|
||||
<template>
|
||||
<view :style="warpCss">
|
||||
<view :class="['float-btn flex flex-col z-1000 items-center px-[24rpx] fixed', diyComponent.bottomPosition, diyStore.mode == 'decorate' ? 'float-btn-border' : '']" :style="floatBtnWrapCss">
|
||||
<view class="float-btn fixed z-1000" :class="[diyComponent.style,diyComponent.bottomPosition, diyStore.mode == 'decorate' ? 'float-btn-border' : '']" :style="floatBtnWrapCss">
|
||||
<view v-if="diyComponent.style==='style-1'" class="flex flex-col items-center p-[24rpx]" :style="warpCss">
|
||||
<view v-for="(item,index) in diyComponent.list" :key="index" @click="diyStore.toRedirect(item.link)" :class="{'flex items-center justify-center' : true, 'mb-[20rpx]': diyComponent.list.length != index+1 }" :style="floatBtnItemCss">
|
||||
<image v-if="item && item.imageUrl" :style="floatBtnItemCss" :src="img(item.imageUrl)" mode="aspectFit"></image>
|
||||
<image v-else :src="img('static/resource/images/diy/figure.png')" mode="aspectFit" :style="floatBtnItemCss"/>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view v-if="diyComponent.style==='style-2'" class="relative w-[3rpx] h-[3rpx]">
|
||||
<view class="py-[14rpx] overflow-hidden absolute right-[25rpx] top-[1rpx] transform -translate-y-1/2" :style="styleTwoWarpCss">
|
||||
<swiper :style="{'width':diyComponent.imageSize * 2+24+'rpx','height':diyComponent.imageSize * 2+44+'rpx !important',}" circular>
|
||||
<swiper-item v-for="(item,index) in diyComponent.list" :key="index">
|
||||
<view @click="diyStore.toRedirect(item.link)" class="px-[12rpx] flex flex-col items-center justify-center">
|
||||
<image v-if="item && item.imageUrl" :style="floatBtnItemCss" :src="img(item.imageUrl)" mode="aspectFit"></image>
|
||||
<image v-else :src="img('static/resource/images/diy/figure.png')" mode="aspectFit" :style="floatBtnItemCss"/>
|
||||
<view class="text-[24rpx] text-[303133] text-center mt-[20rpx]">{{ item.link.title }}</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<view class="w-[60rpx] h-[60rpx] absolute right-[-64rpx] top-[1rpx] transform -translate-y-1/2 rounded-[30rpx] flex items-center" :style="styleTwoSphere">
|
||||
<text class="!text-[60rpx] iconfont iconxiaolian-1 text-[var(--primary-color)] font-400 transform rotate-90 translate-x-[-13rpx]"></text>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// 浮动按钮组件
|
||||
import { computed, watch } from 'vue';
|
||||
import { computed, watch,ref } from 'vue';
|
||||
import { onPageScroll } from '@dcloudio/uni-app';
|
||||
import useDiyStore from '@/app/stores/diy';
|
||||
import { img } from '@/utils/common';
|
||||
|
||||
@ -37,6 +54,7 @@
|
||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
||||
|
||||
return style;
|
||||
})
|
||||
|
||||
@ -52,14 +70,49 @@
|
||||
let style = '';
|
||||
if(diyComponent.value.offset){
|
||||
if(diyComponent.value.bottomPosition == 'lowerRight' || diyComponent.value.bottomPosition == 'lowerLeft'){
|
||||
style += 'padding-bottom:'+ diyComponent.value.offset * 2 + 'rpx;';
|
||||
style += 'transform: translateY('+ ((-diyComponent.value.offset) * 2) + 'rpx)';
|
||||
}else if(diyComponent.value.bottomPosition == 'upperRight' || diyComponent.value.bottomPosition == 'upperLeft'){
|
||||
style += 'padding-top:'+ diyComponent.value.offset * 2 + 'rpx;';
|
||||
style += 'transform: translateX('+ diyComponent.value.offset * 2 + 'rpx);';
|
||||
}
|
||||
}
|
||||
return style;
|
||||
})
|
||||
|
||||
//样式二
|
||||
const styleTwoRepeat = ref(true)
|
||||
const styleTwoRepeatTime = ref(null)
|
||||
const styleTwoWarpCss = computed(() => {
|
||||
var style = '';
|
||||
if(diyComponent.value.componentStartBgColor) {
|
||||
if (diyComponent.value.componentStartBgColor && diyComponent.value.componentEndBgColor) style += `background:linear-gradient(${diyComponent.value.componentGradientAngle},${diyComponent.value.componentStartBgColor},${diyComponent.value.componentEndBgColor});`;
|
||||
else style += 'background-color:' + diyComponent.value.componentStartBgColor + ';';
|
||||
}
|
||||
if (diyComponent.value.topRounded) style += 'border-top-left-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
||||
if (diyComponent.value.topRounded) style += 'border-top-right-radius:' + diyComponent.value.topRounded * 2 + 'rpx;';
|
||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
||||
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
|
||||
style += 'transition: right .25s;box-shadow:0px 32rpx 96rpx 32rpx rgba(0, 0, 0, .08), 0px 24rpx 64px rgba(0, 0, 0, .12), 0px 16rpx 32rpx -16rpx rgba(0, 0, 0, .16);'
|
||||
style +=styleTwoRepeat.value?'transition-delay: 0.25s;':('right:-'+(diyComponent.value.imageSize * 2+24)+'rpx !important;');
|
||||
return style;
|
||||
})
|
||||
|
||||
const styleTwoSphere = computed(()=>{
|
||||
var style = 'transition: right .25s;background: rgba(0, 0, 0, 0.5);';
|
||||
style +=styleTwoRepeat.value?'':'right:-32rpx !important;transition-delay: 0.25s;';
|
||||
return style
|
||||
})
|
||||
|
||||
onPageScroll(() => {
|
||||
if(diyComponent.value.style==='style-2'){
|
||||
if(styleTwoRepeatTime) clearTimeout(styleTwoRepeatTime.value)
|
||||
styleTwoRepeat.value = false
|
||||
styleTwoRepeatTime.value = setTimeout(()=>{
|
||||
styleTwoRepeat.value = true
|
||||
clearTimeout(styleTwoRepeatTime.value)
|
||||
},200)
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.pullDownRefreshCount,
|
||||
(newValue, oldValue) => {
|
||||
@ -70,20 +123,20 @@
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.float-btn{
|
||||
&.decorate-position.upperRight,&.decorate-position.lowerRight {
|
||||
align-items: flex-end;
|
||||
}
|
||||
&.decorate-position.upperLeft,&.decorate-position.lowerLeft {
|
||||
align-items: baseline;
|
||||
}
|
||||
&.upperLeft {
|
||||
top: 100rpx;
|
||||
left: 30rpx;
|
||||
&.style-2{
|
||||
left:0 ;
|
||||
}
|
||||
}
|
||||
|
||||
&.upperRight {
|
||||
top: 100rpx;
|
||||
right: 30rpx;
|
||||
&.style-2{
|
||||
right:0 ;
|
||||
}
|
||||
}
|
||||
|
||||
&.lowerLeft {
|
||||
@ -93,6 +146,10 @@
|
||||
/*兼容 IOS<11.2*/
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
/*兼容 IOS>11.2*/
|
||||
&.style-2{
|
||||
left:0 ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.lowerRight {
|
||||
@ -102,6 +159,9 @@
|
||||
/*兼容 IOS<11.2*/
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
/*兼容 IOS>11.2*/
|
||||
&.style-2{
|
||||
right:0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
.z-1000{
|
||||
|
||||
@ -40,9 +40,9 @@
|
||||
|
||||
<template v-for="(item, index) in diyComponent.list">
|
||||
|
||||
<view class="graphic-nav-item" :class="[diyComponent.mode]" :key="item.id" v-if="swiperCondition(index,numItem)" :style="{ width: 100 / diyComponent.rowCount + '%' }">
|
||||
<view :class="[diyComponent.mode]" :key="item.id" v-if="swiperCondition(index,numItem)" :style="{ width: 100 / diyComponent.rowCount + '%' }">
|
||||
|
||||
<view @click="diyStore.toRedirect(item.link)" class="flex flex-col items-center box-border py-2">
|
||||
<view @click="diyStore.toRedirect(item.link)" class="graphic-nav-item flex flex-col items-center box-border py-2">
|
||||
|
||||
<view class="graphic-img relative flex items-center justify-center w-10 h-10"
|
||||
v-if="diyComponent.mode != 'text'"
|
||||
@ -72,6 +72,45 @@
|
||||
</template>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
<scroll-view v-else-if="diyComponent.layout == 'horizontal' && diyComponent.pageCount == 2 && diyComponent.showStyle == 'singleSlide'" :scroll-x="diyComponent.showStyle == 'singleSlide'" :class="['graphic-nav','graphic-nav-' + diyComponent.showStyle]" class="py-[10rpx]">
|
||||
<!-- #ifdef MP -->
|
||||
<view class="uni-scroll-view-content">
|
||||
<!-- #endif -->
|
||||
<view :style="horizontalSingleSlideStyle" class="flex">
|
||||
<view class="graphic-nav-wrap flex flex-wrap" :style="horizontalSingleSlideBoxStyle(numIndex)" v-for="(numItem, numIndex) in Math.ceil(diyComponent.list.length / (diyComponent.pageCount * diyComponent.rowCount))">
|
||||
<template v-for="(item, index) in diyComponent.list">
|
||||
|
||||
<view v-if="swiperCondition(index,numItem)" @click="diyStore.toRedirect(item.link)" :style="horizontalSingleSlideItemStyle(numIndex)" class="graphic-nav-item flex flex-col items-center box-border py-2">
|
||||
<view class="graphic-img relative flex items-center justify-center w-10 h-10"
|
||||
v-if="diyComponent.mode != 'text'"
|
||||
:style="{ width: diyComponent.imageSize * 2 + 'rpx', height: diyComponent.imageSize * 2 + 'rpx' }">
|
||||
<image v-if="item.imageUrl" :src="img(item.imageUrl)" mode="aspectFill"
|
||||
:style="{ maxWidth: diyComponent.imageSize * 2 + 'rpx', maxHeight: diyComponent.imageSize * 2 + 'rpx', borderRadius: diyComponent.aroundRadius * 2 + 'rpx' }"/>
|
||||
<image v-else :src="img('static/resource/images/diy/figure.png')" mode="aspectFill"
|
||||
:style="{ maxWidth: diyComponent.imageSize * 2 + 'rpx', maxHeight: diyComponent.imageSize * 2 + 'rpx', borderRadius: diyComponent.aroundRadius * 2 + 'rpx' }"/>
|
||||
<text
|
||||
:class="['tag absolute -top-[10rpx] -right-[24rpx] text-white rounded-[24rpx] rounded-bl-none transform scale-80 py-1 px-2 text-xs']"
|
||||
v-if="item.label.control"
|
||||
:style="{ color: item.label.textColor, backgroundImage: 'linear-gradient(' + item.label.bgColorStart + ',' + item.label.bgColorEnd + ')' }">
|
||||
{{ item.label.text }}
|
||||
</text>
|
||||
</view>
|
||||
<text v-if="diyComponent.mode != 'img'"
|
||||
class="graphic-text w-full text-center truncate leading-normal"
|
||||
:class="{ 'pt-1.5' : diyComponent.mode != 'text' }"
|
||||
:style="{ fontSize: diyComponent.font.size * 2 + 'rpx', fontWeight: diyComponent.font.weight, color: diyComponent.font.color }">
|
||||
{{ item.title }}
|
||||
</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #ifdef MP -->
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
</scroll-view>
|
||||
|
||||
<scroll-view v-else :scroll-x="diyComponent.showStyle == 'singleSlide'" :class="['graphic-nav','graphic-nav-' + diyComponent.showStyle]" class=" py-[10rpx]">
|
||||
<!-- #ifdef MP -->
|
||||
@ -170,6 +209,48 @@
|
||||
|
||||
return style;
|
||||
});
|
||||
|
||||
// 多行,单行滑动样式
|
||||
const horizontalSingleSlideStyle = computed(()=>{
|
||||
let style = {width: ""};
|
||||
let widthStr = 100 / diyComponent.value.rowCount; // 表示每项宽度
|
||||
let itemLen = (parseInt(diyComponent.value.list.length / (diyComponent.value.rowCount*2))*diyComponent.value.rowCount) + (diyComponent.value.list.length%(diyComponent.value.rowCount*2)); // 表示展示几列
|
||||
let marginLen = diyComponent.value.margin.both*4
|
||||
style.width = `calc(${widthStr * itemLen}vw - ${marginLen}rpx)`;
|
||||
return style;
|
||||
})
|
||||
|
||||
const horizontalSingleSlideBoxStyle = (index: any)=>{
|
||||
let style = {width: ""};
|
||||
let widthStr = 100 / diyComponent.value.rowCount; // 表示每项宽度
|
||||
let marginLen = diyComponent.value.margin.both * 4 / diyComponent.value.rowCount;
|
||||
if(parseInt(diyComponent.value.list.length / (diyComponent.value.rowCount*2)) >= (index+1)){
|
||||
style.width = `calc(${widthStr * diyComponent.value.rowCount}vw - ${marginLen*diyComponent.value.rowCount}rpx)`;
|
||||
}else{
|
||||
let len = diyComponent.value.list.length%(diyComponent.value.rowCount*2);
|
||||
if(len > diyComponent.value.rowCount){ // 满足了一行,但没有满足于一页
|
||||
style.width = `calc(${widthStr * diyComponent.value.rowCount}vw - ${marginLen*diyComponent.value.rowCount}rpx)`;
|
||||
}else{
|
||||
style.width = `calc(${widthStr * len}vw - ${marginLen * len}rpx)`; // 未满足了一行
|
||||
}
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
const horizontalSingleSlideItemStyle = (index: any)=>{
|
||||
let style = {width: ""};
|
||||
if(parseInt(diyComponent.value.list.length / (diyComponent.value.rowCount*2)) >= (index+1)){
|
||||
style.width = `${100 / diyComponent.value.rowCount}%`;
|
||||
}else{
|
||||
let len = diyComponent.value.list.length%(diyComponent.value.rowCount*2);
|
||||
if(len > diyComponent.value.rowCount){ // 满足了一行,但没有满足于一页
|
||||
style.width = `${100 / diyComponent.value.rowCount}%`;
|
||||
}else{
|
||||
style.width = `${100 / len}%`; // 未满足了一行
|
||||
}
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.pullDownRefreshCount,
|
||||
@ -187,14 +268,8 @@
|
||||
const swiperCondition = (index, numItem) => {
|
||||
let count = diyComponent.value.pageCount * diyComponent.value.rowCount;
|
||||
let result = true;
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
result = index >= [(numItem) * (count)] && index < [(numItem + 1) * (count)];
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
|
||||
result = index >= [(numItem - 1) * (count)] && index < [numItem * (count)];
|
||||
// #endif
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -206,7 +281,11 @@
|
||||
var height = 0;
|
||||
const query = uni.createSelectorQuery().in(instance);
|
||||
query.select('.graphic-nav-item').boundingClientRect((data: any) => {
|
||||
height = data.height * diyComponent.value.pageCount;
|
||||
let len = 1;
|
||||
if(diyComponent.value.pageCount == 2){
|
||||
len = (diyComponent.value.list.length / diyComponent.value.rowCount) > 1 ? 2 : 1 ;
|
||||
}
|
||||
height = data.height * len;
|
||||
swiperHeight.value = (height * 2) + 'rpx';
|
||||
}).exec();
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<!-- #endif -->
|
||||
<view v-if="info" class="flex ml-[32rpx] mr-[52rpx] items-center relative">
|
||||
<!-- 唤起获取微信 -->
|
||||
<u-avatar :src="img(info.headimg)" size="55" leftIcon="none" @click="clickAvatar"></u-avatar>
|
||||
<u-avatar :src="img(info.headimg)" size="55" leftIcon="none" :default-url="img('static/resource/images/default_headimg.png')" @click="clickAvatar"></u-avatar>
|
||||
<view class="ml-[22rpx]">
|
||||
<view class="text-[#222222] flex pr-[50rpx] flex-wrap items-center">
|
||||
<view class="text-[#222222] truncate max-w-[320rpx] font-bold text-lg mr-[16rpx]" :style="{ color : diyComponent.textColor }">{{ info.nickname }}</view>
|
||||
@ -21,7 +21,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="flex ml-[32rpx] mr-[52rpx] items-center relative" @click="toLogin">
|
||||
<u-avatar src="" size="55"></u-avatar>
|
||||
<u-avatar src="" size="55" :default-url="img('static/resource/images/default_headimg.png')" />
|
||||
<view class="ml-[22rpx]">
|
||||
<view class="text-[#222222] font-bold text-lg" :style="{ color : diyComponent.textColor }">
|
||||
{{ t('login') }}/{{ t('register') }}
|
||||
@ -58,6 +58,11 @@
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<information-filling ref="infoFill"></information-filling>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -69,9 +74,11 @@
|
||||
import { t } from '@/locale'
|
||||
import { wechatSync } from '@/app/api/system'
|
||||
import useDiyStore from '@/app/stores/diy'
|
||||
import useConfigStore from '@/stores/config'
|
||||
|
||||
const props = defineProps(['component', 'index', 'pullDownRefreshCount','global']);
|
||||
|
||||
const configStore = useConfigStore()
|
||||
const diyStore = useDiyStore();
|
||||
|
||||
const diyComponent = computed(() => {
|
||||
@ -144,7 +151,21 @@
|
||||
})
|
||||
|
||||
const toLogin = () => {
|
||||
useLogin().setLoginBack({ url: '/app/pages/member/index' })
|
||||
if(configStore.login.is_username || configStore.login.is_mobile || configStore.login.is_bind_mobile){
|
||||
useLogin().setLoginBack({ url: '/app/pages/member/index' })
|
||||
}else if(configStore.login.is_auth_register){ // 判断是否开启第三方自动注册登录
|
||||
// 第三方平台自动登录
|
||||
// #ifdef MP
|
||||
useLogin().getAuthCode()
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
if (isWeixinBrowser()) {
|
||||
useLogin().getAuthCode('snsapi_userinfo')
|
||||
}
|
||||
// #endif
|
||||
}else{
|
||||
uni.showToast({ title: '商家未开启注册方式', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
const infoFill = ref(false)
|
||||
|
||||
@ -25,22 +25,25 @@
|
||||
</view>
|
||||
<view v-if="diyComponent.style == 'style-3'" class="rounded-[16rpx] style-bg-3 p-[30rpx]">
|
||||
<view class="flex items-center justify-between style-border-3 mb-[22rpx] pb-[22rpx]">
|
||||
<view class="flex flex-col">
|
||||
<view class="flex items-center">
|
||||
<view class="flex justify-end leading-[30rpx] box-border text-[#fff] pr-[10rpx] text-[26rpx] w-[120rpx] h-[30rpx] bg-contain bg-no-repeat" :style="{'backgroundImage': 'url('+img('static/resource/images/diy/member/VIP.png')+')'}">
|
||||
VIP.{{currIndex}}
|
||||
<view class="flex flex-col flex-1">
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="flex items-center">
|
||||
<view class="flex justify-end leading-[30rpx] box-border text-[#fff] pr-[10rpx] text-[26rpx] w-[120rpx] h-[30rpx] bg-contain bg-no-repeat" :style="{'backgroundImage': 'url('+img('static/resource/images/diy/member/VIP.png')+')'}">
|
||||
VIP.{{currIndex}}
|
||||
</view>
|
||||
<text class="text-[#733F02] ml-[8rpx] text-[30rpx] font-bold max-w-[380rpx] truncate">{{info.member_level_name}}</text>
|
||||
</view>
|
||||
<view class="flex items-center" @click="toLink('/app/pages/member/level')">
|
||||
<view class="flex items-center">
|
||||
<image :src="img('static/resource/images/diy/member/rule.png')" mode="aspectFit" class="w-[20rpx] h-[20rpx]" />
|
||||
<text class="text-[18rpx] text-[#733F02] ml-[6rpx] leading-[24rpx]">规则</text>
|
||||
</view>
|
||||
<view class="ml-[6rpx] text-[#733F02] !text-[26rpx] nc-iconfont nc-icon-youV6xx"></view>
|
||||
</view>
|
||||
<text class="text-[#733F02] ml-[8rpx] text-[30rpx] font-bold max-w-[380rpx] truncate">{{info.member_level_name}}</text>
|
||||
</view>
|
||||
<text class="text-[28rpx] text-[#794200] mt-[16rpx]">购物或邀请好友可以提升等级</text>
|
||||
</view>
|
||||
<view class="flex items-center" @click="toLink('/app/pages/member/level')">
|
||||
<view class="flex flex-col items-center justify-center">
|
||||
<image :src="img('static/resource/images/diy/member/rule.png')" mode="aspectFit" class="w-[26rpx] h-[26rpx]" />
|
||||
<text class="text-[24rpx] text-[#733F02] mt-[10rpx]">规则</text>
|
||||
</view>
|
||||
<view class="ml-[10rpx] text-[#733F02] !text-[26rpx] nc-iconfont nc-icon-youV6xx"></view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="flex flex-col flex-1">
|
||||
|
||||
@ -14,10 +14,10 @@
|
||||
<view class="flex-1 flex overflow-hidden horizontal-body" :id="'horizontal-body-'+diyComponent.id" :class="{'items-center':diyComponent.scrollWay == 'upDown'}">
|
||||
<!-- 横向滚动 -->
|
||||
<view class="horizontal-wrap" :style="marqueeStyle" v-if="diyComponent.scrollWay == 'horizontal'">
|
||||
<view class="marquee marquee-one" id="marquee-one" >
|
||||
<view class="marquee marquee-one" id="marquee-one">
|
||||
<view class="item flex-shrink-0 !leading-[40rpx] h-[40rpx]" :class="{'ml-[80rpx]':index}" v-for="(item, index) in diyComponent.list" :key="index" @click="toRedirect(item)" :style="{ color: diyComponent.textColor, fontSize: diyComponent.fontSize * 2 + 'rpx', fontWeight: diyComponent.fontWeight }">{{ item.text }}</view>
|
||||
</view>
|
||||
<view class="marquee">
|
||||
<view class="marquee" v-if="marqueeBodyWidth < (marqueeOneWidth-30)">
|
||||
<view class="item flex-shrink-0 !leading-[40rpx] h-[40rpx]" :class="{'ml-[80rpx]':index}" v-for="(item, index) in diyComponent.list" :key="index" @click="toRedirect(item)" :style="{ color: diyComponent.textColor, fontSize: diyComponent.fontSize * 2 + 'rpx', fontWeight: diyComponent.fontWeight }">{{ item.text }}</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -117,14 +117,11 @@ watch(
|
||||
)
|
||||
|
||||
const marqueeBodyWidth = ref(0); // 容器宽度
|
||||
const marqueeOneWidth = ref(0); // 内容宽度
|
||||
const marqueeStyle = ref(''); // 横向滚动样式
|
||||
const time = ref(0); // 滚动完成时间
|
||||
const delayTime = ref(800); // 动画延迟时间
|
||||
// px转rpx
|
||||
const pxToRpx=(px)=> {
|
||||
const screenWidth = uni.getSystemInfoSync().screenWidth
|
||||
return (750 * Number.parseInt(px)) / screenWidth
|
||||
}
|
||||
|
||||
// 绑定横向滚动事件
|
||||
const bindCrossSlipEvent = ()=> {
|
||||
if (diyComponent.value.scrollWay == 'horizontal') {
|
||||
@ -135,9 +132,9 @@ const bindCrossSlipEvent = ()=> {
|
||||
marqueeBodyWidth.value = res.width;
|
||||
const query = uni.createSelectorQuery().in(instance);
|
||||
query.select('#horizontal-body-' + diyComponent.value.id + ' .marquee-one').boundingClientRect((data: any) => {
|
||||
const width = data.width
|
||||
time.value = Math.ceil(width * 14);
|
||||
if (marqueeBodyWidth.value > width) {
|
||||
marqueeOneWidth.value = data.width
|
||||
time.value = Math.ceil(marqueeOneWidth.value * 14);
|
||||
if (marqueeBodyWidth.value > (marqueeOneWidth.value-30)) {
|
||||
marqueeStyle.value = `animation: none;`;
|
||||
} else {
|
||||
marqueeStyle.value = `
|
||||
@ -152,9 +149,9 @@ const bindCrossSlipEvent = ()=> {
|
||||
let marqueeOne = window.document.getElementById('marquee-one');
|
||||
if(documentObj && marqueeOne) {
|
||||
marqueeBodyWidth.value = documentObj.offsetWidth;
|
||||
const width = marqueeOne.offsetWidth;
|
||||
time.value = Math.ceil(width * 14);
|
||||
if (marqueeBodyWidth.value > width) {
|
||||
marqueeOneWidth.value = marqueeOne.offsetWidth;
|
||||
time.value = Math.ceil(marqueeOneWidth.value * 14);
|
||||
if (marqueeBodyWidth.value > (marqueeOneWidth.value-30)) {
|
||||
marqueeStyle.value = `animation: none;`;
|
||||
} else {
|
||||
marqueeStyle.value = `
|
||||
@ -199,12 +196,11 @@ const refresh = ()=> {
|
||||
|
||||
const toRedirect = (data: {}) => {
|
||||
if (diyStore.mode == 'decorate') return false;
|
||||
|
||||
if (diyComponent.value.showType == 'popup') {
|
||||
noticeShow.value = true;
|
||||
noticeContent.value = data.text;
|
||||
} else {
|
||||
diyStore.toRedirect(data);
|
||||
diyStore.toRedirect(data.link);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -276,8 +272,7 @@ const toRedirect = (data: {}) => {
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
white-space: nowrap;
|
||||
padding-right: 60rpx;
|
||||
|
||||
padding-right: 30px;
|
||||
|
||||
// -webkit-perspective: 1000;
|
||||
// -moz-perspective: 1000;
|
||||
|
||||
@ -6,5 +6,6 @@
|
||||
"pleaceAgree": "请勾选已阅读并同意",
|
||||
"mobilePlaceholder": "请输入手机号",
|
||||
"codePlaceholder": "请输入验证码",
|
||||
"weixinUserAuth": "微信用户一键绑定"
|
||||
"weixinUserAuth": "一键绑定",
|
||||
"mobileQuickLogin": "手机号快捷登录"
|
||||
}
|
||||
@ -10,5 +10,6 @@
|
||||
"isAgreeTips": "请先阅读并同意协议",
|
||||
"usernameLogin": "密码登录",
|
||||
"mobileLogin": "验证码登录",
|
||||
"mobilePlaceholder": "请输入手机号"
|
||||
"mobilePlaceholder": "请输入手机号",
|
||||
"oneClicklogin":"一键登录"
|
||||
}
|
||||
@ -1,6 +1,11 @@
|
||||
<template>
|
||||
<view v-if="agreement" class="p-[30rpx]" :style="themeColor()">
|
||||
<u-parse :content="agreement.content" :tagStyle="{img: 'vertical-align: top;'}"></u-parse>
|
||||
<view :style="themeColor()">
|
||||
<view v-if="agreement && agreement.content" class="p-[30rpx]">
|
||||
<u-parse :content="agreement.content" :tagStyle="{img: 'vertical-align: top;'}"></u-parse>
|
||||
</view>
|
||||
<view v-else class="h-[100vh] w-full flex items-center justify-center">
|
||||
<u-empty :icon="img('static/resource/images/empty.png')" text="暂无协议" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -8,6 +13,7 @@
|
||||
import { ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { getAgreementInfo } from '@/app/api/system'
|
||||
import { img} from '@/utils/common'
|
||||
|
||||
const agreement = ref(null)
|
||||
|
||||
|
||||
@ -10,11 +10,11 @@
|
||||
<view class="px-[60rpx]">
|
||||
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
|
||||
<u-form-item label="" prop="mobile" :border-bottom="true">
|
||||
<u-input v-model="formData.mobile" border="none" clearable :placeholder="t('mobilePlaceholder')" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.mobile" border="none" clearable :placeholder="t('mobilePlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]"/>
|
||||
</u-form-item>
|
||||
<view class="mt-[40rpx]">
|
||||
<u-form-item label="" prop="mobile_code" :border-bottom="true">
|
||||
<u-input v-model="formData.mobile_code" border="none" clearable :placeholder="t('codePlaceholder')" class="!bg-transparent" :disabled="real_name_input">
|
||||
<u-input v-model="formData.mobile_code" border="none" clearable :placeholder="t('codePlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]">
|
||||
<template #suffix>
|
||||
<sms-code :mobile="formData.mobile" type="bind_mobile" v-model="formData.mobile_key"></sms-code>
|
||||
</template>
|
||||
@ -36,12 +36,12 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-[60rpx]">
|
||||
<u-button type="primary" :text="t('bind')" :loading="loading" :loadingText="t('binding')" @click="handleBind"></u-button>
|
||||
<button hover-class="none" class="bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" :loading="loading" :loadingText="t('binding')" @click="handleBind">{{t('bind')}}</button>
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="mt-[30rpx]">
|
||||
<u-button type="primary" :plain="true" :text="t('weixinUserAuth')" @click="agreeTips" v-if="!info && config.agreement_show && !isAgree"></u-button>
|
||||
<u-button type="primary" :plain="true" :text="t('weixinUserAuth')" open-type="getPhoneNumber" @getphonenumber="mobileAuth" v-else></u-button>
|
||||
<u-button type="primary" :plain="true" :text="t('mobileQuickLogin')" open-type="getPhoneNumber" @getphonenumber="mobileAuth" @click="checkWxPrivacy" v-else></u-button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</u-form>
|
||||
@ -50,7 +50,7 @@
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup>
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
@ -81,7 +81,7 @@
|
||||
mobile_key: ''
|
||||
})
|
||||
|
||||
let real_name_input = ref(true);
|
||||
const real_name_input = ref(true);
|
||||
onMounted(() => {
|
||||
// 防止浏览器自动填充
|
||||
setTimeout(()=>{
|
||||
@ -153,6 +153,13 @@
|
||||
})
|
||||
}
|
||||
|
||||
const wxPrivacyPopupRef:any = ref(null)
|
||||
|
||||
// 检测是否同意隐私协议
|
||||
const checkWxPrivacy = ()=>{
|
||||
wxPrivacyPopupRef.value.proactive();
|
||||
}
|
||||
|
||||
const mobileAuth = (e) => {
|
||||
if (!isAgree.value && !info.value && config.value.agreement_show) {
|
||||
uni.showToast({
|
||||
|
||||
@ -17,21 +17,21 @@
|
||||
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
|
||||
<view v-show="type == 'username'">
|
||||
<u-form-item label="" prop="username" :border-bottom="true">
|
||||
<u-input v-model="formData.username" border="none" clearable :placeholder="t('usernamePlaceholder')" autocomplete="off" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.username" border="none" clearable :placeholder="t('usernamePlaceholder')" autocomplete="off" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2] text-[26rpx]"/>
|
||||
</u-form-item>
|
||||
<view class="mt-[40rpx]">
|
||||
<u-form-item label="" prop="password" :border-bottom="true">
|
||||
<u-input v-model="formData.password" border="none" type="password" clearable :placeholder="t('passwordPlaceholder')" autocomplete="new-password" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.password" border="none" type="password" clearable :placeholder="t('passwordPlaceholder')" autocomplete="new-password" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2] text-[26rpx]"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
</view>
|
||||
<view v-show="type == 'mobile'">
|
||||
<u-form-item label="" prop="mobile" :border-bottom="true">
|
||||
<u-input v-model="formData.mobile" border="none" clearable :placeholder="t('mobilePlaceholder')" autocomplete="off" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.mobile" border="none" clearable :placeholder="t('mobilePlaceholder')" autocomplete="off" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]"/>
|
||||
</u-form-item>
|
||||
<view class="mt-[40rpx]">
|
||||
<u-form-item label="" prop="mobile_code" :border-bottom="true">
|
||||
<u-input v-model="formData.mobile_code" border="none" clearable class="!bg-transparent" :disabled="real_name_input" :placeholder="t('codePlaceholder')">
|
||||
<u-input v-model="formData.mobile_code" border="none" clearable class="!bg-transparent" fontSize="26rpx" :disabled="real_name_input" :placeholder="t('codePlaceholder')" placeholderClass="!text-[#8288A2]">
|
||||
<template #suffix>
|
||||
<sms-code :mobile="formData.mobile" type="login" v-model="formData.mobile_key"></sms-code>
|
||||
</template>
|
||||
@ -39,16 +39,24 @@
|
||||
</u-form-item>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex text-xs justify-between mt-[20rpx] text-gray-400">
|
||||
<view class="flex text-xs justify-between mt-[20rpx] text-[#8288A2]">
|
||||
<view @click="redirect({ url: '/app/pages/auth/register' })">{{ t('noAccount') }}
|
||||
<text class="text-primary">{{ t('toRegister') }}</text>
|
||||
</view>
|
||||
<view @click="redirect({ url: '/app/pages/auth/resetpwd' })">{{ t('resetpwd') }}</view>
|
||||
</view>
|
||||
<view class="mt-[80rpx]">
|
||||
<u-button type="primary" :text="t('login')" :loading="loading" :loadingText="t('logining')" @click="handleLogin">
|
||||
</u-button>
|
||||
<button hover-class="none" class="bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" :loading="loading" :loadingText="t('logining')" @click="handleLogin">{{t('login')}}</button>
|
||||
</view>
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="mt-[20rpx]" v-if="configStore.login.is_auth_register">
|
||||
<button hover-class="none" class="text-[var(--primary-color)] bg-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" :loading="loginLoading" :loadingText="t('logining')" @click="oneClickLogin">{{t('oneClicklogin')}}</button>
|
||||
</view>
|
||||
<view class="mt-[20rpx]" v-else-if="type == 'mobile'">
|
||||
<u-button :customStyle="{border:'none',color:'var(--primary-color)',fontSize:'26rpx',height:'40rpx', lineHeight:'40rpx'}" :text="t('mobileQuickLogin')" open-type="getPhoneNumber" @getphonenumber="mobileAuth" @click="checkWxPrivacy"></u-button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</u-form>
|
||||
</view>
|
||||
</view>
|
||||
@ -63,17 +71,22 @@
|
||||
<text class="text-primary">{{ t('privacyAgreement') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { usernameLogin, mobileLogin } from '@/app/api/auth'
|
||||
import { usernameLogin, mobileLogin,bind } from '@/app/api/auth'
|
||||
import useMemberStore from '@/stores/member'
|
||||
import useConfigStore from '@/stores/config'
|
||||
import { useLogin } from '@/hooks/useLogin'
|
||||
import { t } from '@/locale'
|
||||
import { redirect } from '@/utils/common'
|
||||
import { redirect,getToken } from '@/utils/common'
|
||||
import { onLoad,onShow } from '@dcloudio/uni-app';
|
||||
|
||||
const formData = reactive({
|
||||
username: '',
|
||||
@ -83,7 +96,7 @@
|
||||
mobile_key: ''
|
||||
})
|
||||
|
||||
let real_name_input = ref(true);
|
||||
const real_name_input = ref(true);
|
||||
onMounted(() => {
|
||||
// 防止浏览器自动填充
|
||||
setTimeout(()=>{
|
||||
@ -91,23 +104,34 @@
|
||||
},800)
|
||||
});
|
||||
|
||||
if (!uni.getStorageSync('autoLoginLock')) {
|
||||
uni.getStorageSync('openid') && (Object.assign(formData, { openid: uni.getStorageSync('openid') }))
|
||||
uni.getStorageSync('unionid') && (Object.assign(formData, { unionid: uni.getStorageSync('unionid') }))
|
||||
}
|
||||
uni.getStorageSync('pid') && (Object.assign(formData, { pid: uni.getStorageSync('pid') }))
|
||||
|
||||
const memberStore = useMemberStore()
|
||||
const configStore = useConfigStore()
|
||||
|
||||
onLoad(async()=>{
|
||||
await configStore.getLoginConfig()
|
||||
uni.getStorageSync('openid') && (Object.assign(formData, { openid: uni.getStorageSync('openid') }))
|
||||
uni.getStorageSync('unionid') && (Object.assign(formData, { unionid: uni.getStorageSync('unionid') }))
|
||||
uni.getStorageSync('pid') && (Object.assign(formData, { pid: uni.getStorageSync('pid') }))
|
||||
if(!getToken() && !configStore.login.is_username && !configStore.login.is_mobile && !configStore.login.is_bind_mobile){
|
||||
uni.showToast({ title: '商家未开启普通账号登录注册', icon: 'none' })
|
||||
setTimeout(() => {
|
||||
redirect({ url: '/app/pages/index/index', mode: 'reLaunch' })
|
||||
}, 100)
|
||||
}
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
const type = ref('')
|
||||
|
||||
const loginType = computed(() => {
|
||||
const value = []
|
||||
configStore.login.is_username && (value.push({ type: 'username', title: t('usernameLogin') }))
|
||||
configStore.login.is_mobile && (value.push({ type: 'mobile', title: t('mobileLogin') }))
|
||||
if(configStore.login.is_username){
|
||||
value.push({ type: 'username', title: t('usernameLogin') })
|
||||
}
|
||||
if(configStore.login.is_bind_mobile || configStore.login.is_mobile){
|
||||
value.push({ type: 'mobile', title: t('mobileLogin') })
|
||||
}
|
||||
type.value = value[0] ? value[0].type : ''
|
||||
return value
|
||||
})
|
||||
@ -169,12 +193,72 @@
|
||||
|
||||
login(formData).then((res) => {
|
||||
memberStore.setToken(res.data.token)
|
||||
if(configStore.login.is_bind_mobile && !res.data.mobile){
|
||||
uni.setStorageSync('isbindmobile', true)
|
||||
}
|
||||
useLogin().handleLoginBack()
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// todo 一键登录
|
||||
const loginLoading = ref(false)
|
||||
const oneClickLogin = () =>{
|
||||
// 第三方平台自动登录
|
||||
if (loginLoading.value) return
|
||||
loginLoading.value =true
|
||||
const login = useLogin()
|
||||
login.getAuthCode('',false,true)
|
||||
}
|
||||
|
||||
const wxPrivacyPopupRef:any = ref(null)
|
||||
|
||||
// 检测是否同意隐私协议
|
||||
const checkWxPrivacy = ()=>{
|
||||
wxPrivacyPopupRef.value.proactive();
|
||||
}
|
||||
const mobileAuth = (e) => {
|
||||
if (!isAgree.value && configStore.login.agreement_show) {
|
||||
uni.showToast({
|
||||
title: `${ t('pleaceAgree') }《${ t('userAgreement') }》《${ t('privacyAgreement') }》`,
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const login = useLogin()
|
||||
login.getAuthCode('',false,true,(data) => {
|
||||
if (e.detail.errMsg == 'getPhoneNumber:ok') {
|
||||
uni.showLoading({ title: '' })
|
||||
|
||||
bind({
|
||||
openid:data.openid,
|
||||
unionid:data.unionid,
|
||||
mobile_code: e.detail.code
|
||||
}).then((res) => {
|
||||
uni.hideLoading()
|
||||
memberStore.setToken(res.data.token)
|
||||
useLogin().handleLoginBack()
|
||||
|
||||
}).catch((res) => {
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
}, 2000);
|
||||
})
|
||||
}
|
||||
|
||||
if (e.detail.errno == 104) {
|
||||
let msg = '用户未授权隐私权限';
|
||||
uni.showToast({ title: msg, icon: 'none' })
|
||||
}
|
||||
if (e.detail.errMsg == "getPhoneNumber:fail user deny") {
|
||||
let msg = '用户拒绝获取手机号码';
|
||||
uni.showToast({ title: msg, icon: 'none' })
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<view class="w-screen h-screen flex flex-col" :style="themeColor()" v-show="type">
|
||||
<view class="w-screen h-screen flex flex-col" :style="themeColor()" >
|
||||
<view class="flex-1">
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="h-[100rpx]"></view>
|
||||
@ -18,31 +18,31 @@
|
||||
<view v-show="type == 'username'">
|
||||
<view class="mt-[30rpx]">
|
||||
<u-form-item label="" prop="username" :border-bottom="true">
|
||||
<u-input v-model="formData.username" border="none" clearable :placeholder="t('usernamePlaceholder')" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.username" border="none" clearable :placeholder="t('usernamePlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[30rpx]">
|
||||
<u-form-item label="" prop="password" :border-bottom="true">
|
||||
<u-input v-model="formData.password" border="none" type="password" clearable :placeholder="t('passwordPlaceholder')" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.password" border="none" type="password" clearable :placeholder="t('passwordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[30rpx]">
|
||||
<u-form-item label="" prop="confirm_password" :border-bottom="true">
|
||||
<u-input v-model="formData.confirm_password" border="none" type="password" clearable :placeholder="t('confirmPasswordPlaceholder')" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.confirm_password" border="none" type="password" clearable :placeholder="t('confirmPasswordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
</view>
|
||||
<view v-show="type == 'mobile' || configStore.login.is_bind_mobile">
|
||||
<view class="mt-[30rpx]">
|
||||
<u-form-item label="" prop="mobile" :border-bottom="true">
|
||||
<u-input v-model="formData.mobile" border="none" clearable :placeholder="t('mobilePlaceholder')" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.mobile" border="none" clearable :placeholder="t('mobilePlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[30rpx]">
|
||||
<u-form-item label="" prop="code" :border-bottom="true">
|
||||
<u-input v-model="formData.mobile_code" border="none" clearable :placeholder="t('codePlaceholder')" class="!bg-transparent" :disabled="real_name_input">
|
||||
<u-form-item label="" prop="mobile_code" :border-bottom="true">
|
||||
<u-input v-model="formData.mobile_code" border="none" clearable :placeholder="t('codePlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]">
|
||||
<template #suffix>
|
||||
<sms-code :mobile="formData.mobile" type="register" v-model="formData.mobile_key"></sms-code>
|
||||
<sms-code v-show="type" :mobile="formData.mobile" type="register" v-model="formData.mobile_key"></sms-code>
|
||||
</template>
|
||||
</u-input>
|
||||
</u-form-item>
|
||||
@ -51,7 +51,7 @@
|
||||
<view v-show="type == 'username'">
|
||||
<view class="mt-[30rpx]">
|
||||
<u-form-item label="" prop="captcha_code" :border-bottom="true">
|
||||
<u-input v-model="formData.captcha_code" border="none" clearable :placeholder="t('captchaPlaceholder')" class="!bg-transparent" :disabled="real_name_input">
|
||||
<u-input v-model="formData.captcha_code" border="none" clearable :placeholder="t('captchaPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]">
|
||||
<template #suffix>
|
||||
<image :src="captcha.image.value" class="h-[48rpx] w-[60rpx] ml-[20rpx]" mode="heightFix" @click="captcha.refresh()"></image>
|
||||
</template>
|
||||
@ -59,12 +59,11 @@
|
||||
</u-form-item>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex text-xs justify-between mt-[20rpx] text-gray-400">
|
||||
<view class="flex text-xs justify-between mt-[20rpx] text-[#8288A2]">
|
||||
<view @click="redirect({ url: '/app/pages/auth/login' })">{{ t('haveAccount') }},<text class="text-primary">{{ t('toLogin') }}</text></view>
|
||||
</view>
|
||||
<view class="mt-[80rpx]">
|
||||
<u-button type="primary" :text="t('register')" :loading="loading" :loadingText="t('registering')" @click="handleRegister">
|
||||
</u-button>
|
||||
<button hover-class="none" class="bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" :loading="loading" :loadingText="t('registering')" @click="handleRegister">{{t('register')}}</button>
|
||||
</view>
|
||||
</u-form>
|
||||
</view>
|
||||
@ -91,7 +90,8 @@
|
||||
import { useLogin } from '@/hooks/useLogin'
|
||||
import { useCaptcha } from '@/hooks/useCaptcha'
|
||||
import { t } from '@/locale'
|
||||
import { redirect } from '@/utils/common'
|
||||
import { redirect, getToken } from '@/utils/common'
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
|
||||
const formData = reactive({
|
||||
username: '',
|
||||
@ -104,7 +104,7 @@
|
||||
captcha_code: ''
|
||||
})
|
||||
|
||||
let real_name_input = ref(true);
|
||||
const real_name_input = ref(true);
|
||||
onMounted(() => {
|
||||
// 防止浏览器自动填充
|
||||
setTimeout(()=>{
|
||||
@ -112,18 +112,27 @@
|
||||
},800)
|
||||
});
|
||||
|
||||
if (!uni.getStorageSync('autoLoginLock')) {
|
||||
uni.getStorageSync('openid') && (Object.assign(formData, {openid: uni.getStorageSync('openid')}))
|
||||
uni.getStorageSync('pid') && (Object.assign(formData, {pid: uni.getStorageSync('pid')}))
|
||||
}
|
||||
uni.getStorageSync('unionid') && (Object.assign(formData, { unionid: uni.getStorageSync('unionid') }))
|
||||
const memberStore = useMemberStore()
|
||||
const configStore = useConfigStore()
|
||||
|
||||
onLoad(async() =>{
|
||||
await configStore.getLoginConfig()
|
||||
if (!uni.getStorageSync('autoLoginLock')) {
|
||||
uni.getStorageSync('openid') && (Object.assign(formData, {openid: uni.getStorageSync('openid')}))
|
||||
uni.getStorageSync('pid') && (Object.assign(formData, {pid: uni.getStorageSync('pid')}))
|
||||
}
|
||||
uni.getStorageSync('unionid') && (Object.assign(formData, { unionid: uni.getStorageSync('unionid') }))
|
||||
if(!getToken() && !configStore.login.is_username && !configStore.login.is_mobile && !configStore.login.is_bind_mobile){
|
||||
uni.showToast({ title: '商家未开启普通账号登录注册', icon: 'none' })
|
||||
setTimeout(() => {
|
||||
redirect({ url: '/app/pages/index/index', mode: 'reLaunch' })
|
||||
}, 100)
|
||||
}
|
||||
})
|
||||
|
||||
const captcha = useCaptcha(formData)
|
||||
captcha.refresh()
|
||||
|
||||
const memberStore = useMemberStore()
|
||||
const configStore = useConfigStore()
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
const type = ref('')
|
||||
|
||||
@ -12,12 +12,12 @@
|
||||
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
|
||||
<view class="mt-[30rpx]">
|
||||
<u-form-item label="" prop="mobile" :border-bottom="true">
|
||||
<u-input v-model="formData.mobile" border="none" clearable :placeholder="t('mobilePlaceholder')" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.mobile" border="none" clearable :placeholder="t('mobilePlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[30rpx]">
|
||||
<u-form-item label="" prop="code" :border-bottom="true">
|
||||
<u-input v-model="formData.mobile_code" border="none" clearable :placeholder="t('codePlaceholder')" class="!bg-transparent" :disabled="real_name_input">
|
||||
<u-input v-model="formData.mobile_code" border="none" clearable :placeholder="t('codePlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]">
|
||||
<template #suffix>
|
||||
<sms-code :mobile="formData.mobile" type="find_pass" v-model="formData.mobile_key"></sms-code>
|
||||
</template>
|
||||
@ -26,17 +26,16 @@
|
||||
</view>
|
||||
<view class="mt-[30rpx]">
|
||||
<u-form-item label="" prop="password" :border-bottom="true">
|
||||
<u-input v-model="formData.password" border="none" type="password" clearable :placeholder="t('passwordPlaceholder')" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.password" border="none" type="password" clearable :placeholder="t('passwordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[30rpx]">
|
||||
<u-form-item label="" prop="confirm_password" :border-bottom="true">
|
||||
<u-input v-model="formData.confirm_password" border="none" type="password" clearable :placeholder="t('confirmPasswordPlaceholder')" class="!bg-transparent" :disabled="real_name_input"/>
|
||||
<u-input v-model="formData.confirm_password" border="none" type="password" clearable :placeholder="t('confirmPasswordPlaceholder')" class="!bg-transparent" :disabled="real_name_input" fontSize="26rpx" placeholderClass="!text-[#8288A2]"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[80rpx]">
|
||||
<u-button type="primary" :text="t('confirm')" :loading="loading" :loadingText="t('confirm')" @click="handleConfirm">
|
||||
</u-button>
|
||||
<button hover-class="none" class="bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" :loading="loading" :loadingText="t('confirm')" @click="handleConfirm">{{t('confirm')}}</button>
|
||||
</view>
|
||||
</u-form>
|
||||
</view>
|
||||
@ -58,7 +57,7 @@
|
||||
confirm_password: ''
|
||||
})
|
||||
|
||||
let real_name_input = ref(true);
|
||||
const real_name_input = ref(true);
|
||||
onMounted(() => {
|
||||
// 防止浏览器自动填充
|
||||
setTimeout(()=>{
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup>
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
|
||||
</view>
|
||||
@ -51,6 +51,9 @@
|
||||
setShare(share);
|
||||
diyGroupRef.value?.refresh();
|
||||
});
|
||||
|
||||
// 监听页面卸载
|
||||
diy.onUnload();
|
||||
|
||||
// 监听下拉刷新事件
|
||||
diy.onPullDownRefresh()
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup>
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
|
||||
</view>
|
||||
@ -57,6 +57,9 @@
|
||||
}
|
||||
diyGroupRef.value?.refresh();
|
||||
});
|
||||
|
||||
// 监听页面卸载
|
||||
diy.onUnload();
|
||||
|
||||
// 监听下拉刷新事件
|
||||
diy.onPullDownRefresh()
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<view class="w-screen h-screen bg-page" :style="themeColor()">
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getCashoutAccountListFn">
|
||||
<view class="h-[20rpx]"></view>
|
||||
<u-swipe-action-item :options="accountOptions" @click="swipeClick(index)" v-for="(item, index) in accountList" :key="index" class="mx-[32rpx] my-[20rpx]">
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getCashoutAccountListFn">
|
||||
<view class="h-[10rpx]"></view>
|
||||
<u-swipe-action-item :options="accountOptions" @click="swipeClick(index)" v-for="(item, index) in accountList" :key="index" class="sidebar-marign my-[20rpx]">
|
||||
<view class="p-[30rpx] bg-white rounded flex justify-between" >
|
||||
<view class="flex">
|
||||
<view class="w-[100rpx] h-[100rpx] flex items-center justify-center mr-[10rpx]" @click="handleClick(item)">
|
||||
@ -21,7 +21,7 @@
|
||||
<text class="flex items-center nc-iconfont nc-icon-xiugaiV6xx shrink-0 text-[32rpx] p-[20rpx] pr-0" @click="editAccount(item)"></text>
|
||||
</view>
|
||||
</u-swipe-action-item>
|
||||
<view class="p-[30rpx] bg-white mx-[32rpx] my-[20rpx] rounded flex" @click="redirect({ url: '/app/pages/member/account_edit', param: { type: accountType, mode } })">
|
||||
<view class="p-[30rpx] bg-white sidebar-marign my-[20rpx] rounded flex" @click="redirect({ url: '/app/pages/member/account_edit', param: { type: accountType, mode } })">
|
||||
<u-icon name="plus" color="#333" size="16"></u-icon>
|
||||
<text class="text-sm ml-[10rpx] flex-1">{{ accountType == 'bank' ? t('addBankCard') : t('addAlipayAccount') }}</text>
|
||||
<u-icon name="arrow-right" color="#333" size="14"></u-icon>
|
||||
@ -46,7 +46,7 @@
|
||||
const mescrollRef = ref(null)
|
||||
const mode = ref('get')
|
||||
|
||||
onLoad((data) => {
|
||||
onLoad((data: any) => {
|
||||
data.type && (accountType.value = data.type)
|
||||
data.mode && (mode.value = data.mode)
|
||||
})
|
||||
|
||||
@ -1,27 +1,27 @@
|
||||
<template>
|
||||
<view :style="themeColor()">
|
||||
<scroll-view scroll-y="true" class="w-screen h-screen bg-page">
|
||||
<view class="h-[30rpx]"></view>
|
||||
<view class="p-[30rpx] bg-white mx-[32rpx] rounded">
|
||||
<view class="h-[20rpx]"></view>
|
||||
<view class="p-[30rpx] bg-white sidebar-marign rounded">
|
||||
<block v-if="formData.account_type == 'bank'">
|
||||
<view class="text-center text-base font-bold mt-[50rpx]">{{ t('addBankCard') }}</view>
|
||||
<view class="text-center text-sm mt-[10rpx]">{{ t('addBankCardTips') }}</view>
|
||||
|
||||
<view class="mt-[50rpx]">
|
||||
<u-form labelPosition="left" :model="formData" labelWidth="200rpx" errorType='toast' :rules="rules" ref="formRef">
|
||||
<u-form labelPosition="left" :model="formData" :label-style="{'font-size':'28rpx'}" labelWidth="200rpx" errorType='toast' :rules="rules" ref="formRef">
|
||||
<view class="mt-[10rpx]">
|
||||
<u-form-item :label="t('bankRealname')" prop="realname" :border-bottom="true">
|
||||
<u-input v-model.trim="formData.realname" maxlength="30" border="none" clearable :placeholder="t('bankRealnamePlaceholder')"/>
|
||||
<u-input v-model.trim="formData.realname" fontSize="28rpx" maxlength="30" border="none" clearable :placeholder="t('bankRealnamePlaceholder')"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[10rpx]">
|
||||
<u-form-item :label="t('bankName')" prop="bank_name" :border-bottom="true">
|
||||
<u-input v-model.trim="formData.bank_name" maxlength="30" border="none" clearable :placeholder="t('bankNamePlaceholder')"/>
|
||||
<u-input v-model.trim="formData.bank_name" fontSize="28rpx" maxlength="30" border="none" clearable :placeholder="t('bankNamePlaceholder')"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[10rpx]">
|
||||
<u-form-item :label="t('bankAccountNo')" prop="account_no" :border-bottom="true">
|
||||
<u-input v-model.trim="formData.account_no" maxlength="30" border="none" clearable :placeholder="t('bankAccountNoPlaceholder')"/>
|
||||
<u-input v-model.trim="formData.account_no" fontSize="28rpx" maxlength="30" border="none" clearable :placeholder="t('bankAccountNoPlaceholder')"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
</u-form>
|
||||
@ -49,12 +49,12 @@
|
||||
</block>
|
||||
|
||||
<view class="mt-[100rpx]">
|
||||
<u-button :text="t('save')" type="primary" shape="circle" :loading="loading" @click="handleSave"></u-button>
|
||||
<button :loading="loading" class="bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" @click="handleSave">{{t('save')}}</button>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<u-modal :show="deleteConfirm" :content="t('deleteConfirm')" :confirmText="t('confirm')" :cancelText="t('cancel')" :showCancelButton="true" @confirm="handleDelete" @cancel="deleteConfirm = false"></u-modal>
|
||||
<u-modal :show="deleteConfirm" :content="t('deleteConfirm')" :confirmText="t('confirm')" :cancelText="t('cancel')" :showCancelButton="true" @confirm="handleDelete" @cancel="deleteConfirm = false" confirmColor="var(--primary-color)"></u-modal>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -100,13 +100,13 @@
|
||||
}
|
||||
})
|
||||
|
||||
onLoad((data) => {
|
||||
onLoad((data: any) => {
|
||||
data.type && (formData.account_type = data.type)
|
||||
data.mode && (mode.value = data.mode)
|
||||
if (data.id) {
|
||||
formData.account_id = data.id
|
||||
|
||||
getCashoutAccountInfo({ account_id: data.id }).then((res : responseResult) => {
|
||||
getCashoutAccountInfo({ account_id: data.id }).then((res : any) => {
|
||||
if (res.data) {
|
||||
Object.keys(formData).forEach((key : string) => {
|
||||
if (res.data[key] != undefined) formData[key] = res.data[key]
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<view v-if="!loading" :style="themeColor()">
|
||||
<scroll-view scroll-y="true">
|
||||
<u-swipe-action>
|
||||
<view class="p-[30rpx]">
|
||||
<view class="py-[30rpx] sidebar-marign">
|
||||
<u-swipe-action-item :options="addressOptions" @click="swipeClick(key)" v-for="(item, key) in addressList">
|
||||
<view class="border-0 !border-b !border-[#f5f5f5] border-solid pb-[30rpx] flex items-center">
|
||||
<view class="flex-1 line-feed" @click="selectAddress(item)">
|
||||
@ -23,7 +23,7 @@
|
||||
</u-swipe-action>
|
||||
<u-tabbar :fixed="true" :safeAreaInsetBottom="true" :border="false" zIndex="99">
|
||||
<view class="p-[24rpx] pt-0 w-full">
|
||||
<u-button type="primary" shape="circle" :text="t('createAddress')" @click="addAddress"></u-button>
|
||||
<button hover-class="none" class="bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" @click="addAddress">{{t('createAddress')}}</button>
|
||||
</view>
|
||||
</u-tabbar>
|
||||
</scroll-view>
|
||||
@ -45,7 +45,7 @@
|
||||
const type = ref('')
|
||||
const source = ref('')
|
||||
|
||||
onLoad((data) => {
|
||||
onLoad((data: any) => {
|
||||
type.value = data.type || ''
|
||||
source.value = data.source || ''
|
||||
if (data.type) current.value = data.type == 'address' ? 0 : 1
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
<template>
|
||||
<view class="px-[30rpx] pt-[10rpx]" :style="themeColor()">
|
||||
<u-form labelPosition="left" :model="formData" labelWidth="200rpx" errorType='toast' :rules="rules" ref="formRef">
|
||||
<view class="sidebar-marign pt-[10rpx]" :style="themeColor()">
|
||||
<u-form labelPosition="left" :model="formData" :label-style="{'font-size':'28rpx'}" labelWidth="200rpx" errorType='toast' :rules="rules" ref="formRef">
|
||||
<view class="">
|
||||
<u-form-item :label="t('name')" prop="name" :border-bottom="true">
|
||||
<u-input fontSize="30rpx" v-model.trim="formData.name" border="none" clearable maxlength="25" :placeholder="t('namePlaceholder')"/>
|
||||
<u-input fontSize="28rpx" v-model.trim="formData.name" border="none" clearable maxlength="25" :placeholder="t('namePlaceholder')"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[10rpx]">
|
||||
<u-form-item :label="t('mobile')" prop="mobile" :border-bottom="true">
|
||||
<u-input fontSize="30rpx" v-model.trim="formData.mobile" border="none" clearable :placeholder="t('mobilePlaceholder')"/>
|
||||
<u-input fontSize="28rpx" v-model.trim="formData.mobile" border="none" clearable :placeholder="t('mobilePlaceholder')"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[10rpx]">
|
||||
<u-form-item :label="t('selectArea')" prop="area" :border-bottom="true" >
|
||||
<view class="flex w-full items-center" v-if="addressType == 'address' && isSelectMap != 1" @click="selectArea">
|
||||
<view v-if="!formData.area" class="text-gray-placeholder text-[30rpx] flex-1">{{ t('selectAreaPlaceholder') }}</view>
|
||||
<view v-else class="text-[30rpx] flex-1">{{ formData.area }}</view>
|
||||
<view v-if="!formData.area" class="text-gray-placeholder text-[28rpx] flex-1">{{ t('selectAreaPlaceholder') }}</view>
|
||||
<view v-else class="text-[28rpx] flex-1">{{ formData.area }}</view>
|
||||
<view @click.stop="chooseLocation" class="flex items-center">
|
||||
<text class="nc-iconfont nc-icon-dizhiguanliV6xx mr-[4rpx] text-[32rpx] text-[#e93323]"></text>
|
||||
<text class="text-[24rpx] whitespace-nowrap">定位</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="flex justify-between items-center flex-1" @click="chooseLocation">
|
||||
<view class="text-[30rpx] text-[#303133]" v-if="formData.area || formData.address_name">{{formData.area || formData.address_name}}</view>
|
||||
<view class="text-[#c3c4d5] text-[30rpx]" v-else>{{t('selectAddressPlaceholder')}}</view>
|
||||
<view class="text-[28rpx] text-[#303133]" v-if="formData.area || formData.address_name">{{formData.area || formData.address_name}}</view>
|
||||
<view class="text-[#c3c4d5] text-[28rpx]" v-else>{{t('selectAddressPlaceholder')}}</view>
|
||||
<view class="flex items-center">
|
||||
<text class="nc-iconfont nc-icon-dizhiguanliV6xx text-[32rpx] mr-[4rpx] text-[#e93323]"></text>
|
||||
<text class="text-[24rpx] whitespace-nowrap">定位</text>
|
||||
@ -33,7 +33,7 @@
|
||||
</view>
|
||||
<view class="mt-[10rpx]">
|
||||
<u-form-item :label="t('address')" prop="address" :border-bottom="true">
|
||||
<u-input fontSize="30rpx" v-model.trim="formData.address" border="none" clearable maxlength="120" :placeholder="t('addressPlaceholder')"/>
|
||||
<u-input fontSize="28rpx" v-model.trim="formData.address" border="none" clearable maxlength="120" :placeholder="t('addressPlaceholder')"/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[10rpx]">
|
||||
@ -42,13 +42,13 @@
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[40rpx]">
|
||||
<u-button type="primary" shape="circle" :text="t('save')" @click="save" :disabled="btnDisabled" :loading="operateLoading"></u-button>
|
||||
<button hover-class="none" class="!bg-[var(--primary-color)] !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" :class="{'opacity-50': btnDisabled}" @click="save" :disabled="btnDisabled" :loading="operateLoading">{{t('save')}}</button>
|
||||
</view>
|
||||
</u-form>
|
||||
<area-select ref="areaRef" @complete="areaSelectComplete" :area-id="formData.district_id"/>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup>
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
|
||||
@ -82,23 +82,21 @@
|
||||
const formRef = ref(null)
|
||||
const source = ref('')
|
||||
const btnDisabled = ref(false)
|
||||
let isSelectAddress = ref(false)
|
||||
let addressType = ref('address');
|
||||
let isSelectMap = ref(2) // 值为1,该地址需要有经纬度,反之不需要
|
||||
const isSelectAddress = ref(false)
|
||||
const addressType = ref('address');
|
||||
const isSelectMap = ref(2) // 值为1,该地址需要有经纬度,反之不需要
|
||||
|
||||
onLoad((data) => {
|
||||
onLoad((data: any) => {
|
||||
isSelectMap.value = data.isSelectMap || '';
|
||||
const selectAddress = uni.getStorageSync('selectAddressCallback')
|
||||
if (data.id) {
|
||||
getAddressInfo(data.id)
|
||||
.then(res => {
|
||||
getAddressInfo(data.id).then(res => {
|
||||
res.data && Object.assign(formData.value, res.data)
|
||||
// 兼容待支付页面编辑地址
|
||||
if(selectAddress){
|
||||
addressType.value = selectAddress.delivery == 'express' ? 'address' : 'locationAddress';
|
||||
}
|
||||
})
|
||||
.catch()
|
||||
|
||||
}else if (data.name) {
|
||||
if (uni.getStorageSync('addressInfo')) {
|
||||
@ -198,8 +196,7 @@
|
||||
btnDisabled.value = false
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
save(formData.value).then((res) => {
|
||||
operateLoading.value = false
|
||||
setTimeout(() => {
|
||||
@ -273,8 +270,7 @@
|
||||
window.location.href = 'https://apis.map.qq.com/tools/locpicker?search=1&type=0&backurl=' + encodeURIComponent(backurl) + '&key=' + manifestJson.h5.sdkConfigs.maps.qqmap.key + '&referer=myapp';
|
||||
// #endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//获取详细地址
|
||||
const getAddress = (latlng:any)=> {
|
||||
getAddressByLatlng({latlng}).then((res: any) => {
|
||||
@ -310,4 +306,6 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<view :style="themeColor()">
|
||||
<scroll-view scroll-y="true" class="w-screen h-screen bg-page" v-if="!pageLoading && config.is_open == 1">
|
||||
<view class="px-[30rpx] pt-[20rpx]">
|
||||
<view class="p-[20rpx] bg-white rounded-[16rpx]">
|
||||
<scroll-view :scroll-y="true" class="w-screen h-screen bg-page" v-if="!pageLoading && config.is_open == 1">
|
||||
<view class="sidebar-marign pt-[20rpx]">
|
||||
<view class="card-template">
|
||||
<view class="font-500 text-[32rpx] text-[#333] leading-[44rpx]">{{t('cashOutMoneyTip')}}</view>
|
||||
<view class="flex pt-[30rpx] pb-[8rpx] items-center border-0 border-b-[2rpx] border-solid border-gray-200">
|
||||
<text class="text-[54rpx] font-bold leading-[76rpx] ">{{ t('currency') }}</text>
|
||||
<input type="digit" class="h-[76rpx] leading-[76rpx] pl-[10rpx] flex-1 font-bold text-[54rpx] bg-[#fff]" v-model="applyData.apply_money" maxlength="7" :placeholder="applyData.apply_money?'':(t('minWithdrawal') + t('currency') + moneyFormat(config.min))" placeholder-class="apply-price" :adjust-position="false"/>
|
||||
<view class="flex pt-[30rpx] pb-[8rpx] items-center border-0 border-b-[2rpx] border-solid border-[#F1F2F5]">
|
||||
<text class="text-[54rpx] font-500 leading-[76rpx] ">{{ t('currency') }}</text>
|
||||
<input type="digit" class="h-[76rpx] leading-[76rpx] pl-[10rpx] flex-1 font-bold text-[54rpx] bg-[#fff]" v-model="applyData.apply_money" maxlength="7" :placeholder="applyData.apply_money?'':(t('minWithdrawal') + t('currency') + moneyFormat(config.min))" placeholder-class="apply-price" :adjust-position="false"/>
|
||||
<image @click="clearMoney" v-if="applyData.apply_money"
|
||||
:src="img('static/resource/images/member/apply_withdrawal/close.png')" class="w-[40rpx] h-[40rpx]"
|
||||
mode="widthFix" />
|
||||
</view>
|
||||
<view class="pt-[18rpx] flex items-center justify-between mb-[20rpx]">
|
||||
<view class="text-[26rpx] text-[#666] leading-[36rpx]">
|
||||
<view class="pt-[20rpx] flex items-center justify-between">
|
||||
<view class="text-[26rpx] text-[#626779] leading-[36rpx]">
|
||||
<text>{{t('money')}}:{{ t('currency') }}{{ moneyFormat(cashOutMoney) }}</text>
|
||||
<text>,{{t('commissionTo')}}{{ config.rate + '%' }}</text>
|
||||
</view>
|
||||
@ -20,10 +20,10 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="px-[20rpx] pt-[20rpx] pb-[30rpx] bg-white mt-[20rpx] rounded-[16rpx]">
|
||||
<view class="font-500 text-[32rpx] text-[#333] leading-[44rpx] mb-[20rpx]">到账方式</view>
|
||||
<view class="mt-[20rpx] card-template">
|
||||
<view class="font-500 text-[32rpx] text-[#333] leading-[44rpx] mb-[30rpx]">到账方式</view>
|
||||
<!-- 提现到微信 -->
|
||||
<view class="p-[20rpx] mb-[20rpx] flex items-center rounded-[16rpx] border-[2rpx] border-solid border-[#eee]" v-if="config.transfer_type.includes('wechatpay') && memberStore.info && (memberStore.info.wx_openid || memberStore.info.weapp_openid)" @click="applyData.transfer_type = 'wechatpay'" :class="{'border-[#089C98] bg-[#F6FFFF]': applyData.transfer_type == 'wechatpay'}">
|
||||
<view class="p-[20rpx] mb-[20rpx] flex items-center rounded-[16rpx] border-[1rpx] border-solid border-[#eee]" v-if="config.transfer_type.includes('wechatpay') && memberStore.info && (memberStore.info.wx_openid || memberStore.info.weapp_openid)" @click="applyData.transfer_type = 'wechatpay'" :class="{'border-[#089C98] bg-[#F6FFFF]': applyData.transfer_type == 'wechatpay'}">
|
||||
<view>
|
||||
<image class="h-[60rpx] w-[60rpx]" :src="img('static/resource/images/member/apply_withdrawal/wechat.png')" mode="widthFix" />
|
||||
</view>
|
||||
@ -34,7 +34,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 提现到支付宝 -->
|
||||
<view class="p-[20rpx] mb-[20rpx] flex items-center rounded-[16rpx] border-[2rpx] border-solid border-[#eee]" v-if="config.transfer_type.includes('alipay')" :class="{'border-[#089C98] bg-[#F6FFFF]': applyData.transfer_type == 'alipay' && alipayAccountInfo}" >
|
||||
<view class="p-[20rpx] mb-[20rpx] flex items-center rounded-[16rpx] border-[1rpx] border-solid border-[#eee]" v-if="config.transfer_type.includes('alipay')" :class="{'border-[#089C98] bg-[#F6FFFF]': applyData.transfer_type == 'alipay' && alipayAccountInfo}" >
|
||||
<view @click="transferAlipay" >
|
||||
<image class="h-[60rpx] w-[60rpx] align-middle" :src="img('static/resource/images/member/apply_withdrawal/alipay-icon.png')" mode="widthFix" />
|
||||
</view>
|
||||
@ -55,7 +55,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 提现到银行卡 -->
|
||||
<view class="p-[20rpx] flex items-center rounded-[16rpx] border-[2rpx] border-solid border-[#eee]" v-if="config.transfer_type.includes('bank')" :class="{'border-[#089C98] bg-[#F6FFFF]': applyData.transfer_type == 'bank' && bankAccountInfo}">
|
||||
<view class="p-[20rpx] flex items-center rounded-[16rpx] border-[1rpx] border-solid border-[#eee]" v-if="config.transfer_type.includes('bank')" :class="{'border-[#089C98] bg-[#F6FFFF]': applyData.transfer_type == 'bank' && bankAccountInfo}">
|
||||
<view @click="transferBank" >
|
||||
<image class="h-[42rpx] w-[60rpx] align-middle" :src="img('static/resource/images/member/apply_withdrawal/bank-icon.png')" mode="widthFix" />
|
||||
</view>
|
||||
@ -72,23 +72,23 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<u-button :plain="true" :text="t('toAdd')" type="primary" shape="circle" :custom-style="{height: '56rpx'}" v-if="!bankAccountInfo && !bankLoading" @click="redirect({ url: '/app/pages/member/account', param: { type: 'bank', mode: 'select' }, mode: 'redirectTo' })"></u-button>
|
||||
<text v-else class="nc-iconfont nc-icon-youV6xx text-[40rpx] text-[#999] p-[10rpx]" @click.stop="redirect({ url: '/app/pages/member/account', param: { type: 'bank', mode: 'select' }, mode: 'redirectTo' })"></text>
|
||||
<button hover-class="none" class="h-[54rpx] leading-[50rpx] rounded-full p-[0] w-[100rpx] text-[var(--primary-color)] bg-transparent border-[2rpx] border-solid border-[var(--primary-color)] text-[28rpx]" v-if="!bankAccountInfo && !bankLoading" @click="redirect({ url: '/app/pages/member/account', param: { type: 'bank', mode: 'select' }, mode: 'redirectTo' })">{{t('toAdd')}}</button>
|
||||
<text v-else class="nc-iconfont nc-icon-youV6xx text-[40rpx] text-[#999] p-[10rpx]" @click.stop="redirect({ url: '/app/pages/member/account', param: { type: 'bank', mode: 'select' }, mode: 'redirectTo' })"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-[100rpx]">
|
||||
<u-button type="primary" shape="circle" :text="t('cashOutNow')" class="mb-[40rpx]" :disabled="applyData.apply_money == '' || applyData.apply_money == 0" :loading="loading" @click="cashOut" :customStyle="{background: 'linear-gradient( 94deg, #FB7939 0%, #FE120E 99%), #EF000C',fontSize:'32rpx'}"></u-button>
|
||||
</view>
|
||||
|
||||
<view class="mt-[40rpx] text-center text-[26rpx] text-primary" @click.stop="redirect({ url: '/app/pages/member/cash_out'})">
|
||||
{{t('cashOutList')}}
|
||||
|
||||
<view class="fixed bottom-[60rpx] left-0 right-0 px-[30rpx]">
|
||||
<button class="mt-[100rpx] h-[80rpx] !text-[#fff] leading-[80rpx] primary-btn-bg rounded-[50rpx] text-[32rpx]" :disabled="applyData.apply_money == '' || applyData.apply_money == 0" :loading="loading" @click="cashOut">{{t('cashOutNow')}}</button>
|
||||
<view class="mt-[20rpx] text-center text-[26rpx] text-primary" @click.stop="redirect({ url: '/app/pages/member/cash_out'})">
|
||||
{{t('cashOutList')}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<block v-if="config.is_open == 0 && !pageLoading">
|
||||
<u-empty :text="t('isOpenApply')" :icon="img('static/resource/images/empty.png')"/>
|
||||
</block>
|
||||
<view class="h-[100vh] w-[100vw] flex justify-center items-center" v-if="config.is_open == 0 && !pageLoading">
|
||||
<u-empty :text="t('isOpenApply')" width="320rpx" height="244rpx" :icon="img('static/resource/images/empty.png')"/>
|
||||
</view>
|
||||
<u-loading-page :loading="pageLoading" bg-color="#e8e8e8" loading-text=""></u-loading-page>
|
||||
</view>
|
||||
</template>
|
||||
@ -156,7 +156,18 @@
|
||||
title: t('abnormalOperation'),
|
||||
icon: 'none',
|
||||
success() {
|
||||
setTimeout(() => { uni.navigateBack({ delta: 1}) }, 1500)
|
||||
setTimeout(() => {
|
||||
if(getCurrentPages().length > 1){
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
}else{
|
||||
redirect({
|
||||
url: '/app/pages/member/index',
|
||||
mode: 'reLaunch'
|
||||
});
|
||||
}
|
||||
}, 1500)
|
||||
}
|
||||
})
|
||||
return
|
||||
@ -301,7 +312,7 @@
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.apply-price){
|
||||
color:#999;
|
||||
color: #8288A2;
|
||||
font-size: 26rpx;
|
||||
font-weight: normal;
|
||||
line-height: 76rpx;
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<view class="fixed w-full z-2 !bg-[#F6F6F6]">
|
||||
<view class="pb-[203rpx] text-[#fff] w-full" :style="headerStyle">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<top-tabbar :data="param" titleColor="#fff" class="top-header"/>
|
||||
<top-tabbar :data="param" class="top-header"/>
|
||||
<!-- #endif -->
|
||||
<view class="leading-[39rpx] text-[28rpx] pl-[53rpx] pt-[79rpx]">{{t('accountBalance')}}</view>
|
||||
<view class="flex items-baseline pl-[53rpx]">
|
||||
@ -11,7 +11,7 @@
|
||||
<text class="text-[70rpx] leading-[98rpx]">{{ memberStore.info ? moneyFormat((parseFloat(memberStore.info.balance) + parseFloat(memberStore.info.money)).toString()) : '0.00' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mx-[30rpx] py-[30rpx] bg-[#fff] rounded-[16rpx] px-[40rpx] box-border w-[calc(100% - 60rpx)] mt-[-112rpx]">
|
||||
<view class="sidebar-marign py-[30rpx] bg-[#fff] rounded-[16rpx] px-[40rpx] box-border w-[calc(100% - 60rpx)] mt-[-112rpx]">
|
||||
<view class="flex flex-col items-center w-full" @click="redirect({ url: '/app/pages/member/detailed_account', param: { type : 'money' } })" :class="{'pt-[12rpx]': !Object.keys(cashOutConfigObj).length || (Object.keys(cashOutConfigObj).length && !systemStore.siteAddons.includes('recharge') && cashOutConfigObj.is_open != 1)}">
|
||||
<view class=" text-[#999] text-[24rpx] leading-[34rpx] font-400">{{t('money')}}</view>
|
||||
<view class="flex items-baseline text-[#333]">
|
||||
@ -21,22 +21,26 @@
|
||||
|
||||
</view>
|
||||
<view class="mt-[50rpx] flex justify-between" v-if="Object.keys(cashOutConfigObj).length && (systemStore.siteAddons.includes('recharge') || cashOutConfigObj.is_open == 1)">
|
||||
<button :class="{'!w-[610rpx]': cashOutConfigObj.is_open != 1}" class="w-[280rpx] h-[66rpx] rounded-[40rpx] text-[30rpx] !bg-[#fff] !text-[var(--primary-color)] leading-[64rpx] !m-0 border-[2rpx] border-[var(--primary-color)] border-solid box-border" shape="circle" v-if="systemStore.siteAddons.includes('recharge')"
|
||||
<button :class="{'!w-[630rpx]': cashOutConfigObj.is_open != 1}" class="w-[280rpx] h-[66rpx] rounded-[40rpx] text-[30rpx] !bg-[#fff] !text-[var(--primary-color)] leading-[64rpx] !m-0 border-[2rpx] border-[var(--primary-color)] border-solid box-border" shape="circle" v-if="systemStore.siteAddons.includes('recharge')"
|
||||
@click="redirect({url: '/addon/recharge/pages/recharge'})">充值</button>
|
||||
<view v-if="cashOutConfigObj.is_open == 1" :class="{'!w-[610rpx]': !systemStore.siteAddons.includes('recharge')}" class="text-center w-[280rpx] h-[66rpx] rounded-[40rpx] text-[30rpx] !text-[#fff] leading-[66rpx] !m-0"
|
||||
style="background: linear-gradient( 94deg, #FB7939 0%, #FE120E 99%), #EF000C;" shape="circle" @click="applyCashOut">{{t('cashOut')}}</view>
|
||||
<view v-if="cashOutConfigObj.is_open == 1" :class="{'!w-[630rpx]': !systemStore.siteAddons.includes('recharge')}" class="text-center w-[280rpx] h-[66rpx] rounded-[40rpx] text-[30rpx] !text-[#fff] leading-[66rpx] !m-0"
|
||||
style="background: linear-gradient( 94deg, #FB7939 0%, #FE120E 99%), #EF000C;" @click="applyCashOut">{{t('cashOut')}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class=" box-border px-[30rpx] w-full mt-[20rpx]">
|
||||
<scroll-view :scroll-x="true" scroll-with-animation :scroll-into-view="'id' + (subActive>3 ? subActive - 2 : 0)" class="!h-[100%]">
|
||||
<view class="px-[var(--sidebar-m)] box-border mt-[20rpx] flex justify-between items-center">
|
||||
<scroll-view :scroll-x="true" scroll-with-animation :scroll-into-view="'id' + (subActive>3 ? subActive - 2 : 0)" class="!h-[100%] flex-1">
|
||||
<view class="flex whitespace-nowrap">
|
||||
<view :id="'id' + index" class="text-[26rpx] leading-[70rpx] text-[#666] font-400" :class="{ 'class-select': fromType === item.key,'ml-30rpx':index}" @click="fromTypeFn(item.key,index)" v-for="(item, index) in accountTypeList">{{ item.name }}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="flex items-center" @click="handleSelect">
|
||||
<view class="text-[26rpx] text-[#333] mr-[10rpx]">日期</view>
|
||||
<view class="nc-iconfont nc-icon-riliV6xx !text-[28rpx] leading-[36rpx]"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getListFn" :top="mescrollTop">
|
||||
<view class="px-[30rpx] pt-[20rpx] body-bottom" v-if="list.length">
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" height="auto" @up="getListFn" :top="mescrollTop">
|
||||
<view class="sidebar-marign pt-[20rpx] body-bottom" v-if="list.length">
|
||||
<view v-for="(item,index) in list" :key="item.id" class="w-full h-[120rpx] flex justify-between items-center bg-[#fff] box-border p-[20rpx] rounded-[16rpx]" :class="{'mt-[20rpx]':index>0}">
|
||||
<view class="flex items-center">
|
||||
<view class="w-[80rpx] h-[80rpx] text-center rounded-[40rpx] text-[40rpx] font-bold leading-[80rpx] text-[#fff]"
|
||||
@ -59,7 +63,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="box-border pt-[20rpx] px-[30rpx] body-bottom" :style="{'height':'calc(100vh - '+mescrollTop +')'}" v-if="!list.length && !loading &&!listLoading">
|
||||
<view class="h-full bg-[#fff] rounded-[16rpx] flex items-center justify-center">
|
||||
<view class="h-full rounded-[16rpx] flex items-center justify-center">
|
||||
<mescroll-empty></mescroll-empty>
|
||||
</view>
|
||||
</view>
|
||||
@ -67,33 +71,34 @@
|
||||
</mescroll-body>
|
||||
<u-loading-page bg-color="rgb(248,248,248)" :loading="loading" loadingText="" fontSize="16" color="#303133"></u-loading-page>
|
||||
<!-- <pay ref="payRef" @close="rechargeLoading = false"></pay> -->
|
||||
<!-- 时间选择 -->
|
||||
<select-date ref="selectDateRef" @confirm="confirmFn" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive,computed } from 'vue'
|
||||
import { t } from '@/locale'
|
||||
import { moneyFormat, redirect, img } from '@/utils/common';
|
||||
import { moneyFormat, redirect, img,pxToRpx } from '@/utils/common';
|
||||
import { cashOutConfig,getBalanceListAll } from '@/app/api/member';
|
||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
||||
import { onLoad,onShow, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { onShow, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
||||
import useMemberStore from '@/stores/member'
|
||||
import useSystemStore from '@/stores/system'
|
||||
import { topTabar } from '@/utils/topTabbar'
|
||||
import selectDate from '@/components/select-date/select-date.vue';
|
||||
|
||||
const { downCallback,mescrollInit, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
||||
const memberStore = useMemberStore()
|
||||
const systemStore = useSystemStore()
|
||||
let param = ref({
|
||||
title:'我的余额',
|
||||
topStatusBar: {
|
||||
style: 'style-1',
|
||||
isTransparent: true,
|
||||
bgColor: 'transparent',
|
||||
textColor: '#fff'
|
||||
}
|
||||
})
|
||||
const systemStore = useSystemStore()
|
||||
|
||||
/********* 自定义头部 - start ***********/
|
||||
const topTabarObj = topTabar()
|
||||
let param = topTabarObj.setTopTabbarParam({title:'我的余额'})
|
||||
/********* 自定义头部 - end ***********/
|
||||
|
||||
const cashOutConfigObj = reactive({})
|
||||
onShow(() => {
|
||||
cashOutConfig().then((res) => {
|
||||
@ -116,20 +121,25 @@
|
||||
backgroundSize: 'cover',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundPosition: 'bottom',
|
||||
// paddingTop:Object.keys(menuButtonInfo).length?(Number(menuButtonInfo.height) * 2 + menuButtonInfo.top * 2 + 99)+'rpx':'99rpx',
|
||||
}
|
||||
})
|
||||
|
||||
const mescrollTop = computed(()=>{
|
||||
return Object.keys(menuButtonInfo).length?(pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) +pxToRpx(8)+669)+'rpx':'669rpx'
|
||||
if(Object.keys(cashOutConfigObj).length && (systemStore.siteAddons.includes('recharge') || cashOutConfigObj.is_open == 1)){
|
||||
if(Object.keys(menuButtonInfo).length){
|
||||
return (pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) +pxToRpx(8)+669)+'rpx'
|
||||
}else{
|
||||
return '669rpx'
|
||||
}
|
||||
}else {
|
||||
if(Object.keys(menuButtonInfo).length){
|
||||
return (pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) +pxToRpx(8)+566)+'rpx'
|
||||
}else{
|
||||
return '566rpx'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// px转rpx
|
||||
const pxToRpx=(px)=> {
|
||||
const screenWidth = uni.getSystemInfoSync().screenWidth
|
||||
return (750 * Number.parseInt(px)) / screenWidth
|
||||
}
|
||||
|
||||
//获取数据来源类型
|
||||
const accountTypeList = ref([
|
||||
{name:'全部',key:''},
|
||||
@ -138,6 +148,7 @@
|
||||
{name:'提现',key:'cash_out'},
|
||||
])
|
||||
const fromType = ref('')
|
||||
const create_time = ref([])
|
||||
//来源类型
|
||||
const subActive = ref(0)
|
||||
const fromTypeFn = (key,index)=>{
|
||||
@ -168,7 +179,8 @@
|
||||
let data : Object = {
|
||||
page: mescroll.num,
|
||||
limit: mescroll.size,
|
||||
from_type:fromType.value
|
||||
trade_type:fromType.value,
|
||||
create_time: create_time.value
|
||||
|
||||
};
|
||||
interface acceptingDataStructure {
|
||||
@ -177,12 +189,12 @@
|
||||
code : number
|
||||
}
|
||||
interface acceptingDataItemStructure {
|
||||
data : object,
|
||||
data : [],
|
||||
[propName : string] : number | string | object
|
||||
}
|
||||
|
||||
getBalanceListAll(data).then((res : acceptingDataStructure) => {
|
||||
let newArr = res.data.data;-
|
||||
let newArr = res.data.data;
|
||||
mescroll.endSuccess(newArr.length);
|
||||
//设置列表数据
|
||||
if (mescroll.num == 1) {
|
||||
@ -197,6 +209,17 @@
|
||||
mescroll.endErr(); // 请求失败, 结束加载
|
||||
})
|
||||
}
|
||||
//日期筛选
|
||||
const selectDateRef = ref()
|
||||
const handleSelect = () =>{
|
||||
selectDateRef.value.show = true
|
||||
}
|
||||
// 确定时间筛选
|
||||
const confirmFn = (data) =>{
|
||||
create_time.value = data;
|
||||
list.value = []
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -226,4 +249,5 @@
|
||||
.pl-20rpx{
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view class="member-record-list" :style="themeColor()">
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getCashOutListFn">
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getCashOutListFn">
|
||||
<view v-for="(item,index) in cashOutList" :key="item.id" class="member-record-item" @click="toDetailFn(item)">
|
||||
<view class="name">{{item.transfer_type_name}}</view>
|
||||
<view class="desc">{{t('applyTime')}}: {{item.create_time}}</view>
|
||||
@ -8,9 +8,7 @@
|
||||
<view class="money" :class="item.apply_money > 0 ? 'text-active' : ''">
|
||||
{{ item.apply_money > 0 ? '+' + item.apply_money : item.apply_money }}
|
||||
</view>
|
||||
<view class="state">
|
||||
{{ item.status_name }}
|
||||
</view>
|
||||
<view class="state">{{ item.status_name }}</view>
|
||||
</view>
|
||||
<mescroll-empty v-if="!cashOutList.length && loading" :option="{tip : t('emptyTip')}"></mescroll-empty>
|
||||
</mescroll-body>
|
||||
@ -29,9 +27,9 @@ import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
||||
|
||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
||||
|
||||
let cashOutList = ref<Array<any>>([]);
|
||||
let mescrollRef = ref(null);
|
||||
let loading = ref<boolean>(false);
|
||||
const cashOutList = ref<Array<any>>([]);
|
||||
const mescrollRef = ref(null);
|
||||
const loading = ref<boolean>(false);
|
||||
let account_type = uni.getStorageSync('cashOutAccountType')
|
||||
const currentStatusDesc = (status) =>{
|
||||
switch(status){
|
||||
@ -47,12 +45,12 @@ const currentStatusDesc = (status) =>{
|
||||
}
|
||||
|
||||
const getCashOutListFn = (mescroll)=>{
|
||||
let data = ref({});
|
||||
let data:any = {}
|
||||
loading.value = false;
|
||||
data.value.page = mescroll.num;
|
||||
data.value.page_size = mescroll.size;
|
||||
data.value.account_type = account_type;
|
||||
getCashOutList(data.value).then((res) => {
|
||||
data.page = mescroll.num;
|
||||
data.page_size = mescroll.size;
|
||||
data.account_type = account_type;
|
||||
getCashOutList(data).then((res) => {
|
||||
let newArr = res.data.data;
|
||||
mescroll.endSuccess(newArr.length);
|
||||
//设置列表数据
|
||||
|
||||
@ -56,9 +56,9 @@ import { t } from '@/locale'
|
||||
import { redirect, img } from '@/utils/common';
|
||||
import { getCashOutDetail } from '@/app/api/member';
|
||||
|
||||
let cashOutInfo = ref({});
|
||||
let loading = ref<boolean>(true);
|
||||
onLoad((option) => {
|
||||
const cashOutInfo = ref({});
|
||||
const loading = ref<boolean>(true);
|
||||
onLoad((option: any) => {
|
||||
let id = option.id || "";
|
||||
getCashoutAccountListFn(id)
|
||||
})
|
||||
|
||||
@ -1,38 +1,32 @@
|
||||
<template>
|
||||
<view class="bg-[#F6F6F6] min-h-[100vh] w-full" :style="themeColor()" v-if="memberStore.info">
|
||||
<view class="fixed w-full z-2 !bg-[#F6F6F6]">
|
||||
<view class="pb-[174rpx]" :style="headerStyle">
|
||||
<view class="fixed w-full z-2 !bg-[#F6F6F6]">
|
||||
<view class="pb-[272rpx]" :style="headerStyle">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<top-tabbar :data="param" class="top-header"/>
|
||||
<top-tabbar :data="param" class="top-header"/>
|
||||
<!-- #endif -->
|
||||
<!-- <view class="pt-[18rpx] pb-[20rpx] pl-[30rpx] flex items-center" v-if="info">
|
||||
<u-avatar :src="img(info.headimg)" :size="'60rpx'" leftIcon="none"></u-avatar>
|
||||
<view class="ml-[12rpx] mr-[46rpx] text-[32rpx] font-bold text-[#333] leading-[38rpx]">{{info.nickname}}</view>
|
||||
<view class="member-level pl-[30rpx] pr-[12rpx] py-[2rpx] font-400 text-[24rpx] text-[#fff] leading-[34rpx] relative">
|
||||
<text>{{ info.member_level_name }}</text>
|
||||
<image class="h-[40rpx] w-[36rpx] absolute top-0 left-[-20rpx] " :src="img('static/resource/images/member/commission/level_icon.png')" mode="heightFix" />
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
<view class=" mt-[-114rpx] mx-[30rpx]" :style="{ backgroundImage: 'url(' + img('static/resource/images/member/commission/account_bg.png') + ')',backgroundRepeat:'no-repeat',backgroundSize:'100% 100%'}">
|
||||
<view class="pt-[40rpx] pb-[20rpx]">
|
||||
<view class="mt-[-232rpx] sidebar-marign" :style="{ backgroundImage: 'url(' + img('static/resource/images/member/commission/account_bg.png') + ')',backgroundRepeat:'no-repeat',backgroundSize:'100% 100%'}">
|
||||
<view class="pt-[40rpx]">
|
||||
<view class="flex items-center justify-between px-[30rpx]">
|
||||
<view>
|
||||
<view class="text-[26rpx] font-500 text-[#fff] leading-[36rpx] mb-[8rpx]">{{t('accountCommission')}}</view>
|
||||
<view class="text-[56rpx] font-bold text-[#fff] leading-[68rpx]">{{ memberStore.info ? moneyFormat(memberStore.info.commission) : 0.00 }}</view>
|
||||
<view class="text-[26rpx] font-400 text-[#fff] leading-[36rpx] mb-[16rpx]">{{t('accountCommission')}}</view>
|
||||
<view class="font-bold text-[#fff] flex items-baseline">
|
||||
<text class="text-[56rpx] h-[72rpx] price-font">{{ memberStore.info ? (moneyFormat(memberStore.info.commission).split(".")[0]+'.') : '0.' }}</text>
|
||||
<text class="text-[44rpx] h-[56rpx] price-font">{{ memberStore.info ? moneyFormat(memberStore.info.commission).split(".")[1] : '00' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<u-button type="primary" :text="t('transferMoney')" :plain="true" shape="circle" :customStyle="{backgroundColor: '#fff',color: '#EF000C',width: '150rpx', height:'66rpx', lineHeight:'66rpx', margin:'0rpx',border:'none'}" @click="applyCashOut"></u-button>
|
||||
<button @click="applyCashOut" hover-class="none" class="bg-[#fff] rounded-[100rpx] w-[150rpx] h-[66rpx] leading-[66rpx] text-[#EF000C] m-[0] border-[0] text-[32rpx]">{{t('transferMoney')}}</button>
|
||||
</view>
|
||||
<view class="h-[1rpx] bg-[#fff] opacity-30 mt-[80rpx] mb-[20rpx]"></view>
|
||||
<view class="flex items-center px-[30rpx]">
|
||||
<view class="flex items-center mt-[68rpx] px-[30rpx] border-[0] border-t-[2rpx] border-solid border-[rgba(255,255,255,.3)] h-[126rpx]">
|
||||
<view class="flex-1">
|
||||
<view class="font-bold text-[#fff] text-[36rpx] leading-[44rpx] mb-[6rpx]">
|
||||
<view class="font-bold text-[#fff] text-[36rpx] leading-[44rpx] mb-[6rpx] price-font">
|
||||
{{ moneyFormat(memberStore.info?.commission_get)|| '0.00' }}
|
||||
</view>
|
||||
<view class="text-[26rpx] text-[#fff] leading-[36rpx]">{{ t('commission') }}</view>
|
||||
</view>
|
||||
<view class="flex-1">
|
||||
<view class="font-bold text-[#fff] text-[36rpx] leading-[44rpx] mb-[6rpx]">
|
||||
<view class="font-bold text-[#fff] text-[36rpx] leading-[44rpx] mb-[6rpx] price-font">
|
||||
{{ moneyFormat(memberStore.info?.commission_cash_outing)|| '0.00' }}
|
||||
</view>
|
||||
<view class="text-[26rpx] text-[#fff] leading-[36rpx]">{{ t('money') }}</view>
|
||||
@ -40,41 +34,46 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-[40rpx] box-border px-[15rpx]">
|
||||
<view class="flex whitespace-nowrap">
|
||||
<view class="text-[26rpx] leading-[70rpx] text-[#666] font-400 px-[15rpx]" :class="{ 'class-select': fromType.from_type === item.from_type && fromType.account_data_gt === item.account_data_gt }" @click="fromTypeFn(item,index)" v-for="(item, index) in accountTypeList">{{ item.name }}</view>
|
||||
<view class="mt-[40rpx] tab-style-1">
|
||||
<view class="tab-left">
|
||||
<view class="tab-left-item" :class="{ 'class-select': fromType.from_type === item.from_type && fromType.account_data_gt === item.account_data_gt }" @click="fromTypeFn(item,index)" v-for="(item, index) in accountTypeList">{{ item.name }}</view>
|
||||
</view>
|
||||
<view class="tab-right" @click="handleSelect">
|
||||
<view class="tab-right-date">日期</view>
|
||||
<view class="nc-iconfont nc-icon-riliV6xx tab-right-icon"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="geCommissiontListFn" :top="mescrollTop">
|
||||
<view class="px-[30rpx] pt-[20rpx] body-bottom" v-if="list.length">
|
||||
<view v-for="(item,index) in list" :key="item.id" class="w-full h-[120rpx] flex justify-between items-center bg-[#fff] box-border p-[20rpx] rounded-[16rpx]" :class="{'mt-[20rpx]':index}">
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="geCommissionListFn" :top="mescrollTop">
|
||||
<view class="px-[var(--sidebar-m)] pt-[20rpx] body-bottom" v-if="list.length">
|
||||
<view v-for="(item,index) in list" :key="item.id" class="w-full h-[140rpx] flex justify-between items-center card-template" :class="{'mt-[20rpx]':index}">
|
||||
<view class="flex items-center">
|
||||
<view class="w-[80rpx] h-[80rpx] text-center rounded-[40rpx] text-[40rpx] font-bold leading-[80rpx] text-[#fff]"
|
||||
<view class="w-[80rpx] h-[80rpx] text-center rounded-[40rpx] text-[40rpx] font-500 leading-[80rpx] text-[#fff]"
|
||||
:class="{'bg-[#EF000C]' :item.account_data > 0, 'bg-[#1379FF]':item.account_data <= 0 }">
|
||||
{{item.account_data > 0?'收':'提'}}
|
||||
</view>
|
||||
<view class="flex flex-col ml-[20rpx]">
|
||||
<view class="text-[#333] text-[26rpx] leading-[36rpx]">{{item.from_type_name}}</view>
|
||||
<view class="text-[#999] text-[24rpx] leading-[34rpx] mt-[4rpx] font-400">{{item.create_time}}</view>
|
||||
<view class="text-[#8288A2] text-[24rpx] leading-[34rpx] mt-[4rpx] font-400">{{item.create_time}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-[36rpx] leading-[50rpx]" :class="{'text-[#EF000C]' :item.account_data > 0, 'text-[#333]':item.account_data <= 0 }">{{ item.account_data > 0 ? '+' + item.account_data : item.account_data }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="box-border pt-[20rpx] px-[30rpx] body-bottom" :style="{'height':'calc(100vh - '+mescrollTop +')'}" v-if="!list.length && !loading &&!listLoading">
|
||||
<view class="h-full bg-[#fff] rounded-[16rpx] flex items-center justify-center">
|
||||
<view class="box-border pt-[20rpx] px-[30rpx] body-bottom" :style="{'height':'calc(100vh - '+ mescrollTop +')'}" v-if="!list.length && !loading &&!listLoading">
|
||||
<view class="h-full rounded-[16rpx] flex items-center justify-center">
|
||||
<mescroll-empty></mescroll-empty>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</mescroll-body>
|
||||
<u-loading-page bg-color="rgb(248,248,248)" :loading="loading" loadingText="" fontSize="16" color="#303133"></u-loading-page>
|
||||
<!-- 时间选择 -->
|
||||
<select-date ref="selectDateRef" @confirm="confirmFn" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { computed, ref, reactive } from 'vue'
|
||||
import { t } from '@/locale'
|
||||
import { moneyFormat, redirect, img } from '@/utils/common';
|
||||
import useMemberStore from '@/stores/member'
|
||||
@ -82,7 +81,9 @@
|
||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
||||
import { onLoad, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { topTabar } from '@/utils/topTabbar'
|
||||
import selectDate from '@/components/select-date/select-date.vue';
|
||||
|
||||
const { downCallback,mescrollInit, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
||||
const memberStore = useMemberStore();
|
||||
@ -91,17 +92,13 @@
|
||||
const applyCashOut = ()=> {
|
||||
uni.setStorageSync('cashOutAccountType', 'commission')
|
||||
redirect({ url: '/app/pages/member/apply_cash_out' })
|
||||
}
|
||||
}
|
||||
|
||||
/********* 自定义头部 - start ***********/
|
||||
const topTabarObj = topTabar()
|
||||
let param = topTabarObj.setTopTabbarParam({title:'我的佣金',topStatusBar:{bgColor: '#fff',textColor: '#333'}})
|
||||
/********* 自定义头部 - end ***********/
|
||||
|
||||
let param = ref({
|
||||
title:'我的佣金',
|
||||
topStatusBar: {
|
||||
isTransparent: true,
|
||||
style: 'style-1',
|
||||
bgColor: 'transparent',
|
||||
textColor: '#333'
|
||||
}
|
||||
})
|
||||
// 获取系统状态栏的高度
|
||||
let menuButtonInfo:any = {};
|
||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
||||
@ -113,12 +110,12 @@
|
||||
backgroundImage: 'url(' + img('static/resource/images/member/commission/commission_bg.png') + ') ',
|
||||
backgroundSize: 'cover',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundPosition: 'center',
|
||||
backgroundPosition: 'bottom',
|
||||
}
|
||||
})
|
||||
// 16为自定头部的padding-bottom
|
||||
const mescrollTop = computed(()=>{
|
||||
return Object.keys(menuButtonInfo).length?(Number(menuButtonInfo.height) * 2 + menuButtonInfo.top * 2 + 530 + 16)+'rpx':'530rpx'
|
||||
return Object.keys(menuButtonInfo).length? (Number(menuButtonInfo.height) * 2 + menuButtonInfo.top * 2 + 486 + 16)+'rpx':'504rpx'
|
||||
})
|
||||
|
||||
//来源类型
|
||||
@ -131,6 +128,7 @@
|
||||
{name:'佣金',from_type:'',account_data_gt: 0},
|
||||
{name:'提现',from_type:'cash_out',account_data_gt: ''},
|
||||
])
|
||||
const create_time = ref([])
|
||||
const list = ref<Array<any>>([])
|
||||
const loading = ref<boolean>(true)
|
||||
const listLoading = ref<boolean>(true)
|
||||
@ -141,13 +139,14 @@
|
||||
fromType.value.account_data_gt = data.account_data_gt
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
const geCommissiontListFn = (mescroll) => {
|
||||
const geCommissionListFn = (mescroll) => {
|
||||
listLoading.value = true;
|
||||
let data : Object = {
|
||||
page: mescroll.num,
|
||||
limit: mescroll.size,
|
||||
from_type:fromType.value.from_type,
|
||||
account_data_gt: fromType.value.account_data_gt
|
||||
account_data_gt: fromType.value.account_data_gt,
|
||||
create_time:create_time.value
|
||||
}
|
||||
getMemberCommission(data).then((res:any) => {
|
||||
let newArr = res.data.data;-
|
||||
@ -165,6 +164,17 @@
|
||||
mescroll.endErr(); // 请求失败, 结束加载
|
||||
})
|
||||
}
|
||||
//日期筛选
|
||||
const selectDateRef = ref()
|
||||
const handleSelect = () =>{
|
||||
selectDateRef.value.show = true
|
||||
}
|
||||
// 确定时间筛选
|
||||
const confirmFn = (data) =>{
|
||||
create_time.value = data;
|
||||
list.value = []
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@ -172,22 +182,6 @@
|
||||
background: linear-gradient( 360deg, #F23621 11%, #FF7F71 100%), #D9D9D9;
|
||||
border-radius: 0rpx 20rpx 20rpx 0rpx;
|
||||
}
|
||||
.class-select {
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
color: var(--primary-color);
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 4rpx;
|
||||
border-radius: 4rpx;
|
||||
background-color: var(--primary-color);
|
||||
width: 40rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
:deep(.uni-scroll-view){
|
||||
overflow: auto hidden !important;
|
||||
}
|
||||
|
||||
192
uni-app/src/app/pages/member/components/select-date.vue
Normal file
192
uni-app/src/app/pages/member/components/select-date.vue
Normal file
@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<u-popup :show="show" @close="show = false" mode="bottom" :round="10" >
|
||||
<view>
|
||||
<view class="py-[30rpx] px-[40rpx] flex items-center justify-between">
|
||||
<view class="text-center flex-1">选择时间</view>
|
||||
<view class="nc-iconfont nc-icon-guanbiV6xx text-[36rpx] text-primary" @click="show = false"></view>
|
||||
</view>
|
||||
<view class="px-[30rpx] mb-[20rpx]">
|
||||
<view class="flex items-center justify-between mb-[30rpx]">
|
||||
<view class="w-[160rpx] h-[60rpx] leading-[60rpx] rounded-[30rpx] bg-[#F4F6FA] text-center text-[26rpx] text-[#666] border-[2rpx] border-solid border-[#F4F6FA]" v-for="(item,index) in curselectDate" :key="'a'+index" :class="{'text-primary !border-[var(--primary-color)] !bg-[rgba(239,0,12,0.04)]': currentValue.type == item.type}" @click="loadDateFn(item)">{{item.name}}</view>
|
||||
</view>
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="w-[316rpx] h-[60rpx] leading-[60rpx] rounded-[30rpx] bg-[#F4F6FA] text-center text-[26rpx] text-[#666] border-[2rpx] border-solid border-[#F4F6FA]" :class="{'text-primary !border-[var(--primary-color)] !bg-[rgba(239,0,12,0.04)]': currentValue.type == 'first'}" @click="currentValue.type = 'first'">{{dateList.nowDate[0]}}</view>
|
||||
<view class="nc-iconfont nc-icon-jianV6xx"></view>
|
||||
<view class="w-[316rpx] h-[60rpx] leading-[60rpx] rounded-[30rpx] bg-[#F4F6FA] text-center text-[26rpx] text-[#666] border-[2rpx] border-solid border-[#F4F6FA]" :class="{'text-primary !border-[var(--primary-color)] !bg-[rgba(239,0,12,0.04)]': currentValue.type == 'second'}" @click="currentValue.type = 'second'">{{dateList.nowDate[1]}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="h-[396rpx]">
|
||||
<picker-view :indicator-style="{height:'70rpx',backgroundColor:'#F4F6FA'}" :value="dateList.curIndex" @change="bindChange" class="px-[60rpx] h-full">
|
||||
<picker-view-column>
|
||||
<view class="text-center leading-[70rpx] !h-[70rpx] text-[28rpx]" v-for="(item,index) in dateList.years" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="text-center leading-[70rpx] !h-[70rpx] text-[28rpx]" v-for="(item,index) in dateList.months" :key="index">{{item}}月</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="text-center leading-[70rpx] !h-[70rpx] text-[28rpx]" v-for="(item,index) in dateList.days" :key="index">{{item}}日</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
<view class="px-[30rpx] pb-[30rpx] pt-[20rpx] flex justify-between">
|
||||
<button class="w-[330rpx] h-[88rpx] text-[var(--primary-color)] text-[32rpx] leading-[84rpx] border-[2rpx] border-solid border-[var(--primary-color)] rounded-[100rpx] bg-transparent" @click="reset">重置</button>
|
||||
<button class="w-[330rpx] h-[88rpx] text-[#fff] text-[32rpx] leading-[88rpx] border-[0] rounded-[100rpx] primary-btn-bg" shape="circle" @click="save">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref,reactive } from 'vue'
|
||||
|
||||
const emits = defineEmits(['confirm'])
|
||||
// 弹框时间选择
|
||||
const show = ref(false)
|
||||
const create_time = ref([])
|
||||
// 日期
|
||||
const init = () =>{
|
||||
const date = new Date();
|
||||
const years = []
|
||||
const months = []
|
||||
const days = []
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth();
|
||||
const day = date.getDate()
|
||||
|
||||
for (let i = 1990; i <= date.getFullYear()+2; i++) {
|
||||
years.push(i)
|
||||
}
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
months.push(i)
|
||||
}
|
||||
let dayCount = getDaysInMonth(year, month+1)
|
||||
for (let i = 1; i <= dayCount; i++) {
|
||||
days.push(i)
|
||||
}
|
||||
let yearIndex = years.indexOf(year)
|
||||
let curIndex = [yearIndex, month, day-1]
|
||||
let nowDate = `${year}-${month + 1 < 10 ? '0' + (month + 1) :(month + 1) }-${day < 10 ? '0' + day :day }`
|
||||
let lastMonthDate = new Date(date.getFullYear(),month - 1,date.getDate())
|
||||
let lastThreeMonthDate = new Date(date.getFullYear(),month - 3,date.getDate())
|
||||
let halfYear = new Date(date.getFullYear(), month - 6, date.getDate())
|
||||
let lastYear =new Date(date.getFullYear() - 1, month, date.getDate())
|
||||
const formatDate = (dateTime:any) => {
|
||||
const yearTime = dateTime.getFullYear()
|
||||
const monthTime = dateTime.getMonth() + 1
|
||||
const dayTime = dateTime.getDate()
|
||||
return `${yearTime}-${monthTime < 10 ? '0' + monthTime : monthTime}-${dayTime < 10 ? '0' + dayTime :dayTime }`
|
||||
}
|
||||
return {
|
||||
years,
|
||||
months,
|
||||
days,
|
||||
curIndex,
|
||||
nowDate,
|
||||
lastMonth: formatDate(lastMonthDate),
|
||||
lastThreeMonth: formatDate(lastThreeMonthDate),
|
||||
halfYear: formatDate(halfYear),
|
||||
lastYear: formatDate(lastYear)
|
||||
}
|
||||
}
|
||||
const getDaysInMonth = (year, month) => {
|
||||
let date = new Date(year, month, 0).getDate()
|
||||
return date
|
||||
}
|
||||
const getDaysCount = (year, month) =>{
|
||||
let count = getDaysInMonth(year, month)
|
||||
let days = []
|
||||
for (let i = 1; i <= count; i++) {
|
||||
days.push(i)
|
||||
}
|
||||
return days
|
||||
}
|
||||
const dateList = reactive({
|
||||
years: init().years,
|
||||
months: init().months,
|
||||
days: init().days,
|
||||
curIndex:init().curIndex, //当前选中下标
|
||||
nowDate:[init().nowDate,init().nowDate] //当前选中日期
|
||||
})
|
||||
|
||||
const bindChange = (e) =>{
|
||||
const val = e.detail.value
|
||||
let year = dateList.years[val[0]]
|
||||
let month= dateList.months[val[1]]
|
||||
let day = dateList.days[val[2]]
|
||||
// 根据年份,月份判断天数
|
||||
dateList.days = getDaysCount(year, month)
|
||||
if(currentValue.value.type == 'first'){
|
||||
dateList.nowDate[0] = `${year}-${month < 10 ? '0' + month :month }-${day < 10 ? '0' + day :day }`
|
||||
}else if(currentValue.value.type == 'second'){
|
||||
dateList.nowDate[1] = `${year}-${month < 10 ? '0' + month :month }-${day < 10 ? '0' + day :day }`
|
||||
}
|
||||
}
|
||||
const curselectDate = reactive([
|
||||
{
|
||||
time:[init().lastMonth,init().nowDate],
|
||||
type:'lastMonth',
|
||||
name:'近1个月'
|
||||
},
|
||||
{
|
||||
time:[init().lastThreeMonth,init().nowDate],
|
||||
type:'lastThreeMonth',
|
||||
name:'近3个月'
|
||||
},
|
||||
{
|
||||
time:[init().halfYear,init().nowDate],
|
||||
type:'halfYear',
|
||||
name:'近半年'
|
||||
},
|
||||
{
|
||||
time:[init().lastYear,init().nowDate],
|
||||
type:'lastYear',
|
||||
name:'近一年'
|
||||
}
|
||||
])
|
||||
// 时间搜索
|
||||
const currentValue = ref({
|
||||
type: 'first',
|
||||
time: []
|
||||
})
|
||||
const loadDateFn = (data) =>{
|
||||
currentValue.value.type = data.type
|
||||
currentValue.value.time = data.time
|
||||
}
|
||||
|
||||
const save = () =>{
|
||||
if(currentValue.value.type == 'first' ||currentValue.value.type == 'second'){
|
||||
create_time.value = dateList.nowDate
|
||||
let start = new Date(create_time.value[0]).getTime()
|
||||
let end = new Date(create_time.value[1]).getTime()
|
||||
if( start > end){
|
||||
uni.showToast({ title: '开始时间不能大于结束时间', icon: 'none' })
|
||||
return
|
||||
}
|
||||
}else{
|
||||
create_time.value = currentValue.value.time
|
||||
}
|
||||
emits('confirm',create_time.value)
|
||||
show.value = false
|
||||
}
|
||||
const reset = () =>{
|
||||
currentValue.value.type = 'first'
|
||||
dateList.curIndex = init().curIndex
|
||||
dateList.nowDate = [init().nowDate,init().nowDate]
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.uni-picker-view-content){
|
||||
z-index: 10;
|
||||
}
|
||||
:deep(.uni-picker-view-indicator::before){
|
||||
border: none !important;
|
||||
}
|
||||
:deep(.uni-picker-view-indicator::after){
|
||||
border: none !important;
|
||||
}
|
||||
</style>
|
||||
49
uni-app/src/app/pages/member/contact.vue
Normal file
49
uni-app/src/app/pages/member/contact.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<view class="flex items-center justify-center min-h-[100vh]" :style="themeColor()">
|
||||
<view class="contact-wrap pt-[5%]">
|
||||
<image :src="img('static/resource/images/member/contact_service.png')" mode="widthFix" />
|
||||
<view class="mt-[40rpx] text-[28rpx]">
|
||||
欢迎您联系我们,提供您宝贵的意见!
|
||||
</view>
|
||||
<nc-contact
|
||||
:send-message-title="sendMessageTitle"
|
||||
:send-message-path="sendMessagePath"
|
||||
:send-message-img="sendMessageImg">
|
||||
<button type="primary" class="btn-wrap primary-btn-bg">{{ t('customerService') }}</button>
|
||||
</nc-contact>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { t } from '@/locale'
|
||||
import { img } from '@/utils/common';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const sendMessageTitle = ref('')
|
||||
const sendMessagePath = ref('')
|
||||
const sendMessageImg = ref('')
|
||||
|
||||
sendMessageImg.value = img('static/resource/images/member/contact_service.png')
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.contact-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
image {
|
||||
width: 674rpx;
|
||||
}
|
||||
|
||||
.btn-wrap {
|
||||
margin-top: 120rpx;
|
||||
width: 530rpx;
|
||||
height: 88rpx;
|
||||
font-size: 32rpx;
|
||||
border-radius: 50rpx;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,34 +1,56 @@
|
||||
<template>
|
||||
<view class="member-record-list" :style="themeColor()">
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getListFn" top="">
|
||||
<view v-for="(item,index) in list" :key="item.id" class="member-record-item">
|
||||
<view class="name">{{item.from_type_name}}</view>
|
||||
<view class="desc" v-if="item.memo">{{item.memo}}</view>
|
||||
<view class="desc">{{item.create_time}}</view>
|
||||
<view class="money" :class="item.account_data > 0 ? 'text-active' : ''">
|
||||
{{ item.account_data > 0 ? '+' + item.account_data : item.account_data }}
|
||||
<view class="min-h-[100vh] bg-[#F6F6F6] overflow-hidden" :style="themeColor()">
|
||||
<view class="fixed left-0 right-0 top-0 z-99">
|
||||
<view class="bg-[#fff] px-[var(--sidebar-m)] h-[88rpx] flex items-center">
|
||||
<view class="flex-1 flex items-center h-[60rpx] bg-[#F8F9FD] rounded-[30rpx] px-[20rpx]">
|
||||
<u-input class="flex-1" maxlength="50" v-model="keyword" @confirm="searchTypeFn()" placeholder="请输入搜索关键词" placeholderClass="text-[#999] text-[24rpx]" fontSize="26rpx" clearable border="none"></u-input>
|
||||
<text class="nc-iconfont nc-icon-sousuo-duanV6xx1 text-[28rpx] ml-[32rpx] !text-[#999]" @click="searchTypeFn()"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tab-style-1 pt-[14rpx] bg-[#fff]">
|
||||
<view class="tab-left">
|
||||
<view class="tab-left-item" :class="{'!text-primary class-select':fromType.from_type === item.from_type && fromType.account_data_gt === item.account_data_gt}" v-for="(item,index) in accountTypeList" :key="index" @click="fromTypeFn(item,index)">{{ item.name }}</view>
|
||||
</view>
|
||||
<view class="tab-right" @click="handleSelect">
|
||||
<view class="tab-right-date">日期</view>
|
||||
<view class="nc-iconfont nc-icon-riliV6xx tab-right-icon"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getListFn" top="196rpx">
|
||||
<view v-for="(item,index) in list" :key="item.id" class="sidebar-marign mb-[20rpx] card-template relative">
|
||||
<view class="flex items-center justify-between mb-[10rpx]">
|
||||
<view class="text-[28rpx] font-500 text-[#333] leading-[40rpx]">{{item.from_type_name}}</view>
|
||||
<view class="absolute right-[30rpx] top-[30rpx] text-[36rpx] font-500 text-[#03B521] leading-[50rpx]" :class="{'!text-[var(--price-text-color)]':item.account_data > 0}">{{ item.account_data > 0 ? '+' + item.account_data : item.account_data }}</view>
|
||||
</view>
|
||||
<view class="text-[24rpx] leading-[34rpx] text-[#8288A2] mb-[10rpx]" v-if="item.memo">{{item.memo}}</view>
|
||||
<view class="text-[24rpx] leading-[34rpx] text-[#8288A2]">{{item.create_time}}</view>
|
||||
</view>
|
||||
<view class="mx-[30rpx] rounded-[16rpx] noData flex items-center justify-center" v-if="!list.length && loading">
|
||||
<mescroll-empty :option="{tip : tip}"></mescroll-empty>
|
||||
</view>
|
||||
<mescroll-empty v-if="!list.length && loading" :option="{tip : tip}"></mescroll-empty>
|
||||
</mescroll-body>
|
||||
<!-- 时间选择 -->
|
||||
<select-date ref="selectDateRef" @confirm="confirmFn" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref,nextTick } from 'vue'
|
||||
import { ref,nextTick, reactive } from 'vue'
|
||||
import { t } from '@/locale'
|
||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
||||
import { getBalanceList, getMoneyList, getCommissionList} from '@/app/api/member';
|
||||
import { onPageScroll, onReachBottom, onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import selectDate from '@/components/select-date/select-date.vue';
|
||||
|
||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
||||
|
||||
const type = ref('')
|
||||
const tip = ref('')
|
||||
|
||||
onLoad((options) => {
|
||||
onLoad((options: any) => {
|
||||
type.value = options.type || 'balance';
|
||||
nextTick(()=>{
|
||||
setTimeout(()=>{
|
||||
@ -43,6 +65,18 @@
|
||||
})
|
||||
});
|
||||
|
||||
const keyword = ref<string>('')
|
||||
const create_time = ref([])
|
||||
//来源类型
|
||||
const fromType = ref({
|
||||
from_type:'',
|
||||
account_data_gt:''
|
||||
})
|
||||
const accountTypeList = ref([
|
||||
{name:'全部',from_type:'',account_data_gt: ''},
|
||||
{name:'佣金',from_type:'',account_data_gt: 0},
|
||||
{name:'提现',from_type:'cash_out',account_data_gt: ''},
|
||||
])
|
||||
const list = ref<Array<any>>([]),
|
||||
loading = ref<boolean>(false),
|
||||
mescrollRef = ref(null);
|
||||
@ -58,7 +92,11 @@
|
||||
loading.value = false;
|
||||
let data : Object = {
|
||||
page: mescroll.num,
|
||||
page_size: mescroll.size
|
||||
page_size: mescroll.size,
|
||||
keyword:keyword.value,
|
||||
create_time:create_time.value,
|
||||
from_type:fromType.value.from_type,
|
||||
account_data_gt: fromType.value.account_data_gt
|
||||
};
|
||||
interface acceptingDataStructure {
|
||||
data : acceptingDataItemStructure,
|
||||
@ -89,8 +127,36 @@
|
||||
mescroll.endErr(); // 请求失败, 结束加载
|
||||
})
|
||||
}
|
||||
|
||||
// 关键词搜索条件搜索
|
||||
const searchTypeFn = () =>{
|
||||
list.value = [];
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
// 类型搜索
|
||||
const fromTypeFn = (data : any ,index : number)=>{
|
||||
fromType.value.from_type = data.from_type
|
||||
fromType.value.account_data_gt = data.account_data_gt
|
||||
list.value = []
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
|
||||
//日期筛选
|
||||
const selectDateRef = ref()
|
||||
const handleSelect = () =>{
|
||||
selectDateRef.value.show = true
|
||||
}
|
||||
// 确定时间筛选
|
||||
const confirmFn = (data) =>{
|
||||
create_time.value = data;
|
||||
list.value = []
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '@/styles/member_record_list.scss';
|
||||
.noData{
|
||||
height: calc(100vh - 210rpx - constant(safe-area-inset-bottom));
|
||||
height: calc(100vh - 210rpx - env(safe-area-inset-bottom));
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup>
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
|
||||
</view>
|
||||
@ -65,6 +65,9 @@
|
||||
useMemberStore().getMemberInfo()
|
||||
}
|
||||
});
|
||||
|
||||
// 监听页面卸载
|
||||
diy.onUnload();
|
||||
|
||||
// 监听下拉刷新事件
|
||||
diy.onPullDownRefresh()
|
||||
|
||||
@ -3,22 +3,18 @@
|
||||
<u-loading-page :loading="loading && memberInfo" loadingText="" bg-color="#f7f7f7"></u-loading-page>
|
||||
<view v-if="!loading && memberInfo && list && list.length" class=" min-h-[100vh] overflow-hidden flex flex-col" :style="{backgroundColor: currLevelInfo.level_style.bg_color }">
|
||||
<!-- #ifdef MP -->
|
||||
<top-tabbar :data="topTabbarData" titleColor="#fff"/>
|
||||
<top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()"/>
|
||||
<!-- #endif -->
|
||||
<view>
|
||||
<view class="pt-[40rpx] mb-[20rpx]">
|
||||
<!-- 轮播图 -->
|
||||
<view class="relative">
|
||||
<swiper class="swiper ns-indicator-dots relative" :style="{ height: '300rpx' }" @change="swiperChange" :current = "swiperIndex"
|
||||
previous-margin="48rpx" next-margin="48rpx">
|
||||
<swiper class="swiper ns-indicator-dots relative" :style="{ height: '300rpx' }" @change="swiperChange" :current = "swiperIndex" previous-margin="48rpx" next-margin="48rpx">
|
||||
<swiper-item class="swiper-item" v-for="(item,index) in list" :key="item.id">
|
||||
<view class="h-[300rpx] relative">
|
||||
<view v-if="memberInfo.member_level == item.level_id && swiperIndex == index" class="text-[24rpx] absolute top-0 left-0 z-10 h-[66rpx] !bg-contain w-[150rpx] flex pt-[12rpx] pl-[16rpx] leadinig-[34rpx] box-border" :style="{ background: 'url(' + img(currLevelInfo.level_tag) + ') no-repeat',color: currLevelInfo.level_style.level_color}">
|
||||
<view v-if="memberInfo.member_level == item.level_id && swiperIndex == index" class="text-[24rpx] absolute top-0 left-0 z-10 h-[66rpx] !bg-contain w-[150rpx] flex pt-[12rpx] pl-[16rpx] box-border" :style="{ background: 'url(' + img(currLevelInfo.level_tag) + ') no-repeat',color: currLevelInfo.level_style.level_color}">
|
||||
当前等级
|
||||
</view>
|
||||
<view v-else-if="Number(memberInfo.growth) < Number(currLevelInfo.growth) && swiperIndex == index" class="text-[24rpx] absolute top-0 left-0 z-10 h-[66rpx] !bg-contain w-[150rpx] text-[#999] flex pt-[12rpx] pl-[16rpx] leadinig-[34rpx] box-border" :style="{ background: 'url(' + img('static/resource/images/member/level/not_reach.png') + ') no-repeat'}" >
|
||||
未达标
|
||||
</view>
|
||||
<view class="absolute top-0 left-0 right-0 bottom-0 z-20 px-[30rpx] pt-[76rpx] box-border" :class="{'px-[50rpx]': swiperIndex != index}">
|
||||
<view class="flex items-center leading-[50rpx] mb-[70rpx]">
|
||||
<image class="h-[32rpx] w-[34rpx] align-middle" :src="img(item.level_icon ? item.level_icon : '')" mode="aspectFill" />
|
||||
@ -26,7 +22,7 @@
|
||||
</view>
|
||||
<view class="flex items-center" :style="{color: currLevelInfo.level_style.level_color}">
|
||||
<view class="text-[28rpx] font-bold leading-[38rpx]">{{ memberInfo.growth }}</view>
|
||||
<view class="text-[24rpx] leading-[34rpx]">/{{list[index].growth}}成长值</view>
|
||||
<view class="text-[24rpx] leading-[34rpx] font-500">/{{list[index].growth}}成长值</view>
|
||||
</view>
|
||||
<view class="flex justify-between items-center mt-[10rpx]">
|
||||
<view class="flex flex-col flex-1">
|
||||
@ -60,14 +56,14 @@
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex mx-[30rpx] px-[38rpx] pt-[30rpx] pb-[46rpx] items-center flex-col level_benefits" v-if="currLevelInfo.benefits_arr && currLevelInfo.benefits_arr.length" :style="{ backgroundImage: 'url(' + img(currLevelInfo.member_bg) + ')'}">
|
||||
<view class="flex mx-[30rpx] pt-[30rpx] pb-[46rpx] items-center flex-col level_benefits" v-if="currLevelInfo.benefits_arr && currLevelInfo.benefits_arr.length" :style="{ backgroundImage: 'url(' + img(currLevelInfo.member_bg) + ')'}">
|
||||
<view class="flex items-center justify-center">
|
||||
<text class="text-[#fff] text-[32rpx] font-bold leading-[44rpx]">会员权益</text>
|
||||
</view>
|
||||
<view class="flex flex-wrap w-[690rpx] mt-[40rpx] justify-between">
|
||||
<view class="flex flex-col w-[25%] items-center" v-for="(item,index) in currLevelInfo.benefits_arr" :key="index">
|
||||
<image class="h-[100rpx] w-[100rpx]" :src="img(item.icon)" mode="heightFix" />
|
||||
<text class="text-[rgba(255,255,255,0.9)] mt-[10rpx] text-[24rpx]">{{item.title}}</text>
|
||||
<text class="text-[rgba(255,255,255,0.9)] mt-[10rpx] text-[24rpx] leading-[34rpx]">{{item.title}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -77,7 +73,7 @@
|
||||
<!-- 升级礼包 -->
|
||||
<view v-if="currLevelInfo.gifts_arr && currLevelInfo.gifts_arr.length">
|
||||
<view class="pt-[10rpx] pb-[30rpx] flex items-center">
|
||||
<text class="text-[32rpx] text-[#3A3945] font-bold leading-[44rpx]">升级礼包</text>
|
||||
<text class="text-[32rpx] text-[#333] font-bold leading-[44rpx]">升级礼包</text>
|
||||
</view>
|
||||
<view class="flex flex-wrap">
|
||||
<view v-for="(item,index) in currLevelInfo.gifts_arr" :key="index" class="mb-[20rpx]" :class="{'mr-[20rpx]': (index+1) % 3 != 0}">
|
||||
@ -106,34 +102,33 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-empty v-if="!loading && (!list || !list.length)" :icon="img('static/resource/images/empty.png')" text="暂无会员等级" />
|
||||
<view v-if="!loading && (!list || !list.length)" class="h-[100vh] w-full flex items-center justify-center">
|
||||
<u-empty :icon="img('static/resource/images/empty.png')" text="暂无会员等级" />
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { getMemberLevel, getTaskGrowth } from '@/app/api/member';
|
||||
import { img,redirect, deepClone, getToken } from '@/utils/common';
|
||||
import useMemberStore from '@/stores/member'
|
||||
import { topTabar } from '@/utils/topTabbar'
|
||||
|
||||
const memberStore = useMemberStore()
|
||||
|
||||
let loading = ref(false)
|
||||
let list = ref([]) // 会员等级
|
||||
let upgradeSkills = ref([]) // 升级技巧
|
||||
const loading = ref(false)
|
||||
const list = ref([]) // 会员等级
|
||||
const upgradeSkills = ref([]) // 升级技巧
|
||||
const swiperIndex = ref(0); //当前滑块的索引
|
||||
const levelIndex = ref(0); //当前等级的索引
|
||||
// 自定义头部
|
||||
let topTabbarData = ref({
|
||||
title: '会员等级',
|
||||
topStatusBar: {
|
||||
isTransparent: true,
|
||||
style: 'style-1',
|
||||
bgColor: 'transparent',
|
||||
textColor: '#fff'
|
||||
}
|
||||
})
|
||||
|
||||
/********* 自定义头部 - start ***********/
|
||||
const topTabarObj = topTabar()
|
||||
let topTabbarData = topTabarObj.setTopTabbarParam({title:'会员等级'})
|
||||
/********* 自定义头部 - end ***********/
|
||||
|
||||
onShow(() => {
|
||||
// 判断是否已登录
|
||||
@ -149,7 +144,7 @@
|
||||
})
|
||||
|
||||
// 进度条值
|
||||
let progress = (index:any) => {
|
||||
const progress = (index:any) => {
|
||||
let indent = index;
|
||||
let num = 100
|
||||
if(list.value[indent] && list.value[indent].growth) {
|
||||
@ -159,7 +154,7 @@
|
||||
}
|
||||
|
||||
// 所需的成长值
|
||||
let upgradeGrowth = (index:any) => {
|
||||
const upgradeGrowth = (index:any) => {
|
||||
let indent = index;
|
||||
let num = 0;
|
||||
if(list.value[indent] && list.value[indent].growth) {
|
||||
@ -228,8 +223,8 @@
|
||||
};
|
||||
|
||||
// 当前的会员等级信息
|
||||
let currLevelInfo = ref<any>({});
|
||||
let infoStructureFn = (index:number)=>{
|
||||
const currLevelInfo = ref<any>({});
|
||||
const infoStructureFn = (index:number)=>{
|
||||
let data:any = deepClone(list.value[index]);
|
||||
// 会员权益
|
||||
if(data && data.level_benefits){
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="mt-[40rpx]">
|
||||
<u-button type="primary" shape="circle" :text="t('save')" @click="save" :disabled="btnDisabled" :loading="operateLoading"></u-button>
|
||||
<button class="!bg-[var(--primary-color)] !text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" :class="{'opacity-50': btnDisabled}" @click="save" :disabled="btnDisabled" :loading="operateLoading">{{t('save')}}</button>
|
||||
</view>
|
||||
</u-form>
|
||||
</view>
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup>
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
@ -79,15 +79,15 @@
|
||||
type: 'location_address'
|
||||
})
|
||||
|
||||
onLoad((option) => {
|
||||
onLoad((option:any) => {
|
||||
if (option.id) {
|
||||
getAddressInfo(option.id).then(({data}) => {
|
||||
getAddressInfo(option.id).then(({ data }) => {
|
||||
if (data) {
|
||||
Object.assign(formData.value, data)
|
||||
formData.value.area = formData.value.full_address.replace(formData.value.address, '').replace(formData.value.address_name, '')
|
||||
}
|
||||
}).catch()
|
||||
}else if (option.name) {
|
||||
} else if (option.name) {
|
||||
if (uni.getStorageSync('addressInfo')) {
|
||||
Object.assign(formData.value, uni.getStorageSync('addressInfo'))
|
||||
}
|
||||
|
||||
@ -2,14 +2,14 @@
|
||||
<view class="w-full h-screen bg-page personal-wrap" v-if="info" :style="themeColor()">
|
||||
<view class="flex flex-col items-center pt-[30rpx]">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button open-type="chooseAvatar" @chooseavatar="onChooseAvatar" :plain="true" class="border-0">
|
||||
<u-avatar :src="img(info.headimg)" size="60" leftIcon="none"></u-avatar>
|
||||
<button open-type="chooseAvatar" @chooseavatar="onChooseAvatar" :plain="true" class="border-0" @click="checkWxPrivacy">
|
||||
<u-avatar :src="img(info.headimg)" :default-url="img('static/resource/images/default_headimg.png')" size="60" leftIcon="none"></u-avatar>
|
||||
<view class="text-primary text-sm mt-[10rpx]">{{ t('updateHeadimg') }}</view>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<u-upload @afterRead="afterRead" :maxCount="1">
|
||||
<u-avatar :src="img(info.headimg)" size="60" leftIcon="none"></u-avatar>
|
||||
<u-avatar :src="img(info.headimg)" :default-url="img('static/resource/images/default_headimg.png')" size="60" leftIcon="none"></u-avatar>
|
||||
<view class="text-primary text-sm mt-[10rpx]">{{ t('updateHeadimg') }}</view>
|
||||
</u-upload>
|
||||
<!-- #endif -->
|
||||
@ -23,23 +23,23 @@
|
||||
<template #value>
|
||||
<view v-if="info.mobile" class="mr-[10rpx]">{{ mobileConceal(info.mobile) }}</view>
|
||||
<view v-else @click="redirect({ url: '/app/pages/auth/bind' })">
|
||||
<u-button type="primary" :plain="true" :text="t('bindMobile')" shape="circle" size="mini"></u-button>
|
||||
<button class="bg-transparent w-[132rpx] p-[0] rounded-[100rpx] text-[var(--primary-color)] !border-[2rpx] !border-solid border-[var(--primary-color)] text-[20rpx] h-[44rpx] leading-[40rpx]">{{t('bindMobile')}}</button>
|
||||
</view>
|
||||
</template>
|
||||
</u-cell>
|
||||
<u-cell :title="t('birthday')" :is-link="true" :value="info.birthday || t('unknown')" @click="birthdayPicker = true"></u-cell>
|
||||
<u-cell :title="t('birthday')" :is-link="true" :value="formatDate(info.birthday) || t('unknown')" @click="birthdayPicker = true"></u-cell>
|
||||
</u-cell-group>
|
||||
</view>
|
||||
|
||||
<u-modal :show="updateNickname.modal" :closeOnClickOverlay="true" @close="updateNickname.modal = false"
|
||||
:show-cancel-button="true"
|
||||
@cancel="updateNickname.modal = false" :title="t('updateNickname')">
|
||||
@cancel="updateNickname.modal = false" :title="t('updateNickname')" confirmColor="var(--primary-color)">
|
||||
<view class="w-full mt-[20rpx] border-0 border-b border-gray-300 border-solid py-[20rpx]">
|
||||
<input type="nickname" v-model="updateNickname.value" :placeholder="t('nicknamePlaceholder')" @blur="bindNickname">
|
||||
</view>
|
||||
<template #confirmButton>
|
||||
<view class="mt-[10rpx]">
|
||||
<u-button type="primary" :text="t('confirm')" shape="circle" @click="updateNicknameConfirm"></u-button>
|
||||
<button class="bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" @click="updateNicknameConfirm">{{t('confirm')}}</button>
|
||||
</view>
|
||||
</template>
|
||||
</u-modal>
|
||||
@ -52,11 +52,15 @@
|
||||
:maxDate="new Date().valueOf()" :minDate="0"
|
||||
:cancel-text="t('cancel')" @cancel="birthdayPicker = false" @confirm="updateBirthday"></u-datetime-picker>
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, reactive, watch } from 'vue'
|
||||
import { ref, computed, reactive } from 'vue'
|
||||
import { t } from '@/locale'
|
||||
import useMemberStore from '@/stores/member'
|
||||
import { img, redirect,mobileConceal } from '@/utils/common'
|
||||
@ -66,6 +70,14 @@
|
||||
const memberStore = useMemberStore()
|
||||
const info = computed(() => memberStore.info)
|
||||
|
||||
|
||||
const wxPrivacyPopupRef:any = ref(null)
|
||||
|
||||
// 检测是否同意隐私协议
|
||||
const checkWxPrivacy = ()=>{
|
||||
wxPrivacyPopupRef.value.proactive();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改昵称
|
||||
*/
|
||||
@ -73,9 +85,11 @@
|
||||
modal: false,
|
||||
value: info.nickname || ''
|
||||
})
|
||||
|
||||
const bindNickname = (e) => {
|
||||
updateNickname.value = e.detail.value
|
||||
}
|
||||
|
||||
const updateNicknameConfirm = () => {
|
||||
if (uni.$u.test.isEmpty(updateNickname.value)) { uni.showToast({ title: t('nicknamePlaceholder'), icon: 'none' }); return }
|
||||
|
||||
@ -155,13 +169,22 @@
|
||||
birthdayPicker.value = false
|
||||
})
|
||||
}
|
||||
const formatDate=(date:any)=>{
|
||||
return date ? uni.$u.date(new Date(date), 'yyyy-mm-dd') : ''
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background: var(--page-bg-color);
|
||||
}
|
||||
|
||||
:deep(.u-upload__wrap ){
|
||||
>view{
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
}
|
||||
:deep(.u-cell-group__wrapper) {
|
||||
.u-cell__body {
|
||||
padding-left: 0;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<view class="w-full bg-[#F6F6F6]">
|
||||
<view class="pb-[210rpx] relative" :style="headerStyle">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<top-tabbar :data="param" titleColor="#fff" class="top-header"/>
|
||||
<top-tabbar :data="param" :scrollBool="topTabarObj.getScrollBool()" class="top-header"/>
|
||||
<!-- #endif -->
|
||||
<view class="text-[70rpx] leading-[98rpx] text-[#fff] pl-[60rpx] font-600 pt-[77rpx]">{{pointInfo.point||0}}</view>
|
||||
<view class="flex items-center pl-[60rpx]">
|
||||
@ -12,16 +12,16 @@
|
||||
<view class="text-[26rpx] leading-[36rpx] text-[#fff] ml-[10rpx]">我的积分</view>
|
||||
</view>
|
||||
<view class="flex items-center absolute right-0 px-[14rpx] bg-color rounded-l-[35rpx] text-[#fff] text-[24rpx] h-[50rpx] z-10" :style="{top: topStyle}" @click="toLink('/app/pages/member/point_detail')">
|
||||
<text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[28rpx] text-[#fff] mr-[4rpx]"></text>
|
||||
<text class="nc-iconfont nc-icon-jifenduihuanV6xx1 text-[28rpx] text-[#fff] mr-[10rpx]"></text>
|
||||
<text class="text-[24rpx]">积分明细</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mx-[30rpx] flex flex-col mt-[-178rpx] relative">
|
||||
<view class="sidebar-marign flex flex-col mt-[-178rpx] relative">
|
||||
<view class="w-[322rpx] h-[80rpx] leading-[80rpx] text-[26rpx] text-[#333] font-bold box-border pl-[30rpx]"
|
||||
:style="{backgroundImage: 'url(' + img('static/resource/images/member/point/top_bg.png') + ') ',backgroundSize: '100% 100%',backgroundRepeat: 'no-repeat'}">
|
||||
积分详情
|
||||
</view>
|
||||
<view class="flex items-center w-[690rpx] px-[30rpx] rounded-[16rpx] !rounded-tl-none bg-[#fff] h-[173rpx] box-border">
|
||||
<view class="flex items-center px-[30rpx] rounded-[16rpx] !rounded-tl-none bg-[#fff] h-[173rpx] box-border">
|
||||
<view class="w-[196rpx] flex-shrink-0 text-center">
|
||||
<view class="text-[#333] text-[42rpx] leading-[59rpx] font-bold">{{pointInfo.point_get||0}}</view>
|
||||
<view class="mt-[8rpx] text-[#666] text-[26rpx] leading-[36rpx] font-400">累计积分</view>
|
||||
@ -39,7 +39,7 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-[20rpx] mx-[30rpx] p-[30rpx] pb-[70rpx] box-border rounded-[16rpx] bg-[#fff]">
|
||||
<view class="mt-[20rpx] sidebar-marign p-[30rpx] pb-[70rpx] box-border rounded-[16rpx] bg-[#fff]">
|
||||
<view class="text-[32rpx] leading-[45rpx] font-bold">热门活动</view>
|
||||
<view class="mt-[50rpx] flex justify-between">
|
||||
<view class="w-[200rpx] h-[253rpx] box-border pt-[69rpx] relative text-center"
|
||||
@ -116,18 +116,15 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { t } from '@/locale'
|
||||
import { redirect, img } from '@/utils/common';
|
||||
import { redirect, img,pxToRpx } from '@/utils/common';
|
||||
import { getMemberAccountPointcount,getTaskPoint } from '@/app/api/member';
|
||||
import { topTabar } from '@/utils/topTabbar'
|
||||
|
||||
/********* 自定义头部 - start ***********/
|
||||
const topTabarObj = topTabar()
|
||||
let param = topTabarObj.setTopTabbarParam({title:'我的积分'})
|
||||
/********* 自定义头部 - end ***********/
|
||||
|
||||
let param = ref({
|
||||
title:'我的积分',
|
||||
topStatusBar: {
|
||||
style: 'style-1',
|
||||
isTransparent: true,
|
||||
bgColor: 'transparent',
|
||||
textColor: '#fff'
|
||||
}
|
||||
})
|
||||
// 获取系统状态栏的高度
|
||||
let menuButtonInfo:any = {};
|
||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
||||
@ -148,11 +145,7 @@ const topStyle = computed(() => {
|
||||
style = Object.keys(menuButtonInfo).length?(pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) + 38) + 'rpx;':'38rpx'
|
||||
return style
|
||||
})
|
||||
// px转rpx
|
||||
const pxToRpx=(px)=> {
|
||||
const screenWidth = uni.getSystemInfoSync().screenWidth
|
||||
return (750 * Number.parseInt(px)) / screenWidth
|
||||
}
|
||||
|
||||
//个人积分信息
|
||||
const pointInfo = ref({});
|
||||
//积分任务
|
||||
|
||||
@ -1,37 +1,101 @@
|
||||
<template>
|
||||
<view class="bg-gray-100 min-h-[100vh]" :class="{'bg-[#fff]':!pointList.length}" :style="themeColor()">
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getPointListFn">
|
||||
<view v-for="(item,index) in pointList" :key="item.id" :class="['bg-white relative p-[10px]',{'border-solid border-t-0 border-l-0 border-r-0 border-b-[1px] border-gray-200': pointList.length-1 != index}] ">
|
||||
<view class="text-[14px]">{{item.from_type_name}}</view>
|
||||
<view class="text-[12px] text-gray-400 mt-[10px]">{{item.create_time}}</view>
|
||||
<view class="text-[14px] absolute top-[50%] transform -translate-y-[50%] right-[10px]" :class="{ 'text-primary' : item.account_data > 0 }">{{item.account_data > 0 ? '+' + item.account_data : item.account_data}}</view>
|
||||
<view class="bg-[#F6F6F6] min-h-[100vh]" :style="themeColor()">
|
||||
<view class="fixed left-0 right-0 top-0 z-10085">
|
||||
<view class="bg-[#fff] px-[var(--sidebar-m)] py-[14rpx] relative z-10084">
|
||||
<view class="flex items-center h-[60rpx] bg-[#F8F9FD] rounded-[30rpx] px-[20rpx]">
|
||||
<view class="flex-1 text-[26rpx] leading-[60rpx] text-[#8288A2]" :class="{'!text-[#333]':from_type}" @click="typePopup = true">{{from_type_name || '请选择来源用途'}}</view>
|
||||
<text class="nc-iconfont nc-icon-shangV6xx-1 text-[32rpx] ml-[18rpx] !text-[#626779]" v-if="typePopup" @click="typePopup = false"></text>
|
||||
<text class="nc-iconfont nc-icon-xiaV6xx text-[32rpx] ml-[18rpx] !text-[#626779]" v-else @click="typePopup = true"></text>
|
||||
</view>
|
||||
</view>
|
||||
<u-popup :show="typePopup" mode="top" @close="typePopup = false" class="type-class">
|
||||
<view @touchmove.prevent.stop class="py-[22rpx]">
|
||||
<view class="leading-[80rpx] text-[26rpx] text-[#333] px-[50rpx]" :class="{'bg-[#FDF8F8] !text-primary font-500' : from_type == ''}" @click="searchTypeFn()">全部</view>
|
||||
<view class="leading-[80rpx] text-[26rpx] text-[#333] px-[50rpx]" :class="{'bg-[#FDF8F8] !text-primary font-500' : from_type == index}" v-for="(item,index) in pointType" @click="searchTypeFn(index,item)">{{ item.name }}</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<view class="px-[var(--sidebar-m)] pt-[30rpx] pb-[20rpx] flex items-center justify-between bg-[#F6F6F6]">
|
||||
<view class="flex items-center">
|
||||
<view class="px-[20rpx] py-[6rpx] bg-[#fff] rounded-[30rpx] text-[26rpx] leading-[36rpx] mr-[20rpx] text-[#333]" :class="{'!text-[var(--primary-color)] font-500':amount_type == item.status}" v-for="(item,index) in typeList" :key="index" @click="loadTypeFn(item.status)">{{ item.name }}</view>
|
||||
</view>
|
||||
<view class="flex items-center" @click="handleSelect">
|
||||
<view class="text-[26rpx] text-[#333] mr-[10rpx]">日期</view>
|
||||
<view class="nc-iconfont nc-icon-riliV6xx !text-[28rpx] leading-[36rpx]"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getPointListFn" top="186rpx">
|
||||
<view v-for="(item,index) in pointList" :key="index" class="bg-white sidebar-marign rounded-[16rpx] px-[30rpx] mb-[20rpx] py-[12rpx]">
|
||||
<view class="flex justify-between items-center">
|
||||
<view class="text-[20rpx] text-[#333] font-500">
|
||||
<text>{{item.month_info.year}}年</text>
|
||||
<text class="text-[36rpx] font-bold ml-[10rpx] mr-[4rpx]">{{item.month_info.month}}</text>
|
||||
<text>月</text>
|
||||
</view>
|
||||
<view>
|
||||
<text class="nc-iconfont nc-icon-xiaV6xx !text-[32rpx] text-[#626779]" v-if="item.flag" @click="item.flag = false"></text>
|
||||
<text class="nc-iconfont nc-icon-shangV6xx-1 !text-[32rpx] text-[#626779]" v-else @click="item.flag = true"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-show="item.flag">
|
||||
<block v-for="(subItem,subIndex) in item.month_data" :key="subItem.id">
|
||||
<view class="flex items-center ">
|
||||
<view class="w-[60rpx] h-[60rpx]">
|
||||
<image v-if="subItem.account_data > 0" :src="img('static/resource/images/member/point/detail/point_add.png')" class="w-[60rpx] h-[60rpx]"></image>
|
||||
<image v-else :src="img('static/resource/images/member/point/detail/point_min.png')" class="w-[60rpx] h-[60rpx]"></image>
|
||||
</view>
|
||||
<view class="flex-1 flex items-center ml-[20rpx] box-border py-[20rpx] border-0" :class="{'border-solid border-t-[2rpx] border-[#F0F2F8]' : subIndex}">
|
||||
<view class="flex-1">
|
||||
<view class="text-[26rpx] font-500 leading-[36rpx] text-[#333]">{{subItem.from_type_name}}</view>
|
||||
<view class="text-[24rpx] text-[#8288A2] leading-[34rpx] mt-[4rpx]">{{subItem.create_time}}</view>
|
||||
</view>
|
||||
<view class="text-[36rpx] font-500 text-[#03B521]" :class="{ '!text-primary' : subItem.account_data > 0 }">{{subItem.account_data > 0 ? '+' + subItem.account_data : subItem.account_data}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mx-[30rpx] rounded-[16rpx] noData flex items-center justify-center" v-if="!pointList.length && loading">
|
||||
<mescroll-empty :option="{tip : '暂无积分明细'}"></mescroll-empty>
|
||||
</view>
|
||||
<mescroll-empty v-if="!pointList.length && loading" :option="{tip : '暂无积分明细'}"></mescroll-empty>
|
||||
</mescroll-body>
|
||||
<!-- 时间选择 -->
|
||||
<select-date ref="selectDateRef" @confirm="confirmFn" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { t } from '@/locale'
|
||||
import { redirect, img } from '@/utils/common';
|
||||
import { getPointList } from '@/app/api/member';
|
||||
import { getPointList, getPointType } from '@/app/api/member';
|
||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
||||
|
||||
import selectDate from '@/components/select-date/select-date.vue';
|
||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
||||
|
||||
let pointList = ref<Array<any>>([]);
|
||||
let mescrollRef = ref(null);
|
||||
let loading = ref<boolean>(false);
|
||||
const from_type = ref('');
|
||||
const from_type_name = ref('')
|
||||
const amount_type = ref('all');
|
||||
const create_time = ref([])
|
||||
const pointList = ref<Array<any>>([]);
|
||||
const mescrollRef = ref(null);
|
||||
const loading = ref<boolean>(false);
|
||||
const typeList = ref([
|
||||
{name:'全部',status:'all'},
|
||||
{name:'收入',status:'income'},
|
||||
{name:'支出',status:'disburse'}
|
||||
])
|
||||
|
||||
const getPointListFn = (mescroll)=> {
|
||||
let data = {
|
||||
page: mescroll.num,
|
||||
page_size: mescroll.size
|
||||
page_size: mescroll.size,
|
||||
from_type:from_type.value,
|
||||
amount_type:amount_type.value,
|
||||
create_time: create_time.value
|
||||
};
|
||||
loading.value = false;
|
||||
getPointList(data).then((res) => {
|
||||
@ -42,12 +106,60 @@ const getPointListFn = (mescroll)=> {
|
||||
pointList.value = []; //如果是第一页需手动制空列表
|
||||
}
|
||||
pointList.value = pointList.value.concat(newArr);
|
||||
pointList.value = pointList.value.map(item =>{
|
||||
item.flag = true
|
||||
return item
|
||||
})
|
||||
loading.value = true;
|
||||
}).catch(() => {
|
||||
loading.value = true;
|
||||
mescroll.endErr(); // 请求失败, 结束加载
|
||||
})
|
||||
}
|
||||
|
||||
const pointType = ref({})
|
||||
const getPointTypeFn = () =>{
|
||||
getPointType('point').then(res =>{
|
||||
pointType.value = res.data
|
||||
})
|
||||
}
|
||||
getPointTypeFn()
|
||||
// 关键词搜索条件搜索
|
||||
const typePopup = ref(false)
|
||||
const searchTypeFn = (index:string = '',item:any = {}) =>{
|
||||
from_type.value = index
|
||||
from_type_name.value = item.name
|
||||
typePopup.value = false
|
||||
pointList.value = [];
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
// 类型搜索
|
||||
const loadTypeFn = (type:string) =>{
|
||||
amount_type.value = type;
|
||||
pointList.value = [];
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
|
||||
//日期筛选
|
||||
const selectDateRef = ref()
|
||||
const handleSelect = () =>{
|
||||
selectDateRef.value.show = true
|
||||
}
|
||||
// 确定时间筛选
|
||||
const confirmFn = (data:any) =>{
|
||||
create_time.value = data;
|
||||
pointList.value = []
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.u-popup.type-class .u-transition) {
|
||||
top: 88rpx !important;
|
||||
box-shadow: 1rpx 1rpx 6rpx 2rpx rgba(184,201,212,0.25);
|
||||
}
|
||||
.noData{
|
||||
height: calc(100vh - 206rpx - constant(safe-area-inset-bottom));
|
||||
height: calc(100vh - 206rpx - env(safe-area-inset-bottom));
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -4,111 +4,115 @@
|
||||
<view v-if="info.is_use">
|
||||
<view class="sigin-header">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="flex items-center absolute right-0 px-[14rpx] bg-color rounded-l-[35rpx] text-[#fff] text-[24rpx] h-[50rpx] z-10" :style="{top: topStyle}" @click="signPopup = true">
|
||||
<text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[28rpx] text-[#fff] mr-[4rpx]"></text>
|
||||
<view class="flex items-center absolute right-0 px-[14rpx] bg-color rounded-l-[35rpx] text-[#fff] text-[24rpx] h-[40rpx] z-10" :style="{top: topStyle}" @click="signPopup = true">
|
||||
<text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[28rpx] text-[#fff] mr-[6rpx]"></text>
|
||||
<text class="text-[24rpx]">签到规则</text>
|
||||
</view>
|
||||
<view :style="{height: headStyle, backgroundImage: 'url(' + img('static/resource/images/app/sigin_uniapp.png') + ')',backgroundSize: '100% 100%', backgroundRepeat: 'no-repeat'}">
|
||||
<top-tabbar :data="topTabbarData" titleColor="#fff" class="top-header" />
|
||||
<top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()" class="top-header" />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<view v-if="info.rule_explain" class="flex items-center absolute top-[38rpx] right-0 px-[14rpx] bg-color rounded-l-[35rpx] text-[#fff] text-[24rpx] h-[50rpx] z-10" @click="signPopup = true">
|
||||
<text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[28rpx] text-[#fff] mr-[4rpx]"></text>
|
||||
<view v-if="info.rule_explain" class="flex items-center absolute top-[44rpx] right-0 px-[14rpx] bg-color rounded-l-[35rpx] text-[#fff] text-[24rpx] h-[40rpx] z-10" @click="signPopup = true">
|
||||
<text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[28rpx] text-[#fff] mr-[6rpx]"></text>
|
||||
<text class="text-[24rpx]">签到规则</text>
|
||||
</view>
|
||||
<view class="h-[382rpx]" :style="{ backgroundImage: 'url(' + img('static/resource/images/app/sigin_h5.png') + ')',backgroundSize: '100%', backgroundRepeat: 'no-repeat'}">
|
||||
<top-tabbar :data="topTabbarData" class="top-header" />
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view>
|
||||
<view class="mx-[30rpx] bg-[#fff] rounded-[16rpx] -mt-[85rpx]">
|
||||
<view class="px-[30rpx]">
|
||||
<view class="pt-[32rpx] mb-[40rpx] flex justify-between items-center" v-if="flag" >
|
||||
<view class="sidebar-marign bg-[#fff] rounded-[16rpx] -mt-[85rpx]">
|
||||
<view class="card-template">
|
||||
<view class=" mb-[30rpx] flex justify-between items-center" v-if="flag">
|
||||
<view class="flex items-center">
|
||||
<text class="iconfont iconshangyibu text-[#999] text-[24rpx]" @click="changeMonth('prev')"></text>
|
||||
<view class="mx-[30rpx] font-bold text-[32rpx] text-[#333] leading-[38rpx]">{{ state.curYear }}年{{ state.curMonth+1 }}月</view>
|
||||
<text class="iconfont iconxiayibu1 text-[#999] text-[24rpx]" @click="changeMonth('next')"></text>
|
||||
<text class="iconfont iconshangyibu text-[#333] text-[24rpx]" @click="changeMonth('prev')"></text>
|
||||
<view class="mx-[30rpx] font-bold text-[32rpx] text-[#333] leading-[45rpx]">{{ state.curYear }}年{{ state.curMonth+1 }}月</view>
|
||||
<text class="iconfont iconxiayibu1 text-[#333] text-[24rpx]" @click="changeMonth('next')"></text>
|
||||
</view>
|
||||
<view class="flex items-center">
|
||||
<text class="nc-iconfont nc-icon-shangV6xx-1 text-[#666] text-[30rpx] transform scale-80" @click="handleChange"></text>
|
||||
<text class="nc-iconfont nc-icon-shangV6xx-1 text-[#626779] text-[26rpx]" @click="handleChange"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pt-[32rpx] mb-[40rpx] flex justify-between items-center" v-else>
|
||||
<view class="mb-[30rpx] flex justify-between items-center" v-else>
|
||||
<view class="flex items-center">
|
||||
<view class="font-bold text-[32rpx] text-[#333] leading-[38rpx]">已连续签到<text class="text-[#EF000C] mx-[4rpx]">{{ info.days }}</text>天</view>
|
||||
<view class="font-500 text-[32rpx] text-[#333] leading-[45rpx]">已连续签到<text class="text-[#EF000C] mx-[4rpx]">{{ info.days }}</text>天</view>
|
||||
</view>
|
||||
<text class="nc-iconfont nc-icon-xiaV6xx text-[#666] text-[30rpx] transform scale-80" v-if="!flag" @click="flag = !flag"></text>
|
||||
<text class="nc-iconfont nc-icon-xiaV6xx text-[#626779] text-[26rpx]" v-if="!flag" @click="flag = !flag"></text>
|
||||
</view>
|
||||
<view class="relative z-9 pb-[30rpx] bg-[#fff] rounded-[18rpx]">
|
||||
<view class="relative z-9 bg-[#fff] rounded-[18rpx]">
|
||||
<view>
|
||||
<view class="flex items-center justify-between text-[#666] text-[26rpx] mb-[14rpx]">
|
||||
<text class="w-[14.2%] leading-[30rpx] text-center">周一</text>
|
||||
<text class="w-[14.2%] leading-[30rpx] text-center">周二</text>
|
||||
<text class="w-[14.2%] leading-[30rpx] text-center">周三</text>
|
||||
<text class="w-[14.2%] leading-[30rpx] text-center">周四</text>
|
||||
<text class="w-[14.2%] leading-[30rpx] text-center">周五</text>
|
||||
<text class="w-[14.2%] leading-[30rpx] text-center">周六</text>
|
||||
<text class="w-[14.2%] leading-[30rpx] text-center">周日</text>
|
||||
<view class="flex items-center justify-between text-[#626779] text-[24rpx] mb-[16rpx]">
|
||||
<text class="w-[14.28%] leading-[36rpx] text-center">周一</text>
|
||||
<text class="w-[14.28%] leading-[36rpx] text-center">周二</text>
|
||||
<text class="w-[14.28%] leading-[36rpx] text-center">周三</text>
|
||||
<text class="w-[14.28%] leading-[36rpx] text-center">周四</text>
|
||||
<text class="w-[14.28%] leading-[36rpx] text-center">周五</text>
|
||||
<text class="w-[14.28%] leading-[36rpx] text-center">周六</text>
|
||||
<text class="w-[14.28%] leading-[36rpx] text-center">周日</text>
|
||||
</view>
|
||||
<view class="flex flex-wrap items-center justify-start" v-if="!flag">
|
||||
<block v-for="(item,index) in state.weekCount" :key="index">
|
||||
<view class="w-[14.2%] flex flex-col justify-center items-center">
|
||||
<view v-if="filteredDate(item)" class="w-[74rpx] h-[92rpx] bg-[#F2F2F2] text-[#666] border-box py-[10rpx] rounded-[8rpx] flex flex-col items-center" :class="{'sigin-bg !text-[#fff]': isVerDate(item),'bg-[#FDFDFD] border-[1rpx] border-[#E0E0E0] border-solid !text-[#999]': !isVerDate(item) && item < state.curDate && (state.curMonth + 1) == (new Date().getMonth() + 1) ,'mb-[10rpx]':isCurrentDate(item),'mb-[20rpx]':!isCurrentDate(item) }" @click="getDayPackFn(item)">
|
||||
<text class="text-[24rpx] leading-[34rpx] mb-[6rpx]">{{ filteredDate(item) }}</text>
|
||||
<view v-if="filteredDate(item)">
|
||||
<view class="w-[14.28%] flex flex-col justify-center items-center">
|
||||
<view v-if="filteredDate(item)" class="w-[74rpx] h-[92rpx] bg-[#F1F2F5] text-[#626779] box-border py-[10rpx] rounded-[8rpx] flex flex-col items-center" :class="{'sigin-bg !text-[#fff]': isVerDate(item),'!bg-[#F6FAFF] border-[1rpx] border-[#F0F4FA] border-solid': !isVerDate(item) && item < state.curDate && (state.curMonth + 1) == (new Date().getMonth() + 1) ,'mb-[20rpx]':isCurrentDate(item),'mb-[30rpx]':!isCurrentDate(item)}" @click="getDayPackFn(item)">
|
||||
<text class="text-[24rpx] leading-[28rpx] mb-[6rpx]">{{ filteredDate(item) }}</text>
|
||||
<view v-if="filteredDate(item)" class="flex items-center justufy-center">
|
||||
<image v-if="isPackDate(item)" :src="img('static/resource/images/app/package.png')" class="w-[40rpx] h-[40rpx]"></image>
|
||||
<image v-else-if="isVerDate(item)" :src="img('static/resource/images/app/hassigin.png')" class="w-[34rpx] h-[34rpx]"></image>
|
||||
<image v-else :src="img('static/resource/images/app/nosigin.png')" class="w-[34rpx] h-[34rpx]"></image>
|
||||
<template v-else>
|
||||
<image v-if="!isVerDate(item) && item < state.curDate && (state.curMonth + 1) == (new Date().getMonth() + 1)" :src="img('static/resource/images/app/nosigin.png')" class="w-[34rpx] h-[34rpx]"></image>
|
||||
<image v-else :src="img('static/resource/images/app/nosigin1.png')" class="w-[34rpx] h-[34rpx]"></image>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
<view class="w-[10rpx] h-[10rpx] rounded-[50%] bg-[#FF5527]" v-if="isCurrentDate(item)"></view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="flex flex-wrap items-center justify-start" v-else>
|
||||
<block v-for="(item,index) in state.dataCount" >
|
||||
<view class="w-[14.2%] flex flex-col justify-center items-center mb-[10rpx]">
|
||||
<view v-if="filteredDate(item)" class="w-[74rpx] h-[92rpx] bg-[#F2F2F2] text-[#666] border-box py-[10rpx] rounded-[8rpx] flex flex-col items-center" :class="{'sigin-bg !text-[#fff]': isVerDate(item) && active ,'bg-[#FDFDFD] border-[1rpx] border-[#E0E0E0] border-solid !text-[#999]': !isVerDate(item) && item < state.curDate && (state.curMonth + 1) == (new Date().getMonth() + 1) && state.curYear == new Date().getFullYear() ,'mb-[10rpx]':isCurrentDate(item),'mb-[20rpx]':!isCurrentDate(item)}" @click="getDayPackFn(item)">
|
||||
<text class="text-[24rpx] leading-[34rpx] mb-[6rpx]">{{ filteredDate(item) }}</text>
|
||||
<view v-if="filteredDate(item)">
|
||||
<view class="w-[14.28%] flex flex-col justify-center items-center mb-[30rpx]">
|
||||
<view v-if="filteredDate(item)" class="w-[74rpx] h-[92rpx] bg-[#F6FAFF] text-[#626779] box-border py-[10rpx] rounded-[8rpx] flex flex-col items-center" :class="{'sigin-bg !text-[#fff]': isVerDate(item) && active ,'!bg-[#FDFDFD] border-[1rpx] border-[#F0F4FA] border-solid': !isVerDate(item) && item < state.curDate && (state.curMonth + 1) == (new Date().getMonth() + 1) && state.curYear == new Date().getFullYear() ,'mb-[20rpx]':isCurrentDate(item),'mb-[30rpx]':!isCurrentDate(item)}" @click="getDayPackFn(item)">
|
||||
<text class="text-[24rpx] leading-[28rpx] mb-[6rpx]">{{ filteredDate(item) }}</text>
|
||||
<view v-if="filteredDate(item)" class="flex items-center justufy-center">
|
||||
<image v-if="isPackDate(item)" :src="img('static/resource/images/app/package.png')" class="w-[40rpx] h-[40rpx]"></image>
|
||||
<image v-else-if="isVerDate(item) && active " :src="img('static/resource/images/app/hassigin.png')" class="w-[34rpx] h-[34rpx]"></image>
|
||||
<image v-else :src="img('static/resource/images/app/nosigin.png')" class="w-[34rpx] h-[34rpx]"></image>
|
||||
<template v-else>
|
||||
<image v-if="!isVerDate(item) && item < state.curDate && (state.curMonth + 1) == (new Date().getMonth() + 1)" :src="img('static/resource/images/app/nosigin.png')" class="w-[34rpx] h-[34rpx]"></image>
|
||||
<image v-else :src="img('static/resource/images/app/nosigin1.png')" class="w-[34rpx] h-[34rpx]"></image>
|
||||
</template>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="w-[10rpx] h-[10rpx] rounded-[50%] bg-[#FF5527]" v-if="isCurrentDate(item)"></view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="mt-[50rpx] mx-[20rpx] flex justify-center" v-if="state.curMonth + 1 == (new Date().getMonth() + 1) && state.curYear == new Date().getFullYear() ">
|
||||
<button v-if="!info.is_sign" class="rounded-[40rpx] !bg-transparent" :style="{width:'470rpx',height:'80rpx',border:'none', color:'#fff', fontSize:'28rpx',lineHeight:'76rpx',backgroundImage: `url(${img('static/resource/images/app/button_bg2.png')})`,backgroundSize: '100%', backgroundRepeat: 'no-repeat'}" shape="circle" @click="setSignFn">
|
||||
<text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[30rpx] text-[#fff] mr-[8rpx]"></text>
|
||||
<view class="mt-[40rpx] flex justify-center" v-if="state.curMonth + 1 == (new Date().getMonth() + 1) && state.curYear == new Date().getFullYear() ">
|
||||
<button v-if="!info.is_sign" class="rounded-[40rpx] !bg-transparent" :style="{width:'490rpx',height:'88rpx',border:'none', color:'#fff', fontSize:'32rpx',lineHeight:'84rpx',backgroundImage: `url(${img('static/resource/images/app/button_bg2.png')})`,backgroundSize: '100%', backgroundRepeat: 'no-repeat'}" shape="circle" @click="setSignFn">
|
||||
<text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[32rpx] text-[#fff] mr-[8rpx]"></text>
|
||||
<text>立即签到</text>
|
||||
</button>
|
||||
<button v-else class="rounded-[40rpx] !bg-transparent" :style="{width:'470rpx',height:'80rpx',border:'none',color:'#fff', fontSize:'28rpx',lineHeight:'76rpx',backgroundImage: `url(${img('static/resource/images/app/button_bg1.png')})`,backgroundSize: '100%', backgroundRepeat: 'no-repeat'}" shape="circle">
|
||||
<text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[30rpx] text-[#fff] mr-[8rpx]"></text>
|
||||
<button v-else class="rounded-[40rpx] !bg-transparent" :style="{width:'490rpx',height:'88rpx',border:'none',color:'#fff', fontSize:'32rpx',lineHeight:'84rpx',backgroundImage: `url(${img('static/resource/images/app/button_bg1.png')})`,backgroundSize: '100%', backgroundRepeat: 'no-repeat'}" shape="circle">
|
||||
<text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[32rpx] text-[#fff] mr-[8rpx]"></text>
|
||||
<text>已签到</text>
|
||||
</button>
|
||||
</view>
|
||||
<!-- <view class="mx-[20rpx] flex items-baseline justify-between mt-[16rpx]">
|
||||
<text class="text-[26rpx] text-[#FF9000] leading-[30rpx]">查看签到记录</text>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-[20rpx] mb-[30rpx] mx-[30rpx] p-[30rpx] bg-[#fff] rounded-[16rpx]">
|
||||
|
||||
<view class="mt-[20rpx] mb-[30rpx] sidebar-marign card-template" v-if="info && info.continue_award && Object.keys(info.continue_award).length">
|
||||
<view class="mb-[30rpx] flex items-center">
|
||||
<view class="font-bold text-[32rpx] text-[#333] leading-[38rpx]">签到奖励</view>
|
||||
<view class="font-500 text-[32rpx] text-[#333] leading-[44rpx]">签到奖励</view>
|
||||
<!-- <view class="text-[#666] text-[26rpx] leading-[30rpx]">
|
||||
<text>签到记录</text>
|
||||
<image :src="img('static/resource/images/app/more.png')" class="w-[12rpx] h-[18rpx] ml-[8rpx]"></image>
|
||||
</view> -->
|
||||
</view>
|
||||
<view>
|
||||
<view v-for="(item,index) in info.continue_award" :key="index" class="flex items-center mt-[40rpx] border-box">
|
||||
<view v-for="(item,index) in info.continue_award" :key="index" class="flex items-center border-box" :class="{'mt-[40rpx]':index}">
|
||||
<view class="w-[90rpx] h-[90rpx] rounded-[50%] bg-[#E7F6FF] flex items-center justify-center flex-shrink-0" v-if="(index + 1) % 4 == 1">
|
||||
<image :src="img('static/resource/images/app/icon_02.png')" class="w-[40rpx] h-[40rpx]"></image>
|
||||
</view>
|
||||
@ -122,26 +126,28 @@
|
||||
<image :src="img('static/resource/images/app/icon_05.png')" class="w-[40rpx] h-[40rpx]"></image>
|
||||
</view>
|
||||
<view class="flex-1 mx-[20rpx]">
|
||||
<view class="font-500 text-[28rpx] text-[#333] leading-[33rpx] mb-[10rpx]">连续签到{{item.continue_sign}}天</view>
|
||||
<view class="font-400 text-[28rpx] text-[#333] leading-[38rpx] mb-[8rpx]">连续签到{{item.continue_sign}}天</view>
|
||||
<view class="flex flex-wrap" v-if="item.gift">
|
||||
<view class="flex mb-[10rpx] ">
|
||||
<view class="flex">
|
||||
<image :src="img(item.gift.total.icon)" class="w-[30rpx] h-[30rpx] flex-shrink-0"></image>
|
||||
<view class="text-[24rpx] ml-[6rpx] text-[#FF9000] leading-[30rpx] max-w-[330rpx]">{{item.gift.total.text}}</view>
|
||||
<view class="text-[24rpx] ml-[8rpx] text-[#FF9000] leading-[34rpx] max-w-[330rpx]">{{item.gift.total.text}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-shrink-0">
|
||||
<view v-if="Number(info.days) < Number(item.continue_sign) " class="px-[28rpx] py-[8rpx] bg-[#FFECE9] rounded-[40rpx] font-500 text-[24rpx] text-[rgba(239,0,12,.8)] leading-[34rpx]">待完成</view>
|
||||
<view v-else class="px-[28rpx] py-[8rpx] rounded-[40rpx] font-500 text-[24rpx] text-[#fff] leading-[34rpx]" style="background:linear-gradient( 90deg, #FB7939 0%, #FE120E 100%) ;">已完成</view>
|
||||
<view v-if="Number(info.days) < Number(item.continue_sign) " class="w-[130rpx] h-[56rpx] text-center bg-[#FFECE9] rounded-[28rpx] font-400 text-[26rpx] text-[#FF343E] leading-[56rpx]">待完成</view>
|
||||
<view v-else class="w-[130rpx] h-[56rpx] text-center rounded-[28rpx] font-400 text-[26rpx] text-[#fff] leading-[56rpx]" style="background:linear-gradient( 90deg, #FB7939 0%, #FE120E 100%) ;">已完成</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="min-h-screen flex flex-col justify-center bg-[#fff]" v-else>
|
||||
<image class="rounded-[8rpx] overflow-hidden mx-auto w-[320rpx] h-[184rpx]" :src="img('static/resource/images/system/empty.png')" model="aspectFill" />
|
||||
<view class="text-[#999] text-[26rpx] font-400 mt-[26rpx] text-center leading-[30rpx]">签到未开启</view>
|
||||
<view class="h-[100vh] w-[100vw] flex justify-center items-center" v-else>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()" class="top-header"/>
|
||||
<!-- #endif -->
|
||||
<u-empty text="签到未开启" width="347rpx" height="265rpx" :icon="img('static/resource/images/system/empty.png')"/>
|
||||
</view>
|
||||
<!-- 签到规则-->
|
||||
<u-popup :show="signPopup" :round="16" mode="bottom" :closeable="true" @close="signPopup = false">
|
||||
@ -153,35 +159,35 @@
|
||||
</block>
|
||||
</scroll-view>
|
||||
<view>
|
||||
<u-button text="知道了" :customStyle="{height:'66rpx',color:'#fff', fontSize:'28rpx',lineHeight:'66rpx',background: 'linear-gradient( 90deg, #fc7035 0%, #EF000C 100%)',border:'none'}" shape="circle" @click="signPopup = false"></u-button>
|
||||
<button class="primary-btn-bg h-[66rpx] text-[#fff] text-[28rpx] border-[0] leading-[66rpx] rounded-[50rpx]" shape="circle" @click="signPopup = false">知道了</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<!-- 签到奖励 -->
|
||||
<u-popup :show="awardShow" class="award-popup" :customStyle="{backgroundColor:'transparent'}" @close="awardShow = false" mode="center" :round="5" :safeAreaInsetBottom="false" >
|
||||
<view class="w-[550rpx]" v-if="Object.values(signAward).length">
|
||||
<view class="w-[550rpx] -mt-[124rpx]" v-if="Object.values(signAward).length">
|
||||
<view class="flex justify-center">
|
||||
<image :src="img('static/resource/images/app/award.png')" class="w-[484rpx] h-[480rpx]"></image>
|
||||
<image :src="img('static/resource/images/app/award.png')" class="w-[484rpx] h-[480rpx] z-10" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="-mt-[265rpx] bg-award rounded-[30rpx] pt-[100rpx] pb-[48rpx] mb-[50rpx] raleative z-10">
|
||||
<view class="-mt-[265rpx] bg-award rounded-[30rpx] pt-[100rpx] pb-[40rpx] mb-[50rpx] relative">
|
||||
<view class="px-[32rpx]">
|
||||
<view class="text-[48rpx] text-[#EF000C] font-bold leading-[56rpx] mb-[4rpx] text-center">{{ signAward.title }}</view>
|
||||
<view class="text-[24rpx] text-[#F05F66] leading-[28rpx] text-center mb-[60rpx]">{{ signAward.info }}</view>
|
||||
<view class="px-[68rpx] mb-[54rpx]">
|
||||
<view class="text-[48rpx] text-[#EF000C] font-bold leading-[68rpx] mb-[6rpx] text-center">{{ signAward.title }}</view>
|
||||
<view class="text-[24rpx] text-[#F05F66] leading-[34rpx] text-center mb-[60rpx]" v-if="signAward.info">{{ signAward.info }}</view>
|
||||
<view class="px-[68rpx] mb-[80rpx]">
|
||||
<block v-for="(item,index) in signAward.awards">
|
||||
<template v-if="item.content" v-for="(subItem,subIndex) in item.content">
|
||||
<view class="flex items-center mb-[30rpx]" >
|
||||
<view class="flex items-center mb-[30rpx]" >
|
||||
<image :src="img(subItem.icon)" class="w-[42rpx] h-[42rpx]"></image>
|
||||
<view class="ml-[20rpx] text-[28rpx] text-[#333] leading-[32rpx]">{{subItem.text }}</view>
|
||||
<view class="ml-[20rpx] text-[28rpx] text-[#333] leading-[38rpx]">{{subItem.text }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</block>
|
||||
</view>
|
||||
<view class="flex justify-center">
|
||||
<view class="w-[380rpx] h-[80rpx] bg-gradient-to-r from-[#FB7939] to-[#FE120E] rounded-[50rpx] text-[#ffffff] text-center leading-[80rpx] text-[30rpx]" @click="awardShow = false">我知道了</view>
|
||||
<view class="flex justify-center relative z-30">
|
||||
<view class="w-[370rpx] h-[88rpx] primary-btn-bg rounded-[50rpx] text-[#ffffff] text-center leading-[88rpx] text-[32rpx]" @click="awardShow = false">我知道了</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex justify-center">
|
||||
<text class="nc-iconfont nc-icon-cuohaoV6xx text-[#fff] text-[60rpx]" @click="awardShow = false"></text>
|
||||
</view>
|
||||
@ -189,26 +195,28 @@
|
||||
</u-popup>
|
||||
<!-- 查看当日或连续签到奖励 -->
|
||||
<u-popup :show="packShow" class="award-popup" :customStyle="{backgroundColor:'transparent'}" @close="packShow = false" mode="center" :round="5" :safeAreaInsetBottom="false">
|
||||
<view class="w-[550rpx]" v-if="Object.values(packInfo).length">
|
||||
<view class="w-[550rpx] -mt-[124rpx]" v-if="Object.values(packInfo).length">
|
||||
<view class="flex justify-center">
|
||||
<image :src="img('static/resource/images/app/award.png')" class="w-[484rpx] h-[480rpx]"></image>
|
||||
<image :src="img('static/resource/images/app/award.png')" class="w-[484rpx] h-[480rpx] z-10" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="-mt-[265rpx] bg-award rounded-[30rpx] pt-[100rpx] pb-[48rpx] mb-[50rpx] raleative z-10">
|
||||
<view class="-mt-[265rpx] bg-award rounded-[30rpx] pt-[100rpx] pb-[40rpx] mb-[50rpx] relative">
|
||||
<view class="px-[32rpx]">
|
||||
<view class="text-[48rpx] text-[#EF000C] font-bold leading-[56rpx] mb-[4rpx] text-center opacity-60">签到奖励</view>
|
||||
<view class="text-[24rpx] text-[#F05F66] opacity-60 leading-[28rpx] text-center mb-[60rpx]">您将获得以下奖励</view>
|
||||
<view class="px-[68rpx] mb-[54rpx]">
|
||||
<block v-for="(item,index) in packInfo">
|
||||
<view class="text-[48rpx] text-[#333] font-bold leading-[68rpx] mb-[6rpx] text-center relative z-20">
|
||||
{{ packInfo.title }}
|
||||
</view>
|
||||
<view class="text-[24rpx] text-[#F05F66] leading-[34rpx] text-center mb-[60rpx]">{{ packInfo.info }}</view>
|
||||
<view class="px-[68rpx] mb-[80rpx]">
|
||||
<block v-for="(item,index) in packInfo.awards">
|
||||
<template v-if="item.content">
|
||||
<view class="flex items-center mb-[32rpx]" v-for="(subItem,subIndex) in item.content" :key="subIndex">
|
||||
<view class="flex items-center mb-[32rpx]" v-for="(subItem,subIndex) in item.content" :key="subIndex">
|
||||
<image :src="img(subItem.icon)" class="w-[42rpx] h-[42rpx]"></image>
|
||||
<view class="ml-[20rpx] text-[28rpx] text-[#333] leading-[32rpx]">{{ subItem.text }}</view>
|
||||
<view class="ml-[20rpx] text-[28rpx] text-[#333] leading-[38rpx]">{{ subItem.text }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</block>
|
||||
</view>
|
||||
<view class="flex justify-center">
|
||||
<view class="w-[380rpx] h-[80rpx] bg-gradient-to-r from-[#FB7939] to-[#FE120E] rounded-[50rpx] text-[#ffffff] text-center leading-[80rpx] text-[30rpx]" @click="packShow = false">我知道了</view>
|
||||
<view class="flex justify-center relative z-30">
|
||||
<view class="w-[370rpx] h-[88rpx] border-[4rpx] border-[#EF000C] border-solid rounded-[50rpx] text-[#EF000C] text-center leading-[88rpx] text-[32rpx] font-500 box-border" @click="packShow = false">我知道了</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -224,12 +232,13 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, toRefs, toRaw, computed } from 'vue'
|
||||
import { redirect, img } from '@/utils/common'
|
||||
import { redirect, img,pxToRpx } from '@/utils/common'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { getSignInfo,getSignConfig, setSign,getDayPack } from '@/app/api/member'
|
||||
import useMemberStore from '@/stores/member'
|
||||
import { topTabar } from '@/utils/topTabbar'
|
||||
|
||||
let state = reactive({
|
||||
const state = reactive({
|
||||
dataCount:[], //当月所有天数
|
||||
weekCount:[], //如果签到周期是7天
|
||||
curYear:0, // 当前年
|
||||
@ -239,21 +248,21 @@ let state = reactive({
|
||||
signInList:[], // 签到列表
|
||||
packList:[] //每个小周期内的礼包
|
||||
})
|
||||
let week = reactive({
|
||||
const week = reactive({
|
||||
weekDay:0, //当前天
|
||||
week:0 //当前星期
|
||||
})
|
||||
const loading = ref(false)
|
||||
let flag = ref(false)
|
||||
let info = ref({}) //签到配置
|
||||
let signPopup = ref(false)//签到规则弹框
|
||||
let signAward = ref({}) //当日签到奖励
|
||||
let awardShow = ref(false) // 每日签到弹框
|
||||
let packShow = ref(false) //查看每天礼包
|
||||
let packInfo = ref({}) //礼包奖励
|
||||
let active = ref(false)
|
||||
let currentYear=null
|
||||
let currentMonth=null
|
||||
const flag = ref(false)
|
||||
const info = ref({}) //签到配置
|
||||
const signPopup = ref(false)//签到规则弹框
|
||||
const signAward = ref({}) //当日签到奖励
|
||||
const awardShow = ref(false) // 每日签到弹框
|
||||
const packShow = ref(false) //查看每天礼包
|
||||
const packInfo = ref({}) //礼包奖励
|
||||
const active = ref(false)
|
||||
let currentYear: any = null
|
||||
let currentMonth: any = null
|
||||
onLoad(() =>{
|
||||
let date=new Date()
|
||||
state.curYear=date.getFullYear()
|
||||
@ -277,6 +286,9 @@ const getSignConfigFn = () =>{
|
||||
loading.value = true
|
||||
getSignConfig().then((res:any) =>{
|
||||
info.value = res.data
|
||||
if(!info.value.is_use){
|
||||
topTabbarData = topTabarObj.setTopTabbarParam({title:'我的签到',topStatusBar:{textColor:'#333',bgColor:'#fff'}})
|
||||
}
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
@ -287,9 +299,12 @@ const getSignInfoFn = (data:any) =>{
|
||||
state.signInList = []
|
||||
state.packList = []
|
||||
state.packList = res.data.period
|
||||
state.signInList = res.data.days.map((el:any) =>{
|
||||
return Number(el)
|
||||
})
|
||||
if(res.data.length){
|
||||
state.signInList = res.data.days.map((el:any) =>{
|
||||
return Number(el)
|
||||
})
|
||||
}
|
||||
|
||||
active.value = true
|
||||
})
|
||||
}
|
||||
@ -364,6 +379,16 @@ const setSignFn = () =>{
|
||||
setSign().then(res =>{
|
||||
if(Object.values(res.data).length){
|
||||
signAward.value = res.data
|
||||
// 如果没有奖励内容则不展示描述信息
|
||||
let isShowInfo = 0
|
||||
Object.values(signAward.value.awards).forEach((item,index)=>{
|
||||
if(!item.content){
|
||||
isShowInfo++;
|
||||
}
|
||||
})
|
||||
if(isShowInfo == Object.values(signAward.value.awards).length){
|
||||
signAward.value.info = "";
|
||||
}
|
||||
getSignInfoFn({year:state.curYear,month:state.curMonth+1})
|
||||
getSignConfigFn()
|
||||
memberStore.getMemberInfo()
|
||||
@ -373,7 +398,7 @@ const setSignFn = () =>{
|
||||
}
|
||||
|
||||
// 查看每日礼包
|
||||
let curPickDay = ref(null)
|
||||
const curPickDay = ref(null)
|
||||
const getDayPackFn = (date:number) =>{
|
||||
let {curYear,curMonth}=toRefs(state)
|
||||
let itemDate=`${curYear.value}-${(curMonth.value+1) < 10 ? '0' + (curMonth.value+1) : (curMonth.value+1)}-${date < 10 ? '0'+date : date}`
|
||||
@ -431,36 +456,19 @@ let menuButtonInfo = {};
|
||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
||||
// #endif
|
||||
let topTabbarData = ref({
|
||||
title:'我的签到',
|
||||
topStatusBar: {
|
||||
style: 'style-1',
|
||||
isTransparent: true,
|
||||
bgColor: 'transparent',
|
||||
textColor: '#fff'
|
||||
}
|
||||
})
|
||||
/********* 自定义头部 - start ***********/
|
||||
const topTabarObj = topTabar()
|
||||
let topTabbarData = topTabarObj.setTopTabbarParam({title:'我的签到'})
|
||||
/********* 自定义头部 - end ***********/
|
||||
|
||||
const headStyle = computed(() => {
|
||||
let style = ''
|
||||
style = pxToRpx(Number(menuButtonInfo.height) + menuButtonInfo.top + 8)+ 382 + 'rpx;'
|
||||
let style = pxToRpx(Number(menuButtonInfo.height) + menuButtonInfo.top + 8)+ 382 + 'rpx;'
|
||||
return style
|
||||
})
|
||||
const topStyle = computed(() => {
|
||||
let style = ''
|
||||
style = pxToRpx(Number(menuButtonInfo.height) + menuButtonInfo.top + 8)+38 + 'rpx;'
|
||||
let style = pxToRpx(Number(menuButtonInfo.height) + menuButtonInfo.top + 8)+38 + 'rpx;'
|
||||
return style
|
||||
})
|
||||
// rpx转px
|
||||
const rpxToPx=(rpx:any)=>{
|
||||
const screenWidth = uni.getSystemInfoSync().screenwidth
|
||||
return(screenWidth*Number.parseInt(rpx))/750
|
||||
}
|
||||
// px转rpx
|
||||
const pxToRpx=(px:any)=>{
|
||||
const screenWidth =uni.getSystemInfoSync().screenWidth
|
||||
return(750*Number.parseInt(px))/screenWidth
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import { img, isWeixinBrowser } from '@/utils/common'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
|
||||
onLoad((data : AnyObject) => {
|
||||
onLoad((data : any) => {
|
||||
if (!isWeixinBrowser() && data.alipay) {
|
||||
uni.setStorageSync('paymenting', { trade_type: data.trade_type, trade_id: data.trade_id })
|
||||
location.href = data.alipay
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<u-button type="primary" :text="payInfo.status == 2 ? t('complete') : t('close')" :plain="true" @click="complete"></u-button>
|
||||
</view>
|
||||
</view>
|
||||
<u-modal :show="loading" :showCancelButton="true" :confirmText="t('pay.completePay')" :cancelText="t('pay.incompletePay')" @cancel="complete">
|
||||
<u-modal :show="loading" :showCancelButton="true" :confirmText="t('pay.completePay')" :cancelText="t('pay.incompletePay')" @cancel="complete" confirmColor="var(--primary-color)">
|
||||
<view class="py-[20rpx]">
|
||||
<u-loading-icon :text="t('pay.getting')" textSize="16" mode="circle" :vertical="true"></u-loading-icon>
|
||||
</view>
|
||||
@ -61,8 +61,6 @@
|
||||
title: payInfo.value.status == 2 ? t('pay.paySuccess') : t('pay.payFail')
|
||||
})
|
||||
}
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -69,7 +69,9 @@
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.u-cell__value{
|
||||
line-height: 1;
|
||||
}
|
||||
.u-cell {
|
||||
&:last-child .u-line {
|
||||
display: none;
|
||||
|
||||
@ -1,47 +1,47 @@
|
||||
<template>
|
||||
<view :style="themeColor()" class="bg-[#f8f8f8] min-h-[100vh] overflow-hidden">
|
||||
<block v-if="!loading">
|
||||
<view class="mt-[30rpx] mx-[30rpx]">
|
||||
<view class="py-[10rpx] px-[20rpx] flex flex-col rounded-[16rpx] bg-white">
|
||||
<view class="flex h-[180rpx]" :class="{'mb-[20rpx]': verifyInfo.value.list.length-1 != index}" v-for="(item,index) in verifyInfo.value.list" :key="index">
|
||||
<image class="w-[120rpx] h-[120rpx] mt-[30rpx] rounded-[8rpx]" mode="aspectFit" v-if="item.cover" :src="img(item.cover)"></image>
|
||||
<image class="w-[120rpx] h-[120rpx] mt-[30rpx] rounded-[8rpx]" mode="aspectFit" v-else :src="img('addon/tourism/tourism/member/hotel.png')"></image>
|
||||
<view class="flex flex-col flex-1 ml-[20rpx] mt-36rpx">
|
||||
<view class="leading-[39rpx] text-[28rpx] max-w-[432rpx] multi-hidden">{{item.name}}</view>
|
||||
<view class="self-end text-[28rpx]">x1</view>
|
||||
<view class="pt-[20rpx] sidebar-marign">
|
||||
<view class="flex flex-col card-template">
|
||||
<view class="flex" :class="{'mb-[20rpx]': verifyInfo.value.list.length-1 != index}" v-for="(item,index) in verifyInfo.value.list" :key="index">
|
||||
<image class="w-[150rpx] h-[150rpx] rounded-[8rpx]" mode="aspectFill" v-if="item.cover" :src="img(item.cover)"></image>
|
||||
<image class="w-[150rpx] h-[150rpx] rounded-[8rpx]" mode="aspectFill" v-else :src="img('addon/tourism/tourism/member/hotel.png')"></image>
|
||||
<view class="flex flex-col flex-1 ml-[20rpx] py-[4rpx]">
|
||||
<view class="leading-[1.3] text-[28rpx] multi-hidden">{{item.name}}</view>
|
||||
<view class="self-end text-[#626779] text-[26rpx] mt-[20rpx]">x1</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="flex flex-col bg-[#fff] p-[20rpx] rounded-[16rpx] mt-[20rpx]">
|
||||
<view class="text-[28rpx] text-[#333333] font-bold leading-[39rpx] h-[39rpx]">核销信息</view>
|
||||
<view class="flex justify-between items-center mt-[30rpx] h-[39rpx]">
|
||||
<text class="text-[28rpx] text-[#333]">核销类型</text>
|
||||
<view class="text-[28rpx] text-[#333]">{{verifyInfo.type_name}}</view>
|
||||
<view class="flex flex-col card-template mt-[20rpx]">
|
||||
<view class="text-[32rpx] text-[#333333] font-500 leading-[1.2] mb-[30rpx]">核销信息</view>
|
||||
<view class="flex justify-between h-[36rpx] items-center">
|
||||
<text class="text-[26rpx] text-[#626779]">核销类型</text>
|
||||
<view class="text-[26rpx] text-[#333]">{{verifyInfo.type_name}}</view>
|
||||
</view>
|
||||
<view class="flex justify-between items-center mt-[20rpx] h-[39rpx]">
|
||||
<text class="text-[28rpx] text-[#333]">核销状态</text>
|
||||
<view class="text-[28rpx] text-[#333]">已核销</view>
|
||||
<view class="flex justify-between h-[36rpx] items-center mt-[20rpx]">
|
||||
<text class="text-[26rpx] text-[#626779]">核销状态</text>
|
||||
<view class="text-[26rpx] text-[#333]">已核销</view>
|
||||
</view>
|
||||
<view class="flex justify-between items-center mt-[20rpx] h-[39rpx]">
|
||||
<text class="text-[28rpx]">核销时间</text>
|
||||
<view class="text-[#333333] text-[28rpx]">{{verifyInfo.create_time}}</view>
|
||||
<view class="flex justify-between h-[36rpx] items-center mt-[20rpx]">
|
||||
<text class="text-[26rpx] text-[#626779]">核销时间</text>
|
||||
<view class="text-[#333333] text-[26rpx]">{{verifyInfo.create_time}}</view>
|
||||
</view>
|
||||
<view class="flex justify-between items-center mt-[20rpx] h-[39rpx]">
|
||||
<text class="text-[28rpx]">核销人员</text>
|
||||
<view class="text-[#333333] text-[28rpx]">{{verifyInfo.member ? verifyInfo.member.nickname : '--'}}</view>
|
||||
<view class="flex justify-between h-[36rpx] items-center mt-[20rpx]">
|
||||
<text class="text-[26rpx] text-[#626779]">核销人员</text>
|
||||
<view class="text-[#333333] text-[26rpx]">{{verifyInfo.member ? verifyInfo.member.nickname : '--'}}</view>
|
||||
</view>
|
||||
<view class="flex items-center justify-between mt-[20rpx]" v-for="(item,index) in verifyInfo.value.content.fixed">
|
||||
<text class="text-[28rpx] text-[#333]">{{item.title}}</text>
|
||||
<view class="text-[28rpx] text-[#333]">{{item.value}}</view>
|
||||
<view class="flex items-center h-[36rpx] justify-between mt-[20rpx]" v-for="(item,index) in verifyInfo.value.content.fixed">
|
||||
<text class="text-[26rpx] text-[#626779]">{{item.title}}</text>
|
||||
<view class="text-[26rpx] text-[#333]">{{item.value}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-for="(item,index) in verifyInfo.value.content.diy" :key="index" class="text-[#838383] bg-white p-[20rpx] rounded-[16rpx] mt-[20rpx]">
|
||||
<view class="text-[28rpx] text-[#333333] font-bold leading-[39rpx] h-[39rpx]">{{item.title}}</view>
|
||||
<view class="flex items-center justify-between h-[39rpx] mt-[20rpx]" v-for="(subItem,subIndex) in item.list" :key="subIndex" :class="{'mt-30rpx' : subIndex == '0'}">
|
||||
<text class="text-[28rpx] text-[#333]">{{subItem.title}}</text>
|
||||
<view class="text-[28rpx] text-[#333]">{{subItem.value}}</view>
|
||||
<view v-for="(item,index) in verifyInfo.value.content.diy" :key="index" class="card-template mt-[20rpx]">
|
||||
<view class="text-[32rpx] text-[#333333] font-500 leading-[1.2] mb-[30rpx]">{{item.title}}</view>
|
||||
<view class="flex items-center h-[36rpx] justify-between mt-[20rpx]" v-for="(subItem,subIndex) in item.list" :key="subIndex" :class="{'mt-30rpx' : subIndex == '0'}">
|
||||
<text class="text-[26rpx] text-[#626779]">{{subItem.title}}</text>
|
||||
<view class="text-[26rpx] text-[#333]">{{subItem.value}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -59,9 +59,9 @@
|
||||
import { t } from '@/locale'
|
||||
|
||||
const loading = ref(true)
|
||||
let code = ref('');
|
||||
onLoad((option)=> {
|
||||
if (option.code) code.value = option.code;
|
||||
const code = ref('');
|
||||
onLoad((option:any)=> {
|
||||
if (option.code) code.value = option.code;
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
@ -70,12 +70,11 @@
|
||||
}
|
||||
})
|
||||
|
||||
let verifyInfo = ref({})
|
||||
const verifyInfo = ref({})
|
||||
const getVerifyDetailFn = ()=>{
|
||||
loading.value = true;
|
||||
getVerifyDetail(code.value).then((res:any) =>{
|
||||
verifyInfo.value = res.data;
|
||||
console.log("verifyInfo.value",verifyInfo.value);
|
||||
loading.value = false;
|
||||
})
|
||||
}
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
<view :style="themeColor()">
|
||||
<view class="w-[100vw] min-h-[100vh] bg-[#f8f8f8]" v-if="!loading">
|
||||
<view class="w-full bg-[#fff] verify-box h-[760rpx]">
|
||||
<view class="text-[var(--primary-color)] fixed top-[30rpx] right-[30rpx] flex items-center" @click="redirect({url:'/app/pages/verify/record'})">
|
||||
<image class="w-[24rpx] h-[28rpx]" :src="img('static/resource/images/verify/history.png')"/>
|
||||
<view class="text-[var(--primary-color)] fixed top-[40rpx] right-[30rpx] flex items-center" @click="redirect({url:'/app/pages/verify/record'})">
|
||||
<image class="w-[26rpx] h-[28rpx]" :src="img('static/resource/images/verify/history.png')"/>
|
||||
<text class="text-[26rpx] ml-[10rpx]">核销记录</text>
|
||||
</view>
|
||||
<view v-show="operationType == 'sweepCode'" class="flex flex-col items-center justify-center">
|
||||
@ -11,43 +11,43 @@
|
||||
<image class="w-[354rpx] h-[354rpx]" :src="img('static/resource/images/verify/saoma.png')"/>
|
||||
</view>
|
||||
<view class="mt-[40rpx] text-[32rpx]">点击扫描二维码</view>
|
||||
<view class="mt-[20rpx] text-[#999] text-[26rpx] font-400 pb-[142rpx]">扫描二维码进行核销</view>
|
||||
<view class="mt-[20rpx] text-[#8288A2] text-[26rpx] font-400 pb-[142rpx]">扫描二维码进行核销</view>
|
||||
</view>
|
||||
|
||||
<view v-show="operationType == 'manualInput'">
|
||||
<view class="flex pt-[126rpx] pb-[30rpx] items-center justify-center">
|
||||
<view class="flex justify-center items-center flex-col pr-[30rpx]">
|
||||
<view class="flex pt-[126rpx] items-center justify-center">
|
||||
<view class="flex justify-center items-center flex-col pr-[30rpx] w-[130rpx]">
|
||||
<image class="w-[100rpx] h-[100rpx]" :src="img('static/resource/images/verify/shuruhexiaoma.png')"/>
|
||||
<view class="text-[26rpx] h-[36rpx] leading-[36rpx] mt-[12rpx]">验证核销码</view>
|
||||
</view>
|
||||
<image class="w-[74rpx] h-[12rpx] mb-[50rpx]" :src="img('static/resource/images/verify/youjiantou.png')"/>
|
||||
<view class="flex justify-center items-center flex-col pl-[30rpx]">
|
||||
<view class="flex justify-center items-center flex-col pl-[30rpx] w-[130rpx]">
|
||||
<image class="w-[100rpx] h-[100rpx]" :src="img('static/resource/images/verify/hexiao1.png')"/>
|
||||
<view class="text-[26rpx] h-[36rpx] leading-[36rpx] mt-[12rpx]">核销</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-[50rpx]">
|
||||
<view class="h-[90rpx] border-[2rpx] border-solid border-[#eee] rounded-[12rpx] box-border p-[20rpx] mx-[60rpx] flex items-center" >
|
||||
<view class="h-[90rpx] border-[2rpx] border-solid border-[#DCE0EF] rounded-[16rpx] box-border p-[20rpx] mx-[60rpx] flex items-center" >
|
||||
<text class="nc-iconfont nc-icon-saotiaoxingmaV6xx text-[44rpx] text-[#EF000C]"></text>
|
||||
<input type="text" placeholder="请输入核销码" class="h-[90rpx] border-none text-start ml-[30rpx] text-[28rpx] flex-1" placeholder-class="_placeholder" v-model="verify_code" :focus="isFocus" ref="input"/>
|
||||
</view>
|
||||
<view class="h-[88rpx] min-w-[630rpx] bg-[var(--primary-color)] text-[#fff] flex items-center justify-center !text-[32rpx] rounded-[50rpx] h-[88rpx] mx-[60rpx] mt-[146rpx] relative z-1" @click="confirm">确认</view>
|
||||
<view class="h-[88rpx] min-w-[630rpx] text-[#fff] flex items-center justify-center !text-[32rpx] save-btn rounded-[50rpx] h-[88rpx] mx-[60rpx] mt-[146rpx] relative z-1" @click="confirm">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="w-[630rpx] h-[100rpx] bg-[#fff] mx-[auto] mt-[220rpx] rounded-[90rpx] flex relative action-type-wrap">
|
||||
<view class="relative w-[51%] rounded-[50rpx] z-0 flex flex-col items-center justify-center" @click="changeOperationType('sweepCode')" :class="{'xuanZhong1': operationType == 'sweepCode'}">
|
||||
<view class="mt-[10rpx]"><text class="nc-iconfont nc-icon-saoyisaoV6xx !text-[42rpx]"></text></view>
|
||||
<view class="text-[24rpx] leading-[34rpx] h-[34rpx] mt-[-6rpx]">扫码核销</view>
|
||||
<view class="relative w-[51%] pr-[50rpx] box-border rounded-[50rpx] z-0 flex flex-col items-center justify-center" @click="changeOperationType('sweepCode')" :class="{'xuanZhong1': operationType == 'sweepCode'}">
|
||||
<text class="nc-iconfont nc-icon-saoyisaoV6xx !text-[40rpx]"></text>
|
||||
<view class="text-[24rpx] leading-[1] mt-[10rpx]">扫码核销</view>
|
||||
</view>
|
||||
<view class="flex flex-col items-center flex-col w-[120rpx] h-[120rpx] bg-[#FF7354] rounded-[50%] absolute top-[-10rpx] left-[255rpx] heXiao text-white z-10 shrink-0">
|
||||
<view class="nc-iconfont nc-icon-saotiaoxingmaV6xx ns-gradient-otherpages-member-balance-balance-rechange !text-[44rpx] mt-[19rpx]"></view>
|
||||
<view class="text-[24rpx] mt-[8rpx] leading-[34rpx] h-[34rpx]">核销台</view>
|
||||
</view>
|
||||
<view class="relative w-[51%] rounded-[50rpx] z-0 flex flex-col items-center justify-center" :class="{'xuanZhong': operationType == 'manualInput'}" @click="changeOperationType('manualInput')">
|
||||
<view class="ml-[20rpx] mt-[10rpx]"><text class="iconfont iconVector-77 !text-[42rpx]"></text></view>
|
||||
<view class="ml-[20rpx] text-[24rpx] leading-[34rpx] h-[34rpx] mt-[-6rpx]" @click="focus">手动输入</view>
|
||||
<view class="relative w-[51%] pl-[50rpx] box-border rounded-[50rpx] z-0 flex flex-col items-center justify-center" :class="{'xuanZhong': operationType == 'manualInput'}" @click="changeOperationType('manualInput')">
|
||||
<text class="iconfont iconVector-77 !text-[40rpx]"></text>
|
||||
<view class="ml-[20rpx] text-[24rpx] leading-[1] mt-[10rpx]" @click="focus">手动输入</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
import { t } from '@/locale'
|
||||
import wechat from '@/utils/wechat'
|
||||
|
||||
let operationType = ref('manualInput'); //类型
|
||||
const operationType = ref('manualInput'); //类型
|
||||
// #ifdef H5
|
||||
operationType.value = 'manualInput';
|
||||
// #endif
|
||||
@ -76,12 +76,11 @@
|
||||
operationType.value = 'sweepCode';
|
||||
// #endif
|
||||
|
||||
let isFocus = ref(false)
|
||||
let verify_code = ref('');
|
||||
let loading = ref(true)
|
||||
const isFocus = ref(false)
|
||||
const verify_code = ref('');
|
||||
const loading = ref(true)
|
||||
onShow(() => {
|
||||
if(getToken())
|
||||
checkIsVerifier();
|
||||
if(getToken()) checkIsVerifier();
|
||||
})
|
||||
|
||||
// 检测是否是核销员
|
||||
@ -93,7 +92,16 @@
|
||||
icon: 'none'
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
if(getCurrentPages().length > 1){
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
}else{
|
||||
redirect({
|
||||
url: '/app/pages/member/index',
|
||||
mode: 'reLaunch'
|
||||
});
|
||||
}
|
||||
}, 1000);
|
||||
}else{
|
||||
loading.value = false;
|
||||
@ -135,8 +143,6 @@
|
||||
|
||||
let isLoading = false;
|
||||
const confirm = () => {
|
||||
if(isLoading) return false;
|
||||
isLoading = true;
|
||||
var reg = /[\S]+/;
|
||||
if (!reg.test(verify_code.value)) {
|
||||
uni.showToast({
|
||||
@ -146,6 +152,9 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isLoading) return false;
|
||||
isLoading = true;
|
||||
|
||||
getVerifierInfo(verify_code.value).then((res:any) =>{
|
||||
isLoading = false;
|
||||
redirect({ url: '/app/pages/verify/verify', param: { code: verify_code.value} })
|
||||
@ -173,7 +182,7 @@
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.action-type-wrap {
|
||||
box-shadow: 0 6px 6px 0 rgba(0, 0, 0, 0.03), 0 4px 2px 0 rgba(0, 0, 0, 0.04);;
|
||||
box-shadow: 0 6px 6px 0 rgba(0, 0, 0, 0.03), 0 4px 2px 0 rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.heXiao{
|
||||
background: linear-gradient( 180deg, #FF7354 0%, #FF020F 100%), #EF000C;
|
||||
@ -191,10 +200,17 @@
|
||||
height: 354rpx;
|
||||
box-shadow: 0 8px 8px 0 rgba(0, 0, 0, 0.03), 0 6px 3px 0 rgba(0, 0, 0, 0.02);
|
||||
border-radius: 50%;
|
||||
margin: 146rpx auto 0rpx;
|
||||
margin-top: 146rpx;
|
||||
}
|
||||
.verify-box {
|
||||
border-bottom-left-radius: 400rpx 60rpx;
|
||||
border-bottom-right-radius: 400rpx 60rpx;
|
||||
}
|
||||
.save-btn{
|
||||
background: linear-gradient( 94deg, #FB7939 0%, #FE120E 99%), #EF000C;
|
||||
}
|
||||
._placeholder{
|
||||
color: #8288A2;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,46 +1,69 @@
|
||||
<template>
|
||||
<view class="bg-[#f8f8f8] min-h-screen overflow-hidden" :style="themeColor()">
|
||||
<mescroll-body ref="mescrollRef" top="30rpx" @init="mescrollInit" @down="downCallback" @up="geVerifyRecordFn">
|
||||
<view class="ml-[30rpx] mr-[30rpx]">
|
||||
<view class="fixed left-0 right-0 top-0 z-99 bg-[#fff] px-[var(--sidebar-m)]">
|
||||
<view class="py-[14rpx] flex items-center justify-between">
|
||||
<view class="flex-1 flex items-center h-[60rpx] bg-[#F8F9FD] rounded-[30rpx] px-[20rpx] mr-[30rpx]">
|
||||
<u-input class="flex-1" maxlength="50" v-model="keyword" @confirm="searchTypeFn()" placeholder="请输入搜索关键词" placeholderClass="text-[#8288A2] text-[24rpx]" fontSize="26rpx" clearable border="none"></u-input>
|
||||
<text class="nc-iconfont nc-icon-sousuo-duanV6xx1 text-[32rpx] ml-[18rpx] !text-[#999]" @click="searchTypeFn()"></text>
|
||||
</view>
|
||||
<view class="nc-iconfont nc-icon-riliV6xx !text-[30rpx] leading-[36rpx]" @click="handleSelect"></view>
|
||||
</view>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" top="108rpx" @init="mescrollInit" :down="{ use: false }" @up="geVerifyRecordFn">
|
||||
<view class="sidebar-marign">
|
||||
<block v-for="(item,index) in list" :key="item.id">
|
||||
<view class="w-full flex flex-col mb-3 bg-[#fff] px-[20rpx] box-border rounded-[18rpx] " @click="toLink(item)">
|
||||
<view class="flex items-center pb-[30rpx] pt-[20rpx] leading-[1]">
|
||||
<view class="nc-iconfont nc-icon-hexiaotaiV6xx pr-[10rpx]"></view>
|
||||
<text class="truncate max-w-[590rpx] text-[#333333] text-[26rpx]">核销码:{{ item.code }}</text>
|
||||
<view class="w-full flex flex-col mb-[20rpx] card-template" @click="toLink(item)">
|
||||
<view class="flex items-center mb-[30rpx] leading-[1]">
|
||||
<view class="nc-iconfont nc-icon-hexiaotaiV6xx !text-[26rpx] pr-[10rpx]"></view>
|
||||
<text class="truncate text-[#333333] text-[26rpx]">核销码:{{ item.code }}</text>
|
||||
</view>
|
||||
<view class="flex flex-1" v-for="(dataItem,dataIndex) in item.value.list" :key="dataIndex">
|
||||
<image class="w-[100rpx] h-[100rpx] rounded-[8rpx]" mode="aspectFit" v-if="dataItem.cover" :src="img(dataItem.cover)"></image>
|
||||
<image class="w-[100rpx] h-[100rpx] rounded-[8rpx]" mode="aspectFit" v-else :src="img('addon/tourism/tourism/member/hotel.png')"></image>
|
||||
|
||||
<view class="flex flex-col flex-1 ml-[20rpx] mt-[3rpx]">
|
||||
<view class="leading-[1.4] multi-hidden text-28rpx text-[#333]">{{dataItem.name}}</view>
|
||||
<view class="self-end text-[28rpx]">x1</view>
|
||||
<view class="flex flex-1" v-for="(dataItem,dataIndex) in item.value.list" :key="dataIndex">
|
||||
<u--image class="rounded-[8rpx] overflow-hidden" width="120rpx" height="120rpx" :src="img(dataItem.cover ? dataItem.cover : '')" model="aspectFill">
|
||||
<template #error>
|
||||
<image class="w-[120rpx] h-[120rpx] rounded-[8rpx] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
|
||||
</template>
|
||||
</u--image>
|
||||
<view class="flex flex-col flex-1 justify-between ml-[20rpx] py-[4rpx]" >
|
||||
<view class="leading-[1.3] multi-hidden text-[28rpx] text-[#333]">{{dataItem.name}}</view>
|
||||
<view class="self-end text-[26rpx] mt-[10rpx] text-[#626779]">x1</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex bg-[#F8F9FD] py-[20rpx] px-[20rpx] rounded-[12rpx] mt-[20rpx]">
|
||||
<view class="flex-1">
|
||||
<view class="text-[22rpx] text-[#8288A2] mb-[10rpx] leading-[30rpx]">核销时间</view>
|
||||
<view class="text-[26rpx] text-[#333] leading-[36rpx]">{{ item.create_time }}</view>
|
||||
</view>
|
||||
<view class="flex-1">
|
||||
<view class="text-[22rpx] text-[#8288A2] mb-[10rpx] leading-[30rpx]">核销员</view>
|
||||
<view class="text-[26rpx] text-[#333] leading-[36rpx]">{{ item.member ? item.member.nickname : '--' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex flex-col bg-[#F6F6F6] p-[20rpx] rounded-[12rpx] mt-[20rpx] mb-[20rpx]">
|
||||
<text class="text-[#333333] text-[26rpx] h-[36rpx] leading-[36rpx]">核销时间:{{ item.create_time }}</text>
|
||||
<text class="text-[#333333] text-[26rpx] h-[36rpx] mt-[10rpx] truncate leading-[36rpx]">核销员:{{ item.member ? item.member.nickname : '--' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<mescroll-empty :option="{'icon': img('static/resource/images/empty.png')}" v-if="!list.length && loading"></mescroll-empty>
|
||||
<view class="mx-[30rpx] rounded-[16rpx] noData flex items-center justify-center" v-if="!list.length && loading">
|
||||
<mescroll-empty :option="{tip : '暂无核销记录'}"></mescroll-empty>
|
||||
</view>
|
||||
</mescroll-body>
|
||||
<!-- 时间选择 -->
|
||||
<select-date ref="selectDateRef" @confirm="confirmFn" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue'
|
||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'
|
||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js'
|
||||
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
|
||||
import { getVerifyRecords } from '@/app/api/verify'
|
||||
import { img, redirect } from '@/utils/common'
|
||||
import selectDate from '@/components/select-date/select-date.vue';
|
||||
|
||||
let list = ref<Array<Object>>([])
|
||||
let loading = ref<boolean>(false)
|
||||
const keyword = ref<string>('')
|
||||
const create_time = ref([])
|
||||
const list = ref<Array<Object>>([])
|
||||
const loading = ref<boolean>(false)
|
||||
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom)
|
||||
|
||||
const geVerifyRecordFn = (mescroll) => {
|
||||
@ -48,6 +71,8 @@
|
||||
let data : object = {
|
||||
page: mescroll.num,
|
||||
limit: mescroll.size,
|
||||
keyword:keyword.value,
|
||||
create_time: create_time.value
|
||||
};
|
||||
|
||||
getVerifyRecords(data).then((res) => {
|
||||
@ -68,7 +93,37 @@
|
||||
const toLink = (data: AnyObject)=> {
|
||||
redirect({ url: '/app/pages/verify/detail', param: { code: data.code } })
|
||||
}
|
||||
|
||||
// 关键词搜索条件搜索
|
||||
const searchTypeFn = () =>{
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
//日期筛选
|
||||
const selectDateRef = ref()
|
||||
const handleSelect = () =>{
|
||||
selectDateRef.value.show = true
|
||||
}
|
||||
// 确定时间筛选
|
||||
const confirmFn = (data) =>{
|
||||
create_time.value = data;
|
||||
list.value = []
|
||||
getMescroll().resetUpScroll();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.uni-picker-view-content){
|
||||
z-index: 10;
|
||||
}
|
||||
:deep(.uni-picker-view-indicator::before){
|
||||
border: none !important;
|
||||
}
|
||||
:deep(.uni-picker-view-indicator::after){
|
||||
border: none !important;
|
||||
}
|
||||
.noData{
|
||||
height: calc(100vh - 132rpx - constant(safe-area-inset-bottom));
|
||||
height: calc(100vh - 132rpx - env(safe-area-inset-bottom));
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -2,60 +2,50 @@
|
||||
<view :style="themeColor()" class="bg-[#f8f8f8] min-h-[100vh] overflow-hidden">
|
||||
<block v-if="!loading && verifyInfo && verifyInfo.value">
|
||||
<view class="w-full bg-[#fff] flex justify-center">
|
||||
<view class="text-[var(--primary-color)] absolute top-[30rpx] right-[30rpx] flex" @click="redirect({url:'/app/pages/verify/record'})">
|
||||
<image class="w-[24rpx] h-[28rpx]" :src="img('static/resource/images/verify/history.png')"/>
|
||||
<text class="text-[26rpx] leading-[30.47rpx] ml-[10rpx] h-[36rpx] leading-[36rpx]">核销记录</text>
|
||||
<view class="text-[var(--primary-color)] absolute top-[40rpx] right-[30rpx] flex items-center" @click="redirect({url:'/app/pages/verify/record'})">
|
||||
<image class="w-[26rpx] h-[28rpx]" :src="img('static/resource/images/verify/history.png')"/>
|
||||
<text class="text-[26rpx] ml-[10rpx]">核销记录</text>
|
||||
</view>
|
||||
<view class="flex pt-[126rpx] pb-[30rpx] items-center">
|
||||
<view class="flex justify-center items-center flex-col pr-[30rpx]">
|
||||
<view class="flex pt-[120rpx] pb-[30rpx] items-center">
|
||||
<view class="flex justify-center items-center flex-col pr-[30rpx] w-[130rpx]">
|
||||
<image class="w-[100rpx] h-[100rpx]" :src="img('static/resource/images/verify/yanzhenghexiaoma.png')"/>
|
||||
<view class="text-[26rpx] mt-[12rpx] h-[36rpx] leading-[36rpx]">验证核销码</view>
|
||||
</view>
|
||||
<image class="w-[74rpx] h-[12rpx] mb-[50rpx]" :src="img('static/resource/images/verify/youjiantou.png')"/>
|
||||
<view class="flex justify-center items-center flex-col pl-[30rpx]">
|
||||
<view class="flex justify-center items-center flex-col pl-[30rpx] w-[130rpx]">
|
||||
<image class="w-[100rpx] h-[100rpx]" :src="img('static/resource/images/verify/hexiao.png')"/>
|
||||
<view class="text-[26rpx] mt-[12rpx] h-[36rpx] leading-[36rpx]">确定核销</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bg-[#fff] rounded-[16rpx] mt-[20rpx] mx-[30rpx] h-[200rpx]">
|
||||
<view class="flex" v-for="(item,index) in verifyInfo.value.list" :key="index">
|
||||
<image class="w-[150rpx] h-[150rpx] ml-[20rpx] mt-[30rpx] rounded-[8rpx]" mode="aspectFit" v-if="item.cover" :src="img(item.cover)"></image>
|
||||
<image class="w-[150rpx] h-[150rpx] ml-[20rpx] mt-[30rpx] rounded-[8rpx]" mode="aspectFit" v-else :src="img('addon/tourism/tourism/member/hotel.png')"></image>
|
||||
<view class="flex flex-col flex-1 ml-[10rpx]">
|
||||
<view class="mt-[33rpx] ml-[20rpx] max-w-[432rpx] multi-hidden">{{item.name}}</view>
|
||||
<view class="card-template mt-[20rpx] sidebar-marign">
|
||||
<view class="flex" :class="{'mb-[20rpx]': (verifyInfo.value.list.length - 1 != index)}" v-for="(item,index) in verifyInfo.value.list" :key="index">
|
||||
<image class="w-[150rpx] h-[150rpx] rounded-[8rpx]" mode="aspectFill" v-if="item.cover" :src="img(item.cover)"></image>
|
||||
<image class="w-[150rpx] h-[150rpx] rounded-[8rpx]" mode="aspectFill" v-else :src="img('addon/tourism/tourism/member/hotel.png')"></image>
|
||||
<view class="flex flex-col flex-1 ml-[20rpx] py-[4rpx]">
|
||||
<view class="leading-[1.3] multi-hidden">{{item.name}}</view>
|
||||
<view class="self-end text-[#626779] text-[28rpx] mt-[10rpx]">x1</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bg-[#fff] rounded-[16rpx] mx-[30rpx] mt-[20rpx]">
|
||||
<view class="pt-[20rpx] pl-[20rpx] text-[28rpx] font-bold h-[39rpx] leading-[39rpx]">核销信息</view>
|
||||
<view class="text-[28rpx] pb-[20rpx]">
|
||||
<view class="flex pt-[30rpx] items-center justify-between px-[20rpx]">
|
||||
<text class="text-[28rpx] text-[#333333] h-[39rpx] leading-[39rpx]">核销类型</text>
|
||||
<view class="text-[28rpx] text-[#333333] h-[39rpx] leading-[39rpx]">{{verifyInfo.type_name}}</view>
|
||||
</view>
|
||||
<view class="flex pt-[30rpx] items-center justify-between px-[20rpx]" v-for="(item,index) in verifyInfo.value.content.fixed">
|
||||
<text class="text-[28rpx] text-[#333333] h-[39rpx] leading-[39rpx]">{{item.title}}</text>
|
||||
<view class="text-[28rpx] text-[#333333] h-[39rpx] leading-[39rpx]">{{item.value}}</view>
|
||||
</view>
|
||||
<view class="card-template mt-[20rpx] sidebar-marign">
|
||||
<view class="text-[32rpx] font-500 leading-[1.3]">核销信息</view>
|
||||
<view class="flex pt-[30rpx] items-center justify-between min-h-[36rpx]">
|
||||
<text class="text-[26rpx] text-[#626779]">核销类型</text>
|
||||
<view class="text-[26rpx] text-[#333333]">{{verifyInfo.type_name}}</view>
|
||||
</view>
|
||||
<view class="flex pt-[20rpx] items-center justify-between min-h-[36rpx]" v-for="(item,index) in verifyInfo.value.content.fixed">
|
||||
<text class="text-[26rpx] text-[#626779]">{{item.title}}</text>
|
||||
<view class="text-[26rpx] text-[#333333]">{{item.value}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-for="(item,index) in verifyInfo.value.content.diy" :key="index" class="bg-[#fff] rounded-[16rpx] mx-[30rpx] mt-[20rpx]">
|
||||
<view class="pt-[20rpx] pl-[20rpx] text-[28rpx] font-bold h-[39rpx] leading-[39rpx]">{{item.title}}</view>
|
||||
<view class="text-[28rpx] pb-[20rpx]">
|
||||
<view class="flex pt-[30rpx] items-center justify-between px-[20rpx]" v-for="(subItem,subIndex) in item.list" :key="subIndex">
|
||||
<text class="text-[28rpx] text-[#333333] h-[39rpx] leading-[39rpx]">{{subItem.title}}</text>
|
||||
<div v-if="subIndex === 0" class="flex items-center">
|
||||
<text class="text-[28rpx] text-[#333333] h-[39rpx] leading-[39rpx] mr-[10rpx]">{{ subItem.value }}</text>
|
||||
<view class="w-[1rpx] h-[20rpx] bg-[#999999] mr-[10rpx]"></view>
|
||||
<view class="text-[#EF900A]" @click="copy(subItem.value)">复制</view>
|
||||
</div>
|
||||
<div v-else>
|
||||
<text class="text-[28rpx] text-[#333333] h-[39rpx] leading-[39rpx]">{{ subItem.value }}</text>
|
||||
</div>
|
||||
</view>
|
||||
<view v-for="(item,index) in verifyInfo.value.content.diy" :key="index" class="card-template mt-[20rpx] sidebar-marign">
|
||||
<view class="text-[32rpx] font-500 leading-[1.3]">{{item.title}}</view>
|
||||
<view class="flex items-center justify-between min-h-[36rpx]" :class="{'pt-[30rpx]': subIndex==0, 'pt-[20rpx]': subIndex!=0}" v-for="(subItem,subIndex) in item.list" :key="subIndex">
|
||||
<text class="text-[26rpx] text-[#626779]">{{subItem.title}}</text>
|
||||
<text class="text-[26rpx] text-[#333333]">{{ subItem.value }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -68,26 +58,23 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { onLoad ,onShow} from '@dcloudio/uni-app'
|
||||
import { img,redirect, isWeixinBrowser, getToken } from '@/utils/common';
|
||||
import { img,redirect, getToken } from '@/utils/common';
|
||||
import { getVerifierInfo, getCheckVerifier, verify } from '@/app/api/verify'
|
||||
import { copy } from '@/utils/common';
|
||||
import { t } from '@/locale'
|
||||
|
||||
const loading = ref(true)
|
||||
const verifyDetail = ref<AnyObject | null>(null)
|
||||
let code = ref('');
|
||||
onLoad((option)=> {
|
||||
if (option.code) code.value = option.code;
|
||||
// 小程序扫码进入
|
||||
if (option.scene) {
|
||||
let sceneParams = decodeURIComponent(option.scene);
|
||||
sceneParams = sceneParams.split('&');
|
||||
if (sceneParams.length) {
|
||||
sceneParams.forEach(item => {
|
||||
if (item.indexOf('code') != -1) code.value = item.split('-')[1];
|
||||
});
|
||||
}
|
||||
}
|
||||
const code = ref('');
|
||||
onLoad((option:any)=> {
|
||||
if (option.code) code.value = option.code;
|
||||
// 小程序扫码进入
|
||||
if (option.scene) {
|
||||
let sceneParams: any = decodeURIComponent(option.scene).split('&');
|
||||
if (sceneParams.length) {
|
||||
sceneParams.forEach((item: any) => {
|
||||
if (item.indexOf('code') != -1) code.value = item.split('-')[1];
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
@ -106,7 +93,16 @@
|
||||
icon: 'none'
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
if(getCurrentPages().length > 1){
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
}else{
|
||||
redirect({
|
||||
url: '/app/pages/member/index',
|
||||
mode: 'reLaunch'
|
||||
});
|
||||
}
|
||||
}, 1000);
|
||||
}else{
|
||||
loading.value = false;
|
||||
@ -114,13 +110,18 @@
|
||||
})
|
||||
}
|
||||
|
||||
let verifyInfo = ref({})
|
||||
const verifyInfo = ref({})
|
||||
const getVerifierInfoFn = ()=>{
|
||||
loading.value = true;
|
||||
getVerifierInfo(code.value).then((res:any) =>{
|
||||
verifyInfo.value = res.data;
|
||||
loading.value = false;
|
||||
})
|
||||
}).catch(() => {
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
redirect({ url: '/app/pages/verify/index', param: {}, mode: 'redirectTo' })
|
||||
}, 1000);
|
||||
})
|
||||
}
|
||||
let isLoading = false;
|
||||
const verifyFn = ()=>{
|
||||
@ -128,8 +129,12 @@
|
||||
isLoading = true;
|
||||
|
||||
verify(code.value).then((res:any) =>{
|
||||
isLoading = false;
|
||||
uni.showToast({
|
||||
title: '核销成功',
|
||||
icon: 'none'
|
||||
});
|
||||
setTimeout(() => {
|
||||
isLoading = false;
|
||||
redirect({ url: '/app/pages/verify/index', param: {}, mode: 'redirectTo' })
|
||||
}, 1000);
|
||||
}).catch(() => {
|
||||
|
||||
@ -8,17 +8,25 @@
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { ref } from 'vue';
|
||||
import { redirect } from '@/utils/common';
|
||||
|
||||
const src = ref('')
|
||||
|
||||
onLoad((option : any) => {
|
||||
src.value = decodeURIComponent(option.src);
|
||||
src.value = option.src ? decodeURIComponent(option.src) : '';
|
||||
})
|
||||
|
||||
const navigateBack = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
if(getCurrentPages().length > 1){
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
}else{
|
||||
redirect({
|
||||
url: '/app/pages/index/index',
|
||||
mode: 'reLaunch'
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -73,7 +73,6 @@
|
||||
data.city && (selected.city = data.city)
|
||||
data.district && (selected.district = data.district)
|
||||
})
|
||||
.catch()
|
||||
}
|
||||
},{
|
||||
immediate:true
|
||||
|
||||
198
uni-app/src/components/bind-mobile/bind-mobile.vue
Normal file
198
uni-app/src/components/bind-mobile/bind-mobile.vue
Normal file
@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<u-popup :show="show" @close="show = false" mode="center" :round="10" :closeable="true" :safeAreaInsetBottom="false" zIndex="10086">
|
||||
<view @touchmove.prevent.stop class="max-w-[630rpx] w-[630rpx] box-border">
|
||||
<view class="text-center py-[50rpx] text-[32rpx] font-500 leading-[46rpx]">{{t('bindMobile')}}</view>
|
||||
<view class="px-[50rpx] pb-[50rpx]">
|
||||
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
|
||||
<u-form-item label="" prop="mobile" :borderBottom="true">
|
||||
<input v-model="formData.mobile" :placeholder="t('mobilePlaceholder')" class=" w-full h-[50rpx] leading-[50rpx] !bg-transparent !px-[20rpx] text-[26rpx] text-[#333]" :disabled="real_name_input" placeholder-class="bind-mobile" />
|
||||
</u-form-item>
|
||||
<view class="mt-[20rpx]">
|
||||
<u-form-item label="" prop="mobile_code" :borderBottom="true">
|
||||
<input v-model="formData.mobile_code" :placeholder="t('codePlaceholder')" class=" box-border w-full h-[50rpx] leading-[50rpx] !bg-transparent !px-[20rpx] text-[26rpx] text-[#333]" :disabled="real_name_input" placeholder-class="bind-mobile" />
|
||||
<template #right>
|
||||
<sms-code :mobile="formData.mobile" type="bind_mobile" v-model="formData.mobile_key"></sms-code>
|
||||
</template>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="flex items-baseline mt-[20rpx] pl-[10rpx]" v-if="config.agreement_show">
|
||||
<u-checkbox-group>
|
||||
<u-checkbox activeColor="var(--primary-color)" :checked="isAgree" shape="shape" size="12" @change="agreeChange" :customStyle="{marginTop: '0rpx',marginBottom: '0rpx'}" :label=" t('agreeTips')" labelSize="22rpx" labelColor="#8288A2" />
|
||||
</u-checkbox-group>
|
||||
<view class="text-[22rpx] text-[#8288A2] leading-[30rpx] flex flex-wrap">
|
||||
<view @click="redirect({ url: '/app/pages/auth/agreement?key=service' })">
|
||||
《<text class="text-primary">{{ t('userAgreement') }}</text>》
|
||||
</view>
|
||||
<view @click="redirect({ url: '/app/pages/auth/agreement?key=privacy' })">
|
||||
《<text class="text-primary">{{ t('privacyAgreement') }}</text>》
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-[120rpx]">
|
||||
<button class="primary-btn-bg text-[26rpx] text-[#fff] !h-[80rpx] leading-[80rpx] rounded-full font-bold" :loading="loading" :loadingText="t('binding')" @click="handleBind">{{t('bind')}}</button>
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="mt-[20rpx]">
|
||||
<u-button :customStyle="{border:'none',color:'var(--primary-color)',fontSize:'26rpx',height:'40rpx', lineHeight:'40rpx'}" :text="t('mobileQuickLogin')" open-type="getPhoneNumber" @getphonenumber="mobileAuth" @click="checkWxPrivacy"></u-button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</u-form>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { t } from '@/locale'
|
||||
import { bindMobile } from '@/app/api/member'
|
||||
import useMemberStore from '@/stores/member'
|
||||
import useConfigStore from '@/stores/config'
|
||||
import { redirect } from '@/utils/common'
|
||||
|
||||
const show = ref(false)
|
||||
const memberStore = useMemberStore()
|
||||
const info = computed(() => memberStore.info)
|
||||
|
||||
const config = computed(() => {
|
||||
return useConfigStore().login
|
||||
})
|
||||
|
||||
const wxPrivacyPopupRef:any = ref(null)
|
||||
|
||||
// 检测是否同意隐私协议
|
||||
const checkWxPrivacy = ()=>{
|
||||
wxPrivacyPopupRef.value.proactive();
|
||||
}
|
||||
|
||||
const loading = ref(false)
|
||||
const isAgree = ref(false)
|
||||
|
||||
const formData = reactive({
|
||||
mobile: '',
|
||||
mobile_code: '',
|
||||
mobile_key: ''
|
||||
})
|
||||
|
||||
let real_name_input = ref(true);
|
||||
onMounted(() => {
|
||||
// 防止浏览器自动填充
|
||||
setTimeout(()=>{
|
||||
real_name_input.value = false;
|
||||
},800)
|
||||
});
|
||||
|
||||
uni.getStorageSync('openid') && (Object.assign(formData, { openid: uni.getStorageSync('openid') }))
|
||||
uni.getStorageSync('pid') && (Object.assign(formData, { pid: uni.getStorageSync('pid') }))
|
||||
uni.getStorageSync('unionid') && (Object.assign(formData, { unionid: uni.getStorageSync('unionid') }))
|
||||
|
||||
const rules = {
|
||||
'mobile': [
|
||||
{
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: t('mobilePlaceholder'),
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
{
|
||||
validator(rule, value, callback) {
|
||||
let mobile = /^1[3-9]\d{9}$/;
|
||||
if (!mobile.test(value)){
|
||||
callback(new Error('请输入正确的手机号'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
message: t('mobileError'),
|
||||
trigger: ['change', 'blur'],
|
||||
}
|
||||
],
|
||||
'mobile_code': {
|
||||
type: 'string',
|
||||
required: true,
|
||||
message: t('codePlaceholder'),
|
||||
trigger: ['blur', 'change']
|
||||
}
|
||||
}
|
||||
|
||||
const agreeChange = () => {
|
||||
isAgree.value = !isAgree.value
|
||||
}
|
||||
|
||||
|
||||
const formRef = ref(null)
|
||||
|
||||
const handleBind = () => {
|
||||
formRef.value.validate().then(() => {
|
||||
if (loading.value) return
|
||||
loading.value = true
|
||||
|
||||
bindMobile(formData).then((res) => {
|
||||
memberStore.getMemberInfo()
|
||||
if(info.value.mobile){
|
||||
uni.removeStorageSync('isbindmobile');
|
||||
}
|
||||
show.value = false
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const mobileAuth = (e) => {
|
||||
if (!isAgree.value && config.value.agreement_show) {
|
||||
uni.showToast({
|
||||
title: `${ t('pleaceAgree') }《${ t('userAgreement') }》《${ t('privacyAgreement') }》`,
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (e.detail.errMsg == 'getPhoneNumber:ok') {
|
||||
uni.showLoading({ title: '' })
|
||||
|
||||
bindMobile({
|
||||
mobile_code: e.detail.code
|
||||
}).then((res) => {
|
||||
uni.hideLoading()
|
||||
memberStore.getMemberInfo()
|
||||
if(res.msg == 1){
|
||||
uni.removeStorageSync('isbindmobile');
|
||||
}
|
||||
show.value = false
|
||||
}).catch((res) => {
|
||||
setTimeout(() => {
|
||||
show.value = false
|
||||
uni.hideLoading()
|
||||
}, 2000);
|
||||
})
|
||||
}
|
||||
|
||||
if (e.detail.errno == 104) {
|
||||
let msg = '用户未授权隐私权限';
|
||||
uni.showToast({ title: msg, icon: 'none' })
|
||||
}
|
||||
if (e.detail.errMsg == "getPhoneNumber:fail user deny") {
|
||||
let msg = '用户拒绝获取手机号码';
|
||||
uni.showToast({ title: msg, icon: 'none' })
|
||||
}
|
||||
}
|
||||
const open = ()=> {
|
||||
show.value = true
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
open
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.bind-mobile){
|
||||
color:#8288A2;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
</style>
|
||||
@ -4,11 +4,11 @@
|
||||
<view class="text-base">{{ t('getAvatarNickname') }}</view>
|
||||
<view class="text-sm mt-[18rpx] text-gray-400">{{ t('getAvatarNicknameTips') }}</view>
|
||||
</view>
|
||||
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
|
||||
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef" labelWidth="65">
|
||||
<view class="mx-[30rpx]">
|
||||
<view class="mt-[20rpx]">
|
||||
<u-form-item :label="t('headimg')" prop="headimg" :border-bottom="true">
|
||||
<button class="m-0 my-[10rpx] p-0 w-[140rpx] h-[140rpx]" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
|
||||
<button class="m-0 my-[10rpx] p-0 w-[140rpx] h-[140rpx]" open-type="chooseAvatar" @chooseavatar="onChooseAvatar" @click="checkWxPrivacy">
|
||||
<view class="w-full h-full flex items-center justify-center overflow-hidden">
|
||||
<u-image :src="img(formData.headimg)" width="140rpx" height="140rpx" v-if="formData.headimg" mode="aspectFill"></u-image>
|
||||
<u-icon name="plus" v-else></u-icon>
|
||||
@ -18,22 +18,31 @@
|
||||
<u-form-item :label=" t('nickname')" prop="nickname" :border-bottom="true">
|
||||
<input type="nickname" v-model="formData.nickname" :placeholder="t('nicknamePlaceholder')" @blur="bindNickname">
|
||||
</u-form-item>
|
||||
<u-form-item :label=" t('mobile')" prop="mobile" :border-bottom="true" v-if="isBindMobile">
|
||||
<input type="mobile" v-model="formData.mobile" :disabled="true" v-if="formData.mobile">
|
||||
<u-button :customStyle="{border:'none',color: 'var(--primary-color)',width:'140rpx', textAlign:'left',margin:'0rpx'}" :text="t('getMobile')" open-type="getPhoneNumber" @getphonenumber="mobileAuth" @click="checkWxPrivacy" v-else></u-button>
|
||||
</u-form-item>
|
||||
</view>
|
||||
</view>
|
||||
<view class="p-[30rpx] mt-[20rpx]">
|
||||
<u-button type="primary" :loading="loading" :text="t('confirm')" shape="circle" @click="confirm"></u-button>
|
||||
<button :loading="loading" class="bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[28rpx]" @click="confirm">{{t('confirm')}}</button>
|
||||
</view>
|
||||
</u-form>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch } from 'vue'
|
||||
import { ref, reactive, computed, watch,onMounted } from 'vue'
|
||||
import { t } from '@/locale'
|
||||
import useMemberStore from '@/stores/member'
|
||||
import { img } from '@/utils/common'
|
||||
import { modifyMember } from '@/app/api/member'
|
||||
import { img, getToken } from '@/utils/common'
|
||||
import { modifyMember, bindMobile } from '@/app/api/member'
|
||||
import { fetchBase64Image } from '@/app/api/system'
|
||||
import { useLogin } from '@/hooks/useLogin'
|
||||
|
||||
const show = ref(false)
|
||||
const loading = ref(false)
|
||||
@ -42,16 +51,34 @@
|
||||
|
||||
const formData = reactive({
|
||||
nickname: '',
|
||||
headimg: ''
|
||||
headimg: '',
|
||||
mobile: '',
|
||||
})
|
||||
|
||||
watch(() => info.value, () => {
|
||||
if (info.value) {
|
||||
formData.nickname = info.value.nickname
|
||||
formData.headimg = info.value.headimg
|
||||
formData.mobile = info.value.mobile
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
let isBindMobile = ref(null)
|
||||
|
||||
onMounted(()=>{
|
||||
uni.getStorageSync('openid') && (Object.assign(formData, { openid: uni.getStorageSync('openid') }))
|
||||
uni.getStorageSync('pid') && (Object.assign(formData, { pid: uni.getStorageSync('pid') }))
|
||||
uni.getStorageSync('unionid') && (Object.assign(formData, { unionid: uni.getStorageSync('unionid') }))
|
||||
isBindMobile.value = uni.getStorageSync('isbindmobile');
|
||||
})
|
||||
|
||||
const wxPrivacyPopupRef:any = ref(null)
|
||||
|
||||
// 检测是否同意隐私协议
|
||||
const checkWxPrivacy = ()=>{
|
||||
wxPrivacyPopupRef.value.proactive();
|
||||
}
|
||||
|
||||
const onChooseAvatar = (e) => {
|
||||
uni.getFileSystemManager().readFile({
|
||||
filePath: e.detail.avatarUrl, //选择图片返回的相对路径
|
||||
@ -80,6 +107,12 @@
|
||||
required: true,
|
||||
message: t('nicknamePlaceholder'),
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
'mobile': {
|
||||
type: 'string',
|
||||
required: isBindMobile.value ? true : false,
|
||||
message: t('mobileTips'),
|
||||
trigger: ['blur', 'change'],
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,8 +139,44 @@
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
// #ifdef MP-WEIXIN
|
||||
const login = useLogin()
|
||||
if( info.value && !info.value.weapp_openid){
|
||||
login.getAuthCode('',true)
|
||||
}
|
||||
// #endif
|
||||
|
||||
})
|
||||
}
|
||||
const mobileAuth = (e) => {
|
||||
|
||||
if (e.detail.errMsg == 'getPhoneNumber:ok') {
|
||||
uni.showLoading({ title: '' })
|
||||
bindMobile({
|
||||
openid: formData.openid,
|
||||
mobile_code: e.detail.code
|
||||
}).then((res) => {
|
||||
uni.hideLoading()
|
||||
memberStore.getMemberInfo()
|
||||
if(info.value.mobile){
|
||||
uni.removeStorageSync('isbindmobile');
|
||||
}
|
||||
}).catch((res) => {
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
}, 2000);
|
||||
})
|
||||
}
|
||||
|
||||
if (e.detail.errno == 104) {
|
||||
let msg = '用户未授权隐私权限';
|
||||
uni.showToast({ title: msg, icon: 'none' })
|
||||
}
|
||||
if (e.detail.errMsg == "getPhoneNumber:fail user deny") {
|
||||
let msg = '用户拒绝获取手机号码';
|
||||
uni.showToast({ title: msg, icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show
|
||||
|
||||
@ -89,25 +89,25 @@ export default {
|
||||
}
|
||||
|
||||
.mescroll-empty .empty-icon {
|
||||
width: 320rpx;
|
||||
height: 320rpx;
|
||||
width: 348rpx;
|
||||
height: 348rpx;
|
||||
}
|
||||
|
||||
.mescroll-empty .empty-tip {
|
||||
margin-top: 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.mescroll-empty .empty-btn {
|
||||
display: inline-block;
|
||||
margin-top: 40rpx;
|
||||
min-width: 200rpx;
|
||||
padding: 18rpx;
|
||||
display: inline-block;
|
||||
min-width: 220rpx;
|
||||
height: 66rpx;
|
||||
line-height: 66rpx;
|
||||
font-size: 28rpx;
|
||||
border: 1rpx solid #e04b28;
|
||||
border: 1rpx solid #EF000C;
|
||||
border-radius: 60rpx;
|
||||
color: #e04b28;
|
||||
color: #EF000C;
|
||||
}
|
||||
|
||||
.mescroll-empty .empty-btn:active {
|
||||
|
||||
99
uni-app/src/components/nc-contact/nc-contact.vue
Normal file
99
uni-app/src/components/nc-contact/nc-contact.vue
Normal file
@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<view class="contact-wrap">
|
||||
<slot></slot>
|
||||
<button
|
||||
type="default"
|
||||
hover-class="none"
|
||||
open-type="contact"
|
||||
class="contact-button"
|
||||
@click="contactService"
|
||||
:send-message-title="props.sendMessageTitle"
|
||||
:send-message-path="props.sendMessagePath"
|
||||
:send-message-img="props.sendMessageImg"
|
||||
:show-message-card="true">
|
||||
</button>
|
||||
|
||||
<u-popup :show="popupShow" @close="popupShow = false" mode="center" :round="5" :safeAreaInsetBottom="false">
|
||||
<view @touchmove.prevent.stop>
|
||||
<view class="py-[25rpx] text-sm leading-none border-0 border-solid border-b-[2rpx] border-[#eee] flex items-center justify-between">
|
||||
<text class="ml-[30rpx]">联系客服</text>
|
||||
<text class="mr-[20rpx] nc-iconfont nc-icon-guanbiV6xx text-[35rpx]" @click="popupShow = false"></text>
|
||||
</view>
|
||||
<view class="px-6 py-3 w-[480rpx] h-[100rpx] text-sm" v-if="siteInfo && siteInfo.phone">
|
||||
<view class="mb-[10rpx]">客服电话</view>
|
||||
<view @click="callPhone" class="text-primary truncate">{{ siteInfo.phone }}</view>
|
||||
</view>
|
||||
<view class="px-6 py-3 w-[480rpx] h-[100rpx] leading-[100rpx] text-sm" v-else>抱歉,商家暂无客服,请线下联系</view>
|
||||
<button @click="popupShow = false"
|
||||
class="!mx-[30rpx] !mb-[40rpx] !w-auto !h-[70rpx] text-[24rpx] leading-[70rpx] rounded-full text-white !bg-[#ff4500] !text-[#fff]">
|
||||
我知道了
|
||||
</button>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import useSystemStore from '@/stores/system'
|
||||
|
||||
const props = defineProps({
|
||||
sendMessageTitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
sendMessagePath: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
sendMessageImg: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const systemStore = useSystemStore()
|
||||
|
||||
const siteInfo:any = computed(() => {
|
||||
return systemStore.site;
|
||||
})
|
||||
|
||||
const popupShow = ref(false);
|
||||
|
||||
const contactService = () => {
|
||||
// #ifdef H5
|
||||
popupShow.value = true;
|
||||
// #endif
|
||||
}
|
||||
|
||||
// 联系客服电话
|
||||
const callPhone = () => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: siteInfo.value.phone
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.contact-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
|
||||
.contact-button {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@ -25,7 +25,7 @@
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="p-[30rpx]">
|
||||
<u-button type="primary" :loading="loading" :text="t('pay.confirmPay')" shape="circle" @click="confirmPay"></u-button>
|
||||
<button class="primary-btn-bg h-[80rpx] rounded-[50rpx] leading-[80rpx] text-[28rpx] text-[#fff]" hover-class="none" :loading="loading" @click="confirmPay">{{t('pay.confirmPay')}}</button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
|
||||
199
uni-app/src/components/select-date/select-date.vue
Normal file
199
uni-app/src/components/select-date/select-date.vue
Normal file
@ -0,0 +1,199 @@
|
||||
<template>
|
||||
<u-popup :show="show" @close="show = false" mode="bottom" :round="10" zIndex="10090">
|
||||
<view>
|
||||
<view class="py-[30rpx] px-[40rpx] flex items-center justify-between">
|
||||
<view class="text-center flex-1 text-[32rpx] font-500 leading-[44rpx]">选择时间</view>
|
||||
<view class="nc-iconfont nc-icon-guanbiV6xx text-[36rpx] text-primary" @click="show = false"></view>
|
||||
</view>
|
||||
<view class="px-[30rpx] mb-[20rpx] mt-[10rpx]">
|
||||
<view class="flex items-center justify-between mb-[30rpx]">
|
||||
<view class="w-[160rpx] h-[60rpx] box-border leading-[60rpx] rounded-[30rpx] bg-[#F4F6FA] text-center text-[26rpx] text-[#666] border-[2rpx] border-solid border-[#F4F6FA]" v-for="(item,index) in curselectDate" :key="'a'+index" :class="{'text-primary !border-[var(--primary-color)] !bg-[rgba(239,0,12,0.04)]': currentValue.type == item.type}" @click="loadDateFn(item)">{{item.name}}</view>
|
||||
</view>
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="w-[316rpx] h-[60rpx] box-border leading-[60rpx] rounded-[30rpx] bg-[#F4F6FA] text-center text-[26rpx] text-[#666] border-[2rpx] border-solid border-[#F4F6FA]" :class="{'text-primary !border-[var(--primary-color)] !bg-[rgba(239,0,12,0.04)]': currentValue.type == 'first'}" @click="currentValue.type = 'first'">{{dateList.nowDate[0].substr(0,10)}}</view>
|
||||
<view class="nc-iconfont nc-icon-jianV6xx"></view>
|
||||
<view class="w-[316rpx] h-[60rpx] box-border leading-[60rpx] rounded-[30rpx] bg-[#F4F6FA] text-center text-[26rpx] text-[#666] border-[2rpx] border-solid border-[#F4F6FA]" :class="{'text-primary !border-[var(--primary-color)] !bg-[rgba(239,0,12,0.04)]': currentValue.type == 'second'}" @click="currentValue.type = 'second'">{{dateList.nowDate[1].substr(0,10)}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<picker-view indicator-class="!h-[70rpx] !bg-[#F4F6FA]" :value="dateList.curIndex" @change="bindChange" class="w-[750rpx] px-[60rpx] h-[396rpx] box-border">
|
||||
<picker-view-column>
|
||||
<view class="text-center leading-[70rpx] text-[28rpx]" v-for="(item,index) in dateList.years" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="text-center leading-[70rpx] text-[28rpx]" v-for="(item,index) in dateList.months" :key="index">{{item}}月</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="text-center leading-[70rpx] text-[28rpx]" v-for="(item,index) in dateList.days" :key="index">{{item}}日</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
<view class="px-[30rpx] pb-[30rpx] pt-[20rpx] flex justify-between">
|
||||
<button class="w-[330rpx] h-[88rpx] text-[var(--primary-color)] text-[32rpx] leading-[84rpx] border-[2rpx] border-solid border-[var(--primary-color)] rounded-[100rpx] bg-transparent" hover-class="none" @click="reset">重置</button>
|
||||
<button class="w-[330rpx] h-[88rpx] text-[#fff] text-[32rpx] leading-[88rpx] border-[0] rounded-[100rpx] primary-btn-bg" shape="circle" hover-class="none" @click="save">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref,reactive } from 'vue'
|
||||
|
||||
const emits = defineEmits(['confirm'])
|
||||
// 弹框时间选择
|
||||
const show = ref(false)
|
||||
let create_time = ref([])
|
||||
// 日期
|
||||
const init = () =>{
|
||||
const date = new Date();
|
||||
const years = []
|
||||
const months = []
|
||||
const days = []
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth();
|
||||
const day = date.getDate()
|
||||
|
||||
for (let i = 1990; i <= date.getFullYear()+2; i++) {
|
||||
years.push(i)
|
||||
}
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
months.push(i)
|
||||
}
|
||||
let dayCount = getDaysInMonth(year, month+1)
|
||||
for (let i = 1; i <= dayCount; i++) {
|
||||
days.push(i)
|
||||
}
|
||||
let yearIndex = years.indexOf(year)
|
||||
let curIndex = [yearIndex, month, day-1]
|
||||
let nowDate = `${year}-${month + 1 < 10 ? '0' + (month + 1) :(month + 1) }-${day < 10 ? '0' + day :day }`
|
||||
let nowDateStart = `${year}-${month + 1 < 10 ? '0' + (month + 1) :(month + 1) }-${day < 10 ? '0' + day :day } 00:00:00`
|
||||
let nowDateEnd = `${year}-${month + 1 < 10 ? '0' + (month + 1) :(month + 1) }-${day < 10 ? '0' + day :day } 23:59:59`
|
||||
let lastMonthDate = new Date(date.getFullYear(),month - 1,date.getDate())
|
||||
let lastThreeMonthDate = new Date(date.getFullYear(),month - 3,date.getDate())
|
||||
let halfYear = new Date(date.getFullYear(), month - 6, date.getDate())
|
||||
let lastYear =new Date(date.getFullYear() - 1, month, date.getDate())
|
||||
const formatDate = (dateTime:any) => {
|
||||
const yearTime = dateTime.getFullYear()
|
||||
const monthTime = dateTime.getMonth() + 1
|
||||
const dayTime = dateTime.getDate()
|
||||
return `${yearTime}-${monthTime < 10 ? '0' + monthTime : monthTime}-${dayTime < 10 ? '0' + dayTime :dayTime } 00:00:00`
|
||||
}
|
||||
return {
|
||||
years,
|
||||
months,
|
||||
days,
|
||||
curIndex,
|
||||
nowDate,
|
||||
nowDateStart,
|
||||
nowDateEnd,
|
||||
lastMonth: formatDate(lastMonthDate),
|
||||
lastThreeMonth: formatDate(lastThreeMonthDate),
|
||||
halfYear: formatDate(halfYear),
|
||||
lastYear: formatDate(lastYear)
|
||||
}
|
||||
}
|
||||
const getDaysInMonth = (year, month) => {
|
||||
let date = new Date(year, month, 0).getDate()
|
||||
return date
|
||||
}
|
||||
const getDaysCount = (year, month) =>{
|
||||
let count = getDaysInMonth(year, month)
|
||||
let days = []
|
||||
for (let i = 1; i <= count; i++) {
|
||||
days.push(i)
|
||||
}
|
||||
return days
|
||||
}
|
||||
const dateList = reactive({
|
||||
years: init().years,
|
||||
months: init().months,
|
||||
days: init().days,
|
||||
curIndex:init().curIndex, //当前选中下标
|
||||
nowDate:[init().nowDateStart,init().nowDateEnd] //当前选中日期
|
||||
})
|
||||
|
||||
const bindChange = (e) =>{
|
||||
const val = e.detail.value
|
||||
let year = dateList.years[val[0]]
|
||||
let month= dateList.months[val[1]]
|
||||
let day = dateList.days[val[2]]
|
||||
// 根据年份,月份判断天数
|
||||
dateList.days = getDaysCount(year, month)
|
||||
if(currentValue.value.type == 'first'){
|
||||
dateList.nowDate[0] = `${year}-${month < 10 ? '0' + month :month }-${day < 10 ? '0' + day :day } 00:00:00`
|
||||
}else if(currentValue.value.type == 'second'){
|
||||
dateList.nowDate[1] = `${year}-${month < 10 ? '0' + month :month }-${day < 10 ? '0' + day :day } 23:59:59`
|
||||
}
|
||||
}
|
||||
const curselectDate = reactive([
|
||||
{
|
||||
time:[init().lastMonth,init().nowDateEnd],
|
||||
type:'lastMonth',
|
||||
name:'近1个月'
|
||||
},
|
||||
{
|
||||
time:[init().lastThreeMonth,init().nowDateEnd],
|
||||
type:'lastThreeMonth',
|
||||
name:'近3个月'
|
||||
},
|
||||
{
|
||||
time:[init().halfYear,init().nowDateEnd],
|
||||
type:'halfYear',
|
||||
name:'近半年'
|
||||
},
|
||||
{
|
||||
time:[init().lastYear,init().nowDateEnd],
|
||||
type:'lastYear',
|
||||
name:'近一年'
|
||||
}
|
||||
])
|
||||
// 时间搜索
|
||||
let currentValue = ref({
|
||||
type: 'first',
|
||||
time: []
|
||||
})
|
||||
const loadDateFn = (data) =>{
|
||||
currentValue.value.type = data.type
|
||||
currentValue.value.time = data.time
|
||||
dateList.nowDate[0] = currentValue.value.time[0]
|
||||
dateList.nowDate[1] = currentValue.value.time[1]
|
||||
}
|
||||
|
||||
const save = () =>{
|
||||
if(currentValue.value.type == 'first' ||currentValue.value.type == 'second'){
|
||||
create_time.value = dateList.nowDate
|
||||
let start = new Date(create_time.value[0]).getTime()
|
||||
let end = new Date(create_time.value[1]).getTime()
|
||||
if( start > end){
|
||||
uni.showToast({ title: '开始时间不能大于结束时间', icon: 'none' })
|
||||
return
|
||||
}
|
||||
}else{
|
||||
create_time.value = currentValue.value.time
|
||||
}
|
||||
emits('confirm',create_time.value)
|
||||
show.value = false
|
||||
}
|
||||
const reset = () =>{
|
||||
currentValue.value.type = 'first'
|
||||
dateList.curIndex = init().curIndex
|
||||
dateList.nowDate = [init().nowDateStart,init().nowDateEnd]
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.uni-picker-view-content){
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
:deep(.uni-picker-view-indicator::before){
|
||||
border: none !important;
|
||||
}
|
||||
:deep(.uni-picker-view-indicator::after){
|
||||
border: none !important;
|
||||
}
|
||||
</style>
|
||||
@ -52,7 +52,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
import { img, copy } from '@/utils/common';
|
||||
import { getPoster } from '@/app/api/system'
|
||||
|
||||
@ -155,17 +155,17 @@ const saveGoodsPoster = () => {
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
if(err.errno == 104){
|
||||
let msg = '用户未授权隐私权限,将图像保存到相册失败';
|
||||
uni.showToast({title: msg, icon: 'none'})
|
||||
}else if (err.errMsg == "saveImageToPhotosAlbum:fail auth deny" ||
|
||||
if (err.errno == 104) {
|
||||
let msg = '用户未授权隐私权限,将图像保存到相册失败';
|
||||
uni.showToast({ title: msg, icon: 'none' })
|
||||
} else if (err.errMsg == "saveImageToPhotosAlbum:fail auth deny" ||
|
||||
err.errMsg == "saveImageToPhotosAlbum:fail:auth denied") {
|
||||
show.value = true;
|
||||
}else if(err.errMsg == "saveImageToPhotosAlbum:fail cancel"){
|
||||
show.value = true;
|
||||
} else if (err.errMsg == "saveImageToPhotosAlbum:fail cancel") {
|
||||
let msg = '用户取消将图片保存到相册';
|
||||
uni.showToast({title: msg, icon: 'none'})
|
||||
}else{
|
||||
uni.showToast({title: err.errMsg, icon: 'none'})
|
||||
uni.showToast({ title: msg, icon: 'none' })
|
||||
} else {
|
||||
uni.showToast({ title: err.errMsg, icon: 'none' })
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<view :class="{'text-primary': sendSms.canGetCode.value, 'text-gray-300': !sendSms.canGetCode.value}" @click="handleSend">{{ sendSms.tips.value }}</view>
|
||||
<view class="text-[26rpx]" :class="{'text-primary': sendSms.canGetCode.value, 'text-gray-300': !sendSms.canGetCode.value}" @click="handleSend">{{ sendSms.tips.value }}</view>
|
||||
<u-code :seconds="sendSms.seconds" :change-text="sendSms.changeText" ref="smsRef" @change="sendSms.codeChange"></u-code>
|
||||
<u-modal :show="show" :title="t('captchaTitle')" :confirm-text="t('confirm')" :cancel-text="t('cancel')" :show-cancel-button="true" @cancel="show = false" @confirm="handleConfirm">
|
||||
<u-modal :show="show" :title="t('captchaTitle')" :confirm-text="t('confirm')" :cancel-text="t('cancel')" :show-cancel-button="true" @cancel="show = false" @confirm="handleConfirm" confirmColor="var(--primary-color)">
|
||||
<view class="flex mt-[20rpx]">
|
||||
<u-input :placeholder="t('captchaPlaceholder')" border="surround" v-model="formData.captcha_code"></u-input>
|
||||
<image :src="captcha.image.value" class="h-[76rpx] ml-[20rpx]" mode="heightFix" @click="captcha.refresh()"></image>
|
||||
@ -38,7 +38,7 @@ const smsRef = ref(null)
|
||||
const sendSms = useSendSms(smsRef)
|
||||
const show = ref(false)
|
||||
|
||||
const formData = reactive<requestMobileParam>({
|
||||
const formData:any = reactive({
|
||||
mobile: '',
|
||||
captcha_code: '',
|
||||
captcha_key: '',
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
<template>
|
||||
<!-- diyStore.mode !='decorate' && topStatusBarData topStatusBarData.style == 'style-5 为了兼容风格五 -->
|
||||
<view class="ns-navbar-wrap" v-if="diyStore.mode !='decorate' && topStatusBarData || diyStore.mode =='decorate' && topStatusBarData && topStatusBarData.style == 'style-5' " :class="topStatusBarData.style">
|
||||
<view class="u-navbar" :style="{ backgroundColor: bgColor}">
|
||||
<view class="ns-navbar-wrap" v-if="diyStore.mode !='decorate' && topStatusBarData" :class="topStatusBarData.style">
|
||||
<view class="u-navbar" :class="{'fixed': props.scrollBool != -1, 'absolute': props.scrollBool == -1}" :style="{ backgroundColor: bgColor}">
|
||||
<view class="navbar-inner" :style="{ width: '100%', height: placeholderHeight + 'px' }">
|
||||
<view v-if="topStatusBarData.style == 'style-1'" class="content-wrap" :class="[topStatusBarData.textAlign]" :style="navbarInnerStyle">
|
||||
<view v-if="isBack && isBackShow" class="back-wrap text-[26px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: topStatusBarData.textColor || titleColor }" @tap="goBack"></view>
|
||||
<view v-if="isBack && isBackShow" class="back-wrap -ml-[16rpx] text-[27px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: titleTextColor }" @tap="goBack"></view>
|
||||
<view class="title-wrap" :style="styleOneFontSize">
|
||||
{{ data.title }}
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="topStatusBarData.style == 'style-2'" class="content-wrap" :style="navbarInnerStyle" @click="diyStore.toRedirect(topStatusBarData.link)">
|
||||
<view v-if="isBack && isBackShow" class="back-wrap text-[26px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: topStatusBarData.textColor || titleColor }" @tap="goBack"></view>
|
||||
<view v-if="isBack && isBackShow" class="back-wrap -ml-[16rpx] text-[27px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: titleTextColor }" @tap="goBack"></view>
|
||||
<view class="title-wrap" :style="{ color: topStatusBarData.textColor }">
|
||||
<view>
|
||||
<image :src="img(topStatusBarData.imgUrl)" mode="heightFix"></image>
|
||||
@ -20,7 +19,7 @@
|
||||
</view>
|
||||
|
||||
<view v-if="topStatusBarData.style == 'style-3'" :style="navbarInnerStyle" class="content-wrap">
|
||||
<view v-if="isBack && isBackShow" class="back-wrap text-[26px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: topStatusBarData.textColor || titleColor }" @tap="goBack"></view>
|
||||
<view v-if="isBack && isBackShow" class="back-wrap -ml-[16rpx] text-[27px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: titleTextColor }" @tap="goBack"></view>
|
||||
<view class="title-wrap" @click="diyStore.toRedirect(topStatusBarData.link)">
|
||||
<image :src="img(topStatusBarData.imgUrl)" mode="heightFix"></image>
|
||||
</view>
|
||||
@ -32,33 +31,32 @@
|
||||
</view>
|
||||
|
||||
<view v-if="topStatusBarData.style == 'style-4'" :style="navbarInnerStyle" class="content-wrap">
|
||||
<view v-if="isBack && isBackShow" class="back-wrap text-[26px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: topStatusBarData.textColor || titleColor }" @tap="goBack"></view>
|
||||
<view v-if="isBack && isBackShow" class="back-wrap -ml-[16rpx] text-[27px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: titleTextColor }" @tap="goBack"></view>
|
||||
<text class="nc-iconfont nc-icon-dizhiguanliV6xx text-[28rpx]" :style="{ color: topStatusBarData.textColor }"></text>
|
||||
<view class="title-wrap" @click="reposition()" :style="{ color: topStatusBarData.textColor }">{{ currentPosition }}</view>
|
||||
<text class="nc-iconfont nc-icon-youV6xx text-[26rpx]" @click="reposition()" :style="{ color: topStatusBarData.textColor }"></text>
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view v-if="topStatusBarData.style == 'style-5'" class="content-wrap" :style="navbarInnerStyle">
|
||||
<view v-if="isBack && isBackShow" class="back-wrap text-[26px] nc-iconfont nc-icon-zuoV6xx" :style="{ color: topStatusBarData.textColor || titleColor }" @tap="goBack"></view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 风格5,填充 -->
|
||||
<view v-if="topStatusBarData.style == 'style-5'" :style="style5Height"></view>
|
||||
|
||||
<!-- 解决fixed定位后导航栏塌陷的问题 -->
|
||||
<view class="u-navbar-placeholder" :style="{ width: '100%', paddingTop: placeholderHeight + 'px' }"></view>
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 小程序隐私协议 -->
|
||||
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup>
|
||||
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted, getCurrentInstance, nextTick } from 'vue';
|
||||
import { img, getLocation, locationStorage } from '@/utils/common';
|
||||
import { getAddressByLatlng } from '@/app/api/system';
|
||||
import useSystemStore from '@/stores/system';
|
||||
import useDiyStore from '@/app/stores/diy';
|
||||
import manifestJson from '@/manifest.json'
|
||||
|
||||
// 获取系统状态栏的高度
|
||||
let systemInfo = uni.getSystemInfoSync();
|
||||
let platform = systemInfo.platform;
|
||||
@ -68,15 +66,8 @@ let menuButtonInfo = {};
|
||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
||||
// #endif
|
||||
|
||||
import { ref, computed, watch, onMounted, getCurrentInstance, nextTick } from 'vue';
|
||||
import { img, getLocation, locationStorage } from '@/utils/common';
|
||||
import { getAddressByLatlng } from '@/app/api/system';
|
||||
import useSystemStore from '@/stores/system';
|
||||
import useDiyStore from '@/app/stores/diy';
|
||||
import manifestJson from '@/manifest.json'
|
||||
const diyStore = useDiyStore();
|
||||
|
||||
// param是一个对象{arrowLink => 箭头链接,isShowArrow => 箭头是否显示,tabbarBg => 背景颜色}
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
@ -92,9 +83,9 @@ const props = defineProps({
|
||||
type: Function,
|
||||
default: null
|
||||
},
|
||||
scrollTop: {
|
||||
scrollBool: {
|
||||
type: [String, Number],
|
||||
default: '0'
|
||||
default: -1
|
||||
},
|
||||
// 是否显示导航栏左边返回图标和辅助文字
|
||||
isBack: {
|
||||
@ -148,32 +139,50 @@ const styleOneFontSize = computed(() => {
|
||||
} else if (platform === 'android') {
|
||||
// 安卓(Android)设备
|
||||
style += 'font-size: 36rpx;';
|
||||
style += 'font-weight: 500;';
|
||||
}
|
||||
// #endif
|
||||
style += `color: ${topStatusBarData.value.textColor};`;
|
||||
style += `color: ${titleTextColor.value};`;
|
||||
if(topStatusBarData.value.style == 'style-1'){
|
||||
style += `text-align: ${topStatusBarData.value.textAlign};`;
|
||||
}
|
||||
return style;
|
||||
})
|
||||
|
||||
const bgColor = computed(() => {
|
||||
var color = '';
|
||||
if (topStatusBarData.value.isTransparent) {
|
||||
// 顶部透明
|
||||
color = 'transparent';
|
||||
if (props.scrollTop) {
|
||||
color = topStatusBarData.value.bgColor;
|
||||
} else {
|
||||
color = 'transparent';
|
||||
}
|
||||
const titleTextColor = computed(()=>{
|
||||
let color = '';
|
||||
if (props.scrollBool == 1) {
|
||||
color = topStatusBarData.value.rollTextColor;
|
||||
} else {
|
||||
color = '#fff';
|
||||
color = topStatusBarData.value.textColor;
|
||||
}
|
||||
|
||||
return color;
|
||||
})
|
||||
|
||||
const bgColor = computed(() => {
|
||||
let color = '';
|
||||
if (props.scrollBool == 1) {
|
||||
color = topStatusBarData.value.rollBgColor;
|
||||
} else {
|
||||
color = topStatusBarData.value.bgColor;
|
||||
}
|
||||
return color;
|
||||
})
|
||||
|
||||
/******************************* 存储滚动值-start ***********************/
|
||||
// 键名和组件名一致即可
|
||||
let componentsScrollVal = uni.getStorageSync('componentsScrollValGroup')
|
||||
if(componentsScrollVal){
|
||||
componentsScrollVal.TopTabbar = 0
|
||||
uni.setStorageSync('componentsScrollValGroup', componentsScrollVal);
|
||||
}else{
|
||||
let obj = {
|
||||
TopTabbar: 0
|
||||
}
|
||||
uni.setStorageSync('componentsScrollValGroup', obj);
|
||||
}
|
||||
/******************************* 存储滚动值-end ***********************/
|
||||
|
||||
/******************************* 返回按钮-start ***********************/
|
||||
let isBackShow = ref(false);
|
||||
let pages = getCurrentPages();
|
||||
@ -309,29 +318,6 @@ const getQueryVariable = (variable:any)=> {
|
||||
}
|
||||
/******************************* 定位-end ***********************/
|
||||
|
||||
/******************************* 风格五-start ***********************/
|
||||
let style5Height = ref('')
|
||||
watch(() => topStatusBarData.value.style, (nval, oval)=> {
|
||||
if(topStatusBarData.value.style == 'style-5'){
|
||||
style5Height.value = '';
|
||||
if(data.value.imgWidth && data.value.imgHeight) {
|
||||
let sysWidth = systemInfo.windowWidth
|
||||
let sysHeight = sysWidth / data.value.imgWidth * data.value.imgHeight
|
||||
style5Height.value += `width:100%;`
|
||||
// #ifdef H5
|
||||
sysHeight = sysHeight - 88; //使用图片高度减去88
|
||||
style5Height.value += `padding-top:${ sysHeight }px;`
|
||||
style5Height.value += `height:0;` //h5需要去掉兼容微信胶囊的高度
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
sysHeight = sysHeight - menuButtonInfo.top - menuButtonInfo.height - 5; //图片高度减去兼容小程序头部的高度[胶囊高度、padding-bottom、padding-top]
|
||||
style5Height.value += `padding-top:${ sysHeight }px;`
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
},{immediate: true, deep:true})
|
||||
/******************************* 风格五-end ***********************/
|
||||
|
||||
onMounted(() => {
|
||||
navbarPlaceholderHeight();
|
||||
if (pages.length > 1) {
|
||||
@ -349,10 +335,8 @@ const refresh = ()=>{
|
||||
}
|
||||
}
|
||||
|
||||
// 表示该组件,需要判断滚动超出1时,需要做相对应反应
|
||||
defineExpose({
|
||||
refresh,
|
||||
scrollValue: 1
|
||||
refresh
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -368,7 +352,6 @@ defineExpose({
|
||||
.u-navbar {
|
||||
width: 100%;
|
||||
transition: background 0.3s;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
@ -511,6 +494,7 @@ defineExpose({
|
||||
margin: 0 10rpx;
|
||||
max-width: 360rpx;
|
||||
font-size: 27rpx;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.nearby-store-name {
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
const agree = ref(false)
|
||||
const showPop = ref(false)
|
||||
const privacyAuthorization = ref(null)
|
||||
const privacyAuthorization: any = ref(null)
|
||||
|
||||
const privacyResolves = new Set()
|
||||
const closeOtherPagePopUpHooks = new Set()
|
||||
@ -33,9 +33,9 @@
|
||||
const emits = defineEmits(['agree','disagree'])
|
||||
|
||||
// 监听何时需要提示用户阅读隐私政策
|
||||
const init = ()=>{
|
||||
const init = ()=> {
|
||||
if (wx.onNeedPrivacyAuthorization) {
|
||||
wx.onNeedPrivacyAuthorization((resolve) => {
|
||||
wx.onNeedPrivacyAuthorization((resolve: any) => {
|
||||
if (typeof privacyAuthorization.value === 'function') {
|
||||
privacyAuthorization.value(resolve)
|
||||
}
|
||||
@ -45,7 +45,7 @@
|
||||
|
||||
//初始化监听程序
|
||||
const curPageShow = ()=> {
|
||||
privacyAuthorization.value = resolve => {
|
||||
privacyAuthorization.value = (resolve: any) => {
|
||||
privacyResolves.add(resolve)
|
||||
//打开弹窗
|
||||
popUp()
|
||||
@ -56,7 +56,7 @@
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
//查询微信侧记录的用户是否有待同意的隐私政策信息
|
||||
// 查询微信侧记录的用户是否有待同意的隐私政策信息
|
||||
try {
|
||||
wx.getPrivacySetting({
|
||||
success(res:any) {
|
||||
@ -72,7 +72,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
//打开隐私协议
|
||||
// 打开隐私协议
|
||||
const openPrivacyContract = ()=> {
|
||||
wx.openPrivacyContract({
|
||||
success(res) {
|
||||
@ -95,15 +95,15 @@
|
||||
|
||||
// 不同意
|
||||
const handleDisagree = ()=> {
|
||||
privacyResolves.forEach(resolve => {
|
||||
privacyResolves.forEach((resolve: any) => {
|
||||
resolve({
|
||||
event: 'disagree',
|
||||
})
|
||||
})
|
||||
privacyResolves.clear()
|
||||
//关闭弹窗
|
||||
// 关闭弹窗
|
||||
disPopUp()
|
||||
//退出小程序
|
||||
// 退出小程序
|
||||
uni.showModal({
|
||||
content: '未同意隐私协议,无法使用相关功能',
|
||||
confirmColor: useConfigStore().themeColor['--primary-color'],
|
||||
@ -115,7 +115,7 @@
|
||||
|
||||
// 同意并继续
|
||||
const handleAgree = ()=> {
|
||||
privacyResolves.forEach(resolve => {
|
||||
privacyResolves.forEach((resolve: any) => {
|
||||
resolve({
|
||||
event: 'agree',
|
||||
buttonId: 'agree-btn'
|
||||
@ -127,24 +127,25 @@
|
||||
emits('agree')
|
||||
}
|
||||
|
||||
//打开弹窗
|
||||
// 打开弹窗
|
||||
const popUp = ()=> {
|
||||
if (showPop.value === false) {
|
||||
showPop.value = true
|
||||
}
|
||||
}
|
||||
|
||||
//关闭弹窗
|
||||
// 关闭弹窗
|
||||
const disPopUp = ()=> {
|
||||
if (showPop.value === true) {
|
||||
showPop.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 主动打开协议弹出框(如果已经同意,则不会弹出)
|
||||
const proactive =()=> {
|
||||
if (wx.getPrivacySetting) {
|
||||
wx.getPrivacySetting({
|
||||
success: (res) => {
|
||||
success: (res: any) => {
|
||||
if (res.needAuthorization) {
|
||||
popUp()
|
||||
// 额外逻辑:当前页面的隐私弹窗弹起的时候,关掉其他页面的隐私弹窗
|
||||
@ -158,6 +159,10 @@
|
||||
emits('agree')
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
proactive
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {ref, reactive, computed} from 'vue';
|
||||
import {onLoad, onShow, onPullDownRefresh, onPageScroll} from '@dcloudio/uni-app';
|
||||
import {img, handleOnloadParams} from '@/utils/common';
|
||||
import {getDiyInfo} from '@/app/api/diy';
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
import { onLoad, onShow, onPullDownRefresh, onPageScroll, onUnload } from '@dcloudio/uni-app';
|
||||
import { img, handleOnloadParams } from '@/utils/common';
|
||||
import { getDiyInfo } from '@/app/api/diy';
|
||||
import useDiyStore from '@/app/stores/diy';
|
||||
|
||||
export function useDiy(params: any = {}) {
|
||||
@ -33,31 +33,25 @@ export function useDiy(params: any = {}) {
|
||||
return diyData;
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const isShowTopTabbar = ref(false);
|
||||
|
||||
const pageStyle = () => {
|
||||
var style = '';
|
||||
if (data.value.global.pageStartBgColor) {
|
||||
if (data.value.global.pageStartBgColor && data.value.global.pageEndBgColor) style += `background:linear-gradient(${data.value.global.pageGradientAngle},${data.value.global.pageStartBgColor},${data.value.global.pageEndBgColor});`;
|
||||
if (data.value.global.pageStartBgColor && data.value.global.pageEndBgColor) style += `background:linear-gradient(${ data.value.global.pageGradientAngle },${ data.value.global.pageStartBgColor },${ data.value.global.pageEndBgColor });`;
|
||||
else style += 'background-color:' + data.value.global.pageStartBgColor + ';';
|
||||
}
|
||||
|
||||
style += 'min-height:calc(100vh - 50px);';
|
||||
if (data.value.global.bgUrl) {
|
||||
style += `background-image:url('${img(data.value.global.bgUrl)}');`;
|
||||
style += `background-image:url('${ img(data.value.global.bgUrl) }');`;
|
||||
}
|
||||
|
||||
if (data.value.global.bgHeightScale) {
|
||||
style += `background-size: 100% ${data.value.global.bgHeightScale}%;`;
|
||||
style += `background-size: 100% ${ data.value.global.bgHeightScale }%;`;
|
||||
}
|
||||
|
||||
// #ifdef H5
|
||||
// 导航栏风格五 - 兼容
|
||||
if(data.value.global && data.value.global.topStatusBar && data.value.global.topStatusBar.style == "style-5"){
|
||||
style += `background-position-y: -176rpx;`;
|
||||
}
|
||||
// #endif
|
||||
|
||||
return style;
|
||||
};
|
||||
|
||||
@ -106,7 +100,7 @@ export function useDiy(params: any = {}) {
|
||||
diyData.value.forEach((item: any, index) => {
|
||||
item.pageStyle = '';
|
||||
if (item.pageStartBgColor) {
|
||||
if (item.pageStartBgColor && item.pageEndBgColor) item.pageStyle += `background:linear-gradient(${item.pageGradientAngle},${item.pageStartBgColor},${item.pageEndBgColor});`;
|
||||
if (item.pageStartBgColor && item.pageEndBgColor) item.pageStyle += `background:linear-gradient(${ item.pageGradientAngle },${ item.pageStartBgColor },${ item.pageEndBgColor });`;
|
||||
else item.pageStyle += 'background-color:' + item.pageStartBgColor + ';';
|
||||
}
|
||||
|
||||
@ -141,6 +135,14 @@ export function useDiy(params: any = {}) {
|
||||
})
|
||||
}
|
||||
|
||||
// 监听页面卸载
|
||||
const onUnloadLifeCycle = () => {
|
||||
onUnload(() => {
|
||||
// 兼容轮播搜索组件-切换分类时,导致个人中心白屏
|
||||
diyStore.topFixedStatus = 'home'
|
||||
})
|
||||
}
|
||||
|
||||
// 监听下拉刷新事件
|
||||
const onPullDownRefreshLifeCycle = () => {
|
||||
onPullDownRefresh(() => {
|
||||
@ -166,6 +168,7 @@ export function useDiy(params: any = {}) {
|
||||
pageStyle,
|
||||
onLoad: onLoadLifeCycle,
|
||||
onShow: onShowLifeCycle,
|
||||
onUnload: onUnloadLifeCycle,
|
||||
onPullDownRefresh: onPullDownRefreshLifeCycle,
|
||||
onPageScroll: onPageScrollLifeCycle,
|
||||
}
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
import { redirect, isWeixinBrowser, urlDeconstruction } from '@/utils/common'
|
||||
import { weappLogin, wechatLogin, wechatUser, wechatUserLogin } from '@/app/api/auth'
|
||||
import {
|
||||
weappLogin,
|
||||
updateWeappOpenid,
|
||||
wechatLogin,
|
||||
updateWechatOpenid,
|
||||
wechatUser,
|
||||
wechatUserLogin
|
||||
} from '@/app/api/auth'
|
||||
import { getWechatAuthCode } from '@/app/api/system'
|
||||
import useMemberStore from '@/stores/member'
|
||||
import useConfigStore from '@/stores/config'
|
||||
@ -8,20 +15,20 @@ export function useLogin() {
|
||||
/**
|
||||
* 设置登录返回页
|
||||
*/
|
||||
const setLoginBack = (data : redirectOptions) => {
|
||||
const setLoginBack = (data: redirectOptions) => {
|
||||
uni.setStorage({ key: 'loginBack', data })
|
||||
setTimeout(() => {
|
||||
const config = useConfigStore()
|
||||
// #ifdef MP-WEIXIN
|
||||
if (!uni.getStorageSync('autoLoginLock') && uni.getStorageSync('openid') && config.login.is_bind_mobile) {
|
||||
redirect({ url: '/app/pages/auth/bind', mode: 'redirectTo' })
|
||||
uni.setStorageSync('isbindmobile', true)
|
||||
return
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
if (!uni.getStorageSync('autoLoginLock') && isWeixinBrowser() && uni.getStorageSync('openid') && config.login.is_bind_mobile) {
|
||||
redirect({ url: '/app/pages/auth/bind', mode: 'redirectTo' })
|
||||
uni.setStorageSync('isbindmobile', true)
|
||||
return
|
||||
}
|
||||
// #endif
|
||||
@ -36,7 +43,7 @@ export function useLogin() {
|
||||
uni.removeStorageSync('autoLoginLock')
|
||||
uni.getStorage({
|
||||
key: 'loginBack',
|
||||
success: (data : AnyObject) => {
|
||||
success: (data: AnyObject) => {
|
||||
data ? redirect(data.data) : redirect({ url: '/app/pages/index/index', mode: 'switchTab' })
|
||||
},
|
||||
fail: (res) => {
|
||||
@ -48,57 +55,114 @@ export function useLogin() {
|
||||
/**
|
||||
* 授权登录
|
||||
*/
|
||||
const authLogin = (code : string | null) => {
|
||||
let obj = {};
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
obj.code = code;
|
||||
uni.getStorageSync('pid') && (Object.assign(obj, { pid: uni.getStorageSync('pid') }))
|
||||
weappLogin(obj).then((res : AnyObject) => {
|
||||
if (res.data.token) {
|
||||
useMemberStore().setToken(res.data.token)
|
||||
setTimeout(() => {
|
||||
const memberInfo = useMemberStore().info
|
||||
memberInfo && memberInfo.weapp_openid && uni.setStorageSync('openid', memberInfo.weapp_openid)
|
||||
}, 1000)
|
||||
} else {
|
||||
uni.setStorageSync('openid', res.data.openid)
|
||||
uni.setStorageSync('unionid', res.data.unionid)
|
||||
}
|
||||
})
|
||||
const authLogin = (code: string | null,backFlag = false,callback: any = null) => {
|
||||
let obj = {};
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
obj.code = code;
|
||||
uni.getStorageSync('pid') && (Object.assign(obj, { pid: uni.getStorageSync('pid') }))
|
||||
weappLogin(obj).then((res: AnyObject) => {
|
||||
if (res.data.token) {
|
||||
useMemberStore().setToken(res.data.token)
|
||||
const config = useConfigStore()
|
||||
setTimeout(() => {
|
||||
const memberInfo = useMemberStore().info
|
||||
memberInfo && memberInfo.weapp_openid && uni.setStorageSync('openid', memberInfo.weapp_openid)
|
||||
// 开启绑定手机号标识
|
||||
if (uni.getStorageSync('isbindmobile')) {
|
||||
uni.removeStorageSync('isbindmobile');
|
||||
}
|
||||
if (config.login.is_bind_mobile && memberInfo && !memberInfo.mobile) {
|
||||
uni.setStorageSync('isbindmobile', true)
|
||||
}
|
||||
if(backFlag) handleLoginBack() //一键登录返回
|
||||
}, 1000)
|
||||
} else {
|
||||
uni.setStorageSync('openid', res.data.openid)
|
||||
uni.setStorageSync('unionid', res.data.unionid)
|
||||
if(callback) callback({
|
||||
openid: uni.getStorageSync('openid'),
|
||||
unionid: uni.getStorageSync('unionid')
|
||||
})
|
||||
}
|
||||
}).catch((err) => {
|
||||
uni.showToast({ title: err.msg, icon: 'none' })
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
obj.code = code;
|
||||
uni.getStorageSync('pid') && (Object.assign(obj, { pid: uni.getStorageSync('pid') }))
|
||||
wechatUser(obj).then((user_res : AnyObject) => {
|
||||
if(user_res.data){
|
||||
wechatUserLogin(user_res.data).then((res : AnyObject) => {
|
||||
if (res.data.token) {
|
||||
useMemberStore().setToken(res.data.token)
|
||||
setTimeout(() => {
|
||||
const memberInfo = useMemberStore().info
|
||||
memberInfo && memberInfo.wx_openid && uni.setStorageSync('openid', memberInfo.wx_openid)
|
||||
}, 1000)
|
||||
} else {
|
||||
uni.setStorageSync('openid', res.data.openid)
|
||||
uni.setStorageSync('unionid', res.data.unionid)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
obj.code = code;
|
||||
uni.getStorageSync('pid') && (Object.assign(obj, { pid: uni.getStorageSync('pid') }))
|
||||
wechatUser(obj).then((user_res: AnyObject) => {
|
||||
if (user_res.data) {
|
||||
wechatUserLogin(user_res.data).then((res: AnyObject) => {
|
||||
if (res.data.token) {
|
||||
useMemberStore().setToken(res.data.token)
|
||||
const config = useConfigStore()
|
||||
setTimeout(() => {
|
||||
const memberInfo = useMemberStore().info
|
||||
memberInfo && memberInfo.wx_openid && uni.setStorageSync('openid', memberInfo.wx_openid)
|
||||
// 开启绑定手机号标识
|
||||
if (uni.getStorageSync('isbindmobile')) {
|
||||
uni.removeStorageSync('isbindmobile');
|
||||
}
|
||||
if (config.login.is_bind_mobile && memberInfo && !memberInfo.mobile) {
|
||||
uni.setStorageSync('isbindmobile', true)
|
||||
}
|
||||
}, 1000)
|
||||
} else {
|
||||
uni.setStorageSync('openid', res.data.openid)
|
||||
uni.setStorageSync('unionid', res.data.unionid)
|
||||
}
|
||||
})
|
||||
}
|
||||
}).catch((err) => {
|
||||
if (err.msg == -1) {
|
||||
getAuthCode('snsapi_userinfo')
|
||||
} else {
|
||||
uni.showToast({ title: err.msg, icon: 'none' })
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
/**
|
||||
* 登录普通账号后修改openid
|
||||
*/
|
||||
const updateOpenid = (code: string | null) => {
|
||||
let obj = {};
|
||||
// #ifdef MP-WEIXIN
|
||||
obj.code = code;
|
||||
updateWeappOpenid(obj).then((res) => {
|
||||
useMemberStore().getMemberInfo()
|
||||
setTimeout(() => {
|
||||
const memberInfo = useMemberStore().info
|
||||
memberInfo && memberInfo.weapp_openid && uni.setStorageSync('openid', memberInfo.weapp_openid)
|
||||
}, 1000)
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
obj.code = code;
|
||||
updateWechatOpenid(obj).then((res) => {
|
||||
useMemberStore().getMemberInfo()
|
||||
setTimeout(() => {
|
||||
const memberInfo = useMemberStore().info
|
||||
memberInfo && memberInfo.wx_openid && uni.setStorageSync('openid', memberInfo.wx_openid)
|
||||
}, 1000)
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
/**
|
||||
* 获取授权码
|
||||
* updateFlag:更新oppenid
|
||||
* backFlag 控制一键登录返回
|
||||
*/
|
||||
const getAuthCode = (scopes : 'snsapi_base' | 'snsapi_userinfo' = 'snsapi_base') => {
|
||||
const getAuthCode = (scopes: '' | 'snsapi_base' | 'snsapi_userinfo' = 'snsapi_base', updateFlag: boolean = false, backFlag: boolean = false,callback = null) => {
|
||||
// #ifdef MP-WEIXIN
|
||||
wx.login({
|
||||
success(res) {
|
||||
if (res.code) {
|
||||
authLogin(res.code)
|
||||
updateFlag ? updateOpenid(res.code) : authLogin(res.code,backFlag,callback)
|
||||
} else {
|
||||
console.log('登录失败!' + res.errMsg)
|
||||
}
|
||||
@ -107,7 +171,7 @@ export function useLogin() {
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
let url = `${location.origin}${location.pathname}`
|
||||
let url = `${ location.origin }${ location.pathname }`
|
||||
let query = urlDeconstruction(location.href).query
|
||||
query.code && (delete query.code)
|
||||
Object.keys(query).length && (url += uni.$u.queryParams(query))
|
||||
@ -115,7 +179,7 @@ export function useLogin() {
|
||||
getWechatAuthCode({
|
||||
url,
|
||||
scopes
|
||||
}).then((res : AnyObject) => {
|
||||
}).then((res: AnyObject) => {
|
||||
location.href = res.data.url
|
||||
})
|
||||
// #endif
|
||||
@ -125,6 +189,7 @@ export function useLogin() {
|
||||
setLoginBack,
|
||||
handleLoginBack,
|
||||
authLogin,
|
||||
updateOpenid,
|
||||
getAuthCode
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,39 +5,39 @@ import { sendSms } from '@/app/api/system'
|
||||
export function useSendSms(smsRef: AnyObject | null) {
|
||||
const tips = ref(t('getSmsCode'))
|
||||
const seconds = 90
|
||||
const changeText = 'X' + t('smsCodeChangeText')
|
||||
|
||||
const canGetCode = computed(() =>{
|
||||
const changeText = 'X' + t('smsCodeChangeText')
|
||||
|
||||
const canGetCode = computed(() => {
|
||||
return smsRef.value ? smsRef.value.canGetCode : true
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* 发送短信
|
||||
*/
|
||||
const send = async (param:requestMobileParam) => {
|
||||
const send = async(param: requestMobileParam) => {
|
||||
if (!canGetCode.value) return
|
||||
|
||||
|
||||
smsRef.value.start()
|
||||
|
||||
|
||||
let result: string | boolean = false
|
||||
await sendSms(param).then(res=>{
|
||||
await sendSms(param).then(res => {
|
||||
if (res.code == 1) {
|
||||
result = res.data.key
|
||||
} else {
|
||||
smsRef.value.reset()
|
||||
result = false
|
||||
}
|
||||
}).catch(err=>{
|
||||
}).catch(err => {
|
||||
result = false
|
||||
smsRef.value.reset()
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
const codeChange = (text: string)=>{
|
||||
|
||||
const codeChange = (text: string) => {
|
||||
tips.value = text
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
tips: tips,
|
||||
seconds,
|
||||
|
||||
@ -7,138 +7,139 @@ import wechat from '@/utils/wechat'
|
||||
// #endif
|
||||
|
||||
export const useShare = () => {
|
||||
var wechatOptions: any = {};
|
||||
var wechatOptions: any = {};
|
||||
|
||||
var weappOptions:any = {};
|
||||
var weappOptions: any = {};
|
||||
|
||||
const wechatInit = () => {
|
||||
if (!isWeixinBrowser()) return;
|
||||
// 初始化sdk
|
||||
wechat.init();
|
||||
}
|
||||
const wechatInit = () => {
|
||||
if (!isWeixinBrowser()) return;
|
||||
// 初始化sdk
|
||||
wechat.init();
|
||||
}
|
||||
|
||||
// 微信公众号分享
|
||||
const wechatShare = () => {
|
||||
if (!isWeixinBrowser()) return;
|
||||
wechat.share(wechatOptions);
|
||||
}
|
||||
// 微信公众号分享
|
||||
const wechatShare = () => {
|
||||
if (!isWeixinBrowser()) return;
|
||||
wechat.share(wechatOptions);
|
||||
}
|
||||
|
||||
const getQuery = ()=>{
|
||||
let query:any = currShareRoute().params;
|
||||
let wap_member_id = uni.getStorageSync('wap_member_id');
|
||||
if (wap_member_id) {
|
||||
query.mid = wap_member_id;
|
||||
}
|
||||
const getQuery = () => {
|
||||
let query: any = currShareRoute().params;
|
||||
let wap_member_id = uni.getStorageSync('wap_member_id');
|
||||
if (wap_member_id) {
|
||||
query.mid = wap_member_id;
|
||||
}
|
||||
|
||||
let queryStr = [];
|
||||
for (let key in query) {
|
||||
queryStr.push(key + '=' + query[key]);
|
||||
}
|
||||
let queryStr = [];
|
||||
for (let key in query) {
|
||||
queryStr.push(key + '=' + query[key]);
|
||||
}
|
||||
|
||||
return queryStr
|
||||
return queryStr
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const setShare = (options : any = {}) => {
|
||||
if(currRoute() == '' || currRoute().indexOf('app/pages/index/close') != -1 || currRoute().indexOf('app/pages/index/nosite') != -1) return;
|
||||
const setShare = (options: any = {}) => {
|
||||
if (currRoute() == '' || currRoute().indexOf('app/pages/index/close') != -1 || currRoute().indexOf('app/pages/index/nosite') != -1) return;
|
||||
|
||||
let queryStr = getQuery();
|
||||
let queryStr = getQuery();
|
||||
|
||||
// #ifdef H5
|
||||
// #ifdef H5
|
||||
|
||||
let h5Link = location.origin + location.pathname + (queryStr.length > 0 ? '?' + queryStr.join('&') : '');
|
||||
let h5Link = location.origin + location.pathname + (queryStr.length > 0 ? '?' + queryStr.join('&') : '');
|
||||
|
||||
wechatOptions = {
|
||||
link: h5Link
|
||||
}
|
||||
wechatOptions = {
|
||||
link: h5Link
|
||||
}
|
||||
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
weappOptions = {
|
||||
path: '/' + currRoute() + (queryStr.length > 0 ? '?' + queryStr.join('&') : ''),
|
||||
query: queryStr.join('&'),
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
weappOptions = {
|
||||
path: '/' + currRoute() + (queryStr.length > 0 ? '?' + queryStr.join('&') : ''),
|
||||
query: queryStr.join('&'),
|
||||
}
|
||||
// #endif
|
||||
|
||||
if (options && options.wechat && options.weapp) {
|
||||
if (options && options.wechat && options.weapp) {
|
||||
|
||||
// #ifdef H5
|
||||
wechatOptions.title = options.wechat.title || ''
|
||||
wechatOptions.link = options.wechat.link || h5Link
|
||||
wechatOptions.desc = options.wechat.desc || ''
|
||||
wechatOptions.imgUrl = options.wechat.url ? img(options.wechat.url) : ''
|
||||
wechatShare()
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
wechatOptions.title = options.wechat.title || ''
|
||||
wechatOptions.link = options.wechat.link || h5Link
|
||||
wechatOptions.desc = options.wechat.desc || ''
|
||||
wechatOptions.imgUrl = options.wechat.url ? img(options.wechat.url) : ''
|
||||
wechatShare()
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
weappOptions.title = options.weapp.title || ''
|
||||
weappOptions.query = options.weapp.path || queryStr.join('&')
|
||||
weappOptions.imageUrl = options.weapp.url ? img(options.weapp.url) : ''
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
weappOptions.title = options.weapp.title || ''
|
||||
weappOptions.query = options.weapp.path || queryStr.join('&')
|
||||
weappOptions.imageUrl = options.weapp.url ? img(options.weapp.url) : ''
|
||||
// #endif
|
||||
|
||||
} else {
|
||||
getShareInfo({
|
||||
route: '/' + currRoute(),
|
||||
params: JSON.stringify(currShareRoute().params)
|
||||
}).then((res: any) => {
|
||||
let data = res.data;
|
||||
uni.setStorageSync('weappOptions', weappOptions)
|
||||
} else {
|
||||
getShareInfo({
|
||||
route: '/' + currRoute(),
|
||||
params: JSON.stringify(currShareRoute().params)
|
||||
}).then((res: any) => {
|
||||
let data = res.data;
|
||||
|
||||
// #ifdef H5
|
||||
let wechat = data.wechat;
|
||||
if (wechat) {
|
||||
wechatOptions.title = wechat.title
|
||||
wechatOptions.desc = wechat.desc
|
||||
wechatOptions.imgUrl = wechat.url ? img(wechat.url) : ''
|
||||
}else{
|
||||
wechatOptions.title = document.title;
|
||||
wechatOptions.desc = ''
|
||||
}
|
||||
wechatShare()
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
let wechat = data.wechat;
|
||||
if (wechat) {
|
||||
wechatOptions.title = wechat.title
|
||||
wechatOptions.desc = wechat.desc
|
||||
wechatOptions.imgUrl = wechat.url ? img(wechat.url) : ''
|
||||
} else {
|
||||
wechatOptions.title = document.title;
|
||||
wechatOptions.desc = ''
|
||||
}
|
||||
wechatShare()
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
let weapp = data.weapp;
|
||||
if (weapp) {
|
||||
weappOptions.title = weapp.title
|
||||
weappOptions.imageUrl = weapp.url ? img(weapp.url) : ''
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
let weapp = data.weapp;
|
||||
if (weapp) {
|
||||
weappOptions.title = weapp.title
|
||||
weappOptions.imageUrl = weapp.url ? img(weapp.url) : ''
|
||||
}
|
||||
// #endif
|
||||
|
||||
})
|
||||
}
|
||||
uni.setStorageSync('weappOptions', weappOptions)
|
||||
}
|
||||
uni.setStorageSync('weappOptions', weappOptions)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 小程序分享,分享给好友
|
||||
const shareApp = (options = {}) => {
|
||||
onShareAppMessage(() => {
|
||||
let config:any= uni.getStorageSync('weappOptions')
|
||||
if(!config) config = {}
|
||||
return {
|
||||
...config,
|
||||
...options
|
||||
}
|
||||
})
|
||||
// 小程序分享,分享给好友
|
||||
const shareApp = (options = {}) => {
|
||||
onShareAppMessage(() => {
|
||||
let config: any = uni.getStorageSync('weappOptions')
|
||||
if (!config) config = {}
|
||||
return {
|
||||
...config,
|
||||
...options
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 小程序分享,分享到朋友圈
|
||||
const shareTime = (options = {}) => {
|
||||
onShareTimeline(() => {
|
||||
let config:any= uni.getStorageSync('weappOptions')
|
||||
if(!config) config = {}
|
||||
return {
|
||||
...config,
|
||||
...options
|
||||
}
|
||||
})
|
||||
}
|
||||
// 小程序分享,分享到朋友圈
|
||||
const shareTime = (options = {}) => {
|
||||
onShareTimeline(() => {
|
||||
let config: any = uni.getStorageSync('weappOptions')
|
||||
if (!config) config = {}
|
||||
return {
|
||||
...config,
|
||||
...options
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
wechatInit:wechatInit,
|
||||
setShare: setShare,
|
||||
onShareAppMessage: shareApp,
|
||||
onShareTimeline: shareTime,
|
||||
}
|
||||
return {
|
||||
wechatInit: wechatInit,
|
||||
setShare: setShare,
|
||||
onShareAppMessage: shareApp,
|
||||
onShareTimeline: shareTime,
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,11 +4,11 @@ import { getWeappTemplateId } from '@/app/api/system'
|
||||
* 小程序订阅消息
|
||||
*/
|
||||
export const useSubscribeMessage = () => {
|
||||
const request = (keys: string)=> {
|
||||
const request = (keys: string) => {
|
||||
// #ifdef MP-WEIXIN
|
||||
const method = getWeappTemplateId
|
||||
// #endif
|
||||
|
||||
|
||||
// #ifdef MP
|
||||
method(keys).then(({ data }) => {
|
||||
uni.requestSubscribeMessage({
|
||||
@ -23,7 +23,7 @@ export const useSubscribeMessage = () => {
|
||||
}).catch()
|
||||
// #endif
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
request
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
"pages.member.detailed_account": "流水明细",
|
||||
"pages.member.index": "",
|
||||
"pages.member.personal": "个人资料",
|
||||
"pages.member.contact": "客服",
|
||||
"pages.pay.browser": "支付",
|
||||
"pages.pay.result": "支付结果",
|
||||
"pages.setting.index": "设置",
|
||||
|
||||
@ -23,9 +23,19 @@
|
||||
"headimgPlaceholder": "请设置头像",
|
||||
"getAvatarNickname": "获取您的昵称头像",
|
||||
"getAvatarNicknameTips": "获取用户头像、昵称完善个人资料,主要用于向用户提供具有辨识度的用户中心界面",
|
||||
"mobile":"手机号",
|
||||
"getMobile":"获取手机号",
|
||||
"mobileTips":"请获取手机号",
|
||||
"point": "积分",
|
||||
"balance": "余额",
|
||||
"login": "登录",
|
||||
"bind": "绑定",
|
||||
"binding": "绑定中",
|
||||
"bindMobile": "绑定手机号",
|
||||
"agreeTips": "请阅读并同意",
|
||||
"pleaceAgree": "请勾选已阅读并同意",
|
||||
"weixinUserAuth": "一键绑定",
|
||||
"mobileQuickLogin": "手机号快捷登录",
|
||||
"register": "注册",
|
||||
"complete": "完成",
|
||||
"close": "关闭",
|
||||
@ -60,7 +70,6 @@
|
||||
"reserveSuccess": "预约成功",
|
||||
"cardLink": "次卡",
|
||||
"myLink": "我的",
|
||||
"siteStatus": "站点状态",
|
||||
"reserveBtn": "去抢购",
|
||||
"cardBtn": "办理",
|
||||
"soldOut": "已售",
|
||||
|
||||
@ -217,6 +217,12 @@
|
||||
},
|
||||
"needLogin": true
|
||||
},
|
||||
{
|
||||
"path": "app/pages/member/contact",
|
||||
"style": {
|
||||
"navigationBarTitleText": "%pages.member.contact%"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "app/pages/pay/browser",
|
||||
"style": {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { getConfig } from '@/app/api/auth'
|
||||
import { getTabbarList } from '@/app/api/diy'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
interface loginConfig {
|
||||
is_username: number | boolean,
|
||||
@ -20,10 +19,10 @@ interface tabbarConfig {
|
||||
|
||||
interface Config {
|
||||
login: loginConfig,
|
||||
tabbarList:any,
|
||||
tabbarList: any,
|
||||
tabbar: tabbarConfig | null,
|
||||
addon: String,
|
||||
themeColor:any
|
||||
themeColor: any
|
||||
}
|
||||
|
||||
const useConfigStore = defineStore('config', {
|
||||
@ -36,10 +35,10 @@ const useConfigStore = defineStore('config', {
|
||||
is_bind_mobile: 0,
|
||||
agreement_show: 0
|
||||
},
|
||||
tabbarList:{},
|
||||
tabbarList: {},
|
||||
tabbar: null,
|
||||
addon: '',
|
||||
themeColor:''
|
||||
themeColor: ''
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
@ -54,9 +53,9 @@ const useConfigStore = defineStore('config', {
|
||||
})
|
||||
},
|
||||
async getTabbarConfig() {
|
||||
await getTabbarList({}).then((res:any)=>{
|
||||
await getTabbarList({}).then((res: any) => {
|
||||
this.tabbarList = res.data;
|
||||
}).catch(()=>{
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
// 获取主色调
|
||||
@ -68,7 +67,7 @@ const useConfigStore = defineStore('config', {
|
||||
if (this.themeColor) {
|
||||
let style = '';
|
||||
for (let k in this.themeColor) {
|
||||
style += `${k}:${this.themeColor[k]};`;
|
||||
style += `${ k }:${ this.themeColor[k] };`;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { setToken, removeToken, redirect } from '@/utils/common'
|
||||
import { getMemberInfo,getMemberLevel } from '@/app/api/member'
|
||||
import { getMemberInfo, getMemberLevel } from '@/app/api/member'
|
||||
import { logout } from '@/app/api/auth'
|
||||
|
||||
import useConfigStore from '@/stores/config'
|
||||
interface Member {
|
||||
token : string | null
|
||||
info : AnyObject | null
|
||||
levelList : Array<any> | null
|
||||
token: string | null
|
||||
info: AnyObject | null
|
||||
levelList: Array<any> | null
|
||||
}
|
||||
|
||||
const useMemberStore = defineStore('member', {
|
||||
state: () : Member => {
|
||||
state: (): Member => {
|
||||
return {
|
||||
token: uni.getStorageSync(import.meta.env.VITE_REQUEST_STORAGE_TOKEN_KEY),
|
||||
info: null,
|
||||
levelList:null
|
||||
levelList: null
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
async setToken(token : string) {
|
||||
async setToken(token: string) {
|
||||
this.token = token
|
||||
setToken(token)
|
||||
await this.getMemberInfo()
|
||||
@ -27,32 +27,38 @@ const useMemberStore = defineStore('member', {
|
||||
if (!this.token) return
|
||||
await getMemberInfo().then((res: any) => {
|
||||
this.info = res.data
|
||||
uni.setStorageSync('wap_member_info',this.info)
|
||||
uni.setStorageSync('wap_member_id',res.data.member_id)
|
||||
}).catch(async () => {
|
||||
uni.setStorageSync('wap_member_info', this.info)
|
||||
uni.setStorageSync('wap_member_id', res.data.member_id)
|
||||
}).catch(async() => {
|
||||
await this.logout()
|
||||
})
|
||||
},
|
||||
async logout(isRedirect : boolean = false) {
|
||||
async logout(isRedirect: boolean = false) {
|
||||
if (!this.token) return
|
||||
this.token = ''
|
||||
this.info = null
|
||||
uni.setStorageSync('autoLoginLock', true)
|
||||
if(useConfigStore().login.is_auth_register){
|
||||
uni.setStorageSync('autoLoginLock', true) // todo 普通账号退出登录,在进行三方账号登录不会自动登录
|
||||
}
|
||||
await logout().then(() => {
|
||||
removeToken()
|
||||
uni.removeStorageSync('wap_member_info');
|
||||
uni.removeStorageSync('openid');
|
||||
uni.removeStorageSync('isbindmobile');
|
||||
isRedirect && redirect({ url: '/app/pages/index/index', mode: 'switchTab' })
|
||||
}).catch(() => {
|
||||
removeToken()
|
||||
uni.removeStorageSync('wap_member_info');
|
||||
uni.removeStorageSync('openid');
|
||||
uni.removeStorageSync('isbindmobile');
|
||||
isRedirect && redirect({ url: '/app/pages/index/index', mode: 'switchTab' })
|
||||
})
|
||||
},
|
||||
getMemberLevel(){
|
||||
getMemberLevel().then((res:any)=>{
|
||||
this.levelList = res.data
|
||||
})
|
||||
}
|
||||
getMemberLevel() {
|
||||
getMemberLevel().then((res: any) => {
|
||||
this.levelList = res.data
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { getSiteInfo, getMap } from '@/app/api/system'
|
||||
import { redirect } from '@/utils/common'
|
||||
|
||||
interface System {
|
||||
site: AnyObject | null,
|
||||
|
||||
@ -4,9 +4,10 @@
|
||||
--primary-color-disabled: #9acafc;
|
||||
--primary-color-light: #ecf5ff;
|
||||
--page-bg-color: #f7f7f7;
|
||||
--sidebar-m: 20rpx;
|
||||
--rounded-angle: 16rpx;
|
||||
}
|
||||
|
||||
// 字体设置
|
||||
// 价格字体设置
|
||||
@font-face {
|
||||
font-family: 'myFont';
|
||||
/* #ifdef MP */
|
||||
@ -16,10 +17,10 @@
|
||||
src: url('@/styles/custom.ttf') format('truetype');
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.price-font{
|
||||
font-family: 'myFont','-apple-system', 'BlinkMacSystemFont', 'Helvetica Neue', 'Helvetica', 'Segoe UI', 'Arial', 'Roboto', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft Yahei','sans-serif';
|
||||
}
|
||||
}
|
||||
|
||||
// 全局基础样式
|
||||
uni-page-body {
|
||||
line-height: 1.8;
|
||||
@ -42,6 +43,72 @@ button[type='primary'],uni-button[type='primary']{
|
||||
background-color: var(--primary-color) !important;
|
||||
}
|
||||
|
||||
// 提交按钮背景颜色
|
||||
.primary-btn-bg{
|
||||
background: linear-gradient( 94deg, #FB7939 0%, #FE120E 99%), #EF000C;
|
||||
}
|
||||
// 侧边栏宽度
|
||||
.sidebar-marign{
|
||||
margin-left: var(--sidebar-m) !important;
|
||||
margin-right: var(--sidebar-m) !important;
|
||||
}
|
||||
// 圆角
|
||||
.rounded-angle{
|
||||
border-radius: var(--rounded-angle);
|
||||
}
|
||||
// 卡片模块
|
||||
.card-template{
|
||||
padding: 30rpx;
|
||||
border-radius: var(--rounded-angle);
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// 适用于左边tab切换,右边是日期;参考页面如:我的佣金、销售奖励
|
||||
.tab-style-1{
|
||||
@apply box-border flex items-center justify-between;
|
||||
padding: 0 var(--sidebar-m) 20rpx;
|
||||
.tab-left{
|
||||
@apply flex whitespace-nowrap;
|
||||
.tab-left-item{
|
||||
@apply font-400;
|
||||
margin-left: 0;
|
||||
margin-right: 40rpx;
|
||||
color: #626779;
|
||||
line-height: 40rpx;
|
||||
font-size: 28rpx;
|
||||
&.class-select{
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
color: var(--primary-color);
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -14rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 100rpx;
|
||||
background-color: var(--primary-color);
|
||||
width: 40rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tab-right{
|
||||
@apply flex items-center;
|
||||
.tab-right-date{
|
||||
font-size: 28rpx !important;
|
||||
color: #333;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.tab-right-icon{
|
||||
font-size: 30rpx !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 单行超出隐藏 */
|
||||
.using-hidden {
|
||||
word-break: break-all;
|
||||
@ -105,3 +172,14 @@ button[type='primary'],uni-button[type='primary']{
|
||||
color: #999;
|
||||
}
|
||||
/****************** u-cell-end *********************/
|
||||
|
||||
/******************** u-toolbar__wrapper__confirm start **********************/
|
||||
.u-toolbar__wrapper__confirm{
|
||||
color: var(--primary-color) !important;
|
||||
}
|
||||
/******************** u-toolbar__wrapper__confirm end **********************/
|
||||
/******************** 物流 state **********************/
|
||||
.u-steps-item__line.u-steps-item__line--column{
|
||||
height:100% !important;
|
||||
}
|
||||
/******************** 物流 state **********************/
|
||||
@ -2,7 +2,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
background-size: contain;
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat !important;
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 3952239 */
|
||||
src: url('//at.alicdn.com/t/c/font_3952239_da988xfzfy9.woff2?t=1718609129756') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_3952239_da988xfzfy9.woff?t=1718609129756') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_3952239_da988xfzfy9.ttf?t=1718609129756') format('truetype');
|
||||
src: url('//at.alicdn.com/t/c/font_3952239_mvhdfb735e.woff2?t=1719994029682') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_3952239_mvhdfb735e.woff?t=1719994029682') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_3952239_mvhdfb735e.ttf?t=1719994029682') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -13,6 +13,30 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconyouV6xx:before {
|
||||
content: "\e648";
|
||||
}
|
||||
|
||||
.iconguanzhuV6xx:before {
|
||||
content: "\e79b";
|
||||
}
|
||||
|
||||
.iconxihuanV6mm:before {
|
||||
content: "\e691";
|
||||
}
|
||||
|
||||
.iconfapiao:before {
|
||||
content: "\e86b";
|
||||
}
|
||||
|
||||
.iconlishijiluV6xx:before {
|
||||
content: "\e6f6";
|
||||
}
|
||||
|
||||
.iconchaochangyoujiantouV6xx:before {
|
||||
content: "\e6fc";
|
||||
}
|
||||
|
||||
.iconyuanhu:before {
|
||||
content: "\e644";
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.member-record-list{
|
||||
@apply min-h-[100vh];
|
||||
.member-record-item{
|
||||
@apply relative mx-4 border-solid border-t-0 border-l-0 border-r-0 border-b-1 border-[#ECEBEC] py-3;
|
||||
@apply relative sidebar-marign border-solid border-t-0 border-l-0 border-r-0 border-b-1 border-[#ECEBEC] py-3 mx-[var(--sidebar-m)];
|
||||
.name{
|
||||
@apply text-sm;
|
||||
}
|
||||
@ -12,10 +12,10 @@
|
||||
color: #FF0D3E;
|
||||
}
|
||||
.money{
|
||||
@apply absolute right-3 top-4 text-base font-bold;
|
||||
@apply absolute right-0 top-4 text-base font-bold;
|
||||
}
|
||||
.state{
|
||||
@apply absolute right-3 top-11 text-[#8D8C8D] text-xs;
|
||||
@apply absolute right-0 top-11 text-[#8D8C8D] text-xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "nc-iconfont"; /* Project id 4567203 */
|
||||
src: url('//at.alicdn.com/t/c/font_4567203_jiym07jhp7i.woff2?t=1718104706175') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_4567203_jiym07jhp7i.woff?t=1718104706175') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_4567203_jiym07jhp7i.ttf?t=1718104706175') format('truetype');
|
||||
src: url('//at.alicdn.com/t/c/font_4567203_fc0pt9szyn7.woff2?t=1721726440236') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_4567203_fc0pt9szyn7.woff?t=1721726440236') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_4567203_fc0pt9szyn7.ttf?t=1721726440236') format('truetype');
|
||||
}
|
||||
|
||||
.nc-iconfont {
|
||||
@ -13,6 +13,18 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.nc-icon-a-xiangshangV6xx1:before {
|
||||
content: "\e799";
|
||||
}
|
||||
|
||||
.nc-icon-a-xiangxiaV6xx1:before {
|
||||
content: "\e796";
|
||||
}
|
||||
|
||||
.nc-icon-fuzhiV6xx1:before {
|
||||
content: "\e76c";
|
||||
}
|
||||
|
||||
.nc-icon-kefuV6xx1:before {
|
||||
content: "\e76a";
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ const loginBack = useLogin()
|
||||
/**
|
||||
* 检测是否需要登录
|
||||
*/
|
||||
export function checkNeedLogin(route: AnyObject){
|
||||
export function checkNeedLogin(route: AnyObject) {
|
||||
const pages = getNeedLoginPages()
|
||||
|
||||
if (pages.includes(route.path) && !getToken()) {
|
||||
|
||||
@ -2,6 +2,8 @@ import { getTabbarPages } from './pages'
|
||||
import useDiyStore from '@/app/stores/diy'
|
||||
import useMemberStore from '@/stores/member'
|
||||
import useSystemStore from '@/stores/system'
|
||||
import useConfigStore from '@/stores/config'
|
||||
import { getNeedLoginPages } from '@/utils/pages'
|
||||
|
||||
/**
|
||||
* 跳转页面
|
||||
@ -11,6 +13,14 @@ export const redirect = (redirect : redirectOptions) => {
|
||||
if (useDiyStore().mode == 'decorate') return
|
||||
|
||||
let { url, mode, param, success, fail, complete } = redirect
|
||||
|
||||
const config = useConfigStore()
|
||||
// 如果未开启普通账号登录注册,不展示登录注册页面
|
||||
if(!getToken() && getNeedLoginPages().indexOf(url) != -1 && !config.login.is_username && !config.login.is_mobile && !config.login.is_bind_mobile){
|
||||
uni.showToast({ title: '商家未开启普通账号登录注册', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
mode = mode || 'navigateTo'
|
||||
const tabBar = getTabbarPages()
|
||||
tabBar.includes(url) && (mode = 'switchTab')
|
||||
@ -442,3 +452,8 @@ const isArray = (value: any) => {
|
||||
return Object.prototype.toString.call(value) === '[object Array]'
|
||||
}
|
||||
|
||||
// px转rpx
|
||||
export function pxToRpx(px: any) {
|
||||
const screenWidth = uni.getSystemInfoSync().screenWidth;
|
||||
return (750 * Number.parseInt(px)) / screenWidth;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { language } from '@/locale'
|
||||
import { checkNeedLogin } from '@/utils/auth'
|
||||
import { redirect, getToken, isWeixinBrowser } from '@/utils/common'
|
||||
import { getToken } from '@/utils/common'
|
||||
import { memberLog } from '@/app/api/auth'
|
||||
import useConfigStore from "@/stores/config";
|
||||
import { useShare } from '@/hooks/useShare'
|
||||
@ -81,7 +81,7 @@ const setAddonName = async (path: string) => {
|
||||
// 设置插件应用的主色调,排除系统
|
||||
if (route != 'app') {
|
||||
try {
|
||||
const theme = await import(`../addon/${route}/utils/theme.json`)
|
||||
const theme = await import(`../addon/${ route }/utils/theme.json`)
|
||||
configStore.themeColor = theme.default
|
||||
uni.setStorageSync('current_theme_color', JSON.stringify(theme.default));
|
||||
} catch (e) {
|
||||
@ -89,10 +89,11 @@ const setAddonName = async (path: string) => {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 加载分享
|
||||
const loadShare = () => {
|
||||
const { setShare } = useShare()
|
||||
setShare()
|
||||
}
|
||||
}
|
||||
@ -4,16 +4,16 @@ import pagesJson from '@/pages.json'
|
||||
* 获取需要登录的页面
|
||||
*/
|
||||
export function getNeedLoginPages() {
|
||||
const pages = []
|
||||
const pages: any = []
|
||||
// 获取主包中需要登录的页面
|
||||
pagesJson.pages.forEach(item => {
|
||||
if (item.needLogin) pages.push(`/${item.path}`)
|
||||
if (item.needLogin) pages.push(`/${ item.path }`)
|
||||
})
|
||||
// 获取分包中需要登录的页面
|
||||
if (pagesJson.subPackages) {
|
||||
pagesJson.subPackages.forEach(subPackages => {
|
||||
subPackages.pages.forEach(item => {
|
||||
if (item.needLogin) pages.push(`/${subPackages.root}/${item.path}`)
|
||||
if (item.needLogin) pages.push(`/${ subPackages.root }/${ item.path }`)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -24,21 +24,21 @@ export function getNeedLoginPages() {
|
||||
* 获取所有页面
|
||||
*/
|
||||
export function getAppPages() {
|
||||
const pages = []
|
||||
const pages: any = []
|
||||
// 获取主包中需要登录的页面
|
||||
pagesJson.pages.forEach(item => {
|
||||
pages.push(`/${item.path}`)
|
||||
pages.push(`/${ item.path }`)
|
||||
})
|
||||
return pages
|
||||
}
|
||||
|
||||
export function getSubPackagesPages() {
|
||||
const pages = []
|
||||
const pages: any = []
|
||||
// 获取分包中需要登录的页面
|
||||
if (pagesJson.subPackages) {
|
||||
pagesJson.subPackages.forEach(subPackages => {
|
||||
subPackages.pages.forEach(item => {
|
||||
pages.push(`/${subPackages.root}/${item.path}`)
|
||||
pages.push(`/${ subPackages.root }/${ item.path }`)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -49,7 +49,9 @@ export function getSubPackagesPages() {
|
||||
* 获取tabbar
|
||||
*/
|
||||
export function getTabbarPages() {
|
||||
return pagesJson.tabBar.list.map(item => { return `/${item.pagePath}` })
|
||||
return pagesJson.tabBar.list.map(item => {
|
||||
return `/${ item.pagePath }`
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -4,181 +4,182 @@ import { getToken, getAppChannel, redirect, currRoute } from './common'
|
||||
import qs from 'qs'
|
||||
|
||||
interface RequestConfig {
|
||||
showErrorMessage ?: boolean
|
||||
showSuccessMessage ?: boolean
|
||||
showErrorMessage?: boolean
|
||||
showSuccessMessage?: boolean
|
||||
}
|
||||
|
||||
interface RequestOptions extends UniNamespace.RequestOptions, RequestOptions { }
|
||||
interface RequestOptions extends UniNamespace.RequestOptions, RequestOptions {
|
||||
}
|
||||
|
||||
class Request {
|
||||
private baseUrl : string
|
||||
private baseUrl: string
|
||||
|
||||
private config : RequestOptions = {
|
||||
url: '',
|
||||
header: {}
|
||||
}
|
||||
private config: RequestOptions = {
|
||||
url: '',
|
||||
header: {}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
// #ifdef H5
|
||||
this.baseUrl = import.meta.env.VITE_APP_BASE_URL || `${location.origin}/api/`
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
this.baseUrl = import.meta.env.VITE_APP_BASE_URL
|
||||
// #endif
|
||||
this.baseUrl.substr(-1) != '/' && (this.baseUrl += '/')
|
||||
constructor() {
|
||||
// #ifdef H5
|
||||
this.baseUrl = import.meta.env.VITE_APP_BASE_URL || `${ location.origin }/api/`
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
this.baseUrl = import.meta.env.VITE_APP_BASE_URL
|
||||
// #endif
|
||||
this.baseUrl.substr(-1) != '/' && (this.baseUrl += '/')
|
||||
|
||||
try {
|
||||
this.config.header[import.meta.env.VITE_REQUEST_HEADER_CHANNEL_KEY] = getAppChannel()
|
||||
} catch (e) {
|
||||
}
|
||||
try {
|
||||
this.config.header[import.meta.env.VITE_REQUEST_HEADER_CHANNEL_KEY] = getAppChannel()
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求拦截器
|
||||
*/
|
||||
private requestInterceptors() {
|
||||
// 携带token
|
||||
try {
|
||||
getToken() && (this.config.header[import.meta.env.VITE_REQUEST_HEADER_TOKEN_KEY] = getToken())
|
||||
this.config.header[import.meta.env.VITE_REQUEST_HEADER_CHANNEL_KEY] = getAppChannel()
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 请求拦截器
|
||||
*/
|
||||
private requestInterceptors() {
|
||||
// 携带token
|
||||
try {
|
||||
getToken() && (this.config.header[import.meta.env.VITE_REQUEST_HEADER_TOKEN_KEY] = getToken())
|
||||
this.config.header[import.meta.env.VITE_REQUEST_HEADER_CHANNEL_KEY] = getAppChannel()
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
public get(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
|
||||
return this.request('GET', url, data, config)
|
||||
}
|
||||
public get(url: string, data: AnyObject = {}, config: RequestConfig = {}) {
|
||||
return this.request('GET', url, data, config)
|
||||
}
|
||||
|
||||
public post(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
|
||||
return this.request('POST', url, data, config)
|
||||
}
|
||||
public post(url: string, data: AnyObject = {}, config: RequestConfig = {}) {
|
||||
return this.request('POST', url, data, config)
|
||||
}
|
||||
|
||||
public put(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
|
||||
return this.request('PUT', url, data, config)
|
||||
}
|
||||
public put(url: string, data: AnyObject = {}, config: RequestConfig = {}) {
|
||||
return this.request('PUT', url, data, config)
|
||||
}
|
||||
|
||||
public delete(url : string, config : RequestConfig = {}) {
|
||||
return this.request('DELETE', url, {}, config)
|
||||
}
|
||||
public delete(url: string, config: RequestConfig = {}) {
|
||||
return this.request('DELETE', url, {}, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送上传请求
|
||||
*/
|
||||
public upload(url : string, data : AnyObject = {}, config : RequestConfig = {}) {
|
||||
this.requestInterceptors()
|
||||
/**
|
||||
* 发送上传请求
|
||||
*/
|
||||
public upload(url: string, data: AnyObject = {}, config: RequestConfig = {}) {
|
||||
this.requestInterceptors()
|
||||
|
||||
const params = Object.assign(uni.$u.deepClone(this.config), config, {
|
||||
url: this.baseUrl + url,
|
||||
...data
|
||||
})
|
||||
const params = Object.assign(uni.$u.deepClone(this.config), config, {
|
||||
url: this.baseUrl + url,
|
||||
...data
|
||||
})
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
...params,
|
||||
success: res => {
|
||||
const data = JSON.parse(res.data)
|
||||
if (data.code == 1) {
|
||||
this.config.showSuccessMessage && uni.showToast({ title: data.msg, icon: 'none' })
|
||||
resolve(data)
|
||||
} else {
|
||||
if (data.code == 0 || data.code == 400) {
|
||||
if (this.config.showErrorMessage !== false) uni.showToast({ title: data.msg, icon: 'none' })
|
||||
} else {
|
||||
this.handleAuthError(data.code)
|
||||
}
|
||||
reject(data)
|
||||
}
|
||||
},
|
||||
fail: res => {
|
||||
reject(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求
|
||||
*/
|
||||
private request(method : string, url : string, data ?: AnyObject, config : RequestConfig = {}) {
|
||||
this.requestInterceptors()
|
||||
|
||||
const params = Object.assign(uni.$u.deepClone(this.config), config,{
|
||||
url: this.baseUrl + url,
|
||||
method
|
||||
})
|
||||
|
||||
if (params.method.toUpperCase() == 'GET') {
|
||||
params.url += '?' + qs.stringify(data);
|
||||
} else {
|
||||
params.data = data;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
...params,
|
||||
success: res => {
|
||||
const data = res.data
|
||||
if (data.code == 1) {
|
||||
config.showSuccessMessage && uni.showToast({ title: data.msg, icon: 'none' })
|
||||
resolve(data)
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
...params,
|
||||
success: res => {
|
||||
const data = JSON.parse(res.data)
|
||||
if (data.code == 1) {
|
||||
this.config.showSuccessMessage && uni.showToast({ title: data.msg, icon: 'none' })
|
||||
resolve(data)
|
||||
} else {
|
||||
if (data.code == 0 || data.code == 400) {
|
||||
if (config.showErrorMessage !== false) uni.showToast({ title: data.msg, icon: 'none' })
|
||||
} else {
|
||||
if (this.config.showErrorMessage !== false) uni.showToast({ title: data.msg, icon: 'none' })
|
||||
} else {
|
||||
this.handleAuthError(data.code)
|
||||
}
|
||||
reject(data)
|
||||
}
|
||||
},
|
||||
fail: res => {
|
||||
reject(res)
|
||||
},
|
||||
complete: (res) => {
|
||||
this.handleRequestFail(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
reject(data)
|
||||
}
|
||||
},
|
||||
fail: res => {
|
||||
reject(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private handleAuthError(code : number) {
|
||||
switch (code) {
|
||||
case 401:
|
||||
useMemberStore().logout()
|
||||
break;
|
||||
case 402:
|
||||
if(currRoute().indexOf('app/pages/index/close') != -1) return;
|
||||
redirect({url: '/app/pages/index/close', mode: 'reLaunch'})
|
||||
break;
|
||||
case 403:
|
||||
if(currRoute().indexOf('app/pages/index/nosite') != -1) return;
|
||||
redirect({url: '/app/pages/index/nosite', mode: 'reLaunch'})
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 发送请求
|
||||
*/
|
||||
private request(method: string, url: string, data ?: AnyObject, config: RequestConfig = {}) {
|
||||
this.requestInterceptors()
|
||||
|
||||
private handleRequestFail(res) {
|
||||
if (res.errMsg && res.errMsg == "request:ok") {
|
||||
if (typeof res.data == 'string') {
|
||||
// #ifdef H5
|
||||
const err = (isUrl(this.baseUrl) ? this.baseUrl : location.origin + this.baseUrl) + t('baseUrlError')
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
const err = this.baseUrl + t('baseUrlError')
|
||||
// #endif
|
||||
uni.showToast({icon: 'none', title: err })
|
||||
return
|
||||
}
|
||||
}
|
||||
if (res.errMsg == 'request:fail') {
|
||||
uni.showToast({ icon: 'none', title: this.baseUrl + t('requestFail') })
|
||||
return
|
||||
}
|
||||
if (res.errMsg && res.errMsg == 'request:fail url not in domain list') {
|
||||
uni.showToast({ icon: 'none', title: this.baseUrl + t('notInDomainList') });
|
||||
return
|
||||
}
|
||||
}
|
||||
const params = Object.assign(uni.$u.deepClone(this.config), config, {
|
||||
url: this.baseUrl + url,
|
||||
method
|
||||
})
|
||||
|
||||
if (params.method.toUpperCase() == 'GET') {
|
||||
params.url += '?' + qs.stringify(data);
|
||||
} else {
|
||||
params.data = data;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
...params,
|
||||
success: res => {
|
||||
const data = res.data
|
||||
if (data.code == 1) {
|
||||
config.showSuccessMessage && uni.showToast({ title: data.msg, icon: 'none' })
|
||||
resolve(data)
|
||||
} else {
|
||||
if (data.code == 0 || data.code == 400) {
|
||||
if (config.showErrorMessage !== false) uni.showToast({ title: data.msg, icon: 'none' })
|
||||
} else {
|
||||
this.handleAuthError(data.code)
|
||||
}
|
||||
reject(data)
|
||||
}
|
||||
},
|
||||
fail: res => {
|
||||
reject(res)
|
||||
},
|
||||
complete: (res) => {
|
||||
this.handleRequestFail(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private handleAuthError(code: number) {
|
||||
switch (code) {
|
||||
case 401:
|
||||
useMemberStore().logout()
|
||||
break;
|
||||
case 402:
|
||||
if (currRoute().indexOf('app/pages/index/close') != -1) return;
|
||||
redirect({ url: '/app/pages/index/close', mode: 'reLaunch' })
|
||||
break;
|
||||
case 403:
|
||||
if (currRoute().indexOf('app/pages/index/nosite') != -1) return;
|
||||
redirect({ url: '/app/pages/index/nosite', mode: 'reLaunch' })
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private handleRequestFail(res) {
|
||||
if (res.errMsg && res.errMsg == "request:ok") {
|
||||
if (typeof res.data == 'string') {
|
||||
// #ifdef H5
|
||||
const err = (isUrl(this.baseUrl) ? this.baseUrl : location.origin + this.baseUrl) + t('baseUrlError')
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
const err = this.baseUrl + t('baseUrlError')
|
||||
// #endif
|
||||
uni.showToast({ icon: 'none', title: err })
|
||||
return
|
||||
}
|
||||
}
|
||||
if (res.errMsg == 'request:fail') {
|
||||
uni.showToast({ icon: 'none', title: this.baseUrl + t('requestFail') })
|
||||
return
|
||||
}
|
||||
if (res.errMsg && res.errMsg == 'request:fail url not in domain list') {
|
||||
uni.showToast({ icon: 'none', title: this.baseUrl + t('notInDomainList') });
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new Request()
|
||||
|
||||
@ -10,31 +10,31 @@ export function uniStorage(){
|
||||
const getStorageSync = uni.getStorageSync
|
||||
const removeStorage = uni.removeStorage
|
||||
const removeStorageSync = uni.removeStorageSync
|
||||
|
||||
|
||||
uni.setStorage = (options: UniNamespace.SetStorageOptions)=> {
|
||||
options.key = handleKey(options.key)
|
||||
setStorage(options)
|
||||
}
|
||||
|
||||
|
||||
uni.setStorageSync = (key: string, data: any) => {
|
||||
setStorageSync(handleKey(key), data)
|
||||
}
|
||||
|
||||
|
||||
uni.getStorage = (options: UniNamespace.GetStorageOptions) => {
|
||||
options.key = handleKey(options.key)
|
||||
getStorage(options)
|
||||
}
|
||||
|
||||
|
||||
uni.getStorageSync = (key: string) => {
|
||||
return getStorageSync(handleKey(key))
|
||||
}
|
||||
|
||||
|
||||
uni.removeStorage = (options: UniNamespace.RemoveStorageOptions) => {
|
||||
options.key = handleKey(options.key)
|
||||
removeStorage(options)
|
||||
}
|
||||
|
||||
|
||||
uni.removeStorageSync = (key: string) => {
|
||||
return removeStorageSync(handleKey(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
58
uni-app/src/utils/topTabbar.ts
Normal file
58
uni-app/src/utils/topTabbar.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { ref } from 'vue';
|
||||
import { onPageScroll } from '@dcloudio/uni-app';
|
||||
|
||||
export function topTabar() {
|
||||
|
||||
const param = ref({
|
||||
title:'',
|
||||
topStatusBar: {
|
||||
style: 'style-1',
|
||||
bgColor: 'transparent',
|
||||
rollBgColor: '#fff',
|
||||
textColor: '#fff',
|
||||
rollTextColor: '#333'
|
||||
}
|
||||
})
|
||||
|
||||
let scrollVal = ref(1); // 默认的传入滚动值
|
||||
let scrollBool = ref(-1);
|
||||
|
||||
// 设置初始数据
|
||||
const setTopTabbarParam = (data: Object = {}) => {
|
||||
if(data && typeof data != 'object') return param
|
||||
for(let key in data){
|
||||
if(key == 'title'){
|
||||
param.value.title = data.title || '';
|
||||
}else if(key == 'topStatusBar' && data.topStatusBar){
|
||||
for(let subKey in data.topStatusBar){
|
||||
param.value.topStatusBar[subKey] = data.topStatusBar[subKey]
|
||||
}
|
||||
}else{
|
||||
param.value[key] = data[key]
|
||||
}
|
||||
}
|
||||
return param.value;
|
||||
}
|
||||
|
||||
onPageScroll((e)=>{
|
||||
if(e.scrollTop <= 0){
|
||||
// -1 表示页面滚动值小于零,头部组件随页面下拉而下来
|
||||
scrollBool.value = -1;
|
||||
}else if(e.scrollTop > scrollVal.value){
|
||||
// 1 表示页面滚动值大于传入滚动值,头部组件随页面上拉背景、文字颜色采用滚动后的变量
|
||||
scrollBool.value = 1
|
||||
}else{
|
||||
// 2 表示页面滚动值小于传入滚动值,头部组件随页面下拉背景、文字颜色采用滚动前的变量
|
||||
scrollBool.value = 2
|
||||
}
|
||||
})
|
||||
|
||||
const getScrollBool = () => {
|
||||
return scrollBool.value;
|
||||
}
|
||||
|
||||
return {
|
||||
getScrollBool,
|
||||
setTopTabbarParam
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user