refactor: 重构多个组件以支持 Vue 3 语法和功能

- 将多个组件转换为 `<script setup>` 语法,提升可读性和性能
- 优化状态管理和事件处理逻辑,简化代码结构
- 更新样式和布局以适应新组件结构
- 添加新功能和修复已知问题,提升用户体验
This commit is contained in:
Yer11214
2026-07-08 18:37:11 +08:00
parent 4d0b0fb5e4
commit 349ffa4f34
189 changed files with 18278 additions and 20758 deletions

View File

@@ -1,43 +1,208 @@
<template>
<div class="wrapper" :style="themeStyle">
<!-- 楼层装修组件 -->
<tpl ref="tpl" />
</div>
<view class="home-page" :style="themeStyle">
<view
v-for="(item, index) in pageData.list"
:key="`${item.type}-${index}`"
class="floor-block"
>
<u-navbar
class="navbar"
v-if="item.type == 'search'"
:auto-back="false"
:fixed="index === 1 ? false : true"
:placeholder="index === 1 ? false : true"
left-icon=""
title=""
bg-color="#ffffff"
>
<template #left>
<view class="navbar-search-wrap" :style="searchBarStyle" @click.stop>
<search :res="item.options" />
</view>
</template>
</u-navbar>
<carousel v-if="item.type == 'carousel'" :res="item.options" />
<titleLayout v-if="item.type == 'title'" :res="item.options" />
<leftOneRightTwo v-if="item.type == 'leftOneRightTwo'" :res="item.options" />
<leftTwoRightOne v-if="item.type == 'leftTwoRightOne'" :res="item.options" />
<topOneBottomTwo v-if="item.type == 'topOneBottomTwo'" :res="item.options" />
<topTwoBottomOne v-if="item.type == 'topTwoBottomOne'" :res="item.options" />
<flexThree v-if="item.type == 'flexThree'" :res="item.options" />
<flexFive v-if="item.type == 'flexFive'" :res="item.options" />
<flexFour v-if="item.type == 'flexFour'" :res="item.options" />
<flexTwo v-if="item.type == 'flexTwo'" :res="item.options" />
<textPicture v-if="item.type == 'textPicture'" :res="item.options" />
<menuLayout v-if="item.type == 'menu'" :res="item.options" />
<flexOne v-if="item.type == 'flexOne'" :res="item.options" />
<goods
v-if="item.type == 'goods'"
:enableBottomLoad="enableLoad"
:res="item.options"
/>
<group v-if="item.type == 'group'" :res="item.options" />
<notice v-if="item.type == 'notice'" :res="item.options" />
<promotions v-if="item.type == 'promotionDetail'" :res="item.options" />
<videoLayout v-if="item.type == 'video'" :res="item.options" />
</view>
<fetchCoupon ref="couponRef" />
</view>
</template>
<script>
import tpl from "@/pages/tabbar/home/views.vue";
export default {
data() {
return {
background: {
backgroundColor: "#fff",
},
};
},
onShow(){
setTimeout(()=>{
this.$refs.tpl.fetchCoupon();
},1000)
},
methods: {
<script setup lang="ts">
import { ref, computed } from 'vue'
import {
onShow,
onReady,
onReachBottom,
onPullDownRefresh,
} from '@dcloudio/uni-app'
import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import carousel from '@/pages/tabbar/home/template/tpl_banner.vue'
import titleLayout from '@/pages/tabbar/home/template/tpl_title.vue'
import leftOneRightTwo from '@/pages/tabbar/home/template/tpl_left_one_right_two.vue'
import leftTwoRightOne from '@/pages/tabbar/home/template/tpl_left_two_right_one.vue'
import topOneBottomTwo from '@/pages/tabbar/home/template/tpl_top_one_bottom_two.vue'
import topTwoBottomOne from '@/pages/tabbar/home/template/tpl_top_two_bottom_one.vue'
import flexOne from '@/pages/tabbar/home/template/tpl_flex_one.vue'
import flexTwo from '@/pages/tabbar/home/template/tpl_flex_two.vue'
import flexThree from '@/pages/tabbar/home/template/tpl_flex_three.vue'
import flexFive from '@/pages/tabbar/home/template/tpl_flex_five.vue'
import flexFour from '@/pages/tabbar/home/template/tpl_flex_four.vue'
import textPicture from '@/pages/tabbar/home/template/tpl_text_picture.vue'
import menuLayout from '@/pages/tabbar/home/template/tpl_menu.vue'
import search from '@/pages/tabbar/home/template/tpl_search.vue'
import group from '@/pages/tabbar/home/template/tpl_group.vue'
import videoLayout from '@/pages/tabbar/home/template/tpl_video.vue'
import goods from '@/pages/tabbar/home/template/tpl_goods.vue'
import notice from '@/pages/tabbar/home/template/tpl_notice.vue'
import promotions from '@/pages/tabbar/home/template/tpl_promotions_detail.vue'
import fetchCoupon from '@/pages/tabbar/home/template/fetch_coupon.vue'
import { getFloorData } from '@/api/home'
},
onReachBottom(){
// 给子级监听触底加载
uni.$emit('onReachBottom',true)
},
onPullDownRefresh() {
this.$refs.tpl.init();
const HOME_LAYOUT_PADDING_RPX = 16
uni.stopPullDownRefresh();
},
components: {
tpl,
},
};
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
const couponRef = ref<InstanceType<typeof fetchCoupon>>()
const pageData = ref<{ list: any[] }>({ list: [] })
const enableLoad = ref(false)
const loading = ref(false)
const searchBarWidth = ref(0)
const searchBarStyle = computed(() => {
if (searchBarWidth.value) {
return { width: `${searchBarWidth.value}px` }
}
return { width: '100%' }
})
function setCapsuleInset() {
try {
const { windowWidth } = uni.getWindowInfo()
const leftPadding = uni.upx2px(HOME_LAYOUT_PADDING_RPX)
const rightPadding = uni.upx2px(HOME_LAYOUT_PADDING_RPX)
// #ifdef MP-WEIXIN
const menuButton = uni.getMenuButtonBoundingClientRect()
searchBarWidth.value = windowWidth - (windowWidth - menuButton.left) - leftPadding
// #endif
// #ifndef MP-WEIXIN
searchBarWidth.value = windowWidth - leftPadding - rightPadding
// #endif
} catch (e) {
searchBarWidth.value = 0
}
}
function fetchCouponFn() {
couponRef.value?.firstGetAuto()
}
function init() {
if (loading.value) return
loading.value = true
getFloorData()
.then((res) => {
const payload = res?.data ?? res
const pageDataStr = payload?.result?.pageData
const isSuccess = payload?.success === true || payload?.code === 200
if (!isSuccess || !pageDataStr) return
try {
const result = JSON.parse(pageDataStr)
pageData.value = Array.isArray(result?.list) ? result : { list: [] }
const lastItem = pageData.value.list[pageData.value.list.length - 1]
enableLoad.value =
lastItem?.type === 'goods' || lastItem?.model === 'goods'
} catch (parseError) {
console.error('parse pageData failed', parseError)
}
})
.catch((err) => {
console.error('getFloorData failed', err)
})
.finally(() => {
loading.value = false
})
}
onReady(() => {
setCapsuleInset()
init()
// #ifdef MP-WEIXIN
uni.showShareMenu({ withShareTicket: true })
// #endif
})
onShow(() => {
setTimeout(() => {
fetchCouponFn()
}, 1000)
})
onReachBottom(() => {
uni.$emit('onReachBottom', true)
})
onPullDownRefresh(() => {
init()
uni.stopPullDownRefresh()
})
</script>
<style lang="scss" scoped>
<style scoped lang="scss">
@import '@/pages/tabbar/home/template/tpl.scss';
.home-page {
width: 100%;
min-height: 100%;
background: #f9f9f9;
}
.floor-block {
width: 100%;
display: block;
}
.navbar {
width: 100%;
:deep(.u-navbar__content) {
width: 100%;
}
:deep(.u-navbar__content__left) {
flex: 1;
width: auto !important;
max-width: 100%;
padding: 0 0 0 $home-layout-padding !important;
}
}
.navbar-search-wrap {
box-sizing: border-box;
flex: 1;
min-width: 0;
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div>
<view>
<u-popup v-model:show="enableShowCoupon" mode="center" width="550rpx" height="400px">
<view style="height: 130rpx">
<view
@@ -80,72 +80,70 @@
</view>
</scroll-view>
</u-popup>
</div>
</view>
</template>
<script>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { getAutoCoup } from "@/api/login";
import storage from "@/utils/storage.js";
export default {
data() {
return {
storage,
enableShowCoupon: false,
coupList:[]
};
},
mounted() {
this.firstGetAuto();
},
methods: {
firstGetAuto() {
if(!this.isLogin('auth')) return false
let data = new Date();
let now = data.getDate();
let hours = data.getHours();
let flagCoup = storage.getAutoCp();
if (
storage.getAutoCp() &&
storage.getAutoCp() != "" &&
storage.getAutoCp() != undefined &&
storage.getAutoCp() != null
) {
if (Number(now) > Number(flagCoup)) {
if (Number(hours) >= 6) {
storage.setAutoCp(now);
this.getAutoCp();
}
}
} else {
this.getAutoCp();
import { isLogin, unitPrice } from "@/utils/filters.js";
const enableShowCoupon = ref(false);
const coupList = ref<any[]>([]);
onMounted(() => {
firstGetAuto();
});
function firstGetAuto() {
if (!isLogin("auth")) return false;
const data = new Date();
const now = data.getDate();
const hours = data.getHours();
const flagCoup = storage.getAutoCp();
if (
storage.getAutoCp() &&
storage.getAutoCp() != "" &&
storage.getAutoCp() != undefined &&
storage.getAutoCp() != null
) {
if (Number(now) > Number(flagCoup)) {
if (Number(hours) >= 6) {
storage.setAutoCp(now);
getAutoCp();
}
},
getAutoCp() {
let data = new Date();
let now = data.getDate();
getAutoCoup().then((res) => {
console.log(res);
if (res.data.success) {
this.coupList.push(...res.data.result);
if (this.coupList != "") {
this.enableShowCoupon = true;
} else {
this.enableShowCoupon = false;
}
storage.setAutoCp(now);
let objs = {};
this.coupList = this.coupList.reduce((cur, next) => {
//对象去重
if (next.id != undefined) {
objs[next.id] ? "" : (objs[next.id] = true && cur.push(next));
}
return cur;
}, []);
}
} else {
getAutoCp();
}
}
function getAutoCp() {
const data = new Date();
const now = data.getDate();
getAutoCoup().then((res) => {
console.log(res);
if (res.data.success) {
coupList.value.push(...res.data.result);
if (coupList.value != "") {
enableShowCoupon.value = true;
} else {
enableShowCoupon.value = false;
}
storage.setAutoCp(now);
const objs: Record<string, boolean> = {};
coupList.value = coupList.value.reduce((cur, next) => {
if (next.id != undefined) {
objs[next.id] ? "" : (objs[next.id] = true && cur.push(next));
}
});
},
},
};
return cur;
}, [] as any[]);
}
});
}
defineExpose({ firstGetAuto });
</script>
<style lang="scss" scoped>

View File

@@ -118,9 +118,17 @@ export function modelNavigateTo(item) {
});
break;
case "小程序直播":
// #ifndef MP-WEIXIN
uni.navigateTo({
url: `/pages/promotion/lives`,
});
// #endif
// #ifdef MP-WEIXIN
uni.showToast({
title: "小程序暂不支持直播",
icon: "none",
});
// #endif
break;
case "砍价":
uni.navigateTo({

View File

@@ -1,6 +1,6 @@
.image-mode {
width: 100%;
height: 100%;
height: auto;
display: block;
padding: 2rpx;
}
@@ -21,10 +21,10 @@ $home-layout-padding: 16rpx;
width: 100%;
}
.view-height-75 {
// height: 150rpx;
min-height: 150rpx;
}
.view-height-150 {
// height: 300rpx;
min-height: 300rpx;
flex: 1;
}

View File

@@ -14,35 +14,20 @@
indicator
@click="clickSwiper"
>
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-swiper>
</view>
</view>
</template>
<script>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
export default {
title: "导航栏",
props: ["res"],
watch: {
res: {
handler(newValue, oldValue) {
this["res"] = newValue;
},
deep: true,
},
},
mounted() {
},
methods: {
clickSwiper(index) {
modelNavigateTo(this.res.list[index]);
},
},
};
const props = defineProps<{ res: any }>();
function clickSwiper(index: number) {
modelNavigateTo(props.res.list[index]);
}
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -2,23 +2,15 @@
<template>
<div class="layout">
<u-image width="140rpx" mode="aspectFit" height="140rpx" @click="modelNavigateTo(item)" class="image-mode" v-for="(item,index) in res.list" :key="index" :src="item.img" alt="">
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
</template>
<script>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
export default {
title: "五列单行图片模块",
props: ["res"],
data() {
return {
modelNavigateTo,
};
},
mounted() {},
};
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -2,23 +2,15 @@
<template>
<div class="layout">
<u-image height="175rpx" mode="aspectFit" width="175rpx" @click="modelNavigateTo(item)" class="image-mode" :src="item.img" v-for="(item,index) in res.list" :key="index">
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
</template>
<script>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
export default {
title: "四列单行图片模块",
props: ["res"],
data() {
return {
modelNavigateTo,
};
},
mounted() {},
};
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -1,27 +1,30 @@
<template>
<div class="layout">
<div class="flex-one">
<u-image v-if="res.list[0].zoneInfo == ''" @click="modelNavigateTo(res.list[0])" width="100%" mode="aspectFit" height="280rpx" :src="res.list[0].img" alt=""></u-image>
<view class="layout">
<view class="flex-one">
<u-image
v-if="!hasHotZone"
@click="modelNavigateTo(res.list[0])"
width="100%"
mode="aspectFit"
height="280rpx"
:src="res.list[0].img"
alt=""
></u-image>
<hotzone v-else :res="res"></hotzone>
</div>
</div>
</view>
</view>
</template>
<script>
<script setup lang="ts">
import { computed } from "vue";
import { modelNavigateTo } from "./tpl";
import hotzone from "@/pages/tabbar/home/template/tpl_hot_zone.vue";
import hotzone from "./tpl_hot_zone.vue";
export default {
title: "单行图片模块",
components: {
hotzone,
},
data() {
return {
modelNavigateTo
};
},
props: ["res"],
};
const props = defineProps<{ res: any }>();
const hasHotZone = computed(() => {
const zoneInfo = props.res?.list?.[0]?.zoneInfo;
return Array.isArray(zoneInfo) ? zoneInfo.length > 0 : !!zoneInfo;
});
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -2,26 +2,15 @@
<template>
<div class="layout">
<u-image @click="modelNavigateTo(item)" height="240rpx" width="240rpx" class="image-mode" :src="item.img" v-for="(item, index) in res.list" :key="index">
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
</template>
<script>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
export default {
title: "三列单行图片模块",
props: ["res"],
mounted() {
},
data() {
return {
modelNavigateTo,
};
},
};
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -1,33 +1,23 @@
<template>
<div class="layout">
<div class="flex-two">
<div class="flex-item" @click="modelNavigateTo(res.list[0])">
<view class="layout">
<view class="flex-two">
<view class="flex-item" @click="modelNavigateTo(res.list[0])">
<u-image height="250rpx" width="100%" mode="scaleToFill" :src="res.list[0].img" alt>
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
<div class="flex-item" @click="modelNavigateTo(res.list[1])">
</view>
<view class="flex-item" @click="modelNavigateTo(res.list[1])">
<u-image height="250rpx" width="100%" mode="scaleToFill" :src="res.list[1].img" alt>
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
</div>
</div>
</view>
</view>
</view>
</template>
<script>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
export default {
title: "两张横图",
props: ["res"],
mounted() {
},
data() {
return {
modelNavigateTo,
};
},
};
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -1,8 +1,8 @@
<template>
<div class="layout">
<view class="layout">
<u-sticky>
<div class="goods-cell-title">
<div
<view class="goods-cell-title">
<view
class="goods-item-title"
:class="{ 'selected-title': selected.index == index }"
@click="handleClickTitle(title, index)"
@@ -10,13 +10,13 @@
:key="index"
>
<h4 class="h4">{{ title.title }}</h4>
<div class="title-desc">{{ title.desc }}</div>
</div>
</div>
<view class="title-desc">{{ title.desc }}</view>
</view>
</view>
</u-sticky>
<div class="goods-list">
<view class="goods-list">
<template v-for="(item, item_index) in res.list[0].listWay" :key="item_index">
<div
<view
v-if="
item.___index != undefined
? selected.index == item.___index
@@ -25,144 +25,149 @@
@click="handleClick(item)"
class="goods-item"
>
<div class="goods-img">
<view class="goods-img">
<u-image
:src="item.img"
height="350rpx"
mode="aspectFit"
width="100%"
>
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
<div class="goods-desc">
<div class="goods-title">
</view>
<view class="goods-desc">
<view class="goods-title">
{{ item.title }}
</div>
<div class="goods-bottom">
<div class="goods-price">
</view>
<view class="goods-bottom">
<view class="goods-price">
¥<span class="price-int"
>{{ goodsFormatPrice(item.price)[0] }} </span
>.{{ goodsFormatPrice(item.price)[1] }}
</div>
</div>
</div>
</div>
</view>
</view>
</view>
</view>
</template>
<template
v-if="res.list[0].titleWay[selected.index].bindCategory && goodsData.length"
v-if="currentTitleWay?.bindCategory && goodsData.length"
>
<div
<view
v-for="(item, index) in goodsData"
:key="index"
class="goods-item"
@click="handleClick(item)"
>
<div class="goods-img">
<view class="goods-img">
<u-image
:src="item.thumbnail"
height="350rpx"
mode="aspectFit"
width="100%"
>
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
<div class="goods-desc">
<div class="goods-title">
</view>
<view class="goods-desc">
<view class="goods-title">
{{ item.goodsName }}
</div>
<div class="goods-bottom">
<div class="goods-price">
</view>
<view class="goods-bottom">
<view class="goods-price">
¥<span class="price-int"
>{{ goodsFormatPrice(item.price)[0] }} </span
>.{{ goodsFormatPrice(item.price)[1] }}
</div>
</div>
</div>
</div>
</view>
</view>
</view>
</view>
</template>
</div>
</div>
</view>
</view>
</template>
<script>
<script setup lang="ts">
import { ref, reactive, watch, onMounted, onUnmounted, computed } from "vue";
import { getGoodsList } from "@/api/goods.js";
export default {
title: "商品分类以及商品",
data() {
return {
selected: {
index: 0,
val: "",
},
params: {
pageNumber: 1,
pageSize: 100,
categoryId: "",
},
goodsData: [], //商品循环内容
goodsResult:"", //es总返回内容
};
import { goodsFormatPrice } from "@/utils/filters.js";
const props = defineProps<{ res: any; enableBottomLoad?: boolean }>();
const selected = reactive({
index: 0,
val: "",
});
const currentTitleWay = computed(() => {
return props.res?.list?.[0]?.titleWay?.[selected.index]
})
const params = reactive({
pageNumber: 1,
pageSize: 100,
categoryId: "",
});
const goodsData = ref<any[]>([]);
const goodsResult = ref<any>("");
watch(
() => props.res,
(val) => {
if (!val?.list?.[0]) return
const firstListWay = val.list[0].listWay?.[0]
selected.val = firstListWay?.type || ''
const firstTitleWay = val.list[0].titleWay?.[0]
if (firstTitleWay?.bindCategory) {
initGoods(firstTitleWay)
}
},
props: ["res","enableBottomLoad"],
watch: {
res: {
handler(val) {
// 监听父级的值 如果有值将值赋给selected
if (val) {
// 如果第一个标签页绑定为商品
this.selected.val = this.res.list[0].listWay[0] ? this.res.list[0].listWay[0].type: '';
// 如果第一个标签为绑定为分类
this.res.list[0].titleWay[0].bindCategory ? this.initGoods(this.res.list[0].titleWay[0]) : ''
}
},
immediate: true,
},
},
mounted() {
uni.$on('onReachBottom',()=>{
if(this.enableBottomLoad && this.goodsResult.totalElements >= this.params.pageNumber * this.params.pageSize){
this.params.pageNumber++
this.initGoods(this.res.list[0].titleWay[this.selected.index])
}
})
},
destroyed(){
uni.$off('onReachBottom')
},
methods: {
handleClick(item) {
uni.navigateTo({
url: `/pages/product/goods?id=${item.id}&goodsId=${item.goodsId}`,
});
},
closeGoods(val, index) {
this.res.list[0].listWay.splice(index, 1);
},
async initGoods(val) {
if(this.enableBottomLoad) this.params.pageSize = 20
val ? this.params.categoryId = val.bindCategory.id : '';
const res = await getGoodsList(this.params);
if (res.data.success) {
this.goodsResult = res.data.result
const result = res.data.result.records
this.goodsData.push(...result);
console.log(this.goodsData)
}
},
handleClickTitle(val, index) {
this.selected.index = index;
this.selected.val = val.title;
if (val.bindCategory) {
this.params.pageNumber = 1
this.goodsData = []
this.initGoods(val);
}
},
},
};
{ immediate: true }
)
onMounted(() => {
uni.$on("onReachBottom", () => {
if (
props.enableBottomLoad &&
goodsResult.value.totalElements >=
params.pageNumber * params.pageSize
) {
params.pageNumber++;
initGoods(props.res.list[0].titleWay[selected.index]);
}
});
});
onUnmounted(() => {
uni.$off("onReachBottom");
});
function handleClick(item: any) {
if (!item?.id || !item?.goodsId) return
uni.navigateTo({
url: `/pages/product/goods?id=${item.id}&goodsId=${item.goodsId}`,
})
}
async function initGoods(val: any) {
if (props.enableBottomLoad) params.pageSize = 20;
val ? (params.categoryId = val.bindCategory.id) : "";
const res = await getGoodsList(params);
if (res.data.success) {
goodsResult.value = res.data.result;
const result = res.data.result.records;
goodsData.value.push(...result);
console.log(goodsData.value);
}
}
function handleClickTitle(val: any, index: number) {
selected.index = index;
selected.val = val.title;
if (val.bindCategory) {
params.pageNumber = 1;
goodsData.value = [];
initGoods(val);
}
}
</script>
<style lang="scss" scoped>
$w_94: 94%;

View File

@@ -31,38 +31,38 @@
</div>
</div>
</template>
<script>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import * as API_Promotions from "@/api/promotions";
export default {
props: ["res"],
title: "拼团",
data() {
return {
goodsList: [],
};
},
mounted() {
API_Promotions.getAssembleList({
pageNumber: 1,
pageSize: this.res.list[0].count || 3,
promotionStatus: "START",
}).then((res) => {
if (res.data.success && res.data.result && res.data.result.records) {
this.goodsList = res.data.result.records.slice(0, this.res.list[0].count || 3);
}
});
},
methods: {
goMore() {
uni.navigateTo({ url: "/pages/promotion/joinGroup" });
},
goDetail(item) {
uni.navigateTo({
url: `/pages/product/goods?id=${item.skuId}&goodsId=${item.goodsId}`,
});
},
},
};
const props = defineProps<{ res: any }>();
const goodsList = ref<any[]>([]);
onMounted(() => {
API_Promotions.getAssembleList({
pageNumber: 1,
pageSize: props.res.list[0].count || 3,
promotionStatus: "START",
}).then((res) => {
if (res.data.success && res.data.result && res.data.result.records) {
goodsList.value = res.data.result.records.slice(
0,
props.res.list[0].count || 3
);
}
});
});
function goMore() {
uni.navigateTo({ url: "/pages/promotion/joinGroup" });
}
function goDetail(item: any) {
uni.navigateTo({
url: `/pages/product/goods?id=${item.skuId}&goodsId=${item.goodsId}`,
});
}
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -21,18 +21,10 @@
</div>
</div>
</template>
<script>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
export default {
title: "热区模块",
data() {
return {
modelNavigateTo,
};
},
props: ["res"],
};
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -31,35 +31,35 @@
</div>
</div>
</template>
<script>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import * as API_Promotions from "@/api/promotions";
export default {
props: ["res"],
title: "积分商品",
data() {
return {
goodsList: [],
};
},
mounted() {
API_Promotions.getPointsGoods({
pageNumber: 1,
pageSize: this.res.list[0].count || 3,
}).then((res) => {
if (res.data.success && res.data.result && res.data.result.records) {
this.goodsList = res.data.result.records.slice(0, this.res.list[0].count || 3);
}
});
},
methods: {
goMore() {
uni.navigateTo({ url: "/pages/promotion/point/pointList" });
},
goDetail(item) {
uni.navigateTo({ url: `/pages/promotion/point/detail?id=${item.id}` });
},
},
};
const props = defineProps<{ res: any }>();
const goodsList = ref<any[]>([]);
onMounted(() => {
API_Promotions.getPointsGoods({
pageNumber: 1,
pageSize: props.res.list[0].count || 3,
}).then((res) => {
if (res.data.success && res.data.result && res.data.result.records) {
goodsList.value = res.data.result.records.slice(
0,
props.res.list[0].count || 3
);
}
});
});
function goMore() {
uni.navigateTo({ url: "/pages/promotion/point/pointList" });
}
function goDetail(item: any) {
uni.navigateTo({ url: `/pages/promotion/point/detail?id=${item.id}` });
}
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -1,38 +1,30 @@
<template>
<div class="layout">
<div class="view-height-150" @click="modelNavigateTo(res.list[0])">
<u-image width="100%" height="340rpx" class="image-mode" :src="res.list[0].img">
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="view-height-150">
<div class="view-height-75" @click="modelNavigateTo(res.list[1])">
<u-image width="100%" height="170rpx" class="image-mode" :src="res.list[1].img" alt>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="view-height-75" @click="modelNavigateTo(res.list[2])">
<u-image width="100%" height="170rpx" class="image-mode" :src="res.list[2].img" alt>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
</div>
</div>
</template>
<script>
<view class="layout">
<view class="view-height-150" @click="modelNavigateTo(res.list[0])">
<u-image width="100%" height="340rpx" class="image-mode" :src="res.list[0].img">
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</view>
<view class="view-height-150">
<view class="view-height-75" @click="modelNavigateTo(res.list[1])">
<u-image width="100%" height="170rpx" class="image-mode" :src="res.list[1].img" alt>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</view>
<view class="view-height-75" @click="modelNavigateTo(res.list[2])">
<u-image width="100%" height="170rpx" class="image-mode" :src="res.list[2].img" alt>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
export default {
title: "左一右二",
props: ["res"],
data() {
return {
modelNavigateTo,
};
},
mounted() {},
};
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -15,20 +15,10 @@
</div>
</template>
<script>
import {modelNavigateTo} from './tpl'
export default {
title: "左二右一",
props: ["res"],
data () {
return {
modelNavigateTo,
}
},
mounted() {
}
};
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -14,7 +14,7 @@
class="menu-img"
:src="item.img"
>
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</view>
<view class="menu-title">{{ item.title }}</view>
@@ -22,17 +22,10 @@
</view>
</view>
</template>
<script>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
export default {
title: "五列菜单",
props: ["res"],
data() {
return {
modelNavigateTo,
};
},
};
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -6,19 +6,14 @@
</div>
</template>
<script>
export default {
title: "公告",
props: ["res"],
data() {
return {
list: []
}
},
mounted() {
this.list = this.res.list[0].title.map(i => i.context);
},
};
<script setup lang="ts">
import { computed } from "vue";
const props = defineProps<{ res: any }>();
const list = computed(() =>
props.res.list[0].title.map((i: { context: string }) => i.context)
);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -2,7 +2,7 @@
<div class="layout">
<div class="join-list">
<div
v-for="(item, index) in res.list"
v-for="(item, index) in displayList"
:key="index"
class="join-list-item"
@click="goToDetail(item.type)"
@@ -63,113 +63,132 @@
</div>
</div>
</template>
<script>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from "vue";
import * as API_Promotions from "@/api/promotions";
import Foundation from "@/utils/Foundation.js";
export default {
props: ["res"],
data() {
return {
timeLine: "", //获取几个点活动
resTime: 0, //当前时间
time: 0, //距离下一个活动的时间值
times: {}, //时间集合
onlyOne: "", //是否最后一个商品
};
},
mounted() {
let params = {
pageNumber: 1,
pageSize: 2,
status: "START",
promotionStatus: "START",
};
this._setTimeInterval = setInterval(() => {
if (this.time <= 0) {
clearInterval(this._setTimeInterval);
} else {
this.times = Foundation.countTimeDown(this.time);
this.time--;
}
}, 1000);
this.res.list.forEach((ele) => {
switch (ele.type) {
case "PINTUAN":
API_Promotions.getAssembleList(params).then((response) => {
const data = response.data.result.records;
if (data) {
ele.data = data;
}
});
break;
case "SECKILL":
API_Promotions.getSeckillTimeLine().then((response) => {
if (response.data.success && response.data.result) {
ele.data = response.data.result[0].seckillGoodsList.slice(0, 2);
let timeLine = response.data.result.sort(
(x, y) => Number(x.timeLine) - Number(y.timeLine)
);
this.timeLine = timeLine.slice(0, 5);
this.resTime = parseInt(new Date().getTime() / 1000);
this.onlyOne = response.data.result.length === 1;
this.diffTime = parseInt(new Date().getTime() / 1000) - this.resTime;
this.time =
this.timeLine[0].distanceStartTime ||
(this.timeLine[1] && this.timeLine[1].distanceStartTime) ||
Foundation.theNextDayTime() - this.diffTime;
this.times = Foundation.countTimeDown(this.time);
console.log(this.timeLine);
}
});
break;
case "LIVE":
API_Promotions.getLiveList(params).then((response) => {
if (response.success && response.result.records) {
ele.data = response.result.records[0].commodityList.slice(0, 2);
}
});
break;
case "KANJIA":
API_Promotions.getBargainList(params).then((response) => {
if (response.success && response.result) {
ele.data = response.result.records(0, 2);
}
});
break;
default:
break;
}
});
},
methods: {
//跳转详情
goToDetail(type) {
switch(type) {
case "SECKILL":
uni.navigateTo({
url: `/pages/promotion/seckill`,
});
break;
case "PINTUAN":
uni.navigateTo({
url: `/pages/promotion/joinGroup`,
});
break;
case "LIVE":
uni.navigateTo({
url: `/pages/promotion/lives`,
});
break;
case "KANJIA":
uni.navigateTo({
url: `/pages/promotion/bargain/list`,
});
break;
};
const props = defineProps<{ res: any }>();
const displayList = computed(() => {
const list = props.res?.list || [];
// #ifdef MP-WEIXIN
return list.filter((item: any) => item.type !== "LIVE");
// #endif
// #ifndef MP-WEIXIN
return list;
// #endif
});
const timeLine = ref<any>("");
const resTime = ref(0);
const time = ref(0);
const times = ref<any>({});
const onlyOne = ref("");
let setTimeInterval: ReturnType<typeof setInterval> | null = null;
let diffTime = 0;
onMounted(() => {
const params = {
pageNumber: 1,
pageSize: 2,
status: "START",
promotionStatus: "START",
};
setTimeInterval = setInterval(() => {
if (time.value <= 0) {
if (setTimeInterval) clearInterval(setTimeInterval);
} else {
times.value = Foundation.countTimeDown(time.value);
time.value--;
}
},
};
}, 1000);
props.res.list.forEach((ele: any) => {
// #ifdef MP-WEIXIN
if (ele.type === "LIVE") return;
// #endif
switch (ele.type) {
case "PINTUAN":
API_Promotions.getAssembleList(params).then((response) => {
const data = response.data.result.records;
if (data) {
ele.data = data;
}
});
break;
case "SECKILL":
API_Promotions.getSeckillTimeLine().then((response) => {
if (response.data.success && response.data.result) {
ele.data = response.data.result[0].seckillGoodsList.slice(0, 2);
const timeline = response.data.result.sort(
(x: any, y: any) => Number(x.timeLine) - Number(y.timeLine)
);
timeLine.value = timeline.slice(0, 5);
resTime.value = parseInt(String(new Date().getTime() / 1000));
onlyOne.value = response.data.result.length === 1;
diffTime =
parseInt(String(new Date().getTime() / 1000)) - resTime.value;
time.value =
timeLine.value[0].distanceStartTime ||
(timeLine.value[1] && timeLine.value[1].distanceStartTime) ||
Foundation.theNextDayTime() - diffTime;
times.value = Foundation.countTimeDown(time.value);
console.log(timeLine.value);
}
});
break;
// #ifndef MP-WEIXIN
case "LIVE":
API_Promotions.getLiveList(params).then((response) => {
if (response.success && response.result.records) {
ele.data = response.result.records[0].commodityList.slice(0, 2);
}
});
break;
// #endif
case "KANJIA":
API_Promotions.getBargainList(params).then((response) => {
if (response.success && response.result) {
ele.data = response.result.records(0, 2);
}
});
break;
default:
break;
}
});
});
onUnmounted(() => {
if (setTimeInterval) clearInterval(setTimeInterval);
});
function goToDetail(type: string) {
switch (type) {
case "SECKILL":
uni.navigateTo({
url: `/pages/promotion/seckill`,
});
break;
case "PINTUAN":
uni.navigateTo({
url: `/pages/promotion/joinGroup`,
});
break;
// #ifndef MP-WEIXIN
case "LIVE":
uni.navigateTo({
url: `/pages/promotion/lives`,
});
break;
// #endif
case "KANJIA":
uni.navigateTo({
url: `/pages/promotion/bargain/list`,
});
break;
}
}
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -6,25 +6,20 @@
</view>
</view>
</template>
<script>
export default {
title:"搜索栏",
props: ["res","storeId"],
methods: {
handleSearch() {
if(this.storeId){
uni.navigateTo({
url: `/pages/navigation/search/searchPage?storeId=${this.storeId}`,
});
}else{
uni.navigateTo({
url: `/pages/navigation/search/searchPage`,
});
}
},
},
};
<script setup lang="ts">
const props = defineProps<{ res: any; storeId?: string }>();
function handleSearch() {
if (props.storeId) {
uni.navigateTo({
url: `/pages/navigation/search/searchPage?storeId=${props.storeId}`,
});
} else {
uni.navigateTo({
url: `/pages/navigation/search/searchPage`,
});
}
}
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -31,41 +31,38 @@
</div>
</div>
</template>
<script>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import * as API_Promotions from "@/api/promotions";
export default {
props: ["res"],
title: "秒杀",
data() {
return {
goodsList: [],
};
},
mounted() {
API_Promotions.getSeckillTimeLine().then((res) => {
if (res.data.success && res.data.result && res.data.result.length) {
const sorted = res.data.result.sort(
(x, y) => Number(x.timeLine) - Number(y.timeLine)
);
const first = sorted[0] || {};
this.goodsList = (first.seckillGoodsList || []).slice(
0,
this.res.list[0].count || 3
);
}
});
},
methods: {
goMore() {
uni.navigateTo({ url: "/pages/promotion/seckill" });
},
goDetail(item) {
uni.navigateTo({
url: `/pages/product/goods?id=${item.skuId}&goodsId=${item.goodsId}`,
});
},
},
};
const props = defineProps<{ res: any }>();
const goodsList = ref<any[]>([]);
onMounted(() => {
API_Promotions.getSeckillTimeLine().then((res) => {
if (res.data.success && res.data.result && res.data.result.length) {
const sorted = res.data.result.sort(
(x: any, y: any) => Number(x.timeLine) - Number(y.timeLine)
);
const first = sorted[0] || {};
goodsList.value = (first.seckillGoodsList || []).slice(
0,
props.res.list[0].count || 3
);
}
});
});
function goMore() {
uni.navigateTo({ url: "/pages/promotion/seckill" });
}
function goDetail(item: any) {
uni.navigateTo({
url: `/pages/product/goods?id=${item.skuId}&goodsId=${item.goodsId}`,
});
}
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -32,21 +32,10 @@
</div>
</template>
<script>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
import {modelNavigateTo} from './tpl'
export default {
title: "文字图片模板",
props: ["res"],
data () {
return {
modelNavigateTo,
}
},
mounted() {
}
};
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -12,18 +12,10 @@
</template>
<script>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
export default {
title: "标题栏",
props: ["res"],
data() {
return {
modelNavigateTo,
};
},
mounted() {},
};
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -3,36 +3,28 @@
<div class="layout">
<div class="view-width-100" @click="modelNavigateTo(res.list[0])">
<u-image class="image-mode" width="100%" height="200rpx" :src="res.list[0].img">
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
<div class="view-width-100" @click="modelNavigateTo(res.list[1])">
<div class="view-height-85">
<u-image class="image-mode" width="100%" height="170rpx" :src="res.list[1].img">
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
<div class="view-height-85" @click="modelNavigateTo(res.list[2])">
<u-image class="image-mode" width="100%" height="170rpx" :src="res.list[2].img">
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
</div>
</div>
</template>
<script>
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
export default {
title: "上一下二",
props: ["res"],
data() {
return {
modelNavigateTo,
};
},
mounted() {},
};
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -9,7 +9,7 @@
:src="res.list[0].img"
alt
>
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
<div class="view-height-85" @click="modelNavigateTo(res.list[1])">
@@ -20,7 +20,7 @@
:src="res.list[1].img"
alt
>
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
</div>
@@ -31,26 +31,16 @@
width="100%"
:src="res.list[2].img"
>
<template #loading><u-loading></u-loading></template>
<template #loading><u-loading-icon></u-loading-icon></template>
</u-image>
</div>
</div>
</template>
<script>
import {modelNavigateTo} from './tpl'
export default {
title: "上二下一",
props: ["res"],
data () {
return {
modelNavigateTo,
}
},
mounted() {
},
};
<script setup lang="ts">
import { modelNavigateTo } from "./tpl";
defineProps<{ res: any }>();
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -26,7 +26,11 @@
</div>
</div>
</template>
<script>
<script setup lang="ts">
import { computed } from "vue";
const props = defineProps<{ res: any }>();
const DEFAULT_VIDEO_STYLE = {
bgType: "color",
bgColorStart: "#F5F5F5",
@@ -49,13 +53,13 @@ const DEFAULT_VIDEO_STYLE = {
shadowSpread: 0,
};
const ASPECT_RATIO_MAP = {
const ASPECT_RATIO_MAP: Record<string, number> = {
"16:9": 56.25,
"4:3": 75,
"1:1": 100,
};
function ensureVideoItem(item) {
function ensureVideoItem(item: any) {
if (!item.aspectRatio) item.aspectRatio = "16:9";
if (!item.style) {
item.style = { ...DEFAULT_VIDEO_STYLE };
@@ -63,16 +67,16 @@ function ensureVideoItem(item) {
}
Object.keys(DEFAULT_VIDEO_STYLE).forEach((key) => {
if (item.style[key] === undefined) {
item.style[key] = DEFAULT_VIDEO_STYLE[key];
item.style[key] = DEFAULT_VIDEO_STYLE[key as keyof typeof DEFAULT_VIDEO_STYLE];
}
});
}
function getVideoGradient(style) {
function getVideoGradient(style: any) {
const start = style.bgColorStart || "#F5F5F5";
const end = style.bgColorEnd || start;
const colors = `${start}, ${end}`;
const dirMap = {
const dirMap: Record<string, string> = {
horizontal: `linear-gradient(to right, ${colors})`,
vertical: `linear-gradient(to bottom, ${colors})`,
skewLeft: `linear-gradient(135deg, ${colors})`,
@@ -81,60 +85,57 @@ function getVideoGradient(style) {
return dirMap[style.bgGradientDir] || dirMap.horizontal;
}
export default {
props: ["res"],
title: "视频",
computed: {
item() {
const data = this.res.list[0] || {};
ensureVideoItem(data);
return data;
},
wrapperStyle() {
const style = this.item.style;
return {
margin: `${style.margin || 0}px`,
padding: `${style.padding || 0}px`,
background: style.bottomBgColor || "#F5F5F5",
boxSizing: "border-box",
};
},
boxStyle() {
const style = this.item.style;
const box = {
borderRadius: `${style.bgRadius || 0}px`,
overflow: "hidden",
position: "relative",
width: "100%",
};
const item = computed(() => {
const data = props.res.list[0] || {};
ensureVideoItem(data);
return data;
});
if (style.bgType === "image" && style.bgImage) {
box.backgroundImage = `url(${style.bgImage})`;
box.backgroundSize = "cover";
box.backgroundPosition = "center";
} else {
box.background = getVideoGradient(style);
}
const wrapperStyle = computed(() => {
const style = item.value.style;
return {
margin: `${style.margin || 0}px`,
padding: `${style.padding || 0}px`,
background: style.bottomBgColor || "#F5F5F5",
boxSizing: "border-box",
};
});
if (style.borderShow) {
box.border = `${style.borderWidth || 1}px ${style.borderStyle || "solid"} ${
style.borderColor || "#e5e5e5"
}`;
}
const boxStyle = computed(() => {
const style = item.value.style;
const box: Record<string, string> = {
borderRadius: `${style.bgRadius || 0}px`,
overflow: "hidden",
position: "relative",
width: "100%",
};
if (style.shadowShow) {
box.boxShadow = `${style.shadowX || 0}px ${style.shadowY || 0}px ${
style.shadowBlur || 10
}px ${style.shadowSpread || 0}px ${style.shadowColor || "rgba(0,0,0,0.1)"}`;
}
if (style.bgType === "image" && style.bgImage) {
box.backgroundImage = `url(${style.bgImage})`;
box.backgroundSize = "cover";
box.backgroundPosition = "center";
} else {
box.background = getVideoGradient(style);
}
return box;
},
aspectPadding() {
return ASPECT_RATIO_MAP[this.item.aspectRatio] || ASPECT_RATIO_MAP["16:9"];
},
},
};
if (style.borderShow) {
box.border = `${style.borderWidth || 1}px ${style.borderStyle || "solid"} ${
style.borderColor || "#e5e5e5"
}`;
}
if (style.shadowShow) {
box.boxShadow = `${style.shadowX || 0}px ${style.shadowY || 0}px ${
style.shadowBlur || 10
}px ${style.shadowSpread || 0}px ${style.shadowColor || "rgba(0,0,0,0.1)"}`;
}
return box;
});
const aspectPadding = computed(
() => ASPECT_RATIO_MAP[item.value.aspectRatio] || ASPECT_RATIO_MAP["16:9"]
);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -8,7 +8,7 @@
@change="change"
></u-tabs>
<view v-if="showLoading" style="width:500rpx;margin:0 auto;text-align: center;height:800rpx;line-height: 800rpx;">
<u-loading mode="flower" ></u-loading>
<u-loading-icon mode="flower" ></u-loading-icon>
<text>正在加载中</text>
</view>
<u-cell-group v-if="current == 0">
@@ -64,130 +64,124 @@
</view>
</template>
<script>
import {
messages,
editMessages
} from "@/api/message.js"
export default {
data() {
return {
showLoading:true,
params: {
pageSize: 20,
pageNumber: 1,
memberId: "",
messageId: "",
status:"UN_READY"
},
loadText: {
loadmore: '轻轻上拉',
loading: '努力加载中',
nomore: '实在没有了'
},
list: [{
name: "未读"
}, {
name: "已读"
}],
current: 0,
lists: [],
status: "loadmore"
}
},
onShow() {
this.getMessage()
},
onReachBottom() {
this.params.pageNumber++;
this.statuss = "loading";
this.getMessage()
},
methods: {
linkMsgDetail(v) {
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { onShow, onReachBottom } from '@dcloudio/uni-app'
import { messages, editMessages } from '@/api/message.js'
import { useStore } from '@/store'
import { isLogin } from '@/utils/filters.js'
if (v.status == 'UN_READY') {
let params = {}
params.messageId = v.memberId
editMessages(v.id, params).then(res => {
if (res.data.success) {
console.log( this.lists)
this.lists.forEach((item,index)=>{
console.log(item)
if(item.id == v.id){
this.lists.splice(index, 1)
}
})
}
})
}
// uni.navigateTo({
// url:`/pages/tabbar/home/messageDetail?data=${encodeURIComponent(JSON.stringify(v))}`
// })
const store = useStore()
const lightColor = computed(() => store.getters.lightColor)
const mainColor = computed(() => store.getters.mainColor)
const aiderLightColor = computed(() => store.getters.aiderLightColor)
},
/**
* 返回
*/
back() {
if (getCurrentPages().length == 1) {
uni.switchTab({
url: "/pages/tabbar/home/index",
});
} else {
uni.navigateBack();
}
},
change(e) {
const index = typeof e === 'object' && e != null ? e.index : e;
this.showLoading = true;
this.current = index;
if (index == 0) {
this.params.status = "UN_READY"
this.params.pageNumber = 1;
} else if (index == 1) {
this.params.status = "ALREADY_READY"
this.params.pageNumber = 1;
}
this.lists = []
this.getMessage()
},
getMessage() {
this.params.memberId = this.isLogin().id;
messages(this.params).then(res => {
console.log(res)
if (res.data.success) {
this.showLoading = false
if (res.data.result.records == '') {
console.log(11111)
this.status = "nomore"
}
res.data.result.records.forEach(item => {
this.lists.push(item)
let obj = {};
this.lists = this.lists.reduce(
(cur, next) => {
//对象去重
if (next.id != undefined) {
obj[next.id] ?
"" :
(obj[next.id] = true && cur.push(next));
}
console.log(cur);
return cur;
},
[]
)
})
const showLoading = ref(true)
const params = reactive({
pageSize: 20,
pageNumber: 1,
memberId: '',
messageId: '',
status: 'UN_READY'
})
const loadText = {
loadmore: '轻轻上拉',
loading: '努力加载中',
nomore: '实在没有了'
}
const list = [
{ name: '未读' },
{ name: '已读' }
]
const current = ref(0)
const lists = ref<any[]>([])
const status = ref('loadmore')
onShow(() => {
getMessage()
})
onReachBottom(() => {
params.pageNumber++
status.value = 'loading'
getMessage()
})
function linkMsgDetail(v: any) {
if (v.status == 'UN_READY') {
const editParams: any = {}
editParams.messageId = v.memberId
editMessages(v.id, editParams).then((res: any) => {
if (res.data.success) {
console.log(lists.value)
lists.value.forEach((item: any, index: number) => {
console.log(item)
if (item.id == v.id) {
lists.value.splice(index, 1)
}
})
}
},
})
}
}
/**
* 返回
*/
function back() {
if (getCurrentPages().length == 1) {
uni.switchTab({
url: '/pages/tabbar/home/index'
})
} else {
uni.navigateBack()
}
}
function change(e: any) {
const index = typeof e === 'object' && e != null ? e.index : e
showLoading.value = true
current.value = index
if (index == 0) {
params.status = 'UN_READY'
params.pageNumber = 1
} else if (index == 1) {
params.status = 'ALREADY_READY'
params.pageNumber = 1
}
lists.value = []
getMessage()
}
function getMessage() {
params.memberId = isLogin().id
messages(params).then((res: any) => {
console.log(res)
if (res.data.success) {
showLoading.value = false
if (res.data.result.records == '') {
console.log(11111)
status.value = 'nomore'
}
res.data.result.records.forEach((item: any) => {
lists.value.push(item)
let obj: Record<string, any> = {}
lists.value = lists.value.reduce(
(cur: any[], next: any) => {
// 对象去重
if (next.id != undefined) {
!obj[next.id] && (obj[next.id] = true) && cur.push(next)
}
console.log(cur)
return cur
},
[]
)
})
}
})
}
</script>
<style>
.foot {

View File

@@ -1,312 +1,4 @@
<!-- 首页已合并至 index.vue请勿再引用本文件 -->
<template>
<div class="wrapper" :style="themeStyle">
<!-- uni 中不能使用 vue component 所以用if判断每个组件 -->
<div v-for="(item, index) in pageData.list" :key="index">
<!-- 搜索栏如果在楼层装修顶部则会自动浮动否则不浮动 -->
<u-navbar
class="navbar"
v-if="item.type == 'search'"
:auto-back="false"
:fixed="index === 1 ? false : true"
:placeholder="index === 1 ? false : true"
left-icon=""
title=""
bg-color="#ffffff"
>
<template #left>
<view class="navbar-search-wrap" :style="searchBarStyle" @click.stop>
<search :res="item.options" />
</view>
</template>
</u-navbar>
<carousel v-if="item.type == 'carousel'" :res="item.options" />
<titleLayout v-if="item.type == 'title'" :res="item.options" />
<leftOneRightTwo v-if="item.type == 'leftOneRightTwo'" :res="item.options" />
<leftTwoRightOne v-if="item.type == 'leftTwoRightOne'" :res="item.options" />
<topOneBottomTwo v-if="item.type == 'topOneBottomTwo'" :res="item.options" />
<topTwoBottomOne v-if="item.type == 'topTwoBottomOne'" :res="item.options" />
<flexThree v-if="item.type == 'flexThree'" :res="item.options" />
<flexFive v-if="item.type == 'flexFive'" :res="item.options" />
<flexFour v-if="item.type == 'flexFour'" :res="item.options" />
<flexTwo v-if="item.type == 'flexTwo'" :res="item.options" />
<textPicture v-if="item.type == 'textPicture'" :res="item.options" />
<menuLayout v-if="item.type == 'menu'" :res="item.options" />
<flexOne v-if="item.type == 'flexOne'" :res="item.options" />
<goods :enableBottomLoad="enableLoad" v-if="item.type == 'goods'" :res="item.options" />
<group v-if="item.type == 'group'" :res="item.options" />
<notice v-if="item.type == 'notice'" :res="item.options" />
<promotions v-if="item.type == 'promotionDetail'" :res="item.options" />
<!-- <integral v-if="item.type == 'integral'" :res="item.options" /> -->
<!-- <spike v-if="item.type == 'spike'" :res="item.options" /> -->
<videoLayout v-if="item.type == 'video'" :res="item.options" />
</div>
<fetchCoupon ref='coupon' />
<u-no-network @retry="init" @isConnected="isConnected"></u-no-network>
</div>
<view />
</template>
<script>
// 引用组件
import tpl_banner from "@/pages/tabbar/home/template/tpl_banner"; //导航栏模块
import tpl_title from "@/pages/tabbar/home/template/tpl_title"; //标题栏模块
import tpl_left_one_right_two from "@/pages/tabbar/home/template/tpl_left_one_right_two"; //左一右二模块
import tpl_left_two_right_one from "@/pages/tabbar/home/template/tpl_left_two_right_one"; //左二右一模块
import tpl_top_one_bottom_two from "@/pages/tabbar/home/template/tpl_top_one_bottom_two"; //上一下二模块
import tpl_top_two_bottom_one from "@/pages/tabbar/home/template/tpl_top_two_bottom_one"; //上二下一模块
import tpl_flex_one from "@/pages/tabbar/home/template/tpl_flex_one"; //单行图片模块
import tpl_flex_two from "@/pages/tabbar/home/template/tpl_flex_two"; //两张横图模块
import tpl_flex_three from "@/pages/tabbar/home/template/tpl_flex_three"; //三列单行图片模块
import tpl_flex_five from "@/pages/tabbar/home/template/tpl_flex_five"; //五列单行图片模块
import tpl_flex_four from "@/pages/tabbar/home/template/tpl_flex_four"; //四列单行图片模块
import tpl_text_picture from "@/pages/tabbar/home/template/tpl_text_picture"; //文字图片模板
import tpl_menu from "@/pages/tabbar/home/template/tpl_menu"; //五列菜单模块
import tpl_search from "@/pages/tabbar/home/template/tpl_search"; //搜索栏
import tpl_group from "@/pages/tabbar/home/template/tpl_group"; //
import tpl_video from "@/pages/tabbar/home/template/tpl_video"; //视频模块
import tpl_goods from "@/pages/tabbar/home/template/tpl_goods"; //商品分类以及分类中的商品
// 结束引用组件
import { getFloorData } from "@/api/home"; //获取楼层装修接口
import permission from "@/js_sdk/wa-permission/permission.js"; //权限工具类
import config from "@/config/config";
import tpl_notice from "@/pages/tabbar/home/template/tpl_notice"; //标题栏模块
import tpl_promotions from "@/pages/tabbar/home/template/tpl_promotions_detail"; //标题栏模块
import storage from "@/utils/storage.js";
import fetchCoupon from '@/pages/tabbar/home/template/fetch_coupon'
// 与 tpl.scss $home-layout-padding 保持一致
const HOME_LAYOUT_PADDING_RPX = 16;
// import {receiveCoupons} from "@/api/members"
export default {
data () {
return {
config,
storage,
showCp:true,
pageData: "", //楼层页面数据
isIos: "",
enableLoad: false, //触底加载 针对于商品模块
capsuleInsetRight: 0,
searchBarWidth: 0,
};
},
computed: {
searchBarStyle() {
if (this.searchBarWidth) {
return {
width: `${this.searchBarWidth}px`,
};
}
return {
width: "100%",
};
},
},
components: {
carousel: tpl_banner,
titleLayout: tpl_title,
leftOneRightTwo: tpl_left_one_right_two,
leftTwoRightOne: tpl_left_two_right_one,
topOneBottomTwo: tpl_top_one_bottom_two,
topTwoBottomOne: tpl_top_two_bottom_one,
flexThree: tpl_flex_three,
flexFive: tpl_flex_five,
flexFour: tpl_flex_four,
flexTwo: tpl_flex_two,
textPicture: tpl_text_picture,
menuLayout: tpl_menu,
search: tpl_search,
flexOne: tpl_flex_one,
goods: tpl_goods,
group: tpl_group,
notice: tpl_notice,
promotions: tpl_promotions,
videoLayout: tpl_video,
fetchCoupon
},
mounted () {
this.setCapsuleInset();
this.init();
// #ifdef MP-WEIXIN
// 小程序默认分享
uni.showShareMenu({ withShareTicket: true });
// #endif
},
methods: {
setCapsuleInset() {
try {
const { windowWidth } = uni.getWindowInfo();
const leftPadding = uni.upx2px(HOME_LAYOUT_PADDING_RPX);
const rightPadding = uni.upx2px(HOME_LAYOUT_PADDING_RPX);
// #ifdef MP-WEIXIN
const menuButton = uni.getMenuButtonBoundingClientRect();
this.capsuleInsetRight = windowWidth - menuButton.left;
this.searchBarWidth =
windowWidth - this.capsuleInsetRight - leftPadding;
// #endif
// #ifndef MP-WEIXIN
this.searchBarWidth = windowWidth - leftPadding - rightPadding;
// #endif
} catch (e) {
this.capsuleInsetRight = 0;
this.searchBarWidth = 0;
}
},
fetchCoupon(){
this.$refs.coupon.firstGetAuto();
},
/**
* 实例化首页数据楼层
*/
init () {
this.pageData = "";
getFloorData().then((res) => {
if (res.data.success) {
const result = JSON.parse(res.data.result.pageData)
this.pageData = result;
if (result.list.length) {
// 如果最后一个装修模块是商品模块的话 默认启用自动加载
result.list[result.list.length - 1] ? result.list[result.list.length - 1].model == 'goods' ? this.enableLoad = true : '' : ''
}
}
});
},
// 是否有网络链接
isConnected (val) {
val ? this.init() : ''
},
/**
* TODO 扫码功能后续还会后续增加
* 应该实现的功能目前计划有:
* 扫描商品跳转商品页面
* 扫描活动跳转活动页面
* 扫描二维码登录
* 扫描其他站信息 弹出提示,返回首页。
*/
scanCode () {
uni.scanCode({
success: function (res) {
let path = encodeURIComponent(res.result);
if (path != undefined && path.indexOf("QR_CODE_LOGIN_SESSION") == 0) {
console.log(path)
//app扫码登录
uni.navigateTo({
url: "/pages/passport/scannerCodeLoginConfirm?token=" + path
});
return;
}
// WX_CODE 为小程序码
if (res.scanType == "WX_CODE") {
console.log(res);
uni.navigateTo({
url: `/${res.path}`,
});
} else {
config.scanAuthNavigation.forEach((src) => {
if (res.result.indexOf(src) != -1) {
uni.navigateTo({
url: `/${res.result.substring(src.length)}`,
});
} else {
setTimeout(() => {
uni.navigateTo({
url: "/pages/tabbar/home/web-view?src=" + path,
});
}, 100);
}
});
}
},
});
},
/**
* 提示获取权限
*/
tipsGetSettings () {
uni.showModal({
title: "提示",
content: "您已经关闭相机权限,去设置",
success: function (res) {
if (res.confirm) {
if (this.isIos) {
plus.runtime.openURL("app-settings:");
} else {
permission.gotoAppPermissionSetting();
}
}
},
});
},
/**
* 唤醒客户端扫码
* 没权限去申请权限,有权限获取扫码功能
*/
async scan () {
// #ifdef APP-PLUS
this.isIos = plus.os.name == "iOS";
// 判断是否是Ios
if (this.isIos) {
const iosFirstCamera = uni.getStorageSync("iosFirstCamera"); //是不是第一次开启相机
if (iosFirstCamera !== "false") {
uni.setStorageSync("iosFirstCamera", "false"); //设为false就代表不是第一次开启相机
this.scanCode();
} else {
if (permission.judgeIosPermission("camera")) {
this.scanCode();
} else {
// 没有权限提醒是否去申请权限
this.tipsGetSettings();
}
}
} else {
/**
* TODO 安卓 权限已经授权了调用api总是显示用户已永久拒绝申请。人傻了
* TODO 如果xdm有更好的办法请在 https://gitee.com/beijing_hongye_huicheng/lilishop/issues 提下谢谢
*/
this.scanCode();
}
// #endif
// #ifdef MP-WEIXIN
this.scanCode();
// #endif
},
},
};
</script>
<style scoped lang="scss">
@import "@/pages/tabbar/home/template/tpl.scss";
.navbar {
width: 100%;
:deep(.u-navbar__content) {
width: 100%;
}
:deep(.u-navbar__content__left) {
flex: 1;
width: auto !important;
max-width: 100%;
padding: 0 0 0 $home-layout-padding !important;
}
}
.navbar-search-wrap {
box-sizing: border-box;
flex: 1;
min-width: 0;
}
</style>

View File

@@ -4,43 +4,38 @@
</view>
</template>
<script>
import configs from "@/config/config";
import storage from "@/utils/storage";
export default {
data() {
return {
configs,
storage,
webviewStyles: {
progress: {
color: this.$lightColor,
},
},
src: "",
};
<script setup lang="ts">
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import configs from '@/config/config'
import storage from '@/utils/storage'
import { useStore } from '@/store'
const store = useStore()
const lightColor = computed(() => store.getters.lightColor)
const mainColor = computed(() => store.getters.mainColor)
const aiderLightColor = computed(() => store.getters.aiderLightColor)
const webviewStyles = computed(() => ({
progress: {
color: lightColor.value,
},
onLoad(params) {
// params.IM ? (this.src = `${configs.imWebSrc}?token=${storage.getAccessToken()}&id=${params.IM}`): (this.src = decodeURIComponent(params.src));
if(params.IM)
{
if(params.IM==0)
{
this.src = `${configs.imWebSrc}?token=${storage.getAccessToken()}`;
}
else
{
this.src = `${configs.imWebSrc}?token=${storage.getAccessToken()}&id=${params.IM}`;
}
}
else
{
this.src = decodeURIComponent(params.src);
console.log(this.src);
}
},
};
}))
const src = ref('')
onLoad((params) => {
if (params.IM) {
if (params.IM == 0) {
src.value = `${configs.imWebSrc}?token=${storage.getAccessToken()}`
} else {
src.value = `${configs.imWebSrc}?token=${storage.getAccessToken()}&id=${params.IM}`
}
} else {
src.value = decodeURIComponent(params.src)
console.log(src.value)
}
})
</script>
<style lang="scss" scoped>