Merge branch 'dev' into test

This commit is contained in:
lifizer
2024-03-21 16:58:59 +08:00
40 changed files with 5075 additions and 2323 deletions
+22
View File
@@ -198,3 +198,25 @@ export function getHotelTypeList() {
export function getPoster(id) { export function getPoster(id) {
return request.get("/api/hotelMain/poster/" + id, {}, {login: true}) return request.get("/api/hotelMain/poster/" + id, {}, {login: true})
} }
/**
* 获取客栈商品列表
* @param data
* @returns {*}
*/
export function getHotelGoodList(data) {
return request.get("/api/hotelMain/goodsList", data, {
login: false
});
}
/**
* 置顶客栈资讯
* @param data
* @returns {*}
*/
export function setTopHotelNew(data) {
return request.post("/api/hotelNews/setIsTop", data, {
login: true
});
}
+10 -2
View File
@@ -16,9 +16,17 @@ export function wellnessPlaceList(param) {
/** /**
* 特色礼品首页 * 特色礼品首页
* */ */
export function customizedGift() { export function customizedGift() {
return request.get("/customizedGift/index", {}, {login: true}) return request.get("/customizedGift/index", {}, {login: false})
}
/**
* 特色礼品省份专题页
*
*/
export function customizedGiftContent(param) {
return request.get("/customizedGift/cityContent", param, {login: false})
} }
/** /**
+5
View File
@@ -534,3 +534,8 @@ export function setDetection() {
export function getRechargeApi() { export function getRechargeApi() {
return request.get("recharge/index"); return request.get("recharge/index");
} }
export function getUserCenterBanner() {
return request.get("userCenterBanner");
}
+10 -1
View File
@@ -25,7 +25,7 @@
} }
.goods-section { .goods-section {
margin: 24rpx; margin: 0 24upx 24upx 24upx;
padding: 30rpx 24rpx; padding: 30rpx 24rpx;
border-radius: 20rpx; border-radius: 20rpx;
background: #fff; background: #fff;
@@ -103,6 +103,15 @@
color: #333; color: #333;
font-size: 30rpx; font-size: 30rpx;
} }
.store-btn {
display: flex;
padding: 12upx;
border-radius: 6upx;
color: #fff;
line-height: 20upx;
font-size: 24rpx;
background-color: #FF564A;
}
.value { .value {
color: #666; color: #666;
+43 -13
View File
@@ -274,7 +274,10 @@ page {
} }
.noCommodity { .noCommodity {
padding-top: 0.75*100rpx; display: flex;
justify-content: center;
padding: 75rpx 0;
background-color: #fff;
} }
.noCommodity .noPictrue { .noCommodity .noPictrue {
@@ -644,6 +647,7 @@ page {
} }
.product-window .productWinList .item .listn .itemn { .product-window .productWinList .item .listn .itemn {
position: relative;
border: 1px solid #bbb; border: 1px solid #bbb;
font-size: 0.26*100rpx; font-size: 0.26*100rpx;
color: #282828; color: #282828;
@@ -657,6 +661,23 @@ page {
background-color: #eb3729; background-color: #eb3729;
border-color: #eb3729; border-color: #eb3729;
} }
.product-window .productWinList .item .listn .itemn.disabled {
color: #333;
background-color: #F1F1F1;
border-color: #F1F1F1;
}
.product-window .productWinList .item .listn .itemn.disabled .tag {
position: absolute;
top: -18upx;
right: -18upx;
height: 28upx;
padding: 0 6upx;
border-radius: 6upx;
color: #fff;
line-height: 28upx;
font-size: 10px;
background-color: #FD5749;
}
.product-window .cart { .product-window .cart {
margin-top: 0.36*100rpx; margin-top: 0.36*100rpx;
@@ -2397,11 +2418,25 @@ page {
.user .wrapper .myOrder .title, .user .wrapper .myOrder .title,
.user .wrapper .myService .title { .user .wrapper .myService .title {
height: 0.88*100rpx; height: 88rpx;
padding: 0 0.3*100rpx; padding: 0 30rpx;
border-bottom: 1px dashed #eee; border-bottom: 1px solid #ECECEE;
font-size: 0.3*100rpx; font-size: 28rpx;
color: #282828; color: #333;
font-weight: 600;
}
.user .wrapper .myService .title {
border-bottom: 0;
}
.user .wrapper .myOrder .title .line,
.user .wrapper .myService .title .line {
display: block;
width: 6rpx;
height: 28rpx;
margin: 0 15rpx 0 0;
border-radius: 6rpx;
background-color: #FF564A;
} }
.user .wrapper .myOrder .title .allOrder { .user .wrapper .myOrder .title .allOrder {
@@ -2428,16 +2463,11 @@ page {
} }
.user .wrapper .myOrder .orderState .item .pictrue { .user .wrapper .myOrder .orderState .item .pictrue {
width: 0.49*100rpx; width: 52rpx;
height: 0.42*100rpx; height: 52rpx;
margin: 0 auto 0.18*100rpx auto; margin: 0 auto 0.18*100rpx auto;
} }
.user .wrapper .myOrder .orderState .item .pictrue image {
width: 100%;
height: 100%;
}
.user .wrapper .myService { .user .wrapper .myService {
background-color: #fff; background-color: #fff;
margin-top: 0.15*100rpx; margin-top: 0.15*100rpx;
+14 -1
View File
@@ -17,7 +17,12 @@
<view class="coupons__rules-title" @click="changeRules()">使用规则 <view class="coupons__rules-title" @click="changeRules()">使用规则
<image :class="{'open':isOpen}" :src="webUrl+'/20231125220409665027.png'" mode="scaleToFill"/> <image :class="{'open':isOpen}" :src="webUrl+'/20231125220409665027.png'" mode="scaleToFill"/>
</view> </view>
<rich-text :nodes="data.description" v-show="isOpen"/> <view
:class="isOpen ? 'auto-height' : ''"
class="coupon-html"
>
<rich-text :nodes="data.description" />
</view>
</view> </view>
</view> </view>
</template> </template>
@@ -124,6 +129,14 @@ export default {
transform: rotate(180deg); transform: rotate(180deg);
} }
} }
.coupon-html {
height: 80rpx;
overflow: hidden;
transition: all .3s;
&.auto-height {
height: auto;
}
}
} }
} }
</style> </style>
+62
View File
@@ -0,0 +1,62 @@
# skeleton
uni-app 骨架屏组件,用于数据加载时显示占位元素
## 属性说明
|属性名|类型|默认值|说明|
| -- | -- | --|--|
| loading | Boolean | true | 是否显示占位图 |
| showAvatar | Boolean | true | 是否显示头像占位图 |
| AvatarSize | String | 50px | 头像站占位图大小 |
| AvatarShape | String | round | 头像形状,可选值:round, square |
| showTitle | Boolean | true | 是否显示标题占位图 |
| titleWidth | String | 40% | 标题占位图宽度 |
| row | Number| 3 | 段落占位图行数 |
| animate | Boolean | true | 是否开启动画 |
## 使用示例
```html
<skeleton
:loading="loading"
:avatarSize="skeleton1.avatarSize"
:row="skeleton1.row"
:showTitle="skeleton1.showTitle"
>
<view class="section-content">我是段落1</view>
</skeleton>
```
```javascript
import Skeleton from '../components/skeleton/index.vue'
export default {
components: {
Skeleton
},
data() {
return {
loading: true,
skeleton1 : {
avatarSize: '52px',
row: 3,
showTitle: true,
}
}
},
created() {
this.reloadData()
},
methods: {
reloadData() {
this.loading = true
setTimeout(() => {
this.loading = false
}, 3000)
},
},
}
```
## 效果图
![](http://images.alisali.cn/img_20191014113211.png)
+145
View File
@@ -0,0 +1,145 @@
<template>
<view>
<view
v-if="loading"
:class="{ animate: animate }"
class="skeleton"
>
<view
v-if="showAvatar"
:class="[avatarShape]"
:style="{ width: avatarSize, height: avatarSize }"
class="skeleton-avatar"
/>
<view class="skeleton-content">
<view
v-if="showTitle"
:style="{ width: titleWidth }"
class="skeleton-title"
/>
<view class="skeleton-rows">
<view
v-for="(item, index) in rowList"
:key="index"
:style="{ width: item.width }"
class="skeleton-row-item"
/>
</view>
</view>
</view>
<view v-else>
<slot />
</view>
</view>
</template>
<script>
const DEFAULT_ROW_WIDTH = '100%'
const DEFAULT_LAST_ROW_WIDTH = '70%'
export default {
props: {
loading: {
type: Boolean,
default: true
},
showAvatar: {
type: Boolean,
default: true
},
avatarSize: {
type: String,
default: '50px'
},
avatarShape: {
type: String,
default: 'round' // square | round
},
showTitle: {
type: Boolean,
default: true
},
titleWidth: {
type: String,
default: '40%'
},
row: {
type: Number,
default: 3
},
animate: {
type: Boolean,
default: true
}
},
data() {
return {}
},
computed: {
rowList() {
const list = []
for (let i = 0; i < this.row; i++) {
list.push({
width: i === this.row - 1 && i !== 0 ? DEFAULT_LAST_ROW_WIDTH : DEFAULT_ROW_WIDTH
})
}
return list
}
}
}
</script>
<style scoped>
.skeleton {
display: flex;
padding: 16px;
--bg-color: #f2f3f5;
--row-height: 16px;
--row-margin-top: 16px;
}
.skeleton-avatar {
flex-shrink: 0;
background: var(--bg-color);
margin-right: 8px;
}
.skeleton-avatar.round {
border-radius: 50%;
}
.skeleton-content {
width: 100%;
}
.skeleton-title {
background-color: var(--bg-color);
height: var(--row-height);
}
.skeleton-title + .skeleton-rows {
margin-top: var(--row-margin-top);
}
.skeleton-row-item {
background-color: var(--bg-color);
height: var(--row-height);
}
.skeleton-row-item:not(:first-child) {
margin-top: var(--row-margin-top);
}
.skeleton.animate {
animation: skeleton-blink 1.2s ease-in-out infinite;
}
@keyframes skeleton-blink {
0% {
opacity: 1;
}
50% {
opacity: 0.6;
}
100% {
opacity: 1;
}
}
</style>
+21 -5
View File
@@ -20,12 +20,21 @@
<view class="title">{{ item.attrName }}</view> <view class="title">{{ item.attrName }}</view>
<view class="listn acea-row row-middle"> <view class="listn acea-row row-middle">
<view <view
class="itemn"
:class="item.index == indexn ? 'on' : ''"
v-for="(itemn, indexn) in item.attrValue" v-for="(itemn, indexn) in item.attrValue"
@click="tapAttr(indexw, indexn)"
:key="indexn" :key="indexn"
>{{ itemn.attr }}</view> :class="{
'on': item.index == indexn,
'disabled': productValue[itemn.attr].stock === 0
}"
class="itemn"
@click="tapAttr(indexw, indexn, itemn)"
>
{{ itemn.attr }}
<text
v-if="productValue[itemn.attr].stock === 0"
class="tag"
>缺货</text>
</view>
</view> </view>
</view> </view>
</view> </view>
@@ -57,6 +66,10 @@ export default {
type: Object, type: Object,
default: () => {} default: () => {}
}, },
productValue: {
type: Object,
default: () => {}
},
cartNum: { cartNum: {
type: Number, type: Number,
default: () => 1 default: () => 1
@@ -80,7 +93,10 @@ export default {
CartNumAdd: function() { CartNumAdd: function() {
this.$emit("changeFun", { action: "ChangeCartNum", value: 1 }); this.$emit("changeFun", { action: "ChangeCartNum", value: 1 });
}, },
tapAttr: function(indexw, indexn) { tapAttr: function(indexw, indexn, itemn) {
if (this.productValue[itemn.attr].stock === 0) {
return
}
// 修改商品规格不生效的原因: // 修改商品规格不生效的原因:
// H5端下面写法,attr更新,但是除H5外其他端不支持, // H5端下面写法,attr更新,但是除H5外其他端不支持,
// 尽量避免下面的骚写法,不要在子组件内更新props // 尽量避免下面的骚写法,不要在子组件内更新props
+17
View File
@@ -0,0 +1,17 @@
<template>
<view class="noCommodity">
<view class="noPictrue">
<image :src="webUrl+'/20210203153900181449.png'" class="image"/>
</view>
</view>
</template>
<script>
export default {
name: "NoGoodData",
data: function() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL
}
}
}
</script>
+17 -5
View File
@@ -43,7 +43,7 @@
} }
}, },
{ {
"path": "components/chose-city/chose-city", "path": "pages/chose-city/chose-city",
"style": { "style": {
"navigationBarTitleText": "选择城市" "navigationBarTitleText": "选择城市"
} }
@@ -461,6 +461,12 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "inn/innGoodList",
"style": {
"navigationBarTitleText": "店铺商品列表"
}
},
{ {
"path": "inn/innApply", "path": "inn/innApply",
"style": { "style": {
@@ -632,9 +638,15 @@
}, },
{ {
"path": "views/giftList", "path": "views/giftList",
"style": {
"navigationBarTitleText": "特色礼品"
}
},
{
"path": "views/giftContent",
"style": { "style": {
"navigationBarTitleText": "特色礼品", "navigationBarTitleText": "特色礼品",
"onReachBottomDistance": 100 "navigationBarTextStyle": "black"
} }
}, },
{ {
@@ -951,9 +963,9 @@
"query": "" "query": ""
}, },
{ {
"name": "提交订单", "name": "特色礼品",
"path": "pages/order/OrderSubmission/index", "path": "pkg_product/views/giftList",
"query": "lotteryRecordId=217" "query": ""
} }
] ]
} }
+1 -1
View File
@@ -41,7 +41,7 @@
<view class="dialog-mask" v-if="showFillOut"> <view class="dialog-mask" v-if="showFillOut">
<view class="dialog-fill flex flex-col ai-center"> <view class="dialog-fill flex flex-col ai-center">
<view class="title bold">请完善您的头像和昵称</view> <view class="title bold">请完善您的头像和昵称</view>
<button class="avatar-wrapper" open-type="chooseAvatar" bindchooseavatar="onChooseAvatar"> <button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<image class="avatar" :src="avatarUrl"></image> <image class="avatar" :src="avatarUrl"></image>
</button> </button>
<input type="nickname" class="input-wrapper" placeholder="请输入昵称" @input="inputName" @confirm="inputName" <input type="nickname" class="input-wrapper" placeholder="请输入昵称" @input="inputName" @confirm="inputName"
@@ -2,90 +2,120 @@
<view class="chose-city"> <view class="chose-city">
<view class="header"> <view class="header">
<view class="search-box flex jc-between ai-center"> <view class="search-box flex jc-between ai-center">
<input type="text" v-model="keyword" placeholder="搜索城市" placeholder-style="color:#999" @confirm="search"> <input
<image class="icon" :src="webUrl+'/20220903142935869059.png'" mode="scaleToFill" @click="search"></image> v-model="keyword"
type="text"
placeholder="搜索城市"
placeholder-style="color:#999"
@confirm="search"
>
<image
:src="webUrl + '/20220903142935869059.png'"
class="icon"
mode="scaleToFill"
@click="search"
/>
</view> </view>
</view> </view>
<view class="aside"> <view class="aside">
<view class="item flex jc-center ai-center" :class="index === navActive ? 'on' : ''" <view
v-for="(item, index) in listGroup" :key="index" @click="asideTap(index)"> v-for="(item, index) in listGroup"
:key="index"
:class="index === navActive ? 'on' : ''"
class="item flex jc-center ai-center"
@click="asideTap(index)"
>
<view class="name">{{ item.label }}</view> <view class="name">{{ item.label }}</view>
</view> </view>
</view> </view>
<view class="content"> <view class="content">
<mescroll-body ref="mescrollRef" top="16rpx" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption" <mescroll-body
@up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick"> ref="mescrollRef"
:up="upOption"
:down="downOption"
top="16rpx"
bottom="0"
class='cotent-scroll'
@up="upCallback"
@down="downCallback"
@init="mescrollInit"
@emptyclick="emptyClick"
>
<view class="fixed-box"> <view class="fixed-box">
<view class="line-location flex ai-center"> <view class="line-location flex ai-center">
<image :src="webUrl+'/20220903142929759087.png'" mode="scaleToFill"></image> <image :src="webUrl + '/20220903142929759087.png'" mode="scaleToFill"></image>
<text class="bold" v-if="location">当前定位{{ location }}</text> <text class="bold" v-if="location">当前定位{{ location }}</text>
<view style="color:#f66" @click="reload()" v-else>定位失败 <view style="color:#f66" @click="reload()" v-else>定位失败
<image :src="webUrl+'/20231215213824297278.png'" mode="scaleToFill"/> <image :src="webUrl + '/20231215213824297278.png'" mode="scaleToFill" />
</view> </view>
</view> </view>
<image
<image class="banner" :src="banner.icon" mode="scaleToFill" v-if="banner" v-if="banner"
@click="$global.commonJump(banner.url)"/> :src="banner.icon"
class="banner"
<!-- <view class="top-box" v-if="listTop.length">--> mode="scaleToFill"
<!-- <view class="tips">特别推荐</view>--> @click="bannerItemTapHandle(banner)"
<!-- <view class="top-list custom-list flex ai-center">--> />
<!-- <view class="item" v-for="(item,index) in listTop" :key="index" @click="select(item)">-->
<!-- <view class="has-goods" v-if="type===0 && item.hasData===0">暂无特产</view>-->
<!-- <view class="has-goods" v-if="type>0 && type<6&& item.hasShop===0">暂无店铺</view>-->
<!-- <image :src="item.icon" mode="scaleToFill"></image>-->
<!-- <view class="one-t">{{ item.cityName }}</view>-->
<!-- </view>-->
<!-- </view>-->
<!-- </view>-->
</view> </view>
<!--9-2 推荐信息--> <!--9-2 推荐信息-->
<view class="recommendInfo" v-if="recommendInfo && type<2"> <view class="recommendInfo" v-if="recommendInfo && type < 2">
<template v-if="(type===0 && recommendInfo.hotelList) || (type===1 && recommendInfo.productList)"> <template v-if="(type === 0 && recommendInfo.hotelList) || (type === 1 && recommendInfo.productList)">
<view class="red-border-title">{{ recommendInfo.title }}</view> <view class="red-border-title">{{ recommendInfo.title }}</view>
<image class="bg-custom" :src="recommendInfo.backgroundImage" mode="scaleToFill"/> <image
:src="recommendInfo.backgroundImage"
class="bg-custom"
mode="scaleToFill"
/>
<scroll-view
enable-flex
scroll-x
class="scroll-box flex"
>
<template v-if="type === 0">
<view
v-for="(item,index) in recommendInfo.hotelList"
:key="index"
<scroll-view class="scroll-box flex" enable-flex scroll-x> class="item flex-0 flex flex-col jc-between ai-center"
<!-- :style="{'backgroundImage':`url(${recommendInfo.backgroundImage})`}"--> @click="goToStore(item.hotelId || '')"
>
<image class="cover" :src="item.hotelImage" mode="scaleToFill" />
<view class="item flex-0 flex flex-col jc-between ai-center" <image class="logo" :src="item.hotelLogo" mode="scaleToFill" />
v-for="(item,index) in recommendInfo.hotelList" <view style="width: 100%;box-sizing: border-box;padding:0 8rpx">
:key="index" v-if="type===0" @click="goStore(item.hotelId)"> <view class="name tc one-t">{{ item.hotelName }}</view>
<image class="cover" :src="item.hotelImage" mode="scaleToFill"/> <rich-text class="text tc one-t" :nodes="item.hotelText" />
<image class="logo" :src="item.hotelLogo" mode="scaleToFill"/> </view>
<view style="width: 100%;box-sizing: border-box;padding:0 8rpx">
<view class="name tc one-t">{{ item.hotelName }}</view>
<rich-text class="text tc one-t" :nodes="item.hotelText"/>
</view> </view>
</view> </template>
<template v-if="type === 1">
<view
v-for="(item,index) in recommendInfo.productList"
:key="index"
class="item flex-0 flex flex-col jc-between ai-center"
<view class="item flex-0 flex flex-col jc-between ai-center" @click="goToGoods(item.productId || '')"
v-for="(item,index) in recommendInfo.productList" :key="index" v-if="type===1" >
@click="$global.navToGoods(item.productId)"> <image class="cover" :src="item.productImage" mode="scaleToFill" />
<image class="cover" :src="item.productImage" mode="scaleToFill"/> <image class="logo" :src="item.merLogo" mode="scaleToFill" />
<image class="logo" :src="item.merLogo" mode="scaleToFill"/> <view style="width: 100%">
<view style="width: 100%"> <view class="name tc one-t">{{ item.productName }}</view>
<view class="name tc one-t">{{ item.productName }}</view> <rich-text class="text tc one-t" :nodes="item.productText" />
<rich-text class="text tc one-t" :nodes="item.productText"/> </view>
</view> </view>
</view> </template>
</scroll-view> </scroll-view>
</template> </template>
</view> </view>
<!-- province-name-->
<view class="red-border-title" style="margin-left: 38rpx;">{{ provinceName }}</view> <view class="red-border-title" style="margin-left: 38rpx;">{{ provinceName }}</view>
<view class="group-list custom-list flex flex-wrap"> <view class="group-list custom-list flex flex-wrap">
<view class="item" v-for="(item, index) in listCity" :key="index" @click="select(item)"> <view class="item"
<view class="has-goods" v-if="type===0 && item.hasData===0">暂无特产</view> v-for="(item, index) in listCity"
<view class="has-goods" v-if="type>0 && type<6&& item.hasShop===0">暂无店铺</view> :key="index"
<view class="has-goods" v-if="type===6 && item.hasData===0">暂无景点</view> @click="select(item)"
>
<view class="has-goods" v-if="type === 0 && item.hasData === 0">暂无特产</view>
<view class="has-goods" v-if="type > 0 && type < 6 && item.hasShop === 0">暂无店铺</view>
<view class="has-goods" v-if="type === 6 && item.hasData === 0">暂无景点</view>
<image :src="item.icon" mode="scaleToFill"></image> <image :src="item.icon" mode="scaleToFill"></image>
<view class="one-t">{{ item.cityName }}</view> <view class="one-t">{{ item.cityName }}</view>
</view> </view>
@@ -120,21 +150,18 @@ export default {
], ],
data() { data() {
return { return {
webUrl: this.$VUE_APP_RESOURCES_URL,
upOption: { upOption: {
noMoreSize: 10, //,;(),; 5 noMoreSize: 10, //,;(),; 5
auto: false, auto: false,
empty: { empty: {
tip: '暂无城市' // tip: '暂无城市'
// btnText:''
} }
}, },
downOption: { downOption: {
auto: true auto: true
}, },
webUrl: this.$VUE_APP_RESOURCES_URL,
listGroup: [], listGroup: [],
listTop: [],
provinceName: "", provinceName: "",
listCity: [], listCity: [],
navActive: 0, navActive: 0,
@@ -142,7 +169,7 @@ export default {
type: null, type: null,
location: "", location: "",
banner: {}, banner: {},
recommendInfo: null, // recommendInfo: null //
}; };
}, },
onLoad(options) { onLoad(options) {
@@ -190,7 +217,6 @@ export default {
} }
}) })
}, },
async getMapData() { async getMapData() {
const map = await getLocation(); const map = await getLocation();
if (map) { if (map) {
@@ -199,18 +225,16 @@ export default {
this.location = address[1].data.result.ad_info.city; this.location = address[1].data.result.ad_info.city;
} }
}, },
init() { init() {
fetchCity(this.type).then(res => { fetchCity(this.type).then(res => {
if (res.success) { if (res.success) {
this.listGroup = res.data.group; this.listGroup = res.data.group;
// this.listTop = res.data.tops;
if (this.listGroup.length > 0) { if (this.listGroup.length > 0) {
this.listTop = this.listGroup[0].top;
this.listCity = this.listGroup[0].city; this.listCity = this.listGroup[0].city;
this.provinceName = this.listGroup[0].label; this.provinceName = this.listGroup[0].label;
this.recommendInfo = this.listGroup[0].recommendInfo this.recommendInfo = this.listGroup[0].recommendInfo
this.banner = { this.banner = {
...this.listGroup[0],
icon: this.listGroup[0].icon, icon: this.listGroup[0].icon,
url: this.listGroup[0].uniappUrl url: this.listGroup[0].uniappUrl
} }
@@ -220,11 +244,11 @@ export default {
}, },
asideTap(index) { asideTap(index) {
this.navActive = index; this.navActive = index;
this.listTop = this.listGroup[index].top;
this.listCity = this.listGroup[index].city; this.listCity = this.listGroup[index].city;
this.provinceName = this.listGroup[index].label; this.provinceName = this.listGroup[index].label;
this.recommendInfo = this.listGroup[index].recommendInfo this.recommendInfo = this.listGroup[index].recommendInfo
this.banner = { this.banner = {
...this.listGroup[index],
icon: this.listGroup[index].icon, icon: this.listGroup[index].icon,
url: this.listGroup[index].uniappUrl url: this.listGroup[index].uniappUrl
} }
@@ -277,12 +301,43 @@ export default {
break; break;
} }
}, },
goToStore(id) {
goStore(id) { if (!id) {
return
}
uni.navigateTo({ uni.navigateTo({
url: "/pagesInn/inn/innHome?id=" + id url: "/pagesInn/inn/innHome?id=" + id
}) })
}, },
goToGoods(productId) {
if (!productId) {
return
}
this.$global.navToGoods(productId)
},
bannerItemTapHandle(banner) {
if (!banner) {
return
}
const url = banner.url || ''
if (url) {
this.$global.commonJump(url)
} else {
const linkType = banner.linkType
if (linkType > 0) {
switch(linkType) {
case 1:
this.goToStore(banner.linkHotelId)
break
case 2:
this.goToGoods(banner.linkProductId)
break
default:
break
}
}
}
}
} }
}; };
</script> </script>
+7 -2
View File
@@ -5,7 +5,12 @@
</view> </view>
<view class="nav-box"> <view class="nav-box">
<view class="item flex-0" v-for="(item,index) in typeList" @click="changeType(index)"> <view
v-for="(item, index) in typeList"
:key="index"
class="item flex-0"
@click="changeType(index)"
>
<image :src="item.icon" mode="scaleToFill"></image> <image :src="item.icon" mode="scaleToFill"></image>
<view class="nav">{{item.name}}</view> <view class="nav">{{item.name}}</view>
</view> </view>
@@ -98,7 +103,7 @@
methods: { methods: {
goCity() { goCity() {
uni.navigateTo({ uni.navigateTo({
url:`/components/chose-city/chose-city?type=2&city=${this.cityName}` url:`/pages/chose-city/chose-city?type=2&city=${this.cityName}`
}) })
}, },
//获取当前定位地址 //获取当前定位地址
+7 -3
View File
@@ -39,7 +39,7 @@ export default {
methods: { methods: {
goCity() { goCity() {
uni.navigateTo({ uni.navigateTo({
url: `/components/chose-city/chose-city?type=2&city=${this.cityName}` url: `/pages/chose-city/chose-city?type=2&city=${this.cityName}`
}) })
}, },
@@ -122,8 +122,12 @@ export default {
<view class="list" v-if="hotelList.length"> <view class="list" v-if="hotelList.length">
<custom-waterfalls-flow :value="hotelList" imageKey="cover"> <custom-waterfalls-flow :value="hotelList" imageKey="cover">
<view class="item" v-for="(item,index) in hotelList" slot="slot{{index}}" <view
@click="goInnDetail(item)"> v-for="(item,index) in hotelList"
:key="index"
class="item"
@click="goInnDetail(item)"
>
<view class="cover-box"> <view class="cover-box">
<image class="cover" :src="item.cover" mode="scaleToFill"></image> <image class="cover" :src="item.cover" mode="scaleToFill"></image>
<view class="my-mask"> <view class="my-mask">
+13 -3
View File
@@ -89,9 +89,19 @@ export default {
<view class="top-box" :style="{'backgroundColor':topBoxBgColor}"> <view class="top-box" :style="{'backgroundColor':topBoxBgColor}">
<view class="view-box"> <view class="view-box">
<view class="search-box flex ai-center"> <view class="search-box flex ai-center">
<input type="text" v-model="keyword" placeholder="搜索商品" placeholder-style="color:#999" <input
@confirm="search()"/> v-model="keyword"
<image :src="webUrl+'/20231223183627184005.png'" mode="scaleToFill" style="width:30rpx;height:30rpx"/> type="text"
placeholder="搜索商品"
placeholder-style="color:#999"
@confirm="search()"
/>
<image
:src="webUrl+'/20231223183627184005.png'"
mode="scaleToFill"
style="width:30rpx;height:30rpx"
@click="search()"
/>
</view> </view>
<view class="map-box"> <view class="map-box">
+36 -14
View File
@@ -292,8 +292,11 @@
<image class="logo" :src="systemStore.image" mode="scaleToFill"/> <image class="logo" :src="systemStore.image" mode="scaleToFill"/>
{{ systemStore.name }} {{ systemStore.name }}
</view> </view>
<view class="value flex ai-center" style="color:#DA0000" @click="goStore">进店逛逛 <view
<uni-icons type="right" size="12" color="#DA0000"></uni-icons> class="flex ai-center store-btn"
@click="goStore"
>
进店逛逛
</view> </view>
</view> </view>
@@ -437,17 +440,36 @@
</view> </view>
<view class="bnt acea-row row-middle row-right" <view
style="background: transparent !important;border-radius: 0 !important;"> class="bnt acea-row row-middle row-right"
<view class="btn-car" :class="{'btn-car-disabled':isOpen === true && attr.productSelect.stock === 0}" style="background: transparent !important;border-radius: 0 !important;"
@click="joinCart">加入购物车 >
<view
class="btn-car"
:class="{
'btn-car-disabled': attr.productSelect.stock === 0
}"
@click="joinCart"
>
加入购物车
</view> </view>
<view class="btn-buy" :class="{'btn-buy-disabled':isOpen === true && attr.productSelect.stock === 0}" <view
@click="tapBuy">立即购买 class="btn-buy"
:class="{
'btn-buy-disabled': attr.productSelect.stock === 0
}"
@click="tapBuy"
>
立即购买
</view> </view>
</view> </view>
</view> </view>
<ProductWindow v-on:changeFun="changeFun" :attr="attr" :cartNum="cart_num"/> <ProductWindow
v-on:changeFun="changeFun"
:attr="attr"
:product-value="productValue"
:cartNum="cart_num"
/>
<StorePoster v-on:setPosterImageStatus="setPosterImageStatus" :posterImageStatus="posterImageStatus" <StorePoster v-on:setPosterImageStatus="setPosterImageStatus" :posterImageStatus="posterImageStatus"
:posterData="posterData" :goodId="id"></StorePoster> :posterData="posterData" :goodId="id"></StorePoster>
<ShareInfo v-on:setShareInfoStatus="setShareInfoStatus" :shareInfoStatus="shareInfoStatus"></ShareInfo> <ShareInfo v-on:setShareInfoStatus="setShareInfoStatus" :shareInfoStatus="shareInfoStatus"></ShareInfo>
@@ -1175,13 +1197,13 @@ export default {
}, },
// 点击加入购物车按钮 // 点击加入购物车按钮
joinCart: function () { joinCart: function () {
if (this.isOpen === true && this.attr.productSelect.stock === 0) return; if (this.attr.productSelect.stock === 0) return;
//0=加入购物车 //0=加入购物车
this.goCat(0); this.goCat(0);
}, },
//立即购买; //立即购买;
tapBuy: function () { tapBuy: function () {
if (this.isOpen === true && this.attr.productSelect.stock === 0) return; if (this.attr.productSelect.stock === 0) return;
// 1=直接购买 // 1=直接购买
this.goCat(1); this.goCat(1);
}, },
@@ -1580,8 +1602,8 @@ export default {
} }
.btn-car-disabled { .btn-car-disabled {
border: 2rpx solid #D0D0D0; border: 2rpx solid #707070;
color: #D0D0D0; color: #707070;
} }
.btn-buy { .btn-buy {
@@ -1594,7 +1616,7 @@ export default {
} }
.btn-buy-disabled { .btn-buy-disabled {
background: #D0D0D0; background: #9D9D9D;
} }
} }
+5 -12
View File
@@ -68,16 +68,7 @@
</view> </view>
</view> </view>
</view> </view>
<!-- <Loading :loaded="loadend" :loading="loading"></Loading>--> <no-good-data v-if="productList.length === 0 && where.page > 1" />
<view
class="noCommodity"
style="background-color: #fff;"
v-if="productList.length === 0 && where.page > 1"
>
<view class="noPictrue">
<image :src="webUrl+'/20210203153900181449.png'" class="image"/>
</view>
</view>
<Recommend v-if="productList.length === 0 && where.page > 1"></Recommend> <Recommend v-if="productList.length === 0 && where.page > 1"></Recommend>
</view> </view>
</template> </template>
@@ -85,15 +76,15 @@
<script> <script>
import Recommend from "@/components/Recommend"; import Recommend from "@/components/Recommend";
import {getProducts} from "@/api/store"; import {getProducts} from "@/api/store";
import Loading from "@/components/Loading";
import {mapGetters} from 'vuex'; import {mapGetters} from 'vuex';
import NP from "number-precision"; import NP from "number-precision";
import NoGoodData from '@/components/good/NoData'
export default { export default {
name: "GoodsList", name: "GoodsList",
components: { components: {
Recommend, Recommend,
Loading NoGoodData
}, },
props: {}, props: {},
computed: mapGetters(["userInfo"]), computed: mapGetters(["userInfo"]),
@@ -314,6 +305,8 @@ export default {
<style scoped lang="less"> <style scoped lang="less">
.noCommodity { .noCommodity {
display: flex;
justify-content: center;
border-top: 3px solid #f5f5f5; border-top: 3px solid #f5f5f5;
padding-bottom: 1px; padding-bottom: 1px;
} }
+502 -894
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+303
View File
@@ -0,0 +1,303 @@
<template>
<view class="container" :style="{height: height}">
<editor
class="ql-container"
:placeholder="placeholder"
:show-img-size="true"
:show-img-toolbar="true"
:show-img-resize="true"
@ready="onEditorReady"
id="editor"
@statuschange="statuschange"
@focus="editFocus"
@blur="editBlur"
ref="editot"
></editor>
<!-- 操作工具 -->
<view class="tool-view" >
<!-- 文字相关操作 -->
<view class="font-more" :style="{ height: showMoreTool ? '100rpx' : 0 }">
<jinIcon class="single" type="&#xe6e7;" title="加粗" @click="setBold" :color="showBold ? activeColor : '#666666'"></jinIcon>
<jinIcon class="single" type="&#xe6fe;" title="斜体" @click="setItalic" :color="showItalic ? activeColor : '#666666'"></jinIcon>
<jinIcon class="single" type="&#xe6f8;" title="分割线" @click="setIns" :color="showIns ? activeColor : '#666666'"></jinIcon>
<jinIcon class="single" type="&#xe6e3;" title="标题" @click="setHeader" :color="showHeader ? activeColor : '#666666'"></jinIcon>
<jinIcon class="single" type="&#xe6f1;" title="居中" @click="setCenter" :color="showCenter ? activeColor : '#666666'"></jinIcon>
<jinIcon class="single" type="&#xe6ed;" title="居右" @click="setRight" :color="showRight ? activeColor : '#666666'"></jinIcon>
</view>
<view class="setting-layer-mask" v-if="showSettingLayer" @click="showSetting"></view>
<view class="setting-layer" v-if="showSettingLayer">
<view class="single" @click="release(true)">
<jinIcon class="icon" type="&#xe639;" ></jinIcon>
<view>公开发布</view>
</view>
<view class="single" @click="release(false)">
<jinIcon class="icon" type="&#xe655;" ></jinIcon>
<view>暂时保存</view>
</view>
</view>
<view class="tool">
<!-- <jinIcon class="single" type="&#xe6f3;" title="图片" @click="insertImage"></jinIcon> -->
<jinIcon class="single" type="&#xe6f9;" title="格式" @click="showMore" :color="showMoreTool ? activeColor : '#666666'"></jinIcon>
<jinIcon class="single" type="&#xe6eb;" title="分割线" @click="insertDivider"></jinIcon>
<jinIcon class="single" type="&#xe6e8;" title="撤回" @click="undo"></jinIcon>
<jinIcon class="single" type="&#xe705;" title="还原" @click="redo"></jinIcon>
<!-- <jinIcon class="single" type="&#xeb8a;" title="设置" @click="showSetting"></jinIcon> -->
</view>
</view>
</view>
</template>
<script>
import jinIcon from './jin-icons.vue';
export default {
props: {
// 点击图片时显示图片大小控件
showImgSize: {
type: Boolean,
default: false
},
// 点击图片时显示工具栏控件
showImgToolbar: {
type: Boolean,
default: false
},
// 点击图片时显示修改尺寸控件
showImgResize: {
type: Boolean,
default: false
},
// 占位符
placeholder: {
type: String,
default: '开始输入...'
},
// 图片上传的地址
uploadFileUrl: {
type: String,
default: '#'
},
// 上传文件时的name
fileKeyName: {
type: String,
default: 'file'
},
// 上传图片时,http请求的header
header: {
type: Object
},
// 初始化html
html: {
type: String
},
// 整个控件的高度
height: {
type: String,
default: '25vh'
}
},
computed:{
},
data() {
return {
showMoreTool: false,
showBold: false,
showItalic: false,
showIns: false,
showHeader: false,
showCenter: false,
showRight: false,
showSettingLayer: false,
activeColor: '#F56C6C'
};
},
components: {
jinIcon
},
mounted() {
},
methods: {
onEditorReady(e) {
uni.createSelectorQuery()
.in(this)
.select('.ql-container')
.fields({
size: true,
context: true
},res => {
this.editorCtx = res.context;
this.editorCtx.setContents({
html: this.html
})
})
.exec();
},
undo() {
this.editorCtx.undo();
},
/// 插入分割线
insertDivider() {
this.editorCtx.insertDivider();
},
redo() {
this.editorCtx.redo();
},
showMore() {
this.showMoreTool = !this.showMoreTool;
this.editorCtx.setContents()
},
setBold() {
this.showBold = !this.showBold;
this.editorCtx.format('bold');
},
setItalic() {
this.showItalic = !this.showItalic;
this.editorCtx.format('italic');
},
checkStatus(name, detail, obj) {
if (detail.hasOwnProperty(name)) {
this[obj] = true;
} else {
this[obj] = false;
}
},
statuschange(e) {
var detail = e.detail;
this.checkStatus('bold', detail, 'showBold');
this.checkStatus('italic', detail, 'showItalic');
this.checkStatus('ins', detail, 'showIns');
this.checkStatus('header', detail, 'showHeader');
if (detail.hasOwnProperty('align')) {
if (detail.align == 'center') {
this.showCenter = true;
this.showRight = false;
} else if (detail.align == 'right') {
this.showCenter = false;
this.showRight = true;
} else {
this.showCenter = false;
this.showRight = false;
}
} else {
this.showCenter = false;
this.showRight = false;
}
},
setIns() {
this.showIns = !this.showIns;
this.editorCtx.format('ins');
},
setHeader() {
this.showHeader = !this.showHeader;
this.editorCtx.format('header', this.showHeader ? 'H2' : false);
},
setCenter() {
this.showCenter = !this.showCenter;
this.editorCtx.format('align', this.showCenter ? 'center' : false);
},
setRight() {
this.showRight = !this.showRight;
this.editorCtx.format('align', this.showRight ? 'right' : false);
},
showSetting() {
this.showSettingLayer = !this.showSettingLayer;
},
async editFocus(e) {
},
editBlur(e) {
this.editorCtx.getContents({
success: res => {
this.$emit('editOk', res);
}
})
},
release(isPublic) {
this.showSettingLayer = false;
this.editorCtx.getContents({
success: res => {
Object.assign(res, {
isPublic: isPublic
})
this.$emit('editOk', res);
}
})
},
}
};
</script>
<style scoped>
.container {
box-sizing: border-box;
display: flex;
flex-direction: column;
height: 100%;
box-sizing: border-box;
/* padding-top: 30rpx; */
}
.ql-container {
line-height: 150%;
font-size: 22rpx;
width: 100%;
height: 240px;
background: #fff;
margin: 0 auto;
flex: 1;
box-sizing: border-box;
/* padding-bottom: 5rpx; */
}
.tool-view{
width: 100%;
background: #eee;
/* margin-top: 20px; */
}
.tool {
height: 95rpx;
display: flex;
align-items: center;
justify-content: space-around;
width: 100%;
}
.font-more {
display: flex;
align-items: center;
justify-content: space-around;
width: 100%;
background: rgb(235, 235, 235);
overflow: hidden;
transition: all 0.15s;
}
.setting-layer {
position: absolute;
bottom: 100rpx;
background: #fff;
width: 250rpx;
right: 20rpx;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
border-radius: 8rpx;
}
.setting-layer .single {
height: 80rpx;
font-size: 32rpx;
padding: 0 30rpx;
display: flex;
align-items: center;
line-height: 80rpx;
flex-direction: row;
color: #666;
}
.setting-layer .single .icon {
margin-right: 20rpx;
}
.setting-layer-mask{
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background: transparent;
}
</style>
@@ -0,0 +1,71 @@
<template>
<view class="content">
<view
class="icon"
:style="{color: color, fontSize: fontSize}"
v-html="type"
@click="toclick"
></view>
<view class="desc">{{ title }}</view>
</view>
</template>
<script>
export default {
props: {
type: {
type: String,
default: '&#xe644;'
},
color: {
type: String,
default: '#666666'
},
fontSize: {
type: String,
default: '32rpx'
},
title: {
type: String,
default: '说明'
}
},
methods: {
toclick() {
this.$emit('click');
}
}
}
</script>
<style scoped>
.content{
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 80upx;
min-width: 60px;
padding-bottom: 15upx;
}
.content .desc {
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
font-size: 8px;
color: #666;
line-height: 8px;
transform: translateY(-8px);
}
@font-face {
font-family: 'jin';
/** 阿里巴巴矢量图标库的字体库地址,可以替换自己的字体库地址 **/
src: url('https://at.alicdn.com/t/font_1491431_6m7ltjo8wi.ttf') format('truetype');
}
.icon {
font-family: jin !important;
}
</style>
+65
View File
@@ -0,0 +1,65 @@
## jin-edit 基于editor的富文本编辑器
### 兼容性
这是一个uni-app的通用组件,兼容微信小程序端、安卓端、ios端(未测试)、H5端。作者因没有ios设备无法对ios端进行测试,其他端测试无问题。
微信小程序 | APP | H5
:--: | :--: | :--:
√ | √ | √
我的HbuilderX版本2.6.7,不同的版本可能会造成不兼容的问题。
### 使用方式
1. 将此组件进入你的项目中的 /components/ 目录中
2. 在某个页面中使用该插件
-`script` 中引用组件
```javascript
import jinEdit from '../../components/jin-edit/jin-edit.vue';
export default {
data() {
return {
}
},
components: {
jinEdit
},
methods: {
// 点击发布
editOk(res) {
console.log(res);
}
}
}
```
-`template` 中使用组件
```html
<jinEdit placeholder="请输入内容" @editOk="editOk" uploadFileUrl="/#"></jinEdit>
```
### Demo
[uni-jin(一个uni-app组件集合)](https://github.com/wangjinxin613/uni-jin)
### 参数
属性 | 类型 | 默认值 | 说明
:--: | :--: | :--: | :--:
showImgSize | Boolean | false | 点击图片时显示图片大小控件
showImgToolbar | Boolean | false | 点击图片时显示工具栏控件
showImgResize | Boolean | false | 点击图片时显示修改尺寸控件
placeholder | String | '' | 编辑器占位符
uploadFileUrl | String | '#' | 图片上传的服务器地址
fileKeyName | String | 'file' | 图片上传时的name
header | Object | - | 图片上传http请求的header
html | String | - | 初始化的html
### 方法
方法名 | 参数 | 说明
:--: | :--: | :--:
editOk | e={html,text,delta,isPublic} | 点击发布按钮触发
以上
+193
View File
@@ -0,0 +1,193 @@
<template>
<view class="container">
<view v-if="isLoad">
<view class="goods-section flex flex-wrap">
<view
v-for="(item,index) in goodsList"
:key="index"
class="item"
@click="goGoodsConByID(item)"
>
<image
:src="item.image"
class="cover"
/>
<view class="">
<view class="name more-t">{{ item.storeName }}</view>
<view class="price-line flex ai-center">
<image
:src="webUrl + '/20221118104357701129.png'"
class="label"
mode="scaleToFill"
/>
<text>{{ item.price }}</text>
</view>
</view>
<view class="sales-line flex ai-center">
<image
:src="webUrl + '/20221118092713277343.png'"
class="icon"
mode="scaleToFill"
/>
<text>{{ item.sales }}人已购买</text>
</view>
</view>
</view>
<view
v-if="loading"
class="loading-txt"
>
加载中...
</view>
<view
v-if="page >= totalPage"
class="loading-txt"
>
已经到底了
</view>
</view>
<goo-skeleton v-else />
</view>
</template>
<script>
import {
getHotelGoodList
} from "@/api/inn.js";
import imgBox from '@/components/imageTypeSet/imagebox.vue'
import GooSkeleton from '@/components/GooSkeleton/index.vue'
export default {
components: {
imgBox,
GooSkeleton
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
isLoad: false,
loading: false,
page: 1,
totalPage: 1,
goodsList: [],
id: null,
}
},
onLoad(options) {
if (options.id) {
this.id = options.id || null;
this.fetchGoods()
}
},
onReachBottom() {
if (this.page >= this.totalPage) {
return
}
if (!this.loading) {
this.page++
this.fetchGoods()
}
},
methods: {
goGoodsConByID(item) {
this.$yrouter.push({
path: '/pages/shop/GoodsCon/index',
query: {
id: item.id
}
})
},
fetchGoods() {
this.loading = true
getHotelGoodList({
id: this.id,
page: this.page,
limit: 10
}).then(res => {
const { success, data } = res
if (success) {
this.isLoad = true
this.totalPage = data.pages
const len = data.records.length
if (len > 0) {
for (let i = 0; i < len; i++) {
this.goodsList.push(data.records[i])
}
}
}
}).finally(() => {
this.loading = false
})
}
}
}
</script>
<style scoped lang="less">
@import "@/assets/css/store.less";
.goods-section {
padding: 40rpx 32rpx 0;
.item {
position: relative;
width: 332rpx;
height: 528rpx;
box-sizing: border-box;
margin-right: 22rpx;
margin-bottom: 24rpx;
border-radius: 8rpx;
background: #fff;
.name {
padding: 8rpx 6rpx;
font-size: 26rpx;
line-height: 36rpx;
color: #333333;
}
.price-line {
padding: 0 10rpx;
font-size: 26rpx;
line-height: 38rpx;
color: #ED0F0F;
}
.sales-line {
position: absolute;
bottom: 0;
width: 100%;
padding: 8rpx 10rpx 18rpx;
border-top: 1rpx solid #EFEFEF;
font-size: 24rpx;
line-height: 34rpx;
color: #8D8D8D;
}
}
.item:nth-child(2n) {
margin-right: 0;
}
.cover {
width: 332rpx;
height: 332rpx;
background: rgba(255, 255, 255, 0.39);
border-radius: 8rpx;
vertical-align: middle;
}
.label {
width: 40rpx;
height: 24rpx;
margin-right: 4rpx;
vertical-align: middle;
}
.icon {
width: 24rpx;
height: 24rpx;
margin-right: 6rpx;
vertical-align: middle;
}
}
.container {
position: relative;
background: #F5F5FA;
}
.loading-txt {
padding: 30rpx 0;
color: #999;
text-align: center;
}
</style>
+891 -694
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -20,7 +20,7 @@
</view> </view>
<view class="video-box" v-if="info.type==='NT_VIDEO'"> <view class="video-box" v-if="info.type==='NT_VIDEO'">
<video style="width: 100%;height: 320rpx;" :src="info.resources[0]" controls play-btn-position="center"/> <video style="width: 100%;height: 320rpx;" :src="info.video" controls play-btn-position="center"/>
</view> </view>
<view class="content-box"> <view class="content-box">
+92 -39
View File
@@ -1,38 +1,69 @@
<template> <template>
<view class="page-info-publish"> <view class="page-info-publish">
<view class="tab-box flex jc-center"> <view class="tab-box flex jc-center">
<text :class="{'active':tabIndex==index}" v-for="(item,index) in tabData" :key="item" <text
@click="changeTab(index)">{{item.label}}</text> v-for="(item,index) in tabData"
:key="item"
:class="{
'active': tabIndex === index
}"
@click="changeTab(index)"
>{{item.label}}</text>
</view> </view>
<form @submit="formSubmit"> <form @submit="formSubmit">
<view class="form-item"> <view class="form-item">
<view class="title">标题:</view> <view class="title">标题:</view>
<input v-model="title" type="text" placeholder="请输入动态标题..." <input
placeholder-style="font-size:24rpx;color:#C2C5CC;" /> v-model="form.title"
type="text"
placeholder="请输入动态标题..."
placeholder-style="font-size:24rpx;color:#C2C5CC;"
class="inp inp-input"
/>
</view> </view>
<view class="form-item"> <view class="form-item">
<textarea class="content-style" v-model="content" placeholder="请输入动态内容..." <view class="title">简介:</view>
placeholder-style="font-size:24rpx;color:#C2C5CC;" /> <textarea
v-model="form.intro"
placeholder="请输入简介..."
placeholder-style="font-size:24rpx;color:#C2C5CC;"
class="content-style inp"
/>
</view> </view>
<view class="form-item" v-if="showUpload"> <view class="form-item" v-if="showUpload">
<tm-upload :dataList="picsArray" :upload_img_wh="uploadImgWH" :upload_max="uploadMax" :url="uploadUrl" :type='uploadType' <view v-if="uploadType === 'image'" class="title">图片(最多9张):</view>
:header="uploadHeader" @change="uploadedImgChange" /> <view v-else class="title">视频:</view>
<tm-upload
:dataList="picsArray"
:upload_img_wh="uploadImgWH"
:upload_max="uploadMax"
:url="uploadUrl"
:type='uploadType'
:header="uploadHeader"
@change="uploadedImgChange"
/>
</view>
<view class="form-item">
<view class="title">资讯详情:</view>
<view class="inp">
<jin-edit
:html="form.content"
placeholder="请输入内容"
height="320px"
@editOk="editOk"
/>
</view>
</view> </view>
<view class="form-btn"> <view class="form-btn">
<button form-type="submit">发布</button> <button form-type="submit">发布</button>
</view> </view>
</form> </form>
</view> </view>
</template> </template>
<script> <script>
import tmUpload from '@/pagesInn/components/tm-upload/tm-upload.vue'; import tmUpload from '@/pagesInn/components/tm-upload/tm-upload.vue';
import jinEdit from '@/pagesInn/components/jin-edit/jin-edit.vue';
import { import {
VUE_APP_API_URL VUE_APP_API_URL
} from "@/config"; } from "@/config";
@@ -41,7 +72,8 @@
} from "@/api/inn.js"; } from "@/api/inn.js";
export default { export default {
components: { components: {
tmUpload tmUpload,
jinEdit
}, },
data() { data() {
return { return {
@@ -73,8 +105,11 @@
} }
], ],
tabIndex: 0, tabIndex: 0,
title: "", form: {
content: "" title: '',
intro: '',
content: ''
}
} }
}, },
onLoad(option) { onLoad(option) {
@@ -83,46 +118,48 @@
methods: { methods: {
changeTab(index) { changeTab(index) {
this.tabIndex = index; this.tabIndex = index;
this.showUpload=false; this.showUpload = false;
this.uploadType= this.tabData[index].uploadType; this.uploadType = this.tabData[index].uploadType;
this.uploadCount= this.tabData[index].uploadCount; this.uploadCount = this.tabData[index].uploadCount;
setTimeout(()=>{ setTimeout(()=>{
this.showUpload=true; this.showUpload = true;
},100) },100)
}, },
editOk(res) {
this.form.content = res.html
},
//文件上传结果 //文件上传结果
uploadedImgChange: function(uploadedFilesList) { uploadedImgChange: function(uploadedFilesList) {
this.uploadedFilesArray = uploadedFilesList; this.uploadedFilesArray = uploadedFilesList;
}, },
formSubmit(e) { formSubmit(e) {
if (this.title.length == 0) { if (!this.form.title) {
this.$dialog.error("请输入动态标题"); this.$dialog.error("请输入动态标题");
return; return;
} }
if (!this.form.intro) {
if (this.content.length == 0) { this.$dialog.error("请输入简介");
this.$dialog.error("请输入动态内容"); return;
}
if (!this.form.content) {
this.$dialog.error("请输入资讯详情");
return; return;
} }
if (this.uploadedFilesArray.length == 0) { if (this.uploadedFilesArray.length == 0) {
this.$dialog.error("请上传动态图片或视频"); this.$dialog.error("请上传动态图片或视频");
return; return;
} }
let param = {
hotelId: this.hotelId,
name: this.title,
content: this.content,
type: this.tabData[this.tabIndex].type,
resources: this.uploadedFilesArray.join(",")
};
uni.showLoading(); uni.showLoading();
postHotelNewsAdd(param).then(res => { postHotelNewsAdd({
hotelId: this.hotelId,
name: this.form.title,
intro: this.form.intro,
content: this.form.content,
type: this.uploadType === 'image' ? 'NT_TEXT' : 'NT_VIDEO',
resources: this.uploadType === 'image' ? this.uploadedFilesArray : [],
video: this.uploadType === 'image' ? '' : this.uploadedFilesArray[0]
}).then(res => {
uni.hideLoading(); uni.hideLoading();
this.$dialog.toast({ this.$dialog.toast({
mes: "发布成功!" mes: "发布成功!"
@@ -141,6 +178,7 @@
<style lang="scss"> <style lang="scss">
.page-info-publish { .page-info-publish {
padding: 0 0 80rpx 0;
font-size: 28rpx; font-size: 28rpx;
.tab-box { .tab-box {
@@ -173,10 +211,25 @@
background: #fff; background: #fff;
.content-style { .content-style {
width: 100%;
height: 200rpx; height: 200rpx;
color: #C2C5CC; box-sizing: border-box;
color: #333;
font-size: 28rpx; font-size: 28rpx;
} }
.inp {
padding: 10rpx 16rpx;
border: 1px solid #eee;
border-radius: 6rpx;
}
.inp-input {
padding: 0 16rpx;
height: 76rpx;
line-height: 76rpx;
}
.title {
margin: 0 0 10rpx 0;
}
} }
.form-btn { .form-btn {
+199 -197
View File
@@ -1,25 +1,30 @@
<template> <template>
<view class="container"> <view class="container">
<view class="base-info-section">
<view class="base-info-section" style="margin-bottom: 86rpx;margin-bottom: 86rpx;"> <view
<!-- <text class="section-title">详细信息</text> --> class="item is_required"
<view class="item is_required" @click="chooseLogoImg()"> @click="chooseLogoImg()"
>
<view class="cell acea-row row-between row-middle"> <view class="cell acea-row row-between row-middle">
<view class="cell-title">店铺LOGO</view> <view class="cell-title">店铺LOGO</view>
<view class=""> <view>
<image style="width: 64rpx;height: 64rpx;" <image
:src="innApplyInfo.logo.length>0?innApplyInfo.logo:webUrl+'/20210228103411271415.png'" :src="innApplyInfo.logo ? innApplyInfo.logo : webUrl + '/20210228103411271415.png'"
mode=""></image> class="img-item"
/>
</view> </view>
</view> </view>
<text class="iconfont icon-jiantou"></text> <text class="iconfont icon-jiantou"></text>
</view> </view>
<view class="item is_required"> <view class="item is_required">
<view class="cell acea-row row-between row-middle"> <view class="cell acea-row row-between row-middle">
<view class="cell-title">店铺类型</view> <view class="cell-title">店铺类型</view>
<view class="cell-value"> <view class="cell-value">
<picker :value="typeIndex" @change="typePickerChange" :range="typeRange"> <picker
:value="typeIndex"
:range="typeRange"
@change="typePickerChange"
>
<view style="text-align: right;font-size:24rpx;color:#C2C5CC;" v-if="typeList.length>0"> <view style="text-align: right;font-size:24rpx;color:#C2C5CC;" v-if="typeList.length>0">
{{ typeList[typeIndex].name }} {{ typeList[typeIndex].name }}
</view> </view>
@@ -29,97 +34,110 @@
</view> </view>
<text class="iconfont icon-jiantou"></text> <text class="iconfont icon-jiantou"></text>
</view> </view>
<view v-if="innApplyInfo.coverType === 1" class="item is_required" @click="chooseCoverImg()">
<view class="item is_required" @click="chooseCoverImg()">
<view class="cell acea-row row-between row-middle"> <view class="cell acea-row row-between row-middle">
<view class="cell-title">封面照片</view> <view class="cell-title">封面照片</view>
<view class=""> <view>
<image style="width: 64rpx;height: 64rpx;" <image
:src="innApplyInfo.cover.length>0?innApplyInfo.cover:webUrl+'/20210228103411271415.png'" :src="innApplyInfo.cover ? innApplyInfo.cover : webUrl + '/20210228103411271415.png'"
mode=""></image> class="img-item"
/>
</view>
</view>
<text class="iconfont icon-jiantou"></text>
</view>
<view v-if="innApplyInfo.coverType === 2" class="item is_required" @click="chooseLogoVideo()">
<view class="cell acea-row row-between row-middle">
<view class="cell-title">封面视频</view>
<view>
<video
:src="innApplyInfo.coverVideo"
:poster="innApplyInfo.coverVideo + '?vframe/jpg/offset/1'"
:controls="false"
play-btn-position="center"
class="video-item"
/>
</view> </view>
</view> </view>
<text class="iconfont icon-jiantou"></text> <text class="iconfont icon-jiantou"></text>
</view> </view>
<view class="item" @click="chooseQrcodeImg()"> <view class="item" @click="chooseQrcodeImg()">
<view class="cell acea-row row-between row-middle"> <view class="cell acea-row row-between row-middle">
<view class="cell-title">微信二维码</view> <view class="cell-title">微信二维码</view>
<view class=""> <view>
<image style="width: 64rpx;height: 64rpx;" <image
:src="innApplyInfo.qrcode.length>0?innApplyInfo.qrcode:webUrl+'/20210228103411271415.png'" :src="innApplyInfo.qrcode ? innApplyInfo.qrcode : webUrl + '/20210228103411271415.png'"
mode=""></image> class="img-item"
/>
</view> </view>
</view> </view>
<text class="iconfont icon-jiantou"></text> <text class="iconfont icon-jiantou"></text>
</view> </view>
<view class="item is_required"> <view class="item is_required">
<view class="cell acea-row row-between row-middle"> <view class="cell acea-row row-between row-middle">
<view class="cell-title">店主名字</view> <view class="cell-title">店主名字</view>
<view class="cell-value" style="text-align: right;"> <view class="cell-value">
<input type="text" v-model="innApplyInfo.ownerName" placeholder="请输入店主名字" <input
placeholder-style="font-size:24rpx;color:#C2C5CC;"/> v-model="innApplyInfo.ownerName"
type="text"
placeholder="请输入店主名字"
placeholder-style="font-size:24rpx;color:#C2C5CC;"
/>
</view> </view>
</view> </view>
</view> </view>
<!-- <view class="item is_required">-->
<!-- <view class="cell acea-row row-between row-middle">-->
<!-- <view class="cell-title">关键词</view>-->
<!-- <view class="cell-value" style="text-align: right;">-->
<!-- <input type="text" v-model="innApplyInfo.tips" placeholder="店主想对游客说的话" placeholder-style="font-size:24rpx;color:#C2C5CC;" />-->
<!-- </view>-->
<!-- </view>-->
<!-- </view>-->
<view class="item is_required"> <view class="item is_required">
<view class="cell acea-row row-between row-middle"> <view class="cell acea-row row-between row-middle">
<view class="cell-title">一句话介绍</view> <view class="cell-title">一句话介绍</view>
<view class="cell-value" style="text-align: right;"> <view class="cell-value">
<input type="text" v-model="innApplyInfo.content" placeholder="店铺风格一句话描述" <input
placeholder-style="font-size:24rpx;color:#C2C5CC;"/> v-model="innApplyInfo.content"
type="text"
placeholder="店铺风格一句话描述"
placeholder-style="font-size:24rpx;color:#C2C5CC;"
/>
</view> </view>
</view> </view>
</view> </view>
<view class="item is_required"> <view class="item is_required">
<view class="cell acea-row row-column"> <view class="cell acea-row row-column">
<view class="cell-title">店铺简介</view> <view class="cell-title">店铺简介</view>
<view class=""> <view>
<textarea style="height: 200rpx;color:#C2C5CC;" v-model="innApplyInfo.desc" placeholder="请输入店铺简介..." <textarea
placeholder-style="font-size:24rpx;color:#C2C5CC;"/> v-model="innApplyInfo.desc"
placeholder="请输入店铺简介..."
placeholder-style="font-size:24rpx;color:#C2C5CC;"
class="inp-textarea"
/>
</view> </view>
</view> </view>
</view> </view>
<view class="item"> <view class="item">
<view class="img-upload"> <view class="img-upload">
<tm-upload <tm-upload
:dataList="picsArray" :dataList="picsArray"
:upload_img_wh="uploadImgWH" :upload_img_wh="(750 - 3 * 16 - 2 * 32) / 3.0"
:upload_max="uploadMax" :upload_max="10"
:url="uploadUrl" :url="uploadUrl"
:header="uploadHeader" :header="uploadHeader"
@change="uploadedImgChange"/> @change="uploadedImgChange"
/>
</view> </view>
</view> </view>
</view> </view>
<view class="submit-btn" @tap="submit">确定修改</view> <view class="submit-btn" @tap="submit">确定修改</view>
</view> </view>
</template> </template>
<script> <script>
import CitySelect from "@/components/CitySelect"; import CitySelect from '@/components/CitySelect'
import tmUpload from '@/pagesInn/components/tm-upload/tm-upload.vue'; import tmUpload from '@/pagesInn/components/tm-upload/tm-upload.vue'
import {chooseImage} from "@/utils"; import {
import {VUE_APP_API_URL} from "@/config" chooseImage,
import {getHotelTypeList, postHotelInfoEdit} from "@/api/inn.js"; chooseVideoToUpload
} from '@/utils'
var that; import {VUE_APP_API_URL} from '@/config'
import {getHotelTypeList, postHotelInfoEdit} from '@/api/inn.js'
export default { export default {
components: { components: {
CitySelect, CitySelect,
@@ -129,190 +147,164 @@ export default {
return { return {
webUrl: this.$VUE_APP_RESOURCES_URL, webUrl: this.$VUE_APP_RESOURCES_URL,
uploadUrl: VUE_APP_API_URL + '/api/upload', uploadUrl: VUE_APP_API_URL + '/api/upload',
uploadImgWH: (750 - 3 * 16 - 2 * 32) / 3.0,
uploadHeader: { uploadHeader: {
Authorization: "Bearer " + this.$store.getters.token Authorization: 'Bearer ' + this.$store.getters.token
}, },
innHistory: {},//历史信息 innHistory: {}, // 历史信息
picsArray: [], picsArray: [],
typeList: [],//类型列表 typeList: [], // 类型列表
typeIndex: 0,//选中的类型 typeIndex: 0, // 选中的类型
typeRange: [],//类型数据源 typeRange: [], // 类型数据源
uploadedFilesArray: [], uploadedFilesArray: [],
uploadMax: 10,
innApplyInfo: { innApplyInfo: {
"address": "", 'address': '',
"areaId": 0, 'areaId': 0,
"cityId": 0, 'cityId': 0,
"provinceId": 0, 'provinceId': 0,
"content": "", 'content': '',
"cover": "", 'cover': '',
"desc": "", 'coverType': 1, // coverType: 1-图片,2-视频
"logo": "", 'desc': '',
"name": "", 'logo': '',
"ownerName": "", 'name': '',
"pics": [], 'ownerName': '',
"position": "", 'pics': [],
"tel": "", 'position': '',
"qrcode": "", 'tel': '',
"tips": "", 'qrcode': '',
"type": "", 'tips': '',
'type': ''
} }
} }
}, },
onShow: function () { onShow() {
this.getHotelType(); this.getHotelType()
}, },
onLoad: function (e) { onLoad(options) {
that = this; const id = options.id
if (e.hotel) { if (id) {
//赋值 // 赋值
var hotel = JSON.parse(decodeURIComponent(e.hotel)); const hotel = JSON.parse(uni.getStorageSync('MY_HOTEL_INFO'))
this.innHistory = hotel; this.innHistory = hotel
this.fillData(this.innApplyInfo, this.innHistory)
this.fillData(this.innApplyInfo, this.innHistory); if (hotel.coverType === 2) {
this.innApplyInfo.coverVideo = hotel.cover
//Object.assign(this.innApplyInfo,hotel); } else {
this.innApplyInfo.coverVideo = ''
}
//this.addressText = this.innHistory.provinceName+" "+this.innHistory.cityName+" "+this.innHistory.areaName; // 图片填充
//图片填充
this.picsArray = hotel.pics.map(function (item) { this.picsArray = hotel.pics.map(function (item) {
var obj = { return {
path: item, path: item,
upload_percent: 100 upload_percent: 100
} }
return obj; })
});
} }
}, },
methods: { methods: {
typePickerChange: function (e) { typePickerChange: function (e) {
this.typeIndex = e.target.value; this.typeIndex = e.target.value
// 修改type
//修改type
if (this.typeList.length > 0) { if (this.typeList.length > 0) {
this.$set(this.innApplyInfo, 'type', this.typeList[this.typeIndex].id); this.$set(this.innApplyInfo, 'type', this.typeList[this.typeIndex].id)
} }
}, },
getHotelType: function () { getHotelType() {
const _this = this
getHotelTypeList().then((res) => { getHotelTypeList().then((res) => {
that.typeList = res.data; _this.typeList = res.data
// 构建数据源
//构建数据源 _this.typeRange = [];
that.typeRange = []; _this.typeList.forEach((item, index) => {
that.typeList.forEach((item, index) => { _this.typeRange.push(item.name)
that.typeRange.push(item.name); })
}); // 重新填写模式预填充type
const len = this.typeList.length
//重新填写模式预填充type
let len = this.typeList.length;
if (len > 0) { if (len > 0) {
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
if (this.typeList[i].id === this.innHistory.type) this.typeIndex = i; if (this.typeList[i].id === this.innHistory.type) this.typeIndex = i
} }
} }
}).catch((err) => {
}).finally(() => {
}) })
}, },
fillData: function (target, source) { fillData: function (target, source) {
//var keys = Object.keys(target);
//this.uploadedFilesArray = source.pics;
Object.keys(target).forEach((value, key) => { Object.keys(target).forEach((value, key) => {
target[value] = source[value]; target[value] = source[value]
// console.log('key:'+value); })
});
}, },
//文件上传结果 // 文件上传结果
uploadedImgChange: function (uploadedFilesList) { uploadedImgChange: function (uploadedFilesList) {
this.uploadedFilesArray = uploadedFilesList; this.uploadedFilesArray = uploadedFilesList
}, },
chooseQrcodeImg: function () { chooseQrcodeImg() {
chooseImage(img => { chooseImage(img => {
that.$set(that.innApplyInfo, 'qrcode', img); this.$set(this.innApplyInfo, 'qrcode', img)
}); })
}, },
chooseLogoImg: function () { chooseLogoImg() {
chooseImage(img => { chooseImage(img => {
that.innApplyInfo.logo = img; this.$set(this.innApplyInfo, 'logo', img)
}); })
}, },
chooseCoverImg: function () { chooseLogoVideo() {
chooseVideoToUpload(path => {
this.$set(this.innApplyInfo, 'coverVideo', path)
})
},
chooseCoverImg() {
chooseImage(img => { chooseImage(img => {
that.innApplyInfo.cover = img; this.$set(this.innApplyInfo, 'cover', img)
}); })
}, },
// successImage(e){ submit() {
// uni.showModal({ if (this.innApplyInfo.logo.length === 0) {
// content : '上传成功,详细信息请看控制台' this.$dialog.error('请上传店铺LOGO图片')
// }) return
// },
// successvideo(e){
// },
submit: function () {
if (this.innApplyInfo.logo.length == 0) {
this.$dialog.error("请上传店铺LOGO图片");
return;
} }
if (this.innApplyInfo.cover.length === 0 && this.innApplyInfo.coverType === 1) {
if (this.innApplyInfo.cover.length == 0) { this.$dialog.error('请上传店铺封面图片')
this.$dialog.error("请上传店铺封面图片"); return
return;
} }
if (this.innApplyInfo.coverVideo.length === 0 && this.innApplyInfo.coverType === 2) {
if (this.innApplyInfo.ownerName.length == 0) { this.$dialog.error('请上传店铺封面视频')
this.$dialog.error("请输入店主名字"); return
return;
} }
if (this.innApplyInfo.ownerName.length === 0) {
// if (this.innApplyInfo.tips.length == 0) { this.$dialog.error('请输入店主名字')
// this.$dialog.error("请输入关键词"); return
// return;
// }
if (this.innApplyInfo.content.length == 0) {
this.$dialog.error("请输入一句话介绍");
return;
} }
if (this.innApplyInfo.content.length === 0) {
if (this.innApplyInfo.desc.length == 0) { this.$dialog.error('请输入一句话介绍')
this.$dialog.error("请输入店铺简介"); return
return;
} }
if (this.innApplyInfo.desc.length === 0) {
if (this.uploadedFilesArray.length == 0) { this.$dialog.error('请输入店铺简介')
this.$dialog.error("请上传至少一张店铺图片"); return
return;
} }
if (this.uploadedFilesArray.length === 0) {
var param = {}; this.$dialog.error('请上传至少一张店铺图片')
//深拷贝 return
param = JSON.parse(JSON.stringify(this.innApplyInfo)); }
// 深拷贝
const param = JSON.parse(JSON.stringify(this.innApplyInfo))
if (this.uploadedFilesArray.length > 0) { if (this.uploadedFilesArray.length > 0) {
param.pics = this.uploadedFilesArray.join(','); param.pics = this.uploadedFilesArray.join(',')
} }
param.id = this.innHistory.id
param.id = this.innHistory.id; if (param.coverType === 2) {
param.cover = param.coverVideo
}
uni.showLoading(); uni.showLoading()
postHotelInfoEdit(param).then((res) => { postHotelInfoEdit(param).then((res) => {
uni.hideLoading() uni.hideLoading()
uni.showToast({ uni.showToast({
title: '修改成功!', title: '修改成功!',
mask: false, mask: false,
duration: 1500 duration: 1500
}); })
setTimeout(function () { setTimeout(function () {
uni.navigateBack()
that.$yrouter.back(); }, 1000)
}, 1000);
}).catch((err) => { }).catch((err) => {
uni.hideLoading() uni.hideLoading()
uni.showToast({ uni.showToast({
@@ -320,22 +312,31 @@ export default {
icon: 'none', icon: 'none',
mask: false, mask: false,
duration: 1500 duration: 1500
}); })
}).finally(() => {
}) })
} }
} }
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.base-info-section { .base-info-section {
padding: 32rpx; padding: 32rpx 32rpx 120rpx 32rpx;
background: #FFFFFF; background: #FFFFFF;
.img-item {
display: block;
width: 64rpx;
height: 64rpx;
}
.video-item {
width: 64rpx;
height: 64rpx;
}
.inp-textarea {
width: 100%;
height: 200rpx;
color:#C2C5CC;
}
} }
.base-info-section .section-title { .base-info-section .section-title {
@@ -406,6 +407,7 @@ export default {
.base-info-section .item.is_required .cell .cell-value { .base-info-section .item.is_required .cell .cell-value {
flex-grow: 1; flex-grow: 1;
text-align: right;
} }
.base-info-section .item.is_required .cell .cell-title::before { .base-info-section .item.is_required .cell .cell-title::before {
+50 -26
View File
@@ -1,35 +1,48 @@
<template> <template>
<view class="pkg-lottery-log" v-if="ready"> <view class="pkg-lottery-log">
<image style="width: 734rpx;height: 1418rpx" :src="webUrl+'/20240125215943273915.png'" mode="scaleToFill"/> <image
:src="webUrl+'/20240125215943273915.png'"
mode="scaleToFill"
style="width: 734rpx;height: 1418rpx"
/>
<view class="th flex"> <view class="th flex">
<view>日期</view> <view>日期</view>
<view style="margin-left: 168rpx;">抽奖结果</view> <view style="margin-left: 168rpx;">抽奖结果</view>
</view> </view>
<scroll-view
<scroll-view class="list-box" scroll-y @scrolltolower="onBottom"> scroll-y
<view class="item flex jc-between ai-center" v-for="(item,index) in list" :key="index"> class="list-box"
@scrolltolower="onBottom"
>
<view
v-for="(item, index) in list"
:key="index"
class="item flex jc-between ai-center"
>
<view class="flex ai-center"> <view class="flex ai-center">
<view style="width: 288rpx;color:#BD2323;font-size: 28rpx">{{ item['drawTime'] }}</view> <view style="width: 288rpx;color:#BD2323;font-size: 28rpx">{{ item['drawTime'] }}</view>
<view class="more-t">{{ item['prizeName'] }}</view> <view class="more-t">{{ item['prizeName'] }}</view>
</view> </view>
<image
<image class="flex-0" style="width: 111rpx;height: 64rpx" :src="webUrl+'/20240124232010456109.png'" v-if="item['isHit'] === 1 && item['status'] === 1"
mode="scaleToFill" v-if="item['isHit']===1 && item['status']===1" @click="takeItem(item)"/> :src="webUrl+'/20240124232010456109.png'"
class="flex-0"
style="width: 111rpx;height: 64rpx"
mode="scaleToFill"
@click="takeItem(item, index)"
/>
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
</template> </template>
<script> <script>
import {getLogs, takePrize} from "@/api/lottery"; import {getLogs, takePrize} from "@/api/lottery";
export default { export default {
data() { data() {
return { return {
webUrl: this.$VUE_APP_RESOURCES_URL, webUrl: this.$VUE_APP_RESOURCES_URL,
ready: false, loading: false,
page: 1, page: 1,
list: [] list: []
} }
@@ -40,30 +53,44 @@ export default {
this.fetchList() this.fetchList()
}, },
methods: { methods: {
async fetchList() { fetchList() {
const res = await getLogs(this.page, 20) this.loading = true
if (res.success) { getLogs(this.page, 20).then(res => {
res.data['records']?.forEach(item => this.list.push(item)) const { success, data } = res
this.ready = true if (success) {
} if (data) {
if (data.records) {
data.records.map(item => {
this.list.push(item)
})
}
}
}
this.loading = false
}).catch(() => {
this.loading = false
}).finally(() => {
this.loading = false
})
}, },
onBottom() { onBottom() {
if (this.loading) {
return
}
this.page++ this.page++
this.fetchList() this.fetchList()
}, },
async takeItem(item) {
async takeItem (item) { // 领取商品
if (item['prizeType'] === 1 && item['status'] === 1) { if (item['prizeType'] === 1 && item['status'] === 1) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/order/OrderSubmission/index?lotteryRecordId=' + item['id'] url: '/pages/order/OrderSubmission/index?lotteryRecordId=' + item['id']
}) })
return return
} }
const res = await takePrize(item.id) const res = await takePrize(item.id)
if (res.success) { if (res.success) {
item['status'] = 2 this.$set(this.list[index], 'status', 2)
uni.showModal({ uni.showModal({
title: '领取成功', title: '领取成功',
content: '您的奖品已经领取成功,请前往我的订单查看奖品发货信息', content: '您的奖品已经领取成功,请前往我的订单查看奖品发货信息',
@@ -84,9 +111,6 @@ export default {
} }
} }
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
+12 -2
View File
@@ -25,8 +25,15 @@
获得{{ diceResult['prizeName'] }}一份 获得{{ diceResult['prizeName'] }}一份
</view> </view>
</view> </view>
<image class="btn-result" style="width: 240rpx;height: 68rpx" :src="webUrl+'/20240125205521152611.png'" <!-- fix bug#972: 抽奖抽中优惠券优惠券直接自动领取并保存在优惠券卡包不需要再通过抽奖记录进行领取 -->
mode="scaleToFill" @click="closeResultModel" v-if="diceResult['isHit']!==0"/> <image
v-if="diceResult['isHit'] === 1 && diceResult.prizeType !== 3"
:src="webUrl+'/20240125205521152611.png'"
class="btn-result"
style="width: 240rpx;height: 68rpx"
mode="scaleToFill"
@click="closeResultModel"
/>
</view> </view>
<view class="dialog-take flex jc-center" :style="{'backgroundImage':`url(${webUrl}/20240124210904824337.png)`}" <view class="dialog-take flex jc-center" :style="{'backgroundImage':`url(${webUrl}/20240124210904824337.png)`}"
@@ -90,6 +97,7 @@ export default {
}, },
diceImg: '', diceImg: '',
diceResult: { diceResult: {
prizeType: '', // 1-商城商品,2-积分,3-优惠券,4-谢谢参与
prizeName: '', prizeName: '',
prizeImage: '', prizeImage: '',
diceImage: '', diceImage: '',
@@ -174,11 +182,13 @@ export default {
}, },
closeResultModel() { closeResultModel() {
// 谢谢参与
if (this.diceResult['prizeType'] === 4) { if (this.diceResult['prizeType'] === 4) {
this.showResult = false this.showResult = false
this.showDialog = false this.showDialog = false
return return
} }
// 领取商品
if (this.diceResult['prizeType'] === 1) { if (this.diceResult['prizeType'] === 1) {
this.showResult = false this.showResult = false
this.showDialog = false this.showDialog = false
+127 -35
View File
@@ -16,18 +16,80 @@
</template> </template>
</u-cell> </u-cell>
</u-form-item> </u-form-item>
<u-form-item prop="coverType">
<u-form-item prop="cover"> <u-cell title="封面类型" :border="false">
<u-cell title="店铺封面图" :border="false"> <template #icon>
<text class="required">*</text>
</template>
<template #value>
<u-radio-group
v-model="form.coverType"
placement="row"
>
<u-radio
:name="1"
:customStyle="{marginRight: '16px'}"
active-color="red"
label="图片"
/>
<u-radio
:name="2"
active-color="red"
label="视频"
/>
</u-radio-group>
</template>
</u-cell>
</u-form-item>
<u-form-item v-if="form.coverType === 1" prop="cover">
<u-cell title="店铺图片封面" :border="false">
<template #icon> <template #icon>
<text class="required">*</text> <text class="required">*</text>
</template> </template>
</u-cell> </u-cell>
<u-cell :border="false"> <u-cell :border="false">
<template #title> <template #title>
<view class="box-upload" @click="chooseLogoImg('cover')"> <view
<view class="btn-upload" v-if="form.cover.length===0 || form.cover==null">上传图片</view> class="box-upload"
<image class="img-preview" :src="form.cover" v-else/> @click="chooseLogoImg('cover')"
>
<view
v-if="!form.cover"
class="btn-upload"
>上传图片</view>
<image
v-else
:src="form.cover"
class="img-preview"
/>
</view>
</template>
</u-cell>
</u-form-item>
<u-form-item v-if="form.coverType === 2" prop="coverVideo">
<u-cell title="店铺视频封面" :border="false">
<template #icon>
<text class="required">*</text>
</template>
</u-cell>
<u-cell :border="false">
<template #title>
<view
class="box-upload"
@click="chooseLogoVideo()"
>
<view
v-if="!form.coverVideo"
class="btn-upload"
>上传视频</view>
<video
v-else
:src="form.coverVideo"
:poster="form.coverVideo + '?vframe/jpg/offset/1'"
:controls="false"
play-btn-position="center"
class="video-item"
/>
</view> </view>
</template> </template>
</u-cell> </u-cell>
@@ -225,7 +287,9 @@
<u-popup :show="show" mode="center" round="10" closeable @close="show=false"> <u-popup :show="show" mode="center" round="10" closeable @close="show=false">
<view class="popup-body"> <view class="popup-body">
<view class="tc bold">入驻申请须知</view> <view class="tc bold">入驻申请须知</view>
<view class="content" v-html="notice"></view> <view class="content">
<rich-text :nodes="notice" />
</view>
<view class="agree-box"> <view class="agree-box">
<checkbox-group @change="changeAgree"> <checkbox-group @change="changeAgree">
<label> <label>
@@ -241,36 +305,50 @@
</template> </template>
<script> <script>
import CitySelect from "@/components/CitySelect"; import CitySelect from "@/components/CitySelect"
import {getShopData, getShopInfo, removeApply, saveShop} from "@/api/join"; import {
import {getCity, registerVerify} from "@/api/user"; getShopData,
import {chooseImage, moreImage, uploadImage} from "@/utils"; getShopInfo,
removeApply,
saveShop
} from "@/api/join"
import {
getCity,
registerVerify
} from "@/api/user"
import {
chooseImage,
moreImage,
uploadImage,
chooseVideoToUpload
} from "@/utils"
export default { export default {
name: "pkgJoinShop", name: "PkgJoinShop",
components: { components: {
CitySelect CitySelect
}, },
data() { data() {
return { return {
partnerId: null, partnerId: null,
pics: [], pics: [],
quaPics: [], quaPics: [],
tips: "", tips: '',
form: { form: {
name: "", name: '',
cover: "", cover: '',
logo: "", coverVideo: '',
qualification: "", coverType: 1, // coverType: 1-图片,2-视频
logo: '',
qualification: '',
type: 0, type: 0,
typeText: "", typeText: '',
phone: "", phone: '',
captcha: "", captcha: '',
area: "", area: '',
address: "", address: '',
position: "", position: '',
content: "" content: ''
}, },
rules: { rules: {
'name': { 'name': {
@@ -282,7 +360,13 @@ export default {
'cover': { 'cover': {
type: 'string', type: 'string',
required: true, required: true,
message: '请上传店铺封面', message: '请上传店铺图片封面',
trigger: ['blur', 'change']
},
'coverVideo': {
type: 'string',
required: true,
message: '请上传店铺视频方面',
trigger: ['blur', 'change'] trigger: ['blur', 'change']
}, },
'logo': { 'logo': {
@@ -340,23 +424,19 @@ export default {
trigger: ['blur', 'change'] trigger: ['blur', 'change']
} }
}, },
showType: false, showType: false,
columnsType: [], columnsType: [],
indexType: [0], indexType: [0],
district: [], district: [],
address: {}, address: {},
isAgree: false, isAgree: false,
show: false, show: false,
notice: "", notice: '',
showRemove: false, showRemove: false,
isDraft: null, isDraft: null,
reviewStatus: null, reviewStatus: null,
stateTitle: "", stateTitle: '',
stateType: "primary", stateType: 'primary',
isPass: false isPass: false
} }
}, },
@@ -458,6 +538,11 @@ export default {
this.form[target] = img; this.form[target] = img;
}); });
}, },
chooseLogoVideo() {
chooseVideoToUpload(path => {
this.form.coverVideo = path
})
},
chooseShopImg() { chooseShopImg() {
let that = this; let that = this;
@@ -593,8 +678,11 @@ export default {
this.form.qualification += (item.url + ","); this.form.qualification += (item.url + ",");
}) })
this.form.qualification = this.form.qualification.substring(0, this.form.qualification.length - 1); this.form.qualification = this.form.qualification.substring(0, this.form.qualification.length - 1);
const postData = Object.assign({}, this.form)
saveShop(this.form, this.partnerId).then(res => { if (postData.coverType === 2) {
postData.cover = postData.coverVideo
}
saveShop(postData, this.partnerId).then(res => {
if (res.status === 200) { if (res.status === 200) {
uni.showToast({ uni.showToast({
title: "您的入驻申请已提交成功,请耐心等待审核", title: "您的入驻申请已提交成功,请耐心等待审核",
@@ -643,4 +731,8 @@ export default {
.font-color-red { .font-color-red {
font-size: 22rpx; font-size: 22rpx;
} }
.video-item {
width: 80px;
height: 80px;
}
</style> </style>
+151
View File
@@ -0,0 +1,151 @@
<template>
<view class="gift-page">
<view class="page1-wrap">
<!-- <image :src="data.mainImage" class="bg" /> -->
<rich-text :nodes="data.mainImageHtml" />
</view>
<view class="page2-wrap">
<view class="bg-cont">
<rich-text :nodes="data.backgroundImage1Html" />
<!-- <image :src="data.backgroundImage1" class="bg" /> -->
</view>
<view class="good-list">
<view
v-for="(item, index) in data.productList1"
:key="index"
class="good-item"
@click="goodItemClick(item)"
>
<image :src="item.productImage" class="img" />
</view>
</view>
</view>
<view class="page3-wrap">
<view class="bg-cont">
<rich-text :nodes="data.backgroundImage2Html" />
<!-- <image :src="data.backgroundImage2" class="bg" /> -->
</view>
<view class="good-list">
<view
v-for="(item, index) in data.productList2"
:key="index"
class="good-item"
@click="goodItemClick(item)"
>
<image :src="item.productImage" class="img" />
</view>
</view>
</view>
</view>
</template>
<script>
import {
customizedGiftContent
} from '@/api/product'
export default {
name: 'GiftContent',
data() {
return {
data: {
backgroundImage1: '',
backgroundImage2: '',
backgroundImage1Html: '',
backgroundImage2Html: '',
mainImage: '',
productList1: [],
productList2: [],
}
}
},
onLoad(options) {
uni.setNavigationBarTitle({
title: options.name + '-' + '特色礼品'
})
this.getPageDataReq(options.id)
},
methods: {
getPageDataReq(id) {
uni.showLoading({
title: '数据加载中...'
})
customizedGiftContent({ id }).then(res => {
const { success, data } = res
if (success) {
this.data = {
...data,
mainImageHtml: `<img src="${data.mainImage}" style="display: block;max-width: 100%;">`,
backgroundImage1Html: `<img src="${data.backgroundImage1}" style="display: block;max-width: 100%;">`,
backgroundImage2Html: `<img src="${data.backgroundImage2}" style="display: block;max-width: 100%;">`
}
}
uni.hideLoading()
}).catch(() => {
uni.hideLoading()
})
},
goodItemClick(good) {
const productId = good.productId
if (!productId) {
return
}
uni.navigateTo({
url: `/pages/shop/GoodsCon/index?id=${productId}`
})
}
}
}
</script>
<style scoped lang="less">
.page1-wrap {
.bg {
display: block;
width: 100%;
height: 100vh;
}
}
.good-list {
position: absolute;
z-index: 5;
width: 100%;
}
.page2-wrap {
position: relative;
.bg-cont {
position: relative;
z-index: 2;
}
.good-list {
top: 0;
padding: 0;
.good-item + .good-item {
margin: 25px 0 0 0;
}
.good-item {
.img {
display: block;
width: 325px;
height: 332px;
margin: 0 auto;
}
}
}
}
.page3-wrap {
position: relative;
.good-list {
top: 0;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
padding: 12px 0 0 0;
.good-item {
margin: 0 0 20px 0;
.img {
width: 166px;
height: 262px;
}
}
}
}
</style>
+260 -235
View File
@@ -1,270 +1,295 @@
<template> <template>
<view class="pkg-product-list"> <view class="gift-page">
<view class="fixed-header"> <view class="banner" @click="linkTo">
<swiper class="swiper-box" indicator-dots indicator-color="rgba(255,255,255,.3)" indicator-active-color="#fff" <rich-text :nodes="topBannerHtml" />
autoplay circular v-if="bannerList.length>0"> </view>
<swiper-item v-for="(item,index) in bannerList" :key="index"> <view class="province-enter-wrap">
<image :src="item.pic" mode="scaleToFill" @click="$global.commonJump(item.uniappUrl)"/> <view
</swiper-item> class="scroll-x-wrap"
</swiper> >
<view
<view class="search-box flex jc-between ai-center"> :class="!toggleStatus ? '' : 'hide'"
<input type="text" v-model="keyword" placeholder="搜索商品" placeholder-style="color:#949494" @confirm="search"> class="list-cont"
<image class="icon" :src="webUrl+'/20220903142935869059.png'" mode="scaleToFill" @click="search"></image> >
<view
v-for="(item, index) in provinceList"
:key="index"
class="item"
@click="provinceItemClick(item)"
>
<image :src="item.icon" class="img" />
<view class="name">{{ item.provinceMergerName }}</view>
</view>
</view>
<view
:class="toggleStatus ? 'show' : ''"
class="list-cont list-show-all"
>
<view
v-for="(item, index) in provinceList"
:key="index"
class="item"
@click="provinceItemClick(item)"
>
<image :src="item.icon" class="img" />
<view class="name">{{ item.provinceMergerName }}</view>
</view>
</view>
<view
v-if="!toggleStatus && provinceList.length > 5"
class="toggle-btn"
@click="toggleHandle(true)"
>
<view></view>
<view></view>
</view>
<view
v-if="toggleStatus"
class="toggle-btn"
@click="toggleHandle(false)"
>
<view></view>
<view></view>
</view>
</view> </view>
</view> </view>
<view class="province-bg-list">
<view class="fixed-aside flex-0"> <view
<view class="item flex jc-center ai-center" :class="index === asideIndex ? 'active' : ''" v-for="(item, index) in provinceList"
v-for="(item, index) in asideList" :key="index" @click="asideTap(index)"> :key="index"
<text class="one-t">{{ item.label }}</text> class="item"
</view> >
</view> <view class="bg" @click="provinceItemClick(item)">
<rich-text :nodes="item.bgHtml" />
<view class="conter"> </view>
<mescroll-body ref="mescrollRef" top="0" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption" <view class="good-list">
@up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick"> <view
v-for="(goodItem, goodIndex) in item.productList"
<view class="list flex flex-wrap"> :key="goodIndex"
<view v-for="(item, index) in dataList" :key="index"> class="good-item"
<view class="item" @click="goGoods(item.id)"> @click.stop="goodItemClick(goodItem)"
<image class="cover" :src="item.image" mode="scaleToFill"/> >
<view class="name more-t">{{ item.storeName }}</view> <view class="good-img">
<view class="price">{{ item.price }}</view> <image :src="goodItem.productImage" class="img" />
</view>
<view class="name">
{{ goodItem.productName }}
</view>
<view class="price">
<text class="txt"></text>
{{ goodItem.productPrice }}
</view> </view>
</view> </view>
</view> </view>
</mescroll-body> </view>
</view> </view>
<!-- <view class="article-box">-->
<!-- <mescroll-body ref="mescrollRef" top="16rpx" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption"-->
<!-- @up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick">-->
<!-- <view class="list flex flex-wrap">-->
<!-- <view v-for="(item, index) in dataList" :key="index">-->
<!-- <view class="item" @click="goGoods(item.id)">-->
<!-- <image class="cover" :src="item.image" mode="scaleToFill"/>-->
<!-- <view class="name more-t">{{ item.storeName }}</view>-->
<!-- <view class="price">{{ item.price }}</view>-->
<!-- </view>-->
<!-- </view>-->
<!-- </view>-->
<!-- </mescroll-body>-->
<!-- </view>-->
<!-- </view>-->
</view> </view>
</template> </template>
<script> <script>
import MescrollMixins from "@/mixins/mescroll-mixins.js"; import {
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue"; customizedGift
import {customizedGift} from "@/api/product"; } from '@/api/product'
import {fetchCity} from "@/api/wenwan";
import {getProducts} from "@/api/store";
export default { export default {
name: "giftList", name: 'GiftList',
components: {
MescrollBody
},
data() { data() {
return { return {
webUrl: this.$VUE_APP_RESOURCES_URL, provinceList: [],
keyword: "", topBannerHtml: '',
bannerList: [], topBannerUrl: '',
asideList: [], toggleStatus: false
asideIndex: 0,
dataList: [], // 列表数据
upOption: {
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto: true,
empty: {
tip: '', // 提示
icon:this.$VUE_APP_RESOURCES_URL+'/20240102232724024787.png',
width:381,
height:348
}
},
downOption: {
auto: false
}
} }
}, },
mixins: [
MescrollMixins({
getPageData(mescroll) {
let that = this;
// 此时mescroll会携带page的参数:
let pageNum = mescroll.num; // 页码, 默认从1开始
let timer = setInterval(() => {
if (that.asideList.length > 0) {
clearInterval(timer);
let param = {
isCustomizedGift: 1,
page: pageNum,
limit: 10,
keyword: that.keyword,
provinceId: that.asideList.length > 0 ? that.asideList[that.asideIndex].provinceId : ""
}
getProducts(param).then(({data}) => {
if (mescroll.num === 1) {
that.dataList = [];
}
that.dataList = that.dataList.concat(data);
mescroll.endSuccess(data.length);
}).catch(err => {
mescroll.endErr();
uni.showToast({
title: err + '',
icon: 'none',
mask: false,
duration: 1500
});
});
}
}, 500)
}
})
],
onLoad() { onLoad() {
customizedGift().then(({data}) => this.bannerList = data.banner); this.getPageDataReq()
fetchCity(3).then(({data}) => this.asideList = data.group);
}, },
methods: { methods: {
search() { getPageDataReq() {
//触发加载请求 customizedGift().then(res => {
this.mescroll.scrollTo(0, 0); const { success, data } = res
this.mescroll && this.mescroll.resetUpScroll(false); if (success) {
}, this.topBannerHtml = `<img src="${data.topBanner.image}" style="display: block;max-width: 100%;">`
asideTap(index) { this.topBannerUrl = data.topBanner.appUrl || ''
this.asideIndex = index; const list = data.cities || []
this.search(); if (list.length > 0) {
}, list.map(item => {
goGoods(id) { const backgroundImage = item.backgroundImage || ''
uni.navigateTo({ if (backgroundImage && item.productList.length > 0) {
url: "/pages/shop/GoodsCon/index?id=" + id this.provinceList.push({
...item,
bgHtml: `<img src="${item.backgroundImage}" style="display: block;max-width: 100%;">`
})
}
})
}
}
}) })
},
linkTo() {
if (!this.topBannerUrl) {
return
}
uni.navigateTo({
url: this.topBannerUrl
})
},
provinceItemClick(item) {
const id = item.id
if (!id) {
return
}
uni.navigateTo({
url: `/pkg_product/views/giftContent?id=${id}&name=${item.provinceMergerName}`
})
},
goodItemClick(good) {
const productId = good.productId
if (!productId) {
return
}
uni.navigateTo({
url: `/pages/shop/GoodsCon/index?id=${productId}`
})
},
toggleHandle(value) {
this.toggleStatus = value
} }
} }
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import "@/assets/css/product.less"; .banner {
position: relative;
.pkg-product-list { z-index: 1;
min-height: 100vh; }
box-sizing: border-box; .province-enter-wrap {
background: #fff; position: relative;
z-index: 5;
.fixed-header { margin-top: -80rpx;
position: fixed; padding: 30rpx 30rpx 0 30rpx;
top: 0; .scroll-x-wrap {
left: 0; position: relative;
width: 100%; height: 140rpx;
padding: 18rpx 0; padding: 24rpx 80rpx 16rpx 24rpx;
background: #fff; border-radius: 24rpx;
z-index: 9;
}
.search-box {
margin-top: 14rpx;
}
.body-box {
position: fixed;
top: 472rpx;
height: calc(100vh - 472rpx);
}
.fixed-aside {
position: fixed;
width: 194rpx;
left: 0;
top: 472rpx;
bottom: 0 !important;
box-sizing: border-box;
border-top: 2rpx solid #D2D2D2;
border-right: 2rpx solid #DADCE0;
background-color: #fff; background-color: #fff;
overflow-y: auto; box-shadow: 0px 1px 4px rgba(0,0,0,0.16);
overflow-x: hidden; .list-cont {
overflow-scrolling: touch; display: flex;
flex-wrap: nowrap;
.item { overflow-x: auto;
height: 94rpx; &.hide {
box-sizing: border-box; display: none;
border-bottom: 2rpx solid #D2D2D2; }
color: #033333; .item + .item {
margin: 0 0 0 24rpx;
text { }
font-size: 28rpx; .item {
.img {
width: 45px;
height: 45px;
border-radius: 4px;
}
.name {
margin: 12rpx 0 0 0;
font-size: 12px;
color: #333;
text-align: center;
}
} }
} }
.list-show-all {
.active { position: absolute;
border-left: 6rpx solid #FD574B; top: 0;
color: #FD574B; left: 0;
font-weight: bold; right: 0;
z-index: 2;
flex-wrap: wrap;
height: 0;
padding: 24rpx 80rpx 16rpx 24rpx;
border-radius: 24rpx;
box-sizing: border-box;
background-color: #fff;
opacity: 0;
&.show {
height: auto;
opacity: 1;
box-shadow: 0px 1px 4px rgba(0,0,0,0.16);
}
.item {
margin: 0 24rpx 24rpx 0 !important;
}
}
.toggle-btn {
position: absolute;
top: 24rpx;
right: 24rpx;
z-index: 5;
font-size: 14px;
} }
} }
}
.conter { .province-bg-list {
margin-left: 194rpx; padding: 30rpx;
margin-top: 472rpx; .item + .item {
border-top: 2rpx solid #D2D2D2; margin: 30rpx 0 0 0;
}
.empty { .item {
position: absolute; position: relative;
top: 50%; .bg {
left: 50%;
transform: translate(-50%, -50%);
image {
width: 280rpx;
height: 280rpx;
}
view {
color: gray;
font-size: 24rpx;
}
}
.item {
position: relative; position: relative;
width: 242rpx; z-index: 2;
height: 376rpx;
box-sizing: border-box;
margin: 20rpx 0 0 20rpx;
.cover {
width: 242rpx;
height: 242rpx;
margin-bottom: 8rpx;
border-radius: 8rpx;
}
.name {
color: #333;
font-size: 26rpx;
line-height: 36rpx;
}
.price {
position: absolute;
bottom: 4rpx;
color: #DA0000;
font-size: 28rpx;
line-height: 36rpx;
}
} }
.good-list {
.item-store { position: absolute;
height: 336rpx; bottom: 12rpx;
left: 30rpx;
right: 30rpx;
z-index: 5;
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
.good-item {
margin: 0 24rpx 0 0;
text-align: center;
font-size: 12px;
color: #fff;
.good-img {
width: 96px;
height: 96px;
.img {
width: 100%;
height: 100%;
border-radius: 12rpx;
}
}
.name {
height: 28px;
margin: 3px 0;
box-sizing: border-box;
line-height: 14px;
display: -webkit-box;
overflow: hidden;
white-space: normal !important;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
word-wrap: break-word;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.price {
display: inline-block;
height: 18px;
padding: 0 20rpx;
border-radius: 11px;
border: 1px solid #fff;
line-height: 18px;
background-color: rgba(0, 0, 0, .5);
.txt {
font-size: 10px;
}
}
}
} }
} }
} }
+271
View File
@@ -0,0 +1,271 @@
<template>
<view class="pkg-product-list">
<view class="fixed-header">
<swiper class="swiper-box" indicator-dots indicator-color="rgba(255,255,255,.3)" indicator-active-color="#fff"
autoplay circular v-if="bannerList.length>0">
<swiper-item v-for="(item,index) in bannerList" :key="index">
<image :src="item.pic" mode="scaleToFill" @click="$global.commonJump(item.uniappUrl)"/>
</swiper-item>
</swiper>
<view class="search-box flex jc-between ai-center">
<input type="text" v-model="keyword" placeholder="搜索商品" placeholder-style="color:#949494" @confirm="search">
<image class="icon" :src="webUrl+'/20220903142935869059.png'" mode="scaleToFill" @click="search"></image>
</view>
</view>
<view class="fixed-aside flex-0">
<view class="item flex jc-center ai-center" :class="index === asideIndex ? 'active' : ''"
v-for="(item, index) in asideList" :key="index" @click="asideTap(index)">
<text class="one-t">{{ item.label }}</text>
</view>
</view>
<view class="conter">
<mescroll-body ref="mescrollRef" top="0" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption"
@up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick">
<view class="list flex flex-wrap">
<view v-for="(item, index) in dataList" :key="index">
<view class="item" @click="goGoods(item.id)">
<image class="cover" :src="item.image" mode="scaleToFill"/>
<view class="name more-t">{{ item.storeName }}</view>
<view class="price">{{ item.price }}</view>
</view>
</view>
</view>
</mescroll-body>
</view>
<!-- <view class="article-box">-->
<!-- <mescroll-body ref="mescrollRef" top="16rpx" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption"-->
<!-- @up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick">-->
<!-- <view class="list flex flex-wrap">-->
<!-- <view v-for="(item, index) in dataList" :key="index">-->
<!-- <view class="item" @click="goGoods(item.id)">-->
<!-- <image class="cover" :src="item.image" mode="scaleToFill"/>-->
<!-- <view class="name more-t">{{ item.storeName }}</view>-->
<!-- <view class="price">{{ item.price }}</view>-->
<!-- </view>-->
<!-- </view>-->
<!-- </view>-->
<!-- </mescroll-body>-->
<!-- </view>-->
<!-- </view>-->
</view>
</template>
<script>
import MescrollMixins from "@/mixins/mescroll-mixins.js";
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue";
import {customizedGift} from "@/api/product";
import {fetchCity} from "@/api/wenwan";
import {getProducts} from "@/api/store";
export default {
name: "giftList",
components: {
MescrollBody
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
keyword: "",
bannerList: [],
asideList: [],
asideIndex: 0,
dataList: [], // 列表数据
upOption: {
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto: true,
empty: {
tip: '', // 提示
icon:this.$VUE_APP_RESOURCES_URL+'/20240102232724024787.png',
width:381,
height:348
}
},
downOption: {
auto: false
}
}
},
mixins: [
MescrollMixins({
getPageData(mescroll) {
let that = this;
// 此时mescroll会携带page的参数:
let pageNum = mescroll.num; // 页码, 默认从1开始
let timer = setInterval(() => {
if (that.asideList.length > 0) {
clearInterval(timer);
let param = {
isCustomizedGift: 1,
page: pageNum,
limit: 10,
keyword: that.keyword,
provinceId: that.asideList.length > 0 ? that.asideList[that.asideIndex].provinceId : ""
}
getProducts(param).then(({data}) => {
if (mescroll.num === 1) {
that.dataList = [];
}
that.dataList = that.dataList.concat(data);
mescroll.endSuccess(data.length);
}).catch(err => {
mescroll.endErr();
uni.showToast({
title: err + '',
icon: 'none',
mask: false,
duration: 1500
});
});
}
}, 500)
}
})
],
onLoad() {
customizedGift().then(({data}) => this.bannerList = data.banner);
fetchCity(3).then(({data}) => this.asideList = data.group);
},
methods: {
search() {
//触发加载请求
this.mescroll.scrollTo(0, 0);
this.mescroll && this.mescroll.resetUpScroll(false);
},
asideTap(index) {
this.asideIndex = index;
this.search();
},
goGoods(id) {
uni.navigateTo({
url: "/pages/shop/GoodsCon/index?id=" + id
})
}
}
}
</script>
<style scoped lang="less">
@import "@/assets/css/product.less";
.pkg-product-list {
min-height: 100vh;
box-sizing: border-box;
background: #fff;
.fixed-header {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 18rpx 0;
background: #fff;
z-index: 9;
}
.search-box {
margin-top: 14rpx;
}
.body-box {
position: fixed;
top: 472rpx;
height: calc(100vh - 472rpx);
}
.fixed-aside {
position: fixed;
width: 194rpx;
left: 0;
top: 472rpx;
bottom: 0 !important;
box-sizing: border-box;
border-top: 2rpx solid #D2D2D2;
border-right: 2rpx solid #DADCE0;
background-color: #fff;
overflow-y: auto;
overflow-x: hidden;
overflow-scrolling: touch;
.item {
height: 94rpx;
box-sizing: border-box;
border-bottom: 2rpx solid #D2D2D2;
color: #033333;
text {
font-size: 28rpx;
}
}
.active {
border-left: 6rpx solid #FD574B;
color: #FD574B;
font-weight: bold;
}
}
.conter {
margin-left: 194rpx;
margin-top: 472rpx;
border-top: 2rpx solid #D2D2D2;
.empty {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
image {
width: 280rpx;
height: 280rpx;
}
view {
color: gray;
font-size: 24rpx;
}
}
.item {
position: relative;
width: 242rpx;
height: 376rpx;
box-sizing: border-box;
margin: 20rpx 0 0 20rpx;
.cover {
width: 242rpx;
height: 242rpx;
margin-bottom: 8rpx;
border-radius: 8rpx;
}
.name {
color: #333;
font-size: 26rpx;
line-height: 36rpx;
}
.price {
position: absolute;
bottom: 4rpx;
color: #DA0000;
font-size: 28rpx;
line-height: 36rpx;
}
}
.item-store {
height: 336rpx;
}
}
}
</style>
+1 -1
View File
@@ -73,7 +73,7 @@ export default {
methods: { methods: {
goCity() { goCity() {
uni.redirectTo({ uni.redirectTo({
url: `/components/chose-city/chose-city?type=0&city=${this.cityName}` url: `/pages/chose-city/chose-city?type=0&city=${this.cityName}`
}) })
}, },
init() { init() {
+154 -55
View File
@@ -6,39 +6,57 @@
<!-- </view>--> <!-- </view>-->
<view class="img-box flex jc-between ai-end"> <view class="img-box flex jc-between ai-end">
<image class="img-seckill" :src="webUrl+'/20221222155145987590.png'" mode="scaleToFill"/> <image
<image class="img-rule" :src="webUrl+'/20221222155206016851.png'" mode="scaleToFill" @click="changeRule"/> :src="webUrl+'/20221222155145987590.png'"
class="img-seckill"
mode="scaleToFill"
/>
<image
:src="webUrl+'/20221222155206016851.png'"
class="img-rule"
mode="scaleToFill"
@click="changeRule"
/>
</view> </view>
<!-- 规则富文本弹窗 -->
<view class="dialog-mask" v-show="showRule"> <view class="dialog-mask" v-show="showRule">
<view class="dialog"> <view class="dialog">
<image class="icon-close" :src="webUrl+'/20221230200935413332.png'" mode="scaleToFill" @click="changeRule"/> <image
:src="webUrl+'/20221230200935413332.png'"
class="icon-close"
mode="scaleToFill"
@click="changeRule"
/>
<view class="dialog-body"> <view class="dialog-body">
<view class="flex jc-center"> <view class="flex jc-center">
<image class="title" :src="webUrl+'/20221230201151585898.png'" mode="scaleToFill"/> <image class="title" :src="webUrl+'/20221230201151585898.png'" mode="scaleToFill"/>
</view> </view>
<rich-text class="content" :nodes="ruleContent"/> <rich-text class="content" :nodes="ruleContent"/>
<!-- <view class="content">{{ ruleContent }}</view>-->
</view> </view>
</view> </view>
</view> </view>
<view class="top-list flex"> <view class="top-list flex">
<view class="item flex-0" v-for="(item,index) in topList" :key="index" @click="goGoodsConByProductID(item)"> <view class="item flex-0" v-for="(item,index) in topList" :key="index" @click="goGoodsConByProductID(item)">
<view class="header flex jc-between ai-center"> <view class="header flex jc-between ai-center">
<image class="img-rush" :src="webUrl+'/20221222155118237514.png'" mode="scaleToFill"/> <image class="img-rush" :src="webUrl+'/20221222155118237514.png'" mode="scaleToFill"/>
<view class="end-time flex ai-center"> <view class="end-time flex ai-center">
<text class="text-tip">倒计时:</text> <count-down-unit
<count-down-unit :isDay="true" isSecond :dayText="'天'" :hourText="':'" :minuteText="':'" :isDay="true"
:secondText="false" isSecond
:datatime="item.limitEndTimeMillis"></count-down-unit> :dayText="'天'"
:hourText="':'"
:minuteText="':'"
:secondText="false"
:datatime="item.limitEndTimeMillis"
/>
</view> </view>
</view> </view>
<view class="content flex ai-end"> <view class="content flex ai-end">
<image class="img-cover flex-0" :src="item.image" <image
mode="scaleToFill"/> :src="item.image"
class="img-cover flex-0"
mode="scaleToFill"
/>
<view class="info-box flex flex-col jc-between"> <view class="info-box flex flex-col jc-between">
<view class="more-t">{{ item.title }}</view> <view class="more-t">{{ item.title }}</view>
<view class="line-price flex jc-between ai-center"> <view class="line-price flex jc-between ai-center">
@@ -49,51 +67,89 @@
</view> </view>
</view> </view>
</view> </view>
<view class="nav-box flex ai-center"> <view class="nav-box flex ai-center">
<view class="img-section"> <view class="img-section">
<image class="img-hot flex-0" :src="webUrl+'/20230311090049756844.png'" mode="scaleToFill"/> <image
:src="webUrl+'/20230311090049756844.png'"
class="img-hot flex-0"
mode="scaleToFill"
/>
</view> </view>
<view class="nav-line flex"> <view class="nav-line flex">
<view class="nav-item flex-0 flex flex-col jc-end ai-center" :class="{'active':index===seckillTimeIndex}" <view
v-for="(item,index) in seckillTime" :key="index" @click="navChange(index)"> v-for="(item,index) in seckillTime"
:key="index"
:class="{'active':index === seckillTimeIndex}"
class="nav-item flex-0 flex flex-col jc-end ai-center"
@click="navChange(index)"
>
<view class="time">{{ item.time }}</view> <view class="time">{{ item.time }}</view>
<view class="tag">{{ item.state }}</view> <view class="tag">{{ item.state }}</view>
</view> </view>
</view> </view>
</view> </view>
<view class="list-box"> <view class="list-box">
<view class="item flex" v-for="(item,index) in list" :key="index" <template v-if="list.length > 0">
@click="goGoodsConByProductID(item,seckillTime[seckillTimeIndex].status)"> <view
<image class="img-cover flex-0" :src="item.image" v-for="(item, index) in list"
mode="scaleToFill"/> :key="index"
<view class="content flex flex-col jc-between"> class="item flex"
<view class="top-section"> @click="goGoodsConByProductID(item,seckillTime[seckillTimeIndex].status)"
<!-- style="height: 150rpx"--> >
<view class="more-t">{{ item.title }}</view> <image
<view class="company">{{ item.unitName }}</view> :src="item.image"
</view> class="img-cover flex-0"
<view> mode="scaleToFill"
<view class="line-price flex jc-between ai-center"> />
<view class="flex ai-end"> <view class="content flex flex-col jc-between">
<view>秒杀价</view> <view class="top-section">
<view class="price">{{ item.price }}</view> <view class="more-t">{{ item.title }}</view>
</view>
<view class="advance flex jc-center ai-center" v-if="seckillTime[seckillTimeIndex].status>1">即将开始
</view>
</view> </view>
<view class="path-box flex jc-between ai-center" <view class="line-price">
:style="{'backgroundImage':`url(${webUrl}/20221222155107931036.png)`}" <!-- <view class="line-price flex jc-between ai-center">
v-if="seckillTime[seckillTimeIndex].status===1"> <view class="flex ai-end">
<view class="sale flex ai-center">已抢{{ item.sales }}</view> <view>秒杀价</view>
<view class="btn">立即抢购</view> <view class="price">{{ item.price }}</view>
</view>
<view
v-if="seckillTime[seckillTimeIndex].status > 1"
class="advance flex jc-center ai-center"
>
即将开始
</view>
</view>
<view
v-if="seckillTime[seckillTimeIndex].status === 1"
:style="{'backgroundImage':`url(${webUrl}/20221222155107931036.png)`}"
class="path-box flex jc-between ai-center"
>
<view class="sale flex ai-center">已抢{{ item.sales }}</view>
<view class="btn">立即抢购</view>
</view> -->
<view class="number flex">
<view class="bg">
已抢{{ item.sales }}
</view>
<text class="txt"></text>
</view>
<view class="price-wrap flex">
<view class="price-txt">
秒杀价
<text class="txt">{{ item.price }}</text>
</view>
<view class="btn">
<image
:src="webUrl + '/page/seckill/btn.png'"
class="btn-img"
/>
</view>
</view>
</view> </view>
</view> </view>
</view> </view>
</view> </template>
<no-good-data v-else />
</view> </view>
</view> </view>
</template> </template>
@@ -105,11 +161,13 @@ import {mapGetters} from "vuex";
import cookie from "@/utils/store/cookie"; import cookie from "@/utils/store/cookie";
import {userBindParent} from "@/api/user"; import {userBindParent} from "@/api/user";
import {getUrlParam} from "@/utils/common.js"; import {getUrlParam} from "@/utils/common.js";
import NoGoodData from '@/components/good/NoData'
export default { export default {
name: "seckill", name: "seckill",
components: { components: {
CountDownUnit CountDownUnit,
NoGoodData
}, },
data() { data() {
return { return {
@@ -339,24 +397,21 @@ export default {
/deep/ .time { /deep/ .time {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 4rpx 10rpx 4rpx 15rpx;
border-radius: 4rpx;
font-size: 26rpx; font-size: 26rpx;
background-color: #E02619;
color: #fff;
box-shadow: 1px 1px 1px rgba(0,0,0,0.16);
.timeTxt { .styleAll {
color: #E62113; margin: 0 12rpx;
} }
.unit { .unit {
display: inline-flex; display: inline-flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
width: 26rpx;
height: 32rpx;
margin: 0 2rpx;
background: #E02619;
color: #fff;
box-shadow: 2rpx 2rpx 2rpx rgba(0, 0, 0, 0.16);
border-radius: 4rpx;
font-weight: bold;
} }
} }
} }
@@ -556,4 +611,48 @@ export default {
} }
} }
} }
.line-price {
.number {
width: 82px;
height: 24px;
border-radius: 12px;
line-height: 24px;
color: #fff;
font-size: 12px;
font-weight: bold;
background: rgba(250,181,176,0.39);
box-shadow: 1px 1px 1px rgba(0,0,0,0.16);
.bg {
z-index: 1;
height: 100%;
padding: 0 4px 0 12px;
margin: 0 2px 0 0;
border-radius: 12px;
background-color: #E92727;
}
}
.price-wrap {
align-items: flex-end;
.price-txt {
flex: 1;
height: 24px;
padding: 4px 8px;
color: #fff;
font-size: 12px;
background: linear-gradient(270deg, #FFFFFE 0%, #EB5015 100%);
border-radius: 4px;
.txt {
font-size: 18px;
font-weight: bold;
}
}
.btn {
margin: 0 0 0 -16px;
.btn-img {
width: 42px;
height: 43px;
}
}
}
}
</style> </style>
+17 -6
View File
@@ -9,12 +9,23 @@
</view> </view>
</view> </view>
<view class="manage flex jc-end ai-center" @click="changeManage" v-if="!isManage"> <view
<image :src="webUrl+'/20240107224533038041.png'" mode="scaleToFill"/> v-if="!isManage"
管理 class="manage flex jc-end"
>
<view class="flex ai-center" @click="changeManage">
<image :src="webUrl+'/20240107224533038041.png'" mode="scaleToFill"/>
管理
</view>
</view> </view>
<view class="manage flex jc-end ai-center" style="color:#C41617" @click="changeManage" v-else> <view
退出管理 v-else
class="manage flex jc-end ai-center"
style="color:#C41617"
@click="changeManage"
>
<view>退出管理</view>
</view> </view>
<!--商品列表--> <!--商品列表-->
<scroll-view class="scroll-box" :class="{'manage-state':isManage}" scroll-y <scroll-view class="scroll-box" :class="{'manage-state':isManage}" scroll-y
@@ -402,7 +413,7 @@ export default {
} }
.manage { .manage {
margin: 12rpx 32rpx 18rpx; padding: 15rpx 32rpx;
color: #333333; color: #333333;
font-size: 28rpx; font-size: 28rpx;
+45
View File
@@ -1059,6 +1059,51 @@ export function chooseImage(callback) {
}); });
} }
export function chooseVideoToUpload(callback) {
uni.chooseVideo({
count: 1,
sourceType: ['album', 'camera'],
success: res => {
const { tempFilePath, size } = res
if (size / 1024 / 1024 > 30) {
uni.showToast({
title: '视频文件超过30MB',
icon: 'none',
duration: 2000
})
return
}
uni.showLoading({
title: '视频上传中',
mask: true
})
uni.uploadFile({
url: `${VUE_APP_API_URL}/api/upload`,
filePath: tempFilePath,
header: {
Authorization: 'Bearer ' + store.getters.token
},
name: 'file',
success: response => {
if (callback) {
callback(JSON.parse(response.data).link)
}
},
fail: err => {
uni.showToast({
title: '上传视频失败' + err,
icon: 'none',
duration: 2000
})
},
complete: () => {
uni.hideLoading()
}
})
}
})
}
export function moreImage(count, callback) { export function moreImage(count, callback) {
uni.chooseImage({ uni.chooseImage({
count, count,
+1 -1
View File
@@ -69,7 +69,7 @@ export default {
methods: { methods: {
goCity() { goCity() {
uni.redirectTo({ uni.redirectTo({
url: `/components/chose-city/chose-city?type=0&city=${this.cityName}` url: `/pages/chose-city/chose-city?type=0&city=${this.cityName}`
}) })
}, },
goDetils(id) { goDetils(id) {
+1 -1
View File
@@ -78,7 +78,7 @@ export default {
}, },
goCity() { goCity() {
uni.redirectTo({ uni.redirectTo({
url: `/components/chose-city/chose-city?type=1&city=${this.cityName}` url: `/pages/chose-city/chose-city?type=1&city=${this.cityName}`
}) })
}, },
goStore: function (item) { goStore: function (item) {