添加加盟店
BIN
public/img/addr_r.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/img/cate_all.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
public/img/clock.png
Normal file
|
After Width: | Height: | Size: 762 B |
BIN
public/img/icon_canpay.png
Normal file
|
After Width: | Height: | Size: 845 B |
BIN
public/img/icon_disc.png
Normal file
|
After Width: | Height: | Size: 946 B |
BIN
public/img/icon_phone.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/img/mallDetail-i6.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/img/map.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
public/img/shopinfo-top.jpg
Normal file
|
After Width: | Height: | Size: 252 KiB |
@ -14,7 +14,8 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
wechatShareInfo: {}
|
||||
wechatShareInfo: {},
|
||||
geo: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -48,6 +49,9 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
this.$geo.getWebGeo().then(pos => {
|
||||
this.geo = pos
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
updateTitle(title) {
|
||||
|
||||
@ -40,11 +40,11 @@
|
||||
<van-icon class="r" name="arrow"></van-icon>
|
||||
</div>
|
||||
|
||||
<!-- <div @click="navigateAndClose('Social')">
|
||||
<div @click="navigateAndClose('Social')">
|
||||
<img src="/img/my_u7.png" alt="">
|
||||
<span>合作店</span>
|
||||
<span>加盟店</span>
|
||||
<van-icon class="r" name="arrow"></van-icon>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button @click="loginout">
|
||||
|
||||
@ -31,7 +31,7 @@ const routes = [
|
||||
name: 'Social',
|
||||
parentName: 'Index',
|
||||
component: () => import('./views/Tabbars/Social.vue'),
|
||||
meta: { title: '合作店', cache: true }
|
||||
meta: { title: '加盟店', cache: true }
|
||||
},
|
||||
{
|
||||
path: '/My',
|
||||
@ -54,10 +54,15 @@ const routes = [
|
||||
{
|
||||
path: '/PointMall',
|
||||
name: 'PointMall',
|
||||
parentName: 'Index',
|
||||
component: () => import('./views/User/PointMall.vue'),
|
||||
meta: { title: '积分区', cache: true }
|
||||
},
|
||||
{
|
||||
path: '/ShopInfo',
|
||||
name: 'ShopInfo',
|
||||
component: () => import('./views/User/ShopInfo.vue'),
|
||||
meta: { title: '商家详情', cache: true }
|
||||
},
|
||||
{
|
||||
path: '/Login',
|
||||
name: 'Login',
|
||||
@ -235,7 +240,7 @@ const routes = [
|
||||
path: '/Category',
|
||||
name: 'Category',
|
||||
component: () => import('./views/Goods/Category.vue'),
|
||||
meta: { title: '全部分类', noLogin: true, cache: true }
|
||||
meta: { title: '全部分类', noLogin: true }
|
||||
},
|
||||
{
|
||||
path: '/Operations',
|
||||
|
||||
@ -5628,5 +5628,338 @@
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 2.67vw 2.67vw 0vw 0vw;
|
||||
margin-top: -5vw;
|
||||
padding: 4.8vw 4vw;
|
||||
|
||||
.contaniar {
|
||||
.box;
|
||||
.box-center-center;
|
||||
}
|
||||
|
||||
.list_pagebox {
|
||||
.box;
|
||||
.box-tb;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cate_list {
|
||||
// .box;
|
||||
// flex-wrap: wrap;
|
||||
width: max-content;
|
||||
display: grid;
|
||||
grid-template-rows: auto auto;
|
||||
grid-auto-flow: column;
|
||||
overflow-x: auto;
|
||||
|
||||
.cate_item {
|
||||
width: 18.4vw;
|
||||
.box;
|
||||
.box-tb;
|
||||
.box-align-center;
|
||||
height: 20vw;
|
||||
white-space: nowrap;
|
||||
|
||||
img {
|
||||
width: 12vw;
|
||||
height: 10.8vw;
|
||||
margin-bottom: 1.87vw;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #ea3c1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scroll_progress {
|
||||
position: relative;
|
||||
height: 1.33vw;
|
||||
background-color: #ffe4ea;
|
||||
border-radius: 0.67vw;
|
||||
margin-top: 2vw;
|
||||
width: 18vw;
|
||||
|
||||
.progress_thumb {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 3vw;
|
||||
height: 100%;
|
||||
background-color: #b6536a;
|
||||
border-radius: 0.67vw;
|
||||
}
|
||||
}
|
||||
|
||||
.tab {
|
||||
margin-top: 4vw;
|
||||
|
||||
.van-tabs__nav {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.van-tabs__nav--card {
|
||||
border: none;
|
||||
margin: 0;
|
||||
gap: 3.33vw;
|
||||
// height: 6.67vw;
|
||||
}
|
||||
|
||||
.van-tab--card {
|
||||
width: 45.33vw;
|
||||
// height: 6.67vw;
|
||||
border: none;
|
||||
background: #fff;
|
||||
border-radius: 3.33vw;
|
||||
}
|
||||
}
|
||||
|
||||
.shoplist {
|
||||
.box;
|
||||
.box-tb;
|
||||
margin-top: 4vw;
|
||||
|
||||
.shopitem {
|
||||
.box;
|
||||
.box-tb;
|
||||
margin-bottom: 4vw;
|
||||
background-color: #ffffff;
|
||||
border-radius: 2.67vw;
|
||||
padding: 3.33vw;
|
||||
|
||||
.top_box {
|
||||
.box;
|
||||
width: 100%;
|
||||
|
||||
img {
|
||||
width: 18.67vw;
|
||||
height: 18.67vw;
|
||||
border-radius: 2vw;
|
||||
margin-right: 3.33vw;
|
||||
}
|
||||
|
||||
.info_box {
|
||||
.box;
|
||||
.box-tb;
|
||||
.box-pack-around;
|
||||
width: 100%;
|
||||
|
||||
>div {
|
||||
.box;
|
||||
.box-align-center;
|
||||
}
|
||||
|
||||
.name_box {
|
||||
color: #222222;
|
||||
|
||||
b {
|
||||
font-size: 4vw;
|
||||
width: 50vw;
|
||||
.text-hide(1);
|
||||
}
|
||||
|
||||
.type {
|
||||
.r;
|
||||
}
|
||||
}
|
||||
|
||||
.tags {
|
||||
>div {
|
||||
.box;
|
||||
.box-align-center;
|
||||
height: 4.8vw;
|
||||
background-color: #ec6e8c;
|
||||
border-radius: 2.4vw;
|
||||
padding: 0 2vw 0 .27vw;
|
||||
width: max-content;
|
||||
.bs;
|
||||
margin-right: 2.67vw;
|
||||
|
||||
img {
|
||||
width: 4.27vw;
|
||||
height: 4.27vw;
|
||||
margin-right: 1.2vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.addr_box {
|
||||
.box;
|
||||
.box-align-center;
|
||||
margin-top: 3.6vw;
|
||||
color: #222222;
|
||||
|
||||
.addr {
|
||||
width: 60vw;
|
||||
.text-hide(1);
|
||||
}
|
||||
|
||||
.distance {
|
||||
.r;
|
||||
.box;
|
||||
.box-align-center;
|
||||
gap: 1.2vw;
|
||||
|
||||
img {
|
||||
height: 3.47vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shopinfo {
|
||||
.shop_details {
|
||||
background-color: #ffffff;
|
||||
border-radius: 2.67vw 2.67vw 0vw 0vw;
|
||||
margin-top: -35vw;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
padding: 4vw 3.2vw 0;
|
||||
|
||||
.shopi_box {
|
||||
.box;
|
||||
width: 100%;
|
||||
padding-bottom: 3.2vw;
|
||||
border-bottom: 1px solid #f5f5f580;
|
||||
|
||||
img {
|
||||
width: 18.67vw;
|
||||
height: 18.67vw;
|
||||
border-radius: 2vw;
|
||||
margin-right: 3.33vw;
|
||||
}
|
||||
|
||||
.info_box {
|
||||
.box;
|
||||
.box-tb;
|
||||
.box-pack-around;
|
||||
width: 100%;
|
||||
|
||||
>div {
|
||||
.box;
|
||||
.box-align-center;
|
||||
}
|
||||
|
||||
.name_box {
|
||||
color: #222222;
|
||||
|
||||
b {
|
||||
font-size: 4vw;
|
||||
width: 50vw;
|
||||
.text-hide(1);
|
||||
}
|
||||
|
||||
.type {
|
||||
.r;
|
||||
}
|
||||
}
|
||||
|
||||
.tags {
|
||||
>div {
|
||||
.box;
|
||||
.box-align-center;
|
||||
height: 4.8vw;
|
||||
background-color: #ec6e8c;
|
||||
border-radius: 2.4vw;
|
||||
padding: 0 2vw 0 .27vw;
|
||||
width: max-content;
|
||||
.bs;
|
||||
margin-right: 2.67vw;
|
||||
|
||||
img {
|
||||
width: 4.27vw;
|
||||
height: 4.27vw;
|
||||
margin-right: 1.2vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tomap {
|
||||
.box;
|
||||
.box-align-center;
|
||||
padding: 3.33vw;
|
||||
border-bottom: 1px solid #f5f5f580;
|
||||
|
||||
.address {
|
||||
.box;
|
||||
|
||||
.addr_icon {
|
||||
height: 4vw;
|
||||
width: 3.47vw;
|
||||
margin-right: 2.53vw;
|
||||
}
|
||||
|
||||
.ri {
|
||||
span {
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
.distance {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.map_icon {
|
||||
.r;
|
||||
padding-left: 3.33vw;
|
||||
border-left: 1px solid #eeeeee;
|
||||
|
||||
img {
|
||||
width: 6.4vw;
|
||||
height: 6.4vw;
|
||||
background-color: #2dd6aa;
|
||||
border-radius: 1.33vw;
|
||||
}
|
||||
}
|
||||
|
||||
.onlinetime {
|
||||
.box;
|
||||
.box-align-center;
|
||||
padding: 3.33vw;
|
||||
|
||||
.left_box {
|
||||
.box;
|
||||
.box-align-center;
|
||||
|
||||
.clock_icon {
|
||||
width: 3.73vw;
|
||||
height: 3.73vw;
|
||||
margin-right: 2.53vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.intro {
|
||||
margin: 4vw 0;
|
||||
padding: 0 3.33vw;
|
||||
|
||||
.title {
|
||||
font-size: 4vw;
|
||||
color: #222222;
|
||||
margin-left: 1.2vw;
|
||||
}
|
||||
|
||||
.htmlcontent {
|
||||
margin-top: 3.33vw;
|
||||
width: 100%;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
margin-top: 1.2vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -49,21 +49,21 @@
|
||||
</div>
|
||||
<div class="pro-list">
|
||||
<div class="px">
|
||||
<a @click="toggleValue(0)" :class="searchParams.SortType == 0 ? 'a' : ''">
|
||||
<a @click="toggleValue(0)" :class="isActive(0) ? 'a' : ''">
|
||||
综合 <img :src="getImageSource(0)" />
|
||||
</a>
|
||||
<a @click="toggleValue(1)" :class="searchParams.SortType == 1 ? 'a' : ''">
|
||||
<a @click="toggleValue(1)" :class="isActive(1) ? 'a' : ''">
|
||||
价格 <img :src="getImageSource(1)" />
|
||||
</a>
|
||||
<a @click="toggleValue(2)" :class="searchParams.SortType == 2 ? 'a' : ''">
|
||||
<a @click="toggleValue(2)" :class="isActive(2) ? 'a' : ''">
|
||||
销量 <img :src="getImageSource(2)" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="content product_content">
|
||||
<BaseList class="pro-list" ref="productList" :url="`/v1/client/EProsClient`"
|
||||
<BaseList class="pro-list" ref="productList" page-size="100" :url="`/v1/client/EProsClient`"
|
||||
:params="queryParams" @load="onLoad">
|
||||
<template #default="{ item }">
|
||||
<div class="a1" @click="$navigate('/GoodsDetail?id=' + item.id)">
|
||||
<div class="a1" @click="goToDetail(item.id)">
|
||||
<img :src="$file(item.img)" />
|
||||
<div class="c">
|
||||
<div class="name">{{ item.name }}</div>
|
||||
@ -80,7 +80,7 @@
|
||||
<b><span>¥</span>{{ item.saleprice?.toFixed(2) }}</b>
|
||||
<span class="r" style="color: #8a8a8a;font-size: 3.2vw;">销量{{
|
||||
item.salenums
|
||||
}}</span>
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -117,8 +117,7 @@ export default {
|
||||
mainCategory: '',
|
||||
currentThirdId: '',
|
||||
searchParams: {
|
||||
SortType: 0,
|
||||
IsDesc: true,
|
||||
orderby: 'latest',
|
||||
},
|
||||
queryParams: {
|
||||
mallstate: 3,
|
||||
@ -130,57 +129,43 @@ export default {
|
||||
"/img/pro-list-px-1.png",
|
||||
"/img/pro-list-px-2.png",
|
||||
],
|
||||
_scrollRestored: false,
|
||||
_pauseScroll: false,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'searchParams.orderby': {
|
||||
handler(val) {
|
||||
this.queryParams.orderby = val;
|
||||
}
|
||||
},
|
||||
'$route.fullPath': {
|
||||
handler(newFullPath, oldFullPath) {
|
||||
if (newFullPath !== oldFullPath) {
|
||||
// this.searchKey = ''
|
||||
// setTimeout(() => {
|
||||
this.init()
|
||||
// }, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
activated() {
|
||||
this.searchKey = ''
|
||||
this._scrollRestored = false
|
||||
this._pauseScroll = false
|
||||
this.$nextTick(() => {
|
||||
const container = document.querySelector('.product_content')
|
||||
if (container) {
|
||||
container.addEventListener('scroll', this.saveScroll)
|
||||
this.restoreScroll(container)
|
||||
}
|
||||
})
|
||||
mounted() {
|
||||
// 重置标志
|
||||
this._scrollLoadCount = 0
|
||||
this._needRestoreScroll = sessionStorage.getItem('Category_scroll_need_restore') === '1'
|
||||
if (this._needRestoreScroll) {
|
||||
sessionStorage.removeItem('Category_scroll_need_restore')
|
||||
}
|
||||
const container = document.querySelector('.product_content')
|
||||
if (container) {
|
||||
container.addEventListener('scroll', this.saveScroll, { passive: true })
|
||||
}
|
||||
this.init()
|
||||
},
|
||||
beforeRouteLeave(to, from, next) {
|
||||
this._pauseScroll = true
|
||||
// 离开前保存滚动位置
|
||||
const container = document.querySelector('.product_content')
|
||||
if (container) {
|
||||
sessionStorage.setItem('Category_scroll', container.scrollTop || 0)
|
||||
}
|
||||
next()
|
||||
},
|
||||
deactivated() {
|
||||
this._pauseScroll = true
|
||||
const container = document.querySelector('.product_content')
|
||||
if (container) {
|
||||
sessionStorage.setItem('Category_scroll', container.scrollTop || 0)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
const container = document.querySelector('.product_content')
|
||||
if (container) {
|
||||
container.addEventListener('scroll', this.saveScroll)
|
||||
}
|
||||
this.init()
|
||||
},
|
||||
beforeUnmount() {
|
||||
const container = document.querySelector('.product_content')
|
||||
if (container) {
|
||||
@ -189,23 +174,17 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
saveScroll() {
|
||||
if (this._pauseScroll) return
|
||||
const container = document.querySelector('.product_content')
|
||||
if (container) {
|
||||
sessionStorage.setItem('Category_scroll', container.scrollTop || 0)
|
||||
}
|
||||
},
|
||||
restoreScroll(container) {
|
||||
restoreScroll() {
|
||||
const container = document.querySelector('.product_content')
|
||||
if (!container) return
|
||||
const scrollTop = sessionStorage.getItem('Category_scroll')
|
||||
if (scrollTop && scrollTop !== '0' && !this._scrollRestored) {
|
||||
this._scrollRestored = true
|
||||
container.removeEventListener('scroll', this.saveScroll)
|
||||
this.$nextTick(() => {
|
||||
container.scrollTo(0, Number(scrollTop))
|
||||
})
|
||||
setTimeout(() => {
|
||||
container.addEventListener('scroll', this.saveScroll)
|
||||
}, 100)
|
||||
if (scrollTop && scrollTop !== '0') {
|
||||
container.scrollTop = Number(scrollTop)
|
||||
}
|
||||
},
|
||||
async init() {
|
||||
@ -214,8 +193,7 @@ export default {
|
||||
this.changeMainById(Number(this.$route.query.id));
|
||||
}
|
||||
if (this.$route.query.SortType == 2) {
|
||||
this.searchParams.SortType = 2;
|
||||
this.searchParams.IsDesc = true;
|
||||
this.searchParams.orderby = 'salenumdown';
|
||||
}
|
||||
if (this.$route.query.name) {
|
||||
this.searchKey = this.$route.query.name;
|
||||
@ -315,23 +293,69 @@ export default {
|
||||
this.queryParams.name = this.searchKey;
|
||||
this.refreshProductList();
|
||||
},
|
||||
onLoad() {
|
||||
this._scrollLoadCount = (this._scrollLoadCount || 0) + 1
|
||||
// BaseList 数据加载完成后恢复滚动位置(只在首次加载时)
|
||||
if (this._scrollLoadCount === 1 && this._needRestoreScroll) {
|
||||
this._needRestoreScroll = false
|
||||
this.$nextTick(() => {
|
||||
this.restoreScroll()
|
||||
})
|
||||
}
|
||||
},
|
||||
goToDetail(id) {
|
||||
// 立即保存滚动位置和恢复标记
|
||||
const container = document.querySelector('.product_content')
|
||||
if (container) {
|
||||
const scrollTop = container.scrollTop || 0
|
||||
sessionStorage.setItem('Category_scroll', scrollTop)
|
||||
if (scrollTop > 0) {
|
||||
sessionStorage.setItem('Category_scroll_need_restore', '1')
|
||||
}
|
||||
}
|
||||
this.$navigate('/GoodsDetail?id=' + id)
|
||||
},
|
||||
refreshProductList() {
|
||||
this.$refs.productList?.refresh();
|
||||
},
|
||||
toggleValue(e) {
|
||||
if (this.searchParams.SortType == e) {
|
||||
this.searchParams.IsDesc = !this.searchParams.IsDesc;
|
||||
const orderbyMap = {
|
||||
0: ['latest', 'oldest'],
|
||||
1: ['salepriceup', 'salepricedown'],
|
||||
2: ['salenumup', 'salenumdown'],
|
||||
};
|
||||
const current = orderbyMap[e];
|
||||
if (!current) return;
|
||||
if (this.searchParams.orderby === current[0]) {
|
||||
this.searchParams.orderby = current[1];
|
||||
} else if (this.searchParams.orderby === current[1]) {
|
||||
this.searchParams.orderby = current[0];
|
||||
} else {
|
||||
this.searchParams.SortType = e;
|
||||
this.searchParams.IsDesc = true;
|
||||
this.searchParams.orderby = current[0];
|
||||
}
|
||||
this.refreshProductList();
|
||||
},
|
||||
isActive(e) {
|
||||
const orderbyMap = {
|
||||
0: ['latest', 'oldest'],
|
||||
1: ['salepriceup', 'salepricedown'],
|
||||
2: ['salenumup', 'salenumdown'],
|
||||
};
|
||||
return orderbyMap[e]?.includes(this.searchParams.orderby);
|
||||
},
|
||||
getImageSource(e) {
|
||||
if (this.searchParams.SortType == e) {
|
||||
if (this.searchParams.IsDesc) return this.imageSources[2];
|
||||
else return this.imageSources[1];
|
||||
} else return this.imageSources[0];
|
||||
const orderbyMap = {
|
||||
0: ['latest', 'oldest'],
|
||||
1: ['salepriceup', 'salepricedown'],
|
||||
2: ['salenumup', 'salenumdown'],
|
||||
};
|
||||
const current = orderbyMap[e];
|
||||
if (this.searchParams.orderby === current[0]) {
|
||||
return this.imageSources[2];
|
||||
} else if (this.searchParams.orderby === current[1]) {
|
||||
return this.imageSources[1];
|
||||
}
|
||||
return this.imageSources[0];
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ export default {
|
||||
},
|
||||
{
|
||||
Name: 'Social',
|
||||
Label: '合作店',
|
||||
Label: '加盟店',
|
||||
Icon_Active: '/img/Social_Active.png',
|
||||
Icon_Inactive: '/img/Social_Inactive.png',
|
||||
},
|
||||
@ -72,9 +72,9 @@ export default {
|
||||
methods: {
|
||||
updateActive() {
|
||||
const routeName = this.$route.name
|
||||
if (routeName === 'Social') {
|
||||
return
|
||||
}
|
||||
// if (routeName === 'Social') {
|
||||
// return
|
||||
// }
|
||||
const tabbar = this.Tabbars.find(item => item.Name === routeName)
|
||||
if (tabbar) {
|
||||
this.DefaultActive = tabbar.Name
|
||||
@ -84,9 +84,9 @@ export default {
|
||||
return item.Badge || ''
|
||||
},
|
||||
onTabClick(name) {
|
||||
if (name === 'Social') {
|
||||
return
|
||||
}
|
||||
// if (name === 'Social') {
|
||||
// return
|
||||
// }
|
||||
if (this.$route.name === name) {
|
||||
// 当前路由,双击刷新
|
||||
// this.$router.replace({ name })
|
||||
@ -97,11 +97,11 @@ export default {
|
||||
}
|
||||
},
|
||||
onTabChange(name) {
|
||||
if (name === 'Social') {
|
||||
this.$showToast('暂未开放')
|
||||
this.DefaultActive = this.$route.name;
|
||||
return
|
||||
}
|
||||
// if (name === 'Social') {
|
||||
// this.$showToast('暂未开放')
|
||||
// this.DefaultActive = this.$route.name;
|
||||
// return
|
||||
// }
|
||||
this.DefaultActive = name
|
||||
},
|
||||
onUpdateShare(title, desc, imgUrl) {
|
||||
|
||||
@ -26,23 +26,19 @@
|
||||
<van-field v-model="formData.huili" label="惠利比例" type="number" readonly>
|
||||
<template #extra><span style="color:#666">%</span></template>
|
||||
</van-field>
|
||||
<!-- <van-field v-model="formData.cellphone" label="商家分类" type="tel" readonly />
|
||||
<van-field v-model="formData.address" label="经营地址" placeholder="请联系平台修改" type="text" />
|
||||
<van-field v-model="formData.shopcatename" label="商家分类" readonly />
|
||||
<van-field v-model="formData.businesstime" label="营业时间" />
|
||||
|
||||
<van-field label="营业时间" readonly is-link @click="onBusinessTimeClick">
|
||||
<template #input>
|
||||
<span :style="{ color: formData.starttime && formData.endtime ? '#333' : '#ccc' }"
|
||||
style="text-align: right;width: 100%;">
|
||||
{{ formData.starttime && formData.endtime ? formData.starttime + '-' + formData.endtime : '选择营业时间' }}
|
||||
</span>
|
||||
</template>
|
||||
</van-field>
|
||||
<van-collapse v-model="activeNames" style="border: none;">
|
||||
<van-collapse-item title="商家介绍" name="1" style="border: none;">
|
||||
<van-collapse v-model="activeNames">
|
||||
<van-collapse-item title="经营地址" name="1" value="点击展开查看详情">
|
||||
<div style="color: #222;">{{ formData.shopaddress }}</div>
|
||||
修改请联系平台
|
||||
</van-collapse-item>
|
||||
<van-collapse-item title="商家介绍" name="2" value="点击展开查看详情">
|
||||
<div class="shop-intro-wrap">
|
||||
<div class="intro-images">
|
||||
<div v-for="(img, index) in formData.shopintroimages" :key="index" class="intro-img-item">
|
||||
<img :src="img" @click="previewImage(img)" />
|
||||
<img :src="img.url" @click="previewImage(img)" />
|
||||
<van-icon name="cross" class="delete-btn" @click="removeIntroImage(index)" />
|
||||
</div>
|
||||
<van-uploader v-if="formData.shopintroimages.length < 9" :after-read="onIntroImageRead"
|
||||
@ -50,7 +46,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</van-collapse-item>
|
||||
</van-collapse> -->
|
||||
</van-collapse>
|
||||
|
||||
</van-cell-group>
|
||||
</div>
|
||||
@ -105,37 +101,27 @@
|
||||
</div>
|
||||
</van-form>
|
||||
|
||||
<van-popup v-model:show="showStartTimePicker" position="bottom" round>
|
||||
<van-time-picker v-model="currentTime" title="选择开始时间" @confirm="onStartTimeConfirm"
|
||||
@cancel="showStartTimePicker = false" />
|
||||
</van-popup>
|
||||
|
||||
<van-popup v-model:show="showEndTimePicker" position="bottom" round>
|
||||
<van-time-picker v-model="currentTime" title="选择结束时间" @confirm="onEndTimeConfirm"
|
||||
@cancel="showEndTimePicker = false" />
|
||||
</van-popup>
|
||||
</div>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ImagePreview } from 'vant'
|
||||
|
||||
export default {
|
||||
name: 'MerchantIntroduction',
|
||||
data() {
|
||||
return {
|
||||
saving: false,
|
||||
activeNames: [],
|
||||
showStartTimePicker: false,
|
||||
showEndTimePicker: false,
|
||||
currentTime: ['12', '00'],
|
||||
formData: {
|
||||
shopname: '',
|
||||
shopimg: '',
|
||||
AvatarUploader: [],
|
||||
huili: 20,
|
||||
cellphone: '',
|
||||
shopcatename: '',
|
||||
businesstime: '',
|
||||
shopaddress: '',
|
||||
legalpersonname: '',
|
||||
legalpersonphone: '',
|
||||
legalidimg: [],
|
||||
@ -145,10 +131,8 @@ export default {
|
||||
bankcardnumber: '',
|
||||
subbank: '',
|
||||
bankcellphone: '',
|
||||
starttime: '',
|
||||
endtime: '',
|
||||
shopintroimages: [],
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -162,6 +146,9 @@ export default {
|
||||
this.formData.shopimg = data.shopimg
|
||||
this.formData.huili = data.feeratio || 20
|
||||
this.formData.cellphone = data.cellphone
|
||||
this.formData.shopcatename = data.shopcatename || ''
|
||||
this.formData.businesstime = data.businesstime || ''
|
||||
this.formData.shopaddress = data.shopprovince + data.shopcity + data.shopcounty + (data.shopstreet || '') + data.shopaddress
|
||||
this.formData.legalpersonname = data.legalpersonname
|
||||
this.formData.legalpersonphone = data.legalpersonphone
|
||||
this.formData.province = data.shopprovince + data.shopcity + data.shopcounty
|
||||
@ -179,6 +166,12 @@ export default {
|
||||
if (data.businesslicenseimg) {
|
||||
this.formData.licenseimg = [{ url: this.$file(data.businesslicenseimg), isImage: true }]
|
||||
}
|
||||
// 商家介绍图片
|
||||
if (data.shopdescription) {
|
||||
// shopdescription 是多张图片的路径,用逗号或其他分隔符隔开
|
||||
const imgs = data.shopdescription.split(',').filter(Boolean)
|
||||
this.formData.shopintroimages = imgs.map(url => ({ url: this.$file(url) }))
|
||||
}
|
||||
})
|
||||
},
|
||||
uploadShopImg(file) {
|
||||
@ -190,17 +183,41 @@ export default {
|
||||
this.formData.shopimg = file.file
|
||||
},
|
||||
previewImage(url) {
|
||||
ImagePreview([url])
|
||||
const imageUrl = typeof url === 'object' ? url.url : url
|
||||
this.$showImagePreview({ images: [imageUrl], startPosition: 0 })
|
||||
},
|
||||
async save() {
|
||||
if (!this.formData.shopname) {
|
||||
this.$showFailToast('请输入店铺名称')
|
||||
return
|
||||
}
|
||||
if (!this.formData.cellphone) {
|
||||
this.$showFailToast('请输入联系电话')
|
||||
return
|
||||
}
|
||||
this.saving = true
|
||||
try {
|
||||
const fd = new FormData()
|
||||
fd.append('shopname', this.formData.shopname)
|
||||
fd.append('shopphone', this.formData.cellphone)
|
||||
fd.append('Shopname', this.formData.shopname)
|
||||
fd.append('Shopphone', this.formData.cellphone)
|
||||
fd.append('Businesstime', this.formData.businesstime || '')
|
||||
if (this.formData.shopimg instanceof File) {
|
||||
fd.append('file', this.formData.shopimg)
|
||||
fd.append('File', this.formData.shopimg)
|
||||
}
|
||||
// 已有图片转逗号分隔字符串
|
||||
const existingUrls = this.formData.shopintroimages
|
||||
.filter(item => !item.file && item.url)
|
||||
.map(item => item.url)
|
||||
.join(',')
|
||||
if (existingUrls) {
|
||||
fd.append('Shopdescription', existingUrls)
|
||||
}
|
||||
// 新上传的图片
|
||||
this.formData.shopintroimages.forEach(item => {
|
||||
if (item.file) {
|
||||
fd.append('Filedesc', item.file)
|
||||
}
|
||||
})
|
||||
await this.$postForm('/v1/client/DShopsClient/shopinfo', fd)
|
||||
this.$showSuccessToast('保存成功')
|
||||
} catch (err) {
|
||||
@ -209,49 +226,15 @@ export default {
|
||||
this.saving = false
|
||||
}
|
||||
},
|
||||
uploadFile(url, file) {
|
||||
const fd = new FormData()
|
||||
fd.append('file', file)
|
||||
return fetch(`${import.meta.env.VITE_API_URL}${url}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${localStorage.getItem('member_token')}` },
|
||||
body: fd,
|
||||
}).then(res => res.json()).then(res => {
|
||||
if (res.status !== 200) throw new Error(res.message)
|
||||
return res.data
|
||||
})
|
||||
},
|
||||
onStartTimeConfirm({ selectedValues }) {
|
||||
this.formData.starttime = selectedValues.join(':')
|
||||
this.showStartTimePicker = false
|
||||
this.showEndTimePicker = true
|
||||
},
|
||||
onEndTimeConfirm({ selectedValues }) {
|
||||
this.formData.endtime = selectedValues.join(':')
|
||||
this.showEndTimePicker = false
|
||||
},
|
||||
onBusinessTimeClick() {
|
||||
this.showStartTimePicker = true
|
||||
},
|
||||
onIntroImageRead(file) {
|
||||
const img = file.file
|
||||
this.uploadFile('/v1/client/DShopsClient/shopintroimg', img).then(url => {
|
||||
this.formData.shopintroimages.push(this.$file(url))
|
||||
this.formData.shopintroimages.push({
|
||||
url: URL.createObjectURL(file.file),
|
||||
file: file.file,
|
||||
})
|
||||
},
|
||||
removeIntroImage(index) {
|
||||
this.formData.shopintroimages.splice(index, 1)
|
||||
},
|
||||
filter(type, options) {
|
||||
if (type === 'hour') {
|
||||
return options.filter(option => option >= 6 && option <= 23)
|
||||
}
|
||||
return options
|
||||
},
|
||||
onTimeConfirm({ selectedValues }) {
|
||||
this.formData.businesshours = selectedValues.join(':')
|
||||
this.showTimePicker = false
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -433,12 +416,13 @@ export default {
|
||||
.intro-images {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 2vw;
|
||||
gap: 3.33vw;
|
||||
// justify-content: space-between;
|
||||
|
||||
.intro-img-item {
|
||||
position: relative;
|
||||
width: 20vw;
|
||||
height: 20vw;
|
||||
width: 25vw;
|
||||
height: 25vw;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
@ -465,8 +449,9 @@ export default {
|
||||
|
||||
:deep(.van-uploader) {
|
||||
.van-uploader__upload {
|
||||
width: 20vw;
|
||||
height: 20vw;
|
||||
width: 25vw;
|
||||
height: 25vw;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -482,5 +467,6 @@ export default {
|
||||
font-size: 4.27vw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
151
src/views/Tabbars/Social.vue
Normal file
@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<div class="social">
|
||||
<div class="top">
|
||||
<div class="search_box">
|
||||
<img src="/img/search.png" alt="搜索">
|
||||
<input type="text" placeholder="搜索商家门店名称" v-model="searchQuery" @input="onSearchInput">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category_box">
|
||||
<div class="list_pagebox" ref="listPagebox" @scroll="onScroll">
|
||||
<div class="cate_list" ref="cateList">
|
||||
<div class="cate_item" :class="{ active: selectedId === '' }" @click="onSelectCategory('')">
|
||||
<img src="/img/cate_all.png" alt="全部分类">
|
||||
<span>全部分类</span>
|
||||
</div>
|
||||
<div class="cate_item" v-for="item in categories" :key="item.id" :class="{ active: selectedId === item.id }"
|
||||
@click="onSelectCategory(item.id)">
|
||||
<img :src="$file(item.img) || '/img/avatar.png'" alt="分类图片">
|
||||
<!-- <img src="/img/mall_i15.png" alt=""> -->
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contaniar">
|
||||
<div class="scroll_progress">
|
||||
<div class="progress_thumb" :style="thumbStyle"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-tabs class="tab" v-model:active="active" type="card" color="#841e36" title-active-color="#fff"
|
||||
title-inactive-color="#222" @change="onTabChange">
|
||||
<van-tab title="离我最近"></van-tab>
|
||||
<van-tab title="更大优惠"></van-tab>
|
||||
</van-tabs>
|
||||
|
||||
<BaseList class="shoplist" url="/v1/client/DShopsClient/list" :params="searchparams" :auto-load="true">
|
||||
<template #default="{ item }">
|
||||
<div class="shopitem" @click="$navigate(`/ShopInfo?id=${item.userid}`)">
|
||||
<div class="top_box">
|
||||
<img :src="$file(item.shopimg) || '/img/avatar.png'" alt="商户图片">
|
||||
<div class="info_box">
|
||||
<div class="name_box">
|
||||
<b>{{ item.shopname }}</b>
|
||||
<span class="type">{{ item.shopcatename }}</span>
|
||||
</div>
|
||||
<div class="tags">
|
||||
<div class="disc_box"><img src="/img/icon_disc.png" alt="">{{ item.feeratio }}%</div>
|
||||
<div class="canpay_box"><img src="/img/icon_canpay.png" alt="">可到店消费</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="addr_box">
|
||||
<span class="addr">
|
||||
{{ item.shopprovince + item.shopcity + item.shopcounty }}{{ item.shopstreet }}{{ item.shopaddress }}
|
||||
</span>
|
||||
<span class="distance"><img src="/img/addr_r.png" alt="">{{ (item.distance / 1000)?.toFixed(2)
|
||||
}}km</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</BaseList>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Social',
|
||||
data() {
|
||||
return {
|
||||
searchQuery: '',
|
||||
scrollPercent: 0,
|
||||
noScroll: true,
|
||||
selectedId: '',
|
||||
active: 0,
|
||||
categories: [],
|
||||
searchparams: {
|
||||
latitude: 29.309300,
|
||||
longitude: 120.070380,
|
||||
shopcateid: '',
|
||||
orderby: '',
|
||||
shopname: '',
|
||||
},
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
const res = await this.$geo.getWebGeo();
|
||||
this.searchparams.latitude = res.lat;
|
||||
this.searchparams.longitude = res.lon;
|
||||
this.init();
|
||||
this.$nextTick(() => {
|
||||
this.checkScroll();
|
||||
const ro = new ResizeObserver(() => this.checkScroll());
|
||||
ro.observe(this.$refs.cateList);
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
thumbStyle() {
|
||||
if (this.noScroll) {
|
||||
return { width: '100%', transform: 'none' };
|
||||
}
|
||||
return { transform: `translateX(${this.scrollPercent}vw)` };
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
active(val) {
|
||||
this.searchparams.orderby = val === 1 ? 'feeratio' : '';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
Promise.all([
|
||||
this.$get('/v1/client/dshopcatesclient').then(res => {
|
||||
this.categories = res.data
|
||||
})
|
||||
]).catch(err => {
|
||||
console.error('初始化失败:', err)
|
||||
})
|
||||
},
|
||||
onSelectCategory(id) {
|
||||
this.selectedId = id;
|
||||
this.searchparams.shopcateid = id;
|
||||
},
|
||||
onTabChange(val) {
|
||||
this.searchparams.orderby = val === 1 ? 'feeratio' : '';
|
||||
},
|
||||
onScroll() {
|
||||
const el = this.$refs.listPagebox
|
||||
if (!el) return
|
||||
const maxScroll = el.scrollWidth - el.clientWidth
|
||||
this.noScroll = maxScroll <= 0
|
||||
if (this.noScroll) {
|
||||
this.scrollPercent = 0
|
||||
return
|
||||
}
|
||||
const rawPercent = maxScroll > 0 ? (el.scrollLeft / maxScroll) * 15 : 0
|
||||
this.scrollPercent = Math.max(0, Math.min(rawPercent, 15))
|
||||
},
|
||||
checkScroll() {
|
||||
const el = this.$refs.cateList;
|
||||
const parent = this.$refs.listPagebox;
|
||||
if (!el || !parent) return;
|
||||
this.noScroll = el.scrollWidth <= parent.clientWidth;
|
||||
},
|
||||
onSearchInput() {
|
||||
this.searchparams.shopname = this.searchQuery;
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -1,9 +1,12 @@
|
||||
<template>
|
||||
<BasePage :back="back" title="订单支付">
|
||||
<div class="pay">
|
||||
<div class="amount">
|
||||
<div class="amount" v-if="orderInfo.mallstate !== 5">
|
||||
<span>¥</span>{{ orderInfo.needpay || orderInfo.payjifen }}
|
||||
</div>
|
||||
<div class="amount" v-else>
|
||||
{{ orderInfo.needpay || orderInfo.payjifen }} <span> 积分</span>
|
||||
</div>
|
||||
<div class="trade-code">
|
||||
订单号:{{ orderInfo.ordernum }}
|
||||
</div>
|
||||
@ -147,7 +150,7 @@ export default {
|
||||
alipay: 2,
|
||||
wechat: 1,
|
||||
bankcard: 3,
|
||||
point: 5,
|
||||
point: 6,
|
||||
};
|
||||
const paychannel = channelMap[method];
|
||||
const openid = localStorage.getItem('openid') || '';
|
||||
|
||||
@ -93,6 +93,10 @@
|
||||
评价时间
|
||||
<span>{{ $formatGMT(data.evaltime, 'yyyy-MM-dd HH:mm:ss') }}</span>
|
||||
</p>
|
||||
<p v-if="data.refundtime">
|
||||
退款时间
|
||||
<span>{{ $formatGMT(data.refundtime, 'yyyy-MM-dd HH:mm:ss') }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="p" v-else>
|
||||
<p>
|
||||
@ -150,6 +154,10 @@
|
||||
评价时间
|
||||
<span>{{ $formatGMT(data.evaltime, 'yyyy-MM-dd HH:mm:ss') }}</span>
|
||||
</p>
|
||||
<p v-if="data.refundtime">
|
||||
退款时间
|
||||
<span>{{ $formatGMT(data.refundtime, 'yyyy-MM-dd HH:mm:ss') }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
|
||||
106
src/views/User/ShopInfo.vue
Normal file
@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<BasePage>
|
||||
<div class="shopinfo">
|
||||
<img src="/img/shopinfo-top.jpg" style="width: 100%;" alt="店铺图片" class="shop-image">
|
||||
|
||||
<div class="shop_details">
|
||||
<div class="shopi_box">
|
||||
<img :src="$file(shopInfo.shopimg) || '/img/avatar.png'" alt="">
|
||||
<div class="info_box">
|
||||
<div class="name_box">
|
||||
<b>{{ shopInfo.shopname }}</b>
|
||||
<span class="type">{{ shopInfo.shopcatename }}</span>
|
||||
</div>
|
||||
<div class="tags">
|
||||
<div class="disc_box"><img src="/img/icon_disc.png" alt="">{{ shopInfo.feeratio }}%</div>
|
||||
<div class="canpay_box"><img src="/img/icon_canpay.png" alt="">可到店消费</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tomap">
|
||||
<div class="address">
|
||||
<img class="addr_icon" src="/img/addr_r.png" alt="">
|
||||
<div class="ri">
|
||||
<span>{{ shopInfo.shopprovince }}{{ shopInfo.shopcity }}{{ shopInfo.shopcounty }}{{ shopInfo.shopstreet ||
|
||||
'' }}{{ shopInfo.shopaddress }}</span>
|
||||
<div class="distance" v-if="shopInfo.distance">距离{{ (shopInfo.distance / 1000)?.toFixed(2) }}km</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="map_icon" @click="openMap">
|
||||
<img src="/img/map.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="onlinetime">
|
||||
<div class="left_box">
|
||||
<img class="clock_icon" src="/img/clock.png" alt="">
|
||||
<span>{{ shopInfo.businesstime || '暂未设置' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="map_icon" @click="callPhone">
|
||||
<img src="/img/icon_phone.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr style="margin: 0; border: none; height: 1.6vw; background-color: #f5f5f5;">
|
||||
|
||||
<div class="intro">
|
||||
<b class="title">
|
||||
商家介绍
|
||||
</b>
|
||||
<div class="htmlcontent" v-html="shopInfo.shopdescriptionhtml || '暂无商家介绍'"></div>
|
||||
</div>
|
||||
|
||||
<van-action-bar placeholder>
|
||||
<van-action-bar-icon icon="shop-o" text="附近的店" @click="$router.back()" />
|
||||
<van-action-bar-button color="#ca2904" type="danger" text="到店买单" @click="openMap" />
|
||||
</van-action-bar>
|
||||
|
||||
</div>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ShopInfo',
|
||||
data() {
|
||||
return {
|
||||
// 店铺信息数据
|
||||
shopInfo: {
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.$get('/v1/client/DShopsClient/list', { userid: this.$route.query.id }).then(res => {
|
||||
this.shopInfo = res.data.items[0] || {}
|
||||
})
|
||||
},
|
||||
callPhone() {
|
||||
if (this.shopInfo.shopphone) {
|
||||
window.location.href = `tel:${this.shopInfo.shopphone}`
|
||||
}
|
||||
},
|
||||
openMap() {
|
||||
if (this.shopInfo.shoplatitude && this.shopInfo.shoplongitude) {
|
||||
const lat = this.shopInfo.shoplatitude;
|
||||
const lon = this.shopInfo.shoplongitude;
|
||||
const fullAddress = encodeURIComponent(
|
||||
(this.shopInfo.shopprovince || '') +
|
||||
(this.shopInfo.shopcity || '') +
|
||||
(this.shopInfo.shopcounty || '') +
|
||||
(this.shopInfo.shopstreet || '') +
|
||||
(this.shopInfo.shopaddress || '')
|
||||
);
|
||||
window.open(`https://uri.amap.com/navigation?to=${lon},${lat},${fullAddress}&mode=car&src=shop`, '_blank');
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||