Browse Source

上传代码

master
杨豪 3 years ago
parent
commit
b73dd186a4
  1. BIN
      .DS_Store
  2. 1
      .gitignore
  3. 11
      .hbuilderx/launch.json
  4. 359
      App.vue
  5. 153
      api/activity.js
  6. 73
      api/admin.js
  7. 17
      api/live.js
  8. 150
      api/order.js
  9. 108
      api/public.js
  10. 183
      api/store.js
  11. 463
      api/user.js
  12. 0
      app.css
  13. 221
      app.js
  14. 85
      app.json
  15. 2
      assets/css/base.css
  16. 1
      assets/css/base.css.map
  17. 186
      assets/css/base.less
  18. 2
      assets/css/reset.css
  19. 1
      assets/css/reset.css.map
  20. 61
      assets/css/reset.less
  21. 9379
      assets/css/style.less
  22. 661
      assets/iconfont/iconfont.css
  23. 77
      components/AddressWindow.vue
  24. 210
      components/Adv.vue
  25. 289
      components/CitySelect.vue
  26. 120
      components/CountDown.vue
  27. 122
      components/CouponListWindow.vue
  28. 75
      components/CouponPop.vue
  29. 88
      components/CouponWindow.vue
  30. 24
      components/DataFormat.vue
  31. 24
      components/DataFormatT.vue
  32. 65
      components/Footer.vue
  33. 49
      components/GoodList.vue
  34. 59
      components/Home.vue
  35. 21
      components/Loading.vue
  36. 74
      components/Mask.vue
  37. 155
      components/Menu.vue
  38. 99
      components/OrderGoods.vue
  39. 202
      components/Payment.vue
  40. 133
      components/PriceChange.vue
  41. 71
      components/ProductConSwiper.vue
  42. 145
      components/ProductWindow.vue
  43. 215
      components/PromotionGood.vue
  44. 82
      components/Recommend.vue
  45. 40
      components/ShareInfo.vue
  46. 43
      components/ShareRedPackets.vue
  47. 324
      components/ShopLiveCard.vue
  48. 243
      components/StorePoster.vue
  49. 155
      components/SwitchWindow.vue
  50. 52
      components/UserEvaluation.vue
  51. 127
      components/WriteOff.vue
  52. 10
      components/WxEmojiView.vue
  53. 3
      components/WxParseBr.vue
  54. 156
      components/api-set-tabbar.nvue
  55. 184
      components/colorui/animation.css
  56. 70
      components/colorui/components/cu-custom.vue
  57. 1226
      components/colorui/icon.css
  58. 4040
      components/colorui/main.css
  59. 66
      components/product.vue
  60. 75
      components/region-picker/readme.md
  61. 4
      components/region-picker/region-picker.js
  62. 163
      components/region-picker/region-picker.vue
  63. 286
      components/select-tree/select-tree.vue
  64. 40
      components/sh-activity-goods.vue
  65. 217
      components/sh-adv.vue
  66. 197
      components/sh-groupon.vue
  67. 151
      components/tki-tree/style.css
  68. 310
      components/tki-tree/tki-tree.vue
  69. 5
      components/wxParse.vue
  70. 81
      components/wxParse0.vue
  71. 74
      components/wxParse1.vue
  72. 74
      components/wxParse10.vue
  73. 74
      components/wxParse11.vue
  74. 74
      components/wxParse2.vue
  75. 74
      components/wxParse3.vue
  76. 74
      components/wxParse4.vue
  77. 74
      components/wxParse5.vue
  78. 74
      components/wxParse6.vue
  79. 74
      components/wxParse7.vue
  80. 74
      components/wxParse8.vue
  81. 74
      components/wxParse9.vue
  82. 3
      components/wxParseImg.vue
  83. 6
      components/wxParseVideo.vue
  84. 12
      config/index.js
  85. 1
      dist/cell/index.d.ts
  86. 38
      dist/cell/index.js
  87. 6
      dist/cell/index.json
  88. 47
      dist/cell/index.wxml
  89. 17
      dist/cell/index.wxs
  90. 1
      dist/cell/index.wxss
  91. 6
      dist/collapse-item/animate.d.ts
  92. 70
      dist/collapse-item/animate.js
  93. 1
      dist/collapse-item/index.d.ts
  94. 59
      dist/collapse-item/index.js
  95. 6
      dist/collapse-item/index.json
  96. 44
      dist/collapse-item/index.wxml
  97. 1
      dist/collapse-item/index.wxss
  98. 1
      dist/collapse/index.d.ts
  99. 44
      dist/collapse/index.js
  100. 3
      dist/collapse/index.json
  101. Some files were not shown because too many files have changed in this diff Show More

BIN
.DS_Store vendored

Binary file not shown.

1
.gitignore vendored

@ -0,0 +1 @@
node_modules

11
.hbuilderx/launch.json

@ -0,0 +1,11 @@
{ // launch.json configurations app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtypelocalremote, localremote
"version": "0.0",
"configurations": [{
"type": "uniCloud",
"default": {
"launchtype": "local"
}
}
]
}

359
App.vue

@ -0,0 +1,359 @@
<script>
import {
VUE_APP_API_URL
} from "@/config";
export default {
onLaunch: function (e) {
var that = this; //
this.setMenuHeight();
this.autoUpdate();
},
globalData: {
// baseURL : 'http://192.168.0.110:8092/api/',
baseURL: VUE_APP_API_URL+ '/',
// baseURL : 'https://cloud.api.cyjyyjy.com/api/',
userInfo: null,
navHeight: 0,
navTopHeight: 0,
menuTop: 0,
menuHeight: 0,
CustomBar: 0,
isIphoneX: false,
inviterId: null,
//
systemInfo: null,
},
onShow(e) {
//tabbar
uni.hideTabBar();
var query = {};
if (e.query.q) {
//storage
let urlSpread = e.query.q;
if (urlSpread) {
if (urlSpread.indexOf('?') != -1) {
//
urlSpread = urlSpread.split("?")[1].replace(/=/g, ":").replace(/&/g, ",").split(",").map((item, index) => {
item = item.split(":");
return `"${item[0]}":"${item[1]}"`;
}).join(",");
query = JSON.parse("{" + urlSpread + "}");
}
console.log('query1', query);
this.globalData.inviterId = query.id;
}
} else {
query = e.query;
console.log('query2', query);
this.globalData.inviterId = query.id;
}
},
methods: {
autoUpdate: function () {
// console.log(new Date());
var self = this; //
if (uni.canIUse('getUpdateManager')) {
const updateManager = uni.getUpdateManager(); //1.
updateManager.onCheckForUpdate(function (res) {
//
if (res.hasUpdate) {
//2.
updateManager.onUpdateReady(function () {
console.log(new Date());
uni.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success: function (res) {
if (res.confirm) {
//3. applyUpdate
updateManager.applyUpdate();
}
}
});
});
updateManager.onUpdateFailed(function () {
//
uni.showModal({
title: '已经有新版本了哟~',
content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~'
});
});
}
});
} else {
//
uni.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
});
}
},
setMenuHeight() {
uni.getSystemInfo({
success: res => {
console.log(res);
this.globalData.navTopHeight = res.statusBarHeight;
this.globalData.CustomBar = res.statusBarHeight + 45;
this.globalData.systemInfo = res;
let model = res.model;
if (/iphone\sx/i.test(model) || /iphone/i.test(model) && /unknown/.test(model) || /iphone\s11/i.test(model) || /iphone\s12/i.test(model)) {
this.globalData.isIphoneX = true;
}
}
});
let menuButtonObj = uni.getMenuButtonBoundingClientRect();
this.globalData.menuTop = menuButtonObj.top; // console.log(menuButtonObj)
this.globalData.menuHeight = menuButtonObj.height;
this.globalData.navHeight = menuButtonObj.height + (menuButtonObj.top - this.globalData.navTopHeight);
},
getInfo() {
this.http('get', 'userinfo').then(res => {
if (res.data.success) {
uni.setStorageSync('userInfo', res.data.data);
var pages = getCurrentPages().pop(); //
if (pages.getUser) {
pages.getUser();
}
} else {
uni.showToast({
title: res.data.msg,
icon: 'none',
duration: 2000
});
setTimeout(() => {
// uni.navigateTo({
// url: '/pages/login/index'
// });
uni.navigateTo({
url: '/pages/authorization/index'
});
}, 2000);
}
});
},
http(mathods, url, params) {
var that = this;
var header = {
'content-type': 'application/json',
'version': '2.0',
'Authorization': 'Bearer ' + uni.getStorageSync('login_status') || ''
};
return new Promise((resolve, reject) => {
uni.showLoading({
title: "正在加载中..."
});
uni.request({
url: this.globalData.baseURL + url,
//
method: mathods,
//
header: header,
data: params || {},
//
success: res => {
uni.hideLoading(); // console.log(res)
//token res.data.code == 40001
if (!res.data.success && res.data.status == 401) {
// console.log('')
// uni.navigateTo({
// url: '/pages/login/index'
// });
var pages = getCurrentPages().pop(); //
console.log(pages.$page.fullPath)
uni.setStorageSync('redirect',pages.$page.fullPath) //
uni.navigateTo({
url: '/pages/authorization/index'
});
}
resolve(res); //res.data,
},
fail: function () {
//
uni.hideLoading();
uni.showToast({
title: '服务器错误,请稍后再试!',
icon: 'none'
});
reject(err);
}
});
});
},
}
};
</script>
<style lang="scss" scoped>
@import "uview-ui/index.scss";
</style>
<style lang="less">
/**app.wxss**/
@import './assets/iconfont/iconfont.css';
@import './assets/css/base.less';
@import './assets/css/reset.less';
@import './assets/css/style.less';
view,
scroll-view,
swiper,
button,
input,
textarea,
label,
navigator,
image {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
image{
/* border-radius: 8rpx; */
}
/* layout */
.acea-row-nowrap {
display: flex;
/* 辅助类 */
}
.acea-row {
display: flex;
flex-wrap: wrap;
/* 辅助类 */
}
.acea-row.row-middle,.acea-row-nowrap.row-middle{
align-items: center;
}
.acea-row.row-top,.acea-row-nowrap.row-top {
align-items: flex-start;
}
.acea-row.row-bottom {
align-items: flex-end;
}
.acea-row.row-center,.acea-row-nowrap.row-center {
justify-content: center;
}
.acea-row.row-right,.acea-row-nowrap.row-right {
justify-content: flex-end;
}
.acea-row.row-left,.acea-row-nowrap.row-left {
justify-content: flex-start;
}
.acea-row.row-between,.acea-row-nowrap.row-between {
justify-content: space-between;
}
.acea-row.row-around, .acea-row-nowrap.row-around{
justify-content: space-around;
}
.acea-row.row-column-around,.acea-row-nowrap.row-column-around {
flex-direction: column;
justify-content: space-around;
}
.acea-row.row-column {
flex-direction: column;
}
.acea-row.row-column-between,.acea-row-nowrap.row-column-between {
flex-direction: column;
justify-content: space-between;
}
/* 上下左右垂直居中 */
.acea-row.row-center-wrapper,.acea-row-nowrap.row-center-wrapper {
align-items: center;
justify-content: center;
}
/* 上下两边居中对齐 */
.acea-row.row-between-wrapper,.acea-row-nowrap.row-between-wrapper {
align-items: center;
justify-content: space-between;
}
.line1{
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
width: 100%;
}
.line2{
word-break:break-all;
display:-webkit-box;
-webkit-line-clamp:2;
-webkit-box-orient:vertical;
overflow:hidden;
}
.back-btn{
width: 36rpx;
height: 36rpx;
position: fixed;
left: 40rpx;
text-align: center;
line-height: 36rpx;
z-index: 99;
}
.back-btn image{
width: 100%;
height: 100%;
}
radio .wx-radio-input.wx-radio-input-checked {
border-color: #cc0000;
background: #cc0000;
}
radio .wx-radio-input {
height: 33rpx;
width: 33rpx;
margin-top: -4rpx;
border-radius: 50%;
border: 2rpx solid #999;
background: transparent;
}
radio .wx-radio-input.wx-radio-input-checked::before {
border-radius: 50%; /* 圆角 */
width: 35rpx; /* 选中后对勾大小,不要超过背景的尺寸 */
height: 35rpx; /* 选中后对勾大小,不要超过背景的尺寸 */
line-height: 35rpx;
text-align: center;
font-size: 28rpx; /* 对勾大小 30rpx */
color: #fff; /* 对勾颜色 白色 */
background: #FF5100;
border: 2rpx solid #FF5100;
transform: translate(-50%, -50%) scale(1);
-webkit-transform: translate(-50%, -50%) scale(1);
}
.no-list{
display: flex;
flex-direction: column;
align-items: center;
font-size: 46rpx;
color: #D8D8D8;
font-weight: 500;
padding-top: 20%;
}
.no-list image{
width: 536rpx;
height: 490rpx;
}
.no-list .to-btn{
width: 458rpx;
height: 88rpx;
line-height: 88rpx;
text-align: center;
background: linear-gradient(134deg, #FFA782 0%, #FF6D31 100%);
border-radius: 44rpx;
font-size: 40rpx;
color: #fff;
margin-top: 160rpx;
}
</style>

153
api/activity.js

@ -0,0 +1,153 @@
import request from "@/utils/request";
/**
* 拼团列表
*/
export function getCombinationList(data) {
return request.get("/combination/list", data, { login: false });
}
/**
* 拼团产品详情
* @param {*} id
*/
export function getCombinationDetail(id) {
return request.get("/combination/detail/" + id, {}, { login: true });
}
/**
* 拼团 开团
* @param {*} id
*/
export function getCombinationPink(id) {
return request.get("/combination/pink/" + id);
}
/**
* 拼团 取消开团
*/
export function getCombinationRemove(data) {
return request.post("/combination/remove", data);
}
/**
* 拼团海报
* @param {*} id
*/
export function getCombinationPoster(data) {
return request.post("/combination/poster", data);
}
/**
* 秒杀列表配置
*/
export function getSeckillConfig() {
return request.get("/seckill/index", {}, { login: false });
}
/**
* 秒杀列表
*/
export function getSeckillList(time, data) {
return request.get("/seckill/list/" + time, data, { login: false });
}
/**
* 秒杀产品详情
*/
export function getSeckillDetail(id) {
return request.get("/seckill/detail/" + id, {}, { login: true });
}
/**
* 砍价列表
* @param {*} data
*/
export function getBargainList(data) {
return request.get("/bargain/list", data, { login: false });
}
/**
* 砍价产品详情
*/
export function getBargainDetail(id) {
return request.get("/bargain/detail/" + id);
}
/**
* 砍价 观看/分享/参与次数
*/
export function getBargainShare(data) {
return request.post("/bargain/share", data);
}
/**
* 砍价开启
* @param {*} data
*/
export function getBargainStart(data) {
return request.post("/bargain/start", data);
}
/**
* 砍价 帮助好友砍价
* @param {*} data
*/
export function getBargainHelp(data) {
return request.post("/bargain/help", data);
}
/**
* 砍价 砍掉金额
* @param {*} data
*/
export function getBargainHelpPrice(data) {
return request.post("/bargain/help/price", data);
}
/**
* 砍价 砍价帮总人数剩余金额进度条已经砍掉的价格
* @param {*} data
*/
export function getBargainHelpCount(data) {
return request.post("/bargain/help/count", data);
}
/**
* 砍价 开启砍价用户信息
* @param {*} data
*/
export function getBargainStartUser(data) {
return request.post("/bargain/start/user", data);
}
/**
* 砍价 砍价帮
* @param {*} data
*/
export function getBargainHelpList(data) {
return request.post("/bargain/help/list", data);
}
/**
* 砍价海报
* @param {*} data
*/
export function getBargainPoster(data) {
return request.post("/bargain/poster", data);
}
/**
* 砍价列表(已参与)
* @param {*} data
*/
export function getBargainUserList(data) {
return request.get("/bargain/user/list", data);
}
/**
* 砍价取消
*/
export function getBargainUserCancel(data) {
return request.post("/bargain/user/cancel", data);
}

73
api/admin.js

@ -0,0 +1,73 @@
import request from "@/utils/request";
/**
* 统计数据
*/
export function getStatisticsInfo() {
return request.get("/admin/order/statistics", {}, { login: true });
}
/**
* 订单月统计
*/
export function getStatisticsMonth(where) {
return request.get("/admin/order/data", where, { login: true });
}
/**
* 订单月统计
*/
export function getAdminOrderList(where) {
return request.get("/admin/order/list", where, { login: true });
}
/**
* 订单改价
*/
export function setAdminOrderPrice(data) {
return request.post("/admin/order/price", data, { login: true });
}
/**
* 订单备注
*/
export function setAdminOrderRemark(data) {
return request.post("/admin/order/remark", data, { login: true });
}
/**
* 订单详情
*/
export function getAdminOrderDetail(orderId) {
return request.get("/admin/order/detail/" + orderId, {}, { login: true });
}
/**
* 订单发货信息获取
*/
export function getAdminOrderDelivery(orderId) {
return request.get(
"/admin/order/detail/" + orderId,
{},
{ login: true }
);
}
/**
* 订单发货保存
*/
export function setAdminOrderDelivery(data) {
return request.post("/admin/order/delivery/keep", data, { login: true });
}
/**
* 订单统计图
*/
export function getStatisticsTime(data) {
return request.get("/admin/order/time", data, { login: true });
}
/**
* 线下付款订单确认付款
*/
export function setOfflinePay(data) {
return request.post("/admin/order/offline", data, { login: true });
}
/**
* 订单确认退款
*/
export function setOrderRefund(data) {
return request.post("/admin/order/refund", data, { login: true });
}

17
api/live.js

@ -0,0 +1,17 @@
import request from "@/utils/request";
/**
* 查询所有直播间
*/
export function yxWechatLive(data) {
return request.get("/yxWechatLive", data, { login: true });
}
/**
* 获取直播回放
*/
export function getLiveReplay(id, data) {
return request.get("/yxWechatLive/getLiveReplay/" + id, data, { login: false });
}

150
api/order.js

@ -0,0 +1,150 @@
/*
* 订单确认
* */
import request from "@/utils/request";
/**
* 通过购物车 id 获取订单信息
* @param cartId
* @returns {*}
*/
export function postOrderConfirm(cartId) {
return request.post("/order/confirm", {
cartId
});
}
/**
* 计算订单金额
* @param key
* @param data
* @returns {*}
*/
export function postOrderComputed(key, data) {
return request.post("/order/computed/" + key, data);
}
/**
* 获取指定金额可用优惠券
* @param price
* @returns {*}
*/
export function getOrderCoupon(cartId) {
return request.get("/coupons/order/" + cartId);
}
/**
* 生成订单
* @param key
* @param data
* @returns {*}
*/
export function createOrder(key, data) {
return request.post("/order/create/" + key, data || {});
}
/**
* 订单统计数据
* @returns {*}
*/
export function getOrderData() {
return request.get("/order/data");
}
/**
* 订单列表
* @returns {*}
*/
export function getOrderList(data) {
return request.get("/order/list", data);
}
/**
* 取消订单
* @returns {*}
*/
export function cancelOrder(id) {
return request.post("/order/cancel", {
id
});
}
/**
* 订单详情
* @returns {*}
*/
export function orderDetail(id) {
return request.get("/order/detail/" + id);
}
/**
* 退款理由
* @returns {*}
*/
export function getRefundReason() {
return request.get("/order/refund/reason");
}
/**
* 提交退款
* @returns {*}
*/
export function postOrderRefund(data) {
return request.post("/order/refund/verify", data);
}
/**
* 确认收货
* @returns {*}
*/
export function takeOrder(uni) {
return request.post("/order/take", {
uni
});
}
/**
* 删除订单
* @returns {*}
*/
export function delOrder(uni) {
return request.post("/order/del", {
uni
});
}
/**
* 订单查询物流信息
* @returns {*}
*/
export function express(params) {
return request.post("order/express", params);
}
/**
* 订单查询物流信息
* @returns {*}
*/
export function payOrder(uni, paytype, from) {
return request.post("order/pay", {
uni,
paytype,
from
});
}
/**
* 订单核销
* @returns {*}
*/
export function orderVerific(verifyCode, isConfirm) {
return request.post("order/order_verific", { verifyCode, isConfirm });
}
/**
* 获取订阅消息ID
* @param price
* @returns {*}
*/
export function getSubscribeTemplate() {
return request.get("/order/getSubscribeTemplate");
}

108
api/public.js

@ -0,0 +1,108 @@
import request from "@/utils/request";
/**
* 首页
* @returns {*}
*/
export function getHomeData() {
return request.get("index", {}, { login: false });
}
/**
* 首页
* @returns {*}
*/
export function getCanvas() {
return request.get("/getCanvas?terminal=3", {}, { login: false });
}
/**
* 文章 轮播列表
* @returns {*}
*/
export function getArticleBanner() {
return request.get("/article/banner/list", {}, { login: false });
}
/**
* 文章分类列表
* @returns {*}
*/
export function getArticleCategory() {
return request.get("/article/category/list", {}, { login: false });
}
/**
* 文章 热门列表
* @returns {*}
*/
export function getArticleHotList() {
return request.get("/article/hot/list", {}, { login: false });
}
/**
* 文章列表
* @returns {*}
*/
export function getArticleList(q) {
return request.get("/article/list/", q, { login: false });
}
/**
* 分享
* @returns {*}
*/
export function getShare() {
return request.get("/share", {}, { login: false });
}
/**
* 文章详情
* @returns {*}
*/
export function getArticleDetails(id) {
return request.get("/article/details/" + id, {}, { login: false });
}
/**
* 获取微信sdk配置
* @returns {*}
*/
export function getWechatConfig() {
return request.get(
"/wechat/config",
{ url: location.href },
{ login: false }
);
}
/**
* 获取微信sdk配置
* @returns {*}
*/
export function wechatAuth(code, spread, login_type) {
return request.get(
"/wechat/auth",
{ code, spread, login_type },
{ login: false }
);
}
/**
* 获取快递公司
* @returns {*}
*/
export function getLogistics() {
return request.get("/logistics", {}, { login: false });
}
/**
* 获取图片base64
* @retins {*}
* */
export function imageBase64(image, code) {
return request.post(
"/image_base64",
{ image: image, code: code },
{ login: false }
);
}

183
api/store.js

@ -0,0 +1,183 @@
import request from "@/utils/request";
/*
* 商品分类
* */
export function getCategory() {
return request.get("/category", {}, {
login: false
});
}
/*
* 商品详情
* */
export function getProductDetail(id, data) {
return request.get("/product/detail/" + id, data, {
login: true
});
}
/*
* 商品分销二维码
* */
export function getProductCode(id) {
return request.get("/product/code/" + id, {}, {
login: true
});
}
/*
* 商品列表
* */
export function getProducts(q) {
return request.get("/products", q, {
login: false
});
}
/*
* 积分商品列表
* */
export function getProductsIntegral(q) {
return request.get("/products/integral", q, {
login: false
});
}
/*
* 购物车数量
* */
export function getCartNum() {
return request.get("/cart/count");
}
/*
* 添加收藏
* */
export function toCollect(id, category) {
return request.get("/collect/add/" + id + "/" + category);
}
/*
* 为你推荐
* */
export function getHostProducts(page, limit) {
return request.get(
"/product/hot", {
page: page,
limit: limit
}, {
login: false
}
);
}
/*
* 精品热门首发列表
* */
export function getGroomList(type) {
return request.get("/groom/list/" + type, {}, {
login: true
});
}
/*
* 获取商品海报
* */
export function getProductPoster(id, data) {
return request.get("/product/poster/" + id, data, {
login: true
});
}
/*
* 购物车 添加
* */
export function postCartAdd(data) {
return request.post("/cart/add", data);
}
/*
* 购物车列表
* */
export function getCartList() {
return request.get("/cart/list");
}
/*
* 购物车 删除
* */
export function postCartDel(ids) {
return request.post("/cart/del", {
ids
});
}
/*
* 购物车 获取数量
* */
export function getCartCount(data) {
return request.get("/cart/count", data);
}
/*
* 购物车 修改商品数量
* */
export function changeCartNum(id, number) {
return request.post("/cart/num", {
id,
number
});
}
/**
* 搜索推荐关键字
*/
export function getSearchKeyword() {
return request.get("/search/keyword", {}, {
login: false
});
}
/**
* 产品评论列表
*/
export function getReplyList(id, q) {
return request.get("/reply/list/" + id, q, {
login: true
});
}
/**
* 产品评价数量和好评度
*/
export function getReplyConfig(id) {
return request.get("/reply/config/" + id, {}, {
login: true
});
}
/**
* 评价页面获取单个产品详情
*/
export function postOrderProduct(unique) {
return request.post("/order/product", {
unique
}, {
login: true
});
}
/**
* 提交评价页面
*/
export function postOrderComment(data) {
return request.post("/order/comment", data, {
login: true
});
}
export function storeListApi(data) {
return request.get("store_list", data, {
login: false
});
}

463
api/user.js

@ -0,0 +1,463 @@
import request from '@/utils/request'
/**
* 省市区
*/
export function getCity(data) {
return request.get('/city_list', data, {
// return request.get("/citys", data, {
login: false,
})
}
export function district(data) {
// return request.get("/city_list", data, {
return request.get('/citys', data, {
login: false,
})
}
/**
* 用户登录
* @param data object 用户账号密码
*/
export function login(data) {
return request.post('/login', data, {
login: false,
})
}
/**
* 用户手机号登录
* @param data object 用户手机号 也只能
*/
export function loginMobile(data) {
return request.post('/login/mobile', data, {
login: false,
})
}
/**
* 用户发送验证码
* @param data object 用户手机号
*/
export function registerVerify(data) {
return request.post('/register/verify', data, {
login: false,
})
}
/**
* 用户手机号注册
* @param data object 用户手机号 验证码 密码
*/
export function register(data) {
return request.post('/register', data, {
login: false,
})
}
/**
* 用户手机号修改密码
* @param data object 用户手机号 验证码 密码
*/
export function registerReset(data) {
return request.post('/register/reset', data, {
login: false,
})
}
/*
* 领取优惠券列表
* */
export function getCoupon(q) {
return request.get('/coupons', q, {
login: true,
})
}
/*
* 点击领取优惠券
* */
export function getCouponReceive(id) {
return request.post(
'/coupon/receive',
{
couponId: id,
},
{
login: true,
}
)
}
/*
* 批量领取优惠券
* */
export function couponReceiveBatch(couponId) {
return request.post('/coupon/receive/batch', {
couponId,
})
}
/*
* 我的优惠券
* */
export function getCouponsUser(type) {
return request.get('/coupons/user/' + type)
}
/*
* 个人中心
* */
export function getUser() {
return request.get('/user')
}
/*
* 用户信息
* */
export function getUserInfo() {
return request.get('/userinfo', {
login: true,
})
}
/*
* 小程序登陆
* */
export function wxappAuth(data) {
return request.post('/wxapp/auth', data, {
login: false,
})
}
/*
* 个人中心(功能列表)
* */
export function getMenuUser() {
return request.get('/menu/user')
}
/*
* 地址列表
* */
export function getAddressList(data) {
return request.get('/address/list', data || {})
}
/*
* 删除地址
* */
export function getAddressRemove(id) {
return request.post('/address/del', {
id: id,
})
}
/*
* 设置默认地址
* */
export function getAddressDefaultSet(id) {
return request.post('/address/default/set', {
id: id,
})
}
/*
* 获取默认地址
* */
export function getAddressDefault() {
return request.get('/address/default')
}
/*
* 获取单个地址
* */
export function getAddress(id) {
return request.get('/address/detail/' + id)
}
/*
* 修改 添加地址
* */
export function postAddress(data) {
return request.post('/address/edit', data)
}
/*
* 获取收藏产品
* */
export function getCollectUser(page, limit, type) {
return request.get('/collect/user', {
page: page,
limit: limit,
type,
})
}
/*
* 删除收藏产品
* */
export function getCollectDel(id, category) {
return request.post('/collect/del', {
id: id,
category: category,
})
}
/*
* 批量收藏产品
* */
export function postCollectAll(data) {
return request.post('/collect/all', data)
}
/*
* 添加收藏产品
* */
export function getCollectAdd(id, category) {
return request.post('collect/add', {
id: id,
category: category,
})
}
/*
* 签到配置
* */
export function getSignConfig() {
return request.get('/sign/config')
}
/*
* 签到里的签到列表
* */
export function getSignList(page, limit) {
return request.get('/sign/list', {
page: page,
limit: limit,
})
}
/*
* 签到列表
* */
export function getSignMonth(page, limit) {
return request.get('/sign/month', {
page: page,
limit: limit,
})
}
/*
* 签到用户信息
* */
export function postSignUser(sign) {
return request.post('/sign/user', sign)
}
/*
* 签到
* */
export function postSignIntegral(sign) {
return request.post('/sign/integral', sign)
}
/*
* 推广数据
* */
export function getSpreadInfo() {
return request.get('/commission')
}
/*
* 推广人列表
* */
export function getSpreadUser(screen) {
return request.post('/spread/people', screen)
}
/*
* 推广人订单
* */
export function getSpreadOrder(where) {
return request.post('/spread/order', where)
}
/*
* 资金明细types|0=全部,1=消费,2=充值,3=返佣,4=提现
* */
export function getCommissionInfo(q, types) {
return request.get('/spread/commission/' + types, q)
}
/*
* 积分记录
* */
export function getIntegralList(q) {
return request.get('/integral/list', q)
}
/*
* 提现银行
* */
export function getBank() {
return request.get('/extract/bank')
}
/*
* 提现申请
* */
export function postCashInfo(cash) {
return request.post('/extract/cash', cash)
}
/*
* 会员中心
* */
export function getVipInfo() {
return request.get('/user/level/grade')
}
/*
* 会员等级任务
* */
export function getVipTask(id) {
return request.get('/user/level/task/' + id)
}
/*
* 资金统计
* */
export function getBalance() {
return request.get('/user/balance')
}
/*
* 活动状态
* */
export function getActivityStatus() {
return request.get(
'/user/activity',
{},
{
login: false,
}
)
}
/*
* 活动状态
* */
export function getSpreadImg(data) {
return request.get('/spread/banner', data)
}
/*
* 用户修改信息
* */
export function postUserEdit(data) {
return request.post('/user/edit', data)
}
/*
* 用户修改信息
* */
export function getChatRecord(to_uid, data) {
return request.get('user/service/record/' + to_uid, data)
}
/*
* 用户修改信息
* */
export function serviceList() {
return request.get('user/service/list')
}
/*
* 公众号充值
* */
export function rechargeWechat(data) {
return request.post('/recharge/wechat', data)
}
/*
* 退出登录
* */
export function getLogout() {
return request.post('/auth/logout')
}
/*
* 小程序绑定手机号
* */
export function bindingPhone(data) {
return request.post('/binding', data)
}
/*
* 绑定手机号
* */
export function wxappBindingPhone(data) {
return request.post('wxapp/binding', data)
}
/*
* h5切换公众号登陆
* */
export function switchH5Login() {
return request.post('switch_h5', {
from: 'wechat',
})
}
/*
* 获取推广人排行
* */
export function getRankList(q) {
return request.get('rank', q)
}
/*
* 获取佣金排名
* */
export function getBrokerageRank(q) {
return request.get('brokerage_rank', q)
}
/**
* 检测会员等级
*/
export function setDetection() {
return request.get('user/level/detection')
}
export function getRechargeApi() {
return request.get('recharge/index')
}
/*
* 获取我的课程列表
* */
export function getMyCourseList(q) {
return request.get('/Course/listCoursesByMemberId?type='+q)
}
/*
* 获取我的打榜列表
* */
export function getStudyList(q) {
return request.get('/StudyList/getStudyListByMemberId?type='+q)
}
/*
* 获取签到状态
* */
export function integral(q) {
return request.post('/user/integral')
}
/*
* 签到
* */
export function signIntegral(q) {
return request.post('/sign/integral')
}

0
app.wxss → app.css

221
app.js

@ -1,221 +0,0 @@
//app.js
App({
onLaunch: function (e) {
var that = this;
//获取设备信息
this.setMenuHeight()
this.autoUpdate()
},
autoUpdate:function(){
console.log(new Date())
var self=this
// 获取小程序更新机制兼容
if (wx.canIUse('getUpdateManager')) {
const updateManager = wx.getUpdateManager()
//1. 检查小程序是否有新版本发布
updateManager.onCheckForUpdate(function (res) {
// 请求完新版本信息的回调
if (res.hasUpdate) {
//2. 小程序有新版本,则静默下载新版本,做好更新准备
updateManager.onUpdateReady(function () {
console.log(new Date())
wx.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success: function (res) {
if (res.confirm) {
//3. 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate()
}
}
})
})
updateManager.onUpdateFailed(function () {
// 新的版本下载失败
wx.showModal({
title: '已经有新版本了哟~',
content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~',
})
})
}
})
} else {
// 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
}
},
onShow(e){
//隐藏系统tabbar
wx.hideTabBar();
var query = {};
if(e.query.q){
//通过扫码进来获取二维码上的参数并存入storage
let urlSpread = e.query.q;
if (urlSpread) {
if (urlSpread.indexOf('%3F') != -1) {
// 通过扫桌面二维码进来
urlSpread = urlSpread.split("%3F")[1].replace(/%3D/g, ":").replace(/%26/g, ",").split(",").map((item, index) => {
item = item.split(":");
return `"${item[0]}":"${item[1]}"`;
}).join(",");
query = JSON.parse("{" + urlSpread + "}");
}
console.log('query1',query)
this.globalData.inviterId = query.id
}
} else{
query = e.query
console.log('query2',query)
this.globalData.inviterId = query.id
}
},
setMenuHeight(){
wx.getSystemInfo({
success: res => {
// console.log(res)
this.globalData.navTopHeight = res.statusBarHeight;
this.globalData.CustomBar = res.statusBarHeight + 45;
this.globalData.systemInfo = res;
}
});
let menuButtonObj = wx.getMenuButtonBoundingClientRect();
this.globalData.menuTop = menuButtonObj.top;
// console.log(menuButtonObj)
this.globalData.menuHeight = menuButtonObj.height;
this.globalData.navHeight = menuButtonObj.height + (menuButtonObj.top - this.globalData.navTopHeight);
},
editTabbar: function () {
var tabbar = this.globalData.tabBar;
var currentPages = getCurrentPages();
var that = currentPages[currentPages.length - 1];
var pagePath = that.route;
(pagePath.indexOf('/') != 0) && (pagePath = '/' + pagePath);
for (var i in tabbar.list) {
tabbar.list[i].selected = false;
(tabbar.list[i].pagePath == pagePath) && (tabbar.list[i].selected = true);
}
that.setData({
tabbar: tabbar
});
},
getInfo(){
this.http('get','userinfo').then((res)=>{
if(res.data.success){
// console.log(res.data)
wx.setStorageSync('userInfo',res.data.data)
var pages = getCurrentPages().pop();//当前页面
if (pages.getUser){
pages.getUser();
}
} else{
wx.showToast({
title: res.data.msg,
icon: 'none',
duration: 2000
})
setTimeout(()=>{
wx.navigateTo({
url: '/pages/login/index',
})
},2000)
}
})
},
http(mathods,url, params) {
var that = this;
var header = {
'content-type': 'application/json',
'version': '2.0',
'Authorization' : wx.getStorageSync('token') || ''
}
return new Promise(
(resolve,reject) => {
wx.showLoading({
title: "正在加载中...",
})
wx.request({
url: this.globalData.baseURL + url, //请求地址
method: mathods, //请求方法
header: header,
data: params || {}, //请求参数
success: res => {
wx.hideLoading();
console.log(res)
//判断token是否过期 res.data.code == 40001
if(!res.data.success && res.data.status == 401){
console.log('登陆失效')
wx.navigateTo({
url: '/pages/login/index',
})
}
resolve(res);
//成功执行方法,参数值为res.data,直接将返回的数据传入
},
fail: function() {
//请求失败
wx.hideLoading();
wx.showToast({
title: '服务器错误,请稍后再试!',
icon : 'none'
})
reject(err)
},
})
}
)
},
globalData: {
// baseURL : 'http://192.168.0.110:8092/api/',
baseURL : 'http://192.168.0.114:8092/api/',
// baseURL : 'https://www.cyjyyjy.com:8093/api/',
userInfo: null,
navHeight : 0,
navTopHeight: 0,
menuTop: 0,
menuHeight: 0,
CustomBar: 0,
inviterId: null , //分享码
systemInfo: null, //客户端设备信息
tabBar: {
"backgroundColor": "#ffffff",
"color": "#979795",
"selectedColor": "#FF6F34",
"list": [
{
"pagePath": "/pages/index/index",
"iconPath": "icon/home.png",
"selectedIconPath": "icon/home-a.png",
"text": "首页"
},
{
"pagePath": "/pages/demandHall/index",
"iconPath": "icon/tab2.png",
"selectedIconPath": "icon/tab2-a.png",
"text": "供需大厅"
},
{
"pagePath": "/pages/release/index",
"iconPath": "icon/icon_release.png",
"isSpecial": true,
"text": "发布"
},
{
"pagePath": "/pages/life/index",
"iconPath": "icon/tab3.png",
"selectedIconPath": "icon/tab3-a.png",
"text": "生活"
},
{
"pagePath": "/pages/user/index",
"iconPath": "icon/tab4.png",
"selectedIconPath": "icon/tab4-a.png",
"text": "我的"
}
]
}
}
})

85
app.json

@ -1,85 +0,0 @@
{
"pages":[
"pages/index/index",
"pages/user/index",
"pages/login/index",
"pages/webview/index",
"pages/demandHall/createProject/index",
"pages/demandHall/needsContact/index",
"pages/user/needsOrder/index",
"pages/user/resourcesOrder/index",
"pages/user/needsManage/index",
"pages/user/resourcesManage/index",
"pages/user/editNeeds/index",
"pages/demandHall/needsDetail/index",
"pages/demandHall/resourcesDetail/index",
"pages/demandHall/companyDetail/index",
"pages/demandHall/resourcesContact/index",
"pages/demandHall/applyDetail/index",
"pages/demandHall/platform/index",
"pages/demandHall/index",
"pages/release/index",
"pages/release/personAuth/index",
"pages/release/companyAuth/index",
"pages/release/perfectPersonInfo/index",
"pages/release/perfectCompanyInfo/index",
"pages/life/index",
"pages/user/mine/index",
"pages/user/agreement/index",
"pages/user/incomeDetail/index",
"pages/user/profession/index",
"pages/user/completeData/index",
"pages/user/personalData/index",
"pages/activity/index",
"pages/activity/detail/index",
"pages/activity/describe/index",
"pages/activity/signIn/index",
"pages/activity/signIn/confirm/index",
"pages/activity/signIn/paymentSuccess/index",
"pages/user/industry/index"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "禅易云生态",
"navigationBarTextStyle":"black"
},
"tabBar": {
"backgroundColor": "#ffffff",
"color": "#D4D4D4",
"selectedColor": "#FF6F34",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "tabbarComponent/icon/home.png",
"selectedIconPath": "tabbarComponent/icon/home-a.png"
},
{
"pagePath": "pages/demandHall/index",
"text": "供需大厅",
"iconPath": "tabbarComponent/icon/tab2.png",
"selectedIconPath": "tabbarComponent/icon/tab2-a.png"
},
{
"pagePath": "pages/life/index",
"text": "生活",
"iconPath": "tabbarComponent/icon/tab3.png",
"selectedIconPath": "tabbarComponent/icon/tab3-a.png"
},
{
"pagePath": "pages/user/index",
"text": "我的",
"iconPath": "tabbarComponent/icon/tab4.png",
"selectedIconPath": "tabbarComponent/icon/tab4-a.png"
}
]
},
"style": "v2",
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
"sitemapLocation": "sitemap.json"
}

2
assets/css/base.css

@ -0,0 +1,2 @@
@charset "UTF-8";.font-color-red{color:#eb3729 !important}.bg-color-red{background-color:#eb3729 !important}.icon-color{color:#eb3729}.cart-color{color:#eb3729 !important;border:1px solid #eb3729 !important}.padding20{padding:20rpx}.pad20{padding:0 20rpx}.padding30{padding:30rpx}.pad30{padding:0 30rpx}.acea-row{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.acea-row.row-middle{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.acea-row.row-top{-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start}.acea-row.row-bottom{-webkit-box-align:end;-webkit-align-items:flex-end;-ms-flex-align:end;align-items:flex-end}.acea-row.row-center{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.acea-row.row-right{-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end}.acea-row.row-left{-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start}.acea-row.row-between{-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.acea-row.row-around{-webkit-justify-content:space-around;-ms-flex-pack:distribute;justify-content:space-around}.acea-row.row-column-around{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-justify-content:space-around;-ms-flex-pack:distribute;justify-content:space-around}.acea-row.row-column{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.acea-row.row-column-between{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.acea-row.row-center-wrapper{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.acea-row.row-between-wrapper{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between}.slider-banner{position:relative;width:100%;overflow:hidden}.slider-banner .swiper-container{height:100%}.slider-banner image{display:block;width:100%;height:100%}.start{width:122rpx;height:30rpx;background-image:url("https://wx.yixiang.co/static/images/start.png");background-repeat:no-repeat;-webkit-background-size:122rpx auto;background-size:122rpx auto}.start.star5{background-position:0 3rpx}.start.star4{background-position:0 -30rpx}.start.star3{background-position:0 -70rpx}.start.star2{background-position:0 -105rpx}.start.star1{background-position:0 -140rpx}.start.star0{background-position:0 -175rpx}.checkbox-wrapper{position:relative}.checkbox-wrapper input{display:none}.checkbox-wrapper .icon{position:absolute;left:0;top:50%;display:inline-block;width:18px;height:18px;border:1px solid #cccccc;-webkit-border-radius:50%;border-radius:50%;-webkit-transform:translate(0, -50%);-ms-transform:translate(0, -50%);transform:translate(0, -50%)}.checkbox-wrapper input:checked+.icon{background-color:#e93323;border-color:#e93323;background-image:url("https://wx.yixiang.co/static/images/enter.png");-webkit-background-size:21rpx 15rpx;background-size:21rpx 15rpx;background-repeat:no-repeat;background-position:center center}.Loads{height:80rpx;font-size:25rpx;color:#000}.Loads .iconfont{font-size:30rpx;margin-right:10rpx;height:32rpx;line-height:32rpx}@-webkit-keyframes load{from{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes load{from{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.loadingpic{-webkit-animation:load 3s linear 1s infinite;animation:load 3s linear 1s infinite}.loading{-webkit-animation:load linear 1s infinite;animation:load linear 1s infinite}
/*# sourceMappingURL=./base.css.map */

1
assets/css/base.css.map

@ -0,0 +1 @@
{"version":3,"sources":["base.less"],"names":[],"mappings":"AAAA,iBAIA,gBACE,wBAAA,CAEF,cACE,mCAAA,CAEF,YACE,aAAA,CAEF,YACE,yBACA,mCAAA,CAGF,WACE,aAAA,CAGF,OACE,eAAA,CAGF,WACE,aAAA,CAGF,OACE,eAAA,CAGF,UACE,oBACA,AADA,qBACA,AADA,oBACA,AADA,aACA,uBAAA,mBAAA,cAAA,CAGF,qBACE,yBAAA,2BAAA,sBAAA,kBAAA,CAEF,kBACE,wBAAA,+BAAA,qBAAA,sBAAA,CAEF,qBACE,sBAAA,6BAAA,mBAAA,oBAAA,CAEF,qBACE,wBAAA,+BAAA,qBAAA,sBAAA,CAEF,oBACE,qBAAA,iCAAA,kBAAA,wBAAA,CAEF,mBACE,uBAAA,mCAAA,oBAAA,0BAAA,CAEF,sBACE,yBAAA,sCAAA,sBAAA,6BAAA,CAEF,qBACE,qCAAA,yBAAA,4BAAA,CAEF,4BACE,4BACA,AADA,6BACA,AADA,8BACA,AADA,0BACA,AADA,sBACA,qCAAA,yBAAA,4BAAA,CAEF,qBACE,4BAAA,6BAAA,8BAAA,0BAAA,qBAAA,CAEF,6BACE,4BACA,AADA,6BACA,AADA,8BACA,AADA,0BACA,AADA,sBACA,yBAAA,sCAAA,sBAAA,6BAAA,CAGF,6BACE,yBACA,AADA,2BACA,AADA,sBACA,AADA,mBACA,wBAAA,+BAAA,qBAAA,sBAAA,CAGF,8BACE,yBACA,AADA,2BACA,AADA,sBACA,AADA,mBACA,yBAAA,sCAAA,sBAAA,6BAAA,CAIF,eACE,kBACA,WAEA,eAAA,CAKF,iCACE,WAAA,CAEF,qBACE,cACA,WACA,WAAA,CAEF,OACE,aACA,aACA,sEACA,4BACA,oCAAA,2BAAA,CAEF,aACE,0BAAA,CAEF,aACE,4BAAA,CAEF,aACE,4BAAA,CAEF,aACE,6BAAA,CAEF,aACE,6BAAA,CAEF,aACE,6BAAA,CAGF,kBACE,iBAAA,CAEF,wBACE,YAAA,CAEF,wBACE,kBACA,OACA,QACA,qBACA,WACA,YACA,yBACA,0BACA,AADA,kBACA,qCAAW,AAAX,iCAAW,AAAX,4BAAW,CAEb,sCACE,yBACA,qBACA,sEACA,oCACA,AADA,4BACA,4BACA,iCAAA,CAEF,OACE,aACA,gBACA,UAAA,CAEF,iBACE,gBACA,mBACA,aACA,iBAAA,CAGF,wBACE,KACE,+BAAW,AAAX,sBAAW,CAEb,GACE,iCAAW,AAAX,wBAAW,CAAA,CAGf,AARA,gBACE,KACE,+BAAW,AAAX,sBAAW,CAEb,GACE,iCAAW,AAAX,wBAAW,CAAA,CAGf,YACE,6CAAA,oCAAA,CAEF,SACE,0CAAA,iCAAA,CAAA","file":"to.css","sourcesContent":[null]}

186
assets/css/base.less

@ -0,0 +1,186 @@
@charset "UTF-8";
/**
*相关初始化
*/
.font-color-red {
color: #F99C10 !important;
}
.bg-color-red {
background-color: #F99C10 !important;
}
.icon-color {
color: #F99C10;
}
.cart-color {
color: #F99C10 !important;
border: 1px solid #F99C10 !important;
}
/* padding20 */
.padding20 {
padding: 0.2*100rpx;
}
/* pad20 */
.pad20 {
padding: 0 0.2*100rpx;
}
/* padding30 */
.padding30 {
padding: 0.3*100rpx;
}
/*pad30 */
.pad30 {
padding: 0 0.3*100rpx;
}
/* layout */
.acea-row-nowrap {
display: flex;
/* 辅助类 */
}
.acea-row {
display: flex;
flex-wrap: wrap;
/* 辅助类 */
}
.acea-row.row-middle,.acea-row-nowrap.row-middle{
align-items: center;
}
.acea-row.row-top,.acea-row-nowrap.row-top {
align-items: flex-start;
}
.acea-row.row-bottom {
align-items: flex-end;
}
.acea-row.row-center,.acea-row-nowrap.row-center {
justify-content: center;
}
.acea-row.row-right,.acea-row-nowrap.row-right {
justify-content: flex-end;
}
.acea-row.row-left,.acea-row-nowrap.row-left {
justify-content: flex-start;
}
.acea-row.row-between,.acea-row-nowrap.row-between {
justify-content: space-between;
}
.acea-row.row-around, .acea-row-nowrap.row-around{
justify-content: space-around;
}
.acea-row.row-column-around,.acea-row-nowrap.row-column-around {
flex-direction: column;
justify-content: space-around;
}
.acea-row.row-column {
flex-direction: column;
}
.acea-row.row-column-between,.acea-row-nowrap.row-column-between {
flex-direction: column;
justify-content: space-between;
}
/* 上下左右垂直居中 */
.acea-row.row-center-wrapper,.acea-row-nowrap.row-center-wrapper {
align-items: center;
justify-content: center;
}
/* 上下两边居中对齐 */
.acea-row.row-between-wrapper,.acea-row-nowrap.row-between-wrapper {
align-items: center;
justify-content: space-between;
}
/* 轮播图 */
.slider-banner {
position: relative;
width: 100%;
/* height:750rpx; */
overflow: hidden;
}
.slider-banner{
}
.slider-banner .swiper-container {
height: 100%;
}
.slider-banner image{
display: block;
width: 100%;
height: 100%;
}
.start {
width: 1.22*100rpx;
height: 0.3*100rpx;
background-image: url("https://wx.yixiang.co/static/images/start.png");
background-repeat: no-repeat;
background-size: 1.22*100rpx auto;
}
.start.star5 {
background-position: 0 0.03*100rpx;
}
.start.star4 {
background-position: 0 -0.3*100rpx;
}
.start.star3 {
background-position: 0 -0.7*100rpx;
}
.start.star2 {
background-position: 0 -1.05*100rpx;
}
.start.star1 {
background-position: 0 -1.4*100rpx;
}
.start.star0 {
background-position: 0 -1.75*100rpx;
}
/* 单选框和多选框 */
.checkbox-wrapper {
position: relative;
}
.checkbox-wrapper input {
display: none;
}
.checkbox-wrapper .icon {
position: absolute;
left: 0;
top: 50%;
display: inline-block;
width: 18px;
height: 18px;
border: 1px solid #cccccc;
border-radius: 50%;
transform: translate(0, -50%);
}
.checkbox-wrapper input:checked + .icon {
background-color: #e93323;
border-color: #e93323;
background-image: url("https://wx.yixiang.co/static/images/enter.png");
background-size: 0.21*100rpx 0.15*100rpx;
background-repeat: no-repeat;
background-position: center center;
}
.Loads {
height: 0.8*100rpx;
font-size: 0.25*100rpx;
color: #000;
}
.Loads .iconfont {
font-size: 0.3*100rpx;
margin-right: 0.1*100rpx;
height: 0.32*100rpx;
line-height: 0.32*100rpx;
}
/*加载动画*/
@keyframes load {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loadingpic {
animation: load 3s linear 1s infinite;
}
.loading {
animation: load linear 1s infinite;
}

2
assets/css/reset.css

@ -0,0 +1,2 @@
input{line-height:normal;-webkit-box-sizing:border-box;box-sizing:border-box}@font-face{font-family:'GuildfordProBook 5';src:url('https://wx.yixiang.co/static/iconfont/GuildfordProBook5.otf')}[v-cloak]{display:none}.iconfont{font-size:36rpx}@media (-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5){.border-1px::after{-webkit-transform:scaleY(.7);-ms-transform:scaleY(.7);transform:scaleY(.7)}.border-1px::before{-webkit-transform:scaleY(.7);-ms-transform:scaleY(.7);transform:scaleY(.7)}}@media (-webkit-min-device-pixel-ratio:2),(min-device-pixel-ratio:2){.border-1px::after{-webkit-transform:scaleY(.5);-ms-transform:scaleY(.5);transform:scaleY(.5)}.border-1px::before{-webkit-transform:scaleY(.5);-ms-transform:scaleY(.5);transform:scaleY(.5)}}@media (-webkit-min-device-pixel-ratio:3),(min-device-pixel-ratio:3){.border-1px::after{-webkit-transform:scaleY(.33);-ms-transform:scaleY(.33);transform:scaleY(.33)}.border-1px::before{-webkit-transform:scaleY(.33);-ms-transform:scaleY(.33);transform:scaleY(.33)}}.line1{overflow:hidden;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;width:100%}.line2{word-break:break-all;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.mask{position:fixed;top:0;left:0;right:0;bottom:0;z-index:55;background-color:rgba(0,0,0,0.5)}
/*# sourceMappingURL=./reset.css.map */

1
assets/css/reset.css.map

@ -0,0 +1 @@
{"version":3,"sources":["reset.less"],"names":[],"mappings":"AAAA,MAAM,mBAAqB,8BAAA,qBAAA,CAC3B,WACE,iCACA,sEAAS,CAEX,UACE,YAAA,CAEF,UACE,eAAA,CAGF,yEACE,mBACE,6BAAW,AAAX,yBAAW,AAAX,oBAAW,CAEb,oBACE,6BAAW,AAAX,yBAAW,AAAX,oBAAW,CAAA,CAGf,qEACE,mBACE,6BAAW,AAAX,yBAAW,AAAX,oBAAW,CAEb,oBACE,6BAAW,AAAX,yBAAW,AAAX,oBAAW,CAAA,CAGf,qEACE,mBACE,8BAAW,AAAX,0BAAW,AAAX,qBAAW,CAEb,oBACE,8BAAW,AAAX,0BAAW,AAAX,qBAAW,CAAA,CAGf,OAAO,gBAAgB,0BAAuB,AAAvB,uBAAuB,mBAAmB,UAAA,CACjE,OAAO,qBAAqB,oBAAoB,qBAAqB,4BAA4B,eAAA,CACjG,MAAM,eAAe,MAAM,OAAO,QAAQ,SAAS,WAAW,gCAAA,CAAA","file":"to.css","sourcesContent":[null]}

61
assets/css/reset.less

@ -0,0 +1,61 @@
input{line-height: normal; box-sizing:border-box;}
@font-face {
font-family: 'GuildfordProBook 5';
src: url('https://wx.yixiang.co/static/iconfont/GuildfordProBook5.otf');
}
[v-cloak] {
display: none;
}
.iconfont{
font-size: .36*100rpx;
}
/* 一像素边框 */
@media (-webkit-min-device-pixel-ratio: 1.5), (min-device-pixel-ratio: 1.5) {
.border-1px::after {
transform: scaleY(0.7);
}
.border-1px::before {
transform: scaleY(0.7);
}
}
@media (-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2) {
.border-1px::after {
transform: scaleY(0.5);
}
.border-1px::before {
transform: scaleY(0.5);
}
}
@media (-webkit-min-device-pixel-ratio: 3), (min-device-pixel-ratio: 3) {
.border-1px::after {
transform: scaleY(0.33);
}
.border-1px::before {
transform: scaleY(0.33);
}
}
.line1{
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
width: 100%;
}
.line2{
word-break:break-all;
display:-webkit-box;
-webkit-line-clamp:2;
-webkit-box-orient:vertical;
overflow:hidden;
}
.line5{
word-break:break-all;
display:-webkit-box;
-webkit-line-clamp:5;
-webkit-box-orient:vertical;
overflow:hidden;
}
.mask{position:fixed;top:0;left:0;right:0;bottom:0;z-index:55;background-color:rgba(0,0,0,0.5);}

9379
assets/css/style.less

File diff suppressed because it is too large Load Diff

661
assets/iconfont/iconfont.css

File diff suppressed because one or more lines are too long

77
components/AddressWindow.vue

@ -0,0 +1,77 @@
<template>
<view>
<view class="address-window" :class="value === true ? 'on' : ''">
<view class="title">
选择地址
<text class="iconfont icon-guanbi" @click="closeAddress"></text>
</view>
<view class="list" v-if="addressList.length">
<view
class="item acea-row row-between-wrapper"
:class="item.id === checked ? 'font-color-red' : ''"
v-for="(item, addressIndex) in addressList"
@click="tapAddress(addressIndex)"
:key="addressIndex"
>
<text class="iconfont icon-ditu" :class="item.id === checked ? 'font-color-red' : ''"></text>
<view class="addressTxt">
<view class="name" :class="item.id === checked ? 'font-color-red' : ''">
{{ item.realName }}
<text class="phone">{{ item.phone }}</text>
</view>
<view class="line1">
{{ item.province }}{{ item.city }}{{ item.district
}}{{ item.detail }}
</view>
</view>
<text class="iconfont icon-complete" :class="item.id === checked ? 'font-color-red' : ''"></text>
</view>
</view>
<view class="pictrue" v-if="addressList.length < 1">
<image :src="`${$VUE_APP_RESOURCES_URL}/images/noAddress.png`" class="image" />
</view>
<view class="addressBnt bg-color-red" @click="goAddressPages">新加地址</view>
</view>
<view class="mask" @touchmove.prevent :hidden="value === false" @click="closeAddress"></view>
</view>
</template>
<script>
import { getAddressList } from "@/api/user";
export default {
name: "AddressWindow",
props: {
value: Boolean,
checked: Number
},
data: function() {
return {
addressList: [],
current: 0,
cartId: 0,
pinkId: 0,
couponId: 0
};
},
mounted: function() {},
methods: {
getAddressList: function() {
let that = this;
getAddressList().then(res => {
that.addressList = res.data;
});
},
closeAddress() {
this.$emit("input", false);
},
goAddressPages: function() {
this.$yrouter.push('/pagesB/pages/user/address/AddressManagement/index')
this.$emit("redirect");
},
tapAddress: function(index) {
this.$emit("checked", this.addressList[index]);
this.$emit("input", false);
}
}
};
</script>

210
components/Adv.vue

@ -0,0 +1,210 @@
<template>
<view class="adv-box mx20 mb10">
<!-- 模板1-->
<view class="x-f" v-if="detail.style == 1">
<image style="width: 710rpx; height: 220rpx" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
</view>
<!-- 模板2-->
<view class="type1 x-f" v-if="detail.style == 2">
<image class="type1-img" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
<image class="type1-img" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill"></image>
</view>
<!-- 模板3-->
<view class="type2 x-bc" v-if="detail.style == 3">
<image class="type2-img1" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
<view class="y-f type2-box">
<image class="type2-img2" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill" style="border-bottom: 1rpx solid #f6f6f6"></image>
<image class="type2-img2" @tap="jump(detail.list[2])" :src="detail.list[2].image" mode="aspectFill"></image>
</view>
</view>
<!-- 模板4-->
<view class="type3 x-bc" v-if="detail.style == 4">
<view class="type3-box y-f">
<image class="type3-img1" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
<image class="type3-img1" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill"></image>
</view>
<image class="type3-img2" @tap="jump(detail.list[2])" :src="detail.list[2].image" mode="aspectFill"></image>
</view>
<!-- 模板5-->
<view class="type4 y-f" v-if="detail.style == 5">
<view class="type4-box x-f">
<image class="type4-img1" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
<image class="type4-img1" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill"></image>
</view>
<image class="type4-img2" @tap="jump(detail.list[2])" :src="detail.list[2].image" mode="aspectFill"></image>
</view>
<!-- 模板6-->
<view class="type5 y-f" v-if="detail.style == 6">
<image class="type5-img1" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
<view class="type5-box x-bc">
<image class="type5-img2" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill" style="border-bottom: 1rpx solid #f6f6f6"></image>
<image class="type5-img2" @tap="jump(detail.list[2])" :src="detail.list[2].image" mode="aspectFill"></image>
</view>
</view>
<!-- 模板7-->
<view class="type6 y-f" v-if="detail.style == 7">
<view class="x-f type6-box1">
<image class="type6-img1" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
<image class="type6-img1" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill"></image>
</view>
<view class="x-f type6-box2">
<image class="type6-img2" @tap="jump(detail.list[2])" :src="detail.list[2].image" mode="aspectFill"></image>
<image class="type6-img2" @tap="jump(detail.list[3])" :src="detail.list[3].image" mode="aspectFill"></image>
<image class="type6-img2" @tap="jump(detail.list[4])" :src="detail.list[4].image" mode="aspectFill"></image>
</view>
</view>
</view>
</template>
<script>
export default {
components: {},
data() {
return {}
},
props: {
detail: Object,
},
computed: {},
created() {},
methods: {
//
jump(item) {
console.log(item)
if (item) {
this.$yrouter.push(path)
}
},
},
}
</script>
<style lang="scss">
.adv-box {
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
.type1 {
.type1-img {
flex: 1;
height: 220rpx;
&:first-child {
border-right: 1rpx solid #f6f6f6;
}
}
}
.type2 {
.type2-img1 {
width: (710rpx/2);
height: 340rpx;
border-right: 1rpx solid #f6f6f6;
}
.type2-box {
flex: 1;
height: 340rpx;
width: (710rpx/2);
.type2-img2 {
height: (340rpx/2);
}
}
}
.type3 {
.type3-box {
width: (710rpx/2);
border-right: 1rpx solid #f6f6f6;
.type3-img1 {
flex: 1;
height: (340rpx/2);
&:first-child {
border-bottom: 1rpx solid #f6f6f6;
}
}
}
.type3-img2 {
flex: 1;
height: 340rpx;
width: (710rpx/2);
}
}
.type4 {
.type4-box {
border-bottom: 1rpx solid #f6f6f6;
.type4-img1 {
flex: 1;
height: (340rpx/2);
&:first-child {
border-right: 1rpx solid #f6f6f6;
}
}
}
.type4-img2 {
flex: 1;
height: (340rpx/2);
width: 710rpx;
}
}
.type5 {
.type5-img1 {
width: 710rpx;
height: (340rpx/2);
border-bottom: 1rpx solid #f6f6f6;
}
.type5-box {
flex: 1;
height: (340rpx/2);
width: 710rpx;
.type5-img2 {
height: (340rpx/2);
&:first-child {
border-right: 1rpx solid #f6f6f6;
}
}
}
}
.type6 {
.type6-box1 {
.type6-img1 {
width: (710rpx/2);
height: (340rpx/2);
&:first-child {
border-right: 1rpx solid #f6f6f6;
}
}
}
.type6-box2 {
border-top: 1rpx solid #f6f6f6;
.type6-img2 {
width: (710rpx/3);
height: (340rpx/2);
border-right: 1rpx solid #f6f6f6;
&:last-child {
border-right: 0;
}
}
}
}
image {
// background-color: #ccc;
}
}
</style>

289
components/CitySelect.vue

@ -0,0 +1,289 @@
<template>
<view>
<text class="uni-input" @tap="open">{{value}}</text>
<uni-popup ref="popup" type="bottom">
<view class="cityselect">
<view class="cityselect-header">
<view class="cityselect-title">
<text>请选择地址</text>
</view>
<view class="cityselect-nav">
<view class="item" v-if="provinceActive" @tap="changeNav(0)">
<text>{{provinceActive.n}}</text>
</view>
<view class="item" v-if="cityActive" @tap="changeNav(1)">
<text>{{cityActive.n}}</text>
</view>
<view class="item" v-if="districtActive" @tap="changeNav(2)">
<text>{{districtActive.n}}</text>
</view>
<view class="item active" v-else>
<text>请选择</text>
</view>
</view>
</view>
<view class="cityselect-content">
<swiper class="swiper" disable-touch="true" touchable="false" :current="current">
<swiper-item>
<scroll-view scroll-y class="cityScroll">
<view>
<view
class="cityselect-item"
v-for="(item,index) in province"
:key="index"
@tap="selectProvince(index)"
>
<view class="cityselect-item-box">
<text>{{item.n}}</text>
</view>
</view>
</view>
</scroll-view>
</swiper-item>
<swiper-item>
<scroll-view scroll-y class="cityScroll">
<view>
<view
class="cityselect-item"
v-for="(item,index) in city"
:key="index"
@tap="selectCity(index)"
>
<view class="cityselect-item-box">
<text>{{item.n}}</text>
</view>
</view>
</view>
</scroll-view>
</swiper-item>
<swiper-item>
<scroll-view scroll-y class="cityScroll">
<view>
<view
class="cityselect-item"
v-for="(item,index) in district"
:key="index"
@tap="selectDistrict(index)"
>
<view class="cityselect-item-box">
<text>{{item.n}}</text>
</view>
</view>
</view>
</scroll-view>
</swiper-item>
</swiper>
</view>
</view>
</uni-popup>
</view>
</template>
<script type="text/babel">
import uniPopup from "./uni-popup/uni-popup.vue";
import uniPopupMessage from "./uni-popup/uni-popup-message.vue";
import uniPopupDialog from "./uni-popup/uni-popup-dialog.vue";
export default {
name: "CitySelect",
components: {
uniPopup,
uniPopupMessage,
uniPopupDialog
},
props: ["callback", "items", "defaultValue"],
data() {
return {
value: "请选择",
show: this.value,
province: [],
provinceActive: null,
city: [],
cityActive: null,
district: [],
districtActive: null,
current: 0
};
},
watch: {
items(nextItem) {
this.province = nextItem;
},
defaultValue(next){
this.value=next
}
},
mounted() {
console.log(this);
if (this.value) {
this.value = this.value;
}
this.province = this.items;
},
methods: {
open() {
this.province = this.items;
this.provinceActive = null;
this.cityActive = null;
this.districtActive = null;
this.city = [];
this.district = [];
this.current = 0;
this.$refs.popup.open();
},
changeNav(index) {
if (index == 0) {
this.provinceActive = null;
}
if (index == 1) {
this.cityActive = null;
}
if (index == 2) {
this.districtActive = null;
}
this.current = index;
},
selectProvince(index) {
this.provinceActive = this.province[index];
this.city = this.province[index].c;
this.current = 1;
},
selectCity(index) {
this.cityActive = this.city[index];
this.district = this.city[index].c;
this.current = 2;
},
selectDistrict(index) {
this.districtActive = this.district[index];
this.value = `${this.provinceActive.n} ${this.cityActive.n} ${this.districtActive.n}`;
// this.callback({
// province: {
// id: this.provinceActive.v,
// name: this.provinceActive.n
// },
// city: {
// id: this.cityActive.v,
// name: this.cityActive.n
// },
// district: {
// id: this.districtActive.v,
// name: this.districtActive.n
// }
// });
this.$emit("callback", {
province: {
id: this.provinceActive.v,
name: this.provinceActive.n
},
city: {
id: this.cityActive.v,
name: this.cityActive.n
},
district: {
id: this.districtActive.v,
name: this.districtActive.n
}
});
this.$refs.popup.close();
}
}
};
</script>
<style lang="less">
.cityselect {
width: 100%;
height: 75%;
background-color: #fff;
z-index: 1502;
position: relative;
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
.cityScroll {
height: 100%;
}
.swiper {
height: 800rpx;
}
}
.cityselect-header {
width: 100%;
z-index: 1;
}
.cityselect-title {
width: 100%;
font-size: 30rpx;
text-align: center;
height: 95rpx;
line-height: 95rpx;
position: relative;
&:cityselect-title:after {
height: 1px;
position: absolute;
z-index: 0;
bottom: 0;
left: 0;
content: "";
width: 100%;
background-image: linear-gradient(0deg, #ececec 50%, transparent 0);
}
}
.cityselect-nav {
width: 100%;
padding-left: 20rpx;
overflow: hidden;
display: flex;
align-items: center;
justify-content: flex-start;
.item {
font-size: 26rpx;
color: #222;
display: block;
height: 80rpx;
line-height: 92rpx;
padding: 0 16rpx;
position: relative;
margin-right: 30rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 40%;
&.active {
color: #F99C10 !important;
border-bottom: 1rpx solid #F99C10;
}
}
}
.cityselect-content {
height: 100%;
width: 100%;
}
.cityselect-item {
.cityselect-item-box {
display: block;
padding: 0 40rpx;
position: relative;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
word-break: break-all;
text-overflow: ellipsis;
line-height: 64rpx;
max-height: 65rpx;
font-size: 26rpx;
color: #333;
&:after {
content: "";
height: 1rpx;
position: absolute;
z-index: 0;
bottom: 0;
left: 0;
width: 100%;
background-image: linear-gradient(0deg, #ececec 50%, transparent 0);
}
}
}
</style>

120
components/CountDown.vue

@ -0,0 +1,120 @@
<template>
<view class="time">
{{ tipText }}
<text class="styleAll" v-if="isDay === true">{{ day }}</text>
<text class="timeTxt">{{ dayText }}</text>
<text class="styleAll">{{ hour }}</text>
<text class="timeTxt">{{ hourText }}</text>
<text class="styleAll">{{ minute }}</text>
<text class="timeTxt">{{ minuteText }}</text>
<text class="styleAll">{{ second }}</text>
<text class="timeTxt">{{ secondText }}</text>
</view>
</template>
<script>
export default {
name: 'CountDown',
props: {
//
tipText: {
type: String,
default: '倒计时',
},
dayText: {
type: String,
default: '天',
},
hourText: {
type: String,
default: '时',
},
minuteText: {
type: String,
default: '分',
},
secondText: {
type: String,
default: '秒',
},
datatime: {},
isDay: {
type: Boolean,
default: true,
},
},
data: function () {
return {
time: null,
day: '00',
hour: '00',
minute: '00',
second: '00',
}
},
created: function () {
this.show_time()
},
watch: {
datatime(val) {
clearInterval(this.timeInterval)
this.time = val
this.show_time()
},
},
mounted: function () {},
methods: {
show_time: function () {
let that = this
if (parseInt(this.time).length == 13) {
//
console.log('毫秒')
this.time = this.time / 1000
} else if (parseInt(this.time).length == 10) {
console.log('秒')
//
} else {
//
console.log('时间')
console.log(this.time)
this.time = Date.parse(this.time) / 1000
}
console.log(that.time)
function runTime() {
//
let intDiff = that.time - Date.parse(new Date()) / 1000 //
let day = 0,
hour = 0,
minute = 0,
second = 0
if (intDiff > 0) {
//
if (that.isDay === true) {
day = Math.floor(intDiff / (60 * 60 * 24))
} else {
day = 0
}
hour = Math.floor(intDiff / (60 * 60)) - day * 24
minute = Math.floor(intDiff / 60) - day * 24 * 60 - hour * 60
second = Math.floor(intDiff) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60
if (hour <= 9) hour = '0' + hour
if (minute <= 9) minute = '0' + minute
if (second <= 9) second = '0' + second
that.day = day
that.hour = hour
that.minute = minute
that.second = second
} else {
that.day = '00'
that.hour = '00'
that.minute = '00'
that.second = '00'
}
}
runTime()
this.timeInterval = setInterval(runTime, 1000)
},
},
}
</script>

122
components/CouponListWindow.vue

@ -0,0 +1,122 @@
<template>
<view>
<view class="coupon-list-window" :class="value === true ? 'on' : ''">
<view class="title">
优惠券
<text class="iconfont icon-guanbi" @click="close"></text>
</view>
<view v-if="couponList.length > 0">
<view class="coupon-list">
<div
class="item acea-row row-center-wrapper"
v-for="coupon in couponList"
:key="coupon.id"
@click="click(coupon)"
>
<div class="money">
<div>
<span class="num">{{ coupon.couponPrice }}</span>
</div>
<div class="pic-num">{{ coupon.useMinPrice }}元可用</div>
</div>
<div class="text">
<div class="condition line1">{{ coupon.couponTitle }}</div>
<div class="data acea-row row-between-wrapper">
<div v-if="coupon.endTime === 0">不限时</div>
<div v-else>截止:{{ coupon.endTime }}</div>
<div
class="iconfont icon-xuanzhong1 font-color-red"
v-if="checked === coupon.id"
></div>
<div class="iconfont icon-weixuanzhong" v-else></div>
</div>
</div>
</div>
</view>
<view class="couponNo bg-color-red" @click="couponNo">不使用优惠券</view>
</view>
<view v-if="!couponList.length && loaded">
<view class="pictrue">
<image :src="`${$VUE_APP_RESOURCES_URL}/images/noCoupon.png`" class="image" />
</view>
</view>
</view>
<view class="mask" @touchmove.prevent :hidden="value === false" @click="close"></view>
</view>
</template>
<style scoped lang="less">
.coupon-list-window .iconfont {
font-size: 40rpx;
}
.couponNo {
font-size: 30rpx;
font-weight: bold;
color: #fff;
width: 690rpx;
height: 86rpx;
border-radius: 43rpx;
text-align: center;
line-height: 86rpx;
margin: 60rpx auto;
}
</style>
<script>
import { getOrderCoupon } from "@/api/order";
import DataFormatT from "@/components/DataFormatT";
export default {
name: "CouponListWindow",
components: {
DataFormatT
},
props: {
value: Boolean,
checked: Number,
price: {
type: [Number, String],
default: undefined
},
cartid: {
type: String,
default: ""
}
},
data: function() {
return {
couponList: [],
loaded: false
};
},
watch: {
price(n) {
if (n === undefined || n == null) return;
this.getCoupon();
},
cartid(n) {
if (n === undefined || n == null) return;
this.getCoupon();
}
},
mounted: function() {},
methods: {
close: function() {
this.$emit("input", false);
this.$emit("close");
},
getCoupon() {
getOrderCoupon(this.cartid).then(res => {
this.couponList = res.data;
this.loaded = true;
});
},
click(coupon) {
this.$emit("checked", coupon);
this.$emit("input", false);
},
couponNo: function() {
this.$emit("checked", null);
this.$emit("input", false);
}
}
};
</script>

75
components/CouponPop.vue

@ -0,0 +1,75 @@
<template>
<view>
<view class="coupon-list-window" :class="coupon.coupon === true ? 'on' : ''">
<view class="title">
优惠券
<text class="iconfont icon-guanbi" @click="close"></text>
</view>
<view class="coupon-list" v-if="coupon.list.length > 0">
<view
class="item acea-row row-center-wrapper"
v-for="(item, couponpopIndex) in coupon.list"
:key="couponpopIndex"
@click="getCouponUser(couponpopIndex, item.id)"
>
<view class="money">
<text class="num">{{ item.couponPrice }}</text>
</view>
<view class="text">
<view class="condition line1">购物满{{ item.useMinPrice }}元可用</view>
<view class="data acea-row row-between-wrapper">
<view v-if="item.end_time === 0">不限时</view>
<view v-else>{{ item.startTime }}-{{ item.endTime }}</view>
<view
class="bnt acea-row row-center-wrapper"
:class="!item.isUse ? 'bg-color-red' : 'gray'"
>{{ !item.isUse ? "立即领取" : "已领取" }}</view>
</view>
</view>
</view>
</view>
<!--无优惠券-->
<view class="pictrue" v-else>
<image :src="`${$VUE_APP_RESOURCES_URL}/images/noCoupon.png`" class="image" />
</view>
</view>
<view class="mask" @touchmove.prevent :hidden="coupon.coupon === false" @click="close"></view>
</view>
</template>
<script>
import { getCouponReceive } from "@/api/user";
export default {
name: "CouponPop",
props: {
coupon: {
type: Object,
default: () => {}
}
},
data: function() {
return {};
},
mounted: function() {},
methods: {
close: function() {
this.$emit("changeFun", { action: "changecoupon", value: false }); //$emit():
},
getCouponUser: function(index, id) {
let that = this,
list = that.coupon.list;
if (list[index].is_use === true) return;
getCouponReceive(id).then(function() {
uni.showToast({
title: "已领取",
icon: "none",
duration: 2000
});
that.$set(list[index], "is_use", true);
that.$emit("changefun", { action: "currentcoupon", value: index });
that.$emit("changeFun", { action: "changecoupon", value: false });
});
}
}
};
</script>

88
components/CouponWindow.vue

@ -0,0 +1,88 @@
<template>
<view v-if="couponList.length > 0">
<view class="coupon-window" :class="value ? 'on' : ''">
<view class="couponWinList">
<view class="item acea-row row-between-wrapper" v-for="(item, couponwindiwIndex) in couponList" :key="couponwindiwIndex">
<view class="money font-color-red">
<text class="num">{{ item.coupon_price }}</text>
</view>
<view class="text">
<view class="name">
购物买{{ item.use_min_price }}{{ item.coupon_price }}
</view>
<view v-if="item.end_time">
{{ item.start_time }}-{{ item.end_time }}
</view>
</view>
</view>
<view style="height:120rpx"></view>
</view>
<view class="lid">
<view class="bnt font-color-red" @click="checked">立即领取</view>
<view class="iconfont icon-guanbi3" @click="close"></view>
</view>
</view>
<view class="mask" @touchmove.prevent :hidden="!value"></view>
</view>
</template>
<script>
import {
mapGetters
} from "vuex";
import {handleLoginFailure} from "@/utils";
import {
couponReceiveBatch
} from "@/api/user";
export default {
name: "CouponWindow",
props: {
couponList: {
type: Array,
default: () => []
}
},
computed: mapGetters(["isLogin"]),
data: function() {
return {
value: true
};
},
mounted: function() {},
methods: {
checked() {
const isLogin = this.isLogin;
if (!isLogin) return handleLoginFailure();
const ids = this.couponList.reduce((initial, coupon) => {
initial.push(coupon.id);
return initial;
}, []);
couponReceiveBatch(ids)
.then(() => {
this.$emit("success");
uni.showToast({
title: '领取成功',
icon: 'success',
duration: 2000
});
})
.catch(() => {
uni.showToast({
title: '已领取',
icon: 'none',
duration: 2000
});
});
if (isLogin) {
this.value = false;
this.$emit("checked");
}
},
close: function() {
this.value = false;
this.$emit("close");
}
}
};
</script>

24
components/DataFormat.vue

@ -0,0 +1,24 @@
<template>
<text>{{time}}</text>
</template>
<script>
import { dataFormat } from "@/utils";
export default {
name: "DataFormat",
props: ["date"],
data: function() {
return {
time: ""
};
},
mounted() {
this.time = dataFormat(this.date);
},
watch: {
"$props.date"(props) {
this.time = dataFormat(this.date);
}
}
};
</script>

24
components/DataFormatT.vue

@ -0,0 +1,24 @@
<template>
<text>{{time}}</text>
</template>
<script>
import { dateFormatT } from "@/utils";
export default {
name: "DataFormatT",
props: ["date"],
data: function() {
return {
time: ""
};
},
mounted() {
this.time = dateFormatT(this.date);
},
watch: {
"$props.date"(props) {
this.time = dateFormatT(this.date);
}
}
};
</script>

65
components/Footer.vue

@ -0,0 +1,65 @@
<template>
<view>
<view class="footer-bg"></view>
<view id="footer" :class="[isIpx ? 'iphonex-footer' : '', 'acea-row row-middle'] ">
<view
class="item"
:class="{ on: footerIndex == tabtarIndex }"
v-for="(item, footerIndex) in footerList"
:key="footerIndex"
>
<view
class="iconfont"
:class="item.icon1 + ' ' + (footerIndex == tabtarIndex ? item.icon2 : '')"
></view>
<view>{{ item.name }}</view>
</view>
</view>
</view>
</template>
<script>
import { mapState, mapMutations, mapActions } from "vuex";
export default {
name: "Footer",
props: {},
data: function() {
return {
footerList: [
{
name: "首页",
icon1: "icon-shouye-xianxing",
icon2: "icon-shouye",
url: "/pages/home/index"
},
{
name: "分类",
icon1: "icon-yingyongchengxu-xianxing",
icon2: "icon-yingyongchengxu",
url: "/pages/shop/GoodsClass/index"
},
{
name: "购物车",
icon1: "icon-caigou-xianxing",
icon2: "icon-caigou",
url: "/pages/shop/ShoppingCart/index"
},
{
name: "我的",
icon1: "icon-yonghu-xianxing",
icon2: "icon-yonghu",
url: "/pages/user/User/index"
}
],
isIpx: false
};
},
computed: {
...mapState(["tabtarIndex"])
},
methods: {
},
mounted() {
}
};
</script>

49
components/GoodList.vue

@ -0,0 +1,49 @@
<template>
<view class="goodList">
<view @click="routerGo(item)" class="item acea-row row-between-wrapper" v-for="(item, goodlistIndex) in goodList" :key="goodlistIndex">
<view class="pictrue">
<image :src="item.image" class="image" />
<image :src="`${$VUE_APP_RESOURCES_URL}/images/one.png`" class="numPic" v-if="isSort === true && index === 0" />
<image :src="`${$VUE_APP_RESOURCES_URL}/images/two.png`" class="numPic" v-if="isSort === true && index === 1" />
<image :src="`${$VUE_APP_RESOURCES_URL}/images/three.png`" class="numPic" v-if="isSort === true && index === 2" />
</view>
<view class="underline">
<view class="text">
<view class="line1">{{ item.storeName }}</view>
<view class="money font-color-red">
<text class="num">{{ item.price }}</text>
</view>
<view class="vip-money acea-row row-middle">
<view class="vip">{{ item.otPrice || 0 }}</view>
<text class="num">已售{{ item.sales }}{{ item.unitName }}</text>
</view>
</view>
</view>
<!-- <view class="iconfont icon-gouwuche cart-color acea-row row-center-wrapper"></view> -->
</view>
</view>
</template>
<script>
export default {
name: "GoodList",
props: {
goodList: {
type: Array,
default: () => []
},
isSort: {
type: Boolean,
default: true
}
},
data: function() {
return {};
},
methods:{
routerGo(item) {
this.$yrouter.push({ path: '/pages/shop/GoodsCon/index', query: { id: item.id } });
}
}
};
</script>

59
components/Home.vue

@ -0,0 +1,59 @@
<template>
<view class="home" :style="{ top: top + 'px' }" style="position:fixed;" id="right-nav" @touchmove="touchmove($event)">
<view class="homeCon bg-color-red1" :class="homeActive === true ? 'on' : ''">
<view @click="homeGo()" class="iconfont icon-shouye-xianxing " style="color: green;"></view>
<view @click="shoppingCartGo()" class="iconfont icon-caigou-xianxing" style="color: green;"></view>
<!--<view @click="userGo()" class="iconfont icon-yonghu1"></view>-->
</view>
</view>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: 'Home',
props: {},
data: function() {
return {
top: '',
homeActive: true
};
},
computed: mapGetters(['homeActive']),
methods: {
userGo() {
this.$yrouter.push('/pages/user/User/index');
},
homeGo() {
this.$yrouter.switchTab('/pages/home/index');
},
shoppingCartGo() {
this.$yrouter.switchTab('/pages/shop/ShoppingCart/index');
},
touchmove(event) {
// event.preventDefault();
// let top =
// event.touches[0].pageY -
// (document.documentElement.scrollTop || document.body.scrollTop) -
// this.$el.clientHeight;
// if (top > 390) top = 390;
// else if (top < 55) top = 55;
this.top = 55;
},
}
};
</script>
<style scoped lang="less">
.mystyl {
display: inline-block;
width: 64rpx;
height: 64rpx;
margin-top:12rpx;
box-sizing: border-box;
border: 1px solid #e1e1e1;
border-radius: 50%;
background-size: 124rpx auto;
background-repeat: no-repeat;
background-color: rgba(255, 255, 255, 0.9);
}
</style>

21
components/Loading.vue

@ -0,0 +1,21 @@
<template>
<view class="Loads acea-row row-center-wrapper" v-if="loading || !loaded" style="margin-top: 20rpx;">
<template v-if="loading">
<view class="iconfont icon-jiazai loading acea-row row-center-wrapper"></view>
正在加载中
</template>
<template v-if="!loading">
上拉加载更多
</template>
</view>
</template>
<script>
export default {
name: "Loading",
props: {
loaded: Boolean,
loading: Boolean
}
};
</script>

74
components/Mask.vue

@ -0,0 +1,74 @@
<template>
<div
:class="show?'yd-mask g-fix-ios-overflow-scrolling-bug':'yd-mask' "
ref="scrollView"
:style="styles"
>
<slot></slot>
</div>
</template>
<script type="text/babel">
export default {
name: "yd-mask",
data() {
return {
show: this.value
};
},
props: {
value: {
type: Boolean,
default: false
},
bgcolor: {
type: String,
default: "#000"
},
zindex: {
default: 1500
},
opacity: {
default: 0.5
},
animated: {
type: Boolean,
default: true
}
},
computed: {
styles() {
const style = {
"z-index": this.zindex,
"background-color": this.bgcolor
};
if (this.show) {
style["opacity"] = this.opacity;
style["pointer-events"] = "auto";
}
return style;
}
},
mounted() {}
};
</script>
<style lang="less">
@css-prefix: yd;
.@{css-prefix} {
&-mask {
position: fixed;
bottom: 0;
right: 0;
left: 0;
top: 0;
display: flex;
justify-content: center;
align-items: center;
pointer-events: none;
transition: opacity 0.2s ease-in;
opacity: 0;
}
}
</style>

155
components/Menu.vue

@ -0,0 +1,155 @@
<template>
<!-- 产品分类导航 -->
<view class="menu-category-box mb10" v-if="carousel" :style="list.length <= menu ? `height:200rpx` : `height:360rpx`">
<swiper
class="menu-swiper-box"
:style="list.length <= menu ? `height:160rpx` : `height:320rpx`"
@change="onSwiper"
circular
:autoplay="false"
:interval="3000"
:duration="1000"
>
<swiper-item class="menu-swiper-item" v-for="(itemList, index) in carousel" :key="index" :style="list.length <= menu ? `height:200rpx` : `height:340rpx`">
<view class="menu-tab-box">
<view class="tab-list y-f" :style="{ width: 690 / menu + 'rpx' }" v-for="item in itemList" :key="item.name" @tap="routerTo(item)">
<image class="tab-img Shop-selector-circular" :style="{ width: imgW + 'rpx', height: imgW + 'rpx' }" :src="item.pic"></image>
<text class="Shop-selector-rect">{{ item.name }}</text>
</view>
</view>
</swiper-item>
</swiper>
<view class="menu-category-dots" v-if="carousel.length > 1">
<text :class="categoryCurrent === index ? 'category-dot-active' : 'category-dot'" v-for="(dot, index) in carousel.length" :key="index"></text>
</view>
</view>
</template>
<script>
export default {
components: {},
data() {
return {
categoryCurrent: 0 //
};
},
props: {
list: {
type: Array,
default: []
},
menu: {
default: 4
},
imgW: {
type: Number,
default: 88
}
},
computed: {
carousel() {
if (this.list) {
let list = this.sortData(this.list, this.menu * 2);
return list;
}
}
},
created() {},
methods: {
//
sortData(oArr, length) {
let arr = [];
let minArr = [];
oArr.forEach(c => {
if (minArr.length === length) {
minArr = [];
}
if (minArr.length === 0) {
arr.push(minArr);
}
minArr.push(c);
});
return arr;
},
//
onSwiper(e) {
this.categoryCurrent = e.detail.current;
},
//
routerTo(item) {
this.$yrouter.push(item.uniapp_url);
}
}
};
</script>
<style lang="scss">
//
.y-f {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
}
.menu-category-box {
padding: 30rpx 30rpx 0 30rpx;
background: #fff;
box-sizing: border-box;
}
.menu-category-box,
.menu-swiper-box {
position: relative;
background: #fff;
.menu-swiper-item {
background: #fff;
height: 100%;
width: 100%;
}
.menu-tab-box {
display: flex;
flex-wrap: wrap;
.tab-list {
font-size: 22rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(51, 51, 51, 1);
padding-bottom: 30rpx;
.tab-img {
border-radius: 25rpx;
margin-bottom: 10rpx;
}
}
}
.menu-category-dots {
display: flex;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 20rpx;
.category-dot {
width: 40rpx;
height: 3rpx;
background: #eeeeee;
margin-right: 10rpx;
}
.category-dot-active {
width: 40rpx;
height: 3rpx;
background: #a8700d;
margin-right: 10rpx;
}
}
}
</style>

99
components/OrderGoods.vue

@ -0,0 +1,99 @@
<template>
<view class="orderGoods">
<!-- <view class="total">{{ cartInfo.length }}件商品</view> -->
<view class="goodWrapper">
<view class="item acea-row-nowrap" v-for="cart in cartInfo" :key="cart.id">
<view class="pictrue">
<image :src="cart.productInfo.image" class="image" />
</view>
<view class="text">
<view class="acea-row row-between-wrapper">
<view class="name line1">{{ cart.productInfo.storeName }}</view>
</view>
<view class="acea-row-nowrap row-middle">
<view class="attr" v-if="cart.productInfo.attrInfo">{{ cart.productInfo.attrInfo.sku }}</view>
<view class="num">x {{ cart.cartNum }}</view>
</view>
<view class="money"><text class="sm-word"></text>{{ cart.productInfo.price }}<text class="sm-word" v-if="cart.productInfo.giveIntegral > 0">+{{ cart.productInfo.giveIntegral }}积分</text></view>
<!-- <view class="money font-color-red" v-if="isIntegral">{{ cart.costPrice }}积分</view>
<view class="money" v-else><text class="sm-word"></text>{{ cart.truePrice }}</view> -->
<view class="evaluate" v-if="evaluate == 3 && cart.isReply == 0" @click="routerGo(cart)">评价</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'OrderGoods',
props: {
evaluate: Number,
cartInfo: {
type: Array,
default: () => [],
},
isIntegral: Boolean,
},
data: function() {
return {}
},
mounted: function() {},
methods: {
routerGo(cart) {
this.$yrouter.push({
path: '/pagesB/pages/shop/GoodsEvaluate/index',
query: { id: cart.unique },
})
},
},
}
</script>
<style lang="less" scoped>
.orderGoods{
border-radius: 10rpx;
margin: 20rpx 0;
.goodWrapper{
.item{
height: auto;
padding: 30rpx 0;
.pictrue{
width: 170rpx;
height: 170rpx;
border-radius: 10rpx;
}
.attr{
width: auto;
margin-right: 12rpx;
color: #999;
font-size: 24rpx;
line-height: 34rpx;
}
.text{
width: auto;
margin-left: 30rpx;
.name{
width: 420rpx;
font-size: 28rpx;
color: #222;
line-height: 40rpx;
}
.money{
font-size: 38rpx;
color: #E5270F;
font-weight: 500;
margin-top: 38rpx;
}
.sm-word{
font-size: 24rpx;
}
.evaluate{
font-size: 26rpx;
line-height: 46rpx;
text-align: center;
}
}
}
}
}
</style>

202
components/Payment.vue

@ -0,0 +1,202 @@
<template>
<view>
<view class="payment" :class="value === true ? 'on' : ''">
<view class="title acea-row row-center-wrapper">
选择付款方式<text class="iconfont icon-guanbi" @click="close"></text>
</view>
<view
class="item acea-row row-between-wrapper"
v-if="types.indexOf('weixin') !== -1"
@click="checked('weixin')"
>
<view class="left acea-row row-between-wrapper">
<view class="iconfont icon-weixinzhifu"></view>
<view class="text">
<view class="name">微信支付</view>
<view class="info">使用微信快捷支付</view>
</view>
</view>
<view class="iconfont icon-xiangyou"></view>
</view>
<!-- <view
class="item acea-row row-between-wrapper"
v-if="types.indexOf('alipay') !== -1"
@click="checked('alipay')"
>
<view class="left acea-row row-between-wrapper">
<view class="iconfont icon-zhifubao"></view>
<view class="text">
<view class="name">支付宝支付</view>
<view class="info">使用线上支付宝支付</view>
</view>
</view>
<view class="iconfont icon-xiangyou"></view>
</view> -->
<view
class="item acea-row row-between-wrapper"
v-if="types.indexOf('yue') !== -1"
@click="checked('yue')"
>
<view class="left acea-row row-between-wrapper">
<view class="iconfont icon-yuezhifu"></view>
<view class="text">
<view class="name">余额支付</view>
<view class="info">
当前可用余额<text class="money">{{ balance }}</text>
</view>
</view>
</view>
<view class="iconfont icon-xiangyou"></view>
</view>
<!-- <view
class="item acea-row row-between-wrapper"
v-if="types.indexOf('offline') !== -1"
@click="checked('offline')"
>
<view class="left acea-row row-between-wrapper">
<view class="iconfont icon-yuezhifu1"></view>
<view class="text">
<view class="name">线下支付</view>
<view class="info">选择线下付款方式</view>
</view>
</view>
<view class="iconfont icon-xiangyou"></view>
</view> -->
</view>
<view class="mask" v-show="value" @click="close"></view>
</view>
</template>
<script>
export default {
name: "Payment",
props: {
value: {
type: Boolean,
default: false
},
balance: {
type: [Number, String],
default: 0
},
types: {
type: Array,
default: () => ["weixin", "alipay", "yue", "offline"]
}
},
data: function() {
return {};
},
mounted: function() {},
methods: {
checked: function(type) {
this.$emit("checked", type);
this.close();
},
close: function() {
this.$emit("input", false);
}
}
};
</script>
<style scoped lang="less" lang="less">
.payment {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
border-radius: 0.16*100rpx 0.16*100rpx 0 0;
background-color: #fff;
padding-bottom: 0.6*100rpx;
z-index: 99;
transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
-webkit-transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
-moz-transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
-o-transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
transform: translate3d(0, 100%, 0);
-webkit-transform: translate3d(0, 100%, 0);
-ms-transform: translate3d(0, 100%, 0);
-moz-transform: translate3d(0, 100%, 0);
-o-transform: translate3d(0, 100%, 0);
}
.payment.on {
transform: translate3d(0, 0, 0);
-webkit-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
}
.payment .title {
text-align: center;
height: 1.23*100rpx;
font-size: 0.32*100rpx;
color: #282828;
font-weight: bold;
padding-right: 0.3*100rpx;
margin-left: 0.3*100rpx;
position: relative;
border-bottom: 0.01*100rpx solid #eee;
}
.payment .title .iconfont {
position: absolute;
right: 0.3*100rpx;
top: 50%;
transform: translateY(-50%);
font-size: 0.43*100rpx;
color: #8a8a8a;
font-weight: normal;
}
.payment .item {
border-bottom: 0.01*100rpx solid #eee;
height: 1.3*100rpx;
margin-left: 0.3*100rpx;
padding-right: 0.3*100rpx;
}
.payment .item .left {
width: 6.1*100rpx;
}
.payment .item .left .text {
width: 5.4*100rpx;
}
.payment .item .left .text .name {
font-size: 0.32*100rpx;
color: #282828;
}
.payment .item .left .text .info {
font-size: 0.24*100rpx;
color: #999;
}
.payment .item .left .text .info .money {
color: #ff9900;
}
.payment .item .left .iconfont {
font-size: 0.45*100rpx;
color: #09bb07;
}
.payment .item .left .iconfont.icon-zhifubao {
color: #00aaea;
}
.payment .item .left .iconfont.icon-yuezhifu {
color: #ff9900;
}
.payment .item .left .iconfont.icon-yuezhifu1 {
color: #eb6623;
}
.payment .item .iconfont {
font-size: 0.3*100rpx;
color: #999;
}
</style>

133
components/PriceChange.vue

@ -0,0 +1,133 @@
<template>
<view>
<view class="priceChange" :class="change === true ? 'on' : ''">
<view class="priceTitle">
<text v-if="status==0">
<text v-if="orderInfo.refundStatus == 1">立即退款</text>
<text v-if="orderInfo.refundStatus != 1">一键改价</text>
</text>
<text v-if="status!=0">订单备注</text>
<text class="iconfont icon-guanbi" @click="close"></text>
</view>
<view class="listChange" v-if="status == 0">
<view class="item acea-row row-between-wrapper" v-if="orderInfo.refundStatus === 0">
<view>商品总价(¥)</view>
<view class="money">
{{ orderInfo.totalPrice }}
<text class="iconfont icon-suozi"></text>
</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="orderInfo.refundStatus === 0">
<view>原始邮费(¥)</view>
<view class="money">
{{ orderInfo.payPostage }}
<text class="iconfont icon-suozi"></text>
</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="orderInfo.refundStatus === 0">
<view>实际支付(¥)</view>
<view class="money">
<input
type="text"
v-model="price"
:class="focus === true ? 'on' : ''"
@focus="priceChange"
/>
</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="orderInfo.refundStatus === 1">
<view>实际支付(¥)</view>
<view class="money">
{{ orderInfo.payPrice }}
<text class="iconfont icon-suozi"></text>
</view>
</view>
<view class="item acea-row row-between-wrapper" v-if="orderInfo.refundStatus === 1">
<view>退款金额(¥)</view>
<view class="money">
<input
type="text"
v-model="refund_price"
:class="focus === true ? 'on' : ''"
@focus="priceChange"
/>
</view>
</view>
</view>
<view class="listChange" v-else>
<textarea
:placeholder="'请填写备注信息...'"
v-model="remark"
></textarea>
</view>
<view class="modify" @click="save">{{ orderInfo.refundStatus === 0 ? "立即修改" : "确认退款" }}</view>
<view class="modify1" @click="refuse" v-if="orderInfo.refundStatus === 1">拒绝退款</view>
</view>
<view class="mask" @touchmove.prevent v-show="change === true"></view>
</view>
</template>
<style scoped lang="less" >
.priceChange .listChange textarea {
border: 1px solid #eee;
width: 100%;
height: 200rpx;
margin-top: 50rpx;
border-radius: 10rpx;
color: #333;
padding: 20rpx;
}
</style>
<script>
export default {
name: "PriceChange",
components: {},
props: {
change: Boolean,
orderInfo: Object,
status: String
},
data: function() {
return {
focus: false,
price: 0,
refund_price: 0,
remark: ""
};
},
watch: {
orderInfo: function() {
this.price = this.orderInfo.payPrice;
this.refund_price = this.orderInfo.payPrice;
this.remark = "";
}
},
mounted: function() {},
methods: {
priceChange: function() {
this.focus = true;
},
close: function() {
this.price = this.orderInfo.payPrice;
this.$emit("closechange", false);
},
save: function() {
let that = this;
that.$emit("savePrice", {
price: that.price,
refund_price: that.refund_price,
type: 1,
remark: that.remark
});
},
refuse: function() {
let that = this;
that.$emit("savePrice", {
price: that.price,
refund_price: that.refund_price,
type: 2,
remark: that.remark
});
}
}
};
</script>

71
components/ProductConSwiper.vue

@ -0,0 +1,71 @@
<template>
<view class="slider-banner product-bg">
<swiper
class="swiper-wrapper"
@change="handleChange"
v-if="imgUrls.length > 0"
>
<block v-for="(item, imgUrlsIndex) in imgUrls" :key="imgUrlsIndex">
<swiper-item>
<image :src="item" @tap="previewImage(imgUrlsIndex)" class="slide-image" />
</swiper-item>
</block>
</swiper>
<!-- <swiper class="swiper-wrapper" :options="ProductConSwiper" v-if="imgUrls.length > 0">
<swiperSlide class="swiper-slide" v-for="item in imgUrls" :key="item" ref="goodSwiper">
<image :src="item" class="slide-image" />
</swiperSlide>
</swiper>-->
<view class="pages">{{ currents || 1 }}/{{ imgUrls.length || 1 }}</view>
</view>
</template>
<script>
// import { swiper, swiperSlide } from "vue-awesome-swiper";
export default {
name: "ProductConSwiper",
components: {
// swiper,
// swiperSlide
},
props: {
imgUrls: {
type: Array,
default: () => [],
},
},
data: function () {
let that = this;
return {
currents: 1,
ProductConSwiper: {
autoplay: {
disableOnInteraction: false,
delay: 2000,
},
loop: true,
speed: 1000,
observer: true,
observeParents: true,
on: {
slideChangeTransitionStart: function () {
that.currents = this.realIndex + 1;
},
},
},
};
},
mounted: function () {},
methods: {
handleChange(event) {
this.currents = event.mp.detail.current + 1;
},
previewImage(current) {
uni.previewImage({
current,
urls: this.imgUrls,
});
},
},
};
</script>

145
components/ProductWindow.vue

@ -0,0 +1,145 @@
<template>
<view>
<view class="product-window" :class="attr.cartAttr === true ? 'on' : ''">
<view class="textpic acea-row row-between-wrapper">
<view class="pictrue">
<image @tap="previewImage" :src="attr.productSelect.image" class="image" />
</view>
<view class="text">
<view class="line1">{{ attr.productSelect.store_name }}</view>
<view class="money font-color-red" v-if="!isIntegral">
<text class="num">{{ attr.productSelect.price }}</text>
<text class="stock">库存: {{ attr.productSelect.stock }}</text>
</view>
<view class="money font-color-red" v-if="isIntegral">
<text class="num">{{ attr.productSelect.integral }}积分</text>
<text class="stock">库存: {{ attr.productSelect.stock }}</text>
</view>
</view>
<view class="iconfont icon-guanbi" @click="closeAttr"></view>
</view>
<view class="productWinList">
<view
class="item"
v-for="(item, indexw) in attr.productAttr"
:key="indexw"
>
<view class="title">{{ item.attrName }}</view>
<view class="listn acea-row row-middle">
<view
class="itemn"
:class="item.index == indexn ? 'on' : ''"
v-for="(itemn, indexn) in item.attrValue"
@click="tapAttr(indexw, indexn)"
:key="indexn"
>{{ itemn.attr }}</view
>
</view>
</view>
</view>
<view class="cart">
<view class="title">数量</view>
<view class="carnum acea-row row-left">
<view
class="item reduce"
:class="cartNum <= 1 ? 'on' : ''"
@click="CartNumDes"
>-</view
>
<view class="item num">{{ cartNum }}</view>
<view
class="item plus"
:class="cartNum >= attr.productSelect.stock ? 'on' : ''"
@click="CartNumAdd"
>+</view
>
</view>
</view>
</view>
<view
class="mask"
@touchmove.prevent
:hidden="attr.cartAttr === false"
@click="closeAttr"
></view>
</view>
</template>
<script>
export default {
name: "ProductWindow",
props: {
isIntegral:Boolean,
attr: {
type: Object,
default: () => {},
},
cartNum: {
type: Number,
default: () => 1,
},
},
data: function () {
return {};
},
mounted: function () {
console.log(this);
},
watch: {
attr(nextAttr) {
},
},
methods: {
closeAttr: function () {
this.$emit("changeFun", { action: "changeattr", value: false });
},
CartNumDes: function () {
this.$emit("changeFun", { action: "ChangeCartNum", value: false });
},
CartNumAdd: function () {
this.$emit("changeFun", { action: "ChangeCartNum", value: 1 });
},
tapAttr: function (indexw, indexn) {
//
// H5attrH5
// props
//
this.attr.productAttr[indexw].index = indexn;
let that = this;
let value = that.getCheckedValue().sort().join(",");
that.$emit("changeFun", {
action: "ChangeAttr",
value: {
value,
indexw,
indexn,
},
});
},
//
getCheckedValue: function () {
let productAttr = this.attr.productAttr;
let value = [];
for (let i = 0; i < productAttr.length; i++) {
for (let j = 0; j < productAttr[i].attrValueArr.length; j++) {
if (productAttr[i].index === j) {
value.push(productAttr[i].attrValueArr[j]);
}
}
}
return value;
},
previewImage() {
uni.previewImage({
current: 0,
urls: [this.attr.productSelect.image],
});
},
},
};
</script>
<style scoped lang="less">
.product-window{
padding-bottom: 190rpx;
}
</style>

215
components/PromotionGood.vue

@ -0,0 +1,215 @@
<template>
<view>
<view class="sh-title-card mb10">
<view class="title-box">
<image class="title-bg" :src="`${$VUE_APP_RESOURCES_URL}/images/title1.png`" mode="aspectFill" />
<view class="title-text">为你推荐</view>
<!-- <view class="title-text" :style="{ color: detail.color }">为你推荐</view> -->
</view>
</view>
<view class="hot-goods mx20 mb10" v-if="benefit.length">
<view class="goods-list x-f">
<view class="goods-item" v-for="(item, promotionGoodIndex) in benefit" :key="promotionGoodIndex">
<view class="goods-box" @tap="routerGo(item)">
<view class="img-box">
<!-- <image class="tag-img" :src="item.image" mode=""></image> -->
<image class="img" :src="item.image" lazy-load mode="aspectFill"></image>
</view>
<view class="tip one-t">{{ item.storeName }}</view>
<view class="title more-t">{{ item.storeName }}</view>
<view class="price-box">
<view class="flex x-bc align-end">
<view class="current">{{ item.activity_type === 'groupon' ? item.price : item.otPrice }}
</view>
<view class="sales miso-font">仅剩{{ item.stock }}{{ item.unitName }}</view>
</view>
<view class="x-f tag-box">
<!-- <view class="discount">新人礼</view>
<view class="discount">满100减60</view> -->
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'PromotionGood',
props: ['benefit'],
data: function () {
return {};
},
methods: {
routerGo(item) {
this.$yrouter.push({
path: '/pages/shop/GoodsCon/index',
query: {
id: item.id
}
});
}
},
mounted() {
}
};
</script>
<style lang="scss">
.sh-title-card {
width: 750rpx;
}
.title-box {
width: 710rpx;
height: 88rpx;
margin: 0 auto;
position: relative;
border-radius: 30rpx;
.title-bg {
width: 100%;
height: 100%;
}
.title-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-weight: bold;
}
}
.goods-box {
width: 345rpx;
background: #fff;
padding-bottom: 20rpx;
border-radius: 20rpx;
overflow: hidden;
.img-box {
width: 345rpx;
height: 345rpx;
overflow: hidden;
position: relative;
.tag-img {
position: absolute;
left: 0;
top: 0;
z-index: 2;
width: 80rpx;
height: 40rpx;
}
.img {
width: 345rpx;
height: 345rpx;
background-color: #ccc;
}
}
.tip {
width: 346rpx;
line-height: 56rpx;
background: rgba(246, 242, 234, 1);
font-size: 22rpx;
font-family: PingFang SC;
font-weight: 400;
color: rgba(168, 112, 13, 1);
padding: 0 20rpx;
}
.title {
font-size: 24rpx;
font-family: PingFang SC;
font-weight: 500;
line-height: 36rpx;
height: 72rpx;
margin: 20rpx 20rpx 10rpx;
}
.price-box {
padding: 10rpx 20rpx 0;
width: 344rpx;
box-sizing: border-box;
.sales {
font-size: 20rpx;
font-family: PingFang SC;
font-weight: 400;
color: rgba(153, 153, 153, 1);
line-height: 20rpx;
margin-bottom: 20rpx;
}
.current {
font-size: 30rpx;
font-weight: 500;
color: rgba(225, 33, 43, 1);
line-height: 30rpx;
margin-bottom: 20rpx;
&:before {
content: '¥';
font-size: 26rpx;
}
}
.original {
font-size: 22rpx;
font-weight: 400;
text-decoration: line-through;
color: rgba(153, 153, 153, 1);
margin-left: 14rpx;
line-height: 22rpx;
margin-bottom: 10rpx;
&:before {
content: '¥';
font-size: 20rpx;
}
}
.tag-box {
.discount {
line-height: 28rpx;
border: 1rpx solid rgba(225, 33, 43, 1);
border-radius: 8rpx;
font-size: 18rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(225, 33, 43, 1);
padding: 0 8rpx;
margin-right: 10rpx;
}
}
}
}
//
.hot-goods {
// background: linear-gradient(#fff 200rpx, #f6f6f6 500rpx, #f6f6f6);
// border-radius: 20rpx;
.goods-list {
flex-wrap: wrap;
width: 710rpx;
.goods-item {
margin-right: 20rpx;
margin-bottom: 20rpx;
width: 345rpx;
box-shadow: 0px 0px 10rpx 4rpx rgba(199, 199, 199, 0.22);
border-radius: 20rpx;
&:nth-child(2n) {
margin-right: 0;
}
}
}
}
</style>

82
components/Recommend.vue

@ -0,0 +1,82 @@
<template>
<view class="recommend" ref="container">
<view class="title acea-row row-center-wrapper">
<text class="iconfont icon-zhuangshixian"></text>
<text class="name">为你推荐</text>
<text class="iconfont icon-zhuangshixian lefticon"></text>
</view>
<view class="recommendList acea-row row-between-wrapper">
<view @click="routerGo(item)" class="item" v-for="(item, recommendIndex) in hostProduct"
:key="recommendIndex">
<view class="pictrue">
<image :src="item.image" class="image" />
</view>
<view class="name line1">{{ item.storeName }}</view>
<view class="money font-color-red">
<text class="num">{{ item.price }}</text>
</view>
</view>
</view>
<Loading :loaded="loadend" :loading="loading"></Loading>
</view>
</template>
<script>
import {
getHostProducts
} from '@/api/store';
import Loading from '@/components/Loading';
export default {
name: 'Recommend',
props: {
recommendLoading: Boolean
},
components: {
Loading
},
watch: {
recommendLoading(nextLoading) {
if (nextLoading) {
this.hostProducts()
}
}
},
data: function () {
return {
hostProduct: [],
page: 1,
limit: 20,
loadTitle: '',
loading: false,
loadend: false
};
},
mounted: function () {
this.hostProducts();
},
methods: {
routerGo(item) {
this.$yrouter.push({
path: '/pages/shop/GoodsCon/index',
query: {
id: item.id
}
});
},
hostProducts: function () {
let that = this;
if (that.loading) return; //false
if (that.loadend) return; //false
that.loading = true;
getHostProducts(that.page, that.limit).then(res => {
that.loading = false;
//apply();js;
that.hostProduct.push.apply(that.hostProduct, res.data);
that.loadend = res.data.length < that.limit; //
that.page = that.page + 1;
this.$emit('changeRecommendLoading', false)
});
}
},
};
</script>

40
components/ShareInfo.vue

@ -0,0 +1,40 @@
<template>
<view v-if="shareInfoStatus" class="poster-first">
<view class="mask-share">
<!-- <image :src="`${$VUE_APP_RESOURCES_URL}/images/share-info.png`" @click="shareInfoClose" /> -->
</view>
</view>
</template>
<style scoped lang="less">
.poster-first {
overscroll-behavior: contain;
}
.mask-share {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999;
}
.mask-share image{
width: 100%;
}
</style>
<script>
export default {
name: "ShareInfo",
props: {
shareInfoStatus: Boolean
},
data: function() {
return {};
},
mounted: function() {},
methods: {
shareInfoClose: function() {
this.$emit("setShareInfoStatus");
}
}
};
</script>

43
components/ShareRedPackets.vue

@ -0,0 +1,43 @@
<template>
<view class="sharing-packets" :class="state === true ? 'on' : ''">
<view
class="iconfont icon-guanbi acea-row row-center-wrapper"
@click="closeShare"
></view>
<view class="line"></view>
<view class="sharing-con" @click="goShare">
<image :src="`${$VUE_APP_RESOURCES_URL}/images/red-packets.png`" class="image" />
<view class="text font-color-red">
<view>会员分享返</view>
<view class="money"><text class="label"></text>{{ priceName }}</view>
<view class="tip">下单即返佣金</view>
<view class="shareBut">立即分享</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "ShareRedPackets",
props: {
priceName: {
type: [String, Number],
default: ""
}
},
data: function() {
return {
state: false
};
},
mounted: function() {},
methods: {
goShare: function() {
this.$emit("changeFun", { action: "shareCode", value: false });
},
closeShare: function() {
this.state = true;
}
}
};
</script>

324
components/ShopLiveCard.vue

@ -0,0 +1,324 @@
<template>
<view class="sp-live-card" :style="{ width: wh + 'rpx' }">
<view class="live-content" @tap="goRoom" :style="{ width: wh + 'rpx' }">
<image class="item-cover" :src="detail.shareImge" mode="aspectFill"></image>
<view class="item-status">
<image class="status-img" :src="liveStatus[detail.liveStatus].img" mode=""></image>
<text class="status-text">{{ liveStatus[detail.liveStatus].title }}</text>
</view>
<view class="item-title" :style="{ width: wh + 'rpx' }">{{ detail.name }}</view>
</view>
<view class="live-bottom" :style="{ width: wh + 'rpx' }">
<view class="live-info">
<view class="info-box">
<view class="info-name">{{ detail.anchorName }}</view>
</view>
</view>
<slot name="liveGoods">
<view class="live-goods" v-if="detail.product.length">
<view class="live-goods__item" v-for="(goods, index) in detail.product" :key="goods.goodsId"
v-if="index < 3">
<image class="live-goods__img" :src="goods.coverImgeUrl" mode=""></image>
<view class="live-goods__price" v-if="index < 2">{{ goods.price }}</view>
<view class="live-goods__mark" v-else>
<text>{{ detail.product.length }}+</text>
</view>
</view>
</view>
</slot>
</view>
</view>
</template>
<script>
import {
dataFormatL
} from "@/utils";
let HAS_LIVE = false
// #ifdef MP-WEIXIN
HAS_LIVE = true
let livePlayer = null;
if (HAS_LIVE) {
// livePlayer = requirePlugin('live-player-plugin');
}
// #endif
let timer = null;
export default {
name: 'shopLiveCard',
components: {},
data() {
return {
liveStatus: {
'101': {
img: 'https://wx.yixiang.co/static/images/live.png',
title: '直播中'
},
'102': {
img: 'https://wx.yixiang.co/static/images/prevue.png',
title: '未开始'
},
'103': {
img: 'https://wx.yixiang.co/static/images/playback.png',
title: '已结束'
},
'104': {
img: 'https://wx.yixiang.co/static/images/104.png',
title: '禁播'
},
'105': {
img: 'https://wx.yixiang.co/static/images/105.png',
title: '暂停中'
},
'106': {
img: 'https://wx.yixiang.co/static/images/106.png',
title: '异常'
},
'107': {
img: 'https://wx.yixiang.co/static/images/past.png',
title: '已过期'
}
}
};
},
props: {
detail: {
type: Object,
default: null
},
wh: {
type: Number,
default: 345
}
},
computed: {},
created() {
this.getLiveStatus();
},
mounted() {
let that = this;
timer = setInterval(() => {
that.getLiveStatus();
}, 60000);
},
beforeDestroy() {
timer = null;
},
methods: {
goRoom() {
let that = this;
wx.navigateTo({
url: `plugin-private://wx2b03c6e691cd7370/pages/live-player-plugin?room_id=${that.detail.roomId}`
});
},
dateFormat(fmt, date) {
let ret;
const opt = {
"Y+": date.getFullYear().toString(), //
"m+": (date.getMonth() + 1).toString(), //
"d+": date.getDate().toString(), //
"H+": date.getHours().toString(), //
"M+": date.getMinutes().toString(), //
"S+": date.getSeconds().toString() //
//
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
};
};
return fmt;
},
// liveStatus
getLiveStatus() {
if (HAS_LIVE) {
let that = this;
let date = '';
if (that.detail.liveStatus == 102) {
date = this.dateFormat('mm-dd HH:MM', new Date(that.detail.startTime * 1000)).replace('-','/');
that.liveStatus['102'].title = '预告 ' + date;
}
// livePlayer
// .getLiveStatus({
// room_id: that.detail.roomId
// })
// .then(res => {
// // 101: , 102: , 103: , 104: , 105: , 106: 107
// that.detail.liveStatus = res.liveStatus;
// })
// .catch(err => {
// console.log('get live status', err);
// });
}
}
}
};
</script>
<style lang="scss">
.sp-live-card {
width: 344rpx;
box-shadow: 0px 0px 10rpx 4rpx rgba(199, 199, 199, 0.22);
border-radius: 20rpx;
height: 100%;
overflow: auto;
margin-bottom: 20rpx;
}
.live-content {
position: relative;
width: 344rpx;
height: 344rpx;
overflow: hidden;
.item-cover {
background-color: #eee;
width: 100%;
height: 100%;
border-radius: 20rpx 20rpx 0 0;
}
.item-status {
position: absolute;
top: 20rpx;
left: 10rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.4);
border-radius: 20rpx;
display: flex;
justify-content: center;
align-items: center;
.status-img {
width: 40rpx;
height: 40rpx;
}
.status-text {
font-size: 22rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 1);
padding: 0 10rpx;
}
}
.item-title {
width: 345rpx;
position: absolute;
bottom: 0;
line-height: 60rpx;
padding: 0 20rpx;
font-size: 26rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 1);
background: linear-gradient(transparent, rgba(#000, 0.5));
padding-right: 60rpx;
}
.like-img {
position: absolute;
bottom: 20rpx;
right: 10rpx;
width: 60rpx;
height: 130rpx;
}
}
.live-bottom {
background-color: #fff;
padding: 20rpx;
width: 345rpx;
.live-info {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.info-box {
display: flex;
align-items: center;
}
.info-avatar {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
margin-right: 10rpx;
background: #eee;
}
.info-name {
width: 150rpx;
font-size: 24rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(51, 51, 51, 1);
}
.views {
font-size: 20rpx;
font-family: PingFang SC;
font-weight: 400;
color: rgba(153, 153, 153, 1);
}
}
.live-goods {
display: flex;
align-items: center;
margin-top: 20rpx;
&__item {
position: relative;
width: 96rpx;
height: 96rpx;
border: 1rpx solid rgba(238, 238, 238, 1);
border-radius: 10rpx;
overflow: hidden;
margin-right: 8rpx;
&:nth-child(3n) {
margin-right: 0;
}
}
&__img {
background: #eee;
width: 100%;
height: 100%;
}
&__price {
position: absolute;
bottom: 0;
line-height: 40rpx;
width: 100%;
background: linear-gradient(transparent, rgba(#000, 0.5));
font-size: 20rpx;
color: #fff;
}
&__mark {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
background: rgba(#000, 0.3);
font-size: 24rpx;
font-family: PingFang SC;
font-weight: 500;
color: rgba(255, 255, 255, 1);
}
}
}
</style>

243
components/StorePoster.vue

@ -0,0 +1,243 @@
<template>
<view v-if="posterImageStatus" class="poster-first">
<div class="posterCanvasWarp">
<canvas class="posterCanvas" canvas-id="myCanvas"></canvas>
</div>
<!-- <view class="poster-pop" v-show="!canvasStatus">
<image
:src="`${$VUE_APP_RESOURCES_URL}/images/poster-close.png`"
class="close"
@click="posterImageClose"
/>
<view class="canvas" ref="poster">
<image class="image" :src="posterData.image" alt="商品图片" />
<view class="text black">
<text v-text="posterData.title"></text>
</view>
<view class="text rad">
<text v-text="'¥' + posterData.price"></text>
</view>
<view class="code">
<view class="code-img">
<image :src="posterData.code" show-menu-by-longpress mode="widthFix" alt="二维码" />
</view>
<view class="code-text">
<text>长按识别二维码 立即购买</text>
</view>
</view>
</view>
<view class="save-poster" @click="savePosterPath">生成图片</view>
</view>-->
<view class="poster-pop" v-show="canvasStatus">
<img :src="`${$VUE_APP_RESOURCES_URL}/images/poster-close.png`" class="close" @click="posterImageClose" mode="widthFix" />
<image :src="posterImage" alt="tp" class="poster-image" show-menu-by-longpress mode="widthFix" />
<view class="save-poster" @click="saveImg">保存海报</view>
</view>
<view class="mask"></view>
</view>
</template>
<script>
// import html2canvas from "html2canvas";
import { PosterCanvas } from '@/utils'
import { getProductPoster } from '@/api/store'
export default {
name: 'StorePoster',
props: {
posterImageStatus: Boolean,
posterData: Object,
goodId: String,
},
data: function() {
return {
canvasStatus: false,
posterImage: '',
}
},
watch: {
posterImageStatus: function() {
var that = this
if (that.posterImageStatus === true) {
that.$nextTick(function() {
that.savePosterPath()
})
}
},
},
mounted: function() {},
methods: {
posterImageClose: function() {
this.posterImageStatus = false
this.canvasStatus = false
this.$emit('setPosterImageStatus')
},
saveImg: function() {
this.downloadFile(this.posterImage)
},
downloadFile(url) {
uni.downloadFile({
url,
fail: function(res) {
console.log(res)
uni.showModal({
title: '提示',
content: '保存失败',
})
},
success: function(res) {
console.log(res)
uni.showModal({
title: '提示',
content: '保存成功',
})
},
})
},
savePosterPath: function() {
const that = this
uni.showLoading({
title: '海报生成中',
mask: true,
})
getProductPoster(this.goodId, {
from: this.$deviceType == 'weixin' || this.$deviceType == 'weixinh5' ? 'uniappH5' : this.$deviceType,
})
.then(res => {
this.canvasStatus = true
this.posterImage = res.data
})
.finally(() => {
uni.hideLoading()
})
// return;
// //
// that.posterImage = "";
// uni.showLoading({ title: "", mask: true });
// console.log(this);
// var prodId = that.$yrouter.currentRoute.query.id;
// uni.downloadFile({
// url:
// this.$VUE_APP_API_URL +
// "/shareImg/" +
// prodId +
// "?shareImgName=" +
// this.posterData.code,
// fail: function(res) {},
// success: function(res) {
// that.canvasStatus = true;
// that.posterImage = res.tempFilePath;
// uni.hideLoading();
// }
// });
},
},
}
</script>
<style scoped lang="less" lang="less">
.poster-first {
overscroll-behavior: contain;
}
.poster-pop {
width: 4.5 * 100rpx;
height: 8 * 100rpx;
position: fixed;
left: 50%;
transform: translateX(-50%);
z-index: 99;
top: 50%;
margin-top: -4.6 * 100rpx;
}
.poster-pop .canvas {
background-color: #ffffff;
height: 8 * 100rpx;
}
.poster-pop .poster-image {
width: 100%;
height: auto;
}
.poster-pop .canvas .image {
width: 4.5 * 100rpx;
height: 4.5 * 100rpx;
display: block;
}
.poster-pop .canvas .text {
text-align: center;
color: #000000;
margin-top: 0.32 * 100rpx;
}
.poster-pop .canvas .text.black {
height: 0.68 * 100rpx;
}
.poster-pop .canvas .text.rad {
color: #ff0000;
}
.poster-pop .canvas .code {
height: 1.4 * 100rpx;
display: flex;
}
.poster-pop .canvas .code .code-img {
width: 33%;
padding: 0.06 * 100rpx;
}
.poster-pop .canvas .code .code-img image {
width: 100%;
}
.poster-pop .canvas .code .code-text {
width: 60%;
font-size: 0.12 * 100rpx;
line-height: 1.64 * 100rpx;
}
.poster-pop .close {
width: 0.46 * 100rpx;
height: 0.75 * 100rpx;
position: fixed;
right: 0;
top: -0.73 * 100rpx;
display: block;
}
.poster-pop .save-poster {
background-color: #df2d0a;
font-size: 0.22 * 100rpx;
color: #fff;
text-align: center;
height: 0.76 * 100rpx;
line-height: 0.76 * 100rpx;
width: 100%;
margin-top: -0.1 * 100rpx;
border-radius: 0 0 10rpx 10rpx;
}
.poster-pop .keep {
color: #fff;
text-align: center;
font-size: 0.25 * 100rpx;
margin-top: 0.1 * 100rpx;
}
.mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
z-index: 9;
}
</style>

155
components/SwitchWindow.vue

@ -0,0 +1,155 @@
<template>
<view>
<view class="switchWindow" :class="switchActive === true ? 'on' : ''">
<view class="pictrue">
</view>
<!-- 是否选择切换到小程序账户 -->
<view class="info">
<text>是否选择切换到</text>
<text class="font-color" v-if="login_type === 'h5'">微信账号</text>
<text class="font-color" v-else>手机用户</text>
<text></text>
</view>
<view class="switchBnt" @click="switchH5">
<text>切换</text>
</view>
<view class="switchBnt cancelBnt" @click="switchClose">
<text>取消</text>
</view>
</view>
<view class="mask" @touchmove.prevent v-show="switchActive === true" @click="switchClose"></view>
</view>
</template>
<style lang="less">
.switchWindow {
width: 5.6*100rpx;
border-radius: 0.2*100rpx;
-webkit-border-radius: 0.2*100rpx;
background-color: #fff;
position: fixed;
top: 50%;
left: 50%;
margin-left: -2.8*100rpx;
margin-top: -3*100rpx;
z-index: 99;
padding: 0.5*100rpx 0.3*100rpx 0.4*100rpx 0.3*100rpx;
text-align: center;
box-sizing: border-box;
-webkit-box-sizing: border-box;
transition: all 0.3s ease-in-out 0s;
-webkit-transition: all 0.3s ease-in-out 0s;
-moz-transition: all 0.3s ease-in-out 0s;
-o-transition: all 0.3s ease-in-out 0s;
opacity: 0;
transform: scale(0);
}
.switchWindow.on {
opacity: 1;
transform: scale(1);
-webkit-transform: scale(1);
-ms-transform: scale(1);
-moz-transform: scale(1);
-o-transform: scale(1);
}
.switchWindow .pictrue {
width: 2.36*100rpx;
height: 2.36*100rpx;
margin: 0 auto;
}
.switchWindow .pictrue image {
width: 100%;
height: 100%;
display: block;
}
.switchWindow .info {
font-size: 0.32*100rpx;
color: #282828;
margin-top: 0.44*100rpx;
font-weight: bold;
}
.switchWindow .switchBnt {
font-size: 0.32*100rpx;
color: #fff;
width: 3.6*100rpx;
height: 0.82*100rpx;
border-radius: 0.41*100rpx;
-webkit-border-radius: 0.41*100rpx;
margin: 0.57*100rpx auto 0 auto;
line-height: 0.82*100rpx;
background-image: linear-gradient(to right, #f67a38 0%, #f11b09 100%);
background-image: -webkit-linear-gradient(to right, #f67a38 0%, #f11b09 100%);
background-image: -moz-linear-gradient(to right, #f67a38 0%, #f11b09 100%);
}
.switchWindow .switchBnt.cancelBnt {
background-color: #fff;
color: #999;
background-image: none;
margin-top: 0.1*100rpx;
}
</style>
<script>
import { switchH5Login } from "@/api/user";
import cookie from "@/utils/store/cookie";
import store from "@//store";
import dayjs from "dayjs";
export default {
name: "SwitchWindow",
props: {
switchActive: {
type: Boolean,
default: false
},
login_type: {
type: String,
default: ""
}
},
data: function() {
return {};
},
mounted: function() {},
methods: {
switchClose: function() {
this.$emit("changeswitch", false); //$emit():
},
switchH5() {
let that = this;
uni.showLoading({
title: "正在切换中"
});
if (that.login_type === "h5") {
cookie.set("loginType", "wechat", 60);
uni.hideLoading();
this.$store.commit("logout");
this.$emit("changeswitch", false);
location.reload();
} else {
switchH5Login()
.then(({ data }) => {
uni.hideLoading();
const expires_time = dayjs(data.expires_time);
store.commit("login", data.token, expires_time);
this.$emit("changeswitch", false);
location.reload();
})
.catch(err => {
uni.hideLoading();
uni.showToast({
title: err.msg || err.response.data.msg|| err.response.data.message,
icon: "none",
duration: 2000
});
});
}
}
}
};
</script>

52
components/UserEvaluation.vue

@ -0,0 +1,52 @@
<template>
<view class="evaluateWtapper" v-if="reply&&reply.length>0">
<view v-for="(item, evaluateWtapperIndex) in reply" :key="evaluateWtapperIndex">
<view class="evaluateItem" v-if="item">
<view class="pic-text acea-row row-middle">
<view class="pictrue">
<image :src="item.avatar" class="image" />
</view>
<view class="acea-row row-middle">
<view class="name line1">{{ item.nickname }}</view>
<view class="start" :class="'star' + item.star"></view>
</view>
</view>
<view class="time">{{ item.createTime }} {{ item.sku||'' }}</view>
<view class="evaluate-infor">{{ item.comment }}</view>
<view class="imgList acea-row">
<view class="pictrue" v-for="(itemn, eq) in item.picturesArr" :key="eq">
<image :src="itemn" class="image" />
</view>
</view>
<view class="reply" v-if="item.merchantReplyContent">
<span class="font-color-red">yshop店员</span>
{{item.merchantReplyContent}}
</view>
</view>
</view>
</view>
</template>
<script>
import {
dataFormat
} from "@/utils";
export default {
name: "UserEvaluation",
props: {
reply: {
type: Array,
default: () => []
}
},
data: function () {
return {};
},
mounted: function () {
console.log(this)
},
methods: {
dataFormat
}
};
</script>

127
components/WriteOff.vue

@ -0,0 +1,127 @@
<template>
<view v-show="iShidden === false">
<view class="WriteOff">
<view class="num acea-row row-center-wrapper">
{{ orderInfo.orderId }}
</view>
<view class="tip">确定要核销此订单吗</view>
<view class="sure" @click="confirm">确定核销</view>
<view class="sure cancel" @click="cancel">取消</view>
</view>
<view class="mask" @touchmove.prevent></view>
</view>
</template>
<style scoped lang="less">
.WriteOff {
width: 5.6*100rpx;
height: 5*100rpx;
background-color: #fff;
border-radius: 0.2*100rpx;
position: fixed;
top: 50%;
left: 50%;
margin-top: -4*100rpx;
margin-left: -2.8*100rpx;
padding-top: 0.55*100rpx;
z-index: 99999;
}
.WriteOff .pictrue {
width: 3.4*100rpx;
height: 3.4*100rpx;
margin: 0 auto;
}
.WriteOff .pictrue image{
width: 100%;
height: 100%;
display: block;
border-radius: 0.1*100rpx;
}
.WriteOff .num {
font-size: 0.3*100rpx;
color: #666;
margin: 0.28*100rpx 0 0.3*100rpx 0;
}
.WriteOff .num .see {
font-size: 0.16*100rpx;
color: #fff;
border-radius: 0.04*100rpx;
background-color: #c68937;
padding-left: 0.05*100rpx;
margin-left: 0.12*100rpx;
}
.WriteOff .num .see .iconfont {
font-size: 0.15*100rpx;
}
.WriteOff .tip {
font-size: 0.36*100rpx;
color: #282828;
text-align: center;
border-top: 1px dashed #ccc;
padding-top: 0.4*100rpx;
position: relative;
}
.WriteOff .tip:after {
content: "";
position: absolute;
width: 0.25*100rpx;
height: 0.25*100rpx;
border-radius: 50%;
background-color: #7f7f7f;
right: -0.125*100rpx;
top: -0.125*100rpx;
}
.WriteOff .tip:before {
content: "";
position: absolute;
width: 0.25*100rpx;
height: 0.25*100rpx;
border-radius: 50%;
background-color: #7f7f7f;
left: -0.125*100rpx;
top: -0.125*100rpx;
}
.WriteOff .sure {
font-size: 0.32*100rpx;
color: #fff;
text-align: center;
line-height: 0.82*100rpx;
height: 0.82*100rpx;
width: 4.6*100rpx;
border-radius: 0.41*100rpx;
margin: 0.4*100rpx auto 0 auto;
background-image: linear-gradient(to right, #f67a38 0%, #f11b09 100%);
background-image: -webkit-linear-gradient(to right, #f67a38 0%, #f11b09 100%);
background-image: -moz-linear-gradient(to right, #f67a38 0%, #f11b09 100%);
}
.WriteOff .sure.cancel {
background-image: none;
color: #999;
margin-top: 0.1*100rpx;
}
</style>
<script>
export default {
name: "WriteOff",
props: {
iShidden: {
type: Boolean,
default: true
},
orderInfo: {
type: Object
}
},
data: function() {
return {};
},
mounted: function() {},
methods: {
cancel: function() {
this.$emit("cancel", true);
},
confirm: function() {
this.$emit("confirm", true);
}
}
};
</script>

10
components/WxEmojiView.vue

@ -0,0 +1,10 @@
<template name="WxEmojiView">
<view class="WxEmojiView wxParse-inline" :style="item.styleStr">
<block v-for="(item, index) in item.textArray" :key="index">
<block :class="item.text == '\\n' ? 'wxParse-hide':''" v-if="item.node == 'text'">{{item.text}}</block>
<block v-else-if="item.node == 'element'">
<image class="wxEmoji" :src="item.baseSrc + '' + item.text"></image>
</block>
</block>
</view>
</template>

3
components/WxParseBr.vue

@ -0,0 +1,3 @@
<template name="WxParseBr">
<text>\n</text>
</template>

156
components/api-set-tabbar.nvue

@ -0,0 +1,156 @@
<template>
<view class="uni-padding-wrap">
<page-head :title="title"></page-head>
<button class="button" @click="setTabBarBadge">{{ !hasSetTabBarBadge ? '设置tab徽标' : '移除tab徽标' }}</button>
<button class="button" @click="showTabBarRedDot">{{ !hasShownTabBarRedDot ? '显示红点' : '移除红点'}}</button>
<button class="button" @click="customStyle">{{ !hasCustomedStyle ? '自定义Tab样式' : '移除自定义样式'}}</button>
<button class="button" @click="customItem">{{ !hasCustomedItem ? '自定义Tab信息' : '移除自定义信息' }}</button>
<button class="button" @click="hideTabBar">{{ !hasHiddenTabBar ? '隐藏TabBar' : '显示TabBar' }}</button>
<view class="btn-area">
<button class="button" type="primary" @click="navigateBack">返回上一级</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'tababr',
hasSetTabBarBadge: false,
hasShownTabBarRedDot: false,
hasCustomedStyle: false,
hasCustomedItem: false,
hasHiddenTabBar: false
}
},
destroyed() {
if (this.hasSetTabBarBadge) {
uni.removeTabBarBadge({
index: 1
})
}
if (this.hasShownTabBarRedDot) {
uni.hideTabBarRedDot({
index: 1
})
}
if (this.hasHiddenTabBar) {
uni.showTabBar()
}
if (this.hasCustomedStyle) {
uni.setTabBarStyle({
color: '#7A7E83',
selectedColor: '#007AFF',
backgroundColor: '#F8F8F8',
borderStyle: 'black'
})
}
if (this.hasCustomedItem) {
let tabBarOptions = {
index: 1,
text: '接口',
iconPath: '/static/api.png',
selectedIconPath: '/static/apiHL.png'
}
uni.setTabBarItem(tabBarOptions)
}
},
methods: {
navigateBack() {
this.$emit('unmount')
},
setTabBarBadge() {
if(this.hasShownTabBarRedDot){
uni.hideTabBarRedDot({
index: 1
})
this.hasShownTabBarRedDot = !this.hasShownTabBarRedDot
}
if (!this.hasSetTabBarBadge) {
uni.setTabBarBadge({
index: 1,
text: '1'
})
} else {
uni.removeTabBarBadge({
index: 1
})
}
this.hasSetTabBarBadge = !this.hasSetTabBarBadge
},
showTabBarRedDot() {
if(this.hasSetTabBarBadge) {
uni.removeTabBarBadge({
index: 1
})
this.hasSetTabBarBadge = !this.hasSetTabBarBadge
}
if (!this.hasShownTabBarRedDot) {
uni.showTabBarRedDot({
index: 1
})
} else {
uni.hideTabBarRedDot({
index: 1
})
}
this.hasShownTabBarRedDot = !this.hasShownTabBarRedDot
},
hideTabBar() {
if (!this.hasHiddenTabBar) {
uni.hideTabBar()
} else {
uni.showTabBar()
}
this.hasHiddenTabBar = !this.hasHiddenTabBar
},
customStyle() {
if (this.hasCustomedStyle) {
uni.setTabBarStyle({
color: '#7A7E83',
selectedColor: '#007AFF',
backgroundColor: '#F8F8F8',
borderStyle: 'black'
})
} else {
uni.setTabBarStyle({
color: '#FFF',
selectedColor: '#007AFF',
backgroundColor: '#000000',
borderStyle: 'black'
})
}
this.hasCustomedStyle = !this.hasCustomedStyle
},
customItem() {
let tabBarOptions = {
index: 1,
text: '接口',
iconPath: '/static/api.png',
selectedIconPath: '/static/apiHL.png'
}
if (this.hasCustomedItem) {
uni.setTabBarItem(tabBarOptions)
} else {
tabBarOptions.text = 'API'
uni.setTabBarItem(tabBarOptions)
}
this.hasCustomedItem = !this.hasCustomedItem
}
}
}
</script>
<style>
.button {
margin-top: 30rpx;
margin-left: 0;
margin-right: 0;
}
.btn-area {
padding-top: 30rpx;
}
</style>

184
components/colorui/animation.css

@ -0,0 +1,184 @@
/*
Animation 微动画
基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28
*/
/* css 滤镜 控制黑白底色gif的 */
.gif-black{
mix-blend-mode: screen;
}
.gif-white{
mix-blend-mode: multiply;
}
/* Animation css */
[class*=animation-] {
animation-duration: .5s;
animation-timing-function: ease-out;
animation-fill-mode: both
}
.animation-fade {
animation-name: fade;
animation-duration: .8s;
animation-timing-function: linear
}
.animation-scale-up {
animation-name: scale-up
}
.animation-scale-down {
animation-name: scale-down
}
.animation-slide-top {
animation-name: slide-top
}
.animation-slide-bottom {
animation-name: slide-bottom
}
.animation-slide-left {
animation-name: slide-left
}
.animation-slide-right {
animation-name: slide-right
}
.animation-shake {
animation-name: shake
}
.animation-reverse {
animation-direction: reverse
}
@keyframes fade {
0% {
opacity: 0
}
100% {
opacity: 1
}
}
@keyframes scale-up {
0% {
opacity: 0;
transform: scale(.2)
}
100% {
opacity: 1;
transform: scale(1)
}
}
@keyframes scale-down {
0% {
opacity: 0;
transform: scale(1.8)
}
100% {
opacity: 1;
transform: scale(1)
}
}
@keyframes slide-top {
0% {
opacity: 0;
transform: translateY(-100%)
}
100% {
opacity: 1;
transform: translateY(0)
}
}
@keyframes slide-bottom {
0% {
opacity: 0;
transform: translateY(100%)
}
100% {
opacity: 1;
transform: translateY(0)
}
}
@keyframes shake {
0%,
100% {
transform: translateX(0)
}
10% {
transform: translateX(-9px)
}
20% {
transform: translateX(8px)
}
30% {
transform: translateX(-7px)
}
40% {
transform: translateX(6px)
}
50% {
transform: translateX(-5px)
}
60% {
transform: translateX(4px)
}
70% {
transform: translateX(-3px)
}
80% {
transform: translateX(2px)
}
90% {
transform: translateX(-1px)
}
}
@keyframes slide-left {
0% {
opacity: 0;
transform: translateX(-100%)
}
100% {
opacity: 1;
transform: translateX(0)
}
}
@keyframes slide-right {
0% {
opacity: 0;
transform: translateX(100%)
}
100% {
opacity: 1;
transform: translateX(0)
}
}

70
components/colorui/components/cu-custom.vue

@ -0,0 +1,70 @@
<template>
<view class="cu-custom" :style="[{height:CustomBar + 'px'}]">
<view class="cu-bar fixed" :style="style" :class="[bgImage!=''?'none-bg text-white bg-img':'',bgColor]">
<view class="action" @tap="BackPage" v-if="isBack">
<text class="cuIcon-back"></text>
<slot name="backText"></slot>
</view>
<view class="content" :style="[{top:StatusBar + 'px'}]">
<slot name="content"></slot>
</view>
<slot name="right"></slot>
</view>
</view>
</template>
<script>
export default {
data() {
return {
StatusBar: this.StatusBar,
CustomBar: this.CustomBar
};
},
name: 'cu-custom',
computed: {
style() {
var StatusBar = this.StatusBar;
var CustomBar = this.CustomBar;
var bgImage = this.bgImage;
var style = `height:${CustomBar}px;padding-top:${StatusBar}px;background:${this.bgColor} ;`;
if (this.bgImage) {
style = `${style}background-image:url(${bgImage});`;
}
return style
}
},
props: {
bgColor: {
type: String,
default: ''
},
isBack: {
type: [Boolean, String],
default: false
},
bgImage: {
type: String,
default: ''
},
},
methods: {
BackPage() {
uni.navigateBack({
delta: 1
});
}
}
}
</script>
<style>
.fixed{
position: fixed;
top:0;
left:0;
right:0;
z-index: 99;
}
</style>

1226
components/colorui/icon.css

File diff suppressed because one or more lines are too long

4040
components/colorui/main.css

File diff suppressed because it is too large Load Diff

66
components/product.vue

@ -0,0 +1,66 @@
<template>
<view class="product">
<image class="product-image" :src="image ? image : 'https://via.placeholder.com/150x200'"></image>
<view class="product-title">{{title}}</view>
<view class="product-price">
<text class="product-price-favour">{{originalPrice}}</text>
<text class="product-price-original">{{favourPrice}}</text>
<text class="product-tip">{{tip}}</text>
</view>
</view>
</template>
<script>
export default {
name: 'product',
props: ['image', 'title', 'originalPrice', 'favourPrice', 'tip']
}
</script>
<style>
.product {
padding: 10rpx 20rpx;
display: flex;
flex-direction: column;
}
.product-image {
height: 330rpx;
width: 330rpx;
}
.product-title {
width: 300rpx;
font-size: 32rpx;
word-break: break-all;
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.product-price {
font-size: 28rpx;
position: relative;
}
.product-price-original {
color: #E80080;
}
.product-price-favour {
color: #888888;
text-decoration: line-through;
margin-left: 10rpx;
}
.product-tip {
position: absolute;
right: 10rpx;
background-color: #FF3333;
color: #FFFFFF;
padding: 0 10rpx;
border-radius: 5rpx;
}
</style>

75
components/region-picker/readme.md

@ -0,0 +1,75 @@
#### 特性说明
1. 行政区用的是2018还是2019年的全国标准行政区划, 也可以定义远端的 json 地址, 格式看使用文档
2. 返回的 detail.value 和官方的 mode=region 比缺少了 post_code, 主要是我的数据库中没有邮编, 剩下的 code/value 格式和官方保持一致
3. 传参支持官方的 value, disabled, 暂不支持 custom-item
4. 事件支持 change / cancel
5. value 的传值支持
- 行政区号数组 [省,市,区]
- 行政区号字符串 "省,市,区" / "区"
- 暂不支持城市名设置value, 有需要可以自己改造, 很简单的代码
#### 使用方式
```javascript
import regionPicker from "@/components/region-picker/region-picker.vue"
```
```javascript
components: {
regionPicker
},
```
```html
<picker mode="region"
```
替换为
```html
<region-picker
```
即可
```html
<region-picker @change="region_change" :value="350104">
<view class="picker">请选择地区</view>
</region-picker>
```
#### Value 传值说明
```html
<!-- 单传区级行政区号 -->
<region-picker @change="region_change" value="350104">
<!-- 传省市区级行政区号(字符串) -->
<region-picker @change="region_change" value="350000,350100,350104">
<!-- 传省市区级行政区号(数组) -->
<region-picker @change="region_change" :value="[350000,350100,350104]">
<!-- 字符串/整形均可, 没具体测试, 如果报错, 就试着改一下类型 -->
```
#### 使用远端 json
```html
<region-picker jsonPath="远端json文件或者其他返回json格式的数据源">
```
返回json数据应符合格式如下
```json
[{
name: '福建省',
code: '350000',
children: [{
name: '福州市',
code: '350100',
children: [{
name: '仓山区',
code: '350104',
// id: xxx,
// post_code: xxx
// 其他自定义的数据键值对: 值
// change 事件的 detail.data 属性会返回所选区域的完整的对象
},
{
//...第二个区域
}]
},
{
//...第二个城市
}]
},
{
//...第二个省份
}]
```

4
components/region-picker/region-picker.js

File diff suppressed because one or more lines are too long

163
components/region-picker/region-picker.vue

@ -0,0 +1,163 @@
<template name="regionPicker">
<view>
<picker mode="multiSelector" :range="range" :value="dataValue" :disabled="dataDisabled" @change="region_change" @columnchange="region_change_col" @cancel="region_cancel">
<slot></slot>
</picker>
</view>
</template>
<script>
import zones_data from './region-picker.js';
export default {
name: "regionPicker",
props: {
value:{ type: [Array,String,Number], default: [0,0,0] },
disabled:{ type: Boolean, default: false },
//like https://api.591tuangou.com/cache/region-picker.php
jsonPath:{ type:String, default: null },
jsonData:{ type:Array, default: null },
},
data(){
return {
dataValue:[],
dataDisabled:false,
range:[],
zones_tree:[],
}
},
mounted:function(e){
if(this.jsonData){
this.zones_tree=this.jsonData;
this.dataDisabled=this.disabled;
this.value_format();
this.range_set();
}else if(this.jsonPath){
uni.request({
url:this.jsonPath,
success:res=>{
this.zones_tree=res.data;
this.dataDisabled=this.disabled;
this.value_format();
this.range_set();
}
})
}else{
this.zones_tree=zones_data.zones_tree,
this.dataDisabled=this.disabled;
this.value_format();
this.range_set();
}
},
watch:{
jsonData:function (nv,ov){
this.zones_tree=nv;
this.dataDisabled=this.disabled;
this.value_format();
this.range_set();
},
value:function (nv,ov){
if(JSON.stringify(nv)!=JSON.stringify(ov)){
if(typeof(nv)!='object' && typeof(ov)=='object' && ov[2]+''!=nv+''){
this.value=nv;
this.value_format();
this.range_set();
this.region_change({detail:{value:this.dataValue}})
}
}
}
},
methods: {
value_format(){
var value=this.value;
if(typeof(value)=='number'){
value=value+'';
}
if(typeof(value)=='string' && value.indexOf(',')>0){
value=value.split(',');
}
var sk=0,ck=0,zk=0;
if(typeof(value)=='string'){
this.zones_tree.forEach((sv,si)=>{
sv.children.forEach((cv,ci)=>{
cv.children.forEach((zv,zi)=>{
if(zv.code==value){
sk=si;
ck=ci;
zk=zi;
}
})
})
})
this.dataValue=[sk,ck,zk];
}else if(typeof(value[0])=='string' || value[0]>999){
this.zones_tree.forEach((sv,si)=>{
if(sv.code==value[0]){
sk=si;
sv.children.forEach((cv,ci)=>{
if(cv.code==value[1]){
ck=ci;
cv.children.forEach((zv,zi)=>{
if(zv.code==value[2]){
zk=zi;
}
})
}
})
}
})
this.dataValue=[sk,ck,zk];
}else{
this.dataValue=value;
}
},
range_set() {
var zones_ary=[[],[],[]];
this.zones_tree.forEach((sv,si)=>{
zones_ary[0].push(sv.name);
if(si==this.dataValue[0]){
sv.children.forEach((cv,ci)=>{
zones_ary[1].push(cv.name);
if(ci==this.dataValue[1]){
cv.children.forEach((zv,zi)=>{
zones_ary[2].push(zv.name);
})
}
})
}
})
this.range=zones_ary;
},
region_change(e){
var v=e.detail.value;
var value=[],code=[]
var sv=this.zones_tree[v[0]]
value.push(sv.name)
code.push(sv.code)
var cv=sv.children[v[1]];
value.push(cv.name)
code.push(cv.code)
var zv=cv.children[v[2]];
value.push(zv.name)
code.push(zv.code)
e.detail={code:code,value:value,data:zv}
this.$emit('change',e)
},
region_change_col(e){
if (e.detail.column === 0) {
this.dataValue[1] = 0;
this.dataValue[2] = 0;
}
if (e.detail.column === 1) {
this.dataValue[2] = 0;
}
this.dataValue[e.detail.column]=e.detail.value
this.range_set();
this.$emit('columnchange',e)
},
region_cancel(e){
this.$emit('cancel',e)
},
}
}
</script>
<style>
</style>

286
components/select-tree/select-tree.vue

@ -0,0 +1,286 @@
<template>
<view id="section_ul" class="selectTrees">
<!-- 一级分支 -->
<view class="lv1list" v-for="(item, index) in selectList" :key="index">
<view class="tree-one">
<!-- 单选框组件 -->
<checkbox-group v-if="showCheck"
style="position: absolute;height: 80rpx;line-height: 80rpx; left:20rpx;z-index: 1;">
<checkbox :checked="item.checked" @click="_chooseAll(item,index)" />
</checkbox-group>
<!-- 名字和iconfont -->
<label
style="height:80rpx;display: flex;align-items: center;padding: 20rpx;position: relative;border-bottom: 1px solid #e4e4e4;background: #f3f3f3;"
@click="_showlv2(index)">
<view class="itemT">{{item.name}}</view>
<view class="deleteBtn" v-if="showDelete" @click.stop="deleteItem(item)">删除</view>
<i class="iconfont iconshang" v-if="item.show"
style="position: absolute;top: 18%;right: 2%;font-size: 48rpx;"></i>
<i class="iconfont iconxiala" v-else
style="position: absolute;top: 18%;right: 2%;font-size: 48rpx;"></i>
</label>
</view>
<!-- 二级分支 -->
<view v-if='item.show && item.childrenList '>
<view class="tree-two" v-for="(item2, index2) in item.childrenList" :key="index2"
style="display: flex;">
<view class="aui-list-item-inner flexIn">
<checkbox-group v-if="showCheck">
<checkbox v-if="!disableLv2Check" :checked="item2.checked"
@click="_chooseOne(index,index2)" />
<checkbox :checked="item2.checked" disabled="true" v-else />
</checkbox-group>
<label style="font-size: 28rpx;">{{item2.name}}</label>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "select-tree",
data() {
return {
finalList: [],
menuKey: 1,
selectList: this.value
};
},
props: {
// selectList,
value: {
type: Array,
default: function () {
return [
{
name: "水果",
checked: false,
show: true,
childrenList: [
{
checked: false,
name: "西瓜"
},
{
checked: false,
name: "桃子"
}
]
},
{
name: "工具",
checked: false,
show: false,
childrenList: [
{
checked: false,
name: "锄头"
},
{
checked: false,
name: "铲子"
}
]
}
];
}
},
showCheck: {
//
type: Boolean,
default: true
},
disableLv2Check: {
//
type: Boolean,
default: false
},
showDelete: {
//
type: Boolean,
default: false
}
},
mounted() {
// console.log(this.value)
// setTimeout(()=>{
// this.selectList = this.value
// })
// this.$forceUpdate()
},
methods: {
_showlv2(index) {
// console.log('showLv2............................', index)
//
if (this.selectList[index].show) {
this.$set(this.selectList[index], "show", false);
this.$forceUpdate()
this.$emit('input', this.selectList)
} else {
this.$set(this.selectList[index], "show", true);
this.$forceUpdate()
this.$emit('input', this.selectList)
}
},
_chooseAll(item, index) {
//
if (this.selectList[index].checked) {
//
this.$set(this.selectList[index], "checked", false);
this.selectList[index].childrenList.forEach(item => {
item.checked = false;
});
this.$emit('input', this.selectList)
} else {
this.$set(this.selectList[index], "checked", true);
this.selectList[index].childrenList.forEach(item => {
item.checked = true;
});
this.$emit('input', this.selectList)
}
this.$set(this.selectList[index], "show", true);
this.$emit('input', this.selectList)
this.$forceUpdate();
this._computedFinalList();
},
_chooseOne(i1, i2) {
if (this.selectList[i1].childrenList[i2].checked) {
//
this.$set(this.selectList[i1], "checked", true);
this.$set(this.selectList[i1].childrenList[i2], "checked", false);
if (
this.selectList[i1].childrenList.every(item => item.checked == false)
) {
//
this.$set(this.selectList[i1], "checked", false);
}
this.$forceUpdate();
this.$emit('input', this.selectList)
this._computedFinalList();
} else {
//
this.$set(this.selectList[i1], "checked", true);
this.$set(this.selectList[i1].childrenList[i2], "checked", true);
if (
this.selectList[i1].childrenList.every(item => item.checked == true)
) {
//
this.$set(this.selectList[i1], "checked", true);
}
this.$emit('input', this.selectList)
this.$forceUpdate();
this._computedFinalList();
}
},
_computedFinalList() {
//
this.finalList = [];
this.selectList.forEach(item=>{
if(item.checked){
this.finalList.push(JSON.parse(JSON.stringify(item))) //
}
})
this.finalList.forEach(item=>{
item.childrenList.forEach((item2,index2)=>{
if(!item2.checked){
item.childrenList.splice(index2,1)
}
})
})
this.$emit("choose", this.finalList);
},
chooseAll() {
//
this.selectList.forEach(item => {
this.$set(item, "checked", true);
item.childrenList.forEach(item2 => {
this.$set(item2, "checked", true);
});
});
this.$emit('input', this.selectList)
this.$forceUpdate();
this._computedFinalList();
},
cancelAll() {
//
this.selectList.forEach(item => {
this.$set(item, "checked", false);
item.childrenList.forEach(item2 => {
this.$set(item2, "checked", false);
});
});
this.$emit('input', this.selectList)
this.$forceUpdate();
this._computedFinalList();
},
deleteItem(item) {
//
this.$emit('input', this.selectList)
this.$emit("deleteItem", item);
}
},
watch: {
value(res) {
console.log(res)
this.selectList = res
this.$emit('input', this.selectList)
}
},
};
</script>
<style lang="scss" scoped>
* {
font-size: 32rpx;
}
/* #ifdef APP-PLUS*/
.selectTrees{
margin-bottom: 180rpx;
}
/* #endif */
.deleteBtn {
position: absolute;
right: 10%;
background: #f97979;
padding: 2rpx 16rpx;
color: white;
border-radius: 4rpx;
font-size: 28rpx;
}
.itemT {
margin-left: 60rpx;
font-size: 32rpx;
width: 65%;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
.tree-two {
padding: 20rpx 68rpx;
background: white;
border-bottom: 2rpx solid #e2e2e2;
font-size: 28rpx;
}
.flexIn {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
align-content: center;
flex-wrap: nowrap;
width: 100%;
}
</style>

40
components/sh-activity-goods.vue

@ -0,0 +1,40 @@
<template>
<view class="min-goods" @tap="jump('/pages/activity/GroupDetails/index', { id: detail.id })">
<view class="img-box">
<view class="tag" >{{ detail.people}}人团</view>
<image class="img" :src="detail.image" mode="widthFix"></image>
</view>
<view class="price-box">
<view class="y-f">
<text class="seckill-current">{{ detail.price }}</text>
<text class="original">销量{{ detail.sales }}{{detail.unitName}}</text>
</view>
</view>
<view class="title"><slot name="titleText"></slot></view>
</view>
</template>
<script>
export default {
components: {},
data() {
return {};
},
props: {
detail: Object
},
computed: {},
methods: {
//
jump(path, query) {
this.$yrouter.push({
path,
query
});
}
}
};
</script>
<style lang="scss">
</style>

217
components/sh-adv.vue

@ -0,0 +1,217 @@
<template>
<view class="adv-box mx20 mb10">
<!-- 模板1-->
<view class="x-f" v-if="detail.style == 1">
<image style="width: 710rpx; height: 220rpx" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
</view>
<!-- 模板2-->
<view class="type1 x-f" v-if="detail.style == 2">
<image class="type1-img" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"> </image>
<image class="type1-img" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill"> </image>
</view>
<!-- 模板3-->
<view class="type2 x-bc" v-if="detail.style == 3">
<image class="type2-img1" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"> </image>
<view class="y-f type2-box">
<image class="type2-img2" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill" style="border-bottom: 1rpx solid #f6f6f6"></image>
<image class="type2-img2" @tap="jump(detail.list[2])" :src="detail.list[2].image" mode="aspectFill"></image>
</view>
</view>
<!-- 模板4-->
<view class="type3 x-bc" v-if="detail.style == 4">
<view class="type3-box y-f">
<image class="type3-img1" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
<image class="type3-img1" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill"></image>
</view>
<image class="type3-img2" @tap="jump(detail.list[2])" :src="detail.list[2].image" mode="aspectFill"> </image>
</view>
<!-- 模板5-->
<view class="type4 y-f" v-if="detail.style == 5">
<view class="type4-box x-f">
<image class="type4-img1" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
<image class="type4-img1" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill"></image>
</view>
<image class="type4-img2" @tap="jump(detail.list[2])" :src="detail.list[2].image" mode="aspectFill"> </image>
</view>
<!-- 模板6-->
<view class="type5 y-f" v-if="detail.style == 6">
<image class="type5-img1" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"> </image>
<view class="type5-box x-bc">
<image class="type5-img2" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill" style="border-bottom: 1rpx solid #f6f6f6"></image>
<image class="type5-img2" @tap="jump(detail.list[2])" :src="detail.list[2].image" mode="aspectFill"></image>
</view>
</view>
<!-- 模板7-->
<view class="type6 y-f" v-if="detail.style == 7">
<view class="x-f type6-box1">
<image class="type6-img1" @tap="jump(detail.list[0])" :src="detail.list[0].image" mode="aspectFill"></image>
<image class="type6-img1" @tap="jump(detail.list[1])" :src="detail.list[1].image" mode="aspectFill"></image>
</view>
<view class="x-f type6-box2">
<image class="type6-img2" @tap="jump(detail.list[2])" :src="detail.list[2].image" mode="aspectFill"></image>
<image class="type6-img2" @tap="jump(detail.list[3])" :src="detail.list[3].image" mode="aspectFill"></image>
<image class="type6-img2" @tap="jump(detail.list[4])" :src="detail.list[4].image" mode="aspectFill"></image>
</view>
</view>
</view>
</template>
<script>
export default {
components: {},
data() {
return {}
},
props: {
detail: Object,
},
computed: {},
created() {},
mounted() {
console.log(this)
},
methods: {
//
jump(item) {
if (item.uniapp_url) {
this.$yrouter.push(item.uniapp_url)
}
},
},
}
</script>
<style lang="scss">
.adv-box {
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
image {
width: 100%;
}
.type1 {
.type1-img {
flex: 1;
height: 220rpx;
&:first-child {
border-right: 1rpx solid #f6f6f6;
}
}
}
.type2 {
.type2-img1 {
width: (710rpx/2);
height: 340rpx;
border-right: 1rpx solid #f6f6f6;
}
.type2-box {
flex: 1;
height: 340rpx;
width: (710rpx/2);
.type2-img2 {
height: (340rpx/2);
}
}
}
.type3 {
.type3-box {
width: (710rpx/2);
border-right: 1rpx solid #f6f6f6;
.type3-img1 {
flex: 1;
height: (340rpx/2);
&:first-child {
border-bottom: 1rpx solid #f6f6f6;
}
}
}
.type3-img2 {
flex: 1;
height: 340rpx;
width: (710rpx/2);
}
}
.type4 {
.type4-box {
border-bottom: 1rpx solid #f6f6f6;
.type4-img1 {
flex: 1;
height: (340rpx/2);
&:first-child {
border-right: 1rpx solid #f6f6f6;
}
}
}
.type4-img2 {
flex: 1;
height: (340rpx/2);
width: 710rpx;
}
}
.type5 {
.type5-img1 {
width: 710rpx;
height: (340rpx/2);
border-bottom: 1rpx solid #f6f6f6;
}
.type5-box {
flex: 1;
height: (340rpx/2);
width: 710rpx;
.type5-img2 {
height: (340rpx/2);
&:first-child {
border-right: 1rpx solid #f6f6f6;
}
}
}
}
.type6 {
.type6-box1 {
.type6-img1 {
width: (710rpx/2);
height: (340rpx/2);
&:first-child {
border-right: 1rpx solid #f6f6f6;
}
}
}
.type6-box2 {
border-top: 1rpx solid #f6f6f6;
.type6-img2 {
width: (710rpx/3);
height: (340rpx/2);
border-right: 1rpx solid #f6f6f6;
&:last-child {
border-right: 0;
}
}
}
}
image {
// background-color: #ccc;
}
}
</style>

197
components/sh-groupon.vue

@ -0,0 +1,197 @@
<template>
<!-- 今日必拼 -->
<view class="group-goods pa20 mx20 mb10">
<view class="title-box x-bc" @tap="jump('/pages/activity/GoodsGroup/index')">
<text class="title">超值拼团</text>
<view class="group-people x-f">
<text class="tip">更多</text>
<text class="cuIcon-right"></text>
</view>
</view>
<view class="goods-box swiper-box x-f">
<swiper class="carousel" circular @change="swiperChange" :autoplay="true" duration="2000">
<swiper-item v-for="(goods, index) in goodsList" :key="index" class="carousel-item">
<view class="goods-list-box x-f">
<block v-for="mgoods in goods" :key="mgoods.id">
<sh-activity-goods :detail="mgoods" class="goods-item">
<!-- <block slot="titleText">立减8.5</block> -->
</sh-activity-goods>
</block>
</view>
</swiper-item>
</swiper>
<view class="swiper-dots" v-if="goodsList.length > 1">
<text :class="swiperCurrent === index ? 'dot-active' : 'dot'" v-for="(dot, index) in goodsList.length"
:key="index"></text>
</view>
</view>
</view>
</template>
<script>
import shActivityGoods from './sh-activity-goods.vue';
export default {
name: 'shGroupon',
components: {
shActivityGoods
},
data() {
return {
goodsList: [],
swiperCurrent: 0
};
},
props: {
detail: Array
},
computed: {},
created() {},
watch: {
detail(next) {
this.goodsList = this.sortData(next, 4);
}
},
methods: {
swiperChange(e) {
this.swiperCurrent = e.detail.current;
},
//
sortData(oArr, length) {
let arr = [];
let minArr = [];
oArr.forEach(c => {
if (minArr.length === length) {
minArr = [];
}
if (minArr.length === 0) {
arr.push(minArr);
}
minArr.push(c);
});
return arr;
},
jump(path, query) {
this.$yrouter.push({
path,
query,
});
},
}
};
</script>
<style lang="scss">
.swiper-box,
.carousel {
width: 700rpx;
height: 240upx;
position: relative;
border-radius: 20rpx;
.carousel-item {
width: 100%;
height: 100%;
// padding: 0 28upx;
overflow: hidden;
}
.swiper-image {
width: 100%;
height: 100%;
// border-radius: 10upx;
background: #ccc;
}
}
.swiper-dots {
display: flex;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 0rpx;
z-index: 66;
.dot {
width: 45rpx;
height: 3rpx;
background: #eee;
border-radius: 50%;
margin-right: 10rpx;
}
.dot-active {
width: 45rpx;
height: 3rpx;
background: #a8700d;
border-radius: 50%;
margin-right: 10rpx;
}
}
// +
.group-goods {
background: #fff;
border-radius: 20rpx;
overflow: hidden;
.title-box {
padding-bottom: 20rpx;
.title {
font-size: 32rpx;
font-weight: bold;
}
.group-people {
.time-box {
font-size: 26rpx;
color: #edbf62;
.count-text-box {
width: 30rpx;
height: 34rpx;
background: #edbf62;
text-align: center;
line-height: 34rpx;
font-size: 24rpx;
border-radius: 6rpx;
color: rgba(#fff, 0.9);
margin: 0 8rpx;
}
}
.head-box {
.head-img {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background: #ccc;
}
}
.tip {
font-size: 28rpx;
padding-left: 30rpx;
color: #666;
}
.cuIcon-right {
font-size: 30rpx;
line-height: 28rpx;
color: #666;
}
}
}
.goods-box {
.goods-item {
margin-right: 22rpx;
&:nth-child(4n) {
margin-right: 0;
}
}
}
}
</style>

151
components/tki-tree/style.css

@ -0,0 +1,151 @@
.tki-tree-mask {
position: fixed;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
z-index: 9998;
background-color: rgba(0, 0, 0, 0.6);
opacity: 0;
transition: all 0.3s ease;
visibility: hidden;
}
.tki-tree-mask.show {
visibility: visible;
opacity: 1;
}
.tki-tree-cnt {
position: fixed;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
z-index: 9999;
top: 160rpx;
transition: all 0.3s ease;
transform: translateY(100%);
}
.tki-tree-cnt.show {
transform: translateY(0);
}
.tki-tree-bar {
background-color: #fff;
height: 72rpx;
padding-left: 20rpx;
padding-right: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
border-bottom-width: 1rpx !important;
border-bottom-style: solid;
border-bottom-color: #f5f5f5;
font-size: 32rpx;
color: #757575;
line-height: 1;
}
.tki-tree-bar-confirm {
color: #07bb07;
}
.tki-tree-view {
position: absolute;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
top: 72rpx;
background-color: #fff;
padding-top: 20rpx;
padding-right: 20rpx;
padding-bottom: 20rpx;
padding-left: 20rpx;
}
.tki-tree-view-sc {
height: 100%;
overflow: hidden;
}
.tki-tree-item {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 26rpx;
color: #757575;
line-height: 1;
height: 0;
opacity: 0;
transition: 0.2s;
position: relative;
overflow: hidden;
}
.tki-tree-item.show {
height: 80rpx;
opacity: 1;
}
.tki-tree-item.showchild:before {
transform: rotate(90deg);
}
.tki-tree-item.last:before {
opacity: 0;
}
.tki-tree-icon {
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
}
.tki-tree-label {
flex: 1;
display: flex;
align-items: center;
height: 100%;
line-height: 1.2;
}
.tki-tree-check {
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
.tki-tree-check-yes,
.tki-tree-check-no {
width: 20px;
height: 20px;
border-top-left-radius: 20%;
border-top-right-radius: 20%;
border-bottom-right-radius: 20%;
border-bottom-left-radius: 20%;
border-top-width: 1rpx;
border-left-width: 1rpx;
border-bottom-width: 1rpx;
border-right-width: 1rpx;
border-style: solid;
border-color: #07bb07;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
.tki-tree-check-yes-b {
width: 12px;
height: 12px;
border-top-left-radius: 20%;
border-top-right-radius: 20%;
border-bottom-right-radius: 20%;
border-bottom-left-radius: 20%;
background-color: #07bb07;
}
.tki-tree-check .radio {
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
border-bottom-left-radius: 50%;
}
.tki-tree-check .radio .tki-tree-check-yes-b {
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
border-bottom-left-radius: 50%;
}
.hover-c {
opacity: 0.6;
}

310
components/tki-tree/tki-tree.vue

@ -0,0 +1,310 @@
<template xlang="wxml">
<view class="tki-tree">
<view class="tki-tree-mask" :class="{'show':showTree}" @tap="_cancel"></view>
<view class="tki-tree-cnt" :class="{'show':showTree}">
<view class="tki-tree-bar">
<view class="tki-tree-bar-cancel" :style="{'color':cancelColor}" hover-class="hover-c" @tap="_cancel">取消</view>
<view class="tki-tree-bar-title" :style="{'color':titleColor}">{{title}}</view>
<view class="tki-tree-bar-confirm" :style="{'color':confirmColor}" hover-class="hover-c" @tap="_confirm">确定</view>
</view>
<view class="tki-tree-view">
<scroll-view class="tki-tree-view-sc" :scroll-y="true">
<block v-for="(item, index) in treeList" :key="index">
<view class="tki-tree-item" :style="[{
paddingLeft: item.rank*15 + 'px',
zIndex: item.rank*-1 +50
}]"
:class="{
border: border === true,
show: item.show,
last: item.lastRank,
showchild: item.showChild,
open: item.open,
}">
<view class="tki-tree-label" @tap.stop="_treeItemTap(item, index)">
<image class="tki-tree-icon" :src="item.lastRank ? lastIcon : item.showChild ? currentIcon : defaultIcon"></image>
{{item.name}}
</view>
<view class="tki-tree-check" @tap.stop="_treeItemSelect(item, index)" v-if="selectParent?true:item.lastRank">
<view class="tki-tree-check-yes" v-if="item.checked" :class="{'radio':!multiple}" :style="{'border-color':confirmColor}">
<view class="tki-tree-check-yes-b" :style="{'background-color':confirmColor}"></view>
</view>
<view class="tki-tree-check-no" v-else :class="{'radio':!multiple}" :style="{'border-color':confirmColor}"></view>
</view>
</view>
</block>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "tki-tree",
props: {
range: {
type: Array,
default: function() {
return []
}
},
idKey: {
type: String,
default: 'id'
},
rangeKey: {
type: String,
default: 'label'
},
title: {
type: String,
default: ''
},
multiple: { //
type: Boolean,
default: false
// default: true
},
selectParent: { //
type: Boolean,
default: false
},
foldAll: { //
type: Boolean,
default: false
},
confirmColor: { //
type: String,
default: '' // #07bb07
},
cancelColor: { //
type: String,
default: '' // #757575
},
titleColor: { //
type: String,
default: '' // #757575
},
currentIcon: { // ic
type: String,
default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MEQ0QTM0MzQ1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MEQ0QTM0MzU1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowRDRBMzQzMjVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowRDRBMzQzMzVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PidwepsAAAK0SURBVHja7JxbTsJAFIYHww7ciStgCeoGvGxAiOsgURegoL5720AXYLiIr0aJviq3Zx3PhIEnKG3ndtr+f3KixrSUj/ZjzjClIqUUiFm2gAAQAREQEUAEREAERAQQAREQAREBREAEREBEEqa67h9RFDWllDv0awWYlqlQHmu1WjMRRMoV1QFttA12y3xRtdNczq8EsE4/f8FumX2q77ROvNXk8UGMEKdUz6tYJHljaZAbuyUH+UR1to5BEohTuqwPCeS4pAA/qY6o/kyHOAMCeRK3owJnj+rH1jjxhqpVsstaebCz6TmnHWyXyY+xHjSBWBY/bvSgadtXBj9u9KCN3rnIfkzkQVsTEEX0Y2IP2oKo/HhMICcFAThUcwVZNGU6FdbX/XURzkbVF4+ybGhjPrFdgP66QdXNurGtSdk6Xdb9nAJ8oDo3OQlsQZzkdPw41ONBo6vI5scDefRjZg+6gpg3Pxp50CXEvPjR2IOuIXL3oxUPuobI3Y9WPOgDIlc/WvOgL4iL/vqFCcD7LH0xB4hj7cfQ/fWH9qCT+FhG0tN+DBk1PzjOM0SVllixcsBT1AvYc/kAPhc0hRg/3uvxoCgKRN9+dOrBUBB9+9GpB0NC9OVH5x4MDdG1H714kANEV3705kEOEBf9dcPi/lQnsuvLg1wgSu3Ha0v7Uh4MMgUXeuG71H407a+VBy9CPQkOdw+MtB+nGbd/D+FBbhBNxo9SjwcngJjNj0E9yBFiFj8G9SBXiGn8GNyDnCEm8SMLD3KHGOdHNh7kDjHOj2w8mAeIi/5arX+c6b/fxHz9oADEdGdjR/fXCw/OOB5oVfCOgnepz8IB14PMw03jCmTE+QBx5z0gAmKSqK9OUF+hcAeIhu/QYr4Qie8rjW83hhMBERARQAREQAREBBABERCLnH8BBgA+TQI7U4t53AAAAABJRU5ErkJggg=='
},
defaultIcon: { // ic
type: String,
default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAACE0lEQVR4Xu3c200DMRCF4XEltJAOkEugA+ggpUAHoQMqiFMCdEAJUMEiS4mEELlIO7bPOeN9i6K1rG/952myyea1WiCtXmEuYBPR4RBMxInoIOCwhOtJLKVszWyXc/5y2BvNEq6I+/3+kFK6M7OHnPM7jcLKjbZAvD/uaZtzflm5P4rbWyJWgDcze1LPuzVihfxUz7sH4ilJ2bx7Isrm3RtRMu8RiHJ5j0SUyXs0okTeCIj0eSMh0uaNhkiZNyIiXd7IiDR5oyNS5M2ACJ83EyJs3myIkHkzIsLlzYwIkzc7IkTeCojD81ZCHJa3GuKQvBURu+etjNgtb3XELnlHQGyedyTEZnlHQ2ySd0RE97wjI7rlHR3RJe+JeIrbLOecD6ePpZQ6W1kn2epo4MUrPOKyLN8ppYq1+y1VStncOjIdGnFZlo+U0uOtWOeOY2TE12Ouq//pEA7xXL7XfvcufR8K0Svfv6CREN3yDYfYIt9QiK3yjYTYLF95xB75SiP2ylcZsVu+cogj8pVCHJWvEuKwfOkREfKlRkTJlxkRJl86RMR8qRBR82VChM0XHpEhX2hElnyREWnyhUNkzBcKkTVfJETafIcjKuQ7FFEl35GIMvl2R1TMtyuiar49EWXzbY5oZpv/hibXTF2h3+s60FRKeT6+3TjMS3nrA3ZFRD8xrfY3ER1kJ+JEdBBwWGKeRAfEH1wS5WFZSDB/AAAAAElFTkSuQmCC'
},
lastIcon: { // ic
type: String,
default: ''
},
border: { // 线
type: Boolean,
default: false
},
},
data() {
return {
showTree: false,
treeList: [],
selectIndex: -1,
}
},
computed: {},
methods: {
_show() {
this.showTree = true
},
_hide() {
this.showTree = false
},
_cancel() {
this._hide()
this.$emit("cancel", '');
},
_confirm() {
//
let rt = [],
obj = {};
this.treeList.forEach((v, i) => {
if (this.treeList[i].checked) {
obj = {}
obj.parents = this.treeList[i].parents
obj = Object.assign(obj, this.treeList[i].source)
//
delete obj.children
rt.push(obj)
}
})
this._hide()
this.$emit("confirm", rt);
},
//
_renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
list.forEach(item => {
this.treeList.push({
id: item[this.idKey],
name: item[this.rangeKey],
source: item,
parentId, // id
parents, // id
rank, //
showChild: false, //
open: false, //
show: rank === 0, //
hideArr: [],
orChecked: item.checked ? item.checked : false,
checked: item.checked ? item.checked : false,
})
if (Array.isArray(item.children) && item.children.length > 0) {
// console.log(item)
let parentid = [...parentId],
parentArr = [...parents],
childrenid = [...childrenid];
delete parentArr.children
parentid.push(item[this.idKey]);
parentArr.push({
[this.idKey]: item[this.idKey],
[this.rangeKey]: item[this.rangeKey]
})
this._renderTreeList(item.children, rank + 1, parentid, parentArr);
} else {
this.treeList[this.treeList.length - 1].lastRank = true;
}
})
// console.log(list)
},
//
_defaultSelect() {
this.treeList.forEach((v, i) => {
if (v.checked) {
this.treeList.forEach((v2, i2) => {
if (v.parentId.toString().indexOf(v2.parentId.toString()) >= 0) {
v2.show = true
if (v.parentId.includes(v2.id)) {
v2.showChild = true;
v2.open = true;
}
}
})
}
})
},
//
_treeItemTap(item, index) {
if (item.lastRank === true) {
//
this.treeList[index].checked = !this.treeList[index].checked
this._fixMultiple(index)
return;
}
let list = this.treeList;
let id = item.id;
item.showChild = !item.showChild;
item.open = item.showChild ? true : !item.open;
list.forEach((childItem, i) => {
if (item.showChild === false) {
//
if (!childItem.parentId.includes(id)) {
return;
}
if (!this.foldAll) {
if (childItem.lastRank !== true && !childItem.open) {
childItem.showChild = false;
}
//
if (childItem.show) {
childItem.hideArr[item.rank] = id
}
} else {
if (childItem.lastRank !== true) {
childItem.showChild = false;
}
}
childItem.show = false;
} else {
//
if (childItem.parentId[childItem.parentId.length - 1] === id) {
childItem.show = true;
}
//
if (childItem.parentId.includes(id) && !this.foldAll) {
// console.log(childItem.hideArr)
if (childItem.hideArr[item.rank] === id) {
childItem.show = true;
if (childItem.open && childItem.showChild) {
childItem.showChild = true
} else {
childItem.showChild = false
}
childItem.hideArr[item.rank] = null
}
// console.log(childItem.hideArr)
}
}
})
// console.log(this.treeList)
},
_treeItemSelect(item, index) {
this.treeList[index].checked = !this.treeList[index].checked
this._fixMultiple(index)
},
//
_fixMultiple(index) {
if (!this.multiple) {
//
this.treeList.forEach((v, i) => {
if (i != index) {
this.treeList[i].checked = false
} else {
this.treeList[i].checked = true
}
})
} else {
this.treeList.forEach((obj, i) => {
if (!this.treeList[index].checked && this.treeList[index].parentId.indexOf(obj.id) > -1) {
this.treeList[i].checked = false;
} else if (obj.parentId.indexOf(this.treeList[index].id) > -1) {
this.treeList[i].checked = this.treeList[index].checked;
}
})
}
},
//
_reTreeList() {
this.treeList.forEach((v, i) => {
this.treeList[i].checked = v.orChecked
})
},
_initTree(range = this.range){
this.treeList = [];
this._renderTreeList(range);
this.$nextTick(() => {
this._defaultSelect(range)
})
}
},
watch: {
range(list) {
this._initTree(list);
},
multiple() {
if (this.range.length) {
this._reTreeList();
}
},
selectParent() {
if (this.range.length) {
this._reTreeList();
}
},
},
mounted() {
this._initTree();
}
}
</script>
<style scoped>
@import "./style.css";
</style>

5
components/wxParse.vue

@ -0,0 +1,5 @@
<template name="wxParse">
<block v-for="(item, index) in wxParseData" :key="index">
<template is="wxParse0" :data="item"></template>
</block>
</template>

81
components/wxParse0.vue

@ -0,0 +1,81 @@
<template name="wxParse0">
<!--<template is="wxParse1" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse1" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse1" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse1" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'table'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse1" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse1" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse1" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse1.vue

@ -0,0 +1,74 @@
<template name="wxParse1">
<!--<template is="wxParse2" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse2" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse2" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse2" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse2" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse2" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse10.vue

@ -0,0 +1,74 @@
<template name="wxParse10">
<!--<template is="wxParse11" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse11" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse11" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse11" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse11" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse11" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse11.vue

@ -0,0 +1,74 @@
<template name="wxParse11">
<!--<template is="wxParse12" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse12" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse12" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse12" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse12" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse12" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse2.vue

@ -0,0 +1,74 @@
<template name="wxParse2">
<!--<template is="wxParse3" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse3" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse3" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse3" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse3" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse3" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse3.vue

@ -0,0 +1,74 @@
<template name="wxParse3">
<!--<template is="wxParse4" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse4" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse4" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse4" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse4" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse4" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse4.vue

@ -0,0 +1,74 @@
<template name="wxParse4">
<!--<template is="wxParse5" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse5" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse5" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse5" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse5" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse5" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse5.vue

@ -0,0 +1,74 @@
<template name="wxParse5">
<!--<template is="wxParse6" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse6" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse6" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse6" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse6" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse6" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse6.vue

@ -0,0 +1,74 @@
<template name="wxParse6">
<!--<template is="wxParse7" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse7" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse7" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse7" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse7" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse7" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse7.vue

@ -0,0 +1,74 @@
<template name="wxParse7">
<!--<template is="wxParse8" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse8" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse8" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse8" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse8" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse8" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse8.vue

@ -0,0 +1,74 @@
<template name="wxParse8">
<!--<template is="wxParse9" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse9" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse9" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse9" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse9" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse9" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

74
components/wxParse9.vue

@ -0,0 +1,74 @@
<template name="wxParse9">
<!--<template is="wxParse10" data="{{item}}" />-->
<!--判断是否是标签节点-->
<block v-if="item.node == 'element'">
<block v-if="item.tag == 'button'">
<button type="default" size="mini">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse10" :data="item"></template>
</block>
</button>
</block>
<!--li类型-->
<block v-else-if="item.tag == 'li'">
<view :class="item.classStr + ' wxParse-li'" :style="item.styleStr">
<view :class="item.classStr + ' wxParse-li-inner'">
<view :class="item.classStr + ' wxParse-li-text'">
<view :class="item.classStr + ' wxParse-li-circle'"></view>
</view>
<view :class="item.classStr + ' wxParse-li-text'">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse10" :data="item"></template>
</block>
</view>
</view>
</view>
</block>
<!--video类型-->
<block v-else-if="item.tag == 'video'">
<template is="wxParseVideo" :data="item"></template>
</block>
<!--img类型-->
<block v-else-if="item.tag == 'img'">
<template is="wxParseImg" :data="item"></template>
</block>
<!--a类型-->
<block v-else-if="item.tag == 'a'">
<view @tap="wxParseTagATap" :class="'wxParse-inline ' + item.classStr + ' wxParse-' + item.tag" :data-src="item.attr.href" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse10" :data="item"></template>
</block>
</view>
</block>
<block v-else-if="item.tag == 'br'">
<template is="WxParseBr"></template>
</block>
<!--其他块级标签-->
<block v-else-if="item.tagType == 'block'">
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse10" :data="item"></template>
</block>
</view>
</block>
<!--内联标签-->
<view v-else :class="item.classStr + ' wxParse-' + item.tag + ' wxParse-' + item.tagType" :style="item.styleStr">
<block v-for="(item, index) in item.nodes" :key="index">
<template is="wxParse10" :data="item"></template>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="item.node == 'text'">
<!--如果是直接进行-->
<template is="WxEmojiView" :data="item"></template>
</block>
</template>

3
components/wxParseImg.vue

@ -0,0 +1,3 @@
<template name="wxParseImg">
<image :class="item.classStr + ' wxParse-' + item.tag" :data-from="item.from" :data-src="item.attr.src" :data-idx="item.imgIndex" :src="item.attr.src" mode="aspectFit" @load="wxParseImgLoad" @tap="wxParseImgTap" :style="'width:' + item.width + 'px'"></image>
</template>

6
components/wxParseVideo.vue

@ -0,0 +1,6 @@
<template name="wxParseVideo">
<!--增加video标签支持并循环添加-->
<view :class="item.classStr + ' wxParse-' + item.tag" :style="item.styleStr">
<video :class="item.classStr + ' wxParse-' + item.tag + '-video'" :src="item.attr.src"></video>
</view>
</template>

12
config/index.js

@ -0,0 +1,12 @@
// export const VUE_APP_API_URL = 'http://natapp.xinxintuan.co/api';
// export const VUE_APP_API_URL = 'https://wxapi.yixiang.co/api'
// export const VUE_APP_API_URL = 'http://192.168.0.112:8088/api'
export const VUE_APP_API_URL = 'http://192.168.0.112:8092/api'
// export const VUE_APP_API_URL = 'http://192.168.0.114:8092/api'
// export const VUE_APP_API_URL = 'https://www.cyjyyjy.com/api'
// export const VUE_APP_API_URL = 'http://natapp.xinxintuan.co/api';
// export const VUE_APP_API_URL = 'https://thapi.xinxintuan.co/api'
// export const VUE_APP_API_URL = 'https://h5api.xinxintuan.co/api';
// export const VUE_APP_API_URL = 'https://h5api.xinxintuan.co/api';
export const VUE_APP_RESOURCES_URL = 'https://h5.yixiang.co/static'

1
dist/cell/index.d.ts vendored

@ -1 +0,0 @@
export {};

38
dist/cell/index.js vendored

@ -1,38 +0,0 @@
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,
},
titleStyle: String,
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
},
},
});

6
dist/cell/index.json vendored

@ -1,6 +0,0 @@
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}

47
dist/cell/index.wxml vendored

@ -1,47 +0,0 @@
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<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="{{ computed.titleStyle({ titleWidth, titleStyle }) }}"
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>

17
dist/cell/index.wxs vendored

@ -1,17 +0,0 @@
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function titleStyle(data) {
return style([
{
'max-width': addUnit(data.titleWidth),
'min-width': addUnit(data.titleWidth),
},
data.titleStyle,
]);
}
module.exports = {
titleStyle: titleStyle,
};

1
dist/cell/index.wxss vendored

@ -1 +0,0 @@
@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;right:16px;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:4px;margin-right:var(--padding-base,4px)}.van-cell__right-icon-wrap{margin-left:4px;margin-left:var(--padding-base,4px);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__value{font-size:16px;font-size:var(--cell-large-value-font-size,16px)}.van-cell--large .van-cell__label{font-size:14px;font-size:var(--cell-large-label-font-size,14px)}

6
dist/collapse-item/animate.d.ts vendored

@ -1,6 +0,0 @@
/// <reference types="miniprogram-api-typings" />
export declare function setContentAnimate(
context: WechatMiniprogram.Component.TrivialInstance,
expanded: boolean,
mounted: boolean
): void;

70
dist/collapse-item/animate.js vendored

@ -1,70 +0,0 @@
import { canIUseAnimate } from '../common/version';
import { getRect } from '../common/utils';
function useAnimate(context, expanded, mounted, height) {
const selector = '.van-collapse-item__wrapper';
if (expanded) {
context.animate(
selector,
[
{ height: 0, ease: 'ease-in-out', offset: 0 },
{ height: `${height}px`, ease: 'ease-in-out', offset: 1 },
{ height: `auto`, ease: 'ease-in-out', offset: 1 },
],
mounted ? 300 : 0,
() => {
context.clearAnimation(selector);
}
);
return;
}
context.animate(
selector,
[
{ height: `${height}px`, ease: 'ease-in-out', offset: 0 },
{ height: 0, ease: 'ease-in-out', offset: 1 },
],
300,
() => {
context.clearAnimation(selector);
}
);
}
function useAnimation(context, expanded, mounted, height) {
const animation = wx.createAnimation({
duration: 0,
timingFunction: 'ease-in-out',
});
if (expanded) {
if (height === 0) {
animation.height('auto').top(1).step();
} else {
animation
.height(height)
.top(1)
.step({
duration: mounted ? 300 : 1,
})
.height('auto')
.step();
}
context.setData({
animation: animation.export(),
});
return;
}
animation.height(height).top(0).step({ duration: 1 }).height(0).step({
duration: 300,
});
context.setData({
animation: animation.export(),
});
}
export function setContentAnimate(context, expanded, mounted) {
getRect(context, '.van-collapse-item__content')
.then((rect) => rect.height)
.then((height) => {
canIUseAnimate()
? useAnimate(context, expanded, mounted, height)
: useAnimation(context, expanded, mounted, height);
});
}

1
dist/collapse-item/index.d.ts vendored

@ -1 +0,0 @@
export {};

59
dist/collapse-item/index.js vendored

@ -1,59 +0,0 @@
import { VantComponent } from '../common/component';
import { useParent } from '../common/relation';
import { setContentAnimate } from './animate';
VantComponent({
classes: ['title-class', 'content-class'],
relation: useParent('collapse'),
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: {
expanded: false,
},
mounted() {
this.updateExpanded();
this.mounted = true;
},
methods: {
updateExpanded() {
if (!this.parent) {
return;
}
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);
if (expanded !== this.data.expanded) {
setContentAnimate(this, expanded, this.mounted);
}
this.setData({ index, expanded });
},
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);
},
},
});

6
dist/collapse-item/index.json vendored

@ -1,6 +0,0 @@
{
"component": true,
"usingComponents": {
"van-cell": "../cell/index"
}
}

44
dist/collapse-item/index.wxml vendored

@ -1,44 +0,0 @@
<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') }}"
style="height: 0;"
animation="{{ animation }}"
>
<view
class="van-collapse-item__content content-class"
>
<slot />
</view>
</view>
</view>

1
dist/collapse-item/index.wxss vendored

@ -1 +0,0 @@
@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__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)}

1
dist/collapse/index.d.ts vendored

@ -1 +0,0 @@
export {};

44
dist/collapse/index.js vendored

@ -1,44 +0,0 @@
import { VantComponent } from '../common/component';
import { useChildren } from '../common/relation';
VantComponent({
relation: useChildren('collapse-item'),
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;
const changeItem = name;
if (!accordion) {
name = expanded
? (value || []).concat(name)
: (value || []).filter((activeName) => activeName !== name);
} else {
name = expanded ? name : '';
}
if (expanded) {
this.$emit('open', changeItem);
} else {
this.$emit('close', changeItem);
}
this.$emit('change', name);
this.$emit('input', name);
},
},
});

3
dist/collapse/index.json vendored

@ -1,3 +0,0 @@
{
"component": true
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save