This commit is contained in:
全栈小学生 2024-08-06 17:56:04 +08:00
parent 4890be9b9a
commit 4aaf885ef0
85 changed files with 3171 additions and 1404 deletions

View File

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app' import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
import { launchInterceptor } from '@/utils/interceptor' import { launchInterceptor } from '@/utils/interceptor'
import { getToken, isWeixinBrowser } from '@/utils/common' import { getToken, isWeixinBrowser, currRoute } from '@/utils/common'
import useMemberStore from '@/stores/member' import useMemberStore from '@/stores/member'
import useConfigStore from '@/stores/config' import useConfigStore from '@/stores/config'
import useSystemStore from '@/stores/system' import useSystemStore from '@/stores/system'
@ -48,6 +48,30 @@
wechatInit() wechatInit()
// #endif // #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() const configStore = useConfigStore()
await configStore.getTabbarConfig() await configStore.getTabbarConfig()
await configStore.getLoginConfig() await configStore.getLoginConfig()
@ -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()) { if (getToken()) {
const memberStore = useMemberStore() const memberStore = useMemberStore()
@ -70,17 +100,43 @@
setTimeout(() => { setTimeout(() => {
if (!uni.getStorageSync('openid')) { if (!uni.getStorageSync('openid')) {
const memberInfo = useMemberStore().info const memberInfo = useMemberStore().info
const login = useLogin()
// #ifdef MP-WEIXIN // #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 // #endif
// #ifdef H5 // #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 // #endif
} }
//
if (uni.getStorageSync('isbindmobile')) {
uni.removeStorageSync('isbindmobile');
}
if (configStore.login.is_bind_mobile && !memberStore.info.mobile) {
//
uni.setStorageSync('isbindmobile', true)
}
}, 1000) }, 1000)
} }
if (!getToken()) { if (!getToken()) {
// todo 退
// #ifdef MP
if(uni.getStorageSync('autoLoginLock')){
return false
}
// #endif
//
if (configStore.login.is_auth_register) {
const login = useLogin() const login = useLogin()
// //
// #ifdef MP // #ifdef MP
@ -92,6 +148,7 @@
} }
// #endif // #endif
} }
}
}) })
onShow(() => { onShow(() => {

View File

@ -1,4 +1,4 @@
.draggable-element,.ignore-draggable-element { .draggable-element {
&.decorate { &.decorate {
&:hover:before { &:hover:before {
content: ''; content: '';

View File

@ -1,11 +1,11 @@
<template> <template>
<view class="diy-group" id="componentList"> <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" /> <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="getComponentClass(index,component)" :style="component.pageStyle"> <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 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'"> <template v-if="component.componentName == 'GraphicNav'">
<diy-graphic-nav :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" /> <diy-graphic-nav :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
@ -47,179 +47,46 @@
<diy-float-btn :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount"/> <diy-float-btn :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount"/>
</template> </template>
<template v-if="component.componentName == 'CarouselSearch'"> <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> </template>
</view> </view>
</view> </view>
<template v-if="diyStore.mode == '' && data.global.bottomTabBarSwitch"> <template v-if="diyStore.mode == '' && data.global.bottomTabBarSwitch">
<view class="pt-[20rpx]"></view> <view class="pt-[20rpx]"></view>
<tabbar :addon="tabbarAddonName" /> <tabbar />
</template> </template>
</view> </view>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import topTabbar from '@/components/top-tabbar/top-tabbar.vue' import topTabbar from '@/components/top-tabbar/top-tabbar.vue'
import { useDiyGroup } from './useDiyGroup'
import useDiyStore from '@/app/stores/diy'; import useDiyStore from '@/app/stores/diy';
import { ref, onMounted, nextTick, computed, watch } from 'vue'; import { ref } 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'
const props = defineProps(['data', 'pullDownRefreshCount']); const props = defineProps(['data', 'pullDownRefreshCount']);
const topTabbarRef = ref(null);
const diyStore = useDiyStore(); const diyStore = useDiyStore();
const router = useRouter(); const diyGroup = useDiyGroup({
const data = computed(()=>{ ...props,
if (diyStore.mode == 'decorate') { getFormRef() {
return diyStore; return {
} else { topTabbarRef: topTabbarRef.value
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'
} }
}); });
// #endif const data = ref(diyGroup.data)
// #ifdef MP //
wx.onAppRoute(function(res) { diyGroup.onMounted()
if(res.path != "addon/shop/pages/index"){
diyStore.topFixedStatus = 'home'
}
});
// #endif
// - - end
const tabbarAddonName = computed(() => { //
return useConfigStore().addon; diyGroup.onPageScroll()
})
const positionFixed = ref(['fixed', 'top_fixed','right_fixed','bottom_fixed','left_fixed']);
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();
})
}
// carouselSearchScrollBooltrue,
let carouselSearchScrollBool = ref(false)
// top-tabbartrue,
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({ defineExpose({
refresh refresh: diyGroup.refresh
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View 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
}
}

View File

@ -61,6 +61,9 @@ export function wechatUser(data : AnyObject) {
* openid * openid
*/ */
export function wechatUserLogin(data : AnyObject) { export function wechatUserLogin(data : AnyObject) {
if(uni.getStorageSync('pid')){
data.pid = uni.getStorageSync('pid');
}
return request.post('wechat/userlogin', data, { showErrorMessage: true }) return request.post('wechat/userlogin', data, { showErrorMessage: true })
} }
@ -68,16 +71,34 @@ export function wechatUserLogin(data : AnyObject) {
* *
*/ */
export function wechatLogin(data : AnyObject) { export function wechatLogin(data : AnyObject) {
if(uni.getStorageSync('pid')){
data.pid = uni.getStorageSync('pid');
}
return request.post('wechat/login', data, { showErrorMessage: false }) 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) { export function weappLogin(data : AnyObject) {
if(uni.getStorageSync('pid')){
data.pid = uni.getStorageSync('pid');
}
return request.post('weapp/login', data, { showErrorMessage: false }) return request.post('weapp/login', data, { showErrorMessage: false })
} }
/**
* openid
*/
export function updateWeappOpenid(data : AnyObject) {
return request.put('weapp/update_openid', data, { showErrorMessage: false })
}
/** /**
* *
*/ */

View File

@ -10,7 +10,12 @@ export function getMemberInfo() {
export function getPointList(data : AnyObject) { export function getPointList(data : AnyObject) {
return request.get('member/account/point', data) return request.get('member/account/point', data)
} }
/**
*
*/
export function getPointType(account_type : string) {
return request.get(`member/account/fromtype/${account_type}`)
}
/** /**
* *
*/ */

View File

@ -116,13 +116,6 @@ export function getAddressByLatlng(params: Record<string, any>) {
return request.get(`area/address_by_latlng`, params, {showErrorMessage: true}) return request.get(`area/address_by_latlng`, params, {showErrorMessage: true})
} }
/**
*
*/
export function getWapIndexList(data: AnyObject) {
return request.get('wap_index', data)
}
/** /**
* *
* @returns * @returns

View File

@ -21,7 +21,6 @@ export function getCheckVerifier() {
return request.get('check_verifier') return request.get('check_verifier')
} }
/** /**
* *
*/ */
@ -33,7 +32,7 @@ export function getVerifierInfo(code: string) {
* *
*/ */
export function verify(code: string) { export function verify(code: string) {
return request.post(`verify/${code}`,{}, { showSuccessMessage: true, showErrorMessage: true }) return request.post(`verify/${ code }`, {}, { showErrorMessage: true })
} }
/** /**
@ -42,6 +41,3 @@ export function verify(code: string) {
export function getVerifyDetail(code: string) { export function getVerifyDetail(code: string) {
return request.get(`verify_detail/${ code }`, {}, { showErrorMessage: true }) return request.get(`verify_detail/${ code }`, {}, { showErrorMessage: true })
} }

View File

@ -6,14 +6,13 @@
<view v-else class="w-full h-full bg-[#ccc]"></view> <view v-else class="w-full h-full bg-[#ccc]"></view>
<view class="bg-img-box" :style="bgImgBoxStyle"></view> <view class="bg-img-box" :style="bgImgBoxStyle"></view>
</view> </view>
<view class="fixed-wrap" :style="fixedStyle">
<view class="fixed-wrap" :class="[ diyStore.mode != 'decorate' ? diyComponent.positionWay : '' ]" :style="fixedStyle">
<view class="diy-search-wrap relative z-10" @click="diyStore.toRedirect(diyComponent.search.link)" :style="navbarInnerStyle"> <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"> <view class="img-wrap" v-if="diyComponent.search.logo">
<image :src="img(diyComponent.search.logo)" mode="aspectFit"/> <image :src="img(diyComponent.search.logo)" mode="aspectFit"/>
</view> </view>
<view class="search-content"> <view class="search-content" @click="diyStore.toRedirect(diyComponent.search.link)">
<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"/> <text class="input-content text-[#fff] text-[24rpx] leading-[68rpx]">{{isShowSearchPlaceholder ? diyComponent.search.text : ''}}</text>
<text class="nc-iconfont nc-icon-sousuo-duanV6xx1"></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"> <swiper class="swiper-wrap" :interval="diyComponent.search.hotWord.interval * 1000" autoplay="true" vertical="true" circular="true" v-if="!isShowSearchPlaceholder">
@ -47,7 +46,7 @@
<!-- 解决fixed定位后导航栏塌陷的问题 --> <!-- 解决fixed定位后导航栏塌陷的问题 -->
<template v-if="diyStore.mode != 'decorate'"> <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> </template>
<!-- 轮播图 --> <!-- 轮播图 -->
@ -118,8 +117,7 @@
import { getDiyInfo } from '@/app/api/diy'; import { getDiyInfo } from '@/app/api/diy';
const instance = getCurrentInstance(); const instance = getCurrentInstance();
const props = defineProps(['component', 'index', 'pullDownRefreshCount', 'global','scrollTop']); const props = defineProps(['component', 'index', 'pullDownRefreshCount', 'global', 'scrollBool']);
const diyStore = useDiyStore(); const diyStore = useDiyStore();
const diyComponent = computed(() => { const diyComponent = computed(() => {
@ -172,7 +170,12 @@
style += 'top:' + diyStore.topTabarHeight + 'px;'; style += 'top:' + diyStore.topTabarHeight + 'px;';
} }
// #endif // #endif
if(diyComponent.value.positionWay == 'fixed') { 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 // #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
menuButtonInfo = uni.getMenuButtonBoundingClientRect(); menuButtonInfo = uni.getMenuButtonBoundingClientRect();
if(props.global.topStatusBar.isShow) { if(props.global.topStatusBar.isShow) {
@ -181,7 +184,7 @@
// #endif // #endif
fixedStyleBg.value = false; fixedStyleBg.value = false;
if (props.scrollTop) { if (props.scrollBool == 1) {
let str = diyComponent.value.fixedBgColor; let str = diyComponent.value.fixedBgColor;
let arr = str.split(','); let arr = str.split(',');
let num = diyComponent.value.fixedBgColor ? parseInt(arr[arr.length-1]) : 0; let num = diyComponent.value.fixedBgColor ? parseInt(arr[arr.length-1]) : 0;
@ -200,12 +203,12 @@
let color = ''; let color = '';
if(flag){ if(flag){
color = diyComponent.value.tab.selectColor; 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; color = diyComponent.value.tab.fixedSelectColor;
} }
}else{ }else{
color = diyComponent.value.tab.noColor; 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; color = diyComponent.value.tab.fixedNoColor;
} }
} }
@ -288,9 +291,9 @@
} }
} }
let tabAllPopup = ref(false); const tabAllPopup = ref(false);
let menuButtonInfo:any = {}; let menuButtonInfo:any = {};
let navbarInnerStyle = ref('') const navbarInnerStyle = ref('')
onMounted(() => { onMounted(() => {
refresh(); refresh();
@ -397,10 +400,19 @@
isShowDots.value = false; isShowDots.value = false;
// #endif // #endif
// ,20, /******************************* 存储滚动值-start ***********************/
defineExpose({ //
scrollValue: 20 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> </script>
@ -463,12 +475,12 @@
.search-content { .search-content {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 40rpx; padding: 0 32rpx;
border-radius: 50rpx; border-radius: 50rpx;
background-color: rgba(255,255,255,.2); background-color: rgba(255,255,255,.2);
flex: 1; flex: 1;
position: relative; position: relative;
input, .uni-input { .input-content, .uni-input {
box-sizing: border-box; box-sizing: border-box;
display: block; display: block;
height: 64rpx; height: 64rpx;

View File

@ -1,17 +1,34 @@
<template> <template>
<view :style="warpCss"> <view class="float-btn fixed z-1000" :class="[diyComponent.style,diyComponent.bottomPosition, diyStore.mode == 'decorate' ? 'float-btn-border' : '']" :style="floatBtnWrapCss">
<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 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"> <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-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"/> <image v-else :src="img('static/resource/images/diy/figure.png')" mode="aspectFit" :style="floatBtnItemCss"/>
</view> </view>
</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> </view>
</template> </template>
<script setup lang="ts"> <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 useDiyStore from '@/app/stores/diy';
import { img } from '@/utils/common'; 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.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-left-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;'; if (diyComponent.value.bottomRounded) style += 'border-bottom-right-radius:' + diyComponent.value.bottomRounded * 2 + 'rpx;';
return style; return style;
}) })
@ -52,14 +70,49 @@
let style = ''; let style = '';
if(diyComponent.value.offset){ if(diyComponent.value.offset){
if(diyComponent.value.bottomPosition == 'lowerRight' || diyComponent.value.bottomPosition == 'lowerLeft'){ 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'){ }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; 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( watch(
() => props.pullDownRefreshCount, () => props.pullDownRefreshCount,
(newValue, oldValue) => { (newValue, oldValue) => {
@ -70,20 +123,20 @@
<style lang="scss" scoped> <style lang="scss" scoped>
.float-btn{ .float-btn{
&.decorate-position.upperRight,&.decorate-position.lowerRight {
align-items: flex-end;
}
&.decorate-position.upperLeft,&.decorate-position.lowerLeft {
align-items: baseline;
}
&.upperLeft { &.upperLeft {
top: 100rpx; top: 100rpx;
left: 30rpx; left: 30rpx;
&.style-2{
left:0 ;
}
} }
&.upperRight { &.upperRight {
top: 100rpx; top: 100rpx;
right: 30rpx; right: 30rpx;
&.style-2{
right:0 ;
}
} }
&.lowerLeft { &.lowerLeft {
@ -93,6 +146,10 @@
/*兼容 IOS<11.2*/ /*兼容 IOS<11.2*/
padding-bottom: env(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);
/*兼容 IOS>11.2*/ /*兼容 IOS>11.2*/
&.style-2{
left:0 ;
}
} }
&.lowerRight { &.lowerRight {
@ -102,6 +159,9 @@
/*兼容 IOS<11.2*/ /*兼容 IOS<11.2*/
padding-bottom: env(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);
/*兼容 IOS>11.2*/ /*兼容 IOS>11.2*/
&.style-2{
right:0 ;
}
} }
} }
.z-1000{ .z-1000{

View File

@ -40,9 +40,9 @@
<template v-for="(item, index) in diyComponent.list"> <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" <view class="graphic-img relative flex items-center justify-center w-10 h-10"
v-if="diyComponent.mode != 'text'" v-if="diyComponent.mode != 'text'"
@ -73,6 +73,45 @@
</swiper-item> </swiper-item>
</swiper> </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]"> <scroll-view v-else :scroll-x="diyComponent.showStyle == 'singleSlide'" :class="['graphic-nav','graphic-nav-' + diyComponent.showStyle]" class=" py-[10rpx]">
<!-- #ifdef MP --> <!-- #ifdef MP -->
<view class="uni-scroll-view-content"> <view class="uni-scroll-view-content">
@ -171,6 +210,48 @@
return style; 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( watch(
() => props.pullDownRefreshCount, () => props.pullDownRefreshCount,
(newValue, oldValue) => { (newValue, oldValue) => {
@ -188,13 +269,7 @@
let count = diyComponent.value.pageCount * diyComponent.value.rowCount; let count = diyComponent.value.pageCount * diyComponent.value.rowCount;
let result = true; 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)]; result = index >= [(numItem - 1) * (count)] && index < [numItem * (count)];
// #endif
return result; return result;
} }
@ -206,7 +281,11 @@
var height = 0; var height = 0;
const query = uni.createSelectorQuery().in(instance); const query = uni.createSelectorQuery().in(instance);
query.select('.graphic-nav-item').boundingClientRect((data: any) => { 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'; swiperHeight.value = (height * 2) + 'rpx';
}).exec(); }).exec();
} }

View File

@ -7,7 +7,7 @@
<!-- #endif --> <!-- #endif -->
<view v-if="info" class="flex ml-[32rpx] mr-[52rpx] items-center relative"> <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="ml-[22rpx]">
<view class="text-[#222222] flex pr-[50rpx] flex-wrap items-center"> <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> <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> </view>
<view v-else class="flex ml-[32rpx] mr-[52rpx] items-center relative" @click="toLogin"> <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="ml-[22rpx]">
<view class="text-[#222222] font-bold text-lg" :style="{ color : diyComponent.textColor }"> <view class="text-[#222222] font-bold text-lg" :style="{ color : diyComponent.textColor }">
{{ t('login') }}/{{ t('register') }} {{ t('login') }}/{{ t('register') }}
@ -58,6 +58,11 @@
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<information-filling ref="infoFill"></information-filling> <information-filling ref="infoFill"></information-filling>
<!-- #endif --> <!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif -->
</view> </view>
</template> </template>
@ -69,9 +74,11 @@
import { t } from '@/locale' import { t } from '@/locale'
import { wechatSync } from '@/app/api/system' import { wechatSync } from '@/app/api/system'
import useDiyStore from '@/app/stores/diy' import useDiyStore from '@/app/stores/diy'
import useConfigStore from '@/stores/config'
const props = defineProps(['component', 'index', 'pullDownRefreshCount','global']); const props = defineProps(['component', 'index', 'pullDownRefreshCount','global']);
const configStore = useConfigStore()
const diyStore = useDiyStore(); const diyStore = useDiyStore();
const diyComponent = computed(() => { const diyComponent = computed(() => {
@ -144,7 +151,21 @@
}) })
const toLogin = () => { const toLogin = () => {
if(configStore.login.is_username || configStore.login.is_mobile || configStore.login.is_bind_mobile){
useLogin().setLoginBack({ url: '/app/pages/member/index' }) 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) const infoFill = ref(false)

View File

@ -25,22 +25,25 @@
</view> </view>
<view v-if="diyComponent.style == 'style-3'" class="rounded-[16rpx] style-bg-3 p-[30rpx]"> <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 items-center justify-between style-border-3 mb-[22rpx] pb-[22rpx]">
<view class="flex flex-col"> <view class="flex flex-col flex-1">
<view class="flex items-center justify-between">
<view class="flex items-center"> <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')+')'}"> <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}} VIP.{{currIndex}}
</view> </view>
<text class="text-[#733F02] ml-[8rpx] text-[30rpx] font-bold max-w-[380rpx] truncate">{{info.member_level_name}}</text> <text class="text-[#733F02] ml-[8rpx] text-[30rpx] font-bold max-w-[380rpx] truncate">{{info.member_level_name}}</text>
</view> </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>
</view>
<text class="text-[28rpx] text-[#794200] mt-[16rpx]">购物或邀请好友可以提升等级</text> <text class="text-[28rpx] text-[#794200] mt-[16rpx]">购物或邀请好友可以提升等级</text>
</view> </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>
<view class="flex items-center justify-between"> <view class="flex items-center justify-between">
<view class="flex flex-col flex-1"> <view class="flex flex-col flex-1">

View File

@ -17,7 +17,7 @@
<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 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>
<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 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>
</view> </view>
@ -117,14 +117,11 @@ watch(
) )
const marqueeBodyWidth = ref(0); // const marqueeBodyWidth = ref(0); //
const marqueeOneWidth = ref(0); //
const marqueeStyle = ref(''); // const marqueeStyle = ref(''); //
const time = ref(0); // const time = ref(0); //
const delayTime = ref(800); // const delayTime = ref(800); //
// pxrpx
const pxToRpx=(px)=> {
const screenWidth = uni.getSystemInfoSync().screenWidth
return (750 * Number.parseInt(px)) / screenWidth
}
// //
const bindCrossSlipEvent = ()=> { const bindCrossSlipEvent = ()=> {
if (diyComponent.value.scrollWay == 'horizontal') { if (diyComponent.value.scrollWay == 'horizontal') {
@ -135,9 +132,9 @@ const bindCrossSlipEvent = ()=> {
marqueeBodyWidth.value = res.width; marqueeBodyWidth.value = res.width;
const query = uni.createSelectorQuery().in(instance); const query = uni.createSelectorQuery().in(instance);
query.select('#horizontal-body-' + diyComponent.value.id + ' .marquee-one').boundingClientRect((data: any) => { query.select('#horizontal-body-' + diyComponent.value.id + ' .marquee-one').boundingClientRect((data: any) => {
const width = data.width marqueeOneWidth.value = data.width
time.value = Math.ceil(width * 14); time.value = Math.ceil(marqueeOneWidth.value * 14);
if (marqueeBodyWidth.value > width) { if (marqueeBodyWidth.value > (marqueeOneWidth.value-30)) {
marqueeStyle.value = `animation: none;`; marqueeStyle.value = `animation: none;`;
} else { } else {
marqueeStyle.value = ` marqueeStyle.value = `
@ -152,9 +149,9 @@ const bindCrossSlipEvent = ()=> {
let marqueeOne = window.document.getElementById('marquee-one'); let marqueeOne = window.document.getElementById('marquee-one');
if(documentObj && marqueeOne) { if(documentObj && marqueeOne) {
marqueeBodyWidth.value = documentObj.offsetWidth; marqueeBodyWidth.value = documentObj.offsetWidth;
const width = marqueeOne.offsetWidth; marqueeOneWidth.value = marqueeOne.offsetWidth;
time.value = Math.ceil(width * 14); time.value = Math.ceil(marqueeOneWidth.value * 14);
if (marqueeBodyWidth.value > width) { if (marqueeBodyWidth.value > (marqueeOneWidth.value-30)) {
marqueeStyle.value = `animation: none;`; marqueeStyle.value = `animation: none;`;
} else { } else {
marqueeStyle.value = ` marqueeStyle.value = `
@ -199,12 +196,11 @@ const refresh = ()=> {
const toRedirect = (data: {}) => { const toRedirect = (data: {}) => {
if (diyStore.mode == 'decorate') return false; if (diyStore.mode == 'decorate') return false;
if (diyComponent.value.showType == 'popup') { if (diyComponent.value.showType == 'popup') {
noticeShow.value = true; noticeShow.value = true;
noticeContent.value = data.text; noticeContent.value = data.text;
} else { } else {
diyStore.toRedirect(data); diyStore.toRedirect(data.link);
} }
} }
</script> </script>
@ -276,8 +272,7 @@ const toRedirect = (data: {}) => {
align-items: center; align-items: center;
height: 100%; height: 100%;
white-space: nowrap; white-space: nowrap;
padding-right: 60rpx; padding-right: 30px;
// -webkit-perspective: 1000; // -webkit-perspective: 1000;
// -moz-perspective: 1000; // -moz-perspective: 1000;

View File

@ -6,5 +6,6 @@
"pleaceAgree": "请勾选已阅读并同意", "pleaceAgree": "请勾选已阅读并同意",
"mobilePlaceholder": "请输入手机号", "mobilePlaceholder": "请输入手机号",
"codePlaceholder": "请输入验证码", "codePlaceholder": "请输入验证码",
"weixinUserAuth": "微信用户一键绑定" "weixinUserAuth": "一键绑定",
"mobileQuickLogin": "手机号快捷登录"
} }

View File

@ -10,5 +10,6 @@
"isAgreeTips": "请先阅读并同意协议", "isAgreeTips": "请先阅读并同意协议",
"usernameLogin": "密码登录", "usernameLogin": "密码登录",
"mobileLogin": "验证码登录", "mobileLogin": "验证码登录",
"mobilePlaceholder": "请输入手机号" "mobilePlaceholder": "请输入手机号",
"oneClicklogin":"一键登录"
} }

View File

@ -1,13 +1,19 @@
<template> <template>
<view v-if="agreement" class="p-[30rpx]" :style="themeColor()"> <view :style="themeColor()">
<view v-if="agreement && agreement.content" class="p-[30rpx]">
<u-parse :content="agreement.content" :tagStyle="{img: 'vertical-align: top;'}"></u-parse> <u-parse :content="agreement.content" :tagStyle="{img: 'vertical-align: top;'}"></u-parse>
</view> </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> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue' import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app' import { onLoad } from '@dcloudio/uni-app'
import { getAgreementInfo } from '@/app/api/system' import { getAgreementInfo } from '@/app/api/system'
import { img} from '@/utils/common'
const agreement = ref(null) const agreement = ref(null)

View File

@ -10,11 +10,11 @@
<view class="px-[60rpx]"> <view class="px-[60rpx]">
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef"> <u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
<u-form-item label="" prop="mobile" :border-bottom="true"> <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> </u-form-item>
<view class="mt-[40rpx]"> <view class="mt-[40rpx]">
<u-form-item label="" prop="mobile_code" :border-bottom="true"> <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> <template #suffix>
<sms-code :mobile="formData.mobile" type="bind_mobile" v-model="formData.mobile_key"></sms-code> <sms-code :mobile="formData.mobile" type="bind_mobile" v-model="formData.mobile_key"></sms-code>
</template> </template>
@ -36,12 +36,12 @@
</view> </view>
</view> </view>
<view class="mt-[60rpx]"> <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> </view>
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<view class="mt-[30rpx]"> <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')" @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> </view>
<!-- #endif --> <!-- #endif -->
</u-form> </u-form>
@ -50,7 +50,7 @@
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 --> <!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup> <wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif --> <!-- #endif -->
</view> </view>
</template> </template>
@ -81,7 +81,7 @@
mobile_key: '' mobile_key: ''
}) })
let real_name_input = ref(true); const real_name_input = ref(true);
onMounted(() => { onMounted(() => {
// //
setTimeout(()=>{ setTimeout(()=>{
@ -153,6 +153,13 @@
}) })
} }
const wxPrivacyPopupRef:any = ref(null)
//
const checkWxPrivacy = ()=>{
wxPrivacyPopupRef.value.proactive();
}
const mobileAuth = (e) => { const mobileAuth = (e) => {
if (!isAgree.value && !info.value && config.value.agreement_show) { if (!isAgree.value && !info.value && config.value.agreement_show) {
uni.showToast({ uni.showToast({

View File

@ -17,21 +17,21 @@
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef"> <u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
<view v-show="type == 'username'"> <view v-show="type == 'username'">
<u-form-item label="" prop="username" :border-bottom="true"> <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> </u-form-item>
<view class="mt-[40rpx]"> <view class="mt-[40rpx]">
<u-form-item label="" prop="password" :border-bottom="true"> <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> </u-form-item>
</view> </view>
</view> </view>
<view v-show="type == 'mobile'"> <view v-show="type == 'mobile'">
<u-form-item label="" prop="mobile" :border-bottom="true"> <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> </u-form-item>
<view class="mt-[40rpx]"> <view class="mt-[40rpx]">
<u-form-item label="" prop="mobile_code" :border-bottom="true"> <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> <template #suffix>
<sms-code :mobile="formData.mobile" type="login" v-model="formData.mobile_key"></sms-code> <sms-code :mobile="formData.mobile" type="login" v-model="formData.mobile_key"></sms-code>
</template> </template>
@ -39,16 +39,24 @@
</u-form-item> </u-form-item>
</view> </view>
</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') }} <view @click="redirect({ url: '/app/pages/auth/register' })">{{ t('noAccount') }}
<text class="text-primary">{{ t('toRegister') }}</text> <text class="text-primary">{{ t('toRegister') }}</text>
</view> </view>
<view @click="redirect({ url: '/app/pages/auth/resetpwd' })">{{ t('resetpwd') }}</view> <view @click="redirect({ url: '/app/pages/auth/resetpwd' })">{{ t('resetpwd') }}</view>
</view> </view>
<view class="mt-[80rpx]"> <view class="mt-[80rpx]">
<u-button type="primary" :text="t('login')" :loading="loading" :loadingText="t('logining')" @click="handleLogin"> <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>
</u-button>
</view> </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> </u-form>
</view> </view>
</view> </view>
@ -63,17 +71,22 @@
<text class="text-primary">{{ t('privacyAgreement') }}</text> <text class="text-primary">{{ t('privacyAgreement') }}</text>
</view> </view>
</view> </view>
<!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif -->
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue' 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 useMemberStore from '@/stores/member'
import useConfigStore from '@/stores/config' import useConfigStore from '@/stores/config'
import { useLogin } from '@/hooks/useLogin' import { useLogin } from '@/hooks/useLogin'
import { t } from '@/locale' 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({ const formData = reactive({
username: '', username: '',
@ -83,7 +96,7 @@
mobile_key: '' mobile_key: ''
}) })
let real_name_input = ref(true); const real_name_input = ref(true);
onMounted(() => { onMounted(() => {
// //
setTimeout(()=>{ setTimeout(()=>{
@ -91,23 +104,34 @@
},800) },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 memberStore = useMemberStore()
const configStore = useConfigStore() 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 loading = ref(false)
const type = ref('') const type = ref('')
const loginType = computed(() => { const loginType = computed(() => {
const value = [] const value = []
configStore.login.is_username && (value.push({ type: 'username', title: t('usernameLogin') })) if(configStore.login.is_username){
configStore.login.is_mobile && (value.push({ type: 'mobile', title: t('mobileLogin') })) 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 : '' type.value = value[0] ? value[0].type : ''
return value return value
}) })
@ -169,12 +193,72 @@
login(formData).then((res) => { login(formData).then((res) => {
memberStore.setToken(res.data.token) memberStore.setToken(res.data.token)
if(configStore.login.is_bind_mobile && !res.data.mobile){
uni.setStorageSync('isbindmobile', true)
}
useLogin().handleLoginBack() useLogin().handleLoginBack()
}).catch(() => { }).catch(() => {
loading.value = false 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> </script>
<style lang="scss"> <style lang="scss">

View File

@ -1,5 +1,5 @@
<template> <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"> <view class="flex-1">
<!-- #ifdef H5 --> <!-- #ifdef H5 -->
<view class="h-[100rpx]"></view> <view class="h-[100rpx]"></view>
@ -18,31 +18,31 @@
<view v-show="type == 'username'"> <view v-show="type == 'username'">
<view class="mt-[30rpx]"> <view class="mt-[30rpx]">
<u-form-item label="" prop="username" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[30rpx]"> <view class="mt-[30rpx]">
<u-form-item label="" prop="password" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[30rpx]"> <view class="mt-[30rpx]">
<u-form-item label="" prop="confirm_password" :border-bottom="true"> <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> </u-form-item>
</view> </view>
</view> </view>
<view v-show="type == 'mobile' || configStore.login.is_bind_mobile"> <view v-show="type == 'mobile' || configStore.login.is_bind_mobile">
<view class="mt-[30rpx]"> <view class="mt-[30rpx]">
<u-form-item label="" prop="mobile" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[30rpx]"> <view class="mt-[30rpx]">
<u-form-item label="" prop="code" :border-bottom="true"> <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> <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> </template>
</u-input> </u-input>
</u-form-item> </u-form-item>
@ -51,7 +51,7 @@
<view v-show="type == 'username'"> <view v-show="type == 'username'">
<view class="mt-[30rpx]"> <view class="mt-[30rpx]">
<u-form-item label="" prop="captcha_code" :border-bottom="true"> <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> <template #suffix>
<image :src="captcha.image.value" class="h-[48rpx] w-[60rpx] ml-[20rpx]" mode="heightFix" @click="captcha.refresh()"></image> <image :src="captcha.image.value" class="h-[48rpx] w-[60rpx] ml-[20rpx]" mode="heightFix" @click="captcha.refresh()"></image>
</template> </template>
@ -59,12 +59,11 @@
</u-form-item> </u-form-item>
</view> </view>
</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 @click="redirect({ url: '/app/pages/auth/login' })">{{ t('haveAccount') }}<text class="text-primary">{{ t('toLogin') }}</text></view>
</view> </view>
<view class="mt-[80rpx]"> <view class="mt-[80rpx]">
<u-button type="primary" :text="t('register')" :loading="loading" :loadingText="t('registering')" @click="handleRegister"> <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>
</u-button>
</view> </view>
</u-form> </u-form>
</view> </view>
@ -91,7 +90,8 @@
import { useLogin } from '@/hooks/useLogin' import { useLogin } from '@/hooks/useLogin'
import { useCaptcha } from '@/hooks/useCaptcha' import { useCaptcha } from '@/hooks/useCaptcha'
import { t } from '@/locale' import { t } from '@/locale'
import { redirect } from '@/utils/common' import { redirect, getToken } from '@/utils/common'
import { onLoad } from '@dcloudio/uni-app';
const formData = reactive({ const formData = reactive({
username: '', username: '',
@ -104,7 +104,7 @@
captcha_code: '' captcha_code: ''
}) })
let real_name_input = ref(true); const real_name_input = ref(true);
onMounted(() => { onMounted(() => {
// //
setTimeout(()=>{ setTimeout(()=>{
@ -112,18 +112,27 @@
},800) },800)
}); });
const memberStore = useMemberStore()
const configStore = useConfigStore()
onLoad(async() =>{
await configStore.getLoginConfig()
if (!uni.getStorageSync('autoLoginLock')) { if (!uni.getStorageSync('autoLoginLock')) {
uni.getStorageSync('openid') && (Object.assign(formData, {openid: uni.getStorageSync('openid')})) uni.getStorageSync('openid') && (Object.assign(formData, {openid: uni.getStorageSync('openid')}))
uni.getStorageSync('pid') && (Object.assign(formData, {pid: uni.getStorageSync('pid')})) uni.getStorageSync('pid') && (Object.assign(formData, {pid: uni.getStorageSync('pid')}))
} }
uni.getStorageSync('unionid') && (Object.assign(formData, { unionid: uni.getStorageSync('unionid') })) 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) const captcha = useCaptcha(formData)
captcha.refresh() captcha.refresh()
const memberStore = useMemberStore()
const configStore = useConfigStore()
const loading = ref(false) const loading = ref(false)
const type = ref('') const type = ref('')

View File

@ -12,12 +12,12 @@
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef"> <u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef">
<view class="mt-[30rpx]"> <view class="mt-[30rpx]">
<u-form-item label="" prop="mobile" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[30rpx]"> <view class="mt-[30rpx]">
<u-form-item label="" prop="code" :border-bottom="true"> <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> <template #suffix>
<sms-code :mobile="formData.mobile" type="find_pass" v-model="formData.mobile_key"></sms-code> <sms-code :mobile="formData.mobile" type="find_pass" v-model="formData.mobile_key"></sms-code>
</template> </template>
@ -26,17 +26,16 @@
</view> </view>
<view class="mt-[30rpx]"> <view class="mt-[30rpx]">
<u-form-item label="" prop="password" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[30rpx]"> <view class="mt-[30rpx]">
<u-form-item label="" prop="confirm_password" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[80rpx]"> <view class="mt-[80rpx]">
<u-button type="primary" :text="t('confirm')" :loading="loading" :loadingText="t('confirm')" @click="handleConfirm"> <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>
</u-button>
</view> </view>
</u-form> </u-form>
</view> </view>
@ -58,7 +57,7 @@
confirm_password: '' confirm_password: ''
}) })
let real_name_input = ref(true); const real_name_input = ref(true);
onMounted(() => { onMounted(() => {
// //
setTimeout(()=>{ setTimeout(()=>{

View File

@ -23,7 +23,7 @@
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 --> <!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup> <wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif --> <!-- #endif -->
</view> </view>
@ -52,6 +52,9 @@
diyGroupRef.value?.refresh(); diyGroupRef.value?.refresh();
}); });
//
diy.onUnload();
// //
diy.onPullDownRefresh() diy.onPullDownRefresh()

View File

@ -23,7 +23,7 @@
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 --> <!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup> <wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif --> <!-- #endif -->
</view> </view>
@ -58,6 +58,9 @@
diyGroupRef.value?.refresh(); diyGroupRef.value?.refresh();
}); });
//
diy.onUnload();
// //
diy.onPullDownRefresh() diy.onPullDownRefresh()

View File

@ -1,8 +1,8 @@
<template> <template>
<view class="w-screen h-screen bg-page" :style="themeColor()"> <view class="w-screen h-screen bg-page" :style="themeColor()">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getCashoutAccountListFn"> <mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getCashoutAccountListFn">
<view class="h-[20rpx]"></view> <view class="h-[10rpx]"></view>
<u-swipe-action-item :options="accountOptions" @click="swipeClick(index)" v-for="(item, index) in accountList" :key="index" class="mx-[32rpx] my-[20rpx]"> <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="p-[30rpx] bg-white rounded flex justify-between" >
<view class="flex"> <view class="flex">
<view class="w-[100rpx] h-[100rpx] flex items-center justify-center mr-[10rpx]" @click="handleClick(item)"> <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> <text class="flex items-center nc-iconfont nc-icon-xiugaiV6xx shrink-0 text-[32rpx] p-[20rpx] pr-0" @click="editAccount(item)"></text>
</view> </view>
</u-swipe-action-item> </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> <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> <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> <u-icon name="arrow-right" color="#333" size="14"></u-icon>
@ -46,7 +46,7 @@
const mescrollRef = ref(null) const mescrollRef = ref(null)
const mode = ref('get') const mode = ref('get')
onLoad((data) => { onLoad((data: any) => {
data.type && (accountType.value = data.type) data.type && (accountType.value = data.type)
data.mode && (mode.value = data.mode) data.mode && (mode.value = data.mode)
}) })

View File

@ -1,27 +1,27 @@
<template> <template>
<view :style="themeColor()"> <view :style="themeColor()">
<scroll-view scroll-y="true" class="w-screen h-screen bg-page"> <scroll-view scroll-y="true" class="w-screen h-screen bg-page">
<view class="h-[30rpx]"></view> <view class="h-[20rpx]"></view>
<view class="p-[30rpx] bg-white mx-[32rpx] rounded"> <view class="p-[30rpx] bg-white sidebar-marign rounded">
<block v-if="formData.account_type == 'bank'"> <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-base font-bold mt-[50rpx]">{{ t('addBankCard') }}</view>
<view class="text-center text-sm mt-[10rpx]">{{ t('addBankCardTips') }}</view> <view class="text-center text-sm mt-[10rpx]">{{ t('addBankCardTips') }}</view>
<view class="mt-[50rpx]"> <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]"> <view class="mt-[10rpx]">
<u-form-item :label="t('bankRealname')" prop="realname" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[10rpx]"> <view class="mt-[10rpx]">
<u-form-item :label="t('bankName')" prop="bank_name" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[10rpx]"> <view class="mt-[10rpx]">
<u-form-item :label="t('bankAccountNo')" prop="account_no" :border-bottom="true"> <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> </u-form-item>
</view> </view>
</u-form> </u-form>
@ -49,12 +49,12 @@
</block> </block>
<view class="mt-[100rpx]"> <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>
</view> </view>
</scroll-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> </view>
</template> </template>
@ -100,13 +100,13 @@
} }
}) })
onLoad((data) => { onLoad((data: any) => {
data.type && (formData.account_type = data.type) data.type && (formData.account_type = data.type)
data.mode && (mode.value = data.mode) data.mode && (mode.value = data.mode)
if (data.id) { if (data.id) {
formData.account_id = 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) { if (res.data) {
Object.keys(formData).forEach((key : string) => { Object.keys(formData).forEach((key : string) => {
if (res.data[key] != undefined) formData[key] = res.data[key] if (res.data[key] != undefined) formData[key] = res.data[key]

View File

@ -2,7 +2,7 @@
<view v-if="!loading" :style="themeColor()"> <view v-if="!loading" :style="themeColor()">
<scroll-view scroll-y="true"> <scroll-view scroll-y="true">
<u-swipe-action> <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"> <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="border-0 !border-b !border-[#f5f5f5] border-solid pb-[30rpx] flex items-center">
<view class="flex-1 line-feed" @click="selectAddress(item)"> <view class="flex-1 line-feed" @click="selectAddress(item)">
@ -23,7 +23,7 @@
</u-swipe-action> </u-swipe-action>
<u-tabbar :fixed="true" :safeAreaInsetBottom="true" :border="false" zIndex="99"> <u-tabbar :fixed="true" :safeAreaInsetBottom="true" :border="false" zIndex="99">
<view class="p-[24rpx] pt-0 w-full"> <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> </view>
</u-tabbar> </u-tabbar>
</scroll-view> </scroll-view>
@ -45,7 +45,7 @@
const type = ref('') const type = ref('')
const source = ref('') const source = ref('')
onLoad((data) => { onLoad((data: any) => {
type.value = data.type || '' type.value = data.type || ''
source.value = data.source || '' source.value = data.source || ''
if (data.type) current.value = data.type == 'address' ? 0 : 1 if (data.type) current.value = data.type == 'address' ? 0 : 1

View File

@ -1,29 +1,29 @@
<template> <template>
<view class="px-[30rpx] pt-[10rpx]" :style="themeColor()"> <view class="sidebar-marign pt-[10rpx]" :style="themeColor()">
<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=""> <view class="">
<u-form-item :label="t('name')" prop="name" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[10rpx]"> <view class="mt-[10rpx]">
<u-form-item :label="t('mobile')" prop="mobile" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[10rpx]"> <view class="mt-[10rpx]">
<u-form-item :label="t('selectArea')" prop="area" :border-bottom="true" > <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 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-if="!formData.area" class="text-gray-placeholder text-[28rpx] flex-1">{{ t('selectAreaPlaceholder') }}</view>
<view v-else class="text-[30rpx] flex-1">{{ formData.area }}</view> <view v-else class="text-[28rpx] flex-1">{{ formData.area }}</view>
<view @click.stop="chooseLocation" class="flex items-center"> <view @click.stop="chooseLocation" class="flex items-center">
<text class="nc-iconfont nc-icon-dizhiguanliV6xx mr-[4rpx] text-[32rpx] text-[#e93323]"></text> <text class="nc-iconfont nc-icon-dizhiguanliV6xx mr-[4rpx] text-[32rpx] text-[#e93323]"></text>
<text class="text-[24rpx] whitespace-nowrap">定位</text> <text class="text-[24rpx] whitespace-nowrap">定位</text>
</view> </view>
</view> </view>
<view v-else class="flex justify-between items-center flex-1" @click="chooseLocation"> <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-[28rpx] 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-[#c3c4d5] text-[28rpx]" v-else>{{t('selectAddressPlaceholder')}}</view>
<view class="flex items-center"> <view class="flex items-center">
<text class="nc-iconfont nc-icon-dizhiguanliV6xx text-[32rpx] mr-[4rpx] text-[#e93323]"></text> <text class="nc-iconfont nc-icon-dizhiguanliV6xx text-[32rpx] mr-[4rpx] text-[#e93323]"></text>
<text class="text-[24rpx] whitespace-nowrap">定位</text> <text class="text-[24rpx] whitespace-nowrap">定位</text>
@ -33,7 +33,7 @@
</view> </view>
<view class="mt-[10rpx]"> <view class="mt-[10rpx]">
<u-form-item :label="t('address')" prop="address" :border-bottom="true"> <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> </u-form-item>
</view> </view>
<view class="mt-[10rpx]"> <view class="mt-[10rpx]">
@ -42,13 +42,13 @@
</u-form-item> </u-form-item>
</view> </view>
<view class="mt-[40rpx]"> <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> </view>
</u-form> </u-form>
<area-select ref="areaRef" @complete="areaSelectComplete" :area-id="formData.district_id"/> <area-select ref="areaRef" @complete="areaSelectComplete" :area-id="formData.district_id"/>
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 --> <!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup> <wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif --> <!-- #endif -->
</view> </view>
@ -82,23 +82,21 @@
const formRef = ref(null) const formRef = ref(null)
const source = ref('') const source = ref('')
const btnDisabled = ref(false) const btnDisabled = ref(false)
let isSelectAddress = ref(false) const isSelectAddress = ref(false)
let addressType = ref('address'); const addressType = ref('address');
let isSelectMap = ref(2) // 1 const isSelectMap = ref(2) // 1
onLoad((data) => { onLoad((data: any) => {
isSelectMap.value = data.isSelectMap || ''; isSelectMap.value = data.isSelectMap || '';
const selectAddress = uni.getStorageSync('selectAddressCallback') const selectAddress = uni.getStorageSync('selectAddressCallback')
if (data.id) { if (data.id) {
getAddressInfo(data.id) getAddressInfo(data.id).then(res => {
.then(res => {
res.data && Object.assign(formData.value, res.data) res.data && Object.assign(formData.value, res.data)
// //
if(selectAddress){ if(selectAddress){
addressType.value = selectAddress.delivery == 'express' ? 'address' : 'locationAddress'; addressType.value = selectAddress.delivery == 'express' ? 'address' : 'locationAddress';
} }
}) })
.catch()
}else if (data.name) { }else if (data.name) {
if (uni.getStorageSync('addressInfo')) { if (uni.getStorageSync('addressInfo')) {
@ -199,7 +197,6 @@
return false; return false;
} }
save(formData.value).then((res) => { save(formData.value).then((res) => {
operateLoading.value = false operateLoading.value = false
setTimeout(() => { setTimeout(() => {
@ -274,7 +271,6 @@
// #endif // #endif
} }
// //
const getAddress = (latlng:any)=> { const getAddress = (latlng:any)=> {
getAddressByLatlng({latlng}).then((res: any) => { getAddressByLatlng({latlng}).then((res: any) => {
@ -310,4 +306,6 @@
} }
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped>
</style>

View File

@ -1,18 +1,18 @@
<template> <template>
<view :style="themeColor()"> <view :style="themeColor()">
<scroll-view scroll-y="true" class="w-screen h-screen bg-page" v-if="!pageLoading && config.is_open == 1"> <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="sidebar-marign pt-[20rpx]">
<view class="p-[20rpx] bg-white rounded-[16rpx]"> <view class="card-template">
<view class="font-500 text-[32rpx] text-[#333] leading-[44rpx]">{{t('cashOutMoneyTip')}}</view> <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"> <view class="flex pt-[30rpx] pb-[8rpx] items-center border-0 border-b-[2rpx] border-solid border-[#F1F2F5]">
<text class="text-[54rpx] font-bold leading-[76rpx] ">{{ t('currency') }}</text> <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"/> <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" <image @click="clearMoney" v-if="applyData.apply_money"
:src="img('static/resource/images/member/apply_withdrawal/close.png')" class="w-[40rpx] h-[40rpx]" :src="img('static/resource/images/member/apply_withdrawal/close.png')" class="w-[40rpx] h-[40rpx]"
mode="widthFix" /> mode="widthFix" />
</view> </view>
<view class="pt-[18rpx] flex items-center justify-between mb-[20rpx]"> <view class="pt-[20rpx] flex items-center justify-between">
<view class="text-[26rpx] text-[#666] leading-[36rpx]"> <view class="text-[26rpx] text-[#626779] leading-[36rpx]">
<text>{{t('money')}}{{ t('currency') }}{{ moneyFormat(cashOutMoney) }}</text> <text>{{t('money')}}{{ t('currency') }}{{ moneyFormat(cashOutMoney) }}</text>
<text>{{t('commissionTo')}}{{ config.rate + '%' }}</text> <text>{{t('commissionTo')}}{{ config.rate + '%' }}</text>
</view> </view>
@ -20,10 +20,10 @@
</view> </view>
</view> </view>
<view class="px-[20rpx] pt-[20rpx] pb-[30rpx] bg-white mt-[20rpx] rounded-[16rpx]"> <view class="mt-[20rpx] card-template">
<view class="font-500 text-[32rpx] text-[#333] leading-[44rpx] mb-[20rpx]">到账方式</view> <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> <view>
<image class="h-[60rpx] w-[60rpx]" :src="img('static/resource/images/member/apply_withdrawal/wechat.png')" mode="widthFix" /> <image class="h-[60rpx] w-[60rpx]" :src="img('static/resource/images/member/apply_withdrawal/wechat.png')" mode="widthFix" />
</view> </view>
@ -34,7 +34,7 @@
</view> </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" > <view @click="transferAlipay" >
<image class="h-[60rpx] w-[60rpx] align-middle" :src="img('static/resource/images/member/apply_withdrawal/alipay-icon.png')" mode="widthFix" /> <image class="h-[60rpx] w-[60rpx] align-middle" :src="img('static/resource/images/member/apply_withdrawal/alipay-icon.png')" mode="widthFix" />
</view> </view>
@ -55,7 +55,7 @@
</view> </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" > <view @click="transferBank" >
<image class="h-[42rpx] w-[60rpx] align-middle" :src="img('static/resource/images/member/apply_withdrawal/bank-icon.png')" mode="widthFix" /> <image class="h-[42rpx] w-[60rpx] align-middle" :src="img('static/resource/images/member/apply_withdrawal/bank-icon.png')" mode="widthFix" />
</view> </view>
@ -72,23 +72,23 @@
</view> </view>
</view> </view>
<view class="flex items-center"> <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> <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> <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>
</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'})"> <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')}} {{t('cashOutList')}}
</view> </view>
</view> </view>
</view>
</scroll-view> </scroll-view>
<block v-if="config.is_open == 0 && !pageLoading"> <view class="h-[100vh] w-[100vw] flex justify-center items-center" v-if="config.is_open == 0 && !pageLoading">
<u-empty :text="t('isOpenApply')" :icon="img('static/resource/images/empty.png')"/> <u-empty :text="t('isOpenApply')" width="320rpx" height="244rpx" :icon="img('static/resource/images/empty.png')"/>
</block> </view>
<u-loading-page :loading="pageLoading" bg-color="#e8e8e8" loading-text=""></u-loading-page> <u-loading-page :loading="pageLoading" bg-color="#e8e8e8" loading-text=""></u-loading-page>
</view> </view>
</template> </template>
@ -156,7 +156,18 @@
title: t('abnormalOperation'), title: t('abnormalOperation'),
icon: 'none', icon: 'none',
success() { 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 return
@ -301,7 +312,7 @@
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.apply-price){ :deep(.apply-price){
color:#999; color: #8288A2;
font-size: 26rpx; font-size: 26rpx;
font-weight: normal; font-weight: normal;
line-height: 76rpx; line-height: 76rpx;

View File

@ -3,7 +3,7 @@
<view class="fixed w-full z-2 !bg-[#F6F6F6]"> <view class="fixed w-full z-2 !bg-[#F6F6F6]">
<view class="pb-[203rpx] text-[#fff] w-full" :style="headerStyle"> <view class="pb-[203rpx] text-[#fff] w-full" :style="headerStyle">
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<top-tabbar :data="param" titleColor="#fff" class="top-header"/> <top-tabbar :data="param" class="top-header"/>
<!-- #endif --> <!-- #endif -->
<view class="leading-[39rpx] text-[28rpx] pl-[53rpx] pt-[79rpx]">{{t('accountBalance')}}</view> <view class="leading-[39rpx] text-[28rpx] pl-[53rpx] pt-[79rpx]">{{t('accountBalance')}}</view>
<view class="flex items-baseline pl-[53rpx]"> <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> <text class="text-[70rpx] leading-[98rpx]">{{ memberStore.info ? moneyFormat((parseFloat(memberStore.info.balance) + parseFloat(memberStore.info.money)).toString()) : '0.00' }}</text>
</view> </view>
</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="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=" text-[#999] text-[24rpx] leading-[34rpx] font-400">{{t('money')}}</view>
<view class="flex items-baseline text-[#333]"> <view class="flex items-baseline text-[#333]">
@ -21,22 +21,26 @@
</view> </view>
<view class="mt-[50rpx] flex justify-between" v-if="Object.keys(cashOutConfigObj).length && (systemStore.siteAddons.includes('recharge') || cashOutConfigObj.is_open == 1)"> <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> @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" <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;" shape="circle" @click="applyCashOut">{{t('cashOut')}}</view> style="background: linear-gradient( 94deg, #FB7939 0%, #FE120E 99%), #EF000C;" @click="applyCashOut">{{t('cashOut')}}</view>
</view> </view>
</view> </view>
<view class=" box-border px-[30rpx] w-full mt-[20rpx]"> <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%]"> <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 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 :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> </view>
</scroll-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> </view>
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="getListFn" :top="mescrollTop"> </view>
<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 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="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-bold leading-[80rpx] text-[#fff]"
@ -59,7 +63,7 @@
</view> </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="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> <mescroll-empty></mescroll-empty>
</view> </view>
</view> </view>
@ -67,33 +71,34 @@
</mescroll-body> </mescroll-body>
<u-loading-page bg-color="rgb(248,248,248)" :loading="loading" loadingText="" fontSize="16" color="#303133"></u-loading-page> <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> --> <!-- <pay ref="payRef" @close="rechargeLoading = false"></pay> -->
<!-- 时间选择 -->
<select-date ref="selectDateRef" @confirm="confirmFn" />
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive,computed } from 'vue' import { ref, reactive,computed } from 'vue'
import { t } from '@/locale' 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 { cashOutConfig,getBalanceListAll } from '@/app/api/member';
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue'; import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'; import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
import useMescroll from '@/components/mescroll/hooks/useMescroll.js'; 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 useMemberStore from '@/stores/member'
import useSystemStore from '@/stores/system' 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 { downCallback,mescrollInit, getMescroll } = useMescroll(onPageScroll, onReachBottom);
const memberStore = useMemberStore() const memberStore = useMemberStore()
const systemStore = useSystemStore() const systemStore = useSystemStore()
let param = ref({
title:'我的余额', /********* 自定义头部 - start ***********/
topStatusBar: { const topTabarObj = topTabar()
style: 'style-1', let param = topTabarObj.setTopTabbarParam({title:'我的余额'})
isTransparent: true, /********* 自定义头部 - end ***********/
bgColor: 'transparent',
textColor: '#fff'
}
})
const cashOutConfigObj = reactive({}) const cashOutConfigObj = reactive({})
onShow(() => { onShow(() => {
cashOutConfig().then((res) => { cashOutConfig().then((res) => {
@ -116,19 +121,24 @@
backgroundSize: 'cover', backgroundSize: 'cover',
backgroundRepeat: 'no-repeat', backgroundRepeat: 'no-repeat',
backgroundPosition: 'bottom', backgroundPosition: 'bottom',
// paddingTop:Object.keys(menuButtonInfo).length?(Number(menuButtonInfo.height) * 2 + menuButtonInfo.top * 2 + 99)+'rpx':'99rpx',
} }
}) })
const mescrollTop = computed(()=>{ 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'
// pxrpx }else{
const pxToRpx=(px)=> { return '669rpx'
const screenWidth = uni.getSystemInfoSync().screenWidth
return (750 * Number.parseInt(px)) / screenWidth
} }
}else {
if(Object.keys(menuButtonInfo).length){
return (pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) +pxToRpx(8)+566)+'rpx'
}else{
return '566rpx'
}
}
})
// //
const accountTypeList = ref([ const accountTypeList = ref([
@ -138,6 +148,7 @@
{name:'提现',key:'cash_out'}, {name:'提现',key:'cash_out'},
]) ])
const fromType = ref('') const fromType = ref('')
const create_time = ref([])
// //
const subActive = ref(0) const subActive = ref(0)
const fromTypeFn = (key,index)=>{ const fromTypeFn = (key,index)=>{
@ -168,7 +179,8 @@
let data : Object = { let data : Object = {
page: mescroll.num, page: mescroll.num,
limit: mescroll.size, limit: mescroll.size,
from_type:fromType.value trade_type:fromType.value,
create_time: create_time.value
}; };
interface acceptingDataStructure { interface acceptingDataStructure {
@ -177,12 +189,12 @@
code : number code : number
} }
interface acceptingDataItemStructure { interface acceptingDataItemStructure {
data : object, data : [],
[propName : string] : number | string | object [propName : string] : number | string | object
} }
getBalanceListAll(data).then((res : acceptingDataStructure) => { getBalanceListAll(data).then((res : acceptingDataStructure) => {
let newArr = res.data.data;- let newArr = res.data.data;
mescroll.endSuccess(newArr.length); mescroll.endSuccess(newArr.length);
// //
if (mescroll.num == 1) { if (mescroll.num == 1) {
@ -197,6 +209,17 @@
mescroll.endErr(); // , mescroll.endErr(); // ,
}) })
} }
//
const selectDateRef = ref()
const handleSelect = () =>{
selectDateRef.value.show = true
}
//
const confirmFn = (data) =>{
create_time.value = data;
list.value = []
getMescroll().resetUpScroll();
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -226,4 +249,5 @@
.pl-20rpx{ .pl-20rpx{
padding-left: 20rpx; padding-left: 20rpx;
} }
</style> </style>

View File

@ -1,6 +1,6 @@
<template> <template>
<view class="member-record-list" :style="themeColor()"> <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 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="name">{{item.transfer_type_name}}</view>
<view class="desc">{{t('applyTime')}}: {{item.create_time}}</view> <view class="desc">{{t('applyTime')}}: {{item.create_time}}</view>
@ -8,9 +8,7 @@
<view class="money" :class="item.apply_money > 0 ? 'text-active' : ''"> <view class="money" :class="item.apply_money > 0 ? 'text-active' : ''">
{{ item.apply_money > 0 ? '+' + item.apply_money : item.apply_money }} {{ item.apply_money > 0 ? '+' + item.apply_money : item.apply_money }}
</view> </view>
<view class="state"> <view class="state">{{ item.status_name }}</view>
{{ item.status_name }}
</view>
</view> </view>
<mescroll-empty v-if="!cashOutList.length && loading" :option="{tip : t('emptyTip')}"></mescroll-empty> <mescroll-empty v-if="!cashOutList.length && loading" :option="{tip : t('emptyTip')}"></mescroll-empty>
</mescroll-body> </mescroll-body>
@ -29,9 +27,9 @@ import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom); const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
let cashOutList = ref<Array<any>>([]); const cashOutList = ref<Array<any>>([]);
let mescrollRef = ref(null); const mescrollRef = ref(null);
let loading = ref<boolean>(false); const loading = ref<boolean>(false);
let account_type = uni.getStorageSync('cashOutAccountType') let account_type = uni.getStorageSync('cashOutAccountType')
const currentStatusDesc = (status) =>{ const currentStatusDesc = (status) =>{
switch(status){ switch(status){
@ -47,12 +45,12 @@ const currentStatusDesc = (status) =>{
} }
const getCashOutListFn = (mescroll)=>{ const getCashOutListFn = (mescroll)=>{
let data = ref({}); let data:any = {}
loading.value = false; loading.value = false;
data.value.page = mescroll.num; data.page = mescroll.num;
data.value.page_size = mescroll.size; data.page_size = mescroll.size;
data.value.account_type = account_type; data.account_type = account_type;
getCashOutList(data.value).then((res) => { getCashOutList(data).then((res) => {
let newArr = res.data.data; let newArr = res.data.data;
mescroll.endSuccess(newArr.length); mescroll.endSuccess(newArr.length);
// //

View File

@ -56,9 +56,9 @@ import { t } from '@/locale'
import { redirect, img } from '@/utils/common'; import { redirect, img } from '@/utils/common';
import { getCashOutDetail } from '@/app/api/member'; import { getCashOutDetail } from '@/app/api/member';
let cashOutInfo = ref({}); const cashOutInfo = ref({});
let loading = ref<boolean>(true); const loading = ref<boolean>(true);
onLoad((option) => { onLoad((option: any) => {
let id = option.id || ""; let id = option.id || "";
getCashoutAccountListFn(id) getCashoutAccountListFn(id)
}) })

View File

@ -1,38 +1,32 @@
<template> <template>
<view class="bg-[#F6F6F6] min-h-[100vh] w-full" :style="themeColor()" v-if="memberStore.info"> <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="fixed w-full z-2 !bg-[#F6F6F6]">
<view class="pb-[174rpx]" :style="headerStyle"> <view class="pb-[272rpx]" :style="headerStyle">
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<top-tabbar :data="param" class="top-header"/> <top-tabbar :data="param" class="top-header"/>
<!-- #endif --> <!-- #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-[-232rpx] sidebar-marign" :style="{ backgroundImage: 'url(' + img('static/resource/images/member/commission/account_bg.png') + ')',backgroundRepeat:'no-repeat',backgroundSize:'100% 100%'}">
</view> <view class="pt-[40rpx]">
<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="flex items-center justify-between px-[30rpx]"> <view class="flex items-center justify-between px-[30rpx]">
<view> <view>
<view class="text-[26rpx] font-500 text-[#fff] leading-[36rpx] mb-[8rpx]">{{t('accountCommission')}}</view> <view class="text-[26rpx] font-400 text-[#fff] leading-[36rpx] mb-[16rpx]">{{t('accountCommission')}}</view>
<view class="text-[56rpx] font-bold text-[#fff] leading-[68rpx]">{{ memberStore.info ? moneyFormat(memberStore.info.commission) : 0.00 }}</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>
</view> </view>
<view class="h-[1rpx] bg-[#fff] opacity-30 mt-[80rpx] mb-[20rpx]"></view> <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 class="flex items-center px-[30rpx]"> </view>
<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="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' }} {{ moneyFormat(memberStore.info?.commission_get)|| '0.00' }}
</view> </view>
<view class="text-[26rpx] text-[#fff] leading-[36rpx]">{{ t('commission') }}</view> <view class="text-[26rpx] text-[#fff] leading-[36rpx]">{{ t('commission') }}</view>
</view> </view>
<view class="flex-1"> <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' }} {{ moneyFormat(memberStore.info?.commission_cash_outing)|| '0.00' }}
</view> </view>
<view class="text-[26rpx] text-[#fff] leading-[36rpx]">{{ t('money') }}</view> <view class="text-[26rpx] text-[#fff] leading-[36rpx]">{{ t('money') }}</view>
@ -40,41 +34,46 @@
</view> </view>
</view> </view>
</view> </view>
<view class="mt-[40rpx] box-border px-[15rpx]"> <view class="mt-[40rpx] tab-style-1">
<view class="flex whitespace-nowrap"> <view class="tab-left">
<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="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> </view>
</view> </view>
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="geCommissiontListFn" :top="mescrollTop"> <mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" @up="geCommissionListFn" :top="mescrollTop">
<view class="px-[30rpx] pt-[20rpx] body-bottom" v-if="list.length"> <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-[120rpx] flex justify-between items-center bg-[#fff] box-border p-[20rpx] rounded-[16rpx]" :class="{'mt-[20rpx]':index}"> <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="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 }"> :class="{'bg-[#EF000C]' :item.account_data > 0, 'bg-[#1379FF]':item.account_data <= 0 }">
{{item.account_data > 0?'收':'提'}} {{item.account_data > 0?'收':'提'}}
</view> </view>
<view class="flex flex-col ml-[20rpx]"> <view class="flex flex-col ml-[20rpx]">
<view class="text-[#333] text-[26rpx] leading-[36rpx]">{{item.from_type_name}}</view> <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> </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 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> </view>
<view class="box-border pt-[20rpx] px-[30rpx] body-bottom" :style="{'height':'calc(100vh - '+ mescrollTop +')'}" v-if="!list.length && !loading &&!listLoading"> <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> <mescroll-empty></mescroll-empty>
</view> </view>
</view> </view>
</mescroll-body> </mescroll-body>
<u-loading-page bg-color="rgb(248,248,248)" :loading="loading" loadingText="" fontSize="16" color="#303133"></u-loading-page> <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> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { computed, ref, reactive } from 'vue'
import { t } from '@/locale' import { t } from '@/locale'
import { moneyFormat, redirect, img } from '@/utils/common'; import { moneyFormat, redirect, img } from '@/utils/common';
import useMemberStore from '@/stores/member' import useMemberStore from '@/stores/member'
@ -82,7 +81,9 @@
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue'; import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'; import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
import useMescroll from '@/components/mescroll/hooks/useMescroll.js'; 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 { downCallback,mescrollInit, getMescroll } = useMescroll(onPageScroll, onReachBottom);
const memberStore = useMemberStore(); const memberStore = useMemberStore();
@ -93,15 +94,11 @@
redirect({ url: '/app/pages/member/apply_cash_out' }) redirect({ url: '/app/pages/member/apply_cash_out' })
} }
let param = ref({ /********* 自定义头部 - start ***********/
title:'我的佣金', const topTabarObj = topTabar()
topStatusBar: { let param = topTabarObj.setTopTabbarParam({title:'我的佣金',topStatusBar:{bgColor: '#fff',textColor: '#333'}})
isTransparent: true, /********* 自定义头部 - end ***********/
style: 'style-1',
bgColor: 'transparent',
textColor: '#333'
}
})
// //
let menuButtonInfo:any = {}; let menuButtonInfo:any = {};
// (API) // (API)
@ -113,12 +110,12 @@
backgroundImage: 'url(' + img('static/resource/images/member/commission/commission_bg.png') + ') ', backgroundImage: 'url(' + img('static/resource/images/member/commission/commission_bg.png') + ') ',
backgroundSize: 'cover', backgroundSize: 'cover',
backgroundRepeat: 'no-repeat', backgroundRepeat: 'no-repeat',
backgroundPosition: 'center', backgroundPosition: 'bottom',
} }
}) })
// 16padding-bottom // 16padding-bottom
const mescrollTop = computed(()=>{ 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:'',account_data_gt: 0},
{name:'提现',from_type:'cash_out',account_data_gt: ''}, {name:'提现',from_type:'cash_out',account_data_gt: ''},
]) ])
const create_time = ref([])
const list = ref<Array<any>>([]) const list = ref<Array<any>>([])
const loading = ref<boolean>(true) const loading = ref<boolean>(true)
const listLoading = ref<boolean>(true) const listLoading = ref<boolean>(true)
@ -141,13 +139,14 @@
fromType.value.account_data_gt = data.account_data_gt fromType.value.account_data_gt = data.account_data_gt
getMescroll().resetUpScroll(); getMescroll().resetUpScroll();
} }
const geCommissiontListFn = (mescroll) => { const geCommissionListFn = (mescroll) => {
listLoading.value = true; listLoading.value = true;
let data : Object = { let data : Object = {
page: mescroll.num, page: mescroll.num,
limit: mescroll.size, limit: mescroll.size,
from_type:fromType.value.from_type, 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) => { getMemberCommission(data).then((res:any) => {
let newArr = res.data.data;- let newArr = res.data.data;-
@ -165,6 +164,17 @@
mescroll.endErr(); // , mescroll.endErr(); // ,
}) })
} }
//
const selectDateRef = ref()
const handleSelect = () =>{
selectDateRef.value.show = true
}
//
const confirmFn = (data) =>{
create_time.value = data;
list.value = []
getMescroll().resetUpScroll();
}
</script> </script>
<style lang="scss"> <style lang="scss">
@ -172,22 +182,6 @@
background: linear-gradient( 360deg, #F23621 11%, #FF7F71 100%), #D9D9D9; background: linear-gradient( 360deg, #F23621 11%, #FF7F71 100%), #D9D9D9;
border-radius: 0rpx 20rpx 20rpx 0rpx; 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){ :deep(.uni-scroll-view){
overflow: auto hidden !important; overflow: auto hidden !important;
} }

View 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>

View 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>

View File

@ -1,34 +1,56 @@
<template> <template>
<view class="member-record-list" :style="themeColor()"> <view class="min-h-[100vh] bg-[#F6F6F6] overflow-hidden" :style="themeColor()">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getListFn" top=""> <view class="fixed left-0 right-0 top-0 z-99">
<view v-for="(item,index) in list" :key="item.id" class="member-record-item"> <view class="bg-[#fff] px-[var(--sidebar-m)] h-[88rpx] flex items-center">
<view class="name">{{item.from_type_name}}</view> <view class="flex-1 flex items-center h-[60rpx] bg-[#F8F9FD] rounded-[30rpx] px-[20rpx]">
<view class="desc" v-if="item.memo">{{item.memo}}</view> <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>
<view class="desc">{{item.create_time}}</view> <text class="nc-iconfont nc-icon-sousuo-duanV6xx1 text-[28rpx] ml-[32rpx] !text-[#999]" @click="searchTypeFn()"></text>
<view class="money" :class="item.account_data > 0 ? 'text-active' : ''">
{{ item.account_data > 0 ? '+' + item.account_data : item.account_data }}
</view> </view>
</view> </view>
<mescroll-empty v-if="!list.length && loading" :option="{tip : tip}"></mescroll-empty> <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-body> </mescroll-body>
<!-- 时间选择 -->
<select-date ref="selectDateRef" @confirm="confirmFn" />
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref,nextTick } from 'vue' import { ref,nextTick, reactive } from 'vue'
import { t } from '@/locale' import { t } from '@/locale'
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue'; import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'; import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
import useMescroll from '@/components/mescroll/hooks/useMescroll.js'; import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
import { getBalanceList, getMoneyList, getCommissionList} from '@/app/api/member'; import { getBalanceList, getMoneyList, getCommissionList} from '@/app/api/member';
import { onPageScroll, onReachBottom, onLoad, onShow } from '@dcloudio/uni-app'; 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 { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
const type = ref('') const type = ref('')
const tip = ref('') const tip = ref('')
onLoad((options) => { onLoad((options: any) => {
type.value = options.type || 'balance'; type.value = options.type || 'balance';
nextTick(()=>{ nextTick(()=>{
setTimeout(()=>{ 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>>([]), const list = ref<Array<any>>([]),
loading = ref<boolean>(false), loading = ref<boolean>(false),
mescrollRef = ref(null); mescrollRef = ref(null);
@ -58,7 +92,11 @@
loading.value = false; loading.value = false;
let data : Object = { let data : Object = {
page: mescroll.num, 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 { interface acceptingDataStructure {
data : acceptingDataItemStructure, data : acceptingDataItemStructure,
@ -89,8 +127,36 @@
mescroll.endErr(); // , 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> </script>
<style lang="scss"> <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> </style>

View File

@ -23,7 +23,7 @@
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 --> <!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup> <wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif --> <!-- #endif -->
</view> </view>
@ -66,6 +66,9 @@
} }
}); });
//
diy.onUnload();
// //
diy.onPullDownRefresh() diy.onPullDownRefresh()

View File

@ -3,22 +3,18 @@
<u-loading-page :loading="loading && memberInfo" loadingText="" bg-color="#f7f7f7"></u-loading-page> <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 }"> <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 --> <!-- #ifdef MP -->
<top-tabbar :data="topTabbarData" titleColor="#fff"/> <top-tabbar :data="topTabbarData" :scrollBool="topTabarObj.getScrollBool()"/>
<!-- #endif --> <!-- #endif -->
<view> <view>
<view class="pt-[40rpx] mb-[20rpx]"> <view class="pt-[40rpx] mb-[20rpx]">
<!-- 轮播图 --> <!-- 轮播图 -->
<view class="relative"> <view class="relative">
<swiper class="swiper ns-indicator-dots relative" :style="{ height: '300rpx' }" @change="swiperChange" :current = "swiperIndex" <swiper class="swiper ns-indicator-dots relative" :style="{ height: '300rpx' }" @change="swiperChange" :current = "swiperIndex" previous-margin="48rpx" next-margin="48rpx">
previous-margin="48rpx" next-margin="48rpx">
<swiper-item class="swiper-item" v-for="(item,index) in list" :key="item.id"> <swiper-item class="swiper-item" v-for="(item,index) in list" :key="item.id">
<view class="h-[300rpx] relative"> <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>
<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="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]"> <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" /> <image class="h-[32rpx] w-[34rpx] align-middle" :src="img(item.level_icon ? item.level_icon : '')" mode="aspectFill" />
@ -26,7 +22,7 @@
</view> </view>
<view class="flex items-center" :style="{color: currLevelInfo.level_style.level_color}"> <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-[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>
<view class="flex justify-between items-center mt-[10rpx]"> <view class="flex justify-between items-center mt-[10rpx]">
<view class="flex flex-col flex-1"> <view class="flex flex-col flex-1">
@ -60,14 +56,14 @@
</scroll-view> </scroll-view>
</view> </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"> <view class="flex items-center justify-center">
<text class="text-[#fff] text-[32rpx] font-bold leading-[44rpx]">会员权益</text> <text class="text-[#fff] text-[32rpx] font-bold leading-[44rpx]">会员权益</text>
</view> </view>
<view class="flex flex-wrap w-[690rpx] mt-[40rpx] justify-between"> <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"> <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" /> <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> </view>
</view> </view>
@ -77,7 +73,7 @@
<!-- 升级礼包 --> <!-- 升级礼包 -->
<view v-if="currLevelInfo.gifts_arr && currLevelInfo.gifts_arr.length"> <view v-if="currLevelInfo.gifts_arr && currLevelInfo.gifts_arr.length">
<view class="pt-[10rpx] pb-[30rpx] flex items-center"> <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>
<view class="flex flex-wrap"> <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}"> <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> </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> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' 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 { getMemberLevel, getTaskGrowth } from '@/app/api/member';
import { img,redirect, deepClone, getToken } from '@/utils/common'; import { img,redirect, deepClone, getToken } from '@/utils/common';
import useMemberStore from '@/stores/member' import useMemberStore from '@/stores/member'
import { topTabar } from '@/utils/topTabbar'
const memberStore = useMemberStore() const memberStore = useMemberStore()
let loading = ref(false) const loading = ref(false)
let list = ref([]) // const list = ref([]) //
let upgradeSkills = ref([]) // const upgradeSkills = ref([]) //
const swiperIndex = ref(0); // const swiperIndex = ref(0); //
const levelIndex = ref(0); // const levelIndex = ref(0); //
//
let topTabbarData = ref({ /********* 自定义头部 - start ***********/
title: '会员等级', const topTabarObj = topTabar()
topStatusBar: { let topTabbarData = topTabarObj.setTopTabbarParam({title:'会员等级'})
isTransparent: true, /********* 自定义头部 - end ***********/
style: 'style-1',
bgColor: 'transparent',
textColor: '#fff'
}
})
onShow(() => { onShow(() => {
// //
@ -149,7 +144,7 @@
}) })
// //
let progress = (index:any) => { const progress = (index:any) => {
let indent = index; let indent = index;
let num = 100 let num = 100
if(list.value[indent] && list.value[indent].growth) { if(list.value[indent] && list.value[indent].growth) {
@ -159,7 +154,7 @@
} }
// //
let upgradeGrowth = (index:any) => { const upgradeGrowth = (index:any) => {
let indent = index; let indent = index;
let num = 0; let num = 0;
if(list.value[indent] && list.value[indent].growth) { if(list.value[indent] && list.value[indent].growth) {
@ -228,8 +223,8 @@
}; };
// //
let currLevelInfo = ref<any>({}); const currLevelInfo = ref<any>({});
let infoStructureFn = (index:number)=>{ const infoStructureFn = (index:number)=>{
let data:any = deepClone(list.value[index]); let data:any = deepClone(list.value[index]);
// //
if(data && data.level_benefits){ if(data && data.level_benefits){

View File

@ -36,7 +36,7 @@
</u-form-item> </u-form-item>
</view> </view>
<view class="mt-[40rpx]"> <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> </view>
</u-form> </u-form>
</view> </view>
@ -44,7 +44,7 @@
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 --> <!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup> <wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif --> <!-- #endif -->
</view> </view>
</template> </template>
@ -79,7 +79,7 @@
type: 'location_address' type: 'location_address'
}) })
onLoad((option) => { onLoad((option:any) => {
if (option.id) { if (option.id) {
getAddressInfo(option.id).then(({ data }) => { getAddressInfo(option.id).then(({ data }) => {
if (data) { if (data) {

View File

@ -2,14 +2,14 @@
<view class="w-full h-screen bg-page personal-wrap" v-if="info" :style="themeColor()"> <view class="w-full h-screen bg-page personal-wrap" v-if="info" :style="themeColor()">
<view class="flex flex-col items-center pt-[30rpx]"> <view class="flex flex-col items-center pt-[30rpx]">
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<button open-type="chooseAvatar" @chooseavatar="onChooseAvatar" :plain="true" class="border-0"> <button open-type="chooseAvatar" @chooseavatar="onChooseAvatar" :plain="true" class="border-0" @click="checkWxPrivacy">
<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> <view class="text-primary text-sm mt-[10rpx]">{{ t('updateHeadimg') }}</view>
</button> </button>
<!-- #endif --> <!-- #endif -->
<!-- #ifndef MP-WEIXIN --> <!-- #ifndef MP-WEIXIN -->
<u-upload @afterRead="afterRead" :maxCount="1"> <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> <view class="text-primary text-sm mt-[10rpx]">{{ t('updateHeadimg') }}</view>
</u-upload> </u-upload>
<!-- #endif --> <!-- #endif -->
@ -23,23 +23,23 @@
<template #value> <template #value>
<view v-if="info.mobile" class="mr-[10rpx]">{{ mobileConceal(info.mobile) }}</view> <view v-if="info.mobile" class="mr-[10rpx]">{{ mobileConceal(info.mobile) }}</view>
<view v-else @click="redirect({ url: '/app/pages/auth/bind' })"> <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> </view>
</template> </template>
</u-cell> </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> </u-cell-group>
</view> </view>
<u-modal :show="updateNickname.modal" :closeOnClickOverlay="true" @close="updateNickname.modal = false" <u-modal :show="updateNickname.modal" :closeOnClickOverlay="true" @close="updateNickname.modal = false"
:show-cancel-button="true" :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]"> <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"> <input type="nickname" v-model="updateNickname.value" :placeholder="t('nicknamePlaceholder')" @blur="bindNickname">
</view> </view>
<template #confirmButton> <template #confirmButton>
<view class="mt-[10rpx]"> <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> </view>
</template> </template>
</u-modal> </u-modal>
@ -52,11 +52,15 @@
:maxDate="new Date().valueOf()" :minDate="0" :maxDate="new Date().valueOf()" :minDate="0"
:cancel-text="t('cancel')" @cancel="birthdayPicker = false" @confirm="updateBirthday"></u-datetime-picker> :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> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, reactive, watch } from 'vue' import { ref, computed, reactive } from 'vue'
import { t } from '@/locale' import { t } from '@/locale'
import useMemberStore from '@/stores/member' import useMemberStore from '@/stores/member'
import { img, redirect,mobileConceal } from '@/utils/common' import { img, redirect,mobileConceal } from '@/utils/common'
@ -66,6 +70,14 @@
const memberStore = useMemberStore() const memberStore = useMemberStore()
const info = computed(() => memberStore.info) const info = computed(() => memberStore.info)
const wxPrivacyPopupRef:any = ref(null)
//
const checkWxPrivacy = ()=>{
wxPrivacyPopupRef.value.proactive();
}
/** /**
* 修改昵称 * 修改昵称
*/ */
@ -73,9 +85,11 @@
modal: false, modal: false,
value: info.nickname || '' value: info.nickname || ''
}) })
const bindNickname = (e) => { const bindNickname = (e) => {
updateNickname.value = e.detail.value updateNickname.value = e.detail.value
} }
const updateNicknameConfirm = () => { const updateNicknameConfirm = () => {
if (uni.$u.test.isEmpty(updateNickname.value)) { uni.showToast({ title: t('nicknamePlaceholder'), icon: 'none' }); return } if (uni.$u.test.isEmpty(updateNickname.value)) { uni.showToast({ title: t('nicknamePlaceholder'), icon: 'none' }); return }
@ -155,13 +169,22 @@
birthdayPicker.value = false birthdayPicker.value = false
}) })
} }
const formatDate=(date:any)=>{
return date ? uni.$u.date(new Date(date), 'yyyy-mm-dd') : ''
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
page { page {
background: var(--page-bg-color); background: var(--page-bg-color);
} }
:deep(.u-upload__wrap ){
>view{
justify-content: center;
align-items: center;
}
}
:deep(.u-cell-group__wrapper) { :deep(.u-cell-group__wrapper) {
.u-cell__body { .u-cell__body {
padding-left: 0; padding-left: 0;

View File

@ -4,7 +4,7 @@
<view class="w-full bg-[#F6F6F6]"> <view class="w-full bg-[#F6F6F6]">
<view class="pb-[210rpx] relative" :style="headerStyle"> <view class="pb-[210rpx] relative" :style="headerStyle">
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<top-tabbar :data="param" titleColor="#fff" class="top-header"/> <top-tabbar :data="param" :scrollBool="topTabarObj.getScrollBool()" class="top-header"/>
<!-- #endif --> <!-- #endif -->
<view class="text-[70rpx] leading-[98rpx] text-[#fff] pl-[60rpx] font-600 pt-[77rpx]">{{pointInfo.point||0}}</view> <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]"> <view class="flex items-center pl-[60rpx]">
@ -12,16 +12,16 @@
<view class="text-[26rpx] leading-[36rpx] text-[#fff] ml-[10rpx]">我的积分</view> <view class="text-[26rpx] leading-[36rpx] text-[#fff] ml-[10rpx]">我的积分</view>
</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')"> <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> <text class="text-[24rpx]">积分明细</text>
</view> </view>
</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]" <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'}"> :style="{backgroundImage: 'url(' + img('static/resource/images/member/point/top_bg.png') + ') ',backgroundSize: '100% 100%',backgroundRepeat: 'no-repeat'}">
积分详情 积分详情
</view> </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="w-[196rpx] flex-shrink-0 text-center">
<view class="text-[#333] text-[42rpx] leading-[59rpx] font-bold">{{pointInfo.point_get||0}}</view> <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> <view class="mt-[8rpx] text-[#666] text-[26rpx] leading-[36rpx] font-400">累计积分</view>
@ -39,7 +39,7 @@
</view> </view>
</view> </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="text-[32rpx] leading-[45rpx] font-bold">热门活动</view>
<view class="mt-[50rpx] flex justify-between"> <view class="mt-[50rpx] flex justify-between">
<view class="w-[200rpx] h-[253rpx] box-border pt-[69rpx] relative text-center" <view class="w-[200rpx] h-[253rpx] box-border pt-[69rpx] relative text-center"
@ -116,18 +116,15 @@
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app' import { onLoad } from '@dcloudio/uni-app'
import { t } from '@/locale' 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 { 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 = {}; let menuButtonInfo:any = {};
// (API) // (API)
@ -148,11 +145,7 @@ const topStyle = computed(() => {
style = Object.keys(menuButtonInfo).length?(pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) + 38) + 'rpx;':'38rpx' style = Object.keys(menuButtonInfo).length?(pxToRpx(Number(menuButtonInfo.height)) + pxToRpx(menuButtonInfo.top) + 38) + 'rpx;':'38rpx'
return style return style
}) })
// pxrpx
const pxToRpx=(px)=> {
const screenWidth = uni.getSystemInfoSync().screenWidth
return (750 * Number.parseInt(px)) / screenWidth
}
// //
const pointInfo = ref({}); const pointInfo = ref({});
// //

View File

@ -1,37 +1,101 @@
<template> <template>
<view class="bg-gray-100 min-h-[100vh]" :class="{'bg-[#fff]':!pointList.length}" :style="themeColor()"> <view class="bg-[#F6F6F6] min-h-[100vh]" :style="themeColor()">
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="getPointListFn"> <view class="fixed left-0 right-0 top-0 z-10085">
<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="bg-[#fff] px-[var(--sidebar-m)] py-[14rpx] relative z-10084">
<view class="text-[14px]">{{item.from_type_name}}</view> <view class="flex items-center h-[60rpx] bg-[#F8F9FD] rounded-[30rpx] px-[20rpx]">
<view class="text-[12px] text-gray-400 mt-[10px]">{{item.create_time}}</view> <view class="flex-1 text-[26rpx] leading-[60rpx] text-[#8288A2]" :class="{'!text-[#333]':from_type}" @click="typePopup = true">{{from_type_name || '请选择来源用途'}}</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> <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> </view>
<mescroll-empty v-if="!pointList.length && loading" :option="{tip : '暂无积分明细'}"></mescroll-empty>
</mescroll-body> </mescroll-body>
<!-- 时间选择 -->
<select-date ref="selectDateRef" @confirm="confirmFn" />
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { t } from '@/locale' import { t } from '@/locale'
import { redirect, img } from '@/utils/common'; 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 MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'; import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
import useMescroll from '@/components/mescroll/hooks/useMescroll.js'; import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'; import { onPageScroll, onReachBottom } from '@dcloudio/uni-app';
import selectDate from '@/components/select-date/select-date.vue';
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom); const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom);
let pointList = ref<Array<any>>([]); const from_type = ref('');
let mescrollRef = ref(null); const from_type_name = ref('')
let loading = ref<boolean>(false); 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)=> { const getPointListFn = (mescroll)=> {
let data = { let data = {
page: mescroll.num, 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; loading.value = false;
getPointList(data).then((res) => { getPointList(data).then((res) => {
@ -42,12 +106,60 @@ const getPointListFn = (mescroll)=> {
pointList.value = []; // pointList.value = []; //
} }
pointList.value = pointList.value.concat(newArr); pointList.value = pointList.value.concat(newArr);
pointList.value = pointList.value.map(item =>{
item.flag = true
return item
})
loading.value = true; loading.value = true;
}).catch(() => { }).catch(() => {
loading.value = true; loading.value = true;
mescroll.endErr(); // , 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> </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>

View File

@ -4,63 +4,65 @@
<view v-if="info.is_use"> <view v-if="info.is_use">
<view class="sigin-header"> <view class="sigin-header">
<!-- #ifdef MP-WEIXIN --> <!-- #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"> <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-[4rpx]"></text> <text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[28rpx] text-[#fff] mr-[6rpx]"></text>
<text class="text-[24rpx]">签到规则</text> <text class="text-[24rpx]">签到规则</text>
</view> </view>
<view :style="{height: headStyle, backgroundImage: 'url(' + img('static/resource/images/app/sigin_uniapp.png') + ')',backgroundSize: '100% 100%', backgroundRepeat: 'no-repeat'}"> <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> </view>
<!-- #endif --> <!-- #endif -->
<!-- #ifdef H5 --> <!-- #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"> <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-[4rpx]"></text> <text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[28rpx] text-[#fff] mr-[6rpx]"></text>
<text class="text-[24rpx]">签到规则</text> <text class="text-[24rpx]">签到规则</text>
</view> </view>
<view class="h-[382rpx]" :style="{ backgroundImage: 'url(' + img('static/resource/images/app/sigin_h5.png') + ')',backgroundSize: '100%', backgroundRepeat: 'no-repeat'}"> <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> </view>
<!-- #endif --> <!-- #endif -->
</view> </view>
<view> <view>
<view class="mx-[30rpx] bg-[#fff] rounded-[16rpx] -mt-[85rpx]"> <view class="sidebar-marign bg-[#fff] rounded-[16rpx] -mt-[85rpx]">
<view class="px-[30rpx]"> <view class="card-template">
<view class="pt-[32rpx] mb-[40rpx] flex justify-between items-center" v-if="flag" > <view class=" mb-[30rpx] flex justify-between items-center" v-if="flag">
<view class="flex items-center"> <view class="flex items-center">
<text class="iconfont iconshangyibu text-[#999] text-[24rpx]" @click="changeMonth('prev')"></text> <text class="iconfont iconshangyibu text-[#333] text-[24rpx]" @click="changeMonth('prev')"></text>
<view class="mx-[30rpx] font-bold text-[32rpx] text-[#333] leading-[38rpx]">{{ state.curYear }}{{ state.curMonth+1 }}</view> <view class="mx-[30rpx] font-bold text-[32rpx] text-[#333] leading-[45rpx]">{{ state.curYear }}{{ state.curMonth+1 }}</view>
<text class="iconfont iconxiayibu1 text-[#999] text-[24rpx]" @click="changeMonth('next')"></text> <text class="iconfont iconxiayibu1 text-[#333] text-[24rpx]" @click="changeMonth('next')"></text>
</view> </view>
<view class="flex items-center"> <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> </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="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> </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>
<view class="relative z-9 pb-[30rpx] bg-[#fff] rounded-[18rpx]"> <view class="relative z-9 bg-[#fff] rounded-[18rpx]">
<view> <view>
<view class="flex items-center justify-between text-[#666] text-[26rpx] mb-[14rpx]"> <view class="flex items-center justify-between text-[#626779] text-[24rpx] mb-[16rpx]">
<text class="w-[14.2%] leading-[30rpx] text-center">周一</text> <text class="w-[14.28%] leading-[36rpx] text-center">周一</text>
<text class="w-[14.2%] leading-[30rpx] text-center">周二</text> <text class="w-[14.28%] leading-[36rpx] text-center">周二</text>
<text class="w-[14.2%] leading-[30rpx] text-center">周三</text> <text class="w-[14.28%] leading-[36rpx] text-center">周三</text>
<text class="w-[14.2%] leading-[30rpx] text-center">周四</text> <text class="w-[14.28%] leading-[36rpx] text-center">周四</text>
<text class="w-[14.2%] leading-[30rpx] text-center">周五</text> <text class="w-[14.28%] leading-[36rpx] text-center">周五</text>
<text class="w-[14.2%] leading-[30rpx] text-center">周六</text> <text class="w-[14.28%] leading-[36rpx] text-center">周六</text>
<text class="w-[14.2%] leading-[30rpx] text-center">周日</text> <text class="w-[14.28%] leading-[36rpx] text-center">周日</text>
</view> </view>
<view class="flex flex-wrap items-center justify-start" v-if="!flag"> <view class="flex flex-wrap items-center justify-start" v-if="!flag">
<block v-for="(item,index) in state.weekCount" :key="index"> <block v-for="(item,index) in state.weekCount" :key="index">
<view class="w-[14.2%] flex flex-col justify-center items-center"> <view class="w-[14.28%] 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)"> <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-[34rpx] mb-[6rpx]">{{ filteredDate(item) }}</text> <text class="text-[24rpx] leading-[28rpx] mb-[6rpx]">{{ filteredDate(item) }}</text>
<view v-if="filteredDate(item)"> <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-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-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> </view>
<view class="w-[10rpx] h-[10rpx] rounded-[50%] bg-[#FF5527]" v-if="isCurrentDate(item)"></view> <view class="w-[10rpx] h-[10rpx] rounded-[50%] bg-[#FF5527]" v-if="isCurrentDate(item)"></view>
@ -69,46 +71,48 @@
</view> </view>
<view class="flex flex-wrap items-center justify-start" v-else> <view class="flex flex-wrap items-center justify-start" v-else>
<block v-for="(item,index) in state.dataCount" > <block v-for="(item,index) in state.dataCount" >
<view class="w-[14.2%] flex flex-col justify-center items-center mb-[10rpx]"> <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-[#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)"> <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-[34rpx] mb-[6rpx]">{{ filteredDate(item) }}</text> <text class="text-[24rpx] leading-[28rpx] mb-[6rpx]">{{ filteredDate(item) }}</text>
<view v-if="filteredDate(item)"> <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-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-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> </view>
<view class="w-[10rpx] h-[10rpx] rounded-[50%] bg-[#FF5527]" v-if="isCurrentDate(item)"></view> <view class="w-[10rpx] h-[10rpx] rounded-[50%] bg-[#FF5527]" v-if="isCurrentDate(item)"></view>
</view> </view>
</block> </block>
</view> </view>
<view class="mt-[50rpx] mx-[20rpx] flex justify-center" v-if="state.curMonth + 1 == (new Date().getMonth() + 1) && state.curYear == new Date().getFullYear() "> <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:'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"> <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-[30rpx] text-[#fff] mr-[8rpx]"></text> <text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[32rpx] text-[#fff] mr-[8rpx]"></text>
<text>立即签到</text> <text>立即签到</text>
</button> </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"> <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-[30rpx] text-[#fff] mr-[8rpx]"></text> <text class="nc-iconfont nc-icon-meiriqiandaoV6xx text-[32rpx] text-[#fff] mr-[8rpx]"></text>
<text>已签到</text> <text>已签到</text>
</button> </button>
</view> </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> </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="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]"> <!-- <view class="text-[#666] text-[26rpx] leading-[30rpx]">
<text>签到记录</text> <text>签到记录</text>
<image :src="img('static/resource/images/app/more.png')" class="w-[12rpx] h-[18rpx] ml-[8rpx]"></image> <image :src="img('static/resource/images/app/more.png')" class="w-[12rpx] h-[18rpx] ml-[8rpx]"></image>
</view> --> </view> -->
</view> </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"> <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> <image :src="img('static/resource/images/app/icon_02.png')" class="w-[40rpx] h-[40rpx]"></image>
</view> </view>
@ -122,26 +126,28 @@
<image :src="img('static/resource/images/app/icon_05.png')" class="w-[40rpx] h-[40rpx]"></image> <image :src="img('static/resource/images/app/icon_05.png')" class="w-[40rpx] h-[40rpx]"></image>
</view> </view>
<view class="flex-1 mx-[20rpx]"> <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 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> <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>
</view> </view>
<view class="flex-shrink-0"> <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-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="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-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>
</view> </view>
</view> </view>
<view class="min-h-screen flex flex-col justify-center bg-[#fff]" v-else> <view class="h-[100vh] w-[100vw] flex justify-center items-center" v-else>
<image class="rounded-[8rpx] overflow-hidden mx-auto w-[320rpx] h-[184rpx]" :src="img('static/resource/images/system/empty.png')" model="aspectFill" /> <!-- #ifdef MP-WEIXIN -->
<view class="text-[#999] text-[26rpx] font-400 mt-[26rpx] text-center leading-[30rpx]">签到未开启</view> <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> </view>
<!-- 签到规则--> <!-- 签到规则-->
<u-popup :show="signPopup" :round="16" mode="bottom" :closeable="true" @close="signPopup = false"> <u-popup :show="signPopup" :round="16" mode="bottom" :closeable="true" @close="signPopup = false">
@ -153,32 +159,32 @@
</block> </block>
</scroll-view> </scroll-view>
<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> </view>
</u-popup> </u-popup>
<!-- 签到奖励 --> <!-- 签到奖励 -->
<u-popup :show="awardShow" class="award-popup" :customStyle="{backgroundColor:'transparent'}" @close="awardShow = false" mode="center" :round="5" :safeAreaInsetBottom="false" > <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"> <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>
<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="px-[32rpx]">
<view class="text-[48rpx] text-[#EF000C] font-bold leading-[56rpx] mb-[4rpx] text-center">{{ signAward.title }}</view> <view class="text-[48rpx] text-[#EF000C] font-bold leading-[68rpx] mb-[6rpx] text-center">{{ signAward.title }}</view>
<view class="text-[24rpx] text-[#F05F66] leading-[28rpx] text-center mb-[60rpx]">{{ signAward.info }}</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-[54rpx]"> <view class="px-[68rpx] mb-[80rpx]">
<block v-for="(item,index) in signAward.awards"> <block v-for="(item,index) in signAward.awards">
<template v-if="item.content" v-for="(subItem,subIndex) in item.content"> <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> <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> </view>
</template> </template>
</block> </block>
</view> </view>
<view class="flex justify-center"> <view class="flex justify-center relative z-30">
<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="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> </view>
@ -189,26 +195,28 @@
</u-popup> </u-popup>
<!-- 查看当日或连续签到奖励 --> <!-- 查看当日或连续签到奖励 -->
<u-popup :show="packShow" class="award-popup" :customStyle="{backgroundColor:'transparent'}" @close="packShow = false" mode="center" :round="5" :safeAreaInsetBottom="false"> <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"> <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>
<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="px-[32rpx]">
<view class="text-[48rpx] text-[#EF000C] font-bold leading-[56rpx] mb-[4rpx] text-center opacity-60">签到奖励</view> <view class="text-[48rpx] text-[#333] font-bold leading-[68rpx] mb-[6rpx] text-center relative z-20">
<view class="text-[24rpx] text-[#F05F66] opacity-60 leading-[28rpx] text-center mb-[60rpx]">您将获得以下奖励</view> {{ packInfo.title }}
<view class="px-[68rpx] mb-[54rpx]"> </view>
<block v-for="(item,index) in packInfo"> <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"> <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> <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> </view>
</template> </template>
</block> </block>
</view> </view>
<view class="flex justify-center"> <view class="flex justify-center relative z-30">
<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="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> </view>
</view> </view>
@ -224,12 +232,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, toRefs, toRaw, computed } from 'vue' 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 { onLoad } from '@dcloudio/uni-app'
import { getSignInfo,getSignConfig, setSign,getDayPack } from '@/app/api/member' import { getSignInfo,getSignConfig, setSign,getDayPack } from '@/app/api/member'
import useMemberStore from '@/stores/member' import useMemberStore from '@/stores/member'
import { topTabar } from '@/utils/topTabbar'
let state = reactive({ const state = reactive({
dataCount:[], // dataCount:[], //
weekCount:[], //7 weekCount:[], //7
curYear:0, // curYear:0, //
@ -239,21 +248,21 @@ let state = reactive({
signInList:[], // signInList:[], //
packList:[] // packList:[] //
}) })
let week = reactive({ const week = reactive({
weekDay:0, // weekDay:0, //
week:0 // week:0 //
}) })
const loading = ref(false) const loading = ref(false)
let flag = ref(false) const flag = ref(false)
let info = ref({}) // const info = ref({}) //
let signPopup = ref(false)// const signPopup = ref(false)//
let signAward = ref({}) // const signAward = ref({}) //
let awardShow = ref(false) // const awardShow = ref(false) //
let packShow = ref(false) // const packShow = ref(false) //
let packInfo = ref({}) // const packInfo = ref({}) //
let active = ref(false) const active = ref(false)
let currentYear=null let currentYear: any = null
let currentMonth=null let currentMonth: any = null
onLoad(() =>{ onLoad(() =>{
let date=new Date() let date=new Date()
state.curYear=date.getFullYear() state.curYear=date.getFullYear()
@ -277,6 +286,9 @@ const getSignConfigFn = () =>{
loading.value = true loading.value = true
getSignConfig().then((res:any) =>{ getSignConfig().then((res:any) =>{
info.value = res.data info.value = res.data
if(!info.value.is_use){
topTabbarData = topTabarObj.setTopTabbarParam({title:'我的签到',topStatusBar:{textColor:'#333',bgColor:'#fff'}})
}
loading.value = false loading.value = false
}) })
} }
@ -287,9 +299,12 @@ const getSignInfoFn = (data:any) =>{
state.signInList = [] state.signInList = []
state.packList = [] state.packList = []
state.packList = res.data.period state.packList = res.data.period
if(res.data.length){
state.signInList = res.data.days.map((el:any) =>{ state.signInList = res.data.days.map((el:any) =>{
return Number(el) return Number(el)
}) })
}
active.value = true active.value = true
}) })
} }
@ -364,6 +379,16 @@ const setSignFn = () =>{
setSign().then(res =>{ setSign().then(res =>{
if(Object.values(res.data).length){ if(Object.values(res.data).length){
signAward.value = res.data 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}) getSignInfoFn({year:state.curYear,month:state.curMonth+1})
getSignConfigFn() getSignConfigFn()
memberStore.getMemberInfo() memberStore.getMemberInfo()
@ -373,7 +398,7 @@ const setSignFn = () =>{
} }
// //
let curPickDay = ref(null) const curPickDay = ref(null)
const getDayPackFn = (date:number) =>{ const getDayPackFn = (date:number) =>{
let {curYear,curMonth}=toRefs(state) 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}` 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 // #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
menuButtonInfo = uni.getMenuButtonBoundingClientRect(); menuButtonInfo = uni.getMenuButtonBoundingClientRect();
// #endif // #endif
let topTabbarData = ref({ /********* 自定义头部 - start ***********/
title:'我的签到', const topTabarObj = topTabar()
topStatusBar: { let topTabbarData = topTabarObj.setTopTabbarParam({title:'我的签到'})
style: 'style-1', /********* 自定义头部 - end ***********/
isTransparent: true,
bgColor: 'transparent',
textColor: '#fff'
}
})
const headStyle = computed(() => { const headStyle = computed(() => {
let style = '' let style = pxToRpx(Number(menuButtonInfo.height) + menuButtonInfo.top + 8)+ 382 + 'rpx;'
style = pxToRpx(Number(menuButtonInfo.height) + menuButtonInfo.top + 8)+ 382 + 'rpx;'
return style return style
}) })
const topStyle = computed(() => { const topStyle = computed(() => {
let style = '' let style = pxToRpx(Number(menuButtonInfo.height) + menuButtonInfo.top + 8)+38 + 'rpx;'
style = pxToRpx(Number(menuButtonInfo.height) + menuButtonInfo.top + 8)+38 + 'rpx;'
return style return style
}) })
// rpxpx
const rpxToPx=(rpx:any)=>{
const screenWidth = uni.getSystemInfoSync().screenwidth
return(screenWidth*Number.parseInt(rpx))/750
}
// pxrpx
const pxToRpx=(px:any)=>{
const screenWidth =uni.getSystemInfoSync().screenWidth
return(750*Number.parseInt(px))/screenWidth
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -9,7 +9,7 @@
import { img, isWeixinBrowser } from '@/utils/common' import { img, isWeixinBrowser } from '@/utils/common'
import { onLoad } from '@dcloudio/uni-app' import { onLoad } from '@dcloudio/uni-app'
onLoad((data : AnyObject) => { onLoad((data : any) => {
if (!isWeixinBrowser() && data.alipay) { if (!isWeixinBrowser() && data.alipay) {
uni.setStorageSync('paymenting', { trade_type: data.trade_type, trade_id: data.trade_id }) uni.setStorageSync('paymenting', { trade_type: data.trade_type, trade_id: data.trade_id })
location.href = data.alipay location.href = data.alipay

View File

@ -13,7 +13,7 @@
<u-button type="primary" :text="payInfo.status == 2 ? t('complete') : t('close')" :plain="true" @click="complete"></u-button> <u-button type="primary" :text="payInfo.status == 2 ? t('complete') : t('close')" :plain="true" @click="complete"></u-button>
</view> </view>
</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]"> <view class="py-[20rpx]">
<u-loading-icon :text="t('pay.getting')" textSize="16" mode="circle" :vertical="true"></u-loading-icon> <u-loading-icon :text="t('pay.getting')" textSize="16" mode="circle" :vertical="true"></u-loading-icon>
</view> </view>
@ -61,8 +61,6 @@
title: payInfo.value.status == 2 ? t('pay.paySuccess') : t('pay.payFail') title: payInfo.value.status == 2 ? t('pay.paySuccess') : t('pay.payFail')
}) })
} }
}).catch(() => {
}) })
} }

View File

@ -69,7 +69,9 @@
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
} }
.u-cell__value{
line-height: 1;
}
.u-cell { .u-cell {
&:last-child .u-line { &:last-child .u-line {
display: none; display: none;

View File

@ -1,47 +1,47 @@
<template> <template>
<view :style="themeColor()" class="bg-[#f8f8f8] min-h-[100vh] overflow-hidden"> <view :style="themeColor()" class="bg-[#f8f8f8] min-h-[100vh] overflow-hidden">
<block v-if="!loading"> <block v-if="!loading">
<view class="mt-[30rpx] mx-[30rpx]"> <view class="pt-[20rpx] sidebar-marign">
<view class="py-[10rpx] px-[20rpx] flex flex-col rounded-[16rpx] bg-white"> <view class="flex flex-col card-template">
<view class="flex h-[180rpx]" :class="{'mb-[20rpx]': verifyInfo.value.list.length-1 != index}" v-for="(item,index) in verifyInfo.value.list" :key="index"> <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-[120rpx] h-[120rpx] mt-[30rpx] rounded-[8rpx]" mode="aspectFit" v-if="item.cover" :src="img(item.cover)"></image> <image class="w-[150rpx] h-[150rpx] rounded-[8rpx]" mode="aspectFill" 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> <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] mt-36rpx"> <view class="flex flex-col flex-1 ml-[20rpx] py-[4rpx]">
<view class="leading-[39rpx] text-[28rpx] max-w-[432rpx] multi-hidden">{{item.name}}</view> <view class="leading-[1.3] text-[28rpx] multi-hidden">{{item.name}}</view>
<view class="self-end text-[28rpx]">x1</view> <view class="self-end text-[#626779] text-[26rpx] mt-[20rpx]">x1</view>
</view> </view>
</view> </view>
</view> </view>
<view class="flex flex-col bg-[#fff] p-[20rpx] rounded-[16rpx] mt-[20rpx]"> <view class="flex flex-col card-template mt-[20rpx]">
<view class="text-[28rpx] text-[#333333] font-bold leading-[39rpx] h-[39rpx]">核销信息</view> <view class="text-[32rpx] text-[#333333] font-500 leading-[1.2] mb-[30rpx]">核销信息</view>
<view class="flex justify-between items-center mt-[30rpx] h-[39rpx]"> <view class="flex justify-between h-[36rpx] items-center">
<text class="text-[28rpx] text-[#333]">核销类型</text> <text class="text-[26rpx] text-[#626779]">核销类型</text>
<view class="text-[28rpx] text-[#333]">{{verifyInfo.type_name}}</view> <view class="text-[26rpx] text-[#333]">{{verifyInfo.type_name}}</view>
</view> </view>
<view class="flex justify-between items-center mt-[20rpx] h-[39rpx]"> <view class="flex justify-between h-[36rpx] items-center mt-[20rpx]">
<text class="text-[28rpx] text-[#333]">核销状态</text> <text class="text-[26rpx] text-[#626779]">核销状态</text>
<view class="text-[28rpx] text-[#333]">已核销</view> <view class="text-[26rpx] text-[#333]">已核销</view>
</view> </view>
<view class="flex justify-between items-center mt-[20rpx] h-[39rpx]"> <view class="flex justify-between h-[36rpx] items-center mt-[20rpx]">
<text class="text-[28rpx]">核销时间</text> <text class="text-[26rpx] text-[#626779]">核销时间</text>
<view class="text-[#333333] text-[28rpx]">{{verifyInfo.create_time}}</view> <view class="text-[#333333] text-[26rpx]">{{verifyInfo.create_time}}</view>
</view> </view>
<view class="flex justify-between items-center mt-[20rpx] h-[39rpx]"> <view class="flex justify-between h-[36rpx] items-center mt-[20rpx]">
<text class="text-[28rpx]">核销人员</text> <text class="text-[26rpx] text-[#626779]">核销人员</text>
<view class="text-[#333333] text-[28rpx]">{{verifyInfo.member ? verifyInfo.member.nickname : '--'}}</view> <view class="text-[#333333] text-[26rpx]">{{verifyInfo.member ? verifyInfo.member.nickname : '--'}}</view>
</view> </view>
<view class="flex items-center justify-between mt-[20rpx]" v-for="(item,index) in verifyInfo.value.content.fixed"> <view class="flex items-center h-[36rpx] justify-between mt-[20rpx]" v-for="(item,index) in verifyInfo.value.content.fixed">
<text class="text-[28rpx] text-[#333]">{{item.title}}</text> <text class="text-[26rpx] text-[#626779]">{{item.title}}</text>
<view class="text-[28rpx] text-[#333]">{{item.value}}</view> <view class="text-[26rpx] text-[#333]">{{item.value}}</view>
</view> </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 v-for="(item,index) in verifyInfo.value.content.diy" :key="index" class="card-template mt-[20rpx]">
<view class="text-[28rpx] text-[#333333] font-bold leading-[39rpx] h-[39rpx]">{{item.title}}</view> <view class="text-[32rpx] text-[#333333] font-500 leading-[1.2] mb-[30rpx]">{{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'}"> <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-[28rpx] text-[#333]">{{subItem.title}}</text> <text class="text-[26rpx] text-[#626779]">{{subItem.title}}</text>
<view class="text-[28rpx] text-[#333]">{{subItem.value}}</view> <view class="text-[26rpx] text-[#333]">{{subItem.value}}</view>
</view> </view>
</view> </view>
</view> </view>
@ -59,8 +59,8 @@
import { t } from '@/locale' import { t } from '@/locale'
const loading = ref(true) const loading = ref(true)
let code = ref(''); const code = ref('');
onLoad((option)=> { onLoad((option:any)=> {
if (option.code) code.value = option.code; if (option.code) code.value = option.code;
}) })
@ -70,12 +70,11 @@
} }
}) })
let verifyInfo = ref({}) const verifyInfo = ref({})
const getVerifyDetailFn = ()=>{ const getVerifyDetailFn = ()=>{
loading.value = true; loading.value = true;
getVerifyDetail(code.value).then((res:any) =>{ getVerifyDetail(code.value).then((res:any) =>{
verifyInfo.value = res.data; verifyInfo.value = res.data;
console.log("verifyInfo.value",verifyInfo.value);
loading.value = false; loading.value = false;
}) })
} }

View File

@ -2,8 +2,8 @@
<view :style="themeColor()"> <view :style="themeColor()">
<view class="w-[100vw] min-h-[100vh] bg-[#f8f8f8]" v-if="!loading"> <view class="w-[100vw] min-h-[100vh] bg-[#f8f8f8]" v-if="!loading">
<view class="w-full bg-[#fff] verify-box h-[760rpx]"> <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'})"> <view class="text-[var(--primary-color)] fixed top-[40rpx] 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')"/> <image class="w-[26rpx] h-[28rpx]" :src="img('static/resource/images/verify/history.png')"/>
<text class="text-[26rpx] ml-[10rpx]">核销记录</text> <text class="text-[26rpx] ml-[10rpx]">核销记录</text>
</view> </view>
<view v-show="operationType == 'sweepCode'" class="flex flex-col items-center justify-center"> <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')"/> <image class="w-[354rpx] h-[354rpx]" :src="img('static/resource/images/verify/saoma.png')"/>
</view> </view>
<view class="mt-[40rpx] text-[32rpx]">点击扫描二维码</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>
<view v-show="operationType == 'manualInput'"> <view v-show="operationType == 'manualInput'">
<view class="flex pt-[126rpx] pb-[30rpx] items-center justify-center"> <view class="flex pt-[126rpx] items-center justify-center">
<view class="flex justify-center items-center flex-col pr-[30rpx]"> <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')"/> <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 class="text-[26rpx] h-[36rpx] leading-[36rpx] mt-[12rpx]">验证核销码</view>
</view> </view>
<image class="w-[74rpx] h-[12rpx] mb-[50rpx]" :src="img('static/resource/images/verify/youjiantou.png')"/> <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')"/> <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 class="text-[26rpx] h-[36rpx] leading-[36rpx] mt-[12rpx]">核销</view>
</view> </view>
</view> </view>
<view class="mt-[50rpx]"> <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> <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"/> <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>
<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>
</view> </view>
<view class="w-[630rpx] h-[100rpx] bg-[#fff] mx-[auto] mt-[220rpx] rounded-[90rpx] flex relative action-type-wrap"> <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="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'}">
<view class="mt-[10rpx]"><text class="nc-iconfont nc-icon-saoyisaoV6xx !text-[42rpx]"></text></view> <text class="nc-iconfont nc-icon-saoyisaoV6xx !text-[40rpx]"></text>
<view class="text-[24rpx] leading-[34rpx] h-[34rpx] mt-[-6rpx]">扫码核销</view> <view class="text-[24rpx] leading-[1] mt-[10rpx]">扫码核销</view>
</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="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="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 class="text-[24rpx] mt-[8rpx] leading-[34rpx] h-[34rpx]">核销台</view>
</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="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')">
<view class="ml-[20rpx] mt-[10rpx]"><text class="iconfont iconVector-77 !text-[42rpx]"></text></view> <text class="iconfont iconVector-77 !text-[40rpx]"></text>
<view class="ml-[20rpx] text-[24rpx] leading-[34rpx] h-[34rpx] mt-[-6rpx]" @click="focus">手动输入</view> <view class="ml-[20rpx] text-[24rpx] leading-[1] mt-[10rpx]" @click="focus">手动输入</view>
</view> </view>
</view> </view>
@ -68,7 +68,7 @@
import { t } from '@/locale' import { t } from '@/locale'
import wechat from '@/utils/wechat' import wechat from '@/utils/wechat'
let operationType = ref('manualInput'); // const operationType = ref('manualInput'); //
// #ifdef H5 // #ifdef H5
operationType.value = 'manualInput'; operationType.value = 'manualInput';
// #endif // #endif
@ -76,12 +76,11 @@
operationType.value = 'sweepCode'; operationType.value = 'sweepCode';
// #endif // #endif
let isFocus = ref(false) const isFocus = ref(false)
let verify_code = ref(''); const verify_code = ref('');
let loading = ref(true) const loading = ref(true)
onShow(() => { onShow(() => {
if(getToken()) if(getToken()) checkIsVerifier();
checkIsVerifier();
}) })
// //
@ -93,7 +92,16 @@
icon: 'none' icon: 'none'
}); });
setTimeout(() => { setTimeout(() => {
uni.navigateBack(); if(getCurrentPages().length > 1){
uni.navigateBack({
delta: 1
});
}else{
redirect({
url: '/app/pages/member/index',
mode: 'reLaunch'
});
}
}, 1000); }, 1000);
}else{ }else{
loading.value = false; loading.value = false;
@ -135,8 +143,6 @@
let isLoading = false; let isLoading = false;
const confirm = () => { const confirm = () => {
if(isLoading) return false;
isLoading = true;
var reg = /[\S]+/; var reg = /[\S]+/;
if (!reg.test(verify_code.value)) { if (!reg.test(verify_code.value)) {
uni.showToast({ uni.showToast({
@ -146,6 +152,9 @@
return false; return false;
} }
if(isLoading) return false;
isLoading = true;
getVerifierInfo(verify_code.value).then((res:any) =>{ getVerifierInfo(verify_code.value).then((res:any) =>{
isLoading = false; isLoading = false;
redirect({ url: '/app/pages/verify/verify', param: { code: verify_code.value} }) redirect({ url: '/app/pages/verify/verify', param: { code: verify_code.value} })
@ -173,7 +182,7 @@
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.action-type-wrap { .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{ .heXiao{
background: linear-gradient( 180deg, #FF7354 0%, #FF020F 100%), #EF000C; background: linear-gradient( 180deg, #FF7354 0%, #FF020F 100%), #EF000C;
@ -191,10 +200,17 @@
height: 354rpx; height: 354rpx;
box-shadow: 0 8px 8px 0 rgba(0, 0, 0, 0.03), 0 6px 3px 0 rgba(0, 0, 0, 0.02); 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%; border-radius: 50%;
margin: 146rpx auto 0rpx; margin-top: 146rpx;
} }
.verify-box { .verify-box {
border-bottom-left-radius: 400rpx 60rpx; border-bottom-left-radius: 400rpx 60rpx;
border-bottom-right-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> </style>

View File

@ -1,46 +1,69 @@
<template> <template>
<view class="bg-[#f8f8f8] min-h-screen overflow-hidden" :style="themeColor()"> <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="fixed left-0 right-0 top-0 z-99 bg-[#fff] px-[var(--sidebar-m)]">
<view class="ml-[30rpx] mr-[30rpx]"> <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"> <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="w-full flex flex-col mb-[20rpx] card-template" @click="toLink(item)">
<view class="flex items-center pb-[30rpx] pt-[20rpx] leading-[1]"> <view class="flex items-center mb-[30rpx] leading-[1]">
<view class="nc-iconfont nc-icon-hexiaotaiV6xx pr-[10rpx]"></view> <view class="nc-iconfont nc-icon-hexiaotaiV6xx !text-[26rpx] pr-[10rpx]"></view>
<text class="truncate max-w-[590rpx] text-[#333333] text-[26rpx]">核销码{{ item.code }}</text> <text class="truncate text-[#333333] text-[26rpx]">核销码{{ item.code }}</text>
</view> </view>
<view class="flex flex-1" v-for="(dataItem,dataIndex) in item.value.list" :key="dataIndex"> <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> <u--image class="rounded-[8rpx] overflow-hidden" width="120rpx" height="120rpx" :src="img(dataItem.cover ? dataItem.cover : '')" model="aspectFill">
<image class="w-[100rpx] h-[100rpx] rounded-[8rpx]" mode="aspectFit" v-else :src="img('addon/tourism/tourism/member/hotel.png')"></image> <template #error>
<image class="w-[120rpx] h-[120rpx] rounded-[8rpx] overflow-hidden" :src="img('static/resource/images/diy/shop_default.jpg')" mode="aspectFill"></image>
<view class="flex flex-col flex-1 ml-[20rpx] mt-[3rpx]"> </template>
<view class="leading-[1.4] multi-hidden text-28rpx text-[#333]">{{dataItem.name}}</view> </u--image>
<view class="self-end text-[28rpx]">x1</view> <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> </view>
<view class="flex flex-col bg-[#F6F6F6] p-[20rpx] rounded-[12rpx] mt-[20rpx] mb-[20rpx]"> <view class="flex bg-[#F8F9FD] py-[20rpx] px-[20rpx] rounded-[12rpx] mt-[20rpx]">
<text class="text-[#333333] text-[26rpx] h-[36rpx] leading-[36rpx]">核销时间{{ item.create_time }}</text> <view class="flex-1">
<text class="text-[#333333] text-[26rpx] h-[36rpx] mt-[10rpx] truncate leading-[36rpx]">核销员{{ item.member ? item.member.nickname : '--' }}</text> <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> </view>
</block> </block>
</view> </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> </mescroll-body>
<!-- 时间选择 -->
<select-date ref="selectDateRef" @confirm="confirmFn" />
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue' import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue'
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue' import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue'
import useMescroll from '@/components/mescroll/hooks/useMescroll.js' import useMescroll from '@/components/mescroll/hooks/useMescroll.js'
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app' import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
import { getVerifyRecords } from '@/app/api/verify' import { getVerifyRecords } from '@/app/api/verify'
import { img, redirect } from '@/utils/common' import { img, redirect } from '@/utils/common'
import selectDate from '@/components/select-date/select-date.vue';
let list = ref<Array<Object>>([]) const keyword = ref<string>('')
let loading = ref<boolean>(false) const create_time = ref([])
const list = ref<Array<Object>>([])
const loading = ref<boolean>(false)
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom) const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom)
const geVerifyRecordFn = (mescroll) => { const geVerifyRecordFn = (mescroll) => {
@ -48,6 +71,8 @@
let data : object = { let data : object = {
page: mescroll.num, page: mescroll.num,
limit: mescroll.size, limit: mescroll.size,
keyword:keyword.value,
create_time: create_time.value
}; };
getVerifyRecords(data).then((res) => { getVerifyRecords(data).then((res) => {
@ -68,7 +93,37 @@
const toLink = (data: AnyObject)=> { const toLink = (data: AnyObject)=> {
redirect({ url: '/app/pages/verify/detail', param: { code: data.code } }) 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> </script>
<style lang="scss" scoped> <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> </style>

View File

@ -2,60 +2,50 @@
<view :style="themeColor()" class="bg-[#f8f8f8] min-h-[100vh] overflow-hidden"> <view :style="themeColor()" class="bg-[#f8f8f8] min-h-[100vh] overflow-hidden">
<block v-if="!loading && verifyInfo && verifyInfo.value"> <block v-if="!loading && verifyInfo && verifyInfo.value">
<view class="w-full bg-[#fff] flex justify-center"> <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'})"> <view class="text-[var(--primary-color)] absolute top-[40rpx] 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')"/> <image class="w-[26rpx] h-[28rpx]" :src="img('static/resource/images/verify/history.png')"/>
<text class="text-[26rpx] leading-[30.47rpx] ml-[10rpx] h-[36rpx] leading-[36rpx]">核销记录</text> <text class="text-[26rpx] ml-[10rpx]">核销记录</text>
</view> </view>
<view class="flex pt-[126rpx] pb-[30rpx] items-center"> <view class="flex pt-[120rpx] pb-[30rpx] items-center">
<view class="flex justify-center items-center flex-col pr-[30rpx]"> <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')"/> <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 class="text-[26rpx] mt-[12rpx] h-[36rpx] leading-[36rpx]">验证核销码</view>
</view> </view>
<image class="w-[74rpx] h-[12rpx] mb-[50rpx]" :src="img('static/resource/images/verify/youjiantou.png')"/> <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')"/> <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 class="text-[26rpx] mt-[12rpx] h-[36rpx] leading-[36rpx]">确定核销</view>
</view> </view>
</view> </view>
</view> </view>
<view class="bg-[#fff] rounded-[16rpx] mt-[20rpx] mx-[30rpx] h-[200rpx]"> <view class="card-template mt-[20rpx] sidebar-marign">
<view class="flex" v-for="(item,index) in verifyInfo.value.list" :key="index"> <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] ml-[20rpx] mt-[30rpx] rounded-[8rpx]" mode="aspectFit" v-if="item.cover" :src="img(item.cover)"></image> <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] ml-[20rpx] mt-[30rpx] rounded-[8rpx]" mode="aspectFit" v-else :src="img('addon/tourism/tourism/member/hotel.png')"></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-[10rpx]"> <view class="flex flex-col flex-1 ml-[20rpx] py-[4rpx]">
<view class="mt-[33rpx] ml-[20rpx] max-w-[432rpx] multi-hidden">{{item.name}}</view> <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>
</view> </view>
<view class="bg-[#fff] rounded-[16rpx] mx-[30rpx] mt-[20rpx]"> <view class="card-template mt-[20rpx] sidebar-marign">
<view class="pt-[20rpx] pl-[20rpx] text-[28rpx] font-bold h-[39rpx] leading-[39rpx]">核销信息</view> <view class="text-[32rpx] font-500 leading-[1.3]">核销信息</view>
<view class="text-[28rpx] pb-[20rpx]"> <view class="flex pt-[30rpx] items-center justify-between min-h-[36rpx]">
<view class="flex pt-[30rpx] items-center justify-between px-[20rpx]"> <text class="text-[26rpx] text-[#626779]">核销类型</text>
<text class="text-[28rpx] text-[#333333] h-[39rpx] leading-[39rpx]">核销类型</text> <view class="text-[26rpx] text-[#333333]">{{verifyInfo.type_name}}</view>
<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>
<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> </view>
<view v-for="(item,index) in verifyInfo.value.content.diy" :key="index" class="bg-[#fff] rounded-[16rpx] mx-[30rpx] mt-[20rpx]"> <view v-for="(item,index) in verifyInfo.value.content.diy" :key="index" class="card-template mt-[20rpx] sidebar-marign">
<view class="pt-[20rpx] pl-[20rpx] text-[28rpx] font-bold h-[39rpx] leading-[39rpx]">{{item.title}}</view> <view class="text-[32rpx] font-500 leading-[1.3]">{{item.title}}</view>
<view class="text-[28rpx] pb-[20rpx]"> <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">
<view class="flex pt-[30rpx] items-center justify-between px-[20rpx]" v-for="(subItem,subIndex) in item.list" :key="subIndex"> <text class="text-[26rpx] text-[#626779]">{{subItem.title}}</text>
<text class="text-[28rpx] text-[#333333] h-[39rpx] leading-[39rpx]">{{subItem.title}}</text> <text class="text-[26rpx] text-[#333333]">{{ subItem.value }}</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> </view>
</view> </view>
@ -68,22 +58,19 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import { onLoad ,onShow} from '@dcloudio/uni-app' 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 { getVerifierInfo, getCheckVerifier, verify } from '@/app/api/verify'
import { copy } from '@/utils/common';
import { t } from '@/locale' import { t } from '@/locale'
const loading = ref(true) const loading = ref(true)
const verifyDetail = ref<AnyObject | null>(null) const code = ref('');
let code = ref(''); onLoad((option:any)=> {
onLoad((option)=> {
if (option.code) code.value = option.code; if (option.code) code.value = option.code;
// //
if (option.scene) { if (option.scene) {
let sceneParams = decodeURIComponent(option.scene); let sceneParams: any = decodeURIComponent(option.scene).split('&');
sceneParams = sceneParams.split('&');
if (sceneParams.length) { if (sceneParams.length) {
sceneParams.forEach(item => { sceneParams.forEach((item: any) => {
if (item.indexOf('code') != -1) code.value = item.split('-')[1]; if (item.indexOf('code') != -1) code.value = item.split('-')[1];
}); });
} }
@ -106,7 +93,16 @@
icon: 'none' icon: 'none'
}); });
setTimeout(() => { setTimeout(() => {
uni.navigateBack(); if(getCurrentPages().length > 1){
uni.navigateBack({
delta: 1
});
}else{
redirect({
url: '/app/pages/member/index',
mode: 'reLaunch'
});
}
}, 1000); }, 1000);
}else{ }else{
loading.value = false; loading.value = false;
@ -114,12 +110,17 @@
}) })
} }
let verifyInfo = ref({}) const verifyInfo = ref({})
const getVerifierInfoFn = ()=>{ const getVerifierInfoFn = ()=>{
loading.value = true; loading.value = true;
getVerifierInfo(code.value).then((res:any) =>{ getVerifierInfo(code.value).then((res:any) =>{
verifyInfo.value = res.data; verifyInfo.value = res.data;
loading.value = false; loading.value = false;
}).catch(() => {
setTimeout(() => {
loading.value = false;
redirect({ url: '/app/pages/verify/index', param: {}, mode: 'redirectTo' })
}, 1000);
}) })
} }
let isLoading = false; let isLoading = false;
@ -128,8 +129,12 @@
isLoading = true; isLoading = true;
verify(code.value).then((res:any) =>{ verify(code.value).then((res:any) =>{
isLoading = false; uni.showToast({
title: '核销成功',
icon: 'none'
});
setTimeout(() => { setTimeout(() => {
isLoading = false;
redirect({ url: '/app/pages/verify/index', param: {}, mode: 'redirectTo' }) redirect({ url: '/app/pages/verify/index', param: {}, mode: 'redirectTo' })
}, 1000); }, 1000);
}).catch(() => { }).catch(() => {

View File

@ -8,17 +8,25 @@
<script setup lang="ts"> <script setup lang="ts">
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
import { ref } from 'vue'; import { ref } from 'vue';
import { redirect } from '@/utils/common';
const src = ref('') const src = ref('')
onLoad((option : any) => { onLoad((option : any) => {
src.value = decodeURIComponent(option.src); src.value = option.src ? decodeURIComponent(option.src) : '';
}) })
const navigateBack = () => { const navigateBack = () => {
if(getCurrentPages().length > 1){
uni.navigateBack({ uni.navigateBack({
delta: 1 delta: 1
}); });
}else{
redirect({
url: '/app/pages/index/index',
mode: 'reLaunch'
});
}
} }
</script> </script>

View File

@ -73,7 +73,6 @@
data.city && (selected.city = data.city) data.city && (selected.city = data.city)
data.district && (selected.district = data.district) data.district && (selected.district = data.district)
}) })
.catch()
} }
},{ },{
immediate:true immediate:true

View 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>

View File

@ -4,11 +4,11 @@
<view class="text-base">{{ t('getAvatarNickname') }}</view> <view class="text-base">{{ t('getAvatarNickname') }}</view>
<view class="text-sm mt-[18rpx] text-gray-400">{{ t('getAvatarNicknameTips') }}</view> <view class="text-sm mt-[18rpx] text-gray-400">{{ t('getAvatarNicknameTips') }}</view>
</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="mx-[30rpx]">
<view class="mt-[20rpx]"> <view class="mt-[20rpx]">
<u-form-item :label="t('headimg')" prop="headimg" :border-bottom="true"> <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"> <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-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> <u-icon name="plus" v-else></u-icon>
@ -18,22 +18,31 @@
<u-form-item :label=" t('nickname')" prop="nickname" :border-bottom="true"> <u-form-item :label=" t('nickname')" prop="nickname" :border-bottom="true">
<input type="nickname" v-model="formData.nickname" :placeholder="t('nicknamePlaceholder')" @blur="bindNickname"> <input type="nickname" v-model="formData.nickname" :placeholder="t('nicknamePlaceholder')" @blur="bindNickname">
</u-form-item> </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> </view>
<view class="p-[30rpx] mt-[20rpx]"> <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> </view>
</u-form> </u-form>
<!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif -->
</u-popup> </u-popup>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue' import { ref, reactive, computed, watch,onMounted } from 'vue'
import { t } from '@/locale' import { t } from '@/locale'
import useMemberStore from '@/stores/member' import useMemberStore from '@/stores/member'
import { img } from '@/utils/common' import { img, getToken } from '@/utils/common'
import { modifyMember } from '@/app/api/member' import { modifyMember, bindMobile } from '@/app/api/member'
import { fetchBase64Image } from '@/app/api/system' import { fetchBase64Image } from '@/app/api/system'
import { useLogin } from '@/hooks/useLogin'
const show = ref(false) const show = ref(false)
const loading = ref(false) const loading = ref(false)
@ -42,16 +51,34 @@
const formData = reactive({ const formData = reactive({
nickname: '', nickname: '',
headimg: '' headimg: '',
mobile: '',
}) })
watch(() => info.value, () => { watch(() => info.value, () => {
if (info.value) { if (info.value) {
formData.nickname = info.value.nickname formData.nickname = info.value.nickname
formData.headimg = info.value.headimg formData.headimg = info.value.headimg
formData.mobile = info.value.mobile
} }
}, { immediate: true }) }, { 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) => { const onChooseAvatar = (e) => {
uni.getFileSystemManager().readFile({ uni.getFileSystemManager().readFile({
filePath: e.detail.avatarUrl, // filePath: e.detail.avatarUrl, //
@ -80,6 +107,12 @@
required: true, required: true,
message: t('nicknamePlaceholder'), message: t('nicknamePlaceholder'),
trigger: ['blur', 'change'], trigger: ['blur', 'change'],
},
'mobile': {
type: 'string',
required: isBindMobile.value ? true : false,
message: t('mobileTips'),
trigger: ['blur', 'change'],
} }
} }
@ -106,8 +139,44 @@
}).catch(() => { }).catch(() => {
loading.value = false 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({ defineExpose({
show show

View File

@ -89,25 +89,25 @@ export default {
} }
.mescroll-empty .empty-icon { .mescroll-empty .empty-icon {
width: 320rpx; width: 348rpx;
height: 320rpx; height: 348rpx;
} }
.mescroll-empty .empty-tip { .mescroll-empty .empty-tip {
margin-top: 20rpx;
font-size: 24rpx; font-size: 24rpx;
color: gray; color: gray;
} }
.mescroll-empty .empty-btn { .mescroll-empty .empty-btn {
display: inline-block;
margin-top: 40rpx; margin-top: 40rpx;
min-width: 200rpx; display: inline-block;
padding: 18rpx; min-width: 220rpx;
height: 66rpx;
line-height: 66rpx;
font-size: 28rpx; font-size: 28rpx;
border: 1rpx solid #e04b28; border: 1rpx solid #EF000C;
border-radius: 60rpx; border-radius: 60rpx;
color: #e04b28; color: #EF000C;
} }
.mescroll-empty .empty-btn:active { .mescroll-empty .empty-btn:active {

View 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>

View File

@ -25,7 +25,7 @@
</view> </view>
</scroll-view> </scroll-view>
<view class="p-[30rpx]"> <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>
</view> </view>
</u-popup> </u-popup>

View 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>

View File

@ -52,7 +52,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed } from 'vue'; import { ref } from 'vue';
import { img, copy } from '@/utils/common'; import { img, copy } from '@/utils/common';
import { getPoster } from '@/app/api/system' import { getPoster } from '@/app/api/system'

View File

@ -1,7 +1,7 @@
<template> <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-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]"> <view class="flex mt-[20rpx]">
<u-input :placeholder="t('captchaPlaceholder')" border="surround" v-model="formData.captcha_code"></u-input> <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> <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 sendSms = useSendSms(smsRef)
const show = ref(false) const show = ref(false)
const formData = reactive<requestMobileParam>({ const formData:any = reactive({
mobile: '', mobile: '',
captcha_code: '', captcha_code: '',
captcha_key: '', captcha_key: '',

View File

@ -1,16 +1,15 @@
<template> <template>
<!-- diyStore.mode !='decorate' && topStatusBarData topStatusBarData.style == 'style-5 为了兼容风格五 --> <view class="ns-navbar-wrap" v-if="diyStore.mode !='decorate' && topStatusBarData" :class="topStatusBarData.style">
<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" :class="{'fixed': props.scrollBool != -1, 'absolute': props.scrollBool == -1}" :style="{ backgroundColor: bgColor}">
<view class="u-navbar" :style="{ backgroundColor: bgColor}">
<view class="navbar-inner" :style="{ width: '100%', height: placeholderHeight + 'px' }"> <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="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"> <view class="title-wrap" :style="styleOneFontSize">
{{ data.title }} {{ data.title }}
</view> </view>
</view> </view>
<view v-if="topStatusBarData.style == 'style-2'" class="content-wrap" :style="navbarInnerStyle" @click="diyStore.toRedirect(topStatusBarData.link)"> <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 class="title-wrap" :style="{ color: topStatusBarData.textColor }">
<view> <view>
<image :src="img(topStatusBarData.imgUrl)" mode="heightFix"></image> <image :src="img(topStatusBarData.imgUrl)" mode="heightFix"></image>
@ -20,7 +19,7 @@
</view> </view>
<view v-if="topStatusBarData.style == 'style-3'" :style="navbarInnerStyle" class="content-wrap"> <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)"> <view class="title-wrap" @click="diyStore.toRedirect(topStatusBarData.link)">
<image :src="img(topStatusBarData.imgUrl)" mode="heightFix"></image> <image :src="img(topStatusBarData.imgUrl)" mode="heightFix"></image>
</view> </view>
@ -32,33 +31,32 @@
</view> </view>
<view v-if="topStatusBarData.style == 'style-4'" :style="navbarInnerStyle" class="content-wrap"> <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> <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> <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> <text class="nc-iconfont nc-icon-youV6xx text-[26rpx]" @click="reposition()" :style="{ color: topStatusBarData.textColor }"></text>
</view> </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>
</view> </view>
<!-- 风格5填充 -->
<view v-if="topStatusBarData.style == 'style-5'" :style="style5Height"></view>
<!-- 解决fixed定位后导航栏塌陷的问题 --> <!-- 解决fixed定位后导航栏塌陷的问题 -->
<view class="u-navbar-placeholder" :style="{ width: '100%', paddingTop: placeholderHeight + 'px' }"></view> <view class="u-navbar-placeholder" :style="{ width: '100%', paddingTop: placeholderHeight + 'px' }"></view>
<!-- #ifdef MP-WEIXIN --> <!-- #ifdef MP-WEIXIN -->
<!-- 小程序隐私协议 --> <!-- 小程序隐私协议 -->
<wx-privacy-popup ref="wxPrivacyPopup"></wx-privacy-popup> <wx-privacy-popup ref="wxPrivacyPopupRef"></wx-privacy-popup>
<!-- #endif --> <!-- #endif -->
</view> </view>
</template> </template>
<script setup lang="ts"> <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 systemInfo = uni.getSystemInfoSync();
let platform = systemInfo.platform; let platform = systemInfo.platform;
@ -68,15 +66,8 @@ let menuButtonInfo = {};
menuButtonInfo = uni.getMenuButtonBoundingClientRect(); menuButtonInfo = uni.getMenuButtonBoundingClientRect();
// #endif // #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(); const diyStore = useDiyStore();
// param{arrowLink => isShowArrow => tabbarBg => }
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object, type: Object,
@ -92,9 +83,9 @@ const props = defineProps({
type: Function, type: Function,
default: null default: null
}, },
scrollTop: { scrollBool: {
type: [String, Number], type: [String, Number],
default: '0' default: -1
}, },
// //
isBack: { isBack: {
@ -148,32 +139,50 @@ const styleOneFontSize = computed(() => {
} else if (platform === 'android') { } else if (platform === 'android') {
// (Android) // (Android)
style += 'font-size: 36rpx;'; style += 'font-size: 36rpx;';
style += 'font-weight: 500;';
} }
// #endif // #endif
style += `color: ${topStatusBarData.value.textColor};`; style += `color: ${titleTextColor.value};`;
if(topStatusBarData.value.style == 'style-1'){ if(topStatusBarData.value.style == 'style-1'){
style += `text-align: ${topStatusBarData.value.textAlign};`; style += `text-align: ${topStatusBarData.value.textAlign};`;
} }
return style; return style;
}) })
const bgColor = computed(() => { const titleTextColor = computed(()=>{
var color = ''; let color = '';
if (topStatusBarData.value.isTransparent) { if (props.scrollBool == 1) {
// color = topStatusBarData.value.rollTextColor;
color = 'transparent';
if (props.scrollTop) {
color = topStatusBarData.value.bgColor;
} else { } else {
color = 'transparent'; color = topStatusBarData.value.textColor;
} }
} else {
color = '#fff';
}
return color; 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 ***********************/ /******************************* 返回按钮-start ***********************/
let isBackShow = ref(false); let isBackShow = ref(false);
let pages = getCurrentPages(); let pages = getCurrentPages();
@ -309,29 +318,6 @@ const getQueryVariable = (variable:any)=> {
} }
/******************************* 定位-end ***********************/ /******************************* 定位-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-bottompadding-top]
style5Height.value += `padding-top:${ sysHeight }px;`
// #endif
}
}
},{immediate: true, deep:true})
/******************************* 风格五-end ***********************/
onMounted(() => { onMounted(() => {
navbarPlaceholderHeight(); navbarPlaceholderHeight();
if (pages.length > 1) { if (pages.length > 1) {
@ -349,10 +335,8 @@ const refresh = ()=>{
} }
} }
// ,1,
defineExpose({ defineExpose({
refresh, refresh
scrollValue: 1
}) })
</script> </script>
@ -368,7 +352,6 @@ defineExpose({
.u-navbar { .u-navbar {
width: 100%; width: 100%;
transition: background 0.3s; transition: background 0.3s;
position: fixed;
left: 0; left: 0;
right: 0; right: 0;
top: 0; top: 0;
@ -511,6 +494,7 @@ defineExpose({
margin: 0 10rpx; margin: 0 10rpx;
max-width: 360rpx; max-width: 360rpx;
font-size: 27rpx; font-size: 27rpx;
line-height: normal;
} }
.nearby-store-name { .nearby-store-name {

View File

@ -23,7 +23,7 @@
const agree = ref(false) const agree = ref(false)
const showPop = ref(false) const showPop = ref(false)
const privacyAuthorization = ref(null) const privacyAuthorization: any = ref(null)
const privacyResolves = new Set() const privacyResolves = new Set()
const closeOtherPagePopUpHooks = new Set() const closeOtherPagePopUpHooks = new Set()
@ -35,7 +35,7 @@
// //
const init = ()=> { const init = ()=> {
if (wx.onNeedPrivacyAuthorization) { if (wx.onNeedPrivacyAuthorization) {
wx.onNeedPrivacyAuthorization((resolve) => { wx.onNeedPrivacyAuthorization((resolve: any) => {
if (typeof privacyAuthorization.value === 'function') { if (typeof privacyAuthorization.value === 'function') {
privacyAuthorization.value(resolve) privacyAuthorization.value(resolve)
} }
@ -45,7 +45,7 @@
// //
const curPageShow = ()=> { const curPageShow = ()=> {
privacyAuthorization.value = resolve => { privacyAuthorization.value = (resolve: any) => {
privacyResolves.add(resolve) privacyResolves.add(resolve)
// //
popUp() popUp()
@ -95,7 +95,7 @@
// //
const handleDisagree = ()=> { const handleDisagree = ()=> {
privacyResolves.forEach(resolve => { privacyResolves.forEach((resolve: any) => {
resolve({ resolve({
event: 'disagree', event: 'disagree',
}) })
@ -115,7 +115,7 @@
// //
const handleAgree = ()=> { const handleAgree = ()=> {
privacyResolves.forEach(resolve => { privacyResolves.forEach((resolve: any) => {
resolve({ resolve({
event: 'agree', event: 'agree',
buttonId: 'agree-btn' buttonId: 'agree-btn'
@ -141,10 +141,11 @@
} }
} }
//
const proactive =()=> { const proactive =()=> {
if (wx.getPrivacySetting) { if (wx.getPrivacySetting) {
wx.getPrivacySetting({ wx.getPrivacySetting({
success: (res) => { success: (res: any) => {
if (res.needAuthorization) { if (res.needAuthorization) {
popUp() popUp()
// //
@ -158,6 +159,10 @@
emits('agree') emits('agree')
} }
} }
defineExpose({
proactive
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,5 +1,5 @@
import { ref, reactive, computed } from 'vue'; import { ref, reactive, computed } from 'vue';
import {onLoad, onShow, onPullDownRefresh, onPageScroll} from '@dcloudio/uni-app'; import { onLoad, onShow, onPullDownRefresh, onPageScroll, onUnload } from '@dcloudio/uni-app';
import { img, handleOnloadParams } from '@/utils/common'; import { img, handleOnloadParams } from '@/utils/common';
import { getDiyInfo } from '@/app/api/diy'; import { getDiyInfo } from '@/app/api/diy';
import useDiyStore from '@/app/stores/diy'; import useDiyStore from '@/app/stores/diy';
@ -52,12 +52,6 @@ export function useDiy(params: any = {}) {
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; return style;
}; };
@ -141,6 +135,14 @@ export function useDiy(params: any = {}) {
}) })
} }
// 监听页面卸载
const onUnloadLifeCycle = () => {
onUnload(() => {
// 兼容轮播搜索组件-切换分类时,导致个人中心白屏
diyStore.topFixedStatus = 'home'
})
}
// 监听下拉刷新事件 // 监听下拉刷新事件
const onPullDownRefreshLifeCycle = () => { const onPullDownRefreshLifeCycle = () => {
onPullDownRefresh(() => { onPullDownRefresh(() => {
@ -166,6 +168,7 @@ export function useDiy(params: any = {}) {
pageStyle, pageStyle,
onLoad: onLoadLifeCycle, onLoad: onLoadLifeCycle,
onShow: onShowLifeCycle, onShow: onShowLifeCycle,
onUnload: onUnloadLifeCycle,
onPullDownRefresh: onPullDownRefreshLifeCycle, onPullDownRefresh: onPullDownRefreshLifeCycle,
onPageScroll: onPageScrollLifeCycle, onPageScroll: onPageScrollLifeCycle,
} }

View File

@ -1,5 +1,12 @@
import { redirect, isWeixinBrowser, urlDeconstruction } from '@/utils/common' 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 { getWechatAuthCode } from '@/app/api/system'
import useMemberStore from '@/stores/member' import useMemberStore from '@/stores/member'
import useConfigStore from '@/stores/config' import useConfigStore from '@/stores/config'
@ -14,14 +21,14 @@ export function useLogin() {
const config = useConfigStore() const config = useConfigStore()
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
if (!uni.getStorageSync('autoLoginLock') && uni.getStorageSync('openid') && config.login.is_bind_mobile) { 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 return
} }
// #endif // #endif
// #ifdef H5 // #ifdef H5
if (!uni.getStorageSync('autoLoginLock') && isWeixinBrowser() && uni.getStorageSync('openid') && config.login.is_bind_mobile) { 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 return
} }
// #endif // #endif
@ -48,7 +55,7 @@ export function useLogin() {
/** /**
* *
*/ */
const authLogin = (code : string | null) => { const authLogin = (code: string | null,backFlag = false,callback: any = null) => {
let obj = {}; let obj = {};
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
@ -57,14 +64,29 @@ export function useLogin() {
weappLogin(obj).then((res: AnyObject) => { weappLogin(obj).then((res: AnyObject) => {
if (res.data.token) { if (res.data.token) {
useMemberStore().setToken(res.data.token) useMemberStore().setToken(res.data.token)
const config = useConfigStore()
setTimeout(() => { setTimeout(() => {
const memberInfo = useMemberStore().info const memberInfo = useMemberStore().info
memberInfo && memberInfo.weapp_openid && uni.setStorageSync('openid', memberInfo.weapp_openid) 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) }, 1000)
} else { } else {
uni.setStorageSync('openid', res.data.openid) uni.setStorageSync('openid', res.data.openid)
uni.setStorageSync('unionid', res.data.unionid) 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 // #endif
@ -76,9 +98,17 @@ export function useLogin() {
wechatUserLogin(user_res.data).then((res: AnyObject) => { wechatUserLogin(user_res.data).then((res: AnyObject) => {
if (res.data.token) { if (res.data.token) {
useMemberStore().setToken(res.data.token) useMemberStore().setToken(res.data.token)
const config = useConfigStore()
setTimeout(() => { setTimeout(() => {
const memberInfo = useMemberStore().info const memberInfo = useMemberStore().info
memberInfo && memberInfo.wx_openid && uni.setStorageSync('openid', memberInfo.wx_openid) 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) }, 1000)
} else { } else {
uni.setStorageSync('openid', res.data.openid) uni.setStorageSync('openid', res.data.openid)
@ -86,19 +116,53 @@ export function useLogin() {
} }
}) })
} }
}).catch((err) => {
if (err.msg == -1) {
getAuthCode('snsapi_userinfo')
} else {
uni.showToast({ title: err.msg, icon: 'none' })
}
}) })
// #endif // #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
}
/** /**
* *
* updateFlagoppenid
* 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 // #ifdef MP-WEIXIN
wx.login({ wx.login({
success(res) { success(res) {
if (res.code) { if (res.code) {
authLogin(res.code) updateFlag ? updateOpenid(res.code) : authLogin(res.code,backFlag,callback)
} else { } else {
console.log('登录失败!' + res.errMsg) console.log('登录失败!' + res.errMsg)
} }
@ -125,6 +189,7 @@ export function useLogin() {
setLoginBack, setLoginBack,
handleLoginBack, handleLoginBack,
authLogin, authLogin,
updateOpenid,
getAuthCode getAuthCode
} }
} }

View File

@ -77,6 +77,7 @@ export const useShare = () => {
weappOptions.imageUrl = options.weapp.url ? img(options.weapp.url) : '' weappOptions.imageUrl = options.weapp.url ? img(options.weapp.url) : ''
// #endif // #endif
uni.setStorageSync('weappOptions', weappOptions)
} else { } else {
getShareInfo({ getShareInfo({
route: '/' + currRoute(), route: '/' + currRoute(),
@ -105,9 +106,9 @@ export const useShare = () => {
} }
// #endif // #endif
uni.setStorageSync('weappOptions', weappOptions)
}) })
} }
uni.setStorageSync('weappOptions', weappOptions)
} }
// 小程序分享,分享给好友 // 小程序分享,分享给好友

View File

@ -27,6 +27,7 @@
"pages.member.detailed_account": "流水明细", "pages.member.detailed_account": "流水明细",
"pages.member.index": "", "pages.member.index": "",
"pages.member.personal": "个人资料", "pages.member.personal": "个人资料",
"pages.member.contact": "客服",
"pages.pay.browser": "支付", "pages.pay.browser": "支付",
"pages.pay.result": "支付结果", "pages.pay.result": "支付结果",
"pages.setting.index": "设置", "pages.setting.index": "设置",

View File

@ -23,9 +23,19 @@
"headimgPlaceholder": "请设置头像", "headimgPlaceholder": "请设置头像",
"getAvatarNickname": "获取您的昵称头像", "getAvatarNickname": "获取您的昵称头像",
"getAvatarNicknameTips": "获取用户头像、昵称完善个人资料,主要用于向用户提供具有辨识度的用户中心界面", "getAvatarNicknameTips": "获取用户头像、昵称完善个人资料,主要用于向用户提供具有辨识度的用户中心界面",
"mobile":"手机号",
"getMobile":"获取手机号",
"mobileTips":"请获取手机号",
"point": "积分", "point": "积分",
"balance": "余额", "balance": "余额",
"login": "登录", "login": "登录",
"bind": "绑定",
"binding": "绑定中",
"bindMobile": "绑定手机号",
"agreeTips": "请阅读并同意",
"pleaceAgree": "请勾选已阅读并同意",
"weixinUserAuth": "一键绑定",
"mobileQuickLogin": "手机号快捷登录",
"register": "注册", "register": "注册",
"complete": "完成", "complete": "完成",
"close": "关闭", "close": "关闭",
@ -60,7 +70,6 @@
"reserveSuccess": "预约成功", "reserveSuccess": "预约成功",
"cardLink": "次卡", "cardLink": "次卡",
"myLink": "我的", "myLink": "我的",
"siteStatus": "站点状态",
"reserveBtn": "去抢购", "reserveBtn": "去抢购",
"cardBtn": "办理", "cardBtn": "办理",
"soldOut": "已售", "soldOut": "已售",

View File

@ -217,6 +217,12 @@
}, },
"needLogin": true "needLogin": true
}, },
{
"path": "app/pages/member/contact",
"style": {
"navigationBarTitleText": "%pages.member.contact%"
}
},
{ {
"path": "app/pages/pay/browser", "path": "app/pages/pay/browser",
"style": { "style": {

View File

@ -1,7 +1,6 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { getConfig } from '@/app/api/auth' import { getConfig } from '@/app/api/auth'
import { getTabbarList } from '@/app/api/diy' import { getTabbarList } from '@/app/api/diy'
import { cloneDeep } from 'lodash-es'
interface loginConfig { interface loginConfig {
is_username: number | boolean, is_username: number | boolean,

View File

@ -2,7 +2,7 @@ import { defineStore } from 'pinia'
import { setToken, removeToken, redirect } from '@/utils/common' 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 { logout } from '@/app/api/auth'
import useConfigStore from '@/stores/config'
interface Member { interface Member {
token: string | null token: string | null
info: AnyObject | null info: AnyObject | null
@ -37,14 +37,20 @@ const useMemberStore = defineStore('member', {
if (!this.token) return if (!this.token) return
this.token = '' this.token = ''
this.info = null this.info = null
uni.setStorageSync('autoLoginLock', true) if(useConfigStore().login.is_auth_register){
uni.setStorageSync('autoLoginLock', true) // todo 普通账号退出登录,在进行三方账号登录不会自动登录
}
await logout().then(() => { await logout().then(() => {
removeToken() removeToken()
uni.removeStorageSync('wap_member_info'); uni.removeStorageSync('wap_member_info');
uni.removeStorageSync('openid');
uni.removeStorageSync('isbindmobile');
isRedirect && redirect({ url: '/app/pages/index/index', mode: 'switchTab' }) isRedirect && redirect({ url: '/app/pages/index/index', mode: 'switchTab' })
}).catch(() => { }).catch(() => {
removeToken() removeToken()
uni.removeStorageSync('wap_member_info'); uni.removeStorageSync('wap_member_info');
uni.removeStorageSync('openid');
uni.removeStorageSync('isbindmobile');
isRedirect && redirect({ url: '/app/pages/index/index', mode: 'switchTab' }) isRedirect && redirect({ url: '/app/pages/index/index', mode: 'switchTab' })
}) })
}, },

View File

@ -1,6 +1,5 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { getSiteInfo, getMap } from '@/app/api/system' import { getSiteInfo, getMap } from '@/app/api/system'
import { redirect } from '@/utils/common'
interface System { interface System {
site: AnyObject | null, site: AnyObject | null,

View File

@ -4,9 +4,10 @@
--primary-color-disabled: #9acafc; --primary-color-disabled: #9acafc;
--primary-color-light: #ecf5ff; --primary-color-light: #ecf5ff;
--page-bg-color: #f7f7f7; --page-bg-color: #f7f7f7;
--sidebar-m: 20rpx;
--rounded-angle: 16rpx;
} }
// 价格字体设置
// 字体设置
@font-face { @font-face {
font-family: 'myFont'; font-family: 'myFont';
/* #ifdef MP */ /* #ifdef MP */
@ -16,10 +17,10 @@
src: url('@/styles/custom.ttf') format('truetype'); src: url('@/styles/custom.ttf') format('truetype');
/* #endif */ /* #endif */
} }
.price-font{ .price-font{
font-family: 'myFont','-apple-system', 'BlinkMacSystemFont', 'Helvetica Neue', 'Helvetica', 'Segoe UI', 'Arial', 'Roboto', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft Yahei','sans-serif'; 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 { uni-page-body {
line-height: 1.8; line-height: 1.8;
@ -42,6 +43,72 @@ button[type='primary'],uni-button[type='primary']{
background-color: var(--primary-color) !important; 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 { .using-hidden {
word-break: break-all; word-break: break-all;
@ -105,3 +172,14 @@ button[type='primary'],uni-button[type='primary']{
color: #999; color: #999;
} }
/****************** u-cell-end *********************/ /****************** 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 **********************/

View File

@ -2,7 +2,7 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
background-size: contain; background-size: 100%;
background-repeat: no-repeat !important; background-repeat: no-repeat !important;
} }

View File

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 3952239 */ font-family: "iconfont"; /* Project id 3952239 */
src: url('//at.alicdn.com/t/c/font_3952239_da988xfzfy9.woff2?t=1718609129756') format('woff2'), src: url('//at.alicdn.com/t/c/font_3952239_mvhdfb735e.woff2?t=1719994029682') format('woff2'),
url('//at.alicdn.com/t/c/font_3952239_da988xfzfy9.woff?t=1718609129756') format('woff'), url('//at.alicdn.com/t/c/font_3952239_mvhdfb735e.woff?t=1719994029682') format('woff'),
url('//at.alicdn.com/t/c/font_3952239_da988xfzfy9.ttf?t=1718609129756') format('truetype'); url('//at.alicdn.com/t/c/font_3952239_mvhdfb735e.ttf?t=1719994029682') format('truetype');
} }
.iconfont { .iconfont {
@ -13,6 +13,30 @@
-moz-osx-font-smoothing: grayscale; -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 { .iconyuanhu:before {
content: "\e644"; content: "\e644";
} }

View File

@ -1,7 +1,7 @@
.member-record-list{ .member-record-list{
@apply min-h-[100vh]; @apply min-h-[100vh];
.member-record-item{ .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{ .name{
@apply text-sm; @apply text-sm;
} }
@ -12,10 +12,10 @@
color: #FF0D3E; color: #FF0D3E;
} }
.money{ .money{
@apply absolute right-3 top-4 text-base font-bold; @apply absolute right-0 top-4 text-base font-bold;
} }
.state{ .state{
@apply absolute right-3 top-11 text-[#8D8C8D] text-xs; @apply absolute right-0 top-11 text-[#8D8C8D] text-xs;
} }
} }
} }

View File

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "nc-iconfont"; /* Project id 4567203 */ font-family: "nc-iconfont"; /* Project id 4567203 */
src: url('//at.alicdn.com/t/c/font_4567203_jiym07jhp7i.woff2?t=1718104706175') format('woff2'), src: url('//at.alicdn.com/t/c/font_4567203_fc0pt9szyn7.woff2?t=1721726440236') format('woff2'),
url('//at.alicdn.com/t/c/font_4567203_jiym07jhp7i.woff?t=1718104706175') format('woff'), url('//at.alicdn.com/t/c/font_4567203_fc0pt9szyn7.woff?t=1721726440236') format('woff'),
url('//at.alicdn.com/t/c/font_4567203_jiym07jhp7i.ttf?t=1718104706175') format('truetype'); url('//at.alicdn.com/t/c/font_4567203_fc0pt9szyn7.ttf?t=1721726440236') format('truetype');
} }
.nc-iconfont { .nc-iconfont {
@ -13,6 +13,18 @@
-moz-osx-font-smoothing: grayscale; -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 { .nc-icon-kefuV6xx1:before {
content: "\e76a"; content: "\e76a";
} }

View File

@ -2,6 +2,8 @@ import { getTabbarPages } from './pages'
import useDiyStore from '@/app/stores/diy' import useDiyStore from '@/app/stores/diy'
import useMemberStore from '@/stores/member' import useMemberStore from '@/stores/member'
import useSystemStore from '@/stores/system' 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 if (useDiyStore().mode == 'decorate') return
let { url, mode, param, success, fail, complete } = redirect 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' mode = mode || 'navigateTo'
const tabBar = getTabbarPages() const tabBar = getTabbarPages()
tabBar.includes(url) && (mode = 'switchTab') tabBar.includes(url) && (mode = 'switchTab')
@ -442,3 +452,8 @@ const isArray = (value: any) => {
return Object.prototype.toString.call(value) === '[object Array]' 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;
}

View File

@ -1,6 +1,6 @@
import { language } from '@/locale' import { language } from '@/locale'
import { checkNeedLogin } from '@/utils/auth' import { checkNeedLogin } from '@/utils/auth'
import { redirect, getToken, isWeixinBrowser } from '@/utils/common' import { getToken } from '@/utils/common'
import { memberLog } from '@/app/api/auth' import { memberLog } from '@/app/api/auth'
import useConfigStore from "@/stores/config"; import useConfigStore from "@/stores/config";
import { useShare } from '@/hooks/useShare' import { useShare } from '@/hooks/useShare'
@ -89,6 +89,7 @@ const setAddonName = async (path: string) => {
} }
} }
} }
// 加载分享 // 加载分享

View File

@ -4,7 +4,7 @@ import pagesJson from '@/pages.json'
* *
*/ */
export function getNeedLoginPages() { export function getNeedLoginPages() {
const pages = [] const pages: any = []
// 获取主包中需要登录的页面 // 获取主包中需要登录的页面
pagesJson.pages.forEach(item => { pagesJson.pages.forEach(item => {
if (item.needLogin) pages.push(`/${ item.path }`) if (item.needLogin) pages.push(`/${ item.path }`)
@ -24,7 +24,7 @@ export function getNeedLoginPages() {
* *
*/ */
export function getAppPages() { export function getAppPages() {
const pages = [] const pages: any = []
// 获取主包中需要登录的页面 // 获取主包中需要登录的页面
pagesJson.pages.forEach(item => { pagesJson.pages.forEach(item => {
pages.push(`/${ item.path }`) pages.push(`/${ item.path }`)
@ -33,7 +33,7 @@ export function getAppPages() {
} }
export function getSubPackagesPages() { export function getSubPackagesPages() {
const pages = [] const pages: any = []
// 获取分包中需要登录的页面 // 获取分包中需要登录的页面
if (pagesJson.subPackages) { if (pagesJson.subPackages) {
pagesJson.subPackages.forEach(subPackages => { pagesJson.subPackages.forEach(subPackages => {
@ -49,7 +49,9 @@ export function getSubPackagesPages() {
* tabbar * tabbar
*/ */
export function getTabbarPages() { export function getTabbarPages() {
return pagesJson.tabBar.list.map(item => { return `/${item.pagePath}` }) return pagesJson.tabBar.list.map(item => {
return `/${ item.pagePath }`
})
} }
/** /**

View File

@ -8,7 +8,8 @@ interface RequestConfig {
showSuccessMessage?: boolean showSuccessMessage?: boolean
} }
interface RequestOptions extends UniNamespace.RequestOptions, RequestOptions { } interface RequestOptions extends UniNamespace.RequestOptions, RequestOptions {
}
class Request { class Request {
private baseUrl: string private baseUrl: string

View 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
}
}