Commit 89bf3baa by 李嘉林

Merge branch 'mini-zhibo' into product_dev

parents 3eda3608 a5de42a2
import { requestPOST, requestGET, requestPOST1 } from "@/utils/request.js";
export default {
// 查询直播详情
getLiveInfo(options) {
return requestPOST1(`${process.env.OLSHOP_URL}/liveBroadcastInfo/getLiveBroadcastInfoByIds?liveBroadcastId=${options}`);
},
// 查询商品详情
getProductInfo(options) {
return requestPOST1(`${process.env.OLSHOP_URL}/product/get_product_info?productId=${options}`);
},
// 查询所有产品规格详情
getProductGoodsByProductInfo(options) {
return requestPOST1(`${process.env.OLSHOP_URL}/product/get_product_goods_by_product_info?productInfoId=${options}`);
},
// 获取商品所有规格
getProductGoodsSpecifications(options) {
return requestPOST1(`${process.env.OLSHOP_URL}/product/get_goods_specifications?productId=${options}`);
},
// 查询产品信息
getProductGoodsByMixId(options) {
return requestPOST1(`${process.env.OLSHOP_URL}/product/get_product_goods_by_mix_id?productGoodsMixId=${options}`);
},
// 添加购物车
addCart(options) {
return requestPOST(`${process.env.OLSHOP_URL}/cart/add_item`, options);
},
// 实时查询直播状态
getLiveStateById(options) {
return requestPOST(`${process.env.OLSHOP_URL}/liveBroadcastInfo/getLiveStateById`, options);
},
// 用户进入和退出直播间埋点接口
userEntryOrExitsLiveRoom(options) {
return requestPOST(`${process.env.OLSHOP_URL}/liveBroadcastInfo/userEntryOrExitsLiveRoom`, options);
},
// 提交直播评论
addGuestbook(options) {
return requestPOST(`${process.env.OLSHOP_URL}/liveBroadcastInfo/addGuestbook`, options);
},
// 直播间点赞接口
addLiveLikeByUser(options) {
return requestPOST(`${process.env.OLSHOP_URL}/liveBroadcastInfo/addLiveLikeByUser`, options);
},
// 直播中商品列表
getListByLiveBroadcastId(options) {
return requestGET(`${process.env.OLSHOP_URL}/liveBroadcastGoods/getListByLiveBroadcastId?id=${Number(options)}`);
},
// 单次直播数据统计接口
getLiveStatisticsById(options) {
return requestPOST(`${process.env.OLSHOP_URL}/liveBroadcastInfo/getLiveStatisticsById`,options);
},
// 商品点击埋点记录
addLiveUserGoodsByUser(options) {
return requestPOST(`${process.env.OLSHOP_URL}/liveBroadcastInfo/addLiveUserGoodsByUser`,options);
},
// 添加订阅和推送
addLiveNoticeByCustomer(options) {
return requestPOST(`${process.env.OLSHOP_URL}/broadcastReminderRecord/addLiveNoticeByCustomer`,options);
},
// 获取小程序码
getLiveQRCode(options) {
return requestGET(`${process.env.OLSHOP_URL}/liveBroadcastInfo/getLiveQRCode?id=${options}`);
},
};
\ No newline at end of file
{ {
"pages": [ "pages": [
"pages/index/main", "pages/index/main",
"pages/livedPoster/main",
"pages/lived/main",
"pages/login/main", "pages/login/main",
"pages/wxPay/main", "pages/wxPay/main",
"pages/counter/main", "pages/counter/main",
......
<template>
<!-- 公告组件 -->
<div class="livedAnnouncement" v-show="isShow">
<scroll-view :style="{'max-height': '20vh','width':'40vw'}" :scroll-y="true" :scroll-top="scrollTop" :scroll-with-animation="true">
<div class="label">
<span class="labelTit">公告:</span><span class="test">{{liveNotice}}</span>
</div>
</scroll-view>
</div>
</template>
<script type="text/ecmascript-6">
export default {
props:["liveNotice"],
name: "",
data() {
return {
isShow:true,
scrollTop:0,
};
},
components: {},
computed: {},
created() {},
onLoad(){
console.log('----公告')
this.isShow=true;
setTimeout(() => {
this.scrollTop=1000;
}, 2000);
setTimeout(() => {
this.isShow=false;
}, 7000);
},
mounted() {},
methods: {}
};
</script>
<style lang="scss" scoped>
.livedAnnouncement{
margin-left:12px;
width: 40vw;
background: rgba(#000,0.4);
border-radius: 10px;
padding: 6px;
margin-bottom: 10px;
animation:toLeft 6s linear;
opacity: 0;
span{
font-size: 14px;
color: #f1f1f1;
}
.label{
.labelTit{
color: #f9a93c;
}
}
}
@keyframes toLeft {
0%{
opacity: 1;
}
80%{
opacity: 0.6;
}
100%{
opacity: 0;
}
}
</style>
<template>
<!-- 讲解商品 -->
<div class="livedExplainingCommodities">
<div class="goods clearfix" v-if="!showFixedGoods">
<div class="goodsList" :class="{isEC:item.upperScreenState==1}" v-for="(item,index) in list" :key="index">
<img :src="item.productImgUrl" alt />
<p class="num">{{item.number}}</p>
<div class="explain" v-if="item.upperScreenState==1">讲解中</div>
</div>
</div>
<!-- 左上角展示讲解中商品 -->
<div class="fixedGoods" v-else-if="showFixedGoods&&fixedGoodsList&&fixedGoodsList.length>0">
<div class="goodsList" v-for="(item,index) in fixedGoodsList" :key="index">
<img :src="item.productImgUrl" alt />
<p class="num">{{item.number}}</p>
<div class="explain" v-if="item.upperScreenState==1">讲解中</div>
</div>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import { DFSImg } from "@/utils/index";
export default {
props: ["updateGoods", "goodsList"],
name: "",
data() {
return {
showFixedGoods: false, //展示讲解中商品方式 false底部|true左侧固定
list: [],
// 讲解中浮动商品
fixedGoodsList: [],
firstCom:true,//首次进入
};
},
watch: {
updateGoods() {
if(this.firstCom==true){
this.list=[];
this.firstCom=false;
let arr1=[];
let arr2=[];
this.goodsList.forEach((item,index)=>{
if(item.upperScreenState==1){
arr1.push(item);
}else if(item.upperScreenState==0){
arr2.push(item);
}
});
this.list=[...arr1,...arr2];
setTimeout(() => {
this.fixedGoodsList = arr1 ? arr1 : [];
this.showFixedGoods = true;
}, 5000);
}else{
if(!this.equalsObj(this.list, this.goodsList)){
let newArr=[];
newArr=this.goodsList.filter((item,index)=>{
if (item.upperScreenState==1) {
return item;
}
});
if(newArr){
this.fixedGoodsList=newArr;
}
}
}
}
},
components: {},
computed: {},
created() {},
onLoad() {},
onUnload() {
this.fixedGoodsList = [];
this.showFixedGoods = false;
},
mounted() {},
methods: {
/**
* 判断此对象是否是Object类型
* @param {Object} obj
*/
isObject(obj) {
return Object.prototype.toString.call(obj) === "[object Object]";
},
/**
* 判断此类型是否是Array类型
* @param {Array} arr
*/
isArray(arr) {
return Object.prototype.toString.call(arr) === "[object Array]";
},
/**
* 深度比较两个对象是否相同
* @param {Object} oldData
* @param {Object} newData
*/
equalsObj(oldData, newData) {
// 类型为基本类型时,如果相同,则返回true
if (oldData === newData) return true;
if (
this.isObject(oldData) &&
this.isObject(newData) &&
Object.keys(oldData).length === Object.keys(newData).length
) {
// 类型为对象并且元素个数相同
// 遍历所有对象中所有属性,判断元素是否相同
for (const key in oldData) {
if (oldData.hasOwnProperty(key)) {
if (!this.equalsObj(oldData[key], newData[key]))
// 对象中具有不相同属性 返回false
return false;
}
}
} else if (
this.isArray(oldData) &&
this.isArray(oldData) &&
oldData.length === newData.length
) {
// 类型为数组并且数组长度相同
for (let i = 0, length = oldData.length; i < length; i++) {
if (!this.equalsObj(oldData[i], newData[i]))
// 如果数组元素中具有不相同元素,返回false
return false;
}
} else {
// 其它类型,均返回false
return false;
}
// 走到这里,说明数组或者对象中所有元素都相同,返回true
return true;
}
}
};
</script>
<style lang="scss" scoped>
img {
display: block;
}
.fl {
float: left;
}
/*清除浮动*/
.clearfix {
zoom: 1;
}
.clearfix:after {
clear: both;
content: ".";
display: block;
width: 0;
height: 0;
visibility: hidden;
}
.livedExplainingCommodities {
width: 100%;
padding: 0 12px;
overflow-x: auto;
.goods {
overflow-x: auto;
white-space: nowrap;
overflow-y: hidden;
margin-bottom: 10px;
.goodsList {
display: inline-block;
position: relative;
width: 30vw;
height: 30vw;
border: 1px solid #949494;
margin-right: 10px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
.num {
position: absolute;
top: 0;
left: 0;
color: #fff;
font-size: 12px;
background: #666;
padding: 2px 4px;
border-bottom-right-radius: 6px;
}
.explain {
position: absolute;
top: 0;
right: 0;
color: #fff;
font-size: 12px;
background: #ff3334;
padding: 2px 4px;
border-bottom-left-radius: 6px;
}
}
}
.isEC {
border-color: #ff3334;
}
.fixedGoods {
position: fixed;
top: 14vh;
left: 12px;
.goodsList {
width: 22vw;
height: 22vw;
border: 1px solid #ff3334;
margin-right: 10px;
overflow: hidden;
margin-bottom: 10px;
position: relative;
padding: 2px;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
.num {
position: absolute;
top: 0;
left: 0;
color: #fff;
font-size: 12px;
background: #666;
padding: 2px 4px;
border-bottom-right-radius: 6px;
}
.explain {
position: absolute;
top: 0;
right: 0;
color: #fff;
font-size: 12px;
background: #ff3334;
padding: 2px 4px;
border-bottom-left-radius: 6px;
}
}
}
}
</style>
<template>
<div class="livedGoodsList">
<van-popup
:show="showDia"
position="bottom"
custom-style="height: 50vh;padding:14px;border-top-left-radius:10px;border-top-right-radius:10px;"
:close-on-click-overlay="true"
@close="closeDia"
>
<div class="list" v-if="list.length>0">
<div class="item" v-for="(item,index) in list" :key="index">
<div class="img" @click="toGoodsInfo(item)">
<img v-if="item.productImgUrl" :src="item.productImgUrl" alt />
</div>
<div class="info">
<p class="name line-clamp2">{{item.productName}}</p>
<div class="bottom">
<div class="price">
<p>
<span></span>
<span>{{item.minPrice}}</span>
</p>
<!-- <p class="del">
<span></span>
<span>{{999}}</span>
</p>-->
</div>
<div class="icon" @click="isLogin(item)">
<van-icon name="shopping-cart" />
</div>
</div>
</div>
</div>
</div>
<div style="text-align:center;font-size:16px;padding-top:10px;" v-else>暂无商品</div>
</van-popup>
<!-- 选择规格弹层 -->
<livedSelectionSpe
v-if="showSpe"
:show="showSpe"
:productInfoId="itemGoods.productId"
:minSale="itemGoods.minSale"
:maxSale="itemGoods.maxSale"
:goodsImg="itemGoods.goodsImg"
:minSuggestedRetailPrice="itemGoods.minSuggestedRetailPrice"
:maxSuggestedRetailPrice="itemGoods.maxSuggestedRetailPrice"
:goodsLowerShelf="itemGoods.goodsLowerShelf"
@closeSpeDia="closeSpeDia"
></livedSelectionSpe>
</div>
</template>
<script type="text/ecmascript-6">
import livedSelectionSpe from "@/components/livedModel/livedSelectionSpe";
import { DFSImg } from "@/utils/index";
import live from "@/api/live";
export default {
props:["showDia","updateGoods","goodsList"],
name: "",
data() {
return {
liveId: 0,
list: [],
itemGoods: {}, //选中商品
showSpe: false
};
},
components: {
livedSelectionSpe
},
watch:{
updateGoods(){
this.list=this.goodsList;
this.list.forEach((item, index) => {
item.minPrice = Number(item.minPrice);
});
},
},
computed: {},
created() {},
onLoad(options) {
let params = JSON.parse(options.params);
this.liveId = params.liveId;
},
mounted() {},
methods: {
// 关闭
closeDia() {
this.$emit("changeStatus");
},
// 是否登录
isLogin(val) {
let _this = this;
wx.getStorage({
key: "sessionid",
success(res) {
_this.showSpeDia(val);
},
fail(res) {
console.log("未登录------150");
// 跳转登录页
let backUrl = "/lived/main";
let query = {
liveId: _this.liveId,
fromType: "mini"
};
let url = `/pages/login/main?back=${backUrl}&params=${JSON.stringify(
query
)}`;
wx.navigateTo({
url: url
});
}
});
},
showSpeDia(val) {
if (val.multiSpecificationFlag != 1) {
// 不是多规格直接加入购物车
live
.addCart([{ productGoodsId: val.productGoodsId, qty: 1}])
.then(res => {
if (res.data.code == 200) {
wx.showToast({
title: "加入成功",
icon: "success"
});
this.showSize = false;
} else {
wx.showToast({
title: res.data.msg,
icon: "none"
});
}
});
return;
}
let productId = val.productId;
this.itemGoods.productId = productId;
wx.showLoading({
title: "加载中..."
});
live.getProductInfo(productId).then(res => {
wx.hideLoading();
if (res.data.code == 200) {
this.itemGoods.maxSale = Number(
res.data.data.maxSuggestedRetailPrice
);
this.itemGoods.minSale = Number(
res.data.data.minSuggestedRetailPrice
);
this.itemGoods.maxDiscountPrice = Number(
res.data.data.maxDiscountPrice
);
this.itemGoods.minDiscountPrice = Number(
res.data.data.minDiscountPrice
);
this.itemGoods.productNature = res.data.data.productNature;
this.itemGoods.goodsLowerShelf =
res.data.data.saleStatus != 1 ? true : false; //1 上架 0下架 true 下架
if (
res.data.data.productPictures &&
res.data.data.productPictures.length > 0
) {
this.itemGoods.goodsImg = DFSImg(
res.data.data.productPictures[0].url
);
}
this.showSpe = true;
} else {
wx.showToast({
title: res.data.msg,
icon: "none"
});
}
});
},
closeSpeDia() {
this.showSpe = false;
},
// 到商品详情
toGoodsInfo(val) {
// 点击商品埋点
let info={
liveBroadcastId:Number(this.liveId),
liveBroadcastGoodsId:Number(val.productId),
}
live.addLiveUserGoodsByUser(info).then(res=>{});
let query = {
fromLived: 1,
liveId: this.liveId
};
let backPath = `/goods/${val.productId}`;
wx.reLaunch({
url: `../index/main?from=livedToGoodsInfo&backpath=${
backPath
}&params=${JSON.stringify(query)}`
});
}
}
};
</script>
<style lang="scss" scoped>
.livedGoodsList {
.list {
.item {
padding: 10px 4px;
display: flex;
align-items: center;
.img {
width: 70px;
height: 70px;
border-radius: 6px;
overflow: hidden;
background: #999;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.info {
flex: 1;
height: 80px;
margin-left: 16px;
color: #333;
font-size: 16px;
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
text-align: left;
}
.bottom {
display: flex;
justify-content: space-between;
align-items: center;
span {
color: #ff0000;
}
.price {
font-size: 18px;
.del {
font-size: 16px;
text-decoration: line-through;
span {
color: #666;
}
}
}
.icon {
font-size: 22px;
color: #ff8181;
}
}
}
}
}
}
</style>
<template>
<!-- 直播结束组件 -->
<div class="livedIsEnd">
<div class="end">
<p class="endTxt">直播已结束</p>
<p class="time">
<span>直播时长:</span>
<span>{{endInfo.liveTime}}</span>
</p>
<div class="data">
<div>
<p>{{endInfo.watchNum}}</p>
<p>观看</p>
</div>
<div>
<p>{{endInfo.guestBookNum}}</p>
<p>评论</p>
</div>
<div>
<p>{{endInfo.likeNum}}</p>
<p></p>
</div>
</div>
<!-- 商品列表 -->
<div class="goodsList" v-if="list.length>0">
<div class="tit">
<span>商品列表</span>
<span>({{list.length}})</span>
</div>
<div class="list">
<div class="item" v-for="(item,index) in list" :key="index" :class="{'itemBorder':index!=list.length-1}">
<div class="img" @click="toGoodsInfo(item)">
<img :src="item.productImgUrl" alt />
</div>
<div class="info">
<p class="name line-clamp2">{{item.productName}}</p>
<div class="price">
<p>
<span></span>
<span>{{item.minPrice}}</span>
</p>
<div class="icon" @click="isLogin(item)">
<van-icon name="shopping-cart" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 选择规格弹层 -->
<livedSelectionSpe
v-if="showSpe"
:show="showSpe"
:productInfoId="itemGoods.productId"
:minSale="itemGoods.minSale"
:maxSale="itemGoods.maxSale"
:goodsImg="itemGoods.goodsImg"
:minSuggestedRetailPrice="itemGoods.minSuggestedRetailPrice"
:maxSuggestedRetailPrice="itemGoods.maxSuggestedRetailPrice"
:goodsLowerShelf="itemGoods.goodsLowerShelf"
@closeSpeDia="closeSpeDia"
></livedSelectionSpe>
</div>
</template>
<script type="text/ecmascript-6">
import livedSelectionSpe from "@/components/livedModel/livedSelectionSpe";
import { DFSImg } from "@/utils/index";
import live from "@/api/live";
export default {
props: ["updateGoods", "goodsList", "endInfo"],
name: "",
data() {
return {
list: [],
liveId: 0,
itemGoods: {}, //选中商品
showSpe: false
};
},
watch: {
updateGoods() {
this.list = this.goodsList;
}
},
components: {
livedSelectionSpe
},
computed: {},
onLoad(options) {
let params = JSON.parse(options.params);
this.liveId = params.liveId;
},
created() {},
mounted() {},
methods: {
// 到商品详情
toGoodsInfo(val) {
// 点击商品埋点
let info={
liveBroadcastId:Number(this.liveId),
liveBroadcastGoodsId:Number(val.productId),
}
live.addLiveUserGoodsByUser(info).then(res=>{});
let query = {
fromLived: 1,
liveId: this.liveId
};
let backPath = `/goods/${val.productId}`;
wx.reLaunch({
url: `../index/main?from=livedToGoodsInfo&backpath=${backPath}&params=${JSON.stringify(
query
)}`
});
},
// 是否登录
isLogin(val) {
let _this = this;
wx.getStorage({
key: "sessionid",
success(res) {
_this.showSpeDia(val);
},
fail(res) {
console.log("未登录------150");
// 跳转登录页
let backUrl = "/lived/main";
let query = {
liveId: _this.liveId,
fromType: "mini"
};
let url = `/pages/login/main?back=${backUrl}&params=${JSON.stringify(
query
)}`;
wx.navigateTo({
url: url
});
}
});
},
showSpeDia(val) {
if (val.multiSpecificationFlag != 1) {
// 不是多规格直接加入购物车
live
.addCart([{ productGoodsId: val.productGoodsId, qty: 1 }])
.then(res => {
if (res.data.code == 200) {
wx.showToast({
title: "加入成功",
icon: "success"
});
this.showSize = false;
} else {
wx.showToast({
title: res.data.msg,
icon: "none"
});
}
});
return;
}
let productId = val.productId;
this.itemGoods.productId = productId;
wx.showLoading({
title: "加载中..."
});
live.getProductInfo(productId).then(res => {
wx.hideLoading();
if (res.data.code == 200) {
this.itemGoods.maxSale = Number(
res.data.data.maxSuggestedRetailPrice
);
this.itemGoods.minSale = Number(
res.data.data.minSuggestedRetailPrice
);
this.itemGoods.maxDiscountPrice = Number(
res.data.data.maxDiscountPrice
);
this.itemGoods.minDiscountPrice = Number(
res.data.data.minDiscountPrice
);
this.itemGoods.productNature = res.data.data.productNature;
this.itemGoods.goodsLowerShelf =
res.data.data.saleStatus != 1 ? true : false; //1 上架 0下架 true 下架
if (
res.data.data.productPictures &&
res.data.data.productPictures.length > 0
) {
this.itemGoods.goodsImg = DFSImg(
res.data.data.productPictures[0].url
);
}
this.showSpe = true;
} else {
wx.showToast({
title: res.data.msg,
icon: "none"
});
}
});
},
closeSpeDia() {
this.showSpe = false;
}
}
};
</script>
<style lang="scss" scoped>
.line-clamp2 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
line-height: 22px;
word-break: break-all;
}
.livedIsEnd {
position: absolute;
top: 20vh;
bottom: 0;
left: 0;
right: 0;
display: flex;
flex-direction: column;
align-items: center;
.end {
p {
text-align: center;
color: #fff;
}
.endTxt {
font-size: 30px;
font-weight: 400;
}
.time {
margin-top: 10px;
font-size: 16px;
}
.data {
margin-top: 20px;
width: 70vw;
display: flex;
justify-content: space-around;
align-items: center;
& > div {
p {
text-align: center;
font-size: 20px;
}
}
}
.goodsList {
position: absolute;
bottom: 0;
left: 0;
background: rgba(#000, 0.4);
border-top-left-radius: 10px;
border-top-right-radius: 10px;
padding: 12px;
width: 100%;
box-sizing: border-box;
p,
span {
color: #fff;
}
.tit {
font-size: 16px;
padding: 0 4px 6px 0;
}
.list {
max-height: 50vh;
overflow-y: auto;
.item {
padding: 14px 4px;
display: flex;
.img {
width: 100px;
height: 100px;
border-radius: 6px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.info {
flex: 1;
height: 100px;
margin-left: 16px;
color: #fff;
font-size: 16px;
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
text-align: left;
}
.price {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 18px;
span {
color: #ff0000;
}
.icon {
font-size: 22px;
color: #ff8181;
}
}
}
}
.itemBorder{
border-bottom: 1px solid #b8b8b8;
}
}
}
}
}
</style>
<template>
<!-- 评论模块 -->
<div class="livedIsMsg" v-if="list.length>0">
<div class="list">
<scroll-view :style="{'height': '24vh','width':'52vw'}" :scroll-y="true" :scroll-top="scrollTop" :scroll-with-animation="true" @scrolltolower="scrolltolower">
<div class="item flex" v-for="(item,index) in list" :key="index">
<div class="user">
<p class="live"></p>
<div class="name">
<span class="user">{{item.customerName}}</span><span class="test">{{item.guestbookContent}}</span>
</div>
</div>
</div>
</scroll-view>
</div>
</div>
</template>
<script type="text/ecmascript-6">
export default {
props:["guestBookList","updateVal"],
name: "",
data() {
return {
list: [],
scrollTop:0,
};
},
watch:{
updateVal(){
this.list=[...this.list,...this.guestBookList];
this.scrollTop=this.list.length*1000;
}
},
components: {},
computed: {},
created() {},
onLoad(){
},
mounted() {},
methods: {
scrolltolower(){
}
}
};
</script>
<style lang="scss" scoped>
/* 一行否则出现省略号 */
.line-clamp1 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.livedIsMsg {
margin-left: 12px;
padding: 8px;
margin-bottom: 10px;
position: relative;
.list {
width: 50vw;
max-height: 24vh;
overflow: hidden;
bottom: 0;
.item {
width: 50vw;
padding: 4px 0;
display: flex;
align-items: flex-start;
.user {
.name {
color: #f9a93c;
font-size: 14px;
}
}
.test {
font-size: 14px;
color: #f1f1f1;
word-break: break-all;
}
}
}
}
</style>
<template>
<div class="livedposterDia">
<van-popup
:show="showPosterDia"
custom-style="width:100vw;height:100vh;background:transparent;"
:close-on-click-overlay="true"
@close="closeDia"
>
<div class="posterWrap" @click="closeDia">
<canvas canvas-id="posterCanvas" class="myCanvas"></canvas>
<div class="saveBtn" @click="getImg">点击保存海报</div>
</div>
</van-popup>
</div>
</template>
<script type="text/ecmascript-6">
export default {
props: ["showPosterDia", "posterInfo"],
name: "",
data() {
return {
InfoSync: {},
liveId: 0,
params: {},
// 海报中信息
info: {
posterCoverUrl: "",
livedStatus: 1, //直播状态 0未开播 1一开播
livedTime: "3月21日 20:20",
livedTitle: "",
nickName: "",
avatarUrl: "",
miniCode: ""
}
};
},
components: {},
computed: {},
onLoad(options) {
this.params = JSON.parse(options.params);
this.liveId = this.params.liveId;
Object.assign(this.info, this.info, this.posterInfo);
console.log(this.info, "--------------------35");
this.init();
},
created() {},
mounted() {},
methods: {
closeDia() {
this.$emit("closePosterDia");
},
init() {
// wx.showLoading({
// title: "生成中..."
// });
let _this = this;
wx.getUserInfo({
//获取微信用户信息
success: function(res) {
(_this.info.nickName = res.userInfo.nickName),
(_this.info.avatarUrl = res.userInfo.avatarUrl),
_this.initPoster(_this.info);
},
fail: function(res) {
_this.initPoster(_this.info);
}
});
},
initPoster(info) {
console.log(info, "---------------------71");
const InfoSync = wx.getSystemInfoSync();
this.InfoSync = InfoSync;
let bili = InfoSync.windowWidth / 375 * 1;
// let bili = 1;
const ctx = wx.createCanvasContext("posterCanvas");
ctx.setFillStyle("#fff");
ctx.fillRect(0, 0, 310 * bili, 520 * bili);
//封面
this.saveThe(info.posterCoverUrl, path => {
ctx.drawImage(path, 0, 0, 310 * bili, 370 * bili);
ctx.save();
// 微信昵称
ctx.setTextAlign("left");
ctx.setFillStyle("#3F2F00");
ctx.setFontSize(15);
ctx.fillText(info.nickName, 70 * bili, 410 * bili);
ctx.setTextAlign("left");
ctx.setFillStyle("#3F2F00");
ctx.setFontSize(14);
ctx.fillText("邀你一起看直播", 10 * bili, 450 * bili);
// 直播名
ctx.setTextAlign("left");
ctx.setFillStyle("#3F2F00");
ctx.setFontSize(18);
ctx.fillText(info.livedTitle, 10 * bili, 500 * bili);
//圆形头像框
ctx.setStrokeStyle("rgba(0,0,0,0)");
ctx.arc(40 * bili, 400 * bili, 25 * bili, 0, 2 * Math.PI);
ctx.fill();
this.saveThe(info.qrCode, path => {
ctx.drawImage(path, 200 * bili, 390 * bili, 100 * bili, 100 * bili);
ctx.save();
//头像
this.saveThe(info.avatarUrl, path => {
ctx.clip();
ctx.drawImage(path, 10 * bili, 370 * bili, 54 * bili, 54 * bili);
ctx.save();
ctx.stroke();
ctx.draw();
console.log("--------海报生成成功");
});
});
});
},
// 小程序需要将图片下载下来,然后才能绘制到画布上
saveThe(url, callback) {
wx.getImageInfo({
src: url, //服务器返回的图片地址
success: res => {
console.log(res.path, "--------------------131");
callback(res.path);
},
fail: function(res) {}
});
},
getImg() {
this.handleSave();
},
// 点击保存时,将画布生成海报
handleSave() {
var that = this;
wx.showLoading({
title: "正在保存...",
mask: true
});
wx.getSetting({
success(res) {
if (res.authSetting["scope.writePhotosAlbum"]) {
that.saveImg();
} else if (res.authSetting["scope.writePhotosAlbum"] === undefined) {
wx.authorize({
scope: "scope.writePhotosAlbum",
success() {
that.saveImg();
},
fail() {
wx.hideLoading();
wx.showToast({
title: "您没有授权,无法保存到相册",
icon: "none"
});
}
});
} else {
wx.openSetting({
success(res) {
if (res.authSetting["scope.writePhotosAlbum"]) {
that.saveImg();
} else {
wx.showToast({
title: "您没有授权,无法保存到相册",
icon: "none"
});
}
}
});
}
},
fail: err => {
wx.hideLoading();
wx.showToast({
title: "出现了错误,请稍后再试",
icon: "none"
});
}
});
},
saveImg() {
// 按照设备比例去计算图片和画布尺寸
let bili = this.InfoSync.windowWidth / 375 * 1;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 310 * bili,
height: 520 * bili,
destWidth: 310 * bili * this.InfoSync.pixelRatio,
destHeight: 520 * bili * this.InfoSync.pixelRatio,
fileType: "png",
quality: 1,
canvasId: "posterCanvas",
success: function(res) {
wx.hideLoading();
var tempFilePath = res.tempFilePath;
// 需要权限
wx.saveImageToPhotosAlbum({
filePath: tempFilePath,
success(res) {
wx.showModal({
content: "图片已保存到相册,赶紧晒一下吧~",
showCancel: false,
confirmText: "好的",
confirmColor: "#333"
});
},
fail: function(res) {
wx.hideLoading();
wx.showToast({
title: "没有相册权限",
icon: "none",
duration: 2000
});
}
});
},
fail: err => {
wx.hideLoading();
wx.showToast({
title: "出现了错误,请稍后再试",
icon: "none"
});
}
});
},
// 发送给朋友,以图片的方式,先生成临时图片地址,然后调用微信api显示转发
handleShowImg() {
let bili = this.InfoSync.windowWidth / 375 * 1;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 310 * bili,
height: 520 * bili,
destWidth: 310 * bili * this.InfoSync.pixelRatio,
destHeight: 520 * bili * this.InfoSync.pixelRatio,
fileType: "png",
quality: 1,
canvasId: "posterCanvas",
success: function(res) {
wx.hideLoading();
wx.previewImage({
urls: [res.tempFilePath],
current: res.tempFilePath
});
},
fail: err => {
wx.hideLoading();
wx.showToast({
title: "出现了错误,请稍后再试",
icon: "none"
});
}
});
}
}
};
</script>
<style lang="scss" scoped>
.livedposterDia {
.posterWrap {
min-height: calc(100vh - 80px);
padding-top: 80px;
// background-color: #f1f1f1;
.myCanvas {
width: 310px;
height: 520px;
margin: 0 auto;
background: #fff;
}
.saveBtn {
margin: 0 auto;
margin-top: 20px;
background: #f82f31;
width: 50vw;
height: 40px;
border-radius: 40px;
text-align: center;
line-height: 40px;
color: #fff;
}
}
}
</style>
<template>
<div class="notStarted">
<p class="tit">直播倒计时</p>
<div class="time">
<timeDown v-if="startTime" :startTime="startTime"></timeDown>
</div>
<div class="remindBtn" @click="isLogin">开播提醒</div>
</div>
</template>
<script type="text/ecmascript-6">
import live from "@/api/live";
import timeDown from "@/components/livedModel/timeDown";
export default {
props: ["info"],
name: "",
data() {
return {
liveId: 0,
startTime: null
};
},
components: {
timeDown
},
computed: {},
created() {},
onLoad(options) {
let params = JSON.parse(options.params);
this.liveId = params.liveId;
console.log(params, "--------------------126");
this.startTime = this.info.startTime;
},
mounted() {},
methods: {
// 开播提醒
remind() {
let _this = this;
console.log("点击开播,'------------34");
try {
const subscribeMessageObj = this.$store.state.subscribeMessageObj;
if (
subscribeMessageObj &&
Object.keys(subscribeMessageObj).length > 0
) {
// TODO 开播订阅
const tmplIds = [];
for (var key in subscribeMessageObj) {
// 改成开播key
if (key == "start_live") {
tmplIds.push(subscribeMessageObj[key]);
}
}
if (tmplIds.length > 0) {
wx.requestSubscribeMessage({
tmplIds: tmplIds,
success:(res)=> {
if(res.tmplIds[0]=="accept"){
wx.showToast({
title: "您已成功订阅~",
icon: "success"
});
let query = {
liveBroadcastId: Number(_this.liveId),
openId: wx.getStorageSync("openid"),
subMessageTemplateId:tmplIds[0],
};
live.addLiveNoticeByCustomer(query).then(res => {});
}
console.log("message success response: ", res);
},
fail(res) {
console.log("message fail response: ", res);
}
});
}
}
} catch (err) {
console.error("subscribeMessage-err", err);
}
},
// 是否登录
isLogin() {
let _this = this;
wx.getStorage({
key: "sessionid",
success(res) {
_this.remind();
},
fail(res) {
console.log("未登录------150");
// 跳转登录页
let backUrl = "/lived/main";
let query = {
liveId: _this.liveId,
fromType: "mini"
};
let url = `/pages/login/main?back=${backUrl}&params=${JSON.stringify(
query
)}`;
wx.navigateTo({
url: url
});
}
});
}
}
};
</script>
<style lang="scss" scoped>
.notStarted {
position: absolute;
width: 70vw;
top: 40%;
left: 15vw;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.tit {
font-size: 16px;
color: #fff;
}
.time {
margin-top: 16px;
}
.remindBtn {
margin-top: 16px;
height: 20px;
line-height: 20px;
text-align: center;
border-radius: 6px;
color: #fff;
font-size: 18px;
padding: 14px 40px;
background: linear-gradient(to right, #ff877d, #fb566d);
}
}
</style>
\ No newline at end of file
<template>
<!-- 倒计时组件 -->
<div class="days">
<template v-if="days-0>0">
<span class="item">{{days}}</span>
<span class="label"></span>
</template>
<template v-if="hours-0>0">
<span class="item">{{hours}}</span>
<span class="label"></span>
</template>
<span class="item">{{minute}}</span>
<span class="label"></span>
</div>
</template>
<script type="text/ecmascript-6">
let d = null;
// 倒计时方法
if (typeof xcsoft == "undefined") var xcsoft = new function() {}();
xcsoft.countdown = function(a, b, c) {
d = new Object();
var e = 0;
if (typeof a == "object") {
var f = parseInt(new Date().getTime() / 1000);
var g = a.startTime ? parseInt(a.startTime) : 0;
g = g == 0 ? f : g;
var h = a.endTime;
var x = g - f;
d.decimal = parseInt(a.msec ? a.msec : 0);
} else {
var f = 0;
var x = 0;
d.decimal = 0;
var h = a;
var i = h.toString();
if (i.indexOf(".") > 0) {
d.decimal = i.split(".")[1];
if (d.decimal > 3) {
d.decimal = 3;
}
}
}
d.time = h;
d.finish = false;
if (isNaN(h)) {
var j = h.substring(0, 19);
j = j.replace(/-/g, "/");
d.time = new Date(j).getTime() / 1000;
}
var k = d.decimal == 0 ? 100 : 100;
d.day = 0;
d.hour = 0;
d.minute = 0;
d.second = 0;
d.t = setInterval(function() {
e = new Date().getTime();
f = parseInt(e / 1000 + x);
var l = d.time - f;
if (l <= 0) {
e = 0;
l = 0;
}
if (l >= 0) {
d = xcsoft.getTimeObject(d, l);
}
if (d.decimal == 1) {
d.msecZero = d.msec = parseInt(10 - (e % 1000) / 100);
if (d.msec == 10 || l == 0) {
d.msecZero = d.msec = 0;
}
} else if (d.decimal == 2) {
d.msecZero = d.msec = parseInt(100 - (e % 1000) / 10);
if (d.msec < 10) {
d.msecZero = "0" + d.msec;
} else if (d.msec == 100 || l == 0) {
d.msec = 0;
d.msecZero = "0" + d.msec;
}
} else {
d.msecZero = d.msec = parseInt(1000 - e % 1000);
if (d.msec < 10) {
d.msecZero = "00" + d.msec;
} else if (d.msec < 100) {
d.msecZero = "0" + d.msec;
} else if (d.msec == 1000 || l == 0) {
d.msec = 0;
d.msecZero = "00" + d.msec;
}
}
if (b) {
b(d);
}
if (l <= 0 || d.stop == true) {
clearInterval(d.t);
d.finish = true;
if (c) c(d);
}
}, k);
};
xcsoft.getTimeObject = function(a, l) {
var b = 60;
var c = b * b;
var d = 24 * c;
a.days = Math.floor(l / d);
a.year = Math.floor(a.days / 365);
a.day = Math.floor(a.days % 365);
a.hour = Math.floor((l % d) / c);
a.minute = Math.floor((l - (a.days * d + a.hour * c)) / b);
a.second = Math.floor(l % b);
a.dayZero = a.day < 10 ? "0" + a.day : a.day;
a.daysZero = a.days < 10 ? "0" + a.days : a.days;
a.hourZero = a.hour < 10 ? "0" + a.hour : a.hour;
a.minuteZero = a.minute < 10 ? "0" + a.minute : a.minute;
a.secondZero = a.second < 10 ? "0" + a.second : a.second;
return a;
};
export default {
props: ["startTime"],
name: "",
data() {
return {
days: 0,
hours: 0,
minute: 0,
second: 0
};
},
onLoad() {
let _this = this;
console.log(this.startTime, "--------129");
xcsoft.countdown(
this.startTime,
function(time) {
// console.log(time.day,time.hourZero, time.minuteZero, time.secondZero,'--------39')
_this.days = time.dayZero;
_this.hours = time.hourZero;
_this.minute = time.minuteZero;
_this.second = time.secondZero;
},
function(time) {
//倒计时结束后的操作
}
);
},
onUnload() {
// 清除未开播倒计时
d.stop = true;
},
components: {},
computed: {},
mounted() {},
methods: {}
};
</script>
<style lang="scss" scoped>
.days{
font-size: 28px;
font-weight: bold;
color: #fff;
span{
padding: 0 2px;
}
}
</style>
...@@ -88,6 +88,20 @@ export default { ...@@ -88,6 +88,20 @@ export default {
key: "sessionid", key: "sessionid",
data: params.sessionid data: params.sessionid
}); });
} else if (options.from && options.from == "livedToIndex") {
//来自直播详情
this.page = decodeURIComponent(options.backpath);
} else if (options.from && options.from == "livedBackShop") {
//直播页back到商城
this.page = decodeURIComponent(options.backpath);
} else if (options.from && options.from == "livedToGoodsInfo") {
//从直播详情商品列表到商城商品详情
this.page = decodeURIComponent(options.backpath);
this.params += "&" + serialize(options.params);
} else if (options.from && options.from == "livedToOrderConfirm") {
//从直播详情商品列表到商城确认订单
this.page = decodeURIComponent(options.backpath);
this.params += "&" + serialize(options.params);
} else if (options.from && options.from == "login") { } else if (options.from && options.from == "login") {
//来自小程序登录页面 //来自小程序登录页面
this.page = decodeURIComponent(options.backpath); this.page = decodeURIComponent(options.backpath);
...@@ -160,6 +174,9 @@ export default { ...@@ -160,6 +174,9 @@ export default {
}else if(querys.length == 2){ }else if(querys.length == 2){
this.params += `&userId=${querys[1]}` this.params += `&userId=${querys[1]}`
} }
}else if(querys[0] == "coupon"){
this.page = `/personalCenter/coupon/getCoupon`;
this.params+=`&couponId=${querys[1]}`
} }
} }
console.log(querys, "scene"); console.log(querys, "scene");
......
import Vue from 'vue'
import App from './index'
// add this to handle exception
Vue.config.errorHandler = function (err) {
if (console && console.error) {
console.error(err)
}
}
const app = new Vue(App)
app.$mount()
{
"navigationStyle":"custom",
"navigationBarTextStyle": "white",
"disableScroll": true,
"usingComponents": {
"van-button": "/static/vant/button/index",
"van-icon": "/static/vant/icon/index",
"van-popup": "/static/vant/popup/index",
"van-stepper": "/static/vant/stepper/index"
}
}
\ No newline at end of file
<template>
<div class="livedPoster">
<div class="posterWrap">
<canvas canvas-id="posterCanvas" class="myCanvas" @click="getImg"></canvas>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import { serialize, getQueryVariable, DFSImg } from "@/utils/index";
import live from "@/api/live";
export default {
name: "",
data() {
return {
InfoSync: {},
liveId: 0,
params: {},
// 海报中信息
info: {
coverUrl: "",
livedStatus: 1, //直播状态 0未开播 1一开播
livedTime: "3月21日 20:20",
livedTitle: "",
nickName: "",
avatarUrl: "",
miniCode: ""
}
};
},
onLoad(options) {
this.params = JSON.parse(options.params);
this.liveId = this.params.liveId;
Object.assign(this.info,this.info,this.params);
console.log(this.info,'--------------------35');
this.init();
},
onUnload() {},
methods: {
back() {
wx.navigateBack({
delta: 1
});
},
init() {
wx.showLoading({title: '加载中…'})
let liveBroadcastId = this.liveId;
let _this = this;
wx.getUserInfo({
//获取微信用户信息
success: function(res) {
(_this.info.nickName = res.userInfo.nickName),
(_this.info.avatarUrl = res.userInfo.avatarUrl),
_this.initPoster(_this.info);
},
fail: function(res) {
_this.initPoster(_this.info);
}
});
// live.getLiveInfo(liveBroadcastId).then(res => {
// if (res.data.code == 200) {
// let resData = res.data.data;
// this.info.livedTitle = resData.title;
// this.info.livedStatus = resData.liveBroadcastState;
// let cImg = DFSImg(resData.coverUrl);
// if (cImg.indexOf("https") == -1) {
// this.info.coverUrl = cImg.replace("http", "https");
// }
// let newTime = new Date(resData.startTime.replace(/-/g, "/"));
// this.info.livedTime = `${newTime.getMonth() +
// 1}月${newTime.getDate() -
// 1}日 ${newTime.getHours()}:${newTime.getMinutes()}`;
// }
// });
},
initPoster(info) {
console.log(info, "---------------------71");
const InfoSync = wx.getSystemInfoSync();
this.InfoSync = InfoSync;
let bili = InfoSync.windowWidth / 375 * 1;
const ctx = wx.createCanvasContext("posterCanvas");
ctx.setFillStyle("#fff");
ctx.fillRect(0, 0, 310 * bili, 520 * bili);
//封面
this.saveThe(info.coverUrl, path => {
ctx.drawImage(path, 0, 0, 310 * bili, 370 * bili);
ctx.save();
// 微信昵称
ctx.setTextAlign("left");
ctx.setFillStyle("#3F2F00");
ctx.setFontSize(15);
ctx.fillText(info.nickName, 80 * bili, 420 * bili);
ctx.setTextAlign("left");
ctx.setFillStyle("#3F2F00");
ctx.setFontSize(14);
ctx.fillText("邀你一起看直播", 10 * bili, 460 * bili);
// 直播名
ctx.setTextAlign("left");
ctx.setFillStyle("#3F2F00");
ctx.setFontSize(18);
ctx.fillText(info.livedTitle, 10 * bili, 500 * bili);
//圆形头像框
ctx.setStrokeStyle("rgba(0,0,0,0)");
ctx.arc(40 * bili, 410 * bili, 30 * bili, 0, 2 * Math.PI);
ctx.fill();
//头像
this.saveThe(info.avatarUrl, path => {
ctx.clip();
ctx.drawImage(path, 10 * bili, 380 * bili, 70 * bili, 70 * bili);
ctx.save();
ctx.stroke();
ctx.draw();
});
wx.hideLoading();
});
},
// 小程序需要将图片下载下来,然后才能绘制到画布上
saveThe(url, callback) {
wx.getImageInfo({
src: url, //服务器返回的图片地址
success: res => {
callback(res.path);
},
fail: function(res) {}
});
},
getImg() {
this.handleSave();
},
// 点击保存时,将画布生成海报
handleSave() {
var that = this;
wx.showLoading({
title: "正在保存...",
mask: true
});
wx.getSetting({
success(res) {
if (res.authSetting["scope.writePhotosAlbum"]) {
that.saveImg();
} else if (res.authSetting["scope.writePhotosAlbum"] === undefined) {
wx.authorize({
scope: "scope.writePhotosAlbum",
success() {
that.saveImg();
},
fail() {
wx.hideLoading();
wx.showToast({
title: "您没有授权,无法保存到相册",
icon: "none"
});
}
});
} else {
wx.openSetting({
success(res) {
if (res.authSetting["scope.writePhotosAlbum"]) {
that.saveImg();
} else {
wx.showToast({
title: "您没有授权,无法保存到相册",
icon: "none"
});
}
}
});
}
},
fail: err => {
wx.hideLoading();
wx.showToast({
title: "出现了错误,请稍后再试",
icon: "none"
});
}
});
},
saveImg() {
// 按照设备比例去计算图片和画布尺寸
let bili = this.InfoSync.windowWidth / 375 * 1;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 310 * bili,
height: 520 * bili,
destWidth: 310 * bili * this.InfoSync.pixelRatio,
destHeight: 520 * bili * this.InfoSync.pixelRatio,
fileType: "png",
quality: 1,
canvasId: "posterCanvas",
success: function(res) {
wx.hideLoading();
var tempFilePath = res.tempFilePath;
// 需要权限
wx.saveImageToPhotosAlbum({
filePath: tempFilePath,
success(res) {
wx.showModal({
content: "图片已保存到相册,赶紧晒一下吧~",
showCancel: false,
confirmText: "好的",
confirmColor: "#333"
});
},
fail: function(res) {
wx.hideLoading();
wx.showToast({
title: "没有相册权限",
icon: "none",
duration: 2000
});
}
});
},
fail: err => {
wx.hideLoading();
wx.showToast({
title: "出现了错误,请稍后再试",
icon: "none"
});
}
});
},
// 发送给朋友,以图片的方式,先生成临时图片地址,然后调用微信api显示转发
handleShowImg() {
let bili = this.InfoSync.windowWidth / 375 * 1;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 310 * bili,
height: 520 * bili,
destWidth: 310 * bili * this.InfoSync.pixelRatio,
destHeight: 520 * bili * this.InfoSync.pixelRatio,
fileType: "png",
quality: 1,
canvasId: "posterCanvas",
success: function(res) {
wx.hideLoading();
wx.previewImage({
urls: [res.tempFilePath],
current: res.tempFilePath
});
},
fail: err => {
wx.hideLoading();
wx.showToast({
title: "出现了错误,请稍后再试",
icon: "none"
});
}
});
}
}
};
</script>
<style scoped lang="scss">
.livedPoster {
position: relative;
}
.posterWrap {
min-height: calc(100vh - 20px);
padding-top: 20px;
background-color: #f1f1f1;
}
.myCanvas {
width: 310px;
height: 520px;
margin: 0 auto;
background: #fff;
}
</style>
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
\ No newline at end of file
{
"navigationBarTitleText": "点击保存图片"
}
\ No newline at end of file
...@@ -61,7 +61,8 @@ export default { ...@@ -61,7 +61,8 @@ export default {
testd: "", testd: "",
test_sessionId: "", test_sessionId: "",
test_isHaveUnion: "", test_isHaveUnion: "",
test_unionId: "" test_unionId: "",
fromType:'',//来源类型 mini:小程序跳转到当前登录页
}; };
}, },
created() {}, created() {},
...@@ -72,6 +73,8 @@ export default { ...@@ -72,6 +73,8 @@ export default {
} }
if (options.params) { if (options.params) {
this.backParams = serialize(options.params); this.backParams = serialize(options.params);
let params = JSON.parse(options.params);
this.fromType = params.fromType;
} }
this.getshop(); this.getshop();
}, },
...@@ -179,11 +182,14 @@ export default { ...@@ -179,11 +182,14 @@ export default {
if (this.isHaveUnion) { if (this.isHaveUnion) {
wx.hideLoading(); wx.hideLoading();
//是会员 直接登录 //是会员 直接登录
wx.reLaunch({ // 0318写直播改后面注释逻辑相同
url: `../index/main?from=login&backpath=${ // wx.reLaunch({
this.backPath // url: `../index/main?from=login&backpath=${
}&params=${encodeURIComponent(this.backParams)}` // this.backPath
}); // }&params=${encodeURIComponent(this.backParams)}`
// });
// 跳转回小程序页面
this.pushPageType();
} else { } else {
var data = wx_decode( var data = wx_decode(
this.appid, this.appid,
...@@ -210,11 +216,13 @@ export default { ...@@ -210,11 +216,13 @@ export default {
key: "sessionid", key: "sessionid",
data: res.data.data.sessionId data: res.data.data.sessionId
}); });
wx.reLaunch({ // 跳转回小程序页面
url: `../index/main?from=login&backpath=${ this.pushPageType();
this.backPath // wx.reLaunch({
}&params=${encodeURIComponent(this.backParams)}` // url: `../index/main?from=login&backpath=${
}); // this.backPath
// }&params=${encodeURIComponent(this.backParams)}`
// });
} else { } else {
//不是会员需要绑定手机号 //不是会员需要绑定手机号
this.isShowPhone = true; this.isShowPhone = true;
...@@ -232,6 +240,20 @@ export default { ...@@ -232,6 +240,20 @@ export default {
} }
} }
}, },
// 是否跳转h5或小程序
pushPageType(){
if(this.fromType=='mini'){
wx.navigateBack({
delta: 1
});
}else{
wx.reLaunch({
url: `../index/main?from=login&backpath=${
this.backPath
}&params=${encodeURIComponent(this.backParams)}`
});
}
},
getPhoneNumber(e) { getPhoneNumber(e) {
wx.checkSession({ wx.checkSession({
success: () => { success: () => {
...@@ -287,11 +309,13 @@ export default { ...@@ -287,11 +309,13 @@ export default {
key: "sessionid", key: "sessionid",
data: res.data.data.sessionId data: res.data.data.sessionId
}); });
wx.reLaunch({ // 跳转回小程序页面
url: `../index/main?from=login&backpath=${ this.pushPageType();
this.backPath // wx.reLaunch({
}&params=${encodeURIComponent(this.backParams)}` // url: `../index/main?from=login&backpath=${
}); // this.backPath
// }&params=${encodeURIComponent(this.backParams)}`
// });
} }
}) })
.catch(err => { .catch(err => {
...@@ -299,11 +323,13 @@ export default { ...@@ -299,11 +323,13 @@ export default {
}); });
}, },
backMainHandle() { backMainHandle() {
wx.reLaunch({ // 跳转回小程序页面
url: `../index/main?from=login&backpath=${ this.pushPageType();
this.backPath // wx.reLaunch({
}&params=${encodeURIComponent(this.backParams)}` // url: `../index/main?from=login&backpath=${
}); // this.backPath
// }&params=${encodeURIComponent(this.backParams)}`
// });
}, },
eLogin() { eLogin() {
//企业员工登录 //企业员工登录
......
...@@ -6,6 +6,10 @@ const mutations = { ...@@ -6,6 +6,10 @@ const mutations = {
}, },
setSubscribeMessageObj(state, subscribeMessageObj) { setSubscribeMessageObj(state, subscribeMessageObj) {
state.subscribeMessageObj = subscribeMessageObj; state.subscribeMessageObj = subscribeMessageObj;
} },
setOfflineShopCode(state, code) {
state.offlineShopCode = code;
},
}; };
export default mutations export default mutations
\ No newline at end of file
...@@ -2,6 +2,7 @@ const state = { ...@@ -2,6 +2,7 @@ const state = {
spokesmanGroupId: "", spokesmanGroupId: "",
spokesmanShopId: "", spokesmanShopId: "",
spokesmanRelId: "", spokesmanRelId: "",
subscribeMessageObj: {} subscribeMessageObj: {},
offlineShopCode:"",
}; };
export default state export default state
\ No newline at end of file
let shopMixid =process.env.SHOP_MIXID; import store from '../store/index'
let shopMixid = process.env.SHOP_MIXID;
// wx.getStore // wx.getStore
export async function requestGET(url, options) { export async function requestGET(url, options) {
...@@ -8,7 +9,9 @@ export async function requestGET(url, options) { ...@@ -8,7 +9,9 @@ export async function requestGET(url, options) {
data: options, data: options,
method: "GET", method: "GET",
header: { header: {
"Shop-Mixid": shopMixid "Shop-Mixid": shopMixid,
"Offline-Shop-Code": store.state.offlineShopCode,
"dubbo-tag": "ljx"
}, },
success: function (res) { success: function (res) {
resolve(res) resolve(res)
...@@ -28,7 +31,9 @@ export async function requestPOST(url, options) { ...@@ -28,7 +31,9 @@ export async function requestPOST(url, options) {
method: "POST", method: "POST",
header: { header: {
"Shop-Mixid": shopMixid, "Shop-Mixid": shopMixid,
"Authorization": wx.getStorageSync('sessionid') || "" "Authorization": wx.getStorageSync('sessionid') || "",
"Offline-Shop-Code": store.state.offlineShopCode,
"dubbo-tag": "ljx"
}, },
success: function (res) { success: function (res) {
resolve(res) resolve(res)
...@@ -49,7 +54,9 @@ export function requestPOST1(url, options) { ...@@ -49,7 +54,9 @@ export function requestPOST1(url, options) {
header: { header: {
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
"Shop-Mixid": shopMixid, "Shop-Mixid": shopMixid,
Authorization: wx.getStorageSync('sessionid') || "" Authorization: wx.getStorageSync('sessionid') || "",
"Offline-Shop-Code": store.state.offlineShopCode,
"dubbo-tag": "ljx"
}, },
success: function (res) { success: function (res) {
resolve(res) resolve(res)
......
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [button, openType],
props: {
show: Boolean,
title: String,
cancelText: String,
description: String,
round: {
type: Boolean,
value: true
},
zIndex: {
type: Number,
value: 100
},
actions: {
type: Array,
value: []
},
overlay: {
type: Boolean,
value: true
},
closeOnClickOverlay: {
type: Boolean,
value: true
},
closeOnClickAction: {
type: Boolean,
value: true
},
safeAreaInsetBottom: {
type: Boolean,
value: true
}
},
methods: {
onSelect(event) {
const { index } = event.currentTarget.dataset;
const item = this.data.actions[index];
if (item && !item.disabled && !item.loading) {
this.$emit('select', item);
if (this.data.closeOnClickAction) {
this.onClose();
}
}
},
onCancel() {
this.$emit('cancel');
},
onClose() {
this.$emit('close');
},
onClickOverlay() {
this.$emit('click-overlay');
this.onClose();
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-popup": "../popup/index",
"van-loading": "../loading/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<van-popup
show="{{ show }}"
position="bottom"
round="{{ round }}"
z-index="{{ zIndex }}"
overlay="{{ overlay }}"
custom-class="van-action-sheet"
safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
close-on-click-overlay="{{ closeOnClickOverlay }}"
bind:close="onClickOverlay"
>
<view wx:if="{{ title }}" class="van-hairline--bottom van-action-sheet__header">
{{ title }}
<van-icon
name="close"
custom-class="van-action-sheet__close"
bind:click="onClose"
/>
</view>
<view wx:if="{{ description }}" class="van-action-sheet__description">
{{ description }}
</view>
<view wx:if="{{ actions && actions.length }}">
<!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
<button
wx:for="{{ actions }}"
wx:key="index"
open-type="{{ item.openType }}"
style="{{ item.color ? 'color: ' + item.color : '' }}"
class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} van-hairline--top {{ item.className || '' }}"
hover-class="van-action-sheet__item--hover"
data-index="{{ index }}"
bind:tap="onSelect"
bindgetuserinfo="bindGetUserInfo"
bindcontact="bindContact"
bindgetphonenumber="bindGetPhoneNumber"
binderror="bindError"
bindlaunchapp="bindLaunchApp"
bindopensetting="bindOpenSetting"
lang="{{ lang }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
send-message-path="{{ sendMessagePath }}"
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
>
<block wx:if="{{ !item.loading }}">
{{ item.name }}
<text wx:if="{{ item.subname }}" class="van-action-sheet__subname" >{{ item.subname }}</text>
</block>
<van-loading wx:else custom-class="van-action-sheet__loading" size="20px" />
</button>
</view>
<slot />
<view
wx:if="{{ cancelText }}"
class="van-action-sheet__cancel"
hover-class="van-action-sheet__cancel--hover"
hover-stay-time="70"
bind:tap="onCancel"
>
{{ cancelText }}
</view>
</van-popup>
@import '../common/index.wxss';.van-action-sheet{max-height:90%!important;max-height:var(--action-sheet-max-height,90%)!important;color:#323233;color:var(--action-sheet-item-text-color,#323233)}.van-action-sheet__cancel,.van-action-sheet__item{text-align:center;font-size:16px;font-size:var(--action-sheet-item-font-size,16px);line-height:50px;line-height:var(--action-sheet-item-height,50px);background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__cancel--hover,.van-action-sheet__item--hover{background-color:#f2f3f5;background-color:var(--active-color,#f2f3f5)}.van-action-sheet__cancel:before{display:block;content:" ";height:8px;height:var(--action-sheet-cancel-padding-top,8px);background-color:#f7f8fa;background-color:var(--action-sheet-cancel-padding-color,#f7f8fa)}.van-action-sheet__item--disabled{color:#c8c9cc;color:var(--action-sheet-item-disabled-text-color,#c8c9cc)}.van-action-sheet__item--disabled.van-action-sheet__item--hover{background-color:#fff;background-color:var(--action-sheet-item-background,#fff)}.van-action-sheet__subname{margin-left:4px;margin-left:var(--padding-base,4px);font-size:12px;font-size:var(--action-sheet-subname-font-size,12px);color:#646566;color:var(--action-sheet-subname-color,#646566)}.van-action-sheet__header{text-align:center;font-weight:500;font-weight:var(--font-weight-bold,500);font-size:16px;font-size:var(--action-sheet-header-font-size,16px);line-height:44px;line-height:var(--action-sheet-header-height,44px)}.van-action-sheet__description{text-align:center;padding:16px;padding:var(--padding-md,16px);color:#646566;color:var(--action-sheet-description-color,#646566);font-size:14px;font-size:var(--action-sheet-description-font-size,14px);line-height:20px;line-height:var(--action-sheet-description-line-height,20px)}.van-action-sheet__close{position:absolute!important;top:0;right:0;line-height:inherit!important;padding:0 12px;padding:var(--action-sheet-close-icon-padding,0 12px);font-size:18px!important;font-size:var(--action-sheet-close-icon-size,18px)!important;color:#969799;color:var(--action-sheet-close-icon-color,#969799)}.van-action-sheet__loading{display:-webkit-flex!important;display:flex!important;height:50px;height:var(--action-sheet-item-height,50px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { pickerProps } from '../picker/shared';
const COLUMNSPLACEHOLDERCODE = '000000';
VantComponent({
classes: ['active-class', 'toolbar-class', 'column-class'],
props: Object.assign(Object.assign({}, pickerProps), { value: {
type: String,
observer(value) {
this.code = value;
this.setValues();
},
}, areaList: {
type: Object,
value: {},
observer: 'setValues'
}, columnsNum: {
type: null,
value: 3,
observer(value) {
this.setData({
displayColumns: this.data.columns.slice(0, +value)
});
}
}, columnsPlaceholder: {
type: Array,
observer(val) {
this.setData({
typeToColumnsPlaceholder: {
province: val[0] || '',
city: val[1] || '',
county: val[2] || '',
}
});
}
} }),
data: {
columns: [{ values: [] }, { values: [] }, { values: [] }],
displayColumns: [{ values: [] }, { values: [] }, { values: [] }],
typeToColumnsPlaceholder: {}
},
mounted() {
setTimeout(() => {
this.setValues();
}, 0);
},
methods: {
getPicker() {
if (this.picker == null) {
this.picker = this.selectComponent('.van-area__picker');
}
return this.picker;
},
onCancel(event) {
this.emit('cancel', event.detail);
},
onConfirm(event) {
const { index } = event.detail;
let { value } = event.detail;
value = this.parseOutputValues(value);
this.emit('confirm', { value, index });
},
emit(type, detail) {
detail.values = detail.value;
delete detail.value;
this.$emit(type, detail);
},
// parse output columns data
parseOutputValues(values) {
const { columnsPlaceholder } = this.data;
return values.map((value, index) => {
// save undefined value
if (!value)
return value;
value = JSON.parse(JSON.stringify(value));
if (!value.code || value.name === columnsPlaceholder[index]) {
value.code = '';
value.name = '';
}
return value;
});
},
onChange(event) {
const { index, picker, value } = event.detail;
this.code = value[index].code;
this.setValues().then(() => {
this.$emit('change', {
picker,
values: this.parseOutputValues(picker.getValues()),
index
});
});
},
getConfig(type) {
const { areaList } = this.data;
return (areaList && areaList[`${type}_list`]) || {};
},
getList(type, code) {
const { typeToColumnsPlaceholder } = this.data;
let result = [];
if (type !== 'province' && !code) {
return result;
}
const list = this.getConfig(type);
result = Object.keys(list).map(code => ({
code,
name: list[code]
}));
if (code) {
// oversea code
if (code[0] === '9' && type === 'city') {
code = '9';
}
result = result.filter(item => item.code.indexOf(code) === 0);
}
if (typeToColumnsPlaceholder[type] && result.length) {
// set columns placeholder
const codeFill = type === 'province' ? '' : type === 'city' ? COLUMNSPLACEHOLDERCODE.slice(2, 4) : COLUMNSPLACEHOLDERCODE.slice(4, 6);
result.unshift({
code: `${code}${codeFill}`,
name: typeToColumnsPlaceholder[type]
});
}
return result;
},
getIndex(type, code) {
let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
const list = this.getList(type, code.slice(0, compareNum - 2));
// oversea code
if (code[0] === '9' && type === 'province') {
compareNum = 1;
}
code = code.slice(0, compareNum);
for (let i = 0; i < list.length; i++) {
if (list[i].code.slice(0, compareNum) === code) {
return i;
}
}
return 0;
},
setValues() {
const county = this.getConfig('county');
let { code } = this;
if (!code) {
if (this.data.columnsPlaceholder.length) {
code = COLUMNSPLACEHOLDERCODE;
}
else if (Object.keys(county)[0]) {
code = Object.keys(county)[0];
}
else {
code = '';
}
}
const province = this.getList('province');
const city = this.getList('city', code.slice(0, 2));
const picker = this.getPicker();
if (!picker) {
return;
}
const stack = [];
stack.push(picker.setColumnValues(0, province, false));
stack.push(picker.setColumnValues(1, city, false));
if (city.length && code.slice(2, 4) === '00') {
[{ code }] = city;
}
stack.push(picker.setColumnValues(2, this.getList('county', code.slice(0, 4)), false));
return Promise.all(stack)
.catch(() => { })
.then(() => picker.setIndexes([
this.getIndex('province', code),
this.getIndex('city', code),
this.getIndex('county', code)
]))
.catch(() => { });
},
getValues() {
const picker = this.getPicker();
return picker ? picker.getValues().filter(value => !!value) : [];
},
getDetail() {
const values = this.getValues();
const area = {
code: '',
country: '',
province: '',
city: '',
county: ''
};
if (!values.length) {
return area;
}
const names = values.map((item) => item.name);
area.code = values[values.length - 1].code;
if (area.code[0] === '9') {
area.country = names[1] || '';
area.province = names[2] || '';
}
else {
area.province = names[0] || '';
area.city = names[1] || '';
area.county = names[2] || '';
}
return area;
},
reset(code) {
this.code = code || '';
return this.setValues();
}
}
});
{
"component": true,
"usingComponents": {
"van-picker": "../picker/index"
}
}
<van-picker
class="van-area__picker"
active-class="active-class"
toolbar-class="toolbar-class"
column-class="column-class"
show-toolbar
value-key="name"
title="{{ title }}"
loading="{{ loading }}"
columns="{{ displayColumns }}"
item-height="{{ itemHeight }}"
visible-item-count="{{ visibleItemCount }}"
cancel-button-text="{{ cancelButtonText }}"
confirm-button-text="{{ confirmButtonText }}"
bind:change="onChange"
bind:confirm="onConfirm"
bind:cancel="onCancel"
/>
@import '../common/index.wxss';
\ No newline at end of file
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [button, openType],
classes: ['hover-class', 'loading-class'],
data: {
baseStyle: ''
},
props: {
icon: String,
plain: Boolean,
block: Boolean,
round: Boolean,
square: Boolean,
loading: Boolean,
hairline: Boolean,
disabled: Boolean,
loadingText: String,
customStyle: String,
loadingType: {
type: String,
value: 'circular'
},
type: {
type: String,
value: 'default'
},
size: {
type: String,
value: 'normal'
},
loadingSize: {
type: String,
value: '20px'
},
color: {
type: String,
observer(color) {
let style = '';
if (color) {
style += `color: ${this.data.plain ? color : 'white'};`;
if (!this.data.plain) {
// Use background instead of backgroundColor to make linear-gradient work
style += `background: ${color};`;
}
// hide border when color is linear-gradient
if (color.indexOf('gradient') !== -1) {
style += 'border: 0;';
}
else {
style += `border-color: ${color};`;
}
}
if (style !== this.data.baseStyle) {
this.setData({ baseStyle: style });
}
}
}
},
methods: {
onClick() {
if (!this.data.disabled && !this.data.loading) {
this.$emit('click');
}
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<button
id="{{ id }}"
class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
hover-class="van-button--active hover-class"
lang="{{ lang }}"
style="{{ baseStyle }} {{ customStyle }}"
open-type="{{ openType }}"
business-id="{{ businessId }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
send-message-path="{{ sendMessagePath }}"
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
aria-label="{{ ariaLabel }}"
bindtap="onClick"
bindgetuserinfo="bindGetUserInfo"
bindcontact="bindContact"
bindgetphonenumber="bindGetPhoneNumber"
binderror="bindError"
bindlaunchapp="bindLaunchApp"
bindopensetting="bindOpenSetting"
>
<block wx:if="{{ loading }}">
<van-loading
custom-class="loading-class"
size="{{ loadingSize }}"
type="{{ loadingType }}"
color="{{ loadingColor(type,color,plain) }}"
/>
<view
wx:if="{{ loadingText }}"
class="van-button__loading-text"
>
{{ loadingText }}
</view>
</block>
<block wx:else>
<van-icon
wx:if="{{ icon }}"
size="1.2em"
name="{{ icon }}"
class="van-button__icon"
custom-style="line-height: inherit;"
/>
<view class="van-button__text">
<slot />
</view>
</block>
</button>
<wxs module="loadingColor">
function get(type, color,plain) {
if(plain) {
return color ? color: '#c9c9c9';
}
if(type === 'default') {
return '#c9c9c9';
}
return 'white';
}
module.exports = get;
</wxs>
@import '../common/index.wxss';.van-button{position:relative;display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;padding:0;text-align:center;vertical-align:middle;-webkit-appearance:none;-webkit-text-size-adjust:100%;height:44px;height:var(--button-default-height,44px);line-height:20px;line-height:var(--button-line-height,20px);font-size:16px;font-size:var(--button-default-font-size,16px);transition:opacity .2s;transition:opacity var(--animation-duration-fast,.2s);border-radius:2px;border-radius:var(--button-border-radius,2px)}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;border:inherit;border-radius:inherit;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);opacity:0;content:" ";background-color:#000;background-color:var(--black,#000);border-color:#000;border-color:var(--black,#000)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#323233;color:var(--button-default-color,#323233);background:#fff;background:var(--button-default-background-color,#fff);border:1px solid #ebedf0;border:var(--button-border-width,1px) solid var(--button-default-border-color,#ebedf0)}.van-button--primary{color:#fff;color:var(--button-primary-color,#fff);background:#07c160;background:var(--button-primary-background-color,#07c160);border:1px solid #07c160;border:var(--button-border-width,1px) solid var(--button-primary-border-color,#07c160)}.van-button--info{color:#fff;color:var(--button-info-color,#fff);background:#1989fa;background:var(--button-info-background-color,#1989fa);border:1px solid #1989fa;border:var(--button-border-width,1px) solid var(--button-info-border-color,#1989fa)}.van-button--danger{color:#fff;color:var(--button-danger-color,#fff);background:#ee0a24;background:var(--button-danger-background-color,#ee0a24);border:1px solid #ee0a24;border:var(--button-border-width,1px) solid var(--button-danger-border-color,#ee0a24)}.van-button--warning{color:#fff;color:var(--button-warning-color,#fff);background:#ff976a;background:var(--button-warning-background-color,#ff976a);border:1px solid #ff976a;border:var(--button-border-width,1px) solid var(--button-warning-border-color,#ff976a)}.van-button--plain{background:#fff;background:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:#07c160;color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:#1989fa;color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:#ee0a24;color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:#ff976a;color:var(--button-warning-background-color,#ff976a)}.van-button--large{width:100%;height:50px;height:var(--button-large-height,50px)}.van-button--normal{padding:0 15px;font-size:14px;font-size:var(--button-normal-font-size,14px)}.van-button--small{min-width:60px;min-width:var(--button-small-min-width,60px);height:30px;height:var(--button-small-height,30px);padding:0 8px;padding:0 var(--padding-xs,8px);font-size:12px;font-size:var(--button-small-font-size,12px)}.van-button--mini{display:inline-block;min-width:50px;min-width:var(--button-mini-min-width,50px);height:22px;height:var(--button-mini-height,22px);font-size:10px;font-size:var(--button-mini-font-size,10px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:-webkit-flex;display:flex;width:100%}.van-button--round{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5;opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{min-width:1em;line-height:inherit!important;vertical-align:top}.van-button--hairline{padding-top:1px;border-width:0}.van-button--hairline:after{border-color:inherit;border-width:1px;border-radius:4px;border-radius:calc(var(--button-border-radius, 2px)*2)}.van-button--hairline.van-button--round:after{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0}
\ No newline at end of file
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'num-class',
'desc-class',
'thumb-class',
'title-class',
'price-class',
'origin-price-class'
],
mixins: [link],
props: {
tag: String,
num: String,
desc: String,
thumb: String,
title: String,
price: {
type: String,
observer: 'updatePrice'
},
centered: Boolean,
lazyLoad: Boolean,
thumbLink: String,
originPrice: String,
thumbMode: {
type: String,
value: 'aspectFit'
},
currency: {
type: String,
value: '¥'
}
},
methods: {
updatePrice() {
const { price } = this.data;
const priceArr = price.toString().split('.');
this.setData({
integerStr: priceArr[0],
decimalStr: priceArr[1] ? `.${priceArr[1]}` : ''
});
},
onClickThumb() {
this.jumpLink('thumbLink');
}
}
});
{
"component": true,
"usingComponents": {
"van-tag": "../tag/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="custom-class van-card">
<view class="{{ utils.bem('card__header', { center: centered }) }}">
<view class="van-card__thumb" bind:tap="onClickThumb">
<image
wx:if="{{ thumb }}"
src="{{ thumb }}"
mode="{{ thumbMode }}"
lazy-load="{{ lazyLoad }}"
class="van-card__img thumb-class"
/>
<slot name="thumb" />
<van-tag
wx:if="{{ tag }}"
mark
type="danger"
custom-class="van-card__tag"
>
{{ tag }}
</van-tag>
</view>
<view class="van-card__content {{ utils.bem('card__content', { center: centered }) }}">
<view>
<view wx:if="{{ title }}" class="van-card__title title-class">{{ title }}</view>
<slot wx:else name="title" />
<view wx:if="{{ desc }}" class="van-card__desc desc-class">{{ desc }}</view>
<slot wx:else name="desc" />
<slot name="tags" />
</view>
<view class="van-card__bottom">
<slot name="price-top" />
<view wx:if="{{ price || price === 0 }}" class="van-card__price price-class">{{ currency }}<text class="van-card__price-integer">{{ integerStr }}</text><text class="van-card__price-decimal">{{ decimalStr }}</text></view>
<slot wx:else name="price" />
<view wx:if="{{ originPrice || originPrice === 0 }}" class="van-card__origin-price origin-price-class">{{ currency }} {{ originPrice }}</view>
<view wx:if="{{ num }}" class="van-card__num num-class">x {{ num }}</view>
<slot wx:else name="num" />
<slot name="bottom" />
</view>
</view>
</view>
<view class="van-card__footer">
<slot name="footer" />
</view>
</view>
@import '../common/index.wxss';.van-card{position:relative;box-sizing:border-box;padding:8px 16px;padding:var(--card-padding,8px 16px);font-size:12px;font-size:var(--card-font-size,12px);color:#323233;color:var(--card-text-color,#323233);background-color:#fafafa;background-color:var(--card-background-color,#fafafa)}.van-card__header{display:-webkit-flex;display:flex}.van-card__header--center{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.van-card__thumb{position:relative;-webkit-flex:none;flex:none;width:88px;width:var(--card-thumb-size,88px);height:88px;height:var(--card-thumb-size,88px);margin-right:8px;margin-right:var(--padding-xs,8px)}.van-card__thumb:empty{display:none}.van-card__img{width:100%;height:100%;border-radius:8px;border-radius:var(--border-radius-lg,8px)}.van-card__content{position:relative;display:-webkit-flex;display:flex;-webkit-flex:1;flex:1;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:space-between;justify-content:space-between;min-width:0;min-height:88px;min-height:var(--card-thumb-size,88px)}.van-card__content--center{-webkit-justify-content:center;justify-content:center}.van-card__desc,.van-card__title{word-wrap:break-word}.van-card__title{font-weight:700;line-height:16px;line-height:var(--card-title-line-height,16px)}.van-card__desc{line-height:20px;line-height:var(--card-desc-line-height,20px);color:#646566;color:var(--card-desc-color,#646566)}.van-card__bottom{line-height:20px}.van-card__price{display:inline-block;font-weight:700;color:#ee0a24;color:var(--card-price-color,#ee0a24);font-size:12px;font-size:var(--card-price-font-size,12px)}.van-card__price-integer{font-size:16px;font-size:var(--card-price-integer-font-size,16px)}.van-card__price-decimal,.van-card__price-integer{font-family:Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif;font-family:var(--card-price-font-family,Avenir-Heavy,PingFang SC,Helvetica Neue,Arial,sans-serif)}.van-card__origin-price{display:inline-block;margin-left:5px;text-decoration:line-through;font-size:10px;font-size:var(--card-origin-price-font-size,10px);color:#646566;color:var(--card-origin-price-color,#646566)}.van-card__num{float:right}.van-card__tag{position:absolute;top:2px;left:0}.van-card__footer{-webkit-flex:none;flex:none;width:100%;text-align:right}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
props: {
title: String,
border: {
type: Boolean,
value: true
}
}
});
{
"component": true
}
\ No newline at end of file
<view
wx:if="{{ title }}"
class="van-cell-group__title"
>
{{ title }}
</view>
<view class="custom-class van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
<slot />
</view>
@import '../common/index.wxss';.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)}
\ No newline at end of file
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'title-class',
'label-class',
'value-class',
'right-icon-class',
'hover-class'
],
mixins: [link],
props: {
title: null,
value: null,
icon: String,
size: String,
label: String,
center: Boolean,
isLink: Boolean,
required: Boolean,
clickable: Boolean,
titleWidth: String,
customStyle: String,
arrowDirection: String,
useLabelSlot: Boolean,
border: {
type: Boolean,
value: true
}
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
\ No newline at end of file
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable }]) }}"
hover-class="van-cell--hover hover-class"
hover-stay-time="70"
style="{{ customStyle }}"
bind:tap="onClick"
>
<van-icon
wx:if="{{ icon }}"
name="{{ icon }}"
class="van-cell__left-icon-wrap"
custom-class="van-cell__left-icon"
/>
<slot wx:else name="icon" />
<view
style="{{ titleWidth ? 'max-width:' + titleWidth + ';min-width:' + titleWidth : '' }}"
class="van-cell__title title-class"
>
<block wx:if="{{ title }}">{{ title }}</block>
<slot wx:else name="title" />
<view wx:if="{{ label || useLabelSlot }}" class="van-cell__label label-class">
<slot wx:if="{{ useLabelSlot }}" name="label" />
<block wx:elif="{{ label }}">{{ label }}</block>
</view>
</view>
<view class="van-cell__value value-class">
<block wx:if="{{ value || value === 0 }}">{{ value }}</block>
<slot wx:else />
</view>
<van-icon
wx:if="{{ isLink }}"
name="{{ arrowDirection ? 'arrow' + '-' + arrowDirection : 'arrow' }}"
class="van-cell__right-icon-wrap right-icon-class"
custom-class="van-cell__right-icon"
/>
<slot wx:else name="right-icon" />
<slot name="extra" />
</view>
@import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;box-sizing:border-box;width:100%;padding:10px 16px;padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);font-size:14px;font-size:var(--cell-font-size,14px);line-height:24px;line-height:var(--cell-line-height,24px);color:#323233;color:var(--cell-text-color,#323233);background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:auto;right:0;bottom:0;left:16px;border-bottom:1px solid #ebedf0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell__label{margin-top:3px;margin-top:var(--cell-label-margin-top,3px);font-size:12px;font-size:var(--cell-label-font-size,12px);line-height:18px;line-height:var(--cell-label-line-height,18px);color:#969799;color:var(--cell-label-color,#969799)}.van-cell__value{overflow:hidden;text-align:right;vertical-align:middle;color:#969799;color:var(--cell-value-color,#969799)}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:24px;height:var(--cell-line-height,24px);font-size:16px;font-size:var(--cell-icon-size,16px)}.van-cell__left-icon-wrap{margin-right:5px}.van-cell__right-icon-wrap{margin-left:5px;color:#969799;color:var(--cell-right-icon-color,#969799)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:24px;line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5;background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;content:"*";left:8px;left:var(--padding-xs,8px);font-size:14px;font-size:var(--cell-font-size,14px);color:#ee0a24;color:var(--cell-required-color,#ee0a24)}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-top:var(--cell-large-vertical-padding,12px);padding-bottom:12px;padding-bottom:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:16px;font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__label{font-size:14px;font-size:var(--cell-large-label-font-size,14px)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
field: true,
relation: {
name: 'checkbox',
type: 'descendant',
current: 'checkbox-group',
linked(target) {
this.updateChild(target);
},
},
props: {
max: Number,
value: {
type: Array,
observer: 'updateChildren'
},
disabled: {
type: Boolean,
observer: 'updateChildren'
}
},
methods: {
updateChildren() {
(this.children || []).forEach((child) => this.updateChild(child));
},
updateChild(child) {
const { value, disabled } = this.data;
child.setData({
value: value.indexOf(child.data.name) !== -1,
parentDisabled: disabled
});
}
}
});
@import '../common/index.wxss';
\ No newline at end of file
import { VantComponent } from '../common/component';
function emit(target, value) {
target.$emit('input', value);
target.$emit('change', value);
}
VantComponent({
field: true,
relation: {
name: 'checkbox-group',
type: 'ancestor',
current: 'checkbox',
},
classes: ['icon-class', 'label-class'],
props: {
value: Boolean,
disabled: Boolean,
useIconSlot: Boolean,
checkedColor: String,
labelPosition: String,
labelDisabled: Boolean,
shape: {
type: String,
value: 'round'
},
iconSize: {
type: null,
value: 20
}
},
data: {
parentDisabled: false
},
methods: {
emitChange(value) {
if (this.parent) {
this.setParentValue(this.parent, value);
}
else {
emit(this, value);
}
},
toggle() {
const { parentDisabled, disabled, value } = this.data;
if (!disabled && !parentDisabled) {
this.emitChange(!value);
}
},
onClickLabel() {
const { labelDisabled, parentDisabled, disabled, value } = this.data;
if (!disabled && !labelDisabled && !parentDisabled) {
this.emitChange(!value);
}
},
setParentValue(parent, value) {
const parentValue = parent.data.value.slice();
const { name } = this.data;
const { max } = parent.data;
if (value) {
if (max && parentValue.length >= max) {
return;
}
if (parentValue.indexOf(name) === -1) {
parentValue.push(name);
emit(parent, parentValue);
}
}
else {
const index = parentValue.indexOf(name);
if (index !== -1) {
parentValue.splice(index, 1);
emit(parent, parentValue);
}
}
}
}
});
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view class="van-checkbox custom-class">
<view class="van-checkbox__icon-wrap" bindtap="toggle">
<slot wx:if="{{ useIconSlot }}" name="icon" />
<van-icon
wx:else
name="success"
size="0.8em"
class="{{ utils.bem('checkbox__icon', [shape, { disabled: disabled || parentDisabled, checked: value }]) }}"
style="{{ computed.iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) }}"
custom-class="icon-class"
custom-style="line-height: 1.25em;"
/>
</view>
<view class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}" bindtap="onClickLabel">
<slot />
</view>
</view>
/* eslint-disable */
var utils = require('../wxs/utils.wxs');
function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) {
var styles = [['font-size', utils.addUnit(iconSize)]];
if (checkedColor && value && !disabled && !parentDisabled) {
styles.push(['border-color', checkedColor]);
styles.push(['background-color', checkedColor]);
}
return styles
.map(function(item) {
return item.join(':');
})
.join(';');
}
module.exports = {
iconStyle: iconStyle
};
@import '../common/index.wxss';.van-checkbox{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;overflow:hidden;-webkit-user-select:none;user-select:none}.van-checkbox__icon-wrap,.van-checkbox__label{line-height:20px;line-height:var(--checkbox-size,20px)}.van-checkbox__icon-wrap{-webkit-flex:none;flex:none}.van-checkbox__icon{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;width:1em;height:1em;color:transparent;text-align:center;transition-property:color,border-color,background-color;font-size:20px;font-size:var(--checkbox-size,20px);border:1px solid #c8c9cc;border:1px solid var(--checkbox-border-color,#c8c9cc);transition-duration:.2s;transition-duration:var(--checkbox-transition-duration,.2s)}.van-checkbox__icon--round{border-radius:100%}.van-checkbox__icon--checked{color:#fff;color:var(--white,#fff);background-color:#1989fa;background-color:var(--checkbox-checked-icon-color,#1989fa);border-color:#1989fa;border-color:var(--checkbox-checked-icon-color,#1989fa)}.van-checkbox__icon--disabled{background-color:#ebedf0;background-color:var(--checkbox-disabled-background-color,#ebedf0);border-color:#c8c9cc;border-color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__icon--disabled.van-checkbox__icon--checked{color:#c8c9cc;color:var(--checkbox-disabled-icon-color,#c8c9cc)}.van-checkbox__label{word-wrap:break-word;margin-left:10px;margin-left:var(--checkbox-label-margin,10px);color:#323233;color:var(--checkbox-label-color,#323233)}.van-checkbox__label--left{float:left;margin:0 10px 0 0;margin:0 var(--checkbox-label-margin,10px) 0 0}.van-checkbox__label--disabled{color:#c8c9cc;color:var(--checkbox-disabled-label-color,#c8c9cc)}.van-checkbox__label:empty{margin:0}
\ No newline at end of file
import { VantComponent } from '../common/component';
import { isObj } from '../common/utils';
import { BLUE, WHITE } from '../common/color';
function format(rate) {
return Math.min(Math.max(rate, 0), 100);
}
const PERIMETER = 2 * Math.PI;
const BEGIN_ANGLE = -Math.PI / 2;
const STEP = 1;
VantComponent({
props: {
text: String,
lineCap: {
type: String,
value: 'round'
},
value: {
type: Number,
value: 0,
observer: 'reRender'
},
speed: {
type: Number,
value: 50
},
size: {
type: Number,
value: 100,
},
fill: String,
layerColor: {
type: String,
value: WHITE
},
color: {
type: [String, Object],
value: BLUE,
observer: 'setHoverColor'
},
strokeWidth: {
type: Number,
value: 4
},
clockwise: {
type: Boolean,
value: true
}
},
data: {
hoverColor: BLUE
},
methods: {
getContext() {
if (!this.ctx) {
this.ctx = wx.createCanvasContext('van-circle', this);
}
return this.ctx;
},
setHoverColor() {
const context = this.getContext();
const { color, size } = this.data;
let hoverColor = color;
if (isObj(color)) {
const LinearColor = context.createLinearGradient(size, 0, 0, 0);
Object.keys(color)
.sort((a, b) => parseFloat(a) - parseFloat(b))
.map(key => LinearColor.addColorStop(parseFloat(key) / 100, color[key]));
hoverColor = LinearColor;
}
this.setData({ hoverColor });
},
presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) {
const { strokeWidth, lineCap, clockwise, size } = this.data;
const position = size / 2;
const radius = position - strokeWidth / 2;
context.setStrokeStyle(strokeStyle);
context.setLineWidth(strokeWidth);
context.setLineCap(lineCap);
context.beginPath();
context.arc(position, position, radius, beginAngle, endAngle, !clockwise);
context.stroke();
if (fill) {
context.setFillStyle(fill);
context.fill();
}
},
renderLayerCircle(context) {
const { layerColor, fill } = this.data;
this.presetCanvas(context, layerColor, 0, PERIMETER, fill);
},
renderHoverCircle(context, formatValue) {
const { clockwise, hoverColor } = this.data;
// 结束角度
const progress = PERIMETER * (formatValue / 100);
const endAngle = clockwise
? BEGIN_ANGLE + progress
: 3 * Math.PI - (BEGIN_ANGLE + progress);
this.presetCanvas(context, hoverColor, BEGIN_ANGLE, endAngle);
},
drawCircle(currentValue) {
const context = this.getContext();
const { size } = this.data;
context.clearRect(0, 0, size, size);
this.renderLayerCircle(context);
const formatValue = format(currentValue);
if (formatValue !== 0) {
this.renderHoverCircle(context, formatValue);
}
context.draw();
},
reRender() {
// tofector 动画暂时没有想到好的解决方案
const { value, speed } = this.data;
if (speed <= 0 || speed > 1000) {
this.drawCircle(value);
return;
}
this.clearInterval();
this.currentValue = this.currentValue || 0;
this.interval = setInterval(() => {
if (this.currentValue !== value) {
if (this.currentValue < value) {
this.currentValue += STEP;
}
else {
this.currentValue -= STEP;
}
this.drawCircle(this.currentValue);
}
else {
this.clearInterval();
}
}, 1000 / speed);
},
clearInterval() {
if (this.interval) {
clearInterval(this.interval);
this.interval = null;
}
}
},
created() {
const { value } = this.data;
this.currentValue = value;
this.drawCircle(value);
},
destroyed() {
this.ctx = null;
this.clearInterval();
}
});
{
"component": true
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-circle">
<canvas class="van-circle__canvas" style="width: {{ utils.addUnit(size) }};height:{{ utils.addUnit(size) }}" canvas-id="van-circle"></canvas>
<view wx:if="{{ !text }}" class="van-circle__text">
<slot></slot>
</view>
<cover-view wx:else class="van-circle__text">{{ text }}</cover-view>
</view>
\ No newline at end of file
@import '../common/index.wxss';.van-circle{position:relative;display:inline-block;text-align:center}.van-circle__text{position:absolute;top:50%;left:0;width:100%;-webkit-transform:translateY(-50%);transform:translateY(-50%);color:#323233;color:var(--circle-text-color,#323233)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'row',
type: 'ancestor',
current: 'col',
},
props: {
span: Number,
offset: Number
},
data: {
viewStyle: ''
},
methods: {
setGutter(gutter) {
const padding = `${gutter / 2}px`;
const viewStyle = gutter ? `padding-left: ${padding}; padding-right: ${padding};` : '';
if (viewStyle !== this.data.viewStyle) {
this.setData({ viewStyle });
}
}
}
});
{
"component": true
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view
class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}"
style="{{ viewStyle }}"
>
<slot />
</view>
@import '../common/index.wxss';.van-col{float:left;box-sizing:border-box}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%}
\ No newline at end of file
import { VantComponent } from '../common/component';
const nextTick = () => new Promise(resolve => setTimeout(resolve, 20));
VantComponent({
classes: ['title-class', 'content-class'],
relation: {
name: 'collapse',
type: 'ancestor',
current: 'collapse-item',
},
props: {
name: null,
title: null,
value: null,
icon: String,
label: String,
disabled: Boolean,
clickable: Boolean,
border: {
type: Boolean,
value: true
},
isLink: {
type: Boolean,
value: true
}
},
data: {
contentHeight: 0,
expanded: false,
transition: false
},
mounted() {
this.updateExpanded()
.then(nextTick)
.then(() => {
const data = { transition: true };
if (this.data.expanded) {
data.contentHeight = 'auto';
}
this.setData(data);
});
},
methods: {
updateExpanded() {
if (!this.parent) {
return Promise.resolve();
}
const { value, accordion } = this.parent.data;
const { children = [] } = this.parent;
const { name } = this.data;
const index = children.indexOf(this);
const currentName = name == null ? index : name;
const expanded = accordion
? value === currentName
: (value || []).some((name) => name === currentName);
const stack = [];
if (expanded !== this.data.expanded) {
stack.push(this.updateStyle(expanded));
}
stack.push(this.set({ index, expanded }));
return Promise.all(stack);
},
updateStyle(expanded) {
return this.getRect('.van-collapse-item__content')
.then((rect) => rect.height)
.then((height) => {
if (expanded) {
return this.set({
contentHeight: height ? `${height}px` : 'auto'
});
}
return this.set({ contentHeight: `${height}px` })
.then(nextTick)
.then(() => this.set({ contentHeight: 0 }));
});
},
onClick() {
if (this.data.disabled) {
return;
}
const { name, expanded } = this.data;
const index = this.parent.children.indexOf(this);
const currentName = name == null ? index : name;
this.parent.switch(currentName, !expanded);
},
onTransitionEnd() {
if (this.data.expanded) {
this.setData({
contentHeight: 'auto'
});
}
}
}
});
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}
<wxs src="../wxs/utils.wxs" module="utils" />
<view class="van-collapse-item custom-class {{ index !== 0 ? 'van-hairline--top' : '' }}">
<van-cell
title="{{ title }}"
title-class="title-class"
icon="{{ icon }}"
value="{{ value }}"
label="{{ label }}"
is-link="{{ isLink }}"
clickable="{{ clickable }}"
border="{{ border && expanded }}"
class="{{ utils.bem('collapse-item__title', { disabled, expanded }) }}"
right-icon-class="van-cell__right-icon"
custom-class="van-cell"
hover-class="van-cell--hover"
bind:click="onClick"
>
<slot
name="title"
slot="title"
/>
<slot
name="icon"
slot="icon"
/>
<slot name="value" />
<slot
name="right-icon"
slot="right-icon"
/>
</van-cell>
<view
class="{{ utils.bem('collapse-item__wrapper', { transition }) }}"
style="height: {{ contentHeight }};"
bind:transitionend="onTransitionEnd"
>
<view
class="van-collapse-item__content content-class"
>
<slot />
</view>
</view>
</view>
@import '../common/index.wxss';.van-collapse-item__title .van-cell__right-icon{-webkit-transform:rotate(90deg);transform:rotate(90deg);transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;transition:-webkit-transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s);transition:transform var(--collapse-item-transition-duration,.3s),-webkit-transform var(--collapse-item-transition-duration,.3s)}.van-collapse-item__title--expanded .van-cell__right-icon{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.van-collapse-item__title--disabled .van-cell,.van-collapse-item__title--disabled .van-cell__right-icon{color:#c8c9cc!important;color:var(--collapse-item-title-disabled-color,#c8c9cc)!important}.van-collapse-item__title--disabled .van-cell--hover{background-color:#fff!important;background-color:var(--white,#fff)!important}.van-collapse-item__wrapper{overflow:hidden}.van-collapse-item__wrapper--transition{transition:height .3s ease-in-out}.van-collapse-item__content{padding:15px;padding:var(--collapse-item-content-padding,15px);color:#969799;color:var(--collapse-item-content-text-color,#969799);font-size:13px;font-size:var(--collapse-item-content-font-size,13px);line-height:1.5;line-height:var(--collapse-item-content-line-height,1.5);background-color:#fff;background-color:var(--collapse-item-content-background-color,#fff)}
\ No newline at end of file
import { VantComponent } from '../common/component';
VantComponent({
relation: {
name: 'collapse-item',
type: 'descendant',
current: 'collapse',
},
props: {
value: {
type: null,
observer: 'updateExpanded'
},
accordion: {
type: Boolean,
observer: 'updateExpanded'
},
border: {
type: Boolean,
value: true
}
},
methods: {
updateExpanded() {
this.children.forEach((child) => {
child.updateExpanded();
});
},
switch(name, expanded) {
const { accordion, value } = this.data;
if (!accordion) {
name = expanded
? (value || []).concat(name)
: (value || []).filter((activeName) => activeName !== name);
}
else {
name = expanded ? name : '';
}
this.$emit('change', name);
this.$emit('input', name);
}
}
});
<view class="custom-class van-collapse {{ border ? 'van-hairline--top-bottom' : '' }}">
<slot />
</view>
@import '../common/index.wxss';
\ No newline at end of file
export declare const RED = "#ee0a24";
export declare const BLUE = "#1989fa";
export declare const WHITE = "#fff";
export declare const GREEN = "#07c160";
export declare const ORANGE = "#ff976a";
export declare const GRAY = "#323233";
export declare const GRAY_DARK = "#969799";
export const RED = '#ee0a24';
export const BLUE = '#1989fa';
export const WHITE = '#fff';
export const GREEN = '#07c160';
export const ORANGE = '#ff976a';
export const GRAY = '#323233';
export const GRAY_DARK = '#969799';
import { VantComponentOptions, CombinedComponentInstance } from '../definitions/index';
declare function VantComponent<Data, Props, Methods>(vantOptions?: VantComponentOptions<Data, Props, Methods, CombinedComponentInstance<Data, Props, Methods>>): void;
export { VantComponent };
import { basic } from '../mixins/basic';
const relationFunctions = {
ancestor: {
linked(parent) {
this.parent = parent;
},
unlinked() {
this.parent = null;
},
},
descendant: {
linked(child) {
this.children = this.children || [];
this.children.push(child);
},
unlinked(child) {
this.children = (this.children || []).filter(it => it !== child);
},
},
};
function mapKeys(source, target, map) {
Object.keys(map).forEach(key => {
if (source[key]) {
target[map[key]] = source[key];
}
});
}
function makeRelation(options, vantOptions, relation) {
const { type, name, linked, unlinked, linkChanged } = relation;
const { beforeCreate, destroyed } = vantOptions;
if (type === 'descendant') {
options.created = function () {
beforeCreate && beforeCreate.bind(this)();
this.children = this.children || [];
};
options.detached = function () {
this.children = [];
destroyed && destroyed.bind(this)();
};
}
options.relations = Object.assign(options.relations || {}, {
[`../${name}/index`]: {
type,
linked(node) {
relationFunctions[type].linked.bind(this)(node);
linked && linked.bind(this)(node);
},
linkChanged(node) {
linkChanged && linkChanged.bind(this)(node);
},
unlinked(node) {
relationFunctions[type].unlinked.bind(this)(node);
unlinked && unlinked.bind(this)(node);
},
}
});
}
function VantComponent(vantOptions = {}) {
const options = {};
mapKeys(vantOptions, options, {
data: 'data',
props: 'properties',
mixins: 'behaviors',
methods: 'methods',
beforeCreate: 'created',
created: 'attached',
mounted: 'ready',
relations: 'relations',
destroyed: 'detached',
classes: 'externalClasses'
});
const { relation } = vantOptions;
if (relation) {
makeRelation(options, vantOptions, relation);
}
// add default externalClasses
options.externalClasses = options.externalClasses || [];
options.externalClasses.push('custom-class');
// add default behaviors
options.behaviors = options.behaviors || [];
options.behaviors.push(basic);
// map field to form-field behavior
if (vantOptions.field) {
options.behaviors.push('wx://form-field');
}
// add default options
options.options = {
multipleSlots: true,
addGlobalClass: true
};
Component(options);
}
export { VantComponent };
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{display:table;clear:both;content:""}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
\ No newline at end of file
.van-clearfix:after{display:table;clear:both;content:""}
\ No newline at end of file
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}
\ No newline at end of file
.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #eee;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}
\ No newline at end of file
/// <reference types="miniprogram-api-typings" />
export declare function isDef(value: any): boolean;
export declare function isObj(x: any): boolean;
export declare function isNumber(value: any): boolean;
export declare function range(num: number, min: number, max: number): number;
export declare function nextTick(fn: Function): void;
export declare function getSystemInfoSync(): WechatMiniprogram.GetSystemInfoSuccessCallbackResult;
export declare function addUnit(value?: string | number): string | undefined;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment