mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-uniapp.git
synced 2026-08-06 02:47:25 +08:00
refactor: 重构多个组件以支持 Vue 3 语法和功能
- 将多个组件转换为 `<script setup>` 语法,提升可读性和性能 - 优化状态管理和事件处理逻辑,简化代码结构 - 更新样式和布局以适应新组件结构 - 添加新功能和修复已知问题,提升用户体验
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
<u-col span="12">
|
||||
<u-row :gutter="12">
|
||||
<u-col :offset="1" span="4">
|
||||
<u-button class="btns" @click="askValue=''">清空</u-button>
|
||||
<u-button class="btns" @click="params.askValue=''">清空</u-button>
|
||||
</u-col>
|
||||
<u-col :offset="2" span="4">
|
||||
<u-button class="btns" @click="getAskMessage()" type="success">提交</u-button>
|
||||
@@ -36,75 +36,83 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as API_GOODS from "../../api/goods";
|
||||
import * as API_MEM from "../../api/members";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
askGoods: "",
|
||||
queryGoodsDetail: "",
|
||||
border: true,
|
||||
params: {
|
||||
askValue: "",
|
||||
anonymous: "YES",
|
||||
},
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
this.askGoods = options;
|
||||
this.getGoodsData();
|
||||
},
|
||||
methods: {
|
||||
getGoodsData() {
|
||||
if (this.askGoods.goods_id) {
|
||||
API_GOODS.getGoods(this.askGoods.goods_id).then((result) => {
|
||||
this.queryGoodsDetail = result.data;
|
||||
});
|
||||
}
|
||||
},
|
||||
getAskMessage() {
|
||||
uni.showLoading();
|
||||
if (this.params.askValue == "") {
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import * as API_GOODS from '../../api/goods'
|
||||
import * as API_MEM from '../../api/members'
|
||||
import { useStore } from '@/store'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const askGoods = ref<any>('')
|
||||
const queryGoodsDetail = ref<any>('')
|
||||
const border = ref(true)
|
||||
const params = reactive({
|
||||
askValue: '',
|
||||
anonymous: 'YES',
|
||||
})
|
||||
|
||||
function getGoodsData() {
|
||||
if (askGoods.value.goods_id) {
|
||||
API_GOODS.getGoods(askGoods.value.goods_id).then((result) => {
|
||||
queryGoodsDetail.value = result.data
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getAskMessage() {
|
||||
uni.showLoading()
|
||||
if (params.askValue == '') {
|
||||
uni.showToast({
|
||||
title: '请填写内容!',
|
||||
icon: 'none',
|
||||
})
|
||||
if (store.state.isShowToast) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
return false
|
||||
}
|
||||
API_MEM.consultating(
|
||||
askGoods.value.goods_id,
|
||||
params.askValue,
|
||||
params.anonymous
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.statusCode == 200) {
|
||||
uni.showToast({
|
||||
title: "请填写内容!",
|
||||
icon: "none",
|
||||
});
|
||||
if (this.$store.state.isShowToast){ uni.hideLoading() };
|
||||
return false;
|
||||
}
|
||||
API_MEM.consultating(
|
||||
this.askGoods.goods_id,
|
||||
this.params.askValue,
|
||||
this.params.anonymous
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.statusCode == 200) {
|
||||
uni.showToast({
|
||||
title: "提交成功!",
|
||||
icon: "none",
|
||||
});
|
||||
this.askValue = "";
|
||||
}
|
||||
if (this.$store.state.isShowToast){ uni.hideLoading() };
|
||||
title: '提交成功!',
|
||||
icon: 'none',
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
if (this.$store.state.isShowToast){ uni.hideLoading() };
|
||||
});
|
||||
},
|
||||
radioGroupChange(e) {
|
||||
|
||||
},
|
||||
radioChange(e) {
|
||||
if (this.anonymous == "YES") {
|
||||
this.anonymous = "NO";
|
||||
} else {
|
||||
this.anonymous = "YES";
|
||||
params.askValue = ''
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
if (store.state.isShowToast) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (store.state.isShowToast) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function radioGroupChange(_e: any) {}
|
||||
|
||||
function radioChange(_e: any) {
|
||||
if (params.anonymous == 'YES') {
|
||||
params.anonymous = 'NO'
|
||||
} else {
|
||||
params.anonymous = 'YES'
|
||||
}
|
||||
}
|
||||
|
||||
function goodsDetail() {}
|
||||
|
||||
onLoad((options: any) => {
|
||||
askGoods.value = options
|
||||
getGoodsData()
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.img {
|
||||
|
||||
@@ -82,130 +82,129 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as membersApi from "@/api/members.js";
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app'
|
||||
import * as membersApi from '@/api/members.js'
|
||||
import configs from '@/config/config'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
configs,
|
||||
status: "loadmore",
|
||||
userImage: configs.defaultUserPhoto,
|
||||
commentDetail: "",
|
||||
selectIndex: "0",
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
grade: "",
|
||||
import { noPassByName } from '@/utils/filters.js'
|
||||
|
||||
const status = ref('loadmore')
|
||||
const userImage = configs.defaultUserPhoto
|
||||
const commentDetail = ref<any>('')
|
||||
const selectIndex = ref(0)
|
||||
const params = reactive<any>({
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
grade: '',
|
||||
})
|
||||
const gradeList: Record<string, string> = {
|
||||
GOOD: '好评',
|
||||
MODERATE: '中评',
|
||||
WORSE: '差评',
|
||||
HAVEIMAGE: '有图',
|
||||
}
|
||||
const commDetail = ref<any[]>([])
|
||||
const opid = ref('')
|
||||
|
||||
function commentScore(item: any) {
|
||||
return item.descriptionScore || item.deliveryScore || 0
|
||||
}
|
||||
|
||||
function splitImg(val: any) {
|
||||
if (val && val.split(',')) {
|
||||
return val.split(',')
|
||||
} else if (val) {
|
||||
return val
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function getGoodsCommentsFun(id: string) {
|
||||
status.value = 'loading'
|
||||
membersApi.getGoodsComments(id, params).then((res) => {
|
||||
if (
|
||||
res.data.result.records == [] ||
|
||||
res.data.result.records == '' ||
|
||||
res.data.result.records == null
|
||||
) {
|
||||
status.value = 'noMore'
|
||||
return false
|
||||
}
|
||||
commDetail.value = commDetail.value.concat(res.data.result.records)
|
||||
status.value = 'loadmore'
|
||||
})
|
||||
}
|
||||
|
||||
function getGoodsCommentsNum(id: string) {
|
||||
membersApi.getGoodsCommentsCount(id).then((res) => {
|
||||
if (res.statusCode === 200) {
|
||||
commentDetail.value = res.data.result
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function select(index: number) {
|
||||
Object.assign(params, {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
selectIndex.value = index
|
||||
params.grade = ['', 'GOOD', 'MODERATE', 'WORSE', ''][selectIndex.value]
|
||||
if (selectIndex.value === 4) {
|
||||
params.haveImage = 1
|
||||
}
|
||||
commDetail.value = []
|
||||
if (selectIndex.value === 0) {
|
||||
Object.assign(params, {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
grade: '',
|
||||
})
|
||||
}
|
||||
getGoodsCommentsFun(opid.value)
|
||||
}
|
||||
|
||||
function preview(urls: string[], index: number) {
|
||||
uni.previewImage({
|
||||
current: index,
|
||||
urls: urls,
|
||||
longPressActions: {
|
||||
itemList: ['保存图片'],
|
||||
success: function () {
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
duration: 2000,
|
||||
icon: 'none',
|
||||
})
|
||||
},
|
||||
gradeList: {
|
||||
GOOD: "好评",
|
||||
MODERATE: "中评",
|
||||
WORSE: "差评",
|
||||
HAVEIMAGE: "有图",
|
||||
fail: function () {
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
duration: 2000,
|
||||
icon: 'none',
|
||||
})
|
||||
},
|
||||
commDetail: [],
|
||||
dataTotal: 0,
|
||||
opid: "",
|
||||
};
|
||||
},
|
||||
async onLoad(options) {
|
||||
this.getGoodsCommentsFun(options.id);
|
||||
this.getGoodsCommentsNum(options.id);
|
||||
this.opid = options.id;
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
this.params.pageNumber++;
|
||||
this.getGoodsCommentsFun(this.opid);
|
||||
},
|
||||
|
||||
methods: {
|
||||
commentScore(item) {
|
||||
return item.descriptionScore || item.deliveryScore || 0;
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
splitImg(val) {
|
||||
if (val && val.split(",")) {
|
||||
return val.split(",");
|
||||
} else if (val) {
|
||||
return val;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
function loadmore() {
|
||||
params.pageNumber++
|
||||
getGoodsCommentsFun(opid.value)
|
||||
}
|
||||
|
||||
getGoodsCommentsFun(id) {
|
||||
this.status = "loading";
|
||||
membersApi.getGoodsComments(id, this.params).then((res) => {
|
||||
if (
|
||||
res.data.result.records == [] ||
|
||||
res.data.result.records == "" ||
|
||||
res.data.result.records == null
|
||||
) {
|
||||
this.status = "noMore";
|
||||
return false;
|
||||
}
|
||||
this.commDetail = this.commDetail.concat(res.data.result.records);
|
||||
this.dataTotal = res.data.result.total;
|
||||
this.status = "loadmore";
|
||||
});
|
||||
},
|
||||
onLoad((options: any) => {
|
||||
getGoodsCommentsFun(options.id)
|
||||
getGoodsCommentsNum(options.id)
|
||||
opid.value = options.id
|
||||
})
|
||||
|
||||
getGoodsCommentsNum(id) {
|
||||
membersApi.getGoodsCommentsCount(id).then((res) => {
|
||||
if (res.statusCode === 200) {
|
||||
this.commentDetail = res.data.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
select(index) {
|
||||
this.params = {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
this.selectIndex = index;
|
||||
this.params.grade = ["", "GOOD", "MODERATE", "WORSE", ""][
|
||||
this.selectIndex
|
||||
];
|
||||
this.selectIndex === 4 ? (this.params.haveImage = 1) : true;
|
||||
this.commDetail = [];
|
||||
if (this.selectIndex === 0) {
|
||||
this.params = {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
grade: "",
|
||||
};
|
||||
}
|
||||
this.getGoodsCommentsFun(this.opid);
|
||||
},
|
||||
|
||||
preview(urls, index) {
|
||||
uni.previewImage({
|
||||
current: index,
|
||||
urls: urls,
|
||||
longPressActions: {
|
||||
itemList: ["保存图片"],
|
||||
success: function () {
|
||||
uni.showToast({
|
||||
title: "保存成功",
|
||||
duration: 2000,
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
fail: function () {
|
||||
uni.showToast({
|
||||
title: "保存失败",
|
||||
duration: 2000,
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
onReachBottom(() => {
|
||||
params.pageNumber++
|
||||
getGoodsCommentsFun(opid.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -3,89 +3,81 @@
|
||||
<chat></chat>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
onLoad (e) {
|
||||
// 腾讯云智服客服插件需在 manifest.json 的 mp-weixin.plugins 中注册后方可使用,
|
||||
// 未注册时 requirePlugin 会抛出 "has not registered any plugins",此处做容错处理。
|
||||
let chat
|
||||
try {
|
||||
chat = requirePlugin('myPlugin')
|
||||
} catch (err) {
|
||||
uni.showToast({
|
||||
title: '客服功能暂未配置',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}
|
||||
const params = JSON.parse((decodeURIComponent(e.params)))
|
||||
chat.init({
|
||||
sign: params.mpSign, //必传,公司渠道唯一标识,腾讯云智服后台系统创建「小程序插件」渠道后,在「渠道管理」获取
|
||||
token: params.token, //非必填
|
||||
uid: params.uuid, //用户唯一标识,如果没有则不填写,默认为空
|
||||
title: params.storageName, //非必填,如果未填写,默认获取配置标题
|
||||
isRMB: '', //商品是否显示人民币¥,默认显示,false不显示
|
||||
data: { //参数c1,c2,c3,c4,c5用于传递用户信息,参数d1,d2,d3,d4,d5,d6用于传递商品信息,默认为空
|
||||
c1: '',
|
||||
c2: '',
|
||||
c3: '',
|
||||
c4: '',
|
||||
c5: '',
|
||||
d1: params.goodsName, //商品描述
|
||||
d2: params.price, //价格
|
||||
d3: '', //原价格
|
||||
d4: params.goodsImg, //展示商品图片链接
|
||||
d5: '', //商品跳转链接
|
||||
d6: params.goodsId, //商品id
|
||||
data: ''//加密串,非必填
|
||||
},
|
||||
viewUrl(res){ //需要跳转外部链接,则需要配置一个web-view
|
||||
if (res) {
|
||||
wx.navigateTo({
|
||||
url: '/pages/webview/index?href=' + res
|
||||
})
|
||||
}
|
||||
},
|
||||
setTitle(res){ //设置标题
|
||||
if (res) {
|
||||
wx.setNavigationBarTitle({
|
||||
title: res
|
||||
})
|
||||
}
|
||||
},
|
||||
setBarColor(res) { //设置导航栏背景色
|
||||
if (res) {
|
||||
wx.setNavigationBarColor({
|
||||
frontColor: '#ffffff',
|
||||
backgroundColor: res
|
||||
})
|
||||
}
|
||||
},
|
||||
success(res){ //初始化成功时调用
|
||||
if (res.data == 'success') {
|
||||
console.log('success');
|
||||
}
|
||||
},
|
||||
fail(res){ //初始化失败时调用
|
||||
if (res.data == 'initError') {
|
||||
console.log(res.message);
|
||||
}
|
||||
},
|
||||
leave(res){ //离开会话页面
|
||||
if (res) {
|
||||
console.log(res);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
<script setup lang="ts">
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
|
||||
onLoad((e: any) => {
|
||||
// 腾讯云智服客服插件需在 manifest.json 的 mp-weixin.plugins 中注册后方可使用,
|
||||
// 未注册时 requirePlugin 会抛出 "has not registered any plugins",此处做容错处理。
|
||||
let chat
|
||||
try {
|
||||
chat = requirePlugin('myPlugin')
|
||||
} catch (err) {
|
||||
uni.showToast({
|
||||
title: '客服功能暂未配置',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}
|
||||
</script>
|
||||
const params = JSON.parse(decodeURIComponent(e.params))
|
||||
chat.init({
|
||||
sign: params.mpSign,
|
||||
token: params.token,
|
||||
uid: params.uuid,
|
||||
title: params.storageName,
|
||||
isRMB: '',
|
||||
data: {
|
||||
c1: '',
|
||||
c2: '',
|
||||
c3: '',
|
||||
c4: '',
|
||||
c5: '',
|
||||
d1: params.goodsName,
|
||||
d2: params.price,
|
||||
d3: '',
|
||||
d4: params.goodsImg,
|
||||
d5: '',
|
||||
d6: params.goodsId,
|
||||
data: ''
|
||||
},
|
||||
viewUrl(res: string){
|
||||
if (res) {
|
||||
wx.navigateTo({
|
||||
url: '/pages/webview/index?href=' + res
|
||||
})
|
||||
}
|
||||
},
|
||||
setTitle(res: string){
|
||||
if (res) {
|
||||
wx.setNavigationBarTitle({
|
||||
title: res
|
||||
})
|
||||
}
|
||||
},
|
||||
setBarColor(res: string) {
|
||||
if (res) {
|
||||
wx.setNavigationBarColor({
|
||||
frontColor: '#ffffff',
|
||||
backgroundColor: res
|
||||
})
|
||||
}
|
||||
},
|
||||
success(res: any){
|
||||
if (res.data == 'success') {
|
||||
console.log('success');
|
||||
}
|
||||
},
|
||||
fail(res: any){
|
||||
if (res.data == 'initError') {
|
||||
console.log(res.message);
|
||||
}
|
||||
},
|
||||
leave(res: any){
|
||||
if (res) {
|
||||
console.log(res);
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,41 +9,35 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getLicencePhoto } from "@/api/store.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
storeData: {},
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
this.getStoreLicencePhoto(options.id);
|
||||
},
|
||||
methods: {
|
||||
async getStoreLicencePhoto(id) {
|
||||
let res = await getLicencePhoto(id);
|
||||
if (res.data.success) {
|
||||
this.storeData = res.data.result;
|
||||
}
|
||||
},
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { getLicencePhoto } from '@/api/store.js'
|
||||
|
||||
/**
|
||||
* 点击图片放大或保存
|
||||
*/
|
||||
preview() {
|
||||
uni.previewImage({
|
||||
current: 0,
|
||||
urls: [this.storeData.licencePhoto],
|
||||
longPressActions: {
|
||||
itemList: ["保存图片"],
|
||||
success: function (data) {},
|
||||
fail: function (err) {},
|
||||
},
|
||||
});
|
||||
const storeData = ref<any>({})
|
||||
|
||||
async function getStoreLicencePhoto(id: string) {
|
||||
const res = await getLicencePhoto(id)
|
||||
if (res.data.success) {
|
||||
storeData.value = res.data.result
|
||||
}
|
||||
}
|
||||
|
||||
function preview() {
|
||||
uni.previewImage({
|
||||
current: 0,
|
||||
urls: [storeData.value.licencePhoto],
|
||||
longPressActions: {
|
||||
itemList: ['保存图片'],
|
||||
success: function () {},
|
||||
fail: function () {},
|
||||
},
|
||||
},
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
onLoad((options: any) => {
|
||||
getStoreLicencePhoto(options.id)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -53,4 +47,4 @@ export default {
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -64,88 +64,82 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Members from "@/api/members.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
lightColor: this.$lightColor,
|
||||
commDetail: {},
|
||||
readMoreInited: {},
|
||||
grade: "",
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
grade: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
props: {
|
||||
goodsDetail: {
|
||||
default: () => ({}),
|
||||
type: Object,
|
||||
},
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
import * as API_Members from '@/api/members.js'
|
||||
import { noPassByName } from '@/utils/filters.js'
|
||||
import { useStore } from '@/store'
|
||||
|
||||
const props = defineProps<{
|
||||
goodsDetail?: Record<string, any>
|
||||
}>()
|
||||
|
||||
const store = useStore()
|
||||
const lightColor = computed(() => store.getters.lightColor)
|
||||
const commDetail = ref<any>({})
|
||||
const readMoreInited = ref<Record<number, boolean>>({})
|
||||
const grade = ref('')
|
||||
const params = {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
grade: '',
|
||||
}
|
||||
const uReadMore = ref<any>()
|
||||
|
||||
watch(
|
||||
() => props.goodsDetail,
|
||||
(val) => {
|
||||
if (val && val.goodsId) {
|
||||
grade.value = val.grade
|
||||
getGoodsCommentsMethods()
|
||||
}
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
)
|
||||
|
||||
watch: {
|
||||
goodsDetail: {
|
||||
handler(val) {
|
||||
if (val && val.goodsId) {
|
||||
this.grade = val.grade;
|
||||
this.getGoodsCommentsMethods();
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
function commentImages(item: any) {
|
||||
const images = item.images || item.image
|
||||
if (!images) return []
|
||||
return typeof images === 'string' ? images.split(',').filter(Boolean) : images
|
||||
}
|
||||
|
||||
methods: {
|
||||
commentImages(item) {
|
||||
const images = item.images || item.image;
|
||||
if (!images) return [];
|
||||
return typeof images === "string" ? images.split(",").filter(Boolean) : images;
|
||||
},
|
||||
function initReadMore(index: number) {
|
||||
if (readMoreInited.value[index]) return
|
||||
readMoreInited.value[index] = true
|
||||
nextTick(() => {
|
||||
const refs = uReadMore.value
|
||||
const target = Array.isArray(refs) ? refs[index] : refs
|
||||
target?.init?.()
|
||||
})
|
||||
}
|
||||
|
||||
initReadMore(index) {
|
||||
if (this.readMoreInited[index]) return;
|
||||
this.readMoreInited[index] = true;
|
||||
this.$nextTick(() => {
|
||||
const refs = this.$refs.uReadMore;
|
||||
const target = Array.isArray(refs) ? refs[index] : refs;
|
||||
target?.init?.();
|
||||
});
|
||||
},
|
||||
function getGoodsCommentsMethods() {
|
||||
if (!props.goodsDetail?.goodsId) return
|
||||
API_Members.getGoodsComments(props.goodsDetail.goodsId, params).then((res) => {
|
||||
readMoreInited.value = {}
|
||||
commDetail.value = res.data.result || {}
|
||||
nextTick(() => {
|
||||
const records = commDetail.value.records || []
|
||||
records.slice(0, 2).forEach((_: any, index: number) => {
|
||||
setTimeout(() => initReadMore(index), 50 * (index + 1))
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getGoodsCommentsMethods() {
|
||||
if (!this.goodsDetail.goodsId) return;
|
||||
API_Members.getGoodsComments(this.goodsDetail.goodsId, this.params).then((res) => {
|
||||
this.readMoreInited = {};
|
||||
this.commDetail = res.data.result || {};
|
||||
this.$nextTick(() => {
|
||||
const records = this.commDetail.records || [];
|
||||
records.slice(0, 2).forEach((_, index) => {
|
||||
setTimeout(() => this.initReadMore(index), 50 * (index + 1));
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
function toComment(id: string | number, gradeVal: string | number) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/comment?id=${id}&grade=${gradeVal}`,
|
||||
})
|
||||
}
|
||||
|
||||
toComment(id, grade) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/comment?id=${id}&grade=${grade}`,
|
||||
});
|
||||
},
|
||||
|
||||
previewImg(urls, index) {
|
||||
uni.previewImage({
|
||||
urls,
|
||||
indicator: "number",
|
||||
current: index,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
function previewImg(urls: string[], index: number) {
|
||||
uni.previewImage({
|
||||
urls,
|
||||
indicator: 'number',
|
||||
current: index,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -2,12 +2,9 @@
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -39,30 +39,32 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getGoodsMessage } from "@/api/goods";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
goodsDetail: "",
|
||||
style: {
|
||||
img:"display:block;width:100%"
|
||||
}
|
||||
};
|
||||
},
|
||||
props: ["res", "goodsId", "goodsParams"],
|
||||
computed: {
|
||||
hasDetailContent() {
|
||||
return !!(this.res?.mobileIntro || (this.goodsParams && this.goodsParams.length));
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
let res = await getGoodsMessage(this.goodsId);
|
||||
if (res.data.success) {
|
||||
this.goodsDetail = res.data.result;
|
||||
}
|
||||
},
|
||||
};
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { getGoodsMessage } from '@/api/goods'
|
||||
|
||||
const props = defineProps<{
|
||||
res?: any
|
||||
goodsId?: string | number
|
||||
goodsParams?: any[]
|
||||
}>()
|
||||
|
||||
const goodsDetail = ref('')
|
||||
const style = {
|
||||
img: 'display:block;width:100%',
|
||||
}
|
||||
|
||||
const hasDetailContent = computed(() => {
|
||||
return !!(props.res?.mobileIntro || (props.goodsParams && props.goodsParams.length))
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
if (!props.goodsId) return
|
||||
const res = await getGoodsMessage(props.goodsId)
|
||||
if (res.data.success) {
|
||||
goodsDetail.value = res.data.result
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -5,14 +5,12 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import goodsList from '@/components/m-goods-list/list.vue'
|
||||
export default {
|
||||
props: ["res"],
|
||||
components:{goodsList},
|
||||
methods: {
|
||||
}
|
||||
};
|
||||
|
||||
defineProps<{
|
||||
res?: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -27,30 +27,33 @@
|
||||
<view class="swiper-dots">{{ current }}/{{ video ? res.length + 1 : res.length }}</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
current: 1,
|
||||
html: ""
|
||||
};
|
||||
},
|
||||
props: ["res", 'video'],
|
||||
watch: {
|
||||
video(val) {
|
||||
this.html = '<video muted="muted" ref="videoPlay" style="width:100%; height:100%;" src=' + val + ' page-gesture show-mute-btn autoplay webkit-playsinline="" playsinline="" ></video>'
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
res?: string[]
|
||||
video?: string
|
||||
}>()
|
||||
|
||||
const current = ref(1)
|
||||
const html = ref('')
|
||||
|
||||
watch(
|
||||
() => props.video,
|
||||
(val) => {
|
||||
if (val) {
|
||||
html.value =
|
||||
'<video muted="muted" ref="videoPlay" style="width:100%; height:100%;" src=' +
|
||||
val +
|
||||
' page-gesture show-mute-btn autoplay webkit-playsinline="" playsinline="" ></video>'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 轮播图对应的dot
|
||||
swiperChange(e) {
|
||||
this.current = e.detail.current + 1;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.video)
|
||||
}
|
||||
};
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
function swiperChange(e: any) {
|
||||
current.value = e.detail.current + 1
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.carousel {
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
|
||||
.showBack {
|
||||
|
||||
margin-top: calc( var(--status-bar-height) + 20px ) !important;
|
||||
|
||||
}
|
||||
margin-top: calc(var(--status-bar-height) + 20px) !important;
|
||||
}
|
||||
|
||||
/* 商品详情底栏改为 flex 布局后,避免全局 mp-iphonex-bottom 把高度撑乱 */
|
||||
.page-bottom.mp-iphonex-bottom {
|
||||
height: auto !important;
|
||||
min-height: 100rpx;
|
||||
box-sizing: border-box;
|
||||
padding-top: 10rpx;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
@@ -26,83 +26,81 @@
|
||||
<m-city :provinceData="cityList" headTitle="区域选择" ref="cityPicker" pickerSize="4"></m-city>
|
||||
</u-popup>
|
||||
</template>
|
||||
<script>
|
||||
import setup from "@/components/m-buy/popup.js";
|
||||
/************请求存储***************/
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import setup from '@/components/m-buy/popup.js'
|
||||
import * as API_Address from '@/api/address.js'
|
||||
import { clearStrComma, isLogin } from '@/utils/filters.js'
|
||||
|
||||
import * as API_Address from "@/api/address.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
checked: "",
|
||||
setup,
|
||||
addressDetail: "",
|
||||
cityList: [
|
||||
{
|
||||
id: "",
|
||||
localName: "请选择",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
const props = defineProps<{
|
||||
goodsId?: string | number
|
||||
addressFlag?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
closeAddress: [val: boolean]
|
||||
deliveryData: [val: any]
|
||||
}>()
|
||||
|
||||
const checked = ref<any>('')
|
||||
const addressDetail = ref<any>('')
|
||||
const cityList = ref([
|
||||
{
|
||||
id: '',
|
||||
localName: '请选择',
|
||||
children: [],
|
||||
},
|
||||
props: ["goodsId", "addressFlag"],
|
||||
])
|
||||
|
||||
mounted() {
|
||||
if (this.isLogin("auth")) {
|
||||
this.getShippingAddress();
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: "/pages/passport/login",
|
||||
});
|
||||
}
|
||||
},
|
||||
onMounted(() => {
|
||||
if (isLogin('auth')) {
|
||||
getShippingAddress()
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: '/pages/passport/login',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
methods: {
|
||||
/**关闭地址 */
|
||||
closeAddress() {
|
||||
this.$emit("closeAddress", false);
|
||||
this.$emit("deliveryData", this.checked);
|
||||
},
|
||||
function closeAddress() {
|
||||
emit('closeAddress', false)
|
||||
emit('deliveryData', checked.value)
|
||||
}
|
||||
|
||||
getpicker() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/mine/address/add",
|
||||
});
|
||||
this.closeAddress();
|
||||
},
|
||||
function getpicker() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/mine/address/add',
|
||||
})
|
||||
closeAddress()
|
||||
}
|
||||
|
||||
/**获取地址 */
|
||||
getShippingAddress() {
|
||||
if (this.isLogin("auth")) {
|
||||
API_Address.getAddressList(1, 50).then((res) => {
|
||||
if (res.data.success) {
|
||||
this.addressDetail = res.data.result.records;
|
||||
let addr = res.data.result.records.filter((item) => {
|
||||
return item.isDefault == 1;
|
||||
});
|
||||
function getShippingAddress() {
|
||||
if (isLogin('auth')) {
|
||||
API_Address.getAddressList(1, 50).then((res) => {
|
||||
if (res.data.success) {
|
||||
addressDetail.value = res.data.result.records
|
||||
const addr = res.data.result.records.filter((item: any) => {
|
||||
return item.isDefault == 1
|
||||
})
|
||||
|
||||
if (addr[0]) {
|
||||
this.checked = addr[0];
|
||||
this.$emit("deliveryData", this.checked);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (addr[0]) {
|
||||
checked.value = addr[0]
|
||||
emit('deliveryData', checked.value)
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**点击地址返回父级商品状态 */
|
||||
clickAddress(val) {
|
||||
this.checked = val;
|
||||
function clickAddress(val: any) {
|
||||
checked.value = val
|
||||
|
||||
this.addressDetail.forEach((item) => {
|
||||
item.isDefault = false;
|
||||
});
|
||||
val.isDefault = !val.isDefault;
|
||||
this.$emit("deliveryData", this.checked);
|
||||
},
|
||||
},
|
||||
};
|
||||
addressDetail.value.forEach((item: any) => {
|
||||
item.isDefault = false
|
||||
})
|
||||
val.isDefault = !val.isDefault
|
||||
emit('deliveryData', checked.value)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.light {
|
||||
@@ -165,4 +163,4 @@ export default {
|
||||
line-height: 90rpx;
|
||||
font-size: 34rpx;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -23,66 +23,57 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Promotions from "@/api/promotions";
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import * as API_Promotions from '@/api/promotions'
|
||||
import configs from '@/config/config'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
configs,
|
||||
userImage:configs.defaultUserPhoto,
|
||||
import { noPassByName } from '@/utils/filters.js'
|
||||
import { useStore } from '@/store'
|
||||
|
||||
joinBtnStyle: {
|
||||
background: this.$lightColor,
|
||||
color: "#fff",
|
||||
},
|
||||
/** 待成团订单 */
|
||||
assembleOrder: "",
|
||||
const props = defineProps<{
|
||||
res?: any
|
||||
}>()
|
||||
|
||||
/** 查看更多待成团订单 */
|
||||
assembleOrderAll: "",
|
||||
};
|
||||
},
|
||||
props: ["res"],
|
||||
const emit = defineEmits<{
|
||||
'to-assemble-buy-now': [order: any]
|
||||
}>()
|
||||
|
||||
watch: {
|
||||
res: {
|
||||
handler() {
|
||||
if (this.res && this.res.length != 0) {
|
||||
Object.keys(this.res).forEach((item) => {
|
||||
let key = item.split("-");
|
||||
if (key && key[0] == "PINTUAN") {
|
||||
this.getAssembleInfo(item);
|
||||
}
|
||||
});
|
||||
const store = useStore()
|
||||
const userImage = configs.defaultUserPhoto
|
||||
const assembleOrder = ref<any[]>([])
|
||||
|
||||
const joinBtnStyle = computed(() => ({
|
||||
background: store.getters.lightColor,
|
||||
color: '#fff',
|
||||
}))
|
||||
|
||||
watch(
|
||||
() => props.res,
|
||||
(res) => {
|
||||
if (res && res.length != 0) {
|
||||
Object.keys(res).forEach((item) => {
|
||||
const key = item.split('-')
|
||||
if (key && key[0] == 'PINTUAN') {
|
||||
getAssembleInfo(item)
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
|
||||
// assembleOrder(val) {
|
||||
// this.$emit("assembleOrder", val);
|
||||
// },
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
mounted() {},
|
||||
methods: {
|
||||
// 获取此商品所有待成团的订单
|
||||
getAssembleInfo(val) {
|
||||
let id = this.res[val].id;
|
||||
API_Promotions.getPromotionGroupMember(id).then((res) => {
|
||||
if (res.data.success) {
|
||||
console.warn(res.data.result);
|
||||
this.assembleOrder = res.data.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
buy(order) {
|
||||
this.$emit("to-assemble-buy-now", order);
|
||||
},
|
||||
},
|
||||
};
|
||||
function getAssembleInfo(val: string) {
|
||||
const id = props.res[val].id
|
||||
API_Promotions.getPromotionGroupMember(id).then((res) => {
|
||||
if (res.data.success) {
|
||||
assembleOrder.value = res.data.result
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function buy(order: any) {
|
||||
emit('to-assemble-buy-now', order)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -106,119 +106,118 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
countdownData: {},
|
||||
countdownTimer: null,
|
||||
};
|
||||
<script setup lang="ts">
|
||||
import { computed, onUnmounted, ref, watch } from 'vue'
|
||||
import { goodsFormatPrice } from '@/utils/filters.js'
|
||||
|
||||
const props = defineProps<{
|
||||
res?: any
|
||||
detail?: any
|
||||
}>()
|
||||
|
||||
const countdownData = ref<Record<number, any>>({})
|
||||
let countdownTimer: ReturnType<typeof setInterval> | null = null
|
||||
|
||||
const promotionList = computed(() => {
|
||||
if (!props.res || typeof props.res !== 'object') return []
|
||||
return Object.keys(props.res).map((key) => ({
|
||||
...(props.res[key] || {}),
|
||||
__key: key.split('-')[0],
|
||||
}))
|
||||
})
|
||||
|
||||
watch(
|
||||
promotionList,
|
||||
(list) => {
|
||||
refreshCountdown(list)
|
||||
startCountdownTimer()
|
||||
},
|
||||
props: {
|
||||
res: {
|
||||
type: null,
|
||||
default: {},
|
||||
},
|
||||
detail: {
|
||||
type: null,
|
||||
default: {},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
promotionList() {
|
||||
if (!this.res || typeof this.res !== "object") return [];
|
||||
return Object.keys(this.res).map((key) => ({
|
||||
...(this.res[key] || {}),
|
||||
__key: key.split("-")[0],
|
||||
}));
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
promotionList: {
|
||||
handler(list) {
|
||||
this.refreshCountdown(list);
|
||||
this.startCountdownTimer();
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.clearCountdownTimer();
|
||||
},
|
||||
methods: {
|
||||
clearCountdownTimer() {
|
||||
if (this.countdownTimer) {
|
||||
clearInterval(this.countdownTimer);
|
||||
this.countdownTimer = null;
|
||||
}
|
||||
},
|
||||
startCountdownTimer() {
|
||||
this.clearCountdownTimer();
|
||||
this.countdownTimer = setInterval(() => {
|
||||
this.refreshCountdown(this.promotionList);
|
||||
}, 1000);
|
||||
},
|
||||
refreshCountdown(list = this.promotionList) {
|
||||
const next = {};
|
||||
list.forEach((promotion, index) => {
|
||||
next[index] = this.msToTimeData(this.getCountDownMs(promotion));
|
||||
});
|
||||
this.countdownData = next;
|
||||
},
|
||||
padTime(val) {
|
||||
return String(val ?? 0).padStart(2, "0");
|
||||
},
|
||||
countdownDisplayHours(index) {
|
||||
const data = this.countdownData[index];
|
||||
if (!data) return 0;
|
||||
return data.days * 24 + data.hours;
|
||||
},
|
||||
msToTimeData(ms) {
|
||||
const DAY = 86400000;
|
||||
const HOUR = 3600000;
|
||||
const MINUTE = 60000;
|
||||
const SECOND = 1000;
|
||||
const time = Math.max(Number(ms) || 0, 0);
|
||||
return {
|
||||
days: Math.floor(time / DAY),
|
||||
hours: Math.floor((time % DAY) / HOUR),
|
||||
minutes: Math.floor((time % HOUR) / MINUTE),
|
||||
seconds: Math.floor((time % MINUTE) / SECOND),
|
||||
};
|
||||
},
|
||||
parsePromotionTime(val) {
|
||||
if (val == null || val === "") return 0;
|
||||
if (typeof val === "number" && !Number.isNaN(val)) {
|
||||
return val < 1e12 ? val * 1000 : val;
|
||||
}
|
||||
const text = String(val).trim();
|
||||
if (/^\d+$/.test(text)) {
|
||||
const num = Number(text);
|
||||
return num < 1e12 ? num * 1000 : num;
|
||||
}
|
||||
const parsed = Date.parse(text.replace(/-/g, "/"));
|
||||
return Number.isNaN(parsed) ? 0 : parsed;
|
||||
},
|
||||
getCountDownMs(promotion) {
|
||||
if (!promotion || !promotion.endTime) return 0;
|
||||
const now = Date.now();
|
||||
const startMs = this.parsePromotionTime(promotion.startTime || promotion.start_time);
|
||||
const endMs = this.parsePromotionTime(promotion.endTime);
|
||||
if (!endMs) return 0;
|
||||
const target = startMs && now < startMs ? startMs : endMs;
|
||||
const remain = target - now;
|
||||
return remain > 0 ? remain : 0;
|
||||
},
|
||||
getIsTimer(val) {
|
||||
const now = Date.now();
|
||||
const startMs = this.parsePromotionTime(val.startTime || val.start_time);
|
||||
if (startMs && now < startMs) {
|
||||
return "距离活动开始";
|
||||
}
|
||||
return "距离活动结束";
|
||||
},
|
||||
},
|
||||
};
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
onUnmounted(() => {
|
||||
clearCountdownTimer()
|
||||
})
|
||||
|
||||
function clearCountdownTimer() {
|
||||
if (countdownTimer) {
|
||||
clearInterval(countdownTimer)
|
||||
countdownTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
function startCountdownTimer() {
|
||||
clearCountdownTimer()
|
||||
countdownTimer = setInterval(() => {
|
||||
refreshCountdown(promotionList.value)
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
function refreshCountdown(list = promotionList.value) {
|
||||
const next: Record<number, any> = {}
|
||||
list.forEach((promotion, index) => {
|
||||
next[index] = msToTimeData(getCountDownMs(promotion))
|
||||
})
|
||||
countdownData.value = next
|
||||
}
|
||||
|
||||
function padTime(val: number | undefined) {
|
||||
return String(val ?? 0).padStart(2, '0')
|
||||
}
|
||||
|
||||
function countdownDisplayHours(index: number) {
|
||||
const data = countdownData.value[index]
|
||||
if (!data) return 0
|
||||
return data.days * 24 + data.hours
|
||||
}
|
||||
|
||||
function msToTimeData(ms: number) {
|
||||
const DAY = 86400000
|
||||
const HOUR = 3600000
|
||||
const MINUTE = 60000
|
||||
const SECOND = 1000
|
||||
const time = Math.max(Number(ms) || 0, 0)
|
||||
return {
|
||||
days: Math.floor(time / DAY),
|
||||
hours: Math.floor((time % DAY) / HOUR),
|
||||
minutes: Math.floor((time % HOUR) / MINUTE),
|
||||
seconds: Math.floor((time % MINUTE) / SECOND),
|
||||
}
|
||||
}
|
||||
|
||||
function parsePromotionTime(val: any) {
|
||||
if (val == null || val === '') return 0
|
||||
if (typeof val === 'number' && !Number.isNaN(val)) {
|
||||
return val < 1e12 ? val * 1000 : val
|
||||
}
|
||||
const text = String(val).trim()
|
||||
if (/^\d+$/.test(text)) {
|
||||
const num = Number(text)
|
||||
return num < 1e12 ? num * 1000 : num
|
||||
}
|
||||
const parsed = Date.parse(text.replace(/-/g, '/'))
|
||||
return Number.isNaN(parsed) ? 0 : parsed
|
||||
}
|
||||
|
||||
function getCountDownMs(promotion: any) {
|
||||
if (!promotion || !promotion.endTime) return 0
|
||||
const now = Date.now()
|
||||
const startMs = parsePromotionTime(promotion.startTime || promotion.start_time)
|
||||
const endMs = parsePromotionTime(promotion.endTime)
|
||||
if (!endMs) return 0
|
||||
const target = startMs && now < startMs ? startMs : endMs
|
||||
const remain = target - now
|
||||
return remain > 0 ? remain : 0
|
||||
}
|
||||
|
||||
function getIsTimer(val: any) {
|
||||
const now = Date.now()
|
||||
const startMs = parsePromotionTime(val.startTime || val.start_time)
|
||||
if (startMs && now < startMs) {
|
||||
return '距离活动开始'
|
||||
}
|
||||
return '距离活动结束'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -1,79 +1,95 @@
|
||||
<template>
|
||||
<view class="wrapper">
|
||||
<div class="coupon-empty" v-if="!res">暂无优惠券</div>
|
||||
<view class="coupon-List" v-for="(item, index) in couponRes" :key="index">
|
||||
<view class="coupon-empty" v-if="!couponRes.length">暂无优惠券</view>
|
||||
<view class="coupon-List" v-for="(item, index) in couponRes" :key="item.id || index">
|
||||
<view class="coupon-item">
|
||||
<view class="top">
|
||||
<div class="price">
|
||||
<span class="price-num" v-if="item.couponType == 'DISCOUNT'">{{ item.couponDiscount }}折</span>
|
||||
<span class="price-num" v-if="item.couponType == 'PRICE'">¥{{unitPrice(item.price) }}</span>
|
||||
</div>
|
||||
<view class="text">
|
||||
<div class="coupon-List-title">
|
||||
<view v-if="item.scopeType">
|
||||
<span v-if="item.scopeType == 'ALL' && item.storeId == '0'">全平台</span>
|
||||
<span v-if="item.scopeType == 'PORTION_GOODS_CATEGORY'">仅限品类</span>
|
||||
<view v-else>{{
|
||||
item.storeName == "platform" ? "全平台" : item.storeName + "店铺"
|
||||
}}使用</view>
|
||||
</view>
|
||||
</div>
|
||||
<div>满{{unitPrice(item.consumeThreshold) }}可用</div>
|
||||
<view class="price">
|
||||
<text class="price-num" v-if="item.couponType == 'DISCOUNT'">{{ item.couponDiscount }}折</text>
|
||||
<text class="price-num" v-else-if="item.couponType == 'PRICE'">¥{{ unitPrice(item.price) }}</text>
|
||||
</view>
|
||||
<view class="lingqu-btn" @click="getCoupon(item, index)">
|
||||
<div class="lingqu-text" :class="yhqFlag[index] ? 'cur' : ''">
|
||||
{{ yhqFlag[index] ? "已领取或领完" : "立即领取" }}
|
||||
</div>
|
||||
<view class="text">
|
||||
<view class="coupon-List-title">
|
||||
<text v-if="item.scopeType == 'ALL' && item.storeId == '0'">全平台</text>
|
||||
<text v-else-if="item.scopeType == 'PORTION_GOODS_CATEGORY'">仅限品类</text>
|
||||
<text v-else-if="item.scopeType == 'PORTION_GOODS'">部分商品</text>
|
||||
<text v-else>{{ item.storeName == 'platform' ? '全平台' : item.storeName + '店铺' }}使用</text>
|
||||
</view>
|
||||
<text>满{{ unitPrice(item.consumeThreshold) }}可用</text>
|
||||
</view>
|
||||
<view class="lingqu-btn" @tap="getCoupon(item, index)">
|
||||
<view class="lingqu-text" :class="{ cur: yhqFlag[index] }">
|
||||
{{ yhqFlag[index] ? '已领取或领完' : '立即领取' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="line"></view>
|
||||
<view class="time">{{ item.startTime /unixToDate(1000) }} - {{ item.endTime /unixToDate(1000) }}</view>
|
||||
<view class="time">{{ formatCouponTime(item.startTime) }} - {{ formatCouponTime(item.endTime) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
yhqFlag: [], //获取优惠券判断是否点击
|
||||
couponRes: [],
|
||||
};
|
||||
},
|
||||
props: {
|
||||
res: {
|
||||
type: null,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
res: {
|
||||
handler() {
|
||||
if (this.res && this.res.length != 0) {
|
||||
Object.keys(this.res).forEach((item) => {
|
||||
let key = item.split("-")[0];
|
||||
if (key === "COUPON") {
|
||||
this.couponRes.push(this?.res[item]);
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { unitPrice, unixToDate } from '@/utils/filters.js'
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 提交优惠券
|
||||
getCoupon(item, index) {
|
||||
this.yhqFlag[index] = true;
|
||||
this.$emit("getCoupon", item);
|
||||
},
|
||||
},
|
||||
};
|
||||
const props = defineProps<{
|
||||
res?: any
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
getCoupon: [item: any]
|
||||
}>()
|
||||
|
||||
const yhqFlag = ref<boolean[]>([])
|
||||
const couponRes = ref<any[]>([])
|
||||
|
||||
function formatCouponTime(val: any) {
|
||||
if (val == null || val === '') return ''
|
||||
const text = String(val).trim()
|
||||
if (!text) return ''
|
||||
if (text.includes('-') || text.includes('/')) {
|
||||
return text.length > 10 ? text.slice(0, 16) : text
|
||||
}
|
||||
const num = Number(text)
|
||||
if (!Number.isFinite(num)) return text
|
||||
const seconds = num < 1e12 ? num : Math.floor(num / 1000)
|
||||
return unixToDate(seconds, 'yyyy-MM-dd')
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.res,
|
||||
(res) => {
|
||||
const list: any[] = []
|
||||
if (res && typeof res === 'object') {
|
||||
Object.keys(res).forEach((item) => {
|
||||
if (item.split('-')[0] === 'COUPON') {
|
||||
list.push(res[item])
|
||||
}
|
||||
})
|
||||
}
|
||||
couponRes.value = list
|
||||
yhqFlag.value = list.map(() => false)
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
function getCoupon(item: any, index: number) {
|
||||
if (yhqFlag.value[index]) return
|
||||
yhqFlag.value[index] = true
|
||||
yhqFlag.value = [...yhqFlag.value]
|
||||
emit('getCoupon', item)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.coupon-empty {
|
||||
color: #999;
|
||||
font-size: 26rpx;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.coupon-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -85,10 +101,12 @@
|
||||
.coupon-List {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 230rpx;
|
||||
min-height: 230rpx;
|
||||
background: #e9ebfb;
|
||||
margin: 30rpx 0;
|
||||
padding: 10rpx 30rpx;
|
||||
border-radius: 12rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.line {
|
||||
height: 1px;
|
||||
@@ -119,15 +137,17 @@
|
||||
.time {
|
||||
flex: 1;
|
||||
font-size: 24rpx;
|
||||
align-items: center;
|
||||
color: #666;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12rpx 0 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.top {
|
||||
height: 140rpx;
|
||||
min-height: 140rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.price {
|
||||
width: 33%;
|
||||
@@ -135,48 +155,56 @@
|
||||
color: #6772e5;
|
||||
font-size: 40rpx;
|
||||
display: flex;
|
||||
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
.price-num {
|
||||
font-size: 50rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 33%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
font-size: 26rpx;
|
||||
color: 333;
|
||||
margin-left: 40rpx;
|
||||
color: #333;
|
||||
margin-left: 20rpx;
|
||||
min-width: 0;
|
||||
|
||||
.coupon-List-title {
|
||||
font-size: 30rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
}
|
||||
|
||||
.lingqu-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 40rpx;
|
||||
flex-shrink: 0;
|
||||
margin-left: 16rpx;
|
||||
|
||||
.lingqu-text {
|
||||
width: 140rpx;
|
||||
height: 40rpx;
|
||||
min-width: 140rpx;
|
||||
height: 56rpx;
|
||||
padding: 0 16rpx;
|
||||
text-align: center;
|
||||
line-height: 40rpx;
|
||||
line-height: 56rpx;
|
||||
color: #fff;
|
||||
background: #6772e5;
|
||||
border-radius: 5px;
|
||||
font-size: 26rpx;
|
||||
border-radius: 28rpx;
|
||||
font-size: 24rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.cur {
|
||||
background: none;
|
||||
transform: rotate(45deg) translate(10rpx, -46rpx);
|
||||
background: #ccc;
|
||||
color: #fff;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,140 +1,134 @@
|
||||
<template>
|
||||
<view class="wrapper" v-if="res">
|
||||
<view v-for="(prom, index) in Object.keys(res)" :key="index">
|
||||
<view>
|
||||
<view v-if="prom.split('-')[0] == 'FULL_DISCOUNT'">
|
||||
<div class="res_prom_item" v-if="res[prom].fullMinus">
|
||||
<u-tag text="满减" type="error"></u-tag>
|
||||
<!-- TODO 后续将优化为可点击的商品以及优惠券显示明细 -->
|
||||
<span class="pro-text"
|
||||
>满{{ res[prom].fullMoney }}元 立减现金
|
||||
<span class="price">{{ res[prom].fullMinus }}元</span>
|
||||
<span v-if="res[prom].couponFlag"> 赠送<span>优惠券</span></span>
|
||||
<span v-if="res[prom].pointFlag"> 赠送{{ res[prom].point }}积分</span>
|
||||
<span v-if="res[prom].giftFlag"> 赠送商品</span>
|
||||
<span v-if="res[prom].freeFreightFlag">赠送包邮服务</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="res_prom_item" v-if="res[prom].fullRate && res[prom].fullRateFlag">
|
||||
<u-tag text="打折" type="error"></u-tag>
|
||||
<span class="pro-text"
|
||||
>满{{ res[prom].fullMoney }}元,立享<span class="price"
|
||||
>{{ res[prom].fullRate }}折</span
|
||||
>优惠</span
|
||||
>
|
||||
</div>
|
||||
<view v-for="prom in promotionKeys" :key="prom">
|
||||
<view v-if="getPromType(prom) == 'FULL_DISCOUNT'">
|
||||
<view class="res_prom_item" v-if="res[prom].fullMinus">
|
||||
<view class="deg_tag">满减</view>
|
||||
<text class="pro-text">
|
||||
满{{ res[prom].fullMoney }}元 立减现金
|
||||
<text class="price">{{ res[prom].fullMinus }}元</text>
|
||||
<text v-if="res[prom].couponFlag"> 赠送优惠券</text>
|
||||
<text v-if="res[prom].pointFlag"> 赠送{{ res[prom].point }}积分</text>
|
||||
<text v-if="res[prom].giftFlag"> 赠送商品</text>
|
||||
<text v-if="res[prom].freeFreightFlag"> 赠送包邮服务</text>
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view v-if="prom.split('-')[0] == 'PINTUAN'">
|
||||
<div class="res_prom_item" v-if="res[prom].requiredNum">
|
||||
<u-tag text="拼团" type="error"></u-tag>
|
||||
<span class="pro-text"
|
||||
>{{ res[prom].requiredNum }}人拼团 限购<span class="price"
|
||||
>{{ res[prom].limitNum }}件</span
|
||||
></span
|
||||
>
|
||||
</div>
|
||||
<view class="res_prom_item" v-if="res[prom].fullRate && res[prom].fullRateFlag">
|
||||
<view class="deg_tag">打折</view>
|
||||
<text class="pro-text">
|
||||
满{{ res[prom].fullMoney }}元,立享
|
||||
<text class="price">{{ res[prom].fullRate }}折</text>
|
||||
优惠
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="prom.split('-')[0] == 'SECKILL'">
|
||||
<div class="res_prom_item">
|
||||
<u-tag text="限时抢购" type="error"></u-tag>
|
||||
<span class="pro-text">限时抢购</span>
|
||||
</div>
|
||||
<view v-if="getPromType(prom) == 'PINTUAN'">
|
||||
<view class="res_prom_item" v-if="res[prom].requiredNum">
|
||||
<view class="deg_tag">拼团</view>
|
||||
<text class="pro-text">
|
||||
{{ res[prom].requiredNum }}人拼团 限购
|
||||
<text class="price">{{ res[prom].limitNum }}件</text>
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="prom.split('-')[0] == 'POINTS_GOODS'">
|
||||
<div class="res_prom_item">
|
||||
<u-tag text="积分活动" type="error"></u-tag>
|
||||
<span class="pro-text">当前商品参与积分活动。<span @click="handClickToJoinPromotion(prom)" class="href">点击此处参与活动</span></span>
|
||||
</div>
|
||||
<view v-if="getPromType(prom) == 'SECKILL'">
|
||||
<view class="res_prom_item">
|
||||
<view class="deg_tag">限时抢购</view>
|
||||
<text class="pro-text">限时抢购</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="prom.split('-')[0] == 'KANJIA'">
|
||||
<div class="res_prom_item">
|
||||
<u-tag text="砍价活动" type="error"></u-tag>
|
||||
<span class="pro-text">当前商品参与砍价活动。<span @click="handClickToJoinPromotion(prom)" class="href">点击此处参与活动</span></span>
|
||||
</div>
|
||||
<view v-if="getPromType(prom) == 'POINTS_GOODS'">
|
||||
<view class="res_prom_item">
|
||||
<view class="deg_tag">积分活动</view>
|
||||
<text class="pro-text">
|
||||
当前商品参与积分活动。
|
||||
<text @tap="handClickToJoinPromotion(prom)" class="href">点击此处参与活动</text>
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="getPromType(prom) == 'KANJIA'">
|
||||
<view class="res_prom_item">
|
||||
<view class="deg_tag">砍价活动</view>
|
||||
<text class="pro-text">
|
||||
当前商品参与砍价活动。
|
||||
<text @tap="handClickToJoinPromotion(prom)" class="href">点击此处参与活动</text>
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="!res">暂无促销活动</view>
|
||||
<view v-if="!promotionKeys.length">暂无促销活动</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
watch: {
|
||||
res: {
|
||||
handler() {
|
||||
if (this.res && this.res.length != 0) {
|
||||
Object.keys(this.res).forEach((item) => {
|
||||
if (item != "COUPON") {
|
||||
let key = item.split("-")[0];
|
||||
this.res[item]._key = key;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
props: {
|
||||
// 父组件传递回来的数据
|
||||
res: {
|
||||
type: null,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
// 跳转到参与商品活动的详情列表中
|
||||
handClickToJoinPromotion(val){
|
||||
|
||||
const promotion = {
|
||||
"POINTS_GOODS": `/pages/promotion/point/detail?id=${this.res[val].id}`,
|
||||
"KANJIA": `/pages/promotion/bargain/detail?id=${this.res[val].id}`,
|
||||
}
|
||||
const props = defineProps<{
|
||||
res?: any
|
||||
}>()
|
||||
|
||||
uni.navigateTo({
|
||||
url:promotion[val.split('-')[0]]
|
||||
})
|
||||
const promotionKeys = computed(() => {
|
||||
if (!props.res || typeof props.res !== 'object') return []
|
||||
return Object.keys(props.res).filter((key) => getPromType(key) !== 'COUPON')
|
||||
})
|
||||
|
||||
}
|
||||
},
|
||||
};
|
||||
function getPromType(key: string) {
|
||||
return key.split('-')[0]
|
||||
}
|
||||
|
||||
function handClickToJoinPromotion(val: string) {
|
||||
const type = getPromType(val)
|
||||
const promotionMap: Record<string, string> = {
|
||||
POINTS_GOODS: `/pages/promotion/point/detail?id=${props.res[val].id}`,
|
||||
KANJIA: `/pages/promotion/bargain/detail?id=${props.res[val].id}`,
|
||||
}
|
||||
const url = promotionMap[type]
|
||||
if (url) {
|
||||
uni.navigateTo({ url })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.deg_tag {
|
||||
flex-shrink: 0;
|
||||
color: $price-color;
|
||||
padding: 4rpx 12rpx;
|
||||
border: 2rpx solid $price-color;
|
||||
border-radius: 6rpx;
|
||||
font-size: 22rpx;
|
||||
line-height: 1.4;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pro-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 26rpx;
|
||||
font-family: PingFang SC, PingFang SC-Regular;
|
||||
font-weight: 400;
|
||||
text-align: left;
|
||||
line-height: 1.6;
|
||||
color: #333333;
|
||||
margin-left: 20rpx;
|
||||
word-spacing: 15rpx;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
::v-deep .u-mode-light-error {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.res_prom_item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16rpx;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.price_image {
|
||||
display: block;
|
||||
.price {
|
||||
color: $price-color;
|
||||
}
|
||||
.href{
|
||||
|
||||
.href {
|
||||
color: $main-color;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -50,51 +50,45 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="this.res != null && Object.keys(res).length == 0">暂无促销信息</view>
|
||||
<view v-if="res != null && Object.keys(res).length == 0">暂无促销信息</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import promotion from './promotion_type';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
promotion,
|
||||
couponList: ''
|
||||
};
|
||||
},
|
||||
props: {
|
||||
// 父组件传递回来的数据
|
||||
res: {
|
||||
type: null,
|
||||
default: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
res: {
|
||||
handler() {
|
||||
if (this.res && this.res.length != 0 && this.res != null) {
|
||||
Object.keys(this.res).forEach(item => {
|
||||
let key = item.split('-')[0];
|
||||
this.res[item].__key = key;
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import promotion from './promotion_type'
|
||||
|
||||
if (item.split('-')[0] == 'COUPON') {
|
||||
this.couponList = 'COUPON';
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
// 此方法条用父级方法
|
||||
shutMask(val) {
|
||||
this.$emit('shutMasks', val);
|
||||
}
|
||||
}
|
||||
};
|
||||
const props = defineProps<{
|
||||
res?: any
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
shutMasks: [val: number]
|
||||
}>()
|
||||
|
||||
const couponList = ref('')
|
||||
|
||||
watch(
|
||||
() => props.res,
|
||||
(res) => {
|
||||
couponList.value = ''
|
||||
if (res && res.length != 0 && res != null) {
|
||||
Object.keys(res).forEach((item) => {
|
||||
const key = item.split('-')[0]
|
||||
res[item].__key = key
|
||||
|
||||
if (item.split('-')[0] == 'COUPON') {
|
||||
couponList.value = 'COUPON'
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
function shutMask(val: number) {
|
||||
emit('shutMasks', val)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -39,33 +39,31 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
props: ["res", "goodsDetail", "storeDetail"],
|
||||
computed: {
|
||||
recommendGoods() {
|
||||
return (this.res || []).filter((item) => item && item.thumbnail && item.goodsName);
|
||||
},
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
// 点击商品
|
||||
clickGoods(val) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/goods?id=${val.id}&goodsId=${val.goodsId}`,
|
||||
});
|
||||
},
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { goodsFormatPrice } from '@/utils/filters.js'
|
||||
|
||||
tostorePage(val) {
|
||||
uni.navigateTo({
|
||||
url: "../product/shopPage?id=" + val.storeId,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
const props = defineProps<{
|
||||
res?: any[]
|
||||
goodsDetail?: any
|
||||
storeDetail?: any
|
||||
}>()
|
||||
|
||||
const recommendGoods = computed(() => {
|
||||
return (props.res || []).filter((item) => item && item.thumbnail && item.goodsName)
|
||||
})
|
||||
|
||||
function clickGoods(val: any) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/goods?id=${val.id}&goodsId=${val.goodsId}`,
|
||||
})
|
||||
}
|
||||
|
||||
function tostorePage(val: any) {
|
||||
uni.navigateTo({
|
||||
url: '../product/shopPage?id=' + val.storeId,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -30,7 +30,15 @@ page {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.cuxiao{
|
||||
padding:16rpx 32rpx;
|
||||
padding:16rpx 32rpx 32rpx;
|
||||
}
|
||||
|
||||
.con-cuxiao {
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
&.coupons {
|
||||
padding-top: 8rpx;
|
||||
}
|
||||
}
|
||||
.detail-btn {
|
||||
display: flex;
|
||||
@@ -171,6 +179,7 @@ page {
|
||||
.scroll-hide {
|
||||
opacity: 0;
|
||||
transition: all 0.5s;
|
||||
pointer-events: none;
|
||||
}
|
||||
.cur {
|
||||
color: $main-color;
|
||||
@@ -188,52 +197,88 @@ page {
|
||||
|
||||
.header-only-back {
|
||||
background: transparent;
|
||||
z-index: 9;
|
||||
}
|
||||
.header,
|
||||
.header-only-back {
|
||||
padding-left: 10rpx;
|
||||
position: fixed;
|
||||
top: var(--status-bar-height);
|
||||
width: 100%;
|
||||
z-index: 8;
|
||||
height: 90rpx;
|
||||
font-size: 30rpx;
|
||||
transition: all 0.5s;
|
||||
|
||||
:deep(.u-navbar__content__left) {
|
||||
width: auto !important;
|
||||
min-width: 150rpx;
|
||||
padding: 0 8rpx 0 0 !important;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
:deep(.u-navbar__content) {
|
||||
padding: 0 150rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
::v-deep .u-navbar {
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
.nav-item {
|
||||
flex: 2;
|
||||
flex: 0 0 auto;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20rpx;
|
||||
font-size: 28rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.header {
|
||||
color: #666666;
|
||||
background-color: #fff;
|
||||
|
||||
:deep(.u-navbar__content) {
|
||||
background-color: #fff !important;
|
||||
}
|
||||
|
||||
.tab-bar {
|
||||
width: 100%;
|
||||
color: #666;
|
||||
font-weight: 400;
|
||||
view {
|
||||
padding: 0 3px;
|
||||
}
|
||||
}
|
||||
&.bg-none {
|
||||
background: transparent;
|
||||
|
||||
:deep(.u-navbar__content) {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.headerRow--tabs {
|
||||
justify-content: center;
|
||||
gap: 8rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.headerList {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-action {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 56rpx;
|
||||
min-height: 56rpx;
|
||||
padding: 0 6rpx;
|
||||
}
|
||||
|
||||
.page-bottom {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
z-index: 9;
|
||||
background: #fff;
|
||||
height: 100rpx;
|
||||
min-height: 100rpx;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
border-top: 2rpx solid #f2f2f2;
|
||||
@@ -267,15 +312,24 @@ page {
|
||||
}
|
||||
|
||||
.main-page {
|
||||
height: calc(100% - var(--status-bar-height));
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.icon-back {
|
||||
padding-right: 10rpx;
|
||||
|
||||
.index {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.icon-back,
|
||||
.icon-list {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-action + .nav-action {
|
||||
border-left: 2rpx solid rgb(194, 194, 194);
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
.backs,
|
||||
.bg-back {
|
||||
@@ -284,8 +338,9 @@ page {
|
||||
border-radius: 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
justify-content: space-around;
|
||||
padding: 8rpx 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bg-back {
|
||||
background: rgba($color: #fff, $alpha: 0.8);
|
||||
@@ -324,6 +379,12 @@ page {
|
||||
}
|
||||
|
||||
.product-container {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.header-line {
|
||||
height: 1px;
|
||||
background: #f2f2f2;
|
||||
@@ -340,16 +401,16 @@ page {
|
||||
}
|
||||
|
||||
.scroll-page {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.scroll-inner {
|
||||
min-height: 100%;
|
||||
box-sizing: border-box;
|
||||
background: #f0f0f0;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
padding-bottom: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,82 +36,62 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
#TODO 后续将和后端补充从此处
|
||||
<div class="flex store-goods">
|
||||
<div class="store-goods-item" v-for="i in 3" :key="i">
|
||||
<div>
|
||||
<u-image src="https://picsum.photos/id/341/200/200" border-radius="20" width="215rpx" height="215rpx">
|
||||
</u-image>
|
||||
</div>
|
||||
<div class="price">
|
||||
<span>
|
||||
¥
|
||||
<span class=" goods-price-bigshow">{{ formatPrice(16)[0] }}</span>
|
||||
.{{ formatPrice(16)[1] }}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class="wes">test</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
<u-empty style="margin-top:20%;" text="暂无店铺信息" v-else></u-empty>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getStoreList } from "@/api/store";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
keyword: "",
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
storeName: "",
|
||||
},
|
||||
storeList: [], // 店铺列表
|
||||
};
|
||||
},
|
||||
onReachBottom() {
|
||||
this.params.pageNumber++;
|
||||
this.init();
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
fail: () => {
|
||||
uni.switchTab({ url: "/pages/tabbar/home/index" });
|
||||
},
|
||||
});
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { onReachBottom } from '@dcloudio/uni-app'
|
||||
import { getStoreList } from '@/api/store'
|
||||
import { unitPrice } from '@/utils/filters.js'
|
||||
|
||||
const params = reactive({
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
storeName: '',
|
||||
})
|
||||
const storeList = ref<any[]>([])
|
||||
|
||||
function back() {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
fail: () => {
|
||||
uni.switchTab({ url: '/pages/tabbar/home/index' })
|
||||
},
|
||||
handleClickStore(val){
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/shopPage?id=${val.id}`
|
||||
});
|
||||
},
|
||||
search() {
|
||||
this.storeList = [];
|
||||
this.init();
|
||||
},
|
||||
|
||||
async init() {
|
||||
let res = await getStoreList(this.params);
|
||||
if (res.data.success) {
|
||||
let data = res.data.result;
|
||||
|
||||
this.storeList.push(...data.records);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
function handleClickStore(val: any) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/shopPage?id=${val.id}`,
|
||||
})
|
||||
}
|
||||
|
||||
function search() {
|
||||
storeList.value = []
|
||||
params.pageNumber = 1
|
||||
init()
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const res = await getStoreList(params)
|
||||
if (res.data.success) {
|
||||
const data = res.data.result
|
||||
storeList.value.push(...data.records)
|
||||
}
|
||||
}
|
||||
|
||||
onReachBottom(() => {
|
||||
params.pageNumber++
|
||||
init()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -179,4 +159,4 @@ export default {
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
<view v-if="!enablePageData" class="search-wrap" @click.stop>
|
||||
<u-search
|
||||
v-model="keyword"
|
||||
@search="search"
|
||||
@click="search"
|
||||
@search="goToSearch"
|
||||
@click="goToSearch"
|
||||
placeholder="请输入搜索"
|
||||
:show-action="false"
|
||||
></u-search>
|
||||
@@ -134,9 +134,13 @@
|
||||
</div>
|
||||
|
||||
<!-- 楼层装修模式 -->
|
||||
<div v-if="enablePageData">
|
||||
<view v-if="enablePageData" class="floor-page">
|
||||
<!-- uni 中不能使用 vue component 所以用if判断每个组件 -->
|
||||
<div v-for="(item, index) in pageData.list || []" :key="index">
|
||||
<view
|
||||
v-for="(item, index) in pageData.list || []"
|
||||
:key="`${item.type}-${index}`"
|
||||
class="floor-block"
|
||||
>
|
||||
<!-- 搜索栏,如果在楼层装修顶部则会自动浮动,否则不浮动 -->
|
||||
<u-navbar
|
||||
class="navbar shop-navbar"
|
||||
@@ -183,396 +187,352 @@
|
||||
<menuLayout v-if="item.type == 'menu'" :res="item.options" />
|
||||
<flexOne v-if="item.type == 'flexOne'" :res="item.options" />
|
||||
|
||||
<goods v-if="item.type == 'goods'" :res="item.options" />
|
||||
<GoodsFloor v-if="item.type == 'goods'" :res="item.options" />
|
||||
|
||||
<group v-if="item.type == 'group'" :res="item.options" />
|
||||
<!-- <joinGroup v-if="item.type == 'joinGroup'" :res="item.options" /> -->
|
||||
<!-- <integral v-if="item.type == 'integral'" :res="item.options" /> -->
|
||||
<!-- <spike v-if="item.type == 'spike'" :res="item.options" /> -->
|
||||
</div>
|
||||
</div>
|
||||
</view>
|
||||
</view>
|
||||
<u-no-network></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_goods from "@/pages/tabbar/home/template/tpl_goods"; //商品分类以及分类中的商品
|
||||
import goodsTemplate from '@/components/m-goods-list/list'
|
||||
import { getStoreBaseInfo, getStoreCategory } from "@/api/store.js";
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch, onMounted } from 'vue'
|
||||
import {
|
||||
onLoad,
|
||||
onPageScroll,
|
||||
onPullDownRefresh,
|
||||
onReachBottom,
|
||||
} from '@dcloudio/uni-app'
|
||||
import { useStore } from '@/store'
|
||||
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 GoodsFloor from '@/pages/tabbar/home/template/tpl_goods.vue'
|
||||
import goodsTemplate from '@/components/m-goods-list/list.vue'
|
||||
import { getStoreBaseInfo, getStoreCategory } from '@/api/store.js'
|
||||
import {
|
||||
receiveCoupons,
|
||||
deleteStoreCollection,
|
||||
collectionStore,
|
||||
getStoreIsCollect,
|
||||
} from "@/api/members.js";
|
||||
import config from "@/config/config";
|
||||
} from '@/api/members.js'
|
||||
import config from '@/config/config'
|
||||
import { getGoodsList } from '@/api/goods.js'
|
||||
import { getAllCoupons } from '@/api/promotions.js'
|
||||
import { getFloorStoreData } from '@/api/home'
|
||||
import {
|
||||
isLogin,
|
||||
navigateToLogin,
|
||||
talkIm,
|
||||
unitPrice,
|
||||
} from '@/utils/filters.js'
|
||||
import storage from '@/utils/storage.js'
|
||||
|
||||
import { getGoodsList } from "@/api/goods.js";
|
||||
import { getAllCoupons } from "@/api/promotions.js";
|
||||
import { getFloorStoreData } from "@/api/home"; //获取楼层装修接口
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
config,
|
||||
pageData: { list: [] }, //楼层页面数据
|
||||
enablePageData: false, //是否显示楼层装修内容
|
||||
basePageData: false, //基础店铺信息
|
||||
scrollTop: 0,
|
||||
mainColor: this.$mainColor, //主色调
|
||||
current: 0, //初始tabs的索引
|
||||
tabs: [
|
||||
{
|
||||
name: "全部商品",
|
||||
},
|
||||
{
|
||||
name: "分类查看",
|
||||
},
|
||||
], // 标签
|
||||
storeId: "",
|
||||
keyword: "",
|
||||
storeInfo: {}, //店铺详情
|
||||
isCollection: false, //是否关注
|
||||
goodsList: [], //推荐货物
|
||||
couponList: [], //优惠券列表
|
||||
categoryList: [],
|
||||
couponParams: {
|
||||
pageNumber: 1,
|
||||
pageSize: 50,
|
||||
storeId: "",
|
||||
},
|
||||
goodsParams: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
storeId: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
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,
|
||||
goodsTemplate
|
||||
// spike: tpl_spike,
|
||||
// joinGroup: tpl_join_group,
|
||||
// integral: tpl_integral,
|
||||
},
|
||||
watch: {
|
||||
current(val) {
|
||||
val == 0
|
||||
? () => {
|
||||
this.goodsList = [];
|
||||
this.getGoodsData();
|
||||
}
|
||||
: this.getCategoryData();
|
||||
},
|
||||
},
|
||||
const store = useStore()
|
||||
const mainColor = computed(() => store.getters.mainColor)
|
||||
|
||||
computed: {
|
||||
floorHasTopSearch() {
|
||||
const list = this.pageData && this.pageData.list;
|
||||
if (!list || !list.length) return false;
|
||||
return list.some((item, index) => item.type === "search" && index !== 1);
|
||||
},
|
||||
},
|
||||
const pageData = ref<{ list: any[] }>({ list: [] })
|
||||
const enablePageData = ref(false)
|
||||
const basePageData = ref(false)
|
||||
const scrollTop = ref(0)
|
||||
const current = ref(0)
|
||||
const tabs = [
|
||||
{ name: '全部商品' },
|
||||
{ name: '分类查看' },
|
||||
]
|
||||
const storeId = ref('')
|
||||
const keyword = ref('')
|
||||
const storeInfo = ref<any>({})
|
||||
const isCollection = ref(false)
|
||||
const goodsList = ref<any[]>([])
|
||||
const couponList = ref<any[]>([])
|
||||
const categoryList = ref<any[]>([])
|
||||
const couponParams = reactive({
|
||||
pageNumber: 1,
|
||||
pageSize: 50,
|
||||
storeId: '',
|
||||
})
|
||||
const goodsParams = reactive({
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
storeId: '',
|
||||
})
|
||||
|
||||
/**
|
||||
* 加载
|
||||
*/
|
||||
async onLoad(options) {
|
||||
this.storeId = options.id;
|
||||
console.log(this.storeId,'this.storeId')
|
||||
const floorHasTopSearch = computed(() => {
|
||||
const list = pageData.value && pageData.value.list
|
||||
if (!list || !list.length) return false
|
||||
return list.some((item, index) => item.type === 'search' && index !== 1)
|
||||
})
|
||||
|
||||
this.goodsParams.storeId = options.id;
|
||||
this.couponParams.storeId = options.id;
|
||||
},
|
||||
onPageScroll(e) {
|
||||
this.scrollTop = e.scrollTop;
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.init();
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序默认分享
|
||||
uni.showShareMenu({
|
||||
withShareTicket: true,
|
||||
});
|
||||
// #endif
|
||||
this.init();
|
||||
},
|
||||
watch(current, (val) => {
|
||||
if (val == 0) {
|
||||
goodsList.value = []
|
||||
getGoodsData()
|
||||
} else {
|
||||
getCategoryData()
|
||||
}
|
||||
})
|
||||
|
||||
// 下拉加载
|
||||
onReachBottom() {
|
||||
this.goodsParams.pageNumber++;
|
||||
this.getGoodsData();
|
||||
},
|
||||
function talk() {
|
||||
talkIm(storeInfo.value.storeId)
|
||||
}
|
||||
|
||||
methods: {
|
||||
talk(){
|
||||
this.talkIm(this.storeInfo.storeId)
|
||||
},
|
||||
back() {
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length > 1) {
|
||||
uni.navigateBack({ delta: 1 });
|
||||
} else {
|
||||
uni.switchTab({ url: "/pages/tabbar/home/index" });
|
||||
function back() {
|
||||
const pages = getCurrentPages()
|
||||
if (pages.length > 1) {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
} else {
|
||||
uni.switchTab({ url: '/pages/tabbar/home/index' })
|
||||
}
|
||||
}
|
||||
|
||||
function isPageDataSuccess(payload: any) {
|
||||
return payload?.success === true || payload?.code === 200
|
||||
}
|
||||
|
||||
function shouldUseFloorPage(pageShow: unknown) {
|
||||
return pageShow === '1' || pageShow === 1 || pageShow === true
|
||||
}
|
||||
|
||||
function initPageData() {
|
||||
getFloorStoreData({
|
||||
pageType: 'STORE',
|
||||
num: storeId.value,
|
||||
})
|
||||
.then((res) => {
|
||||
const payload = res?.data ?? res
|
||||
const result = payload?.result
|
||||
const pageDataStr = result?.pageData
|
||||
if (!isPageDataSuccess(payload) || !pageDataStr) {
|
||||
fallbackToBasePage()
|
||||
return
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 实例化首页数据楼层
|
||||
*/
|
||||
initPageData() {
|
||||
this.pageData = { list: [] };
|
||||
getFloorStoreData({
|
||||
pageType: "STORE",
|
||||
num: this.storeId,
|
||||
})
|
||||
.then((res) => {
|
||||
const result = res.data && res.data.result;
|
||||
const pageDataStr = result && result.pageData;
|
||||
if (res.data.success && pageDataStr) {
|
||||
try {
|
||||
const parsed = JSON.parse(pageDataStr);
|
||||
this.pageData =
|
||||
parsed && Array.isArray(parsed.list)
|
||||
? parsed
|
||||
: { list: [] };
|
||||
this.enablePageData = true;
|
||||
} catch (e) {
|
||||
this.fallbackToBasePage();
|
||||
}
|
||||
} else {
|
||||
this.fallbackToBasePage();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.fallbackToBasePage();
|
||||
});
|
||||
},
|
||||
fallbackToBasePage() {
|
||||
this.enablePageData = false;
|
||||
this.basePageData = true;
|
||||
this.pageData = { list: [] };
|
||||
this.getGoodsData();
|
||||
this.getCategoryData();
|
||||
},
|
||||
getStoreLicencePhoto() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/licencePhoto?id=${this.storeId}`,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 初始化信息
|
||||
*/
|
||||
init() {
|
||||
this.goodsList = [];
|
||||
this.categoryList = [];
|
||||
this.couponList = [];
|
||||
this.goodsParams.pageNumber = 1;
|
||||
if (this.isLogin("auth")) {
|
||||
this.enableGoodsIsCollect();
|
||||
}
|
||||
// 店铺信息
|
||||
this.getStoreData();
|
||||
},
|
||||
/**
|
||||
* 联系客服
|
||||
*/
|
||||
linkKefuDetail() {
|
||||
// 客服
|
||||
// #ifdef MP-WEIXIN
|
||||
|
||||
const params = {
|
||||
// originalPrice: this.goodsDetail.original || this.goodsDetail.price,
|
||||
uuid: storage.getUuid(),
|
||||
token: storage.getAccessToken(),
|
||||
sign: this.storeInfo.yzfSign,
|
||||
mpSign: this.storeInfo.yzfMpSign,
|
||||
};
|
||||
uni.navigateTo({
|
||||
url:
|
||||
"/pages/mine/im/index"
|
||||
});
|
||||
// uni.navigateTo({
|
||||
// url:
|
||||
// "/pages/product/customerservice/index?params=" +
|
||||
// encodeURIComponent(JSON.stringify(params)),
|
||||
// });
|
||||
// // #endif
|
||||
// // #ifndef MP-WEIXIN
|
||||
// const sign = this.storeInfo.yzfSign;
|
||||
// uni.navigateTo({
|
||||
// url:
|
||||
// "/pages/tabbar/home/web-view?src=https://yzf.qq.com/xv/web/static/chat/index.html?sign=" +
|
||||
// sign,
|
||||
// });
|
||||
// #endif
|
||||
},
|
||||
|
||||
/** 获取店铺分类 */
|
||||
async getCategoryData() {
|
||||
let res = await getStoreCategory(this.storeId);
|
||||
if (res.data.success) {
|
||||
this.categoryList = res.data.result;
|
||||
}
|
||||
},
|
||||
/**是否收藏店铺 */
|
||||
async enableGoodsIsCollect() {
|
||||
let res = await getStoreIsCollect("STORE", this.storeId);
|
||||
if (res.data.success) {
|
||||
this.isCollection = res.data.result;
|
||||
}
|
||||
},
|
||||
|
||||
/**商品分类中商品集合 */
|
||||
getCategoryGoodsList(val) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/shopPageGoods?title=${val.labelName}&id=${val.id}&storeId=${this.storeId}`,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
*/
|
||||
search() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/navigation/search/searchPage?storeId=${this.storeId}&keyword=${this.keyword}`,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 店铺信息
|
||||
*/
|
||||
async getStoreData() {
|
||||
let res = await getStoreBaseInfo(this.storeId);
|
||||
if (res.data.success) {
|
||||
this.storeInfo = res.data.result;
|
||||
// 优惠券信息
|
||||
this.getCouponsData();
|
||||
if(res.data.result.pageShow == '1'){
|
||||
// 开启了楼层装修店铺
|
||||
this.initPageData();
|
||||
try {
|
||||
const parsed = JSON.parse(pageDataStr)
|
||||
pageData.value =
|
||||
parsed && Array.isArray(parsed.list) ? parsed : { list: [] }
|
||||
enablePageData.value = pageData.value.list.length > 0
|
||||
if (!enablePageData.value) {
|
||||
fallbackToBasePage()
|
||||
}
|
||||
else{
|
||||
// 商品信息
|
||||
this.getGoodsData();
|
||||
// 店铺分类
|
||||
this.getCategoryData();
|
||||
|
||||
this.basePageData = true;
|
||||
}
|
||||
} else {
|
||||
uni.reLaunch({
|
||||
url: "/",
|
||||
});
|
||||
} catch (e) {
|
||||
fallbackToBasePage()
|
||||
}
|
||||
},
|
||||
})
|
||||
.catch(() => {
|
||||
fallbackToBasePage()
|
||||
})
|
||||
}
|
||||
|
||||
/** 加载商品 */
|
||||
async getGoodsData() {
|
||||
let res = await getGoodsList(this.goodsParams);
|
||||
function fallbackToBasePage() {
|
||||
enablePageData.value = false
|
||||
basePageData.value = true
|
||||
pageData.value = { list: [] }
|
||||
getGoodsData()
|
||||
getCategoryData()
|
||||
}
|
||||
|
||||
function getStoreLicencePhoto() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/licencePhoto?id=${storeId.value}`,
|
||||
})
|
||||
}
|
||||
|
||||
function init() {
|
||||
goodsList.value = []
|
||||
categoryList.value = []
|
||||
couponList.value = []
|
||||
goodsParams.pageNumber = 1
|
||||
if (isLogin('auth')) {
|
||||
enableGoodsIsCollect()
|
||||
}
|
||||
getStoreData()
|
||||
}
|
||||
|
||||
function linkKefuDetail() {
|
||||
// 客服
|
||||
// #ifdef MP-WEIXIN
|
||||
|
||||
const params = {
|
||||
// originalPrice: goodsDetail.original || goodsDetail.price,
|
||||
uuid: storage.getUuid(),
|
||||
token: storage.getAccessToken(),
|
||||
sign: storeInfo.value.yzfSign,
|
||||
mpSign: storeInfo.value.yzfMpSign,
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: '/pages/mine/im/index',
|
||||
})
|
||||
// uni.navigateTo({
|
||||
// url:
|
||||
// "/pages/product/customerservice/index?params=" +
|
||||
// encodeURIComponent(JSON.stringify(params)),
|
||||
// });
|
||||
// // #endif
|
||||
// // #ifndef MP-WEIXIN
|
||||
// const sign = storeInfo.yzfSign;
|
||||
// uni.navigateTo({
|
||||
// url:
|
||||
// "/pages/tabbar/home/web-view?src=https://yzf.qq.com/xv/web/static/chat/index.html?sign=" +
|
||||
// sign,
|
||||
// });
|
||||
// #endif
|
||||
}
|
||||
|
||||
async function getCategoryData() {
|
||||
const res = await getStoreCategory(storeId.value)
|
||||
if (res.data.success) {
|
||||
categoryList.value = res.data.result
|
||||
}
|
||||
}
|
||||
|
||||
async function enableGoodsIsCollect() {
|
||||
const res = await getStoreIsCollect('STORE', storeId.value)
|
||||
if (res.data.success) {
|
||||
isCollection.value = res.data.result
|
||||
}
|
||||
}
|
||||
|
||||
function getCategoryGoodsList(val: any) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/shopPageGoods?title=${val.labelName}&id=${val.id}&storeId=${storeId.value}`,
|
||||
})
|
||||
}
|
||||
|
||||
function goToSearch() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/navigation/search/searchPage?storeId=${storeId.value}&keyword=${keyword.value}`,
|
||||
})
|
||||
}
|
||||
|
||||
async function getStoreData() {
|
||||
const res = await getStoreBaseInfo(storeId.value)
|
||||
if (res.data.success) {
|
||||
storeInfo.value = res.data.result
|
||||
getCouponsData()
|
||||
if (shouldUseFloorPage(res.data.result.pageShow)) {
|
||||
initPageData()
|
||||
} else {
|
||||
getGoodsData()
|
||||
getCategoryData()
|
||||
basePageData.value = true
|
||||
}
|
||||
} else {
|
||||
uni.reLaunch({
|
||||
url: '/',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function getGoodsData() {
|
||||
const res = await getGoodsList(goodsParams)
|
||||
if (res.data.success) {
|
||||
goodsList.value.push(...res.data.result.records)
|
||||
}
|
||||
}
|
||||
|
||||
async function getCouponsData() {
|
||||
couponParams.storeId = storeId.value
|
||||
const res = await getAllCoupons(couponParams)
|
||||
if (res.data.success) {
|
||||
couponList.value.push(...res.data.result.records)
|
||||
}
|
||||
}
|
||||
|
||||
function whetherCollection() {
|
||||
if (isCollection.value) {
|
||||
deleteStoreCollection(storeId.value).then((res) => {
|
||||
if (res.data.success) {
|
||||
this.goodsList.push(...res.data.result.records);
|
||||
}
|
||||
},
|
||||
|
||||
/** 加载优惠券 */
|
||||
async getCouponsData() {
|
||||
this.couponParams.storeId = this.storeId;
|
||||
let res = await getAllCoupons(this.couponParams);
|
||||
if (res.data.success) {
|
||||
this.couponList.push(...res.data.result.records);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 是否收藏
|
||||
*/
|
||||
whetherCollection() {
|
||||
if (this.isCollection) {
|
||||
deleteStoreCollection(this.storeId).then((res) => {
|
||||
if (res.data.success) {
|
||||
this.isCollection = false;
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
duration: 3000,
|
||||
title: "取消关注成功!",
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
collectionStore(this.storeId).then((res) => {
|
||||
if (res.data.success) {
|
||||
this.isCollection = true;
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
duration: 3000,
|
||||
title: "关注成功!",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 领取
|
||||
*/
|
||||
getCoupon(item) {
|
||||
if (!this.isLogin("auth")) {
|
||||
isCollection.value = false
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
icon: 'none',
|
||||
duration: 3000,
|
||||
title: "请先登录!",
|
||||
});
|
||||
|
||||
this.navigateToLogin("redirectTo");
|
||||
return false;
|
||||
title: '取消关注成功!',
|
||||
})
|
||||
}
|
||||
receiveCoupons(item.id).then((res) => {
|
||||
if (res.data.success) {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
duration: 3000,
|
||||
title: "领取成功!",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
})
|
||||
} else {
|
||||
collectionStore(storeId.value).then((res) => {
|
||||
if (res.data.success) {
|
||||
isCollection.value = true
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
duration: 3000,
|
||||
title: '关注成功!',
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getCoupon(item: any) {
|
||||
if (!isLogin('auth')) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
duration: 3000,
|
||||
title: '请先登录!',
|
||||
})
|
||||
|
||||
navigateToLogin('redirectTo')
|
||||
return false
|
||||
}
|
||||
receiveCoupons(item.id).then((res) => {
|
||||
if (res.data.success) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
duration: 3000,
|
||||
title: '领取成功!',
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onLoad((options: any) => {
|
||||
storeId.value = options.id
|
||||
console.log(storeId.value, 'this.storeId')
|
||||
|
||||
goodsParams.storeId = options.id
|
||||
couponParams.storeId = options.id
|
||||
})
|
||||
|
||||
onPageScroll((e) => {
|
||||
scrollTop.value = e.scrollTop
|
||||
})
|
||||
|
||||
onPullDownRefresh(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
onReachBottom(() => {
|
||||
goodsParams.pageNumber++
|
||||
getGoodsData()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.showShareMenu({
|
||||
withShareTicket: true,
|
||||
})
|
||||
// #endif
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -903,4 +863,14 @@ export default {
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.floor-page {
|
||||
width: 100%;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.floor-block {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -16,54 +16,47 @@
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getGoodsList
|
||||
} from "@/api/goods.js";
|
||||
import goodsTemplate from '@/components/m-goods-list/list'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
title: "",
|
||||
routerVal: "",
|
||||
goodsList: [],
|
||||
params: {
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
keyword: "",
|
||||
storeCatId: "",
|
||||
storeId: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
components: {
|
||||
goodsTemplate
|
||||
},
|
||||
onLoad(options) {
|
||||
this.routerVal = options;
|
||||
this.params.storeId = options.storeId;
|
||||
this.params.storeCatId = options.id;
|
||||
this.title = options.title;
|
||||
},
|
||||
onShow() {
|
||||
this.goodsList = []
|
||||
this.params.pageNumber = 1;
|
||||
this.getGoodsData();
|
||||
},
|
||||
onReachBottom() {
|
||||
this.params.pageNumber++;
|
||||
this.getGoodsData();
|
||||
},
|
||||
methods: {
|
||||
async getGoodsData() {
|
||||
// #TODO
|
||||
let goodsList = await getGoodsList(this.params);
|
||||
if (goodsList.data.success) {
|
||||
this.goodsList.push(...goodsList.data.result.records);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { onLoad, onReachBottom, onShow } from '@dcloudio/uni-app'
|
||||
import { getGoodsList } from '@/api/goods.js'
|
||||
import goodsTemplate from '@/components/m-goods-list/list'
|
||||
|
||||
const title = ref('')
|
||||
const routerVal = ref<any>('')
|
||||
const goodsList = ref<any[]>([])
|
||||
const params = reactive({
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
keyword: '',
|
||||
storeCatId: '',
|
||||
storeId: '',
|
||||
})
|
||||
|
||||
async function getGoodsData() {
|
||||
const res = await getGoodsList(params)
|
||||
if (res.data.success) {
|
||||
goodsList.value.push(...res.data.result.records)
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options: any) => {
|
||||
routerVal.value = options
|
||||
params.storeId = options.storeId
|
||||
params.storeCatId = options.id
|
||||
title.value = options.title
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
goodsList.value = []
|
||||
params.pageNumber = 1
|
||||
getGoodsData()
|
||||
})
|
||||
|
||||
onReachBottom(() => {
|
||||
params.pageNumber++
|
||||
getGoodsData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Reference in New Issue
Block a user