feat: 添加静态资源文件及基础组件
- 新增大量图片资源,包括图标、背景图、海报等,用于页面展示 - 添加字体文件及样式配置,支持自定义字体 - 引入 uni-ui 组件库,包括图标、弹窗、日期选择器等常用组件 - 添加网络状态监听、加密工具等基础工具函数 - 配置 Vuex 状态管理,包括购物车数量、热门搜索词等 - 增加页面组件,如用户协议、分销信息、提现状态等 - 配置项目构建和忽略文件,优化开发体验
This commit is contained in:
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
.history
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
build.sh
|
||||
.idea
|
||||
unpackage
|
||||
project.config.json
|
||||
.hbuilderx
|
||||
/config/app.js
|
||||
331
App.vue
Normal file
331
App.vue
Normal file
@@ -0,0 +1,331 @@
|
||||
<script>
|
||||
import {checkLogin} from './libs/login';
|
||||
import {HTTP_REQUEST_URL} from './config/app';
|
||||
import { LOGIN_STATUS, SUBSCRIBE_MESSAGE } from "./config/cache.js"
|
||||
import { getShopConfig, silenceAuth, getLogo, remoteRegister } from '@/api/public';
|
||||
import { silenceBindingSpread } from '@/utils';
|
||||
import Auth from '@/libs/wechat.js';
|
||||
import Routine from './libs/routine.js';
|
||||
import { colorChange, copyRight } from '@/api/api.js';
|
||||
import { getUserInfo } from "@/api/user.js"
|
||||
import { mapGetters } from "vuex"
|
||||
// #ifdef MP
|
||||
// let livePlayer = requirePlugin('live-player-plugin')
|
||||
// #endif
|
||||
export default {
|
||||
globalData: {
|
||||
spid: 0,
|
||||
code: 0,
|
||||
isLogin: false,
|
||||
userInfo: {},
|
||||
globalData: false,
|
||||
windowHeight: uni.getWindowInfo().windowHeight + 'px',
|
||||
sysHeight:uni.getWindowInfo().statusBarHeight,
|
||||
},
|
||||
computed: mapGetters(['isLogin', 'cartNum']),
|
||||
watch: {
|
||||
cartNum(newCart, b) {
|
||||
this.$store.commit('indexData/setCartNum', newCart + '')
|
||||
if (newCart > 0) {
|
||||
uni.setTabBarBadge({
|
||||
index: 3,
|
||||
text: newCart>99?'99+':newCart+''
|
||||
})
|
||||
} else {
|
||||
uni.hideTabBarRedDot({
|
||||
index: 3
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
onShow(options) {
|
||||
const queryData = uni.getEnterOptionsSync(); // uni-app版本 3.5.1+ 支持
|
||||
if (queryData.query.spid) {
|
||||
this.$Cache.set('spread', queryData.query.spid);
|
||||
this.globalData.spid = queryData.query.spid;
|
||||
this.globalData.pid = queryData.query.spid;
|
||||
silenceBindingSpread(this.globalData);
|
||||
}
|
||||
// #ifdef MP
|
||||
if (queryData.query.scene) {
|
||||
let param = this.$util.getUrlParams(decodeURIComponent(queryData.query.scene));
|
||||
if (param.spid) {
|
||||
this.$Cache.set('spread', param.spid);
|
||||
this.globalData.spid = param.spid;
|
||||
}
|
||||
/** 直播间分享**/
|
||||
// const sceneList = [1007, 1008, 1014, 1044, 1045, 1046, 1047, 1048, 1049, 1073, 1154, 1155];
|
||||
// if (sceneList.includes(queryData.query.scene)) {
|
||||
// livePlayer.getShareParams().then(res => {
|
||||
// //记录推广人uid
|
||||
// if(res.custom_params.pid){
|
||||
// this.$Cache.set('spread', res.custom_params.pid);
|
||||
// this.globalData.spid = res.custom_params.pid;
|
||||
// }
|
||||
// }).catch(err => {
|
||||
// })
|
||||
// }
|
||||
silenceBindingSpread(this.globalData);
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
onLaunch(option) {
|
||||
uni.hideTabBar()
|
||||
//#ifdef APP
|
||||
plus.screen.lockOrientation("portrait-primary");
|
||||
//#endif
|
||||
let that = this;
|
||||
//获取并存储配置
|
||||
this.setConfig();
|
||||
//主题换色
|
||||
this.setTheme();
|
||||
// 通过vuex获取并储存公共配置
|
||||
this.$store.dispatch("getBasicConfig");
|
||||
// 通过vuex获取并储存底部菜单的数据
|
||||
this.$store.dispatch("getPageFooter");
|
||||
// 通过vuex获取并储存活动弹窗的数据
|
||||
this.$store.dispatch("getActivityModal");
|
||||
// #ifdef H5
|
||||
if (!this.isLogin && option.query.hasOwnProperty('remote_token')) {
|
||||
this.remoteRegister(option.query.remote_token);
|
||||
}
|
||||
this.setScript();
|
||||
const queryData = uni.getEnterOptionsSync();
|
||||
uni.getSystemInfo({
|
||||
success(e) {
|
||||
/* 窗口宽度大于420px且不在PC页面且不在移动设备时跳转至 PC.html 页面 */
|
||||
if (e.windowWidth > 420 && !window.top.isPC && !/iOS|Android/i.test(e.system)) {
|
||||
window.location.pathname = '/static/html/pc.html';
|
||||
}
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
// 小程序静默授权
|
||||
if (!this.$store.getters.isLogin) {
|
||||
Routine.getCode().then(code => {
|
||||
this.silenceAuth(code);
|
||||
}).catch(res => {
|
||||
uni.hideLoading();
|
||||
});
|
||||
}else if(this.$store.getters.isLogin && this.getExpired()){
|
||||
//处理小程序有token情况下但是静默授权失败
|
||||
this.$Cache.clear(LOGIN_STATUS);
|
||||
Routine.getCode().then(code => {
|
||||
this.silenceAuth(code);
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
remoteRegister(remote_token) {
|
||||
remoteRegister({ remote_token }).then((res) => {
|
||||
let data = res.data;
|
||||
if (data.get_remote_login_url) {
|
||||
location.href = data.get_remote_login_url
|
||||
} else {
|
||||
this.$store.commit("LOGIN", {
|
||||
'token': data.token,
|
||||
'time': data.expires_time - this.$Cache.time()
|
||||
});
|
||||
getUserInfo().then(res => {
|
||||
this.$store.commit("SETUID", res.data.uid);
|
||||
this.$store.commit("UPDATE_USERINFO", res.data);
|
||||
location.reload()
|
||||
}).catch(error => {
|
||||
return this.$util.Tips({
|
||||
title:err
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
// 小程序静默授权
|
||||
silenceAuth(code) {
|
||||
let that = this;
|
||||
let spid = that.globalData.spid ? that.globalData.spid : '';
|
||||
silenceAuth({
|
||||
code: code,
|
||||
spread_spid: spid,
|
||||
spread_code: that.globalData.code
|
||||
})
|
||||
.then(res => {
|
||||
if (res.data.token !== undefined && res.data.token) {
|
||||
uni.hideLoading();
|
||||
let time = res.data.expires_time - this.$Cache.time();
|
||||
that.$store.commit('LOGIN', {
|
||||
token: res.data.token,
|
||||
time: time
|
||||
});
|
||||
that.$store.commit('SETUID', res.data.userInfo.uid);
|
||||
that.$store.commit('UPDATE_USERINFO', res.data.userInfo);
|
||||
}
|
||||
}).catch(err => {
|
||||
return that.$util.Tips({
|
||||
title:err
|
||||
})
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 检测当前的小程序
|
||||
* 是否是最新版本,是否需要下载、更新
|
||||
*/
|
||||
checkUpdateVersion() {
|
||||
//判断微信版本是否 兼容小程序更新机制API的使用
|
||||
if (wx.canIUse('getUpdateManager')) {
|
||||
const updateManager = wx.getUpdateManager();
|
||||
//检测版本更新
|
||||
updateManager.onCheckForUpdate(function(res) {
|
||||
if (res.hasUpdate) {
|
||||
updateManager.onUpdateReady(function() {
|
||||
wx.showModal({
|
||||
title: '温馨提示',
|
||||
content: '检测到新版本,是否重启小程序?',
|
||||
showCancel: false,
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
||||
updateManager.applyUpdate()
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
updateManager.onUpdateFailed(function() {
|
||||
// 新版本下载失败
|
||||
wx.showModal({
|
||||
title: '已有新版本',
|
||||
content: '请您删除小程序,重新搜索进入',
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
wx.showModal({
|
||||
title: '溫馨提示',
|
||||
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
|
||||
})
|
||||
}
|
||||
},
|
||||
async getExpired(){
|
||||
// 通过一个个人中心的接口判断token是否生效,catch捕获到就证明token过期,返回true
|
||||
try {
|
||||
await getUserInfo();
|
||||
return false; // token有效
|
||||
} catch (err) {
|
||||
return true; // token过期
|
||||
}
|
||||
},
|
||||
setConfig(){
|
||||
uni.removeStorageSync(SUBSCRIBE_MESSAGE);
|
||||
this.$Cache.clear('homeTop');
|
||||
let that = this;
|
||||
// #ifdef MP
|
||||
if (HTTP_REQUEST_URL == '') {
|
||||
uni.showToast({
|
||||
title: "请配置根目录下的config/app.js文件中的HTTP_REQUEST_URL",
|
||||
icon:'error'
|
||||
})
|
||||
}
|
||||
this.checkUpdateVersion();
|
||||
let menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
||||
that.globalData.navH = menuButtonInfo.top * 2 + menuButtonInfo.height / 2;
|
||||
const version = wx.getAppBaseInfo().SDKVersion;
|
||||
if (Routine.compareVersion(version, '2.21.2') >= 0) {
|
||||
that.$Cache.set('MP_VERSION_ISNEW', true)
|
||||
} else {
|
||||
that.$Cache.set('MP_VERSION_ISNEW', false)
|
||||
}
|
||||
// #endif
|
||||
getLogo().then(res => {
|
||||
uni.setStorageSync('BASIC_CONFIG', res.data)
|
||||
});
|
||||
},
|
||||
setTheme(){
|
||||
let green =
|
||||
'--view-theme: #42CA4D;--view-minorColorT:rgba(66, 202, 77, 0.1);--view-bntColor:#FE960F;--view-gradient:#4DEA4D'
|
||||
let red =
|
||||
'--view-theme: #e93323;--view-minorColorT:rgba(233, 51, 35, 0.1);--view-bntColor:#FE960F;--view-gradient:#FF7931'
|
||||
let blue =
|
||||
'--view-theme: #1DB0FC;--view-minorColorT:rgba(9, 139, 243, 0.1);--view-bntColor:#22CAFD;--view-gradient:#5ACBFF'
|
||||
let pink =
|
||||
'--view-theme: #FF448F;--view-minorColorT:rgba(255, 68, 143, 0.1);--view-bntColor:#282828;--view-gradient:#FF67AD'
|
||||
let orange =
|
||||
'--view-theme: #FE5C2D;--view-minorColorT:rgba(254, 92, 45, 0.1);--view-bntColor:#FDB000;--view-gradient:#FF9451'
|
||||
let gold =
|
||||
'--view-theme: #E0A558;--view-minorColorT:rgba(224, 165, 88, 0.1);--view-bntColor:#1A1A1A;--view-gradient:#FFCD8C'
|
||||
colorChange('color_change').then(res => {
|
||||
let statusColor = res.data.status; //判断显示啥颜色
|
||||
let themeType = res.data.color_data?.theme_type || 1;
|
||||
if(themeType == 1){
|
||||
uni.setStorageSync('statusColor', statusColor);
|
||||
uni.$emit('colorOk', statusColor);
|
||||
let themeList = {
|
||||
1:blue, 2:green, 3:red, 4:pink, 5:orange, 6:gold
|
||||
};
|
||||
Object.entries(themeList).forEach(([key, themeSelect]) => {
|
||||
if (key == statusColor) {
|
||||
uni.setStorageSync('viewColor', themeSelect);
|
||||
uni.$emit('ok', themeSelect);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
let colorData = res.data.color_data;
|
||||
let themeStr = `--view-theme: ${colorData.theme_color};--view-minorColorT:${colorData.light_color};--view-bntColor:${colorData.aux_color};--view-gradient:${colorData.gradient_color}`;
|
||||
uni.setStorageSync('viewColor', themeStr);
|
||||
uni.$emit('ok', themeStr);
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
setScript(){
|
||||
// 添加crmeb chat 统计
|
||||
var __s = document.createElement('script');
|
||||
__s.src = `${HTTP_REQUEST_URL}/api/get_script`;
|
||||
document.head.appendChild(__s);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* #ifndef APP-PLUS-NVUE || APP-NVUE */
|
||||
@import url('@/plugin/emoji-awesome/css/tuoluojiang.css');
|
||||
@import 'static/css/base.css';
|
||||
@import 'static/iconfont/iconfont.css';
|
||||
@import 'static/css/unocss.css';
|
||||
@import 'static/fonts/font.scss';
|
||||
|
||||
view {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
page {
|
||||
font-family: PingFang SC;
|
||||
}
|
||||
|
||||
.placeholder{
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.mer-bg{
|
||||
background-color: $primary-merchant;
|
||||
}
|
||||
|
||||
.uni-scroll-view::-webkit-scrollbar {
|
||||
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
||||
display: none;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.uni-system-open-location .map-content.fix-position {
|
||||
height: 100vh;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
275
README.md
Normal file
275
README.md
Normal file
@@ -0,0 +1,275 @@
|
||||
# CRMEB 移动端
|
||||
## 开发规范
|
||||
市面上常用的命名规范:
|
||||
|
||||
* camelCase(小驼峰式命名法 —— 首字母小写)
|
||||
* PascalCase(大驼峰式命名法 —— 首字母大写)
|
||||
* kebab-case(短横线连接式)
|
||||
* snake_a(下划线连接式)
|
||||
|
||||
##### 项目文件命名
|
||||
#####1、项目名
|
||||
#####全部采用小写方式, 以下划线分隔。 例:crmeb_pro_uniapp;
|
||||
#####2、组件(components)
|
||||
#####优先选择单个单词命名,多个单词命名以小驼峰式命名。例:crmebPro;
|
||||
#####3、pages里面的文件名;
|
||||
#####全部采用小写方式, 优先选择单个单词命名,多个单词命名以下划线分隔,组件参考第2条。 例:crmeb_pro_uniapp;
|
||||
#####4、css文件名;
|
||||
#####全部采用小写方式, 优先选择单个单词命名,多个单词命名以短横线分隔。例:crmeb-pro.css
|
||||
#####5、JavaScript 文件名;
|
||||
#####全部采用小写方式, 优先选择单个单词命名,多个单词命名以短横线分隔。例:crmeb-pro.js
|
||||
#####6、HTML 文件名;
|
||||
#####全部采用小写方式, 优先选择单个单词命名,多个单词命名以下划线分隔。例:crmeb_pro.html
|
||||
#####7、图像文件名;
|
||||
#####全部采用小写方式, 优先选择单个单词命名,多个单词命名以短横线分隔。例:crmeb-pro.jpg
|
||||
|
||||
## 目录结构
|
||||
主要目录结构及说明:
|
||||
~~~
|
||||
├── api # 请求接口
|
||||
│ ├── activity # 活动接口
|
||||
│ ├── admin # 管理端接口
|
||||
│ ├── api # 文章优惠券等接口
|
||||
│ ├── esp # esp接口
|
||||
│ ├── kefu # 客服接口
|
||||
│ ├── lottery # 抽奖活动接口
|
||||
│ ├── order # 订单接口
|
||||
│ ├── points_mall # 积分商城接口
|
||||
│ ├── public # 配置类接口
|
||||
│ ├── store # 商品接口
|
||||
│ ├── user # 我的接口
|
||||
│ └──work # 企业微信接口
|
||||
│ ├── components # 公共组件
|
||||
│ │ └──addressWindow # 选择地址
|
||||
│ │ └──cartDiscount # 购物车优惠明细
|
||||
│ │ └──cartList # 购物车列表
|
||||
│ │ └──countDown # 倒计时
|
||||
│ │ └──couponListWindow # 优惠券列表
|
||||
│ │ └──couponWindow # 首页优惠券
|
||||
│ │ └──cusPreviewImg # 规格轮播
|
||||
│ │ └──customForm # 自定义组件
|
||||
│ │ └──d_goodList # 分类二的组件
|
||||
│ │ └──goodClass # 分类三的组件
|
||||
│ │ └──goodList # 营销组件
|
||||
│ │ └──guide # 闪屏组件
|
||||
│ │ └──home # 悬浮导航
|
||||
│ │ └──homeList # 导航列表
|
||||
│ │ └──jyf-parser # 富文本
|
||||
│ │ └──kefuIcon # 客服
|
||||
│ │ └──Loading # 加载
|
||||
│ │ └──orderGoods # 订单商品
|
||||
│ │ └──pageFooter # 底部导航
|
||||
│ │ └──payment # 支付
|
||||
│ │ └──productConSwiper # 商品轮播
|
||||
│ │ └──productWindow # 商品属性
|
||||
│ │ └──recommend # 热门推荐
|
||||
│ │ └──skeleton # 骨架屏
|
||||
│ │ └──storeLis # 门店列表
|
||||
│ │ └──swipers # 轮播
|
||||
│ │ └──uni-calendar # 日期
|
||||
│ │ └──uniNoticeBar # 跑马灯
|
||||
│ │ └──userEvaluation # 评价
|
||||
│ │ └──zb-code # 二维码生成插件
|
||||
│ │ └──emptyPage # 无数据时显示页面
|
||||
│ ├── config # 项目配置文件
|
||||
│ ├── libs
|
||||
│ │ └──login # 登录
|
||||
│ │ └──network # 检测长链接
|
||||
│ │ └──new_chat # 检测长链接
|
||||
│ │ └──order # 订单跳转
|
||||
│ │ └──routine # 授权
|
||||
│ │ └──wechat # h5授权支付等函数
|
||||
│ │ └──work # 企业微信
|
||||
│ ├── mixins # 通用混合
|
||||
│ │ └──color # 一键换色
|
||||
│ │ └──SendVerifyCode # 获取验证码
|
||||
│ ├── pages # 所有页面
|
||||
│ │ └──activity # 活动
|
||||
│ │ └──bargain # 砍价状态列表
|
||||
│ │ └──components # 组件
|
||||
│ │ └──giftGoods # 商品赠品列表
|
||||
│ │ └──discount # 活动折扣列表
|
||||
│ │ └──goods_bargain # 砍价商品列表
|
||||
│ │ └──goods_bargain_details # 砍价详情
|
||||
│ │ └──goods_combination # 拼团列表
|
||||
│ │ └──goods_combination_details # 拼团详情
|
||||
│ │ └──goods_combination_status # 拼团状态
|
||||
│ │ └──goods_seckill # 秒杀列表
|
||||
│ │ └──goods_seckill_details # 秒杀详情
|
||||
│ │ └──poster-poster # 海报
|
||||
│ │ └──presell # 预售列表
|
||||
│ │ └──static # 图片
|
||||
│ │ └──admin # 管理端
|
||||
│ │ └──components # 组件
|
||||
│ │ └──priceChange # 改价以及备注弹窗
|
||||
│ │ └──ucharts # 统计图
|
||||
│ │ └──writeOffSwitching # 核销列表
|
||||
│ │ └──custom_date # 选择日期
|
||||
│ │ └──delivery # 订单发货
|
||||
│ │ └──distribution
|
||||
│ │ └──orderDetail # 订单详情
|
||||
│ │ └──scanning # 扫描结果
|
||||
│ │ └──index # 配送员
|
||||
│ │ └──order # 订单统计
|
||||
│ │ └──order_cancellation # 订单核销
|
||||
│ │ └──orderDetail # 订单详情
|
||||
│ │ └──orderList # 订单列表
|
||||
│ │ └──static # 图片
|
||||
│ │ └──statistics # 订单数据统计
|
||||
│ │ └──store # 门店管理
|
||||
│ │ └──custom_date # 选择日期
|
||||
│ │ └──deliverGoods # 订单发货
|
||||
│ │ └──order # 订单管理
|
||||
│ │ └──orderDetail # 订单详情
|
||||
│ │ └──scanning # 扫描结果
|
||||
│ │ └──statistics # 订单数据统计
|
||||
│ │ └──index # 门店中心
|
||||
│ │ └──annex # 会员
|
||||
│ │ └──offline_pay # 支付
|
||||
│ │ └──offline_result # 支付结果
|
||||
│ │ └──special # 专题页
|
||||
│ │ └──vip_active # 激活会员
|
||||
│ │ └──vip_clause # 会员协议
|
||||
│ │ └──vip_coupon # 会员优惠券
|
||||
│ │ └──vip_paid # SVIP会员
|
||||
│ │ └──web_view # 外部链接跳转
|
||||
│ │ └──auth # 登录页
|
||||
│ │ └──columnGoods
|
||||
│ │ └──HotNewGoods
|
||||
│ │ └──feedback # 我的客服
|
||||
│ │ └──index # 精品推荐
|
||||
│ │ └──live_list #推荐好货
|
||||
│ │ └──static #图片
|
||||
│ │ └──extension
|
||||
│ │ └──components #组件
|
||||
│ │ └──shareInfo # 分享
|
||||
│ │ └──vconsole.min # 查看后台打印
|
||||
│ │ └──customer_list
|
||||
│ │ └──chat # 客服聊天界面
|
||||
│ │ └──invite_friend #邀请好友
|
||||
│ │ └──news_details #资讯详情
|
||||
│ │ └──news_list #资讯
|
||||
│ │ └──static #图片
|
||||
│ │ └──goods
|
||||
│ │ └──admin_order_detail #订单详情
|
||||
│ │ └──components #组件
|
||||
│ │ └──invoiceModal # 选择发票
|
||||
│ │ └──invoicePicker # 添加发票信息
|
||||
│ │ └──lottery # 抽奖转盘
|
||||
│ │ └──maramlee-waterfalls-flow # 客服聊天界面
|
||||
│ │ └──goods_comment_con #组件
|
||||
│ │ └──comment_con # 评价详情
|
||||
│ │ └──index # 商品评价
|
||||
│ │ └──lottery_comment # 订单评价
|
||||
│ │ └──goods_comment_list #商品评分列表
|
||||
│ │ └──goods_details_store #门店列表
|
||||
│ │ └──goods_list #商品列表
|
||||
│ │ └──goods_logistics #商品物流
|
||||
│ │ └──goods_return #申请退货
|
||||
│ │ └──goods_return_list #退货列表
|
||||
│ │ └──goods_search #商品搜索
|
||||
│ │ └──lottery
|
||||
│ │ └──grids
|
||||
│ │ └──index #抽奖活动
|
||||
│ │ └──record #中奖纪录
|
||||
│ │ └──order_confirm #确认订单
|
||||
│ │ └──order_details #订单详情
|
||||
│ │ └──order_pay #订单支付
|
||||
│ │ └──order_pay_status #支付成功
|
||||
│ │ └──order_refund_goods #退回商品
|
||||
│ │ └──order_pay_status #退回商品
|
||||
│ │ └──static #图片
|
||||
│ │ └──goods_cate 分类
|
||||
│ │ └──goods_details 商品详情
|
||||
│ │ └──guide 闪屏
|
||||
│ │ └──index 首页
|
||||
│ │ └──order_addcart 购物车
|
||||
│ │ └──points_mall 积分商城
|
||||
│ │ └──components #组件
|
||||
│ │ └──productWindow #商品规格
|
||||
│ │ └──static #图片
|
||||
│ │ └──exchange_record #兑换记录
|
||||
│ │ └──index #积分商城首页
|
||||
│ │ └──integral_goods_details #商品详情
|
||||
│ │ └──integral_goods_list #商品列表
|
||||
│ │ └──integral_order #积分订单
|
||||
│ │ └──integral_order_details #兑换订单详情
|
||||
│ │ └──integral_order_status #兑换成功
|
||||
│ │ └──logistics_details #兑换物流详情
|
||||
│ │ └──user_address #选择地址
|
||||
│ │ └──user 个人中心
|
||||
│ │ └──users 我的
|
||||
│ │ └──alipay_invoke #支付提示
|
||||
│ │ └──commission_rank #佣金排行
|
||||
│ │ └──components #组件
|
||||
│ │ └──areaWindow #选择地区
|
||||
│ │ └──login_mobile #登录
|
||||
│ │ └──pageHeader #头部导航
|
||||
│ │ └──timeSlot #时间日期插件
|
||||
│ │ └──login #登录
|
||||
│ │ └──message_center
|
||||
│ │ └──index #消息中心
|
||||
│ │ └──messageDetail #消息详情
|
||||
│ │ └──privacy #协议
|
||||
│ │ └──promoter_rank #推广人排行
|
||||
│ │ └──promoter-list #推广人列表
|
||||
│ │ └──promoter-order #推广人订单
|
||||
│ │ └──retrievePassword #忘记密码
|
||||
│ │ └──scan_login #授权登录
|
||||
│ │ └──static #图片
|
||||
│ │ └──user_address #选择地址
|
||||
│ │ └──user_address_list #地址管理
|
||||
│ │ └──user_bill #账单明细
|
||||
│ │ └──user_cancellation #注销说明
|
||||
│ │ └──user_cash #提现
|
||||
│ │ └──user_coupon #我的优惠券
|
||||
│ │ └──user_distribution_level #分销等级
|
||||
│ │ └──user_get_coupon #领取优惠券
|
||||
│ │ └──user_goods_collection #收藏商品
|
||||
│ │ └──user_info #个人资料
|
||||
│ │ └──user_integral #积分详情
|
||||
│ │ └──user_invoice_form #添加新发票
|
||||
│ │ └──user_invoice_list #发票管理
|
||||
│ │ └──user_invoice_order #订单详情
|
||||
│ │ └──user_money #我的账户
|
||||
│ │ └──user_payment #余额储值
|
||||
│ │ └──user_phone #绑定手机
|
||||
│ │ └──user_pwd_edit #修改密码
|
||||
│ │ └──user_return_list #退货列表
|
||||
│ │ └──user_sgin #签到
|
||||
│ │ └──user_sgin_list #签到记录
|
||||
│ │ └──user_spread_code #分销海报
|
||||
│ │ └──user_spread_money #佣金记录
|
||||
│ │ └──user_spread_user #我的推广
|
||||
│ │ └──user_vip #我的等级
|
||||
│ │ └──user_vip_areer #经验记录
|
||||
│ │ └──visit_list #浏览记录
|
||||
│ │ └──wechat_login #账户登录
|
||||
│ │ └──work 企业微信
|
||||
│ │ └──components #组件
|
||||
│ │ └──tabNav #导航
|
||||
│ │ └──groupInfo #群组信息
|
||||
│ │ └──orderDetail #订单详情
|
||||
│ │ └──orderList #交易管理
|
||||
│ │ └──record #记录
|
||||
│ │ └──userInfo #客户信息
|
||||
│ ├── plugins # 插件
|
||||
│ ├── static # 静态文件
|
||||
│ ├── store # Vuex 状态管理
|
||||
│ ├── utils # js工具
|
||||
│ ├── App # 入口文件
|
||||
│ ├── main.js # 入口文件,注册vue等
|
||||
│ └── pages.json # 页面配置
|
||||
~~~
|
||||
## 开发打包项目
|
||||
~~~
|
||||
uniapp开发工具必须为HBuilder
|
||||
|
||||
# 启动项目(本地开发环境)
|
||||
点击运行
|
||||
|
||||
# 打包项目
|
||||
点击发行
|
||||
~~~
|
||||
|
||||
|
||||
28
androidPrivacy.json
Normal file
28
androidPrivacy.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"version" : "1",
|
||||
"prompt" : "template",
|
||||
"title" : "用户协议与隐私政策",
|
||||
"message" : "\t请务必审慎阅读、充分理解“用户协议与 隐私政策”各条款,包括但不限于:为了 向你提供即时通讯、内容分享等服务,我 们需要收集你的设备信息、操作日志等个 人信息。你可以在“设置”中查看、变更、删除个人信息并管理你的授权。<br/>
|
||||
你可以阅读 <a href=\"pages/columnGoods/static/yhxy.html\">《用户协议》</a>与 <a href=\"pages/columnGoods/static/yszc.html\">《隐私政策》</a>了解详细信息。如你同意,请点击“我同意”开始接受我们的服务。",
|
||||
"buttonAccept" : "同意并接受",
|
||||
"buttonRefuse" : "暂不同意",
|
||||
"second" : {
|
||||
"title" : "确认提示",
|
||||
"message" : "进入应用前,你需先同意<a href=\"pages/columnGoods/static/yhxy.html\">《用户协议》</a>与<a href=\"pages/columnGoods/static/yszc.html\">《隐私政策》</a>,否则将退出应用。",
|
||||
"buttonAccept" : "同意并继续",
|
||||
"buttonRefuse" : "退出应用"
|
||||
},
|
||||
"styles" : {
|
||||
"backgroundColor" : "#fff",
|
||||
"borderRadius" : "5px",
|
||||
"title" : {
|
||||
"color" : "#000"
|
||||
},
|
||||
"buttonAccept" : {
|
||||
"color" : "#fff"
|
||||
},
|
||||
"buttonRefuse" : {
|
||||
"color" : "#ccc"
|
||||
}
|
||||
}
|
||||
}
|
||||
421
api/activity.js
Normal file
421
api/activity.js
Normal file
@@ -0,0 +1,421 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
/**
|
||||
*
|
||||
* 所有活动接口 包括:拼团,砍价,秒杀
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* 拼团列表
|
||||
*
|
||||
*/
|
||||
export function getCombinationList(data) {
|
||||
return request.get('combination/list', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团详情
|
||||
*
|
||||
*/
|
||||
export function getCombinationDetail(id) {
|
||||
return request.get('combination/detail/' + id,{},{noAuth: true});
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团 开团
|
||||
*/
|
||||
export function getCombinationPink(id) {
|
||||
return request.get("combination/pink/" + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团 取消开团
|
||||
*/
|
||||
export function postCombinationRemove(data) {
|
||||
return request.post("combination/remove", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 砍价列表
|
||||
*/
|
||||
export function getBargainList(data) {
|
||||
return request.get("bargain/list", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团轮播
|
||||
*
|
||||
*/
|
||||
export function getCombinationBannerList(data) {
|
||||
return request.get('combination/banner_list', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团人数
|
||||
*
|
||||
*/
|
||||
export function getPink(data) {
|
||||
return request.get('pink', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 砍价列表(已参与)
|
||||
* @param object data
|
||||
*/
|
||||
export function getBargainUserList(data) {
|
||||
return request.get('bargain/user/list', data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 砍价产品详情
|
||||
*/
|
||||
export function getBargainDetail(id) {
|
||||
return request.get("bargain/detail/" + id, {},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 砍价 开启砍价用户信息
|
||||
*/
|
||||
export function postBargainStartUser(data) {
|
||||
return request.post("bargain/start/user", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 砍价开启
|
||||
*/
|
||||
export function postBargainStart(bargainId) {
|
||||
return request.post("bargain/start", {
|
||||
bargainId: bargainId
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 砍价 帮助好友砍价
|
||||
*/
|
||||
export function postBargainHelp(data) {
|
||||
return request.post("bargain/help", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 砍价 砍掉金额
|
||||
*/
|
||||
export function postBargainHelpPrice(data) {
|
||||
return request.post("bargain/help/price", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 砍价 砍价帮
|
||||
*/
|
||||
export function postBargainHelpList(data) {
|
||||
return request.post("bargain/help/list", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 砍价 砍价帮总人数、剩余金额、进度条、已经砍掉的价格
|
||||
*/
|
||||
export function postBargainHelpCount(data) {
|
||||
return request.post("bargain/help/count", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 砍价 观看/分享/参与次数
|
||||
*/
|
||||
export function postBargainShare(bargainId) {
|
||||
return request.post("bargain/share", {
|
||||
bargainId: bargainId
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀产品时间区间
|
||||
*
|
||||
*/
|
||||
export function getSeckillIndexTime() {
|
||||
return request.get('seckill/index', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀产品列表
|
||||
* @param int time
|
||||
* @param object data
|
||||
*/
|
||||
export function getSeckillList(time, data) {
|
||||
return request.get('seckill/list/' + time, data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀产品详情
|
||||
* @param int id
|
||||
*/
|
||||
export function getSeckillDetail(id, data) {
|
||||
return request.get('seckill/detail/' + id,data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 砍价海报
|
||||
* @param object data
|
||||
*
|
||||
*/
|
||||
export function getBargainPoster(data) {
|
||||
return request.post('bargain/poster', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团海报
|
||||
* @param object data
|
||||
*
|
||||
*/
|
||||
export function getCombinationPoster(data) {
|
||||
return request.post('combination/poster', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 砍价取消
|
||||
*/
|
||||
export function getBargainUserCancel(data) {
|
||||
return request.post("bargain/user/cancel", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取活动小程序二维码
|
||||
*/
|
||||
export function activityCodeApi(type, id, data) {
|
||||
return request.get(`get_qrcode/${type}/${id}`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取砍价海报详细信息
|
||||
*/
|
||||
export function getCombinationPosterData(id) {
|
||||
return request.get("combination/poster_info/" + id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取砍价海报详细信息
|
||||
*/
|
||||
export function getBargainPosterData(id) {
|
||||
return request.get("bargain/poster_info/" + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分订单详细信息
|
||||
*/
|
||||
export function integralOrderConfirm(data) {
|
||||
return request.post('store_integral/order/confirm', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分订单创建
|
||||
*/
|
||||
export function integralOrderCreate(data) {
|
||||
return request.post('store_integral/order/create', data);
|
||||
}
|
||||
/**
|
||||
* 获取积分订单详情
|
||||
* @param string cartId
|
||||
*/
|
||||
export function integralOrderDetails(order) {
|
||||
return request.get(`store_integral/order/detail/${order}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分产品详情
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function getIntegralProductDetail(id) {
|
||||
return request.get('store_integral/detail/' + id, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分商城商品列表
|
||||
* @param object data
|
||||
*/
|
||||
export function getStoreIntegralList(data) {
|
||||
return request.get('store_integral/list', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分兑换列表
|
||||
* @param object data
|
||||
*/
|
||||
export function getIntegralOrderList(data) {
|
||||
return request.get('store_integral/order/list', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分兑换详情
|
||||
*/
|
||||
export function getLogisticsDetails(orderId) {
|
||||
return request.get(`store_integral/order/express/${orderId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分兑换订单确认收货
|
||||
* @param object data
|
||||
*/
|
||||
export function orderTake(data) {
|
||||
return request.post(`store_integral/order/take`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分兑换订单删除
|
||||
* @param object data
|
||||
*/
|
||||
export function orderDel(data) {
|
||||
return request.post(`store_integral/order/del`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 预售商品列表
|
||||
*/
|
||||
export function getAdvancellList(data) {
|
||||
return request.get("presale/list", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 限时折扣商品列表
|
||||
*/
|
||||
export function promotionsList(type,data) {
|
||||
return request.get("v2/promotions/productList/"+type, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 活动赠送商品
|
||||
*/
|
||||
export function giveInfo(id) {
|
||||
return request.get("v2/promotions/give_info/"+id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 秒杀商品二维码
|
||||
* @param {Object} id
|
||||
*/
|
||||
export function seckillQRCode(id) {
|
||||
return request.get(`seckill/code/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取拼团商品详情二维码
|
||||
* @param {Object} id
|
||||
*/
|
||||
export function combinationQRCode(id) {
|
||||
return request.get(`combination/detail_code/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取新人礼信息
|
||||
*
|
||||
*/
|
||||
export function newcomerInfo() {
|
||||
return request.get('marketing/newcomer/info', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新人专享商品
|
||||
*
|
||||
*/
|
||||
export function newcomerList(data) {
|
||||
return request.get('marketing/newcomer/product_list', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新人大礼包弹窗
|
||||
*
|
||||
*/
|
||||
export function newcomerGift(data) {
|
||||
return request.get('marketing/newcomer/gift');
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分商城
|
||||
*/
|
||||
export function getStoreIntegral(data) {
|
||||
return request.get("store_integral/index", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 积分商城积分范围导航
|
||||
*/
|
||||
export function getIntegralCategory() {
|
||||
return request.get("store_integral/category");
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页排行榜
|
||||
*/
|
||||
export function diyRankApi() {
|
||||
return request.get("diy/product_rank",{},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 礼品卡兑换
|
||||
*/
|
||||
export function giftCardGetInfoApi(data) {
|
||||
return request.post("card/gift_info", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 礼品卡兑换
|
||||
*/
|
||||
export function giftCardReceiveApi(data) {
|
||||
return request.post("card/receive", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 活动弹窗列表
|
||||
*/
|
||||
export function getActivityModalListApi() {
|
||||
return request.get("marketing/holiday_gift/list",{},{noAuth: true});
|
||||
}
|
||||
|
||||
/**
|
||||
* 活动弹窗观看上报
|
||||
*/
|
||||
export function getActivityModalRecordApi(data) {
|
||||
return request.post("marketing/holiday_gift/record",data);
|
||||
}
|
||||
715
api/admin.js
Normal file
715
api/admin.js
Normal file
@@ -0,0 +1,715 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 统计数据
|
||||
*/
|
||||
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 setAdminRefundRemark(data) {
|
||||
return request.post("admin/refund_order/remark", data, {
|
||||
login: true
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 订单详情
|
||||
*/
|
||||
export function getAdminOrderDetail(orderId) {
|
||||
return request.get("admin/order/detail/" + orderId, {}, {
|
||||
login: true
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 订单详情(退款)
|
||||
*/
|
||||
export function getAdminRefundDetail(orderId) {
|
||||
return request.get("admin/refund_order/detail/" + orderId, {}, {
|
||||
login: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单发货信息获取
|
||||
*/
|
||||
export function getAdminOrderDelivery(orderId) {
|
||||
return request.get(
|
||||
"admin/order/delivery/gain/" + orderId, {}, {
|
||||
login: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单发货保存
|
||||
*/
|
||||
export function setAdminOrderDelivery(id, data) {
|
||||
return request.post("admin/order/delivery/keep/" + id, 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
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取快递公司
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getLogistics(data) {
|
||||
return request.get("logistics", data, {
|
||||
login: false
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单核销
|
||||
* @returns {*}
|
||||
*/
|
||||
export function orderVerific(code, auth) {
|
||||
return request.post("admin/order/order_verific", {
|
||||
// verify_code,
|
||||
// is_confirm,
|
||||
code,
|
||||
auth,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取物流公司模板
|
||||
* @returns {*}
|
||||
*/
|
||||
export function orderExportTemp(data) {
|
||||
return request.get("admin/order/export_temp", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单打印默认配置
|
||||
* @returns {*}
|
||||
*/
|
||||
export function orderDeliveryInfo() {
|
||||
return request.get("admin/order/delivery_info");
|
||||
}
|
||||
|
||||
/**
|
||||
* 配送员列表
|
||||
* @returns {*}
|
||||
*/
|
||||
export function orderOrderDelivery() {
|
||||
return request.get("admin/order/delivery");
|
||||
}
|
||||
|
||||
|
||||
// 门店
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*/
|
||||
export function userInfo() {
|
||||
return request.get("store/staff/info");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 门店中心-订单统计
|
||||
*/
|
||||
export function orderInfo(data) {
|
||||
return request.get("store/order/statistics",data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 门店中心-统计菜单
|
||||
*/
|
||||
export function statisticsMenuApi(data) {
|
||||
return request.get("store/staff/statistics",data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 门店中心-详细数据列表
|
||||
*/
|
||||
export function getListApi(data) {
|
||||
return request.get("store/order/data",data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 门店中心-数据详情-列表
|
||||
*/
|
||||
export function getStatisticsListApi(type,data) {
|
||||
return request.get("store/staff/data/"+type,data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 门店中心-订单管理列表
|
||||
*/
|
||||
export function getOrderlistApi(data) {
|
||||
return request.get("store/order/list",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-订单管理列表(退款)
|
||||
*/
|
||||
export function getRefundlistApi(data) {
|
||||
return request.get("store/refund/list",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-订单管理备注
|
||||
*/
|
||||
export function getOrderreMarkApi(data) {
|
||||
return request.post("store/order/remark",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-订单管理备注(退款)
|
||||
*/
|
||||
export function getRefundMarkApi(data) {
|
||||
return request.post("store/refund/remark",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-订单管理改价
|
||||
*/
|
||||
export function getOrderPriceApi(data) {
|
||||
return request.post("store/order/price",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-订单管理确定付款
|
||||
*/
|
||||
export function getOrderOfflineApi(data) {
|
||||
return request.post("store/order/offline",data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 门店中心-去发货-用户
|
||||
*/
|
||||
export function getOrderDeliveryinfoApi(id) {
|
||||
return request.get("store/order/delivery_info/"+id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-去发货-获取快递公司
|
||||
*/
|
||||
export function getOrderExportApi(data) {
|
||||
return request.get("store/order/export_all", data, {
|
||||
login: false
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 门店中心-去发货-获取物流公司模板
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getOrderExportTemp(data) {
|
||||
return request.get("store/order/export_temp", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-去发货-订单发货保存
|
||||
*/
|
||||
export function setOrderDelivery(id, data) {
|
||||
return request.post("store/order/delivery/" + id, data, {
|
||||
login: true
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 门店中心-去发货-获取配送员列表
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getOrderDelivery() {
|
||||
return request.get("store/delivery/list");
|
||||
}
|
||||
/**
|
||||
* 门店中心-订单确认退款
|
||||
*/
|
||||
export function OrderRefund(data) {
|
||||
return request.post("store/order/refund", data, {
|
||||
login: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-订单详情
|
||||
*/
|
||||
export function OrderDetail(id) {
|
||||
return request.get("store/order/detail/"+id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-订单详情(退款)
|
||||
*/
|
||||
export function refundDetail(id) {
|
||||
return request.get("store/refund/detail/"+id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配送员-获取用户信息
|
||||
*/
|
||||
export function deliveryInfo(id) {
|
||||
return request.get("store/delivery/info");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配送员-获取配送统计数据
|
||||
*/
|
||||
export function deliveryStatistics(data) {
|
||||
return request.get("store/delivery/statistics",data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配送员-获取配送统计数据列表
|
||||
*/
|
||||
export function deliveryList(data) {
|
||||
return request.get("store/delivery/data",data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 配送员-获取订单列表数据列表
|
||||
*/
|
||||
export function deliveryOrderList(data) {
|
||||
return request.get("store/delivery/order",data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 门店中心-订单取消、删除
|
||||
*/
|
||||
export function OrderDel(id) {
|
||||
return request.delete("store/order/del/"+id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 门店中心-订单取消、取消
|
||||
*/
|
||||
export function OrderCancel(id) {
|
||||
return request.post("store/order/cancel/"+id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配送员-扫码核销获取订单信息
|
||||
*/
|
||||
export function orderWriteoffInfo(type,data) {
|
||||
return request.get("store/order/writeoff_info/"+type,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-购物车删除
|
||||
*/
|
||||
export function adminCartDel(uid,data) {
|
||||
return request.delete(`admin/order/cart/del/${uid}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-修改购物车数量
|
||||
*/
|
||||
export function adminCartNum(uid,data) {
|
||||
return request.post(`admin/order/cart/num/${uid}`,data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 配送员-核销订单获取商品信息
|
||||
*/
|
||||
export function orderCartInfo(data) {
|
||||
return request.post("store/order/cart_info",data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配送员-订单核销
|
||||
*/
|
||||
export function orderWriteoff(data) {
|
||||
return request.post("store/order/writeoff",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计管理-获取订单可拆分商品列表
|
||||
*/
|
||||
export function orderSplitInfo(id) {
|
||||
return request.get("admin/order/split_cart_info/"+id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计管理-提交
|
||||
*/
|
||||
export function orderSplitDelivery(id,data) {
|
||||
return request.put("admin/order/split_delivery/"+id,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计管理-退货退款
|
||||
*/
|
||||
export function orderRefundAgree(id) {
|
||||
return request.post("admin/order/refund_agree/"+id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-获取订单可拆分商品列表
|
||||
*/
|
||||
export function storeSplitInfo(id) {
|
||||
return request.get("store/order/split_cart_info/"+id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-提交
|
||||
*/
|
||||
export function storeSplitDelivery(id,data) {
|
||||
return request.put("store/order/split_delivery/"+id,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店中心-退货退款
|
||||
*/
|
||||
export function storeRefundAgree(id) {
|
||||
return request.post("store/order/refund_agree/"+id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-退款列表
|
||||
*/
|
||||
export function adminRefundList(data) {
|
||||
return request.get("admin/refund_order/list",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-商品列表
|
||||
*/
|
||||
export function adminProductList(data) {
|
||||
return request.get("admin/product/admin_list",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-商品列表-上下架
|
||||
*/
|
||||
export function productSetShow(data) {
|
||||
return request.post('admin/product/set_show',data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-商品列表-标签
|
||||
*/
|
||||
export function getProductLabel() {
|
||||
return request.get('admin/product/product_label');
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-商品列表-提交标签/分类
|
||||
*/
|
||||
export function postBatchProcess(data) {
|
||||
return request.post('admin/product/batch_process',data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-商品列表-修改库存价格
|
||||
*/
|
||||
export function postUpdateAttrs(id,data) {
|
||||
return request.post(`admin/product/update_attrs/${id}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-商品列表-获取规格
|
||||
*/
|
||||
export function getGetAttrs(id) {
|
||||
return request.get(`admin/product/get_attr/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-商品列表-获取分类
|
||||
*/
|
||||
export function getCategory() {
|
||||
return request.get(`admin/product/category`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-用户列表
|
||||
*/
|
||||
export function getUserList(data) {
|
||||
return request.get(`admin/user/list`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-修改余额、积分
|
||||
*/
|
||||
export function postUserUpdateOther(uid,data) {
|
||||
return request.post(`admin/user/update_other/${uid}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-分组列表
|
||||
*/
|
||||
export function getGroupList() {
|
||||
return request.get(`admin/user/group/list`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-修改用户信息
|
||||
*/
|
||||
export function postUserUpdate(data) {
|
||||
return request.post(`admin/user/update`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-优惠券
|
||||
*/
|
||||
export function getUserCoupon(data) {
|
||||
return request.get(`admin/user/coupon/grant`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-用户标签
|
||||
*/
|
||||
export function getUserLabel() {
|
||||
return request.get(`admin/user/label/0`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-等级列表
|
||||
*/
|
||||
export function getLevelList() {
|
||||
return request.get(`admin/user/level/list`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台-用户详情
|
||||
*/
|
||||
export function getUserInfo(uid) {
|
||||
return request.get(`admin/user/info/${uid}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-用户列表
|
||||
*/
|
||||
export function adminUserList(data) {
|
||||
return request.get("admin/user/list",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-商品分类
|
||||
*/
|
||||
export function adminCategory() {
|
||||
return request.get("admin/product/category");
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-商品列表
|
||||
*/
|
||||
export function adminProList(data) {
|
||||
return request.get("admin/product/list",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-加入购物车
|
||||
*/
|
||||
export function adminCartAdd(uid,data) {
|
||||
return request.post(`admin/order/cart/add/${uid}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-购物车列表
|
||||
*/
|
||||
export function adminCartList(uid,data) {
|
||||
return request.get(`admin/order/cart/${uid}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-用户地址列表
|
||||
*/
|
||||
export function adminUserAddressList(uid,data) {
|
||||
return request.get(`admin/user/address/list/${uid}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-订单确认
|
||||
*/
|
||||
export function orderConfirm(uid,data) {
|
||||
return request.post(`admin/order/confirm/${uid}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-订单计算
|
||||
*/
|
||||
export function postOrderComputed(key,uid,data) {
|
||||
return request.post(`admin/order/computed/${key}/${uid}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-获取用户可使用优惠券列表
|
||||
*/
|
||||
export function getCouponsOrderPrice(uid,data) {
|
||||
return request.get(`admin/order/coupons/${uid}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-订单查创建
|
||||
*/
|
||||
export function orderCreate(key,uid,data) {
|
||||
return request.post(`admin/order/create/${key}/${uid}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-订单收银台
|
||||
*/
|
||||
export function getCashierApi(uid,data) {
|
||||
return request.post(`admin/order/pay/${uid}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-轮询获取订单支付状态
|
||||
*/
|
||||
export function getPayStatusApi(data) {
|
||||
return request.get(`admin/order/pay/status`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-下单订单记录
|
||||
*/
|
||||
export function adminOrderRecordList(data) {
|
||||
return request.get(`admin/order/place/list`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 工作台折线图数据统计
|
||||
*/
|
||||
export function getOrderChart(data) {
|
||||
return request.get('admin/order/time/chart', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 工作台待发货等数据
|
||||
*/
|
||||
export function getOrderStaging() {
|
||||
return request.get('admin/order/staging');
|
||||
}
|
||||
|
||||
/**
|
||||
* 工作台今日订单数等数据
|
||||
*/
|
||||
export function getOrderTime(data) {
|
||||
return request.get('admin/order/time', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拆单退款
|
||||
* @param {Object} id
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function openRefund(id, data) {
|
||||
return request.post(`admin/order/open/refund/${id}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销订单商品列表
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function offOrderInfo(data) {
|
||||
return request.post(`admin/order/info`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销订单
|
||||
* @param {Object} order_id
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function orderWirteOff(order_id, data) {
|
||||
return request.post(`admin/order/wirteoff/${order_id}`,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单核销记录
|
||||
* @param {Object} id
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function orderWirteOffRecords(id, data) {
|
||||
return request.post(`admin/order/wirteoff/records/${id}`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代客下单-采购商列表
|
||||
*/
|
||||
export function adminChannelListApi(data) {
|
||||
return request.get("admin/user/channel/list", data);
|
||||
}
|
||||
495
api/api.js
Normal file
495
api/api.js
Normal file
@@ -0,0 +1,495 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
/**
|
||||
* 公共接口 ,优惠券接口 , 行业此讯 , 手机号码注册
|
||||
*
|
||||
*/
|
||||
export function getAjcaptcha(data) {
|
||||
return request.get("ajcaptcha", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
export function ajcaptchaCheck(data) {
|
||||
return request.post("ajcheck", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取主页数据 无需授权
|
||||
*
|
||||
*/
|
||||
export function getIndexData() {
|
||||
return request.get("v2/index", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取服务器类型
|
||||
*
|
||||
*/
|
||||
export function getServerType() {
|
||||
return request.get("v2/site_serve", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录授权login
|
||||
*
|
||||
*/
|
||||
export function getLogo() {
|
||||
return request.get('wechat/get_logo', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存form_id
|
||||
* @param string formId
|
||||
*/
|
||||
export function setFormId(formId) {
|
||||
return request.post("wechat/set_form_id", {
|
||||
formId: formId
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取优惠卷
|
||||
* @param int couponId
|
||||
*
|
||||
*/
|
||||
export function setCouponReceive(couponId) {
|
||||
return request.post('coupon/receive', {
|
||||
couponId: couponId
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 优惠券列表
|
||||
* @param object data
|
||||
*/
|
||||
export function getCoupons(data) {
|
||||
return request.get('v2/coupons', data, {
|
||||
noAuth: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 我的优惠券
|
||||
* @param int types 0全部 1未使用 2已使用
|
||||
*/
|
||||
export function getUserCoupons(types, data) {
|
||||
return request.get('coupons/user/' + types, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页新人优惠券
|
||||
*
|
||||
*/
|
||||
export function getNewCoupon() {
|
||||
return request.get('v2/new_coupon')
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章分类列表
|
||||
*
|
||||
*/
|
||||
export function getArticleCategoryList() {
|
||||
return request.get('article/category/list', {}, {
|
||||
noAuth: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章列表
|
||||
* @param int cid
|
||||
*
|
||||
*/
|
||||
export function getArticleList(cid, data) {
|
||||
return request.get('article/list/' + cid, data, {
|
||||
noAuth: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章 热门列表
|
||||
*
|
||||
*/
|
||||
export function getArticleHotList() {
|
||||
return request.get('article/hot/list', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章 轮播列表
|
||||
*
|
||||
*/
|
||||
export function getArticleBannerList() {
|
||||
return request.get('article/banner/list', {}, {
|
||||
noAuth: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章详情
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function getArticleDetails(id) {
|
||||
return request.get('article/details/' + id, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号+验证码登录接口
|
||||
* @param object data
|
||||
*/
|
||||
export function loginMobile(data) {
|
||||
return request.post('login/mobile', data, {
|
||||
noAuth: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取短信KEY
|
||||
* @param object phone
|
||||
*/
|
||||
export function verifyCode() {
|
||||
return request.get('verify_code', {}, {
|
||||
noAuth: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码发送
|
||||
* @param object phone
|
||||
*/
|
||||
export function registerVerify(data) {
|
||||
return request.post('register/verify',data, {
|
||||
noAuth: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号注册
|
||||
* @param object data
|
||||
*
|
||||
*/
|
||||
export function phoneRegister(data) {
|
||||
return request.post('register', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号修改密码
|
||||
* @param object data
|
||||
*
|
||||
*/
|
||||
export function phoneRegisterReset(data) {
|
||||
return request.post('register/reset', data, {
|
||||
noAuth: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号+密码登录
|
||||
* @param object data
|
||||
*
|
||||
*/
|
||||
export function phoneLogin(data) {
|
||||
return request.post('login', data, {
|
||||
noAuth: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换H5登录
|
||||
* @param object data
|
||||
*/
|
||||
// #ifdef MP
|
||||
export function switchH5Login() {
|
||||
return request.post('switch_h5', {
|
||||
'from': 'routine'
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
/*
|
||||
* h5切换公众号登陆
|
||||
* */
|
||||
// #ifdef H5
|
||||
export function switchH5Login() {
|
||||
return request.post("switch_h5", {
|
||||
'from': "wechat"
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* 绑定手机号
|
||||
*
|
||||
*/
|
||||
export function bindingPhone(data) {
|
||||
return request.post('binding', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 绑定手机号
|
||||
*
|
||||
*/
|
||||
export function bindingUserPhone(data) {
|
||||
return request.post('user/binding', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登錄
|
||||
*
|
||||
*/
|
||||
export function logout() {
|
||||
return request.get('logout');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订阅消息id
|
||||
*/
|
||||
export function getTemlIds() {
|
||||
return request.get('wechat/teml_ids', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页拼团数据
|
||||
*/
|
||||
export function pink() {
|
||||
return request.get('pink', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取城市信息
|
||||
*/
|
||||
export function getCity() {
|
||||
return request.get('city_list', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取省市区街道
|
||||
*/
|
||||
export function getCityData(pid) {
|
||||
return request.get('city', {'pid':pid}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取小程序观看列表
|
||||
*/
|
||||
export function getLiveList(page, limit) {
|
||||
return request.get('wechat/live', {
|
||||
page,
|
||||
limit
|
||||
}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取首页DIY;
|
||||
*/
|
||||
export function getDiy(id) {
|
||||
return request.get('diy/get_diy/' + id, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键换色;
|
||||
*/
|
||||
export function colorChange(name) {
|
||||
return request.get('v2/diy/color_change/' + name, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公众号关注
|
||||
* @returns {*}
|
||||
*/
|
||||
export function follow() {
|
||||
return request.get("wechat/follow", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更换手机号码
|
||||
* @returns {*}
|
||||
*/
|
||||
export function updatePhone(data) {
|
||||
return request.post("user/updatePhone", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页优惠券弹窗
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getCouponV2() {
|
||||
return request.get("v2/get_today_coupon", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新用户优惠券弹窗
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getCouponNewUser() {
|
||||
return request.get("v2/new_coupon", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页快速选择数据
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function category(data) {
|
||||
return request.get("category", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 个人搜索历史
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function searchList(data) {
|
||||
return request.get('v2/user/search_list', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除搜索历史
|
||||
*/
|
||||
export function clearSearch() {
|
||||
return request.get('v2/user/clean_search');
|
||||
}
|
||||
|
||||
/**
|
||||
* App微信登录
|
||||
* @returns {*}
|
||||
*/
|
||||
export function wechatAppAuth(data) {
|
||||
return request.post("wechat/app_auth", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服配置
|
||||
*/
|
||||
export function customerType() {
|
||||
return request.get('get_customer_type',{},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取开屏广告
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getOpenAdv(data) {
|
||||
return request.get("get_open_adv", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取版权
|
||||
*
|
||||
*/
|
||||
export function copyRight() {
|
||||
return request.get('get_copyright', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
*/
|
||||
export function diyUserInfo() {
|
||||
return request.get('diy/user_info', {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新人专享
|
||||
*
|
||||
*/
|
||||
export function newcomerList(data) {
|
||||
return request.get('diy/newcomer_list', data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取DIY版本接口
|
||||
* @param {Object} id
|
||||
*/
|
||||
export function getDiyVersion(id) {
|
||||
return request.get(`diy/diy_version/${id}`, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品分类类版本
|
||||
*/
|
||||
export function getCategoryVersion() {
|
||||
return request.get('category_version', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function getCouponsNum() {
|
||||
return request.get('coupons/user/num', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
export function getSign() {
|
||||
return request.get('diy/sign', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
export function getSuspended() {
|
||||
return request.get('diy/get_suspended', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
119
api/community.js
Normal file
119
api/community.js
Normal file
@@ -0,0 +1,119 @@
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
export function getCommunityConfig() {
|
||||
return request.get('community/config', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
export function getTopicApi(data) {
|
||||
return request.get('community/topic', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
export function getProductApi(data) {
|
||||
return request.get('community/product_list', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
export function communitySaveApi(data) {
|
||||
return request.post('community/community_save', data);
|
||||
}
|
||||
|
||||
export function communityInfoApi(id) {
|
||||
return request.get(`community/detail/${id}`,{},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
export function communityUpdateApi(id,data) {
|
||||
return request.post(`community/community_update/${id}`, data);
|
||||
}
|
||||
|
||||
export function communityListApi(data) {
|
||||
return request.get(`community/list`,data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
export function communityLikeApi(id, data) {
|
||||
return request.post(`community/community_like/${id}`, data);
|
||||
}
|
||||
|
||||
export function communityReplySaveApi(data) {
|
||||
return request.post(`community/comment/save`, data);
|
||||
}
|
||||
|
||||
export function communityReplyListApi(data) {
|
||||
return request.get(`community/comment/list`, data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
export function communityReplyLikeApi(id,data) {
|
||||
return request.post(`community/comment_like/${id}`, data);
|
||||
}
|
||||
|
||||
export function communityUserInfoApi(id) {
|
||||
return request.get(`community/user_info/${id}`);
|
||||
}
|
||||
|
||||
export function communityUpdateDescApi(data) {
|
||||
return request.post(`community/update_desc`, data);
|
||||
}
|
||||
|
||||
export function communitySetInsterestApi(uid,data) {
|
||||
return request.post(`community/set_interest/${uid}`, data);
|
||||
}
|
||||
|
||||
export function communityLikeListApi(params,) {
|
||||
return request.get(`community/like_list`, params);
|
||||
}
|
||||
|
||||
export function communityFlowListApi(type, params) {
|
||||
return request.get(`community/follow_list/${type}`, params);
|
||||
}
|
||||
|
||||
export function communityFlowIndexApi() {
|
||||
return request.get(`community/follow`);
|
||||
}
|
||||
|
||||
export function communityFriendListApi(params) {
|
||||
return request.get(`community/user_friend`, params);
|
||||
}
|
||||
|
||||
export function communityRecommendListApi(params) {
|
||||
return request.get(`community/recommend_list`, params);
|
||||
}
|
||||
|
||||
export function communityElegantListApi(params) {
|
||||
return request.get(`community/elegant_list`, params);
|
||||
}
|
||||
|
||||
export function communityDeleteApi(id) {
|
||||
return request.delete(`community/community_delete/${id}`);
|
||||
}
|
||||
|
||||
export function communityShareApi(id) {
|
||||
return request.get(`community/share/${id}`);
|
||||
}
|
||||
|
||||
export function communityReplyDeleteApi(id) {
|
||||
return request.delete(`community/comment_delete/${id}`);
|
||||
}
|
||||
|
||||
export function communityBrowseApi(id) {
|
||||
return request.put(`community/browse/${id}`);
|
||||
}
|
||||
|
||||
export function communityTopicCountApi(id) {
|
||||
return request.get(`community/topic_count/${id}`,{},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
export function communityMessageApi(data) {
|
||||
return request.get(`community/message`, data);
|
||||
}
|
||||
19
api/esp.js
Normal file
19
api/esp.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* erp设置
|
||||
*
|
||||
*/
|
||||
export function erpConfig(id,data) {
|
||||
return request.get('admin/erp/config');
|
||||
}
|
||||
123
api/kefu.js
Normal file
123
api/kefu.js
Normal file
@@ -0,0 +1,123 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 客服登录
|
||||
* @param data object 用户账号密码
|
||||
*/
|
||||
export function kefuLogin(data) {
|
||||
return request.post("login", data, { noAuth : true,kefu:true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取左侧客服聊天用户列表
|
||||
* @constructor
|
||||
*/
|
||||
export function record (data) {
|
||||
return request.get("user/record", data, { noAuth : true,kefu:true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服话术
|
||||
* @constructor
|
||||
*/
|
||||
export function speeChcraft (data) {
|
||||
return request.get("service/speechcraft", data, { noAuth : true,kefu:true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服转接列表
|
||||
* @constructor
|
||||
*/
|
||||
export function transferList (data) {
|
||||
return request.get("service/transfer_list", data, { noAuth : true,kefu:true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品购买记录
|
||||
* @constructor
|
||||
*/
|
||||
export function productCart (id,data) {
|
||||
return request.get("product/cart/"+id,data, { noAuth : true,kefu:true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 热销商品
|
||||
* @constructor
|
||||
*/
|
||||
export function productHot (id,data) {
|
||||
return request.get("product/hot/"+id,data, { noAuth : true,kefu:true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品足记
|
||||
* @constructor
|
||||
*/
|
||||
export function productVisit (id,data) {
|
||||
return request.get("product/visit/"+id,data, { noAuth : true,kefu:true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服用户聊天列表
|
||||
* @constructor
|
||||
*/
|
||||
export function serviceList (data) {
|
||||
return request.get("service/list",data, { noAuth : true,kefu:true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服转接
|
||||
* @constructor
|
||||
*/
|
||||
export function serviceTransfer (data) {
|
||||
return request.post("service/transfer",data, { noAuth : true,kefu:true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服详细信息
|
||||
* @constructor
|
||||
*/
|
||||
export function serviceInfo (data) {
|
||||
return request.get("service/info",data, { noAuth : true,kefu:true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服反馈头部信息
|
||||
* @constructor
|
||||
*/
|
||||
export function serviceFeedBack () {
|
||||
return request.get("user/service/feedback");
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服反馈
|
||||
* @constructor
|
||||
*/
|
||||
export function feedBackPost (data) {
|
||||
return request.post("user/service/feedback", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测登录code
|
||||
* @constructor
|
||||
*/
|
||||
export function codeStauts (data) {
|
||||
return request.get("user/code",data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服扫码登录code
|
||||
* @constructor
|
||||
*/
|
||||
export function kefuScanLogin (data) {
|
||||
return request.post("user/code",data);
|
||||
}
|
||||
43
api/lottery.js
Normal file
43
api/lottery.js
Normal file
@@ -0,0 +1,43 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 获取抽奖详情信息
|
||||
*
|
||||
*/
|
||||
export function getLotteryData(type) {
|
||||
return request.get(`v2/lottery/info/${type}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 参与抽奖
|
||||
*
|
||||
*/
|
||||
export function startLottery(data) {
|
||||
return request.post(`v2/lottery`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 领奖
|
||||
*
|
||||
*/
|
||||
export function receiveLottery(data) {
|
||||
return request.post(`v2/lottery/receive`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取中奖记录
|
||||
*
|
||||
*/
|
||||
export function getLotteryList(data) {
|
||||
return request.get(`v2/lottery/record`, data);
|
||||
}
|
||||
435
api/order.js
Normal file
435
api/order.js
Normal file
@@ -0,0 +1,435 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 获取购物车列表
|
||||
* @param numType boolean true 购物车数量,false=购物车产品数量
|
||||
*/
|
||||
export function getCartCounts(numType, storeId, is_channel) {
|
||||
return request.get("cart/count", {
|
||||
numType: numType === undefined ? 0 : numType,
|
||||
store_id: storeId,
|
||||
is_channel: is_channel || "",
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取购物车列表
|
||||
*
|
||||
*/
|
||||
export function getCartList(data) {
|
||||
return request.get("cart/list", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 购物车计算
|
||||
*
|
||||
*/
|
||||
export function cartCompute(data) {
|
||||
return request.post("cart/compute", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改购物车
|
||||
*
|
||||
*/
|
||||
export function getResetCart(data) {
|
||||
return request.post("v2/reset_cart", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改购物车数量
|
||||
* @param int cartId 购物车id
|
||||
* @param int number 修改数量
|
||||
*/
|
||||
export function changeCartNum(cartId, number, type = 1) {
|
||||
return request.post("cart/num", {
|
||||
id: cartId,
|
||||
number,
|
||||
type,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 清除购物车
|
||||
* @param object ids join(',') 切割成字符串
|
||||
*/
|
||||
export function cartDel(ids) {
|
||||
if (typeof ids === "object") ids = ids.join(",");
|
||||
return request.post("cart/del", {
|
||||
ids: ids,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 订单列表
|
||||
* @param object data
|
||||
*/
|
||||
export function getOrderList(data) {
|
||||
return request.get("order/list", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新订单列表 2.1版本
|
||||
* @param object data
|
||||
*/
|
||||
export function getNewOrderList(data) {
|
||||
return request.get("order/refund/list", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单产品信息
|
||||
* @param string unique
|
||||
*/
|
||||
export function orderProduct(unique) {
|
||||
return request.post("order/product", {
|
||||
unique: unique,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单评价
|
||||
* @param object data
|
||||
*
|
||||
*/
|
||||
export function orderComment(data) {
|
||||
return request.post("order/comment", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单支付
|
||||
* @param object data
|
||||
*/
|
||||
export function orderPay(data) {
|
||||
return request.post("order/pay", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单统计数据
|
||||
*/
|
||||
export function orderData(data) {
|
||||
return request.get("order/data", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单取消
|
||||
* @param string id
|
||||
*
|
||||
*/
|
||||
export function orderCancel(id) {
|
||||
return request.post("order/cancel", {
|
||||
id: id,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除已完成订单
|
||||
* @param string uni
|
||||
*
|
||||
*/
|
||||
export function orderDel(uni) {
|
||||
return request.post("order/del", {
|
||||
uni: uni,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除已退款和拒绝退款的订单
|
||||
* @param string uni
|
||||
*
|
||||
*/
|
||||
export function refundOrderDel(uni) {
|
||||
return request.get("order/refund/del/" + uni, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单详情
|
||||
* @param string uni
|
||||
*/
|
||||
export function getOrderDetail(uni) {
|
||||
return request.get("order/detail/" + uni);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款订单详情
|
||||
* @param string uni
|
||||
*/
|
||||
export function getRefundOrderDetail(uni) {
|
||||
return request.get("order/refund/detail/" + uni);
|
||||
}
|
||||
|
||||
/**
|
||||
* 放弃申请退款
|
||||
* @param string uni
|
||||
*/
|
||||
export function cancelRefundOrder(uni) {
|
||||
return request.post("order/refund/cancel/" + uni);
|
||||
}
|
||||
|
||||
/**
|
||||
* 再次下单
|
||||
* @param string uni
|
||||
*
|
||||
*/
|
||||
export function orderAgain(uni) {
|
||||
return request.post("order/again", {
|
||||
uni: uni,
|
||||
});
|
||||
}
|
||||
|
||||
//再次申请售后
|
||||
export function orderRefundAgain(id) {
|
||||
return request.post("order/refund/again/" + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单收货
|
||||
* @param string uni
|
||||
*
|
||||
*/
|
||||
export function orderTake(uni) {
|
||||
return request.post("order/take", {
|
||||
uni: uni,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单查询物流信息
|
||||
* @returns {*}
|
||||
*/
|
||||
export function express(uni, type) {
|
||||
return request.get("order/express/" + uni + (type ? "/" + type : ""));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取退款理由
|
||||
*
|
||||
*/
|
||||
export function ordeRefundReason() {
|
||||
return request.get("order/refund/reason");
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单退款审核
|
||||
* @param object data
|
||||
*/
|
||||
export function orderRefundVerify(data) {
|
||||
return request.post("order/refund/verify", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单确认获取订单详细信息
|
||||
* @param string cartId
|
||||
*/
|
||||
export function orderConfirm(
|
||||
cartId,
|
||||
news,
|
||||
addressId,
|
||||
shippingType,
|
||||
store_id,
|
||||
couponId,
|
||||
luckRecordId,
|
||||
isSendGift
|
||||
) {
|
||||
return request.post("order/confirm", {
|
||||
cartId,
|
||||
new: news,
|
||||
addressId,
|
||||
shipping_type: shippingType,
|
||||
store_id,
|
||||
couponId: couponId,
|
||||
luckRecordId,
|
||||
is_send_gift: isSendGift,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前金额能使用的优惠卷
|
||||
* @param string price
|
||||
*
|
||||
*/
|
||||
export function getCouponsOrderPrice(price, data) {
|
||||
return request.get("coupons/order/" + price, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单创建
|
||||
* @param string key
|
||||
* @param object data
|
||||
*
|
||||
*/
|
||||
export function orderCreate(key, data) {
|
||||
return request.post("order/create/" + key, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算订单金额
|
||||
* @param key
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export function postOrderComputed(key, data) {
|
||||
return request.post("order/computed/" + key, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单优惠券
|
||||
* @param key
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export function orderCoupon(orderId) {
|
||||
return request.post("v2/order/product_coupon/" + orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算会员线下付款金额
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function offlineCheckPrice(data) {
|
||||
return request.post("order/offline/check/price", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 线下扫码付款
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function offlineCreate(data) {
|
||||
return request.post("order/offline/create", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付方式开关
|
||||
*/
|
||||
export function orderOfflinePayType() {
|
||||
return request.get("order/offline/pay/type");
|
||||
}
|
||||
|
||||
/**
|
||||
* 开票记录
|
||||
*/
|
||||
export function orderInvoiceList(data) {
|
||||
return request.get("v2/order/invoice_list", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开票订单详情
|
||||
* @param {Object} id
|
||||
*/
|
||||
export function orderInvoiceDetail(orderId, id) {
|
||||
return request.get(`v2/order/invoice_detail/${orderId}/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝支付
|
||||
* @param {Object} key
|
||||
* @param {Object} quitUrl
|
||||
*/
|
||||
export function aliPay(key, quitUrl) {
|
||||
return request.get(
|
||||
"ali_pay",
|
||||
{
|
||||
key,
|
||||
quitUrl,
|
||||
},
|
||||
{
|
||||
noAuth: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退货物流单号提交
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function refundExpress(data) {
|
||||
return request.post("order/refund/express", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分类购物车列表
|
||||
*/
|
||||
export function vcartList(data) {
|
||||
return request.get("v2/cart_list", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付订单
|
||||
*/
|
||||
export function payCashier(storeId) {
|
||||
return request.get(`order/pay_cashier?store_id=${storeId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款商品列表
|
||||
*/
|
||||
export function refundGoodsList(orderId) {
|
||||
return request.get(`order/refund/cart_info/${orderId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款商品列表
|
||||
*/
|
||||
export function postRefundGoods(data) {
|
||||
return request.post(`order/refund/cart_info`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款商品提交
|
||||
*/
|
||||
export function returnGoodsSubmit(id, data) {
|
||||
return request.post(`order/refund/apply/${id}`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认订单详情(是否显示快递配送)
|
||||
*/
|
||||
export function checkShipping(data) {
|
||||
return request.post(`order/check_shipping`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配送订单详情
|
||||
*/
|
||||
export function deliveryDetail(id) {
|
||||
return request.get(`delivery_order/detail/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台订单信息
|
||||
* @param object data
|
||||
*/
|
||||
export function getCashierOrder(orderId, type) {
|
||||
return request.get(`order/cashier/${orderId}/${type}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单下单奖励
|
||||
* @param object data
|
||||
*/
|
||||
export function getOrderPrizeApi(orderId) {
|
||||
return request.post(`order/prize/${orderId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 礼品订单详情
|
||||
* @param string uni
|
||||
*/
|
||||
export function getSendGiftOrderDetail(id) {
|
||||
return request.get("order/send_gift_detail/" + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取礼物
|
||||
* @param orderId
|
||||
* @param data
|
||||
*/
|
||||
export function orderReceiveGift(orderId, data) {
|
||||
return request.post("order/receive_gift/" + orderId, data);
|
||||
}
|
||||
259
api/public.js
Normal file
259
api/public.js
Normal file
@@ -0,0 +1,259 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
import wechat from "@/libs/wechat.js";
|
||||
|
||||
/**
|
||||
* 获取微信sdk配置
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getWechatConfig() {
|
||||
return request.get(
|
||||
"wechat/config", {
|
||||
url: wechat.signLink()
|
||||
}, {
|
||||
noAuth: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序手机号登录
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function phoneLogin(data) {
|
||||
return request.post('v2/routine/phone_login', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序绑定手机号(最新)
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function routineBindingPhone(data) {
|
||||
return request.post('v2/routine/auth_binding_phone', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 公众号绑定手机号
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function wechatBindingPhone(data) {
|
||||
return request.post('v2/wechat/auth_binding_phone', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* code生成用户
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
export function authType(data) {
|
||||
return request.get("v2/routine/auth_type", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 公众号登录
|
||||
* @returns {*}
|
||||
*/
|
||||
export function wechatAuthLogin(data) {
|
||||
return request.get("v2/wechat/auth_login", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录授权login
|
||||
*
|
||||
*/
|
||||
export function getLogo() {
|
||||
return request.get('wechat/get_logo', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序用户登录
|
||||
* @param data object 小程序用户登陆信息
|
||||
*/
|
||||
export function login(data) {
|
||||
return request.post("wechat/mp_auth", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 静默授权
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function silenceAuth(data) {
|
||||
//#ifdef MP
|
||||
return request.get("v2/wechat/silence_auth", data, {
|
||||
noAuth: true
|
||||
});
|
||||
//#endif
|
||||
//#ifdef H5
|
||||
return request.get("v2/wechat/wx_silence_auth", data, {
|
||||
noAuth: true
|
||||
});
|
||||
//#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getShare() {
|
||||
return request.get("share", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关注海报
|
||||
* @returns {*}
|
||||
*/
|
||||
export function follow() {
|
||||
return request.get("wechat/follow", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 授权登录
|
||||
* @returns {*}
|
||||
*/
|
||||
export function authLogin(data) {
|
||||
return request.get("v2/routine/auth_login", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片base64
|
||||
* @retins {*}
|
||||
* */
|
||||
export function imageBase64(image, code) {
|
||||
return request.post(
|
||||
"image_base64", {
|
||||
image: image,
|
||||
code: code
|
||||
}, {
|
||||
noAuth: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动复制口令功能
|
||||
* @returns {*}
|
||||
*/
|
||||
export function copyWords() {
|
||||
return request.get("copy_words", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商城是否强制绑定手机号
|
||||
*/
|
||||
export function getShopConfig() {
|
||||
return request.get('v2/bind_status', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序绑定手机号
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function getUserPhone(data) {
|
||||
return request.post('v2/auth_bindind_phone', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序用户登录
|
||||
* @param data object 小程序用户登陆信息
|
||||
*/
|
||||
export function routineLogin(data) {
|
||||
return request.get("v2/wechat/routine_auth", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取微信sdk配置
|
||||
* @returns {*}
|
||||
*/
|
||||
export function wechatAuthV2(code, spid) {
|
||||
return request.get(
|
||||
"v2/wechat/auth", {
|
||||
code: code,
|
||||
spread_spid: spid
|
||||
}, {
|
||||
noAuth: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组件底部菜单
|
||||
* @param data object 获取组件底部菜单
|
||||
*/
|
||||
export function getNavigation(data) {
|
||||
return request.get("navigation", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
export function getSubscribe() {
|
||||
return request.get("subscribe", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* iframe登录
|
||||
*
|
||||
*/
|
||||
export function remoteRegister(data) {
|
||||
return request.get(`remote_register`, data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 公共配置接口
|
||||
*
|
||||
*/
|
||||
export function systemConfigApi() {
|
||||
return request.get("system/config", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取版本信息
|
||||
* @param 系统类型
|
||||
*/
|
||||
export function getUpdateInfo(type) {
|
||||
return request.get("get_new_app/" + type, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
103
api/short-video.js
Normal file
103
api/short-video.js
Normal file
@@ -0,0 +1,103 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 短视频列表
|
||||
*
|
||||
*/
|
||||
export function videoList(data) {
|
||||
return request.get(
|
||||
"marketing/short_video",data,{ noAuth: true }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* diy短视频列表
|
||||
*
|
||||
*/
|
||||
export function diyVideoList(data) {
|
||||
return request.get(
|
||||
"diy/video_list",data,{ noAuth: true }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 短视频点赞、收藏、分享
|
||||
*
|
||||
*/
|
||||
export function markeVideo(type,id) {
|
||||
return request.get(
|
||||
`marketing/short_video/${type}/${id}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 短视频评论列表
|
||||
*
|
||||
*/
|
||||
export function commentList(id,data) {
|
||||
return request.get(
|
||||
`marketing/short_video/comment/${id}`,data
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 短视频评价、评价回复
|
||||
*
|
||||
*/
|
||||
export function markeComment(data) {
|
||||
return request.post(
|
||||
`marketing/short_video/comment/${data.id}/${data.pid}`,{content:data.content}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 短视频评价回复列表
|
||||
*
|
||||
*/
|
||||
export function replyCommentList(pid,data) {
|
||||
return request.get(
|
||||
`marketing/short_video/comment_reply/${pid}`,data
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 视频评论点赞
|
||||
*
|
||||
*/
|
||||
export function replyCommentLike(type,id) {
|
||||
return request.get(
|
||||
`marketing/short_video/comment/${type}/${id}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 短视频关联商品列表
|
||||
*
|
||||
*/
|
||||
export function videoProduct(id,data) {
|
||||
return request.get(
|
||||
`marketing/short_video/product/${id}`,data
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 热门视频信息
|
||||
*
|
||||
*/
|
||||
export function videoInfo(id) {
|
||||
return request.get(
|
||||
`marketing/short_video/info/${id}`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
406
api/store.js
Normal file
406
api/store.js
Normal file
@@ -0,0 +1,406 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 获取产品详情
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function getProductDetail(id,data) {
|
||||
return request.get('product/detail/' + id, data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取产品活动相关详情
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function getProductCtivity(id,data) {
|
||||
return request.get('product/detail/activity/' + id, data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取产品详情中推荐商品列表
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function getProductRecommend(id) {
|
||||
return request.get('product/detail/recommend/' + id, {},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 产品分享二维码 推广员
|
||||
* @param int id
|
||||
*/
|
||||
// #ifdef H5 || APP-PLUS
|
||||
export function getProductCode(id) {
|
||||
return request.get('product/code/' + id, {});
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
export function getProductCode(id) {
|
||||
return request.get('product/code/' + id, {
|
||||
user_type: 'routine'
|
||||
},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* 添加收藏
|
||||
* @param int id
|
||||
* @param string category product=普通产品,product_seckill=秒杀产品
|
||||
*/
|
||||
export function collectAdd(id, category) {
|
||||
return request.post('collect/add', {
|
||||
id: id,
|
||||
'category': category === undefined ? 'product' : category
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除收藏产品
|
||||
* @param int id
|
||||
* @param string category product=普通产品,product_seckill=秒杀产品
|
||||
*/
|
||||
export function collectDel(id, category) {
|
||||
return request.post('collect/del', {
|
||||
id: id,
|
||||
category: category === undefined ? 'product' : category
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 购车添加
|
||||
*
|
||||
*/
|
||||
export function postCartAdd(data) {
|
||||
return request.post('cart/add', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分类列表
|
||||
*
|
||||
*/
|
||||
export function getCategoryList() {
|
||||
return request.get('category', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品详情diy
|
||||
* @param {*} data
|
||||
*/
|
||||
export function diyProductApi() {
|
||||
return request.get('v2/diy/product_detail', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取产品列表
|
||||
* @param object data
|
||||
*/
|
||||
export function getProductslist(data) {
|
||||
return request.get('products', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取推荐产品
|
||||
*
|
||||
*/
|
||||
export function getProductHot(data) {
|
||||
return request.get("product/hot", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 批量收藏
|
||||
*
|
||||
* @param object id 产品编号 join(',') 切割成字符串
|
||||
* @param string category
|
||||
*/
|
||||
export function collectAll(id, category) {
|
||||
return request.post('collect/all', {
|
||||
id: id,
|
||||
category: category === undefined ? 'product' : category
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页产品的轮播图和产品信息
|
||||
* @param int type
|
||||
*
|
||||
*/
|
||||
export function getGroomList(type, data) {
|
||||
return request.get('groom/list/' + type, data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收藏列表
|
||||
* @param object data
|
||||
*/
|
||||
export function getCollectUserList(data) {
|
||||
return request.get('collect/user', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览记录列表
|
||||
* @param object data
|
||||
*/
|
||||
export function getVisitList(data) {
|
||||
return request.get('user/visit_list', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览记录列表-删除
|
||||
* @param object data
|
||||
*/
|
||||
export function deleteVisitList(data) {
|
||||
return request.delete('user/visit', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取产品评论
|
||||
* @param int id
|
||||
* @param object data
|
||||
*
|
||||
*/
|
||||
export function getReplyList(id, data) {
|
||||
return request.get('v2/reply/list/' + id, data,{noAuth: true})
|
||||
}
|
||||
|
||||
/**
|
||||
* 产品评价数量和好评度
|
||||
* @param int id
|
||||
*/
|
||||
export function getReplyConfig(id) {
|
||||
return request.get('reply/config/' + id,{},{noAuth: true});
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论点赞
|
||||
* @param int id
|
||||
*/
|
||||
export function getReplyPraise(id) {
|
||||
return request.post('reply/reply_praise/' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消评论点赞
|
||||
* @param int id
|
||||
*/
|
||||
export function getUnReplyPraise(id) {
|
||||
return request.post('reply/un_reply_praise/' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取评论详情
|
||||
* @param int id
|
||||
*/
|
||||
export function getReplyInfo(id) {
|
||||
return request.get('reply/info/' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取评论回复列表
|
||||
* @param int id
|
||||
*/
|
||||
export function getReplyComment(id,data) {
|
||||
return request.get('reply/comment/' + id,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论回复点赞
|
||||
* @param int id
|
||||
*/
|
||||
export function postReplyPraise(id) {
|
||||
return request.post('reply/praise/' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消评论回复点赞
|
||||
* @param int id
|
||||
*/
|
||||
export function postUnReplyPraise(id) {
|
||||
return request.post('reply/un_praise/' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存商品评价回复
|
||||
* @param int id
|
||||
*/
|
||||
export function replyComment(id,data) {
|
||||
return request.post('reply/comment/' + id,data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取搜索关键字获取
|
||||
*
|
||||
*/
|
||||
export function getSearchKeyword(data) {
|
||||
return request.get('search/keyword', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取搜索关键字获取
|
||||
*
|
||||
*/
|
||||
export function getHotWordApi() {
|
||||
return request.get('search/hot_keyword', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取搜索销量评分商品列表
|
||||
*
|
||||
*/
|
||||
export function getSearchRecommendApi(type) {
|
||||
return request.get(`search/recommend/${type}`, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店列表
|
||||
* @returns {*}
|
||||
*/
|
||||
export function storeListApi(data) {
|
||||
return request.get("store_list", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐列表
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function storeDiscountsList(id) {
|
||||
return request.get('store_discounts/list/' + id, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 购车添加、减少、修改
|
||||
*
|
||||
*/
|
||||
export function postCartNum(data) {
|
||||
return request.post('v2/set_cart_num', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取首页的属性
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getAttr(id,type, data) {
|
||||
return request.get("v2/get_attr/"+id+"/"+type, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取店员推广微信会员卡二维码
|
||||
*/
|
||||
export function storeCardApi() {
|
||||
return request.get("store/staff/card/code");
|
||||
}
|
||||
|
||||
/**
|
||||
* 分类列表-品牌列表
|
||||
*/
|
||||
export function searchFilterApi(data) {
|
||||
return request.get("search/filter",data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 分类列表-同级分类
|
||||
*/
|
||||
export function levelCategoryApi(data) {
|
||||
return request.get("level_category",data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新人专享商品详情
|
||||
*/
|
||||
export function newcomerDetail(id) {
|
||||
return request.get("marketing/newcomer/product_detail/"+id,{},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 排行榜商品分类
|
||||
*/
|
||||
export function rankCategoryApi() {
|
||||
return request.get("product/rank/category",{},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 排行榜商品列表
|
||||
* @param {type} type 1:销量 2:评分
|
||||
* @param {data} 分页
|
||||
*/
|
||||
export function rankListApi(type, data) {
|
||||
return request.get(`product/rank/${type}`,data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 搭配够商品列表
|
||||
* @param {id} 商品id
|
||||
* @param {data} 分页参数
|
||||
*/
|
||||
export function matchPayListApi(id, data) {
|
||||
return request.get(`store_discounts/list/${id}`,data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品短链
|
||||
* @param {id} 商品id
|
||||
*/
|
||||
export function getShortLinkApi(id) {
|
||||
return request.get(`product/short_link/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 礼品订单详情
|
||||
* @param string uni
|
||||
*/
|
||||
export function getSendGiftOrderDetail(id) {
|
||||
return request.get('order/send_gift_detail/' + id);
|
||||
}
|
||||
903
api/user.js
Normal file
903
api/user.js
Normal file
@@ -0,0 +1,903 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
*/
|
||||
export function getUserInfo() {
|
||||
return request.get('user');
|
||||
}
|
||||
|
||||
/**
|
||||
* 运营统计数据
|
||||
*
|
||||
*/
|
||||
export function getMenuData() {
|
||||
return request.get('menu/date');
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录成功后更新公众号用户信息
|
||||
*/
|
||||
export function updateWechatInfo(data) {
|
||||
return request.get('v2/user/wechat', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户分享
|
||||
*
|
||||
*/
|
||||
export function userShare() {
|
||||
return request.post('user/share');
|
||||
}
|
||||
|
||||
/**
|
||||
* h5用户登录
|
||||
* @param data object 用户账号密码
|
||||
*/
|
||||
export function loginH5(data) {
|
||||
return request.post("login", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* h5用户手机号登录
|
||||
* @param data object 用户手机号 也只能
|
||||
*/
|
||||
export function loginMobile(data) {
|
||||
return request.post("login/mobile", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码key
|
||||
*/
|
||||
export function getCodeApi() {
|
||||
return request.get("verify_code", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* h5用户发送验证码
|
||||
* @param data object 用户手机号
|
||||
*/
|
||||
export function registerVerify(data) {
|
||||
return request.post("register/verify", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* h5用户手机号注册
|
||||
* @param data object 用户手机号 验证码 密码
|
||||
*/
|
||||
export function register(data) {
|
||||
return request.post("register", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户手机号修改密码
|
||||
* @param data object 用户手机号 验证码 密码
|
||||
*/
|
||||
export function registerReset(data) {
|
||||
return request.post("register/reset", data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户中心菜单
|
||||
*
|
||||
*/
|
||||
export function getMenuList() {
|
||||
return request.get("menu/user", {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* 签到用户信息
|
||||
* */
|
||||
export function postSignUser(sign) {
|
||||
return request.post("sign/user", sign);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取签到配置
|
||||
*
|
||||
*/
|
||||
export function getSignConfig() {
|
||||
return request.get('sign/config')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取签到列表
|
||||
* @param object data
|
||||
*/
|
||||
export function getSignList(data) {
|
||||
return request.get('sign/list', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户签到
|
||||
*/
|
||||
export function setSignIntegral() {
|
||||
return request.post('sign/integral')
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到列表(年月)
|
||||
* @param object data
|
||||
*
|
||||
*/
|
||||
export function getSignMonthList(data) {
|
||||
return request.get('sign/month', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 签到日历
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function getSignCalendar(data) {
|
||||
return request.get('sign/calendar', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 活动状态
|
||||
*
|
||||
*/
|
||||
export function userActivity() {
|
||||
return request.get('user/activity');
|
||||
}
|
||||
|
||||
/*
|
||||
* 资金明细(types|0=全部,1=消费,2=充值,3=返佣,4=提现)这个接口暂时废弃
|
||||
* */
|
||||
export function getCommissionInfo(q, types) {
|
||||
return request.get("spread/commission/" + types, q);
|
||||
}
|
||||
|
||||
// 资金明细(types|0=全部,1=消费,2=充值,3=返佣,4=提现)
|
||||
export function moneyList(q, types) {
|
||||
return request.get("v2/user/money_list/" + types, q);
|
||||
}
|
||||
|
||||
/*
|
||||
* 积分记录
|
||||
* */
|
||||
export function getIntegralList(q) {
|
||||
return request.get("integral/list", q);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分销海报图片
|
||||
*
|
||||
*/
|
||||
export function spreadBanner() {
|
||||
//#ifdef H5 || APP-PLUS
|
||||
return request.get('spread/banner', {
|
||||
type: 2
|
||||
});
|
||||
//#endif
|
||||
//#ifdef MP
|
||||
return request.get('spread/banner', {
|
||||
type: 1
|
||||
});
|
||||
//#endif
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 获取推广用户一级和二级
|
||||
* @param object data
|
||||
*/
|
||||
export function spreadPeople(data) {
|
||||
return request.post('spread/people', data);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 员工列表
|
||||
* @param object data
|
||||
*/
|
||||
export function agentStaffList(data) {
|
||||
return request.get('division/agent/staff_list', data);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* 员工列表-删除
|
||||
*/
|
||||
export function agentDelStaff(id) {
|
||||
return request.get(`division/agent/del_staff/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 员工列表-修改分佣比例
|
||||
*/
|
||||
export function agentStaffPercent(data) {
|
||||
return request.post(`division/agent/staff_percent`,data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 推广佣金/提现总和
|
||||
* @param int type
|
||||
*/
|
||||
export function spreadCount(type) {
|
||||
return request.get('spread/count/' + type);
|
||||
}
|
||||
|
||||
/*
|
||||
* 推广数据
|
||||
* */
|
||||
export function getSpreadInfo() {
|
||||
return request.get("commission");
|
||||
}
|
||||
|
||||
/*
|
||||
* 事业部推广二维码
|
||||
* */
|
||||
export function getAgentCode() {
|
||||
return request.get("division/agent/spread/code");
|
||||
}
|
||||
|
||||
/*
|
||||
* 事业部-绑定员工
|
||||
* */
|
||||
export function agentSpread(data) {
|
||||
return request.post("division/agent/spread", data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 推广订单
|
||||
* @param object data
|
||||
*/
|
||||
export function spreadOrder(data) {
|
||||
return request.post('spread/order', data);
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取推广人排行
|
||||
* */
|
||||
export function getRankList(q) {
|
||||
return request.get("rank", q);
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取佣金排名
|
||||
* */
|
||||
export function getBrokerageRank(q) {
|
||||
return request.get("brokerage_rank", q);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提现申请
|
||||
* @param object data
|
||||
*/
|
||||
export function extractCash(data) {
|
||||
return request.post('extract/cash', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 提现银行/提现最低金额
|
||||
*
|
||||
*/
|
||||
export function extractBank() {
|
||||
return request.get('extract/bank');
|
||||
}
|
||||
|
||||
/**
|
||||
*取消提现
|
||||
*
|
||||
*/
|
||||
export function extractCancelApi(id) {
|
||||
return request.get('extract/cancel/' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员等级列表
|
||||
*
|
||||
*/
|
||||
export function userLevelGrade() {
|
||||
return request.get('user/level/grade');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个等级任务
|
||||
* @param int id 任务id
|
||||
*/
|
||||
export function userLevelTask(id) {
|
||||
return request.get('user/level/task/' + id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查用户是否可以成为会员
|
||||
*
|
||||
*/
|
||||
export function userLevelDetection() {
|
||||
return request.get('user/level/detection');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 地址列表
|
||||
* @param object data
|
||||
*/
|
||||
export function getAddressList(data) {
|
||||
return request.get('address/list', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认地址
|
||||
* @param int id
|
||||
*/
|
||||
export function setAddressDefault(id) {
|
||||
return request.post('address/default/set', {
|
||||
id: id
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改 添加地址
|
||||
* @param object data
|
||||
*/
|
||||
export function editAddress(data) {
|
||||
return request.post('address/edit', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除地址
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function delAddress(id) {
|
||||
return request.post('address/del', {
|
||||
id: id
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个地址
|
||||
* @param int id
|
||||
*/
|
||||
export function getAddressDetail(id) {
|
||||
return request.get('address/detail/' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户信息
|
||||
* @param object
|
||||
*/
|
||||
export function userEdit(data) {
|
||||
return request.post('user/edit', data);
|
||||
}
|
||||
|
||||
/*
|
||||
* 退出登录
|
||||
* */
|
||||
export function getLogout() {
|
||||
return request.get("logout");
|
||||
}
|
||||
|
||||
/*
|
||||
* 充值订单信息
|
||||
* */
|
||||
export function rechargeAPi(data) {
|
||||
return request.post("recharge/recharge", data);
|
||||
}
|
||||
|
||||
/*
|
||||
* 充值支付
|
||||
* */
|
||||
export function rechargePayAPi(data) {
|
||||
return request.post("recharge/pay", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认地址
|
||||
*
|
||||
*/
|
||||
export function getAddressDefault() {
|
||||
return request.get('address/default');
|
||||
}
|
||||
|
||||
/**
|
||||
* 充值金额选择
|
||||
*/
|
||||
export function getRechargeApi() {
|
||||
return request.get("recharge/index");
|
||||
}
|
||||
|
||||
/**
|
||||
* 登陆记录
|
||||
*/
|
||||
export function setVisit(data) {
|
||||
return request.post('user/set_visit', {
|
||||
...data
|
||||
}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服列表
|
||||
*/
|
||||
export function serviceList() {
|
||||
return request.get("user/service/list");
|
||||
}
|
||||
/**
|
||||
* 客服详情
|
||||
*/
|
||||
export function getChatRecord(data) {
|
||||
return request.get("v2/user/service/record", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 静默绑定推广人
|
||||
* @param {Object} puid
|
||||
*/
|
||||
export function spread(puid) {
|
||||
return request.post("user/spread", puid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员详情
|
||||
*/
|
||||
export function getlevelInfo() {
|
||||
return request.get("user/level/info");
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员经验列表
|
||||
*/
|
||||
export function getlevelExpList(data) {
|
||||
return request.get("user/level/expList", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户信息
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function updateUserInfo(data) {
|
||||
return request.post('v2/user/user_update', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信直接手机号登录
|
||||
*/
|
||||
export function phoneWxSilenceAuth(data) {
|
||||
return request.post('v2/phone_wx_silence_auth', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序直接手机号登录
|
||||
*/
|
||||
export function phoneSilenceAuth(data) {
|
||||
return request.post('v2/phone_silence_auth', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户发票列表
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function invoiceList(data) {
|
||||
return request.get('v2/invoice', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户添加|修改发票
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function invoiceSave(data) {
|
||||
return request.post('v2/invoice/save', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户删除发票
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function invoiceDelete(id) {
|
||||
return request.get('v2/invoice/del/' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户默认发票
|
||||
* @param {Object} type
|
||||
*/
|
||||
export function invoiceDefault(type) {
|
||||
return request.get('v2/invoice/get_default/' + type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户单个发票详情
|
||||
* @param {Object} id
|
||||
*/
|
||||
export function invoiceDetail(id) {
|
||||
return request.get('v2/invoice/detail/' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单申请开票
|
||||
* @param {Object} id
|
||||
*/
|
||||
export function invoiceOrder(data) {
|
||||
return request.post('v2/order/make_up_invoice', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单详情中申请开票
|
||||
* @param {Object} id
|
||||
*/
|
||||
export function makeUpinvoice(data) {
|
||||
return request.post('v2/order/make_up_invoice', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员卡主界面
|
||||
*/
|
||||
export function memberCard() {
|
||||
return request.get('user/member/card/index');
|
||||
}
|
||||
|
||||
/**
|
||||
* 卡密领取会员卡
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function memberCardDraw(data) {
|
||||
return request.post('user/member/card/draw', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 购买会员卡
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function memberCardCreate(data) {
|
||||
return request.post('user/member/card/create', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 购买会员卡支付
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function memberCardPayApi(data) {
|
||||
return request.post('user/member/card/pay', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 会员优惠券
|
||||
*/
|
||||
export function memberCouponsList(page, limit) {
|
||||
return request.get('user/member/coupons/list', {
|
||||
page,
|
||||
limit
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* svip推荐商品
|
||||
* @param {Object} id
|
||||
*/
|
||||
export function groomList(id, data) {
|
||||
return request.get(`groom/list/${id}`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 付费会员结束
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function memberOverdueTime(data) {
|
||||
return request.get('user/member/overdue/time', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新版分享海报信息获取
|
||||
*
|
||||
*/
|
||||
export function spreadMsg() {
|
||||
return request.get('user/spread_info');
|
||||
}
|
||||
|
||||
/**
|
||||
* 已邀请/已下单好友
|
||||
*
|
||||
*/
|
||||
export function agentUserList(type, page, limit) {
|
||||
return request.get(`v2/agent/agent_user_list/${type}?page=${page}&limit=${limit}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户推广获得收益,佣金轮播,分销规则
|
||||
|
||||
*
|
||||
*/
|
||||
export function agentInfo() {
|
||||
return request.get(`v2/agent/agent_info`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取小程序二维码
|
||||
*
|
||||
*/
|
||||
export function routineCode(data) {
|
||||
return request.get('user/routine_code', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息中心
|
||||
*/
|
||||
export function serviceRecord(data) {
|
||||
return request.get('user/message', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息中心-站内信列表
|
||||
*/
|
||||
export function messageSystem(data) {
|
||||
return request.get('user/message_system/list', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息中心-站内信列表详情
|
||||
*/
|
||||
export function getMsgDetails(id) {
|
||||
return request.get('user/message_system/detail/' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 苹果账号登录
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function appleLogin(data) {
|
||||
return request.post('apple_login', data, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取隐私协议
|
||||
* */
|
||||
export function getUserAgreement(type) {
|
||||
return request.get(`user_agreement/${type}`, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取分销说明
|
||||
* */
|
||||
export function getDistributionInfo(type) {
|
||||
return request.get(`agreement/2`, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取分销说明
|
||||
* */
|
||||
export function getPayVipInfoApi(type) {
|
||||
return request.get(`agreement/1`, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分销等级列表
|
||||
* @param int id 任务id
|
||||
*/
|
||||
export function agentLevelList() {
|
||||
return request.get('v2/agent/level_list');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分销任务列表
|
||||
* @param int id 任务id
|
||||
*/
|
||||
export function agentLevelTaskList(id) {
|
||||
return request.get('v2/agent/level_task_list?id=' + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取定位详细地址
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function getGeocoder(data) {
|
||||
return request.get(`geoLbscoder?location=${data.lat},${data.long}`, {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前定位选中的地址
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function getCityList(address) {
|
||||
return request.get('v2/cityList', {
|
||||
address
|
||||
}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取版权
|
||||
*
|
||||
*/
|
||||
export function getCopyRight() {
|
||||
return request.get('get_copyright', {}, {
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取code码
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function getRandCode() {
|
||||
return request.get('user/rand_code');
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销用户
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function cancelUser() {
|
||||
return request.get('cancel/user');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取激活会员卡需要的信息
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function levelInfo() {
|
||||
return request.get('user/level/activate_info');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户激活会员卡
|
||||
* @param int id
|
||||
*
|
||||
*/
|
||||
export function levelActivate(data) {
|
||||
return request.post('user/level/activate', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户设置签到提醒
|
||||
*/
|
||||
export function signRemind(status) {
|
||||
return request.get(`sign/remind/${status}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分销员申请
|
||||
* @param data
|
||||
*
|
||||
*/
|
||||
export function promoterCreateApi(id, data) {
|
||||
return request.post(`user/promoter/apply/${id}`, data);
|
||||
}
|
||||
/**
|
||||
* 代理商入住申请
|
||||
* @param data
|
||||
*
|
||||
*/
|
||||
export function agentCreateApi(id, data) {
|
||||
return request.post(`division/agent/apply/${id}`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 代理商详情接口
|
||||
*
|
||||
*/
|
||||
export function userAgentInfo() {
|
||||
return request.get("division/agent/apply/info");
|
||||
}
|
||||
/**
|
||||
* 申请分销员详情接口
|
||||
*
|
||||
*/
|
||||
export function userPromoterInfo() {
|
||||
return request.get("user/promoter/apply/info");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 供应商入住
|
||||
* @param data
|
||||
*
|
||||
*/
|
||||
export function spplyCreateApi(id, data) {
|
||||
return request.post(`user/apply/supplier/${id}`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 供应商详情接口
|
||||
*
|
||||
*/
|
||||
export function userApply(id) {
|
||||
return request.get("user/apply/" + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 供应商记录接口
|
||||
*
|
||||
*/
|
||||
export function recordList() {
|
||||
return request.get("user/apply/record");
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章点赞
|
||||
*
|
||||
*/
|
||||
export function articleStarApi(id, data) {
|
||||
return request.get(`article/like/${id}`, data);
|
||||
}
|
||||
|
||||
// 收益明细
|
||||
export function spreadOrderIncomeApi(data) {
|
||||
return request.get(`spread/order_income`, data);
|
||||
}
|
||||
|
||||
// 分销数据统计
|
||||
export function spreadOverviewApi(data) {
|
||||
return request.get(`spread/overview`, data);
|
||||
}
|
||||
|
||||
// 分销贡献榜单
|
||||
export function spreadContributeApi(type, data) {
|
||||
return request.get(`spread/contribute/${type}`, data);
|
||||
}
|
||||
// 用户确认商家转账
|
||||
export function extractDetailApi(data) {
|
||||
return request.get(`extract/detail`, data);
|
||||
}
|
||||
|
||||
// 采购商申请
|
||||
export function channelApplyApi(data) {
|
||||
return request.post(`channel/apply`, data);
|
||||
}
|
||||
|
||||
// 采购商申请详情
|
||||
export function channelApplyInfoApi() {
|
||||
return request.get(`channel/apply/info`);
|
||||
}
|
||||
|
||||
// 采购商切换身份
|
||||
export function checkIdentityApi(data) {
|
||||
return request.post(`user/switch_identity`, data);
|
||||
}
|
||||
101
api/work.js
Normal file
101
api/work.js
Normal file
@@ -0,0 +1,101 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 获取企业微信基础配置
|
||||
*
|
||||
*/
|
||||
export function getWorkConfig(url) {
|
||||
return request.get('work/config?url=' + url,{},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取企业微信配置
|
||||
*
|
||||
*/
|
||||
export function getWorkAgentConfig(url) {
|
||||
return request.get('work/agentConfig?url=' + url,{},{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户信息详情
|
||||
*
|
||||
*/
|
||||
export function getWorkAgentInfo(data) {
|
||||
return request.get('work/client/info',data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户订单列表
|
||||
*
|
||||
*/
|
||||
export function getWorkOrderList(data) {
|
||||
return request.get('work/order/list',data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户订单详情
|
||||
*
|
||||
*/
|
||||
export function getWorkOrderInfo(id,data) {
|
||||
return request.get(`work/order/info/${id}`,data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 购买商品记录
|
||||
*
|
||||
*/
|
||||
export function getWorkCartList(data) {
|
||||
return request.get(`work/product/cart_list`,data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 浏览记录商品记录
|
||||
*
|
||||
*/
|
||||
export function getWorkVisitInfo(data) {
|
||||
return request.get(`work/product/visit_list`,data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户群详情
|
||||
*
|
||||
*/
|
||||
export function getWorkGroupInfo(data) {
|
||||
return request.get(`work/groupInfo`,data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取群成员列表
|
||||
*
|
||||
*/
|
||||
export function getWorkGroupMember(id,data) {
|
||||
return request.get(`work/groupMember/${id}`,data,{
|
||||
noAuth: true
|
||||
});
|
||||
}
|
||||
395
components/BaseCalendar.vue
Normal file
395
components/BaseCalendar.vue
Normal file
@@ -0,0 +1,395 @@
|
||||
<template>
|
||||
<!-- 打卡日历页面 -->
|
||||
<view class="all">
|
||||
<view class="bar">
|
||||
<!-- 上一个月 -->
|
||||
<view class="previous barbtn" @click="changeMonth(-1)">
|
||||
<view class="iconfont icon-ic_left2"></view>
|
||||
</view>
|
||||
<!-- 显示年月 -->
|
||||
<view class="date">{{ nowYear || '--' }} 年 {{ nowMonth || '--' }} 月</view>
|
||||
<!-- 下一个月 -->
|
||||
<view class="next barbtn" @click="changeMonth(1)">
|
||||
<view class="iconfont icon-ic_right2"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 显示星期 -->
|
||||
<view class="week-area">
|
||||
<view class="week-txt" v-for="(item, index) in weeksTxt[langType]" :key="index">{{ item }}</view>
|
||||
</view>
|
||||
|
||||
<view class="myDateTable">
|
||||
<view v-for="(item, j) in calendarDays" :key="j" class="dateCell">
|
||||
<view v-if="item.date == undefined || item.date == null" class="cell"></view>
|
||||
<template v-else>
|
||||
<!-- 已签到日期 -->
|
||||
<view v-if="item.isSign == true" class="cell signColor bgWhite">
|
||||
<!-- {{ item.date }} -->
|
||||
<image class="sign-today" src="@/pages/users/static/sign-today.png" mode=""></image>
|
||||
<view class="sign">已签</view>
|
||||
</view>
|
||||
<!-- 漏签 -->
|
||||
<view @click="clickSign(item.date, 0)" class="cell outSignStyle" v-else-if="item.isBeforeToday && item.isThisMonth">
|
||||
<!-- redColor bgGray -->
|
||||
{{ item.date }}
|
||||
<!-- <view class="redDot"></view> -->
|
||||
</view>
|
||||
<!-- 今日未签到-->
|
||||
<view @click="clickSign(item.date, 1)" class="cell whiteColor" v-else-if="item.date == today && nowMonth == toMonth && nowYear == toYear">今</view>
|
||||
<!-- 当前日期之后 -->
|
||||
<view class="whiteColor cell" v-else>
|
||||
{{ item.date }}
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
calendarDays: [],
|
||||
SignData: [], // 已经签到的数据
|
||||
nowYear: 0, //当前选的年
|
||||
nowMonth: 0, //当前选的月
|
||||
today: parseInt(new Date().getDate()), //系统本日
|
||||
toMonth: parseInt(new Date().getMonth() + 1), //系统本月
|
||||
toYear: parseInt(new Date().getFullYear()), //系统本年
|
||||
weeksTxt: {
|
||||
ch: ['日', '一', '二', '三', '四', '五', '六'],
|
||||
en: ['Sun', 'Mon', 'Tues', 'Wed', 'Thur', 'Fri', 'Sat']
|
||||
}
|
||||
};
|
||||
},
|
||||
props: {
|
||||
isReplenishSign: {
|
||||
// 是否允许过期补签
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isFullCalendar: {
|
||||
// 是否需要填满日历,前后空的格子填入上/下个月的日期
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
yearMonth: {
|
||||
// 2022-01 这种格式,默认当前年月
|
||||
type: String,
|
||||
default: new Date().getFullYear() + '-' + new Date().getMonth() + 1
|
||||
},
|
||||
dataSource: {
|
||||
//已签到的数据源,例: 5、6号已签到: ["2022-01-05","2022-01-06"],兼容个位数前可加可不加0
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
langType: {
|
||||
//只是示例一个翻译而已,要想所有都翻译自己可以再加加
|
||||
type: String,
|
||||
default: 'ch' //en
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (!/en|ch/g.test(this.langType)) {
|
||||
this.langType = 'ch'; // 非中英,则固定中文
|
||||
}
|
||||
const ymArr = this.yearMonth.split('-');
|
||||
this.buildCalendar(ymArr[0], ymArr[1]);
|
||||
this.onSignDataChange(this.dataSource);
|
||||
},
|
||||
watch: {
|
||||
dataSource: 'onSignDataChange'
|
||||
},
|
||||
methods: {
|
||||
clickSign(date, type) {
|
||||
//type=0补签,type=1当日签到
|
||||
var strTip = '签到';
|
||||
|
||||
if (type == 0) {
|
||||
if (!this.isReplenishSign) {
|
||||
// 未开启补签,阻止继续执行
|
||||
console.log('————补签功能未开启————');
|
||||
return;
|
||||
}
|
||||
strTip = '补签';
|
||||
}
|
||||
uni.showToast({
|
||||
title: date + '号' + strTip + '成功',
|
||||
icon: 'success',
|
||||
position: 'bottom'
|
||||
});
|
||||
this.$emit('clickChange', this.nowYear + '-' + this.nowMonth + '-' + date); //传给调用模板页面
|
||||
// 父页面要在clickChange里去修改输入的数据源dataSource,否则视图不更新的!
|
||||
},
|
||||
//构建日历数据
|
||||
buildCalendar(y, m) {
|
||||
this.nowYear = y;
|
||||
this.nowMonth = m;
|
||||
this.calculateEmptyGrids(y, m);
|
||||
this.calculateDays(y, m);
|
||||
if (this.isFullCalendar) {
|
||||
this.fullCell();
|
||||
}
|
||||
},
|
||||
// 监听到签到数据源改变
|
||||
onSignDataChange(newData, oldData = []) {
|
||||
this.SignData = newData;
|
||||
this.matchSign();
|
||||
},
|
||||
//匹配标记已经签到的日子
|
||||
matchSign() {
|
||||
var signs = this.SignData;
|
||||
var daysArr = this.calendarDays;
|
||||
for (var i = 0; i < signs.length; i++) {
|
||||
var current = new Date(this.toIOSDate(signs[i])).getTime(); // ios只认/格式的日期
|
||||
for (var j = 0; j < daysArr.length; j++) {
|
||||
if (current == new Date(this.toIOSDate(daysArr[j].fullDate)).getTime()) {
|
||||
daysArr[j].isSign = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.calendarDays = daysArr;
|
||||
// console.log(this.calendarDays );
|
||||
},
|
||||
// 计算当月1号前空了几个格子,把它填充在calendarDays数组的前面
|
||||
calculateEmptyGrids(year, month) {
|
||||
//计算每个月时要清零
|
||||
this.calendarDays = [];
|
||||
const firstDayOfWeek = this.getFirstDayOfWeek(year, month);
|
||||
if (firstDayOfWeek > 0) {
|
||||
for (let i = 0; i < firstDayOfWeek; i++) {
|
||||
this.calendarDays.push({
|
||||
date: null, // 显示的日期
|
||||
fullDate: null, // 日期yyyy-mm-dd格式
|
||||
isBeforeToday: true, // 今日之前
|
||||
isSign: false, // 是否签到
|
||||
isThisMonth: false // 是本月
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
// 绘制当月天数占的格子,并把它放到days数组中
|
||||
calculateDays(year, month) {
|
||||
const thisMonthDays = this.getMonthDayLength(year, month);
|
||||
const toDate = new Date(this.toYear + '/' + this.toMonth + '/' + this.today);
|
||||
for (let i = 1; i <= thisMonthDays; i++) {
|
||||
const fullDate = year + '-' + month + '-' + i;
|
||||
const isBeforeToday = new Date(this.toIOSDate(fullDate)) < toDate;
|
||||
this.calendarDays.push({
|
||||
date: i,
|
||||
fullDate,
|
||||
isBeforeToday,
|
||||
isSign: false,
|
||||
isThisMonth: true
|
||||
});
|
||||
}
|
||||
//console.log(this.calendarDays);
|
||||
},
|
||||
// 切换控制年月,上一个月,下一个月
|
||||
changeMonth(type) {
|
||||
console.log(type)
|
||||
const nowYear = parseInt(this.nowYear);
|
||||
const nowMonth = parseInt(this.nowMonth);
|
||||
const newObj = this.getOperateMonthDate(nowYear, nowMonth, type);
|
||||
this.buildCalendar(newObj.year, newObj.month); // 重新构建日历数据
|
||||
this.$emit('dateChange', this.nowYear + '-' + this.nowMonth); //传给调用模板页面去拿新数据
|
||||
},
|
||||
// 获取当月共多少天,也就是获取月的最后一天
|
||||
getMonthDayLength(year, month) {
|
||||
return new Date(year, month, 0).getDate();
|
||||
},
|
||||
// 获取当月第一天星期几
|
||||
getFirstDayOfWeek(year, month, day = 1) {
|
||||
return new Date(Date.UTC(year, month - 1, day)).getDay();
|
||||
},
|
||||
toIOSDate(strDate) {
|
||||
// iso不认识"-"拼接的日期,所以转/
|
||||
return strDate ? strDate.replace(/-/g, '/') : strDate;
|
||||
},
|
||||
// 需要填满格子,上/下个月的日期拉出来填满格子
|
||||
fullCell() {
|
||||
const endDay = this.getMonthDayLength(this.nowYear, this.nowMonth);
|
||||
const beforeEmptyLength = this.getFirstDayOfWeek(this.nowYear, this.nowMonth);
|
||||
const afterEmptyLength = 6 - this.getFirstDayOfWeek(this.nowYear, this.nowMonth, endDay);
|
||||
|
||||
const last = this.getOperateMonthDate(this.nowYear, this.nowMonth, -1);
|
||||
const lastMonthEndDay = this.getMonthDayLength(last.year, last.month);
|
||||
for (let i = 0; i < beforeEmptyLength; i++) {
|
||||
const date = lastMonthEndDay - beforeEmptyLength + i + 1;
|
||||
this.calendarDays[i].date = date;
|
||||
this.calendarDays[i].fullDate = last.year + '-' + last.month + '-' + date;
|
||||
}
|
||||
const next = this.getOperateMonthDate(this.nowYear, this.nowMonth, 1);
|
||||
for (let i = 1; i <= afterEmptyLength; i++) {
|
||||
this.calendarDays.push({
|
||||
date: i, // 显示的日期
|
||||
fullDate: next.year + '-' + next.month + '-' + i, // 日期yyyy-mm-dd格式
|
||||
isBeforeToday: false, // 今日之前
|
||||
isSign: false, // 是否签到
|
||||
isThisMonth: false // 是本月
|
||||
});
|
||||
}
|
||||
// console.log(beforeEmptyLength,afterEmptyLength,lastMonthEndDay);
|
||||
|
||||
// console.log(this.calendarDays);
|
||||
},
|
||||
// 获取加/减一个月的日期
|
||||
getOperateMonthDate(yy, mm, num) {
|
||||
let month = parseInt(mm) + parseInt(num);
|
||||
let year = parseInt(yy);
|
||||
if (month > 12) {
|
||||
month = 1;
|
||||
year++;
|
||||
} else if (month < 1) {
|
||||
month = 12;
|
||||
year--;
|
||||
}
|
||||
return {
|
||||
month,
|
||||
year
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.all {
|
||||
|
||||
// margin-top: 20rpx;
|
||||
.cir-bg {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 324rpx;
|
||||
height: 230rpx;
|
||||
background: #fee3de;
|
||||
opacity: 1;
|
||||
filter: blur(133px);
|
||||
}
|
||||
}
|
||||
|
||||
.all .bar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding: 60rpx 64rpx 64rpx;
|
||||
}
|
||||
|
||||
.bar .barbtn {
|
||||
width: 52rpx;
|
||||
height: 52rpx;
|
||||
background: rgba(233, 51, 35, 0.1);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
|
||||
.iconfont {
|
||||
margin: auto;
|
||||
color: rgba(233, 51, 35, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
.all .week-area {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
box-sizing: border-box;
|
||||
width: 91vw;
|
||||
margin: 10px auto;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.all .week-txt {
|
||||
text-align: center;
|
||||
width: 88rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 34rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.myDateTable {
|
||||
margin: 0 auto;
|
||||
width: 91vw;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.myDateTable .dateCell {
|
||||
width: 13vw;
|
||||
padding: 1vw;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dateCell .cell {
|
||||
display: flex;
|
||||
border-radius: 16rpx;
|
||||
height: 120rpx;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
font-family: 'SemiBold';
|
||||
|
||||
.sign-today {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.sign {
|
||||
font-size: 18rpx;
|
||||
font-weight: 500;
|
||||
color: #e93323;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.whiteColor {
|
||||
color: #981007;
|
||||
}
|
||||
|
||||
.signColor {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.bgWhite {
|
||||
background-color: #fceae9;
|
||||
}
|
||||
|
||||
.bgGray {
|
||||
background-color: rgba(255, 255, 255, 0.42);
|
||||
}
|
||||
|
||||
.bgBlue {
|
||||
font-size: 14px;
|
||||
background-color: #4b95e6;
|
||||
}
|
||||
|
||||
.redColor {
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.outSignStyle {
|
||||
// border: 1px solid #981007;
|
||||
color: #981007;
|
||||
}
|
||||
|
||||
.redDot {
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
border-radius: 16rpx;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 36rpx;
|
||||
font-family: PingFang SC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #981007;
|
||||
}
|
||||
</style>
|
||||
163
components/BaseCode.vue
Normal file
163
components/BaseCode.vue
Normal file
@@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<view class="codePopup tui-modal__container" :class="[isShowCode ? 'tui-modal-show' : '']" @touchmove.stop.prevent="moveHandle">
|
||||
<view class="tui-modal-box" :class="[isShowCode ? 'tui-modal-normal' : 'tui-modal-scale', isShowCode ? 'tui-modal-show' : '']">
|
||||
<view class="header acea-row row-between-wrapper">
|
||||
<view class="title on">员工推广码</view>
|
||||
</view>
|
||||
<view>
|
||||
<view class="acea-row row-center-wrapper mb-20 mt-28">
|
||||
<!-- #ifndef MP -->
|
||||
<w-qrcode :options="config.qrc"></w-qrcode>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<image class="code-img" :src="codeImg" show-menu-by-longpress></image>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view class="tip">如遇到扫码失败</view>
|
||||
<view class="tip">请将屏幕调至最亮重新扫码</view>
|
||||
</view>
|
||||
<view class="close">
|
||||
<view class="iconfont icon-ic_close1" @click="close"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mark" v-if="isShowCode" @touchmove.stop.prevent="moveHandle"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'codeModal',
|
||||
props: {
|
||||
isShowCode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
codeImg: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
config: {
|
||||
bar: {
|
||||
code: '',
|
||||
color: ['#000'],
|
||||
bgColor: '#FFFFFF', // 背景色
|
||||
width: 480, // 宽度
|
||||
height: 110 // 高度
|
||||
},
|
||||
qrc: {
|
||||
code: '123123',
|
||||
size: 380, // 二维码大小
|
||||
level: 3, //等级 0~4
|
||||
bgColor: '#FFFFFF', //二维码背景色 默认白色
|
||||
color: ['#333', '#333'] //边框颜色支持渐变色
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
code(newVal) {
|
||||
// #ifdef MP
|
||||
this.config.qrc.code = newVal;
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.code);
|
||||
// #ifndef MP
|
||||
this.config.qrc.code = this.code;
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
moveHandle() {},
|
||||
close() {
|
||||
this.$emit('update:isShowCode', false);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.mark {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 50;
|
||||
}
|
||||
.tui-modal__container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
visibility: hidden;
|
||||
z-index: 51;
|
||||
}
|
||||
|
||||
.tui-modal-box {
|
||||
position: relative;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s ease-in-out;
|
||||
width: 600rpx;
|
||||
padding: 40rpx;
|
||||
border-radius: 32rpx;
|
||||
background-color: #fff;
|
||||
z-index: 9999;
|
||||
.tip {
|
||||
color: #999999;
|
||||
font-size: 26rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.close {
|
||||
width: 520rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
bottom: -80rpx;
|
||||
.icon-ic_close1 {
|
||||
font-size: 52rpx;
|
||||
color: #cccccc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tui-modal-scale {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.tui-modal-normal {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.tui-modal-show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.codePopup .header .title {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.code-img{
|
||||
width: 380rpx;
|
||||
height: 380rpx;
|
||||
}
|
||||
</style>
|
||||
124
components/BaseMoney.vue
Normal file
124
components/BaseMoney.vue
Normal file
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<view :class="{ line: line, weight: weight }"
|
||||
:style="{color:color, fontFamily: SemiBold ? 'SemiBold' : 'Regular'}"
|
||||
class="base-money">
|
||||
<text v-show="preFix" class="preFix" :style="{'font-size': preFixSize + 'rpx','color':textColor}">{{preFix}}</text>
|
||||
<text class="symbol" :style="{'font-size': symbolSize +'rpx'}">¥</text><text class="integer"
|
||||
:style="{'font-size': integerSize +'rpx'}">{{ integer }}</text>
|
||||
<text v-if="digits && showDigits" class="decimal"
|
||||
:style="{'font-size': decimalSize +'rpx'}">.{{ decimal }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BaseMoney',
|
||||
props: {
|
||||
// 小数位数,为0则不显示
|
||||
digits: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
money: {
|
||||
type: String | Number,
|
||||
default: ""
|
||||
},
|
||||
// 删除线
|
||||
line: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 粗体
|
||||
weight: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
color:{
|
||||
type: String,
|
||||
default: 'var(--view-theme)'
|
||||
},
|
||||
textColor:{
|
||||
type: String,
|
||||
default: '#999'
|
||||
},
|
||||
symbolSize: {
|
||||
type: String,
|
||||
default: '20'
|
||||
},
|
||||
integerSize: {
|
||||
type: String,
|
||||
default: '26'
|
||||
},
|
||||
decimalSize: {
|
||||
type: String,
|
||||
default: '24'
|
||||
},
|
||||
inline: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
preFix:{
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
preFixSize:{
|
||||
type: String,
|
||||
default: '24'
|
||||
},
|
||||
SemiBold:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
isCoupon:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
integer: 0,
|
||||
decimal: 0,
|
||||
showDigits:false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
money: {
|
||||
handler(newValue, oldValue) {
|
||||
let value = Number(newValue).toFixed(this.digits);
|
||||
value = value.split('.');
|
||||
this.integer = value[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
if (value[1]) {
|
||||
this.decimal = value[1];
|
||||
if((this.isCoupon && this.decimal != '00') || !this.isCoupon) {
|
||||
this.showDigits = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.base-money {
|
||||
display: inline-block;
|
||||
&.line {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
&.weight {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
.preFix{
|
||||
font-weight: 500 !important;
|
||||
font-family: PingFang SC-Medium, PingFang SC !important;
|
||||
}
|
||||
.SemiBold{
|
||||
font-family:'SemiBold';
|
||||
}
|
||||
.Regular{
|
||||
font-family:'Regular';
|
||||
}
|
||||
</style>
|
||||
128
components/BaseNumberRun.vue
Normal file
128
components/BaseNumberRun.vue
Normal file
@@ -0,0 +1,128 @@
|
||||
<!-- 数字滚动效果 -->
|
||||
<template>
|
||||
<view class="pengke-scroll" :style="[penkeStyle]">
|
||||
<view v-for="(item, index) in digitalData" :key="index"
|
||||
:class="{'digital': true, 'digital-str': isNaN(item.num)}">
|
||||
<!-- 符号显示 -->
|
||||
<view v-if="isNaN(item.num)">{{item.num}}</view>
|
||||
<!-- 滚动的列表 -->
|
||||
<view v-else class="scroll-num">
|
||||
<view class="tra-num" :style="item.style">0123456789</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
// 数值
|
||||
value: {
|
||||
type: [Number, String],
|
||||
default: '9.99'
|
||||
},
|
||||
|
||||
// 字体大小
|
||||
size: {
|
||||
type: [Number, String],
|
||||
default: '14'
|
||||
},
|
||||
|
||||
// 字体颜色
|
||||
color: {
|
||||
type: String,
|
||||
default: '#333'
|
||||
},
|
||||
|
||||
// 文字居中
|
||||
textAlign: {
|
||||
type: String,
|
||||
default: 'center' // left, center, right
|
||||
},
|
||||
//动画时间
|
||||
time: {
|
||||
type: Number,
|
||||
default: 2
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
digitalData: []
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
penkeStyle(){
|
||||
return {
|
||||
'font-size': this.size + 'px',
|
||||
'color': this.color,
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
const digitalArr = String(val).split('')
|
||||
const dataList = []
|
||||
digitalArr.forEach((num) => {
|
||||
const obj = {
|
||||
num: isNaN(num) ? num : Number(num),
|
||||
style: ''
|
||||
}
|
||||
dataList.push(obj)
|
||||
})
|
||||
this.digitalData = dataList
|
||||
this.setScrollNum()
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 滚动数字
|
||||
setScrollNum() {
|
||||
const defData = JSON.parse(JSON.stringify(this.digitalData))
|
||||
defData.forEach((item, index) => {
|
||||
// 设置移动距离
|
||||
item.style = `transform: translateY(-${item.num}em);transition:all ${this.time}s;`
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.digitalData = defData
|
||||
}, 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pengke-scroll {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.digital {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 0.5em; // 文本间隔
|
||||
height: 1em;
|
||||
line-height: 0.7em;
|
||||
overflow: hidden;
|
||||
|
||||
.scroll-num {
|
||||
// 文本竖直排列
|
||||
writing-mode: vertical-rl;
|
||||
text-orientation: upright;
|
||||
|
||||
.tra-num {
|
||||
transition: all 1s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.digital-str {
|
||||
width: auto;
|
||||
line-height: 1em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
88
components/BaseTag.vue
Normal file
88
components/BaseTag.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<view class="base-tag" :class="{middle: size == 'middle'}" v-if="!imgSrc" :style="[tagStyle]" >{{text}}</view>
|
||||
<image class="img-tag" :class="{'middle-img-tag': size == 'middle'}" :src="imgSrc" mode="heightFix" v-else></image>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "tag",
|
||||
props: {
|
||||
size: {
|
||||
// 标签大小 normal, small
|
||||
type: String,
|
||||
default: "normal"
|
||||
},
|
||||
// 标签内容
|
||||
text: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
circle: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
default: '#e93323'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#ffffff'
|
||||
},
|
||||
borderColor:{
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
imgSrc:{
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
tagStyle(){
|
||||
return {
|
||||
background: this.background,
|
||||
color: this.color,
|
||||
border: this.borderColor ? `1rpx solid ${this.borderColor}` : 'none'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.base-tag {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 30rpx;
|
||||
font-size: 18rpx;
|
||||
padding: 0 8rpx;
|
||||
color: #333;
|
||||
border-radius: 4rpx;
|
||||
background-color: #fff;
|
||||
margin-right: 8rpx;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
.middle{
|
||||
height: 36rpx;
|
||||
padding: 0 12rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 20rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
.img-tag{
|
||||
display: block;
|
||||
height: 30rpx;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 14rpx;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
.middle-img-tag{
|
||||
height: 36rpx;
|
||||
border-radius: 8rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
</style>
|
||||
414
components/BaseTextMore.vue
Normal file
414
components/BaseTextMore.vue
Normal file
@@ -0,0 +1,414 @@
|
||||
<template>
|
||||
<view class="t-wrap">
|
||||
<!-- 虚拟view用于计算,计算完成则消失 -->
|
||||
<view class="t-txt-hide" :id="hid" v-if="!isCompute" :style="[computeStyle(0),{'text-align':oneRowTextAlign}]">
|
||||
<text space="nbsp">{{testContent?testContent:content}}{{showSymbol?'...':''}}</text><text
|
||||
v-if="expandText && collapseText && showSymbol" class="t-button">
|
||||
{{expandText}}
|
||||
</text><text></text>
|
||||
</view>
|
||||
<!-- 真实显示的内容 -->
|
||||
<view class="t-ellipsis" :id="id"
|
||||
:style="[!isCompute?computeStyle(1):computeStyle(2),{'text-align':oneRowTextAlign}]" @click="contentClick">
|
||||
<text space="nbsp">{{(!isCompute || expand)?content:(actualContent+(showSymbol?'...':''))}}</text><text
|
||||
v-if="expandText && collapseText && showSymbol" class="t-button" @click.stop="changeCollapse"
|
||||
:style="{'color':actionFontColor}">{{!expand?expandText:collapseText}}</text><text></text>
|
||||
</view>
|
||||
<!-- 这里加入了自定义的动态骨架屏友好反馈 -->
|
||||
<view v-if="!isCompute && rows>0" class="t-skeleton">
|
||||
<view class="skeletons" v-for="(item,index) in rows" :key="index">
|
||||
<view class="empty"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
//为了兼容部分老机型,增加扰动因子参数
|
||||
const factor = 5;
|
||||
export default {
|
||||
name: "KevyEllipsis",
|
||||
props: {
|
||||
/**
|
||||
* 文本唯一标识符,非必填
|
||||
*/
|
||||
textId: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 文本内容,默认''
|
||||
*/
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 字体大小,单位rpx,默认28
|
||||
*/
|
||||
fontSize: {
|
||||
type: [String, Number],
|
||||
default: 28
|
||||
},
|
||||
/**
|
||||
* 字体颜色,默认#666666
|
||||
*/
|
||||
fontColor: {
|
||||
color: String,
|
||||
default: '#666666'
|
||||
},
|
||||
/**
|
||||
* 收起操作的文案,默认''
|
||||
*/
|
||||
collapseText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 展开操作的文案,默认''
|
||||
*/
|
||||
expandText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 收起、展开操作文字颜色,默认'#007aff'
|
||||
*/
|
||||
actionFontColor: {
|
||||
color: String,
|
||||
default: '#007aff'
|
||||
},
|
||||
/**
|
||||
* 展示行数,默认1
|
||||
*/
|
||||
rows: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
/**
|
||||
* 只有一行时文本对齐方式,支持left、right、justify
|
||||
*/
|
||||
oneRowTextAlign: {
|
||||
type: String,
|
||||
default: "justify"
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//是否展开
|
||||
expand: false,
|
||||
//是否已计算
|
||||
isCompute: false,
|
||||
//内容高度
|
||||
h: undefined,
|
||||
//内容宽度
|
||||
w: undefined,
|
||||
//实际显示内容
|
||||
actualContent: '',
|
||||
//高度探测内容
|
||||
testContent: undefined,
|
||||
//是否显示省略号
|
||||
showSymbol: false,
|
||||
//hid和id,唯一标识符
|
||||
hid: 'hid' + Math.random().toString(36).substr(2),
|
||||
id: 'id' + Math.random().toString(36).substr(2),
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.initEllipsis();
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
//动态计算组件样式
|
||||
computeStyle() {
|
||||
return b => {
|
||||
let lines = this.rows > 0 ? this.rows : 1;
|
||||
let obj = {};
|
||||
if (b == 1) {
|
||||
obj = {
|
||||
'-webkit-line-clamp': lines,
|
||||
'display': '-webkit-box',
|
||||
'text-overflow': 'ellipsis',
|
||||
'overflow': 'hidden',
|
||||
'-webkit-box-orient': 'vertical'
|
||||
};
|
||||
} else if (b == 2) {
|
||||
obj = {
|
||||
'position': 'relative',
|
||||
'left': '0rpx',
|
||||
...obj
|
||||
};
|
||||
}
|
||||
return {
|
||||
'font-size': this.fontSize + 'rpx',
|
||||
'color': this.fontColor,
|
||||
...obj
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
content(newVal, oldVal) {
|
||||
this.expand=false;
|
||||
this.isCompute=false;
|
||||
this.h=undefined;
|
||||
this.w=undefined;
|
||||
this.actualContent='';
|
||||
this.showSymbol=false;
|
||||
this.initEllipsis();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//初始化
|
||||
initEllipsis() {
|
||||
if (this.content?.length > 0) {
|
||||
this.$nextTick(() => {
|
||||
this.init(this, () => {
|
||||
this.compute(this);
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
},
|
||||
//收起展开状态切换
|
||||
changeCollapse() {
|
||||
this.expand = !this.expand;
|
||||
},
|
||||
//文本点击事件
|
||||
contentClick() {
|
||||
this.$emit('contentClick', this.textId);
|
||||
},
|
||||
//组件参数初始化
|
||||
init($this, callback, isali) {
|
||||
if (isali) {
|
||||
uni.createSelectorQuery().in().select('#' + $this.id).boundingClientRect(d => {
|
||||
$this.h = Number(d.height.toFixed(1));
|
||||
$this.w = Number(d.width.toFixed(1));
|
||||
if (callback) {
|
||||
callback()
|
||||
}
|
||||
}).exec();
|
||||
} else {
|
||||
uni.createSelectorQuery().in($this).select('#' + $this.id).boundingClientRect(d => {
|
||||
$this.h = Number(d.height.toFixed(1));
|
||||
$this.w = Number(d.width.toFixed(1));
|
||||
if (callback) {
|
||||
callback()
|
||||
}
|
||||
}).exec();
|
||||
}
|
||||
},
|
||||
//动态计算组件内容
|
||||
computeContent($this, isali, dr) {
|
||||
$this.$nextTick(() => {
|
||||
$this.getH($this, isali, (ch) => {
|
||||
if (ch - factor > $this.h) {
|
||||
if (dr === -1) {
|
||||
$this.testContent = $this.content.substring(0, $this.testContent.length -
|
||||
1);
|
||||
$this.computeContent($this, isali, dr);
|
||||
} else {
|
||||
$this.actualContent = $this.content.substring(0, $this.testContent.length -
|
||||
1);
|
||||
$this.isCompute = true;
|
||||
}
|
||||
} else {
|
||||
if (dr === -1) {
|
||||
$this.actualContent = $this.testContent;
|
||||
$this.isCompute = true;
|
||||
} else {
|
||||
$this.testContent = $this.content.substring(0, $this.testContent.length +
|
||||
1);
|
||||
$this.computeContent($this, isali, dr);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
//计算工具方法
|
||||
compute($this, isali) {
|
||||
let {
|
||||
rows,
|
||||
fontSize,
|
||||
content,
|
||||
h,
|
||||
w
|
||||
} = $this;
|
||||
$this.testContent = content;
|
||||
$this.$nextTick(() => {
|
||||
$this.getH($this, isali, (ch) => {
|
||||
if (ch - factor > h) {
|
||||
let lh = h / rows;
|
||||
let fn = Math.floor(w / $this.rpx2px(fontSize));
|
||||
let sfn = fn * rows;
|
||||
let i = $this.fontNum(content, sfn * 2 - ($this.expandText ? $this.fontNum(
|
||||
$this.expandText) :
|
||||
0) - 3);
|
||||
$this.showSymbol = true;
|
||||
$this.testContent = content.substring(0, i);
|
||||
$this.$nextTick(() => {
|
||||
$this.getH($this, isali, (ch1) => {
|
||||
if (ch1 - factor > h) {
|
||||
$this.testContent = content.substring(0, $this
|
||||
.testContent.length - 1);
|
||||
$this.computeContent($this, isali, -1);
|
||||
} else {
|
||||
$this.testContent = content.substring(0, $this
|
||||
.testContent.length + 1);
|
||||
$this.computeContent($this, isali, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$this.isCompute = true;
|
||||
$this.actualContent = content;
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
//动态计算字符数
|
||||
fontNum(val, limit) {
|
||||
let c = 0;
|
||||
for (let i = 0; i < val.length; i++) {
|
||||
let a = val.charAt(i);
|
||||
if (a.match(/[^\x00-\xff]/ig) != null) {
|
||||
if (limit) {
|
||||
if (c + 2 > limit) {
|
||||
return i;
|
||||
} else {
|
||||
c += 2;
|
||||
}
|
||||
} else {
|
||||
c += 2;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (limit) {
|
||||
if (c + 1 > limit) {
|
||||
return i;
|
||||
} else {
|
||||
c += 1;
|
||||
}
|
||||
} else {
|
||||
c += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!limit) {
|
||||
return c;
|
||||
}
|
||||
},
|
||||
rpx2px(rpx) {
|
||||
return uni.getWindowInfo().windowWidth * Number(rpx) / 750;
|
||||
},
|
||||
getH($, isali, callback) {
|
||||
if (isali) {
|
||||
uni.createSelectorQuery().in().select('#' + $.hid).fields({
|
||||
size: true
|
||||
}, d => {
|
||||
if(d && d.height){
|
||||
callback(Number(d.height.toFixed(1)));
|
||||
}
|
||||
}).exec();
|
||||
} else {
|
||||
uni.createSelectorQuery().in($).select('#' + $.hid).fields({
|
||||
size: true
|
||||
}, d => {
|
||||
if(d && d.height){
|
||||
callback(Number(d.height.toFixed(1)));
|
||||
}
|
||||
}).exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.t-wrap {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.t-txt-hide {
|
||||
box-sizing: border-box;
|
||||
word-break: break-all;
|
||||
position: absolute;
|
||||
top: 999999px;
|
||||
left: 999999px;
|
||||
z-index: -1000;
|
||||
top: 0rpx;
|
||||
width: 100%;
|
||||
margin: 0rpx;
|
||||
text-align: justify;
|
||||
white-space: pre-line;
|
||||
line-height: 1.5 !important;
|
||||
.t-button {
|
||||
float: right;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
.t-ellipsis {
|
||||
text-align: justify;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
word-break: break-all;
|
||||
position: relative;
|
||||
left: 99999px;
|
||||
white-space: pre-line;
|
||||
line-height: 1.5 !important;
|
||||
.t-button {
|
||||
float: right;
|
||||
clear: both;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.t-skeleton {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 0rpx;
|
||||
left: 0rpx;
|
||||
}
|
||||
|
||||
.skeletons:first-child {
|
||||
margin-top: 0rpx !important;
|
||||
}
|
||||
|
||||
.skeletons {
|
||||
position: relative;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 32rpx;
|
||||
margin-top: 12rpx;
|
||||
background-color: rgba(0, 0, 0, 0.06);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.skeletons .empty {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-webkit-transform: translateX(-100%);
|
||||
transform: translateX(-100%);
|
||||
background: linear-gradient(90deg, transparent, rgba(216, 216, 216, 0.753), transparent);
|
||||
-webkit-animation: loading .8s infinite;
|
||||
animation: loading .8s infinite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@keyframes loading {
|
||||
100% {
|
||||
-webkit-transform: translateX(100%);
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
60
components/Loading/index.vue
Normal file
60
components/Loading/index.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<!-- 上拉加载 -->
|
||||
<view>
|
||||
<view class="Loads acea-row row-center-wrapper" v-if="loading && !loaded" style="margin-top: .2rem;">
|
||||
<view v-if="loading">
|
||||
<view class="iconfont icon-jiazai loading acea-row row-center-wrapper"></view>
|
||||
<slot name="loading"></slot>
|
||||
正在加载中
|
||||
</view>
|
||||
<view v-else>
|
||||
<slot name="load"></slot>
|
||||
上拉加载更多
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Loading",
|
||||
props: {
|
||||
loaded: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.Loads {
|
||||
height: 80upx;
|
||||
font-size: 25upx;
|
||||
color: #999;
|
||||
}
|
||||
.Loads .iconfont {
|
||||
font-size: 30upx;
|
||||
margin-right: 10upx;
|
||||
height: 32upx;
|
||||
line-height: 32upx;
|
||||
}
|
||||
/*加载动画*/
|
||||
@keyframes load {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.loadingpic {
|
||||
animation: load 3s linear 1s infinite;
|
||||
}
|
||||
.loading {
|
||||
animation: load linear 1s infinite;
|
||||
}
|
||||
</style>
|
||||
138
components/NavBar.vue
Normal file
138
components/NavBar.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<view class="navbar">
|
||||
<view class="content" :style="{ background: isScrolling ? '#fff' : bagColor,'padding-top': sysHeight + 'px' }">
|
||||
<view class="flex-center h-80 px-20">
|
||||
<view class="w-40 h-40 flex-center">
|
||||
<view
|
||||
v-show="showBack"
|
||||
@click="back"
|
||||
class="iconfont icon-ic_leftarrow"
|
||||
:style="{ color: `${iconColor}`, fontSize: `${iconSize}`, fontWeight: `${iconWeight}` }"
|
||||
></view>
|
||||
</view>
|
||||
<view class="flex-1 text-center"
|
||||
:style="{ color: `${textColor}`, fontSize: `${textSize}`, fontWeight: `${textWeight}` }"
|
||||
v-if="!custom">{{ titleText }}</view>
|
||||
<view class="flex-1" v-else>
|
||||
<slot></slot>
|
||||
</view>
|
||||
<view class="w-40 h-40 flex-center">
|
||||
<view v-show="showRight" class="right-icon"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view :style="{'padding-top': sysHeight + 'px'}" v-if="showEmpty">
|
||||
<view class="h-80"></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let sysHeight = uni.getWindowInfo().statusBarHeight;
|
||||
export default {
|
||||
name: 'navbar',
|
||||
props: {
|
||||
custom:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
fixed: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showEmpty:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 滚动至下部
|
||||
isScrolling: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示返回icon
|
||||
showBack: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// Title
|
||||
titleText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// icon 颜色
|
||||
iconColor: {
|
||||
type: String,
|
||||
default: '#000000'
|
||||
},
|
||||
// icon 字号
|
||||
iconSize: {
|
||||
type: String,
|
||||
default: '40rpx'
|
||||
},
|
||||
// icon 字重
|
||||
iconWeight: {
|
||||
type: String,
|
||||
default: 'bold'
|
||||
},
|
||||
// Title 颜色
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '#333'
|
||||
},
|
||||
// Title 字号
|
||||
textSize: {
|
||||
type: String,
|
||||
default: '34rpx'
|
||||
},
|
||||
// Title 字重
|
||||
textWeight: {
|
||||
type: String,
|
||||
default: '500'
|
||||
},
|
||||
// 背景色
|
||||
bagColor: {
|
||||
type: String,
|
||||
default: 'transparent'
|
||||
},
|
||||
showRight:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sysHeight:sysHeight,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
let pages = getCurrentPages(); // 获取当前打开过的页面路由数,
|
||||
if (pages.length > 1) {
|
||||
uni.navigateBack()
|
||||
} else {
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.navbar {
|
||||
position: relative;
|
||||
color: #333;
|
||||
.content {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 998;
|
||||
background-color: var(--view-theme);
|
||||
font-weight: 500;
|
||||
font-size: 34rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
218
components/WaterfallsFlow/WaterfallsFlow.vue
Normal file
218
components/WaterfallsFlow/WaterfallsFlow.vue
Normal file
@@ -0,0 +1,218 @@
|
||||
<template>
|
||||
<view :class="'wf-page wf-page'+type">
|
||||
<!-- left -->
|
||||
<view>
|
||||
<view id="left" v-if="leftList.length">
|
||||
<view v-for="(item,index) in leftList" :key="index"
|
||||
class="wf-item" @tap="itemTap(item)">
|
||||
<WaterfallsFlowItem
|
||||
:item="item"
|
||||
:isStore="isStore"
|
||||
:type="type"
|
||||
:isMerchant="isMerchant"
|
||||
:recommend="recommend"
|
||||
:showCart="showCart"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- right -->
|
||||
<view>
|
||||
<view id="right" v-if="rightList.length">
|
||||
<view v-for="(item,index) in rightList" :key="index"
|
||||
class="wf-item" @tap="itemTap(item)">
|
||||
<WaterfallsFlowItem
|
||||
:item="item"
|
||||
:isStore="isStore"
|
||||
:type="type"
|
||||
:isMerchant="isMerchant"
|
||||
:recommend="recommend"
|
||||
:showCart="showCart"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WaterfallsFlowItem from './WaterfallsFlowItem.vue'
|
||||
export default {
|
||||
components: {
|
||||
WaterfallsFlowItem
|
||||
},
|
||||
props: {
|
||||
// 瀑布流列表
|
||||
wfList: {
|
||||
type: Array,
|
||||
require: true
|
||||
},
|
||||
updateNum: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
type: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
isStore: {
|
||||
type: [String, Number],
|
||||
default: '1'
|
||||
},
|
||||
recommend:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showCart:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
isMerchant:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
allList: [], // 全部列表
|
||||
leftList: [], // 左边列表
|
||||
rightList: [], // 右边列表
|
||||
mark: 0, // 列表标记
|
||||
boxHeight: [], // 下标0和1分别为左列和右列高度
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 监听列表数据变化
|
||||
wfList: {
|
||||
handler(nVal,oVal){
|
||||
// 如果数据为空或新的列表数据少于旧的列表数据(通常为下拉刷新或切换排序或使用筛选器),初始化变量
|
||||
|
||||
if (!this.wfList.length ||
|
||||
(this.wfList.length === this.updateNum && this.wfList.length <= this.allList.length)) {
|
||||
this.allList = [];
|
||||
this.leftList = [];
|
||||
this.rightList = [];
|
||||
this.boxHeight = [];
|
||||
this.mark = 0;
|
||||
}
|
||||
|
||||
// 如果列表有值,调用waterfall方法
|
||||
|
||||
if (this.wfList.length) {
|
||||
this.allList = this.wfList;
|
||||
this.leftList = [];
|
||||
this.rightList = [];
|
||||
this.boxHeight = [];
|
||||
this.allList.forEach((v, i) => {
|
||||
if(this.allList.length < 3 || (this.allList.length <= 7 && this.allList.length - i > 1) || (this.allList.length > 7 && this.allList.length - i > 2)) {
|
||||
if(i % 2){
|
||||
this.rightList.push(v);
|
||||
}else{
|
||||
this.leftList.push(v);
|
||||
}
|
||||
}
|
||||
});
|
||||
if(this.allList.length < 3){
|
||||
this.mark = this.allList.length+1;
|
||||
}else if(this.allList.length <= 7){
|
||||
this.mark = this.allList.length - 1;
|
||||
}else{
|
||||
this.mark = this.allList.length - 2;
|
||||
}
|
||||
if(this.mark < this.allList.length){
|
||||
this.waterFall()
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
deep:true
|
||||
},
|
||||
mounted(){
|
||||
},
|
||||
|
||||
// 监听标记,当标记发生变化,则执行下一个item排序
|
||||
mark() {
|
||||
const len = this.allList.length;
|
||||
if (this.mark < len && this.mark !== 0 && this.boxHeight.length) {
|
||||
this.waterFall();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 瀑布流排序
|
||||
waterFall() {
|
||||
const i = this.mark;
|
||||
if (i == 0) {
|
||||
// 初始化,从左边开始插入
|
||||
this.leftList.push(this.allList[i]);
|
||||
// 更新左边列表高度
|
||||
this.getViewHeight(0);
|
||||
} else if (i == 1) {
|
||||
// 第二个item插入,默认为右边插入
|
||||
this.rightList.push(this.allList[i]);
|
||||
// 更新右边列表高度
|
||||
this.getViewHeight(1);
|
||||
} else {
|
||||
// 根据左右列表高度判断下一个item应该插入哪边
|
||||
if(!this.boxHeight.length){
|
||||
this.rightList.length < this.leftList.length
|
||||
? this.rightList.push(this.allList[i])
|
||||
: this.leftList.push(this.allList[i]);
|
||||
} else {
|
||||
const leftOrRight = this.boxHeight[0] > this.boxHeight[1] ? 1 : 0;
|
||||
if (leftOrRight) {
|
||||
this.rightList.push(this.allList[i])
|
||||
} else {
|
||||
this.leftList.push(this.allList[i])
|
||||
}
|
||||
}
|
||||
// 更新插入列表高度
|
||||
this.getViewHeight();
|
||||
}
|
||||
},
|
||||
// 获取列表高度
|
||||
getViewHeight() {
|
||||
// 使用nextTick,确保页面更新结束后,再请求高度
|
||||
this.$nextTick(() => {
|
||||
setTimeout(()=>{
|
||||
uni.createSelectorQuery().in(this).select('#right').boundingClientRect(res => {
|
||||
res ? this.boxHeight[1] = res.height : '';
|
||||
uni.createSelectorQuery().in(this).select('#left').boundingClientRect(res => {
|
||||
res ? this.boxHeight[0] = res.height : '';
|
||||
this.mark = this.mark + 1;
|
||||
}).exec();
|
||||
}).exec();
|
||||
},100)
|
||||
})
|
||||
},
|
||||
// item点击
|
||||
itemTap(item) {
|
||||
this.$emit('itemTap', item)
|
||||
},
|
||||
// item点击
|
||||
|
||||
goShop(item) {
|
||||
this.$emit('goShop', item)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$page-padding: 10px;
|
||||
$grid-gap: 10px;
|
||||
|
||||
.wf-page {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: $grid-gap;
|
||||
}
|
||||
.wf-item {
|
||||
width: calc((100vw - 2 * #{$page-padding} - #{$grid-gap}) / 2);
|
||||
padding-bottom: $grid-gap;
|
||||
}
|
||||
.wf-page1 .wf-item{
|
||||
margin-top: 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
129
components/WaterfallsFlow/WaterfallsFlowItem.vue
Normal file
129
components/WaterfallsFlow/WaterfallsFlowItem.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<view class="wf-item-page wf-page0">
|
||||
<view class='pictrue'>
|
||||
<easy-loadimage
|
||||
mode="widthFix"
|
||||
:image-src="item.image"
|
||||
:borderSrc="item.activity_frame.image"
|
||||
width="100%"
|
||||
borderRadius="16rpx 16rpx 0 0"></easy-loadimage>
|
||||
</view>
|
||||
<view class="info_box">
|
||||
<view class="w-full line2 fs-28 text--w111-333 lh-40rpx">
|
||||
<text v-if="item.brand_name" class="brand-tag">{{ item.brand_name }}</text>{{item.store_name}}
|
||||
</view>
|
||||
<view class="flex items-end flex-wrap mt-12 w-full" v-if="item.store_label.length && !isMerchant">
|
||||
<BaseTag
|
||||
:text="label.label_name"
|
||||
:color="label.color"
|
||||
:background="label.bg_color"
|
||||
:borderColor="label.border_color"
|
||||
:circle="label.border_color ? true : false"
|
||||
:imgSrc="label.icon"
|
||||
v-for="(label, idx) in item.store_label" :key="idx"></BaseTag>
|
||||
</view>
|
||||
<view class="flex-between-center mt-7" v-if="recommend">
|
||||
<view class="flex-y-center flex-wrap">
|
||||
<baseMoney :money="isVip ? item.vip_price : item.price" symbolSize="24" integerSize="40" decimalSize="24" weight></baseMoney>
|
||||
<view class="svip-label ml-8"
|
||||
v-if="Number(item.vip_price) > 0 && item.is_vip && !isVip">
|
||||
<text class="text">SVIP</text>
|
||||
<text class="px-8 SemiBold">¥{{item.vip_price}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="w-44 h-44 rd-24 bg-gradient flex-center" v-show="showCart">
|
||||
<text class="iconfont icon-ic_ShoppingCart1 text--w111-fff fs-26"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-8" v-else>
|
||||
<view class="flex-y-center flex-wrap mt-8">
|
||||
<baseMoney :money="item.price" symbolSize="24" integerSize="40" decimalSize="24" :color="isMerchant ? '#FF7E00' : 'var(--view-theme)'" weight></baseMoney>
|
||||
<view class="svip-label" v-if="Number(item.vip_price) > 0 && item.is_vip && !isMerchant">
|
||||
<text class="text">SVIP</text>
|
||||
<text class="px-8 SemiBold">¥{{item.vip_price}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-between-center mt-12">
|
||||
<text class="fs-22 text--w111-999">已售{{item.sales}}{{item.unit_name}}</text>
|
||||
<view class="w-44 h-44 rd-24 flex-center" :class="isMerchant ? 'bg-mer' : 'bg-gradient'" @tap.stop="addCartChange" v-show="showCart">
|
||||
<text class="iconfont icon-ic_ShoppingCart1 fs-26" :class="isMerchant ? 'text-mer' : 'text--w111-fff'"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import easyLoadimage from '@/components/easy-loadimage/easy-loadimage.vue'
|
||||
import {mapGetters} from "vuex";
|
||||
import {HTTP_REQUEST_URL} from '@/config/app';
|
||||
export default {
|
||||
components: {
|
||||
easyLoadimage
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
require: true
|
||||
},
|
||||
type: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
recommend:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showCart:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
isMerchant:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
domain: HTTP_REQUEST_URL,
|
||||
}
|
||||
},
|
||||
inject: {
|
||||
isVip:{
|
||||
from: 'isVip',
|
||||
default: false // 这里设置默认值为 false
|
||||
},
|
||||
addCartClick: {
|
||||
from: 'addCartClick',
|
||||
default: () => {}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addCartChange(){
|
||||
this.addCartClick(this.item);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.wf-item-page {
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
.pictrue{
|
||||
max-height: 560rpx;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.info_box{
|
||||
padding: 16rpx 20rpx;
|
||||
border-radius: 0 0 20rpx 20rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
.bg-mer{
|
||||
background-color: $light-primary-merchant;
|
||||
}
|
||||
.text-mer{
|
||||
color: $primary-merchant;
|
||||
}
|
||||
</style>
|
||||
106
components/activityModal/index.vue
Normal file
106
components/activityModal/index.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<view>
|
||||
<uni-popup ref="popup" :mask-click="false">
|
||||
<view class="w-590 activity-popup">
|
||||
<view class="w-full h-800">
|
||||
<swiper class="w-full h-full"
|
||||
:circular="true"
|
||||
:indicator-dots="modalSwiper.length > 1 ? true : false"
|
||||
autoplay
|
||||
:interval="3000"
|
||||
:duration="500"
|
||||
indicator-color="rgba(255,255,255,0.5)"
|
||||
indicator-active-color="#ffffff">
|
||||
<swiper-item v-for="(item ,index) in modalSwiper" :key="index">
|
||||
<image :src="item.pic" mode="aspectFill" class="w-full h-full" @tap="pageJump(item)"></image>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<view class="flex-x-center mt-54">
|
||||
<text class="iconfont icon-ic_close1 fs-60 text--w111-fff" @tap="closeModal"></text>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getActivityModalRecordApi } from "@/api/activity.js"
|
||||
export default {
|
||||
name:"activityModal",
|
||||
props:{
|
||||
pageIndex:{
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
pageId:{
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modalSwiper:[],
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
activityModalData(){
|
||||
return this.$store.state.app.activityModalList
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
pageIndex:{
|
||||
handler(val){
|
||||
setTimeout(()=>{
|
||||
if (!this.activityModalData.length) return;
|
||||
let dataList = this.activityModalData.filter(item => item.show_page.includes(val))
|
||||
.map(item => item.wechat_image).flat();
|
||||
let ids = this.activityModalData.filter(item => item.show_page.includes(val)).map(item => item.id);
|
||||
let closeModalSwiper = this.$Cache.get('closeModalSwiper');
|
||||
if (dataList.length && !closeModalSwiper) {
|
||||
this.modalSwiper = dataList;
|
||||
this.$refs.popup.open();
|
||||
this.recordLog(ids);
|
||||
}
|
||||
},500)
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
pageJump(item){
|
||||
this.$util.JumpPath(item.url);
|
||||
this.$refs.popup.close();
|
||||
},
|
||||
closeModal(){
|
||||
this.$refs.popup.close();
|
||||
},
|
||||
recordLog(ids){
|
||||
getActivityModalRecordApi({ids: ids.join()}).then(res=>{
|
||||
this.$Cache.set('closeModalSwiper', true);
|
||||
}).catch(err=>{
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* #ifdef H5 || APP-PLUS */
|
||||
.activity-popup /deep/uni-swiper .uni-swiper-dot{
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
}
|
||||
/* #endif */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
.activity-popup /deep/.wx-swiper-dot~.wx-swiper-dot {
|
||||
width: 10rpx;
|
||||
height: 10rpx;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
</style>
|
||||
138
components/addressWindow/index.vue
Normal file
138
components/addressWindow/index.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<view>
|
||||
<base-drawer mode="bottom" :visible="address.address" background-color="transparent" mask maskClosable @close="close">
|
||||
<view class="w-full bg--w111-fff rd-t-40rpx py-32" v-if="shippingType == 0">
|
||||
<view class="text-center fs-32 text--w111-333 fw-500">选择地址</view>
|
||||
<scroll-view scroll-y="true" class="mt-64 px-32" style="max-height: 600rpx;">
|
||||
<view class="mb-38 flex-between-center"
|
||||
v-for="(item,index) in addressList" :key="index"
|
||||
:class="{'font-num': active==index}"
|
||||
@tap='tapAddress(index,item.id,item)'>
|
||||
<text class='iconfont icon-ic_location5 fs-36'></text>
|
||||
<view class="flex-1 pl-40">
|
||||
<view class="fs-28 fw-500">{{item.real_name}}<text class='phone pl-10'>{{item.phone}}</text></view>
|
||||
<view class="w-560 line1 mt-4">{{item.province}}{{item.city}}{{item.district}}{{item.street}}{{item.detail}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="!is_loading && !addressList.length">
|
||||
<emptyPage title="暂无地址信息~" src="/statics/images/noAddress.png"></emptyPage>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="mx-20 pb-safe">
|
||||
<view class="mt-52 h-72 flex-center rd-36px bg-color fs-26 text--w111-fff" @tap='goAddressPages'>选择其它地址</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="w-full bg--w111-fff rd-t-40rpx py-32" v-else>
|
||||
<view class="text-center fs-32 text--w111-333 fw-500">选择自提点</view>
|
||||
<scroll-view scroll-y="true" class="mt-64 px-32" style="max-height: 600rpx;">
|
||||
<view class="mb-38 flex-between-center"
|
||||
v-for="(item,index) in storeList" :key="index"
|
||||
:class="{'font-num': active==index}"
|
||||
@tap='tapStore(index,item)'>
|
||||
<text class='iconfont icon-ic_location5 fs-36'></text>
|
||||
<view class="flex-1 pl-40">
|
||||
<view class="fs-28 fw-500">{{item.name}}<text class='phone pl-10'>{{item.phone}}</text></view>
|
||||
<view class="w-560 line1 mt-4">{{item.address}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</base-drawer>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getAddressList} from '@/api/user.js';
|
||||
import {HTTP_REQUEST_URL} from '@/config/app';
|
||||
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
|
||||
import emptyPage from '@/components/emptyPage.vue';
|
||||
export default {
|
||||
props: {
|
||||
fromType: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
pagesUrl: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
address: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return {
|
||||
address: true,
|
||||
addressId: 0,
|
||||
};
|
||||
}
|
||||
},
|
||||
isLog: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
storeList:{
|
||||
type: Array,
|
||||
default: ()=> []
|
||||
},
|
||||
shippingType:{
|
||||
type: String | Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
components: {
|
||||
baseDrawer,
|
||||
emptyPage
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
active: 0,
|
||||
//地址列表
|
||||
addressList: [],
|
||||
is_loading: true,
|
||||
imgHost: HTTP_REQUEST_URL
|
||||
};
|
||||
},
|
||||
watch:{
|
||||
shippingType(val){
|
||||
this.active = 0;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
tapAddress: function(e, addressid, row) {
|
||||
this.active = e;
|
||||
this.$emit('OnChangeAddress', addressid, row);
|
||||
},
|
||||
close: function() {
|
||||
this.$emit('changeClose');
|
||||
this.$emit('changeTextareaStatus');
|
||||
},
|
||||
goAddressPages: function() {
|
||||
this.$emit('changeClose');
|
||||
this.$emit('changeTextareaStatus');
|
||||
uni.navigateTo({
|
||||
url: this.pagesUrl
|
||||
});
|
||||
},
|
||||
tapStore(index, item){
|
||||
this.active = index;
|
||||
this.$emit('OnChangeAddress', item.id, item);
|
||||
},
|
||||
getAddressList: function() {
|
||||
let that = this;
|
||||
getAddressList({
|
||||
page: 1,
|
||||
limit: 5
|
||||
}).then(res => {
|
||||
let addressList = res.data;
|
||||
//处理默认选中项
|
||||
for (let i = 0, leng = addressList.length; i < leng; i++) {
|
||||
if (addressList[i].id == that.address.addressId) {
|
||||
that.active = i;
|
||||
}
|
||||
}
|
||||
that.$set(that, 'addressList', addressList);
|
||||
that.is_loading = false;
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
267
components/areaWindow/index.vue
Normal file
267
components/areaWindow/index.vue
Normal file
@@ -0,0 +1,267 @@
|
||||
<template>
|
||||
<!-- 地址下拉框 -->
|
||||
<view>
|
||||
<view class="address-window" :class="display==true?'on':''">
|
||||
<view class='title'>请选择所在地区<text class='iconfont icon-guanbi' @tap='close'></text></view>
|
||||
<view class="address-count">
|
||||
<view class="address-selected">
|
||||
<view v-for="(item,index) in selectedArr" :key="index" class="selected-list" :class="{active:index === selectedIndex}" @click="change(item.pid, index)">
|
||||
{{item.label}}
|
||||
<text class="iconfont icon-xiangyou"></text>
|
||||
</view>
|
||||
<view class="selected-list" :class="{active:-1 === selectedIndex}" v-if="showMore" @click="change(-1, -1)">
|
||||
<text class="iconfont icon-xiangyou"></text>
|
||||
请选择
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" :scroll-top="scrollTop" class="address-list" @scroll="scroll">
|
||||
<view v-for="(item,index) in addressList" :key="index" class="list" :class="{active:item.id === activeId}" @click="selected(item)">
|
||||
<text class="item-name">{{item.label}}</text>
|
||||
<text v-if="item.id === activeId" class="iconfont icon-duihao2"></text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view class='mask z-100' catchtouchmove="true" :hidden='display==false' @tap='close'></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
import { getCityData } from '@/api/api.js';
|
||||
|
||||
const CACHE_ADDRESS = {};
|
||||
|
||||
export default {
|
||||
props: {
|
||||
display: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
cityShow: {
|
||||
type: Number,
|
||||
default: 3
|
||||
},
|
||||
address: {
|
||||
type:Array | Object,
|
||||
default:[]
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
active: 0,
|
||||
//地址列表
|
||||
addressList: [],
|
||||
selectedArr: [],
|
||||
selectedIndex: -1,
|
||||
is_loading: false,
|
||||
old: { scrollTop: 0 },
|
||||
scrollTop: 0
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
activeId(){
|
||||
return this.selectedIndex == -1 ? 0 : this.selectedArr[this.selectedIndex].id
|
||||
},
|
||||
showMore(){
|
||||
return this.selectedArr.length ? (this.selectedArr[this.selectedArr.length - 1].hasOwnProperty('children') && ((this.cityShow==1 && this.addressList.level<2) || (this.cityShow==2 && this.addressList.level<3) || (this.cityShow==3 && this.addressList.level<4))) : true
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
address(n){
|
||||
this.selectedArr = n ? [...n] : []
|
||||
},
|
||||
display(n){
|
||||
if(!n) {
|
||||
this.addressList = [];
|
||||
this.selectedArr = this.address ? [...this.address] : [];
|
||||
this.selectedIndex = -1;
|
||||
this.is_loading = false;
|
||||
}else{
|
||||
this.loadAddress(0)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadAddress(0)
|
||||
},
|
||||
methods: {
|
||||
change(pid,index){
|
||||
if(this.selectedIndex == index) return;
|
||||
if(pid === -1){
|
||||
pid = this.selectedArr.length ? this.selectedArr[this.selectedArr.length -1].id : 0;
|
||||
}
|
||||
this.selectedIndex = index;
|
||||
this.loadAddress(pid);
|
||||
},
|
||||
loadAddress(pid){
|
||||
if(CACHE_ADDRESS[pid]){
|
||||
this.addressList = CACHE_ADDRESS[pid];
|
||||
return ;
|
||||
}
|
||||
this.is_loading = true;
|
||||
getCityData(pid).then(res=>{
|
||||
this.is_loading = false;
|
||||
CACHE_ADDRESS[pid] = res.data;
|
||||
this.addressList = res.data;
|
||||
})
|
||||
this.goTop()
|
||||
},
|
||||
selected(item){
|
||||
if(this.is_loading) return;
|
||||
if(this.selectedIndex > -1){
|
||||
this.selectedArr.splice(this.selectedIndex + 1,999)
|
||||
this.selectedArr[this.selectedIndex] = item;
|
||||
this.selectedIndex = -1;
|
||||
}else if(!item.pid){
|
||||
this.selectedArr = [item];
|
||||
}else{
|
||||
this.selectedArr.push(item);
|
||||
}
|
||||
if(item.hasOwnProperty('children') && ((this.cityShow==1 && this.addressList[0].level<2) || (this.cityShow==2 && this.addressList[0].level<3) || (this.cityShow==3 && this.addressList[0].level<4))){
|
||||
this.loadAddress(item.id);
|
||||
} else {
|
||||
this.$emit('submit', [...this.selectedArr]);
|
||||
this.$emit('changeClose');
|
||||
}
|
||||
|
||||
this.goTop()
|
||||
},
|
||||
close: function() {
|
||||
this.$emit('changeClose');
|
||||
},
|
||||
scroll : function(e) {
|
||||
this.old.scrollTop = e.detail.scrollTop
|
||||
},
|
||||
goTop: function(e) {
|
||||
this.scrollTop = this.old.scrollTop
|
||||
this.$nextTick(() => {
|
||||
this.scrollTop = 0
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.address-window {
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 101;
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
transform: translate3d(0, 100%, 0);
|
||||
transition: all .3s cubic-bezier(.25, .5, .5, .9);
|
||||
}
|
||||
.address-window.on {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
.address-window .title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
height: 123rpx;
|
||||
line-height: 123rpx;
|
||||
position: relative;
|
||||
}
|
||||
.address-window .title .iconfont {
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
color: #8a8a8a;
|
||||
font-size: 35rpx;
|
||||
}
|
||||
.address-count{
|
||||
.address-selected{
|
||||
padding: 0 30rpx;
|
||||
margin-top: 10rpx;
|
||||
position: relative;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 2rpx solid #f7f7f7;
|
||||
}
|
||||
.selected-list{
|
||||
font-size: 26rpx;
|
||||
color: #282828;
|
||||
line-height: 50rpx;
|
||||
padding-bottom: 10rpx;
|
||||
padding-left: 60rpx;
|
||||
position: relative;
|
||||
&.active{
|
||||
color: var(--view-theme);
|
||||
}
|
||||
&:before,&:after{
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
}
|
||||
&:before{
|
||||
width: 4rpx;
|
||||
height: 100%;
|
||||
background-color: var(--view-theme);
|
||||
top: 0;
|
||||
left: 10rpx;
|
||||
}
|
||||
&:after{
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: var(--view-theme);
|
||||
border-radius: 100%;
|
||||
left: 6rpx;
|
||||
top: 50%;
|
||||
margin-top: -8rpx;
|
||||
}
|
||||
&:first-child,&:last-child{
|
||||
&:before{
|
||||
height: 50%;
|
||||
}
|
||||
}
|
||||
&:first-child{
|
||||
&:before{
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
.iconfont{
|
||||
font-size: 20rpx;
|
||||
float: right;
|
||||
color: #dddddd;
|
||||
}
|
||||
}
|
||||
scroll-view{
|
||||
height: 550rpx;
|
||||
}
|
||||
.address-list{
|
||||
padding: 0 30rpx;
|
||||
margin-top: 20rpx;
|
||||
box-sizing: border-box;
|
||||
.list{
|
||||
.iconfont{
|
||||
float: right;
|
||||
color: #ddd;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
.item-name{
|
||||
display: inline-block;
|
||||
line-height: 50rpx;
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
&.active{
|
||||
color: var(--view-theme);
|
||||
.iconfont{
|
||||
color: var(--view-theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
3
components/authorize/index.vue
Normal file
3
components/authorize/index.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<view></view>
|
||||
</template>
|
||||
92
components/cartDiscount/index.vue
Normal file
92
components/cartDiscount/index.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- 购物车优惠明细 -->
|
||||
<base-drawer mode="bottom" :visible="discountInfo.discount" background-color="transparent" mask maskClosable @close="closeDiscount">
|
||||
<view class="w-full bg--w111-fff rd-t-40rpx py-32">
|
||||
<view class="text-center fs-32 text--w111-333 fw-500">金额明细</view>
|
||||
<scroll-view scroll-y="true" class="mt-32 scroll-content">
|
||||
<view class="p-32">
|
||||
<view class="flex-between-center">
|
||||
<view class="fs-26">商品总价:</view>
|
||||
<view class="fs-28 SemiBold">¥{{discountInfo.deduction.sum_price}}</view>
|
||||
</view>
|
||||
<!-- <view class="flex-between-center mt-38">
|
||||
<view class="fs-26">优惠抵扣:</view>
|
||||
<view class="fs-28 SemiBold">-¥{{$util.$h.Sub(discountInfo.deduction.sum_price,discountInfo.deduction.pay_price)}}</view>
|
||||
</view> -->
|
||||
<view class="flex-between-center mt-38" v-if="discountInfo.deduction.coupon_price">
|
||||
<view class="fs-26">{{discountInfo.coupon.coupon_title}}:</view>
|
||||
<view class="fs-28 SemiBold">-¥{{discountInfo.deduction.coupon_price}}</view>
|
||||
</view>
|
||||
<view class="flex-between-center mt-38" v-if="discountInfo.deduction.first_order_price">
|
||||
<view class="fs-26">新人首单优惠:</view>
|
||||
<view class="fs-28 SemiBold">-¥{{discountInfo.deduction.first_order_price}}</view>
|
||||
</view>
|
||||
<view class="flex-between-center mt-38" v-if="discountInfo.deduction.promotions_price">
|
||||
<view class="fs-26">优惠活动:</view>
|
||||
<view class="fs-28 SemiBold">-¥{{discountInfo.deduction.promotions_price}}</view>
|
||||
</view>
|
||||
<view class="flex-between-center mt-38" v-if="discountInfo.deduction.vip_price">
|
||||
<view class="fs-26">会员优惠:</view>
|
||||
<view class="fs-28 SemiBold">-¥{{discountInfo.deduction.vip_price}}</view>
|
||||
</view>
|
||||
<view class="flex-between-center mt-38" v-if="discountInfo.deduction.channel_price">
|
||||
<view class="fs-26">采购优惠:</view>
|
||||
<view class="fs-28 SemiBold">-¥{{discountInfo.deduction.channel_price}}</view>
|
||||
</view>
|
||||
<view class="flex-between-center mt-44" v-if="discountInfo.deduction.vip_price">
|
||||
<view class="fs-28 fw-500">优惠合计</view>
|
||||
<view class="fs-32 SemiBold font-num">-¥{{$util.$h.Sub(discountInfo.deduction.sum_price,discountInfo.deduction.pay_price)}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view :class="showFooter ? 'show-footer' : 'hide-footer'"></view>
|
||||
</view>
|
||||
</base-drawer>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
|
||||
export default {
|
||||
props: {
|
||||
discountInfo: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
showFooter:{
|
||||
type:Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
components:{
|
||||
baseDrawer
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
closeDiscount(){
|
||||
this.$emit('myevent');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.scroll-content {
|
||||
max-height: 800rpx;
|
||||
}
|
||||
.show-footer{
|
||||
height: calc(194rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
.hide-footer{
|
||||
/* #ifdef H5 */
|
||||
height: calc(194rpx + env(safe-area-inset-bottom));
|
||||
/* #endif */
|
||||
/* #ifdef MP || APP-PLUS */
|
||||
height: calc(100rpx + env(safe-area-inset-bottom));
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
||||
200
components/cartList/index.vue
Normal file
200
components/cartList/index.vue
Normal file
@@ -0,0 +1,200 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- 分类购物车下拉列表 -->
|
||||
<view class="cartList" :class="{'on':cartData.iScart,'show-pd': hideEmpty}" @touchmove.stop.prevent="moveHandle">
|
||||
<view class="title acea-row row-between-wrapper">
|
||||
<view class="name">购物车 <text class="fs-24 text--w111-999 pl-8">(共{{cartData.cartList.length}}件商品)</text> </view>
|
||||
<view class="del acea-row row-middle" @click="subDel">
|
||||
<view class="iconfont icon-ic_delete"></view>清空
|
||||
</view>
|
||||
</view>
|
||||
<view class="list pb-safe">
|
||||
<scroll-view class="scroll-list" scroll-y="true" :style="{
|
||||
'max-height': '800rpx',
|
||||
'margin-bottom': '126rpx'
|
||||
}">
|
||||
<view class="item flex" v-for="(item,index) in cartData.cartList" :key="index">
|
||||
<view class="pictrue">
|
||||
<image v-if="item.productInfo.attrInfo" :src='item.productInfo.attrInfo.image'></image>
|
||||
<image v-else :src='item.productInfo.image'></image>
|
||||
<view class="mantle" v-if="!item.status || !item.attrStatus"></view>
|
||||
</view>
|
||||
<view class="flex-1 flex-col justify-between ml-20">
|
||||
<view class="w-full">
|
||||
<view class="lh-40rpx fs-28 text--w111-333 line2"
|
||||
:class="(item.attrStatus && item.status)?'':'on'">{{item.productInfo.store_name}}</view>
|
||||
<view class="inline-block max-w-460 h-38 lh-38rpx mt-12 bg--w111-f5f5f5 text--w111-999 rd-20rpx px-12 text-center fs-22"
|
||||
v-if="item.productInfo.spec_type && item.attrStatus">
|
||||
<view class="flex">
|
||||
<text class="line1">属性: {{item.productInfo.attrInfo.suk}}</text>
|
||||
<text class="iconfont icon-ic_downarrow fs-24 ml-12"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="inline-block max-w-460 h-38 lh-38rpx mt-12 bg--w111-f5f5f5 text--w111-999 rd-20rpx px-12 text-center fs-22"
|
||||
v-else>
|
||||
<view class="flex">
|
||||
<text class="line1">属性: {{item.productInfo.attrInfo.suk}}</text>
|
||||
<text class="iconfont icon-ic_downarrow fs-24 ml-12"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-between-center mt-20">
|
||||
<baseMoney :money="item.truePrice" symbolSize="24" integerSize="40" decimalSize="24" weight></baseMoney>
|
||||
<view class="flex-y-center" v-if="item.attrStatus && item.status">
|
||||
<view class="flex-center w-48 h-48 rd-30rpx bg--w111-f5f5f5 text--w111-333"
|
||||
:class="{'disabled-btn': item.productInfo.min_qty && item.cart_num == item.productInfo.min_qty}"
|
||||
@click="leaveCart(index, item)">
|
||||
<text class="iconfont icon-ic_Reduce fs-32"></text>
|
||||
</view>
|
||||
<view class="fs-30 text--w111-333 px-20">{{item.cart_num}}</view>
|
||||
<view class="flex-center w-48 h-48 rd-30rpx bg-color text--w111-fff" @click="joinCart(index)">
|
||||
<text class="iconfont icon-ic_increase fs-32"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="noBnt" v-else-if="!item.attrStatus">已售罄</view>
|
||||
<view class="noBnt" v-else-if="!item.status">已下架</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view :class="isFooter ? 'show-footer' : ''"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mask" v-if="cartData.iScart" @click="closeList" @touchmove.stop.prevent="moveHandle"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props:{
|
||||
cartData: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
isFooter: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideEmpty:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
moveHandle(){
|
||||
return false
|
||||
},
|
||||
closeList(){
|
||||
this.$emit('closeList', false);
|
||||
},
|
||||
leaveCart(index,item){
|
||||
if(item.productInfo.min_qty && item.cart_num == item.productInfo.min_qty) return
|
||||
this.$emit('ChangeCartNumDan', false,index);
|
||||
},
|
||||
joinCart(index){
|
||||
this.$emit('ChangeCartNumDan', true,index);
|
||||
},
|
||||
subDel(){
|
||||
this.$emit('ChangeSubDel');
|
||||
},
|
||||
oneDel(id,index){
|
||||
this.$emit('ChangeOneDel',id,index);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.mask{
|
||||
z-index: 99;
|
||||
}
|
||||
.cartList{
|
||||
position: fixed;
|
||||
left:0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
z-index:100;
|
||||
padding: 40rpx 32rpx 0;
|
||||
box-sizing: border-box;
|
||||
border-radius:40rpx 40rpx 0 0;
|
||||
transform: translate3d(0, 100%, 0);
|
||||
transition: all .3s cubic-bezier(.25, .5, .5, .9);
|
||||
&.on{
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
.title{
|
||||
margin-bottom: 32rpx;
|
||||
.name{
|
||||
font-size:32rpx;
|
||||
color: #333;
|
||||
font-weight:500;
|
||||
}
|
||||
.del{
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
.iconfont{
|
||||
margin-right: 8rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.list{
|
||||
max-height: 1000rpx;
|
||||
.item{
|
||||
margin-bottom: 32rpx;
|
||||
.pictrue{
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: 16rpx;
|
||||
position: relative;
|
||||
image{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
.mantle{
|
||||
position: absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background:rgba(255,255,255,0.65);
|
||||
border-radius:16rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.show-pd{
|
||||
/* #ifdef H5 */
|
||||
padding-bottom: calc(100rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
|
||||
padding-bottom: calc(100rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
|
||||
/* #endif */
|
||||
}
|
||||
.noBnt{
|
||||
width:126rpx;
|
||||
height:44rpx;
|
||||
background:#f5f5f5;
|
||||
border-radius:22rpx;
|
||||
text-align: center;
|
||||
line-height: 44rpx;
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
}
|
||||
.max-w-460{
|
||||
max-width: 460rpx;;
|
||||
}
|
||||
.show-footer{
|
||||
/* #ifdef MP || APP-PLUS */
|
||||
height: calc(104rpx + env(safe-area-inset-bottom));
|
||||
/* #endif */
|
||||
|
||||
}
|
||||
.disabled-btn{
|
||||
color: #DEDEDE;
|
||||
}
|
||||
</style>
|
||||
148
components/countDown/index.vue
Normal file
148
components/countDown/index.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<view class="time" :style="justifyLeft">
|
||||
<!-- 倒计时 -->
|
||||
<text class="title red" v-if="tipText.trim()">{{ tipText }}</text>
|
||||
<text class="styleAll" :style="'background:' + bgColor + ';color:' + colors + ';'" v-if="isDay === true">
|
||||
{{ day }}
|
||||
<text class="dayTxt">{{ inDayText }}</text>
|
||||
</text>
|
||||
<text class="timeTxt red" :style="'color:' + dotColor" v-if="dayText">{{ dayText }}</text>
|
||||
<text class="styleAll" :style="'background:' + bgColor + ';color:' + colors + ';'">{{ hour }}</text>
|
||||
<text class="timeTxt red" :style="'color:' + dotColor" v-if="hourText">{{ hourText }}</text>
|
||||
<text class="styleAll" :style="'background:' + bgColor + ';color:' + colors + ';'">{{ minute }}</text>
|
||||
<text class="timeTxt red" :style="'color:' + dotColor" v-if="minuteText">{{ minuteText }}</text>
|
||||
<text class="styleAll" :style="'background:' + bgColor + ';color:' + colors + ';'" v-if="isSecond === true">{{ second }}</text>
|
||||
<text class="timeTxt red" :style="'color:' + dotColor" v-if="secondText">{{ secondText }}</text>
|
||||
<slot name="bottom"></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'countDown',
|
||||
props: {
|
||||
justifyLeft: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//距离开始提示文字
|
||||
tipText: {
|
||||
type: String,
|
||||
default: '倒计时'
|
||||
},
|
||||
inDayText: {
|
||||
type: String,
|
||||
default: '天'
|
||||
},
|
||||
dayText: {
|
||||
type: String,
|
||||
default: '天'
|
||||
},
|
||||
hourText: {
|
||||
type: String,
|
||||
default: '时'
|
||||
},
|
||||
minuteText: {
|
||||
type: String,
|
||||
default: '分'
|
||||
},
|
||||
secondText: {
|
||||
type: String,
|
||||
default: '秒'
|
||||
},
|
||||
datatime: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
isDay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
isSecond: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
colors: {
|
||||
type: String,
|
||||
default: '#e93323'
|
||||
},
|
||||
dotColor: {
|
||||
type: String,
|
||||
default: '#ffffff'
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
day: '00',
|
||||
hour: '00',
|
||||
minute: '00',
|
||||
second: '00',
|
||||
times: null
|
||||
};
|
||||
},
|
||||
watch:{
|
||||
datatime:{
|
||||
handler(val){
|
||||
this.show_time();
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
show_time: function () {
|
||||
let that = this;
|
||||
|
||||
function runTime() {
|
||||
//时间函数
|
||||
let intDiff = that.datatime - 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';
|
||||
clearInterval(that.times);
|
||||
that.times = null;
|
||||
that.$emit('endTime', 1);
|
||||
}
|
||||
}
|
||||
runTime();
|
||||
this.times = setInterval(runTime, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.time {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.timeTxt {
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
</style>
|
||||
219
components/couponListWindow/index.vue
Normal file
219
components/couponListWindow/index.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<view>
|
||||
<base-drawer mode="bottom" :visible="coupon.coupon" background-color="transparent" mask maskClosable @close="close">
|
||||
<view class="w-full bg--w111-f5f5f5 rd-t-40rpx">
|
||||
<view class="flex-around-center fs-30 nav" v-if="coupon.count">
|
||||
<view v-if="coupon.count[0]" class="h-100 flex-y-center" :class="coupon.type === 0 ? 'active' : ''" @tap="setType(0)">通用券</view>
|
||||
<view v-if="coupon.count[1]" class="h-100 flex-y-center" :class="coupon.type === 1 ? 'active' : ''" @tap="setType(1)">品类券</view>
|
||||
<view v-if="coupon.count[2]" class="h-100 flex-y-center" :class="coupon.type === 2 ? 'active' : ''" @tap="setType(2)">商品券</view>
|
||||
<view v-if="coupon.count[3]" class="h-100 flex-y-center" :class="coupon.type === 3 ? 'active' : ''" @tap="setType(3)">品牌券</view>
|
||||
</view>
|
||||
<view class="text-center fs-32 text--w111-333 fw-500 pt-32 relative" v-else>
|
||||
优惠券
|
||||
<view class="w-36 h-36 rd-50-p111- flex-center close-btn" @tap="close">
|
||||
<text class="iconfont icon-ic_close fs-24 text--w111-666"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="px-20 scroll-content">
|
||||
<scroll-view scroll-y="true" style="max-height: 800rpx">
|
||||
<view class="coupon-list" v-if="coupon.list.length">
|
||||
<view v-for="(item, index) in coupon.list" :key="index" @tap="getCouponUser(index, item.id)">
|
||||
<view class="mt-24 h-170 bg--w111-fff text-center rd-16rpx flex">
|
||||
<view class="left-bg bg-gradient">
|
||||
<view class="left-container w-full h-full relative flex-col flex-between-center py-32">
|
||||
<baseMoney :money="item.coupon_price" symbolSize="28" integerSize="52" decimalSize="28" color="#ffffff" isCoupon v-if="item.coupon_type == 1"></baseMoney>
|
||||
<view v-else class="text--w111-fff fs-52">
|
||||
{{ parseFloat(item.coupon_price) / 10 }}
|
||||
<text class="fs-28">折</text>
|
||||
</view>
|
||||
<text class="fs-24 text--w111-fff" v-show="item.use_min_price == 0">无门槛券</text>
|
||||
<text class="fs-24 text--w111-fff" v-show="item.use_min_price != 0">满{{ item.use_min_price }}元可用</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right-box pt-24 pl-24 pr-14 pb-22 flex-1 flex-col justify-between bg--w111-fff">
|
||||
<view class="flex-y-center">
|
||||
<view class="fs-28 fw-500 text--w111-333 lh-40rpx">{{ item.title }}</view>
|
||||
</view>
|
||||
<view class="flex-between-center">
|
||||
<view class="fs-20 text--w111-666 lh-28rpx" v-if="item.coupon_time">领取后{{ item.coupon_time }}天内可用</view>
|
||||
<view class="fs-20 text--w111-666 lh-28rpx" v-else>{{ item.start_time ? item.start_time + '-' : '' }}{{ item.end_time }}</view>
|
||||
<view class="con_btn bg-primary-light text-primary-con w-136 h-52 rd-28rpx fs-22 flex-center" v-if="coupon.count">
|
||||
{{ item.is_use ? '去使用' : '立即领取' }}
|
||||
</view>
|
||||
<view class="iconfont fs-36 pr-14" :class="" v-else>
|
||||
<view class="iconfont icon-a-ic_CompleteSelect font-color" :class="item.receive_type === 4 ? 'svip' : 'font-num'" v-if="item.is_use"></view>
|
||||
<view class="iconfont icon-ic_unselect text--w111-ccc" v-else></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-y-center fs-20 text--w111-999 lh-28rpx mt-20">
|
||||
<text>{{ item.type | typeFilter }}</text>
|
||||
<view v-show="item.rule" @tap.stop="toggleRule(index)">
|
||||
<text class="pl-8 fs-20">| 查看用券规则</text>
|
||||
<text class="iconfont icon-ic_downarrow fs-20 ml-4"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="rule-desc" v-show="item.ruleshow" v-html="item.rule"></view>
|
||||
</view>
|
||||
<view class="h-200"></view>
|
||||
</view>
|
||||
<view class="mt-20" v-else>
|
||||
<emptyPage title="暂无优惠券" src="/statics/images/noCoupon.gif"></emptyPage>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</base-drawer>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { setCouponReceive } from '@/api/api.js';
|
||||
import { HTTP_REQUEST_URL } from '@/config/app';
|
||||
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
|
||||
import emptyPage from '@/components/emptyPage.vue';
|
||||
export default {
|
||||
filters: {
|
||||
typeFilter(val) {
|
||||
let obj = {
|
||||
0: '通用券',
|
||||
1: '品类券',
|
||||
2: '商品券',
|
||||
3: '品牌券'
|
||||
};
|
||||
return obj[val];
|
||||
}
|
||||
},
|
||||
props: {
|
||||
//打开状态 0=领取优惠券,1=使用优惠券
|
||||
openType: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
coupon: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
baseDrawer,
|
||||
emptyPage
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: 0,
|
||||
imgHost: HTTP_REQUEST_URL
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
close: function () {
|
||||
this.$emit('ChangCouponsClone');
|
||||
this.type = 0;
|
||||
},
|
||||
getCouponUser: function (index, id) {
|
||||
let that = this;
|
||||
let list = that.coupon.list;
|
||||
if (list[index].is_use == true && this.openType == 0) {
|
||||
that.$emit('ChangCoupons', 0);
|
||||
return;
|
||||
}
|
||||
switch (this.openType) {
|
||||
case 0:
|
||||
//领取优惠券
|
||||
setCouponReceive(id)
|
||||
.then((res) => {
|
||||
that.$emit('ChangCouponsUseState', index);
|
||||
that.$util.Tips({
|
||||
title: '领取成功'
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.showToast({
|
||||
title: err,
|
||||
icon: 'none'
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 1:
|
||||
that.$emit('ChangCoupons', index);
|
||||
break;
|
||||
}
|
||||
},
|
||||
setType: function (type) {
|
||||
this.type = type;
|
||||
this.$emit('tabCouponType', type);
|
||||
},
|
||||
toggleRule(index) {
|
||||
this.$emit('ruleToggle', index);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.nav {
|
||||
height: 100rpx;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.active {
|
||||
border-bottom: 1px solid var(--view-theme);
|
||||
color: var(--view-theme);
|
||||
}
|
||||
.left-bg {
|
||||
width: 190rpx;
|
||||
height: 170rpx;
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 24rpx 0 0 24rpx;
|
||||
}
|
||||
.right-box {
|
||||
border-radius: 0 24rpx 24rpx 0;
|
||||
}
|
||||
.left-container {
|
||||
background: radial-gradient(circle at 0px 84rpx, #f5f5f5 12rpx, transparent 0px) top;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0px;
|
||||
width: 6rpx;
|
||||
height: 100%;
|
||||
background-image: radial-gradient(circle at 6rpx 12rpx, #ffffff 6rpx, transparent 6rpx);
|
||||
background-size: 6rpx 18rpx;
|
||||
}
|
||||
}
|
||||
.text-primary-con {
|
||||
color: var(--view-theme);
|
||||
}
|
||||
.bg-primary-light {
|
||||
background: var(--view-minorColorT);
|
||||
}
|
||||
.con-border {
|
||||
border: 1px solid var(--view-theme);
|
||||
}
|
||||
.scroll-content {
|
||||
height: 800rpx;
|
||||
.coupon-list{
|
||||
margin-bottom: 120rpx;
|
||||
}
|
||||
}
|
||||
.rule-desc {
|
||||
margin-top: -16rpx;
|
||||
padding: 40rpx 24rpx 24rpx;
|
||||
white-space: pre-wrap;
|
||||
font-size: 20rpx;
|
||||
line-height: 28rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 0 0 16rpx 16rpx;
|
||||
color: #999;
|
||||
}
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
right: 32rpx;
|
||||
top: 36rpx;
|
||||
background-color: #eee;
|
||||
}
|
||||
</style>
|
||||
179
components/couponWindow/index.vue
Normal file
179
components/couponWindow/index.vue
Normal file
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- 优惠券弹窗 -->
|
||||
<view class="coupon-window relative" :class="{ on: window}">
|
||||
<view class="box-1 cover relative" :style="[box1]">
|
||||
<view class="box-2 bg--w111-fff relative px-32">
|
||||
<view class="box-ht cover abs-lt" :style="[boxHt]"></view>
|
||||
<view class="flex-center mt-26 fs-36 lh-60rpx fw-500 relative z-20">
|
||||
恭喜获得<text class="red">{{couponList.length}}张</text>优惠券
|
||||
</view>
|
||||
<view class="box-item mt-16 flex-between-center relative z-20"
|
||||
v-for="(item,index) in couponList" :key="index"
|
||||
:style="[boxItem]">
|
||||
<baseMoney
|
||||
:money="item.coupon_price"
|
||||
symbolSize="32"
|
||||
integerSize="52"
|
||||
decimalSize="32"
|
||||
color="#e93323"
|
||||
isCoupon
|
||||
v-if="item.coupon_type==1"></baseMoney>
|
||||
<view v-else class="font-color SemiBold fs-42 SemiBold">{{parseFloat(item.coupon_price)/10}}折</view>
|
||||
<view>
|
||||
<view class="fs-28 lh-40rpx red w-234 line1">{{item.coupon_title}}</view>
|
||||
<view class="fs-20 lh-28rpx text--w111-666 mt-8" v-if="item.coupon_time">领取后{{item.coupon_time}}天内可用</view>
|
||||
<view class="fs-20 lh-28rpx text--w111-666 mt-8" v-else>{{item.start_time ? item.start_time+'-' : ''}}{{item.end_time === 0 ? '不限时': item.end_time}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="box-3 cover abs-lb" :style="[box3]">
|
||||
<view class="btn-box flex-center fs-34 fw-500" @tap="goPage">立即领取</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="iconfont icon-ic_close1 fs-60 text--w111-fff" @tap="close"></text>
|
||||
</view>
|
||||
<view class='mask' catchtouchmove="true" :hidden="window==false" @touchmove.stop.prevent></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {HTTP_REQUEST_URL} from '@/config/app';
|
||||
export default {
|
||||
props: {
|
||||
window: {
|
||||
type: Boolean | String | Number,
|
||||
default: false,
|
||||
},
|
||||
couponList: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
},
|
||||
},
|
||||
couponImage: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imgHost:HTTP_REQUEST_URL
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
boxHt(){
|
||||
return {
|
||||
backgroundImage: 'url('+ HTTP_REQUEST_URL +'/statics/images/product/new_coupon_bg1.png'+')'
|
||||
}
|
||||
},
|
||||
boxItem(){
|
||||
return {
|
||||
backgroundImage: 'url('+ HTTP_REQUEST_URL +'/statics/images/product/new_coupon_bg2.png'+')'
|
||||
}
|
||||
},
|
||||
box3(){
|
||||
return {
|
||||
backgroundImage: 'url('+ HTTP_REQUEST_URL +'/statics/images/product/new_coupon_bg3.png'+')'
|
||||
}
|
||||
},
|
||||
box1(){
|
||||
return {
|
||||
backgroundImage: 'url('+ HTTP_REQUEST_URL +'/statics/images/product/new_coupon_bg4.png'+')'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goPage(){
|
||||
this.$emit('onColse');
|
||||
uni.navigateTo({
|
||||
url: '/pages/activity/coupon/index'
|
||||
})
|
||||
},
|
||||
close:function(){
|
||||
this.$emit('onColse');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mask {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.coupon-window {
|
||||
width: 574rpx;
|
||||
height: 860rpx;
|
||||
position: fixed;
|
||||
top: 20%;
|
||||
z-index: 10000;
|
||||
left: 50%;
|
||||
margin-left: -286rpx;
|
||||
transform: translate3d(0, -200%, 0);
|
||||
transition: all .3s cubic-bezier(.25, .5, .5, .9);
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.coupon-window.on {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
.box-1{
|
||||
width: 100%;
|
||||
height: 462rpx;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 108rpx;
|
||||
}
|
||||
.box-2{
|
||||
width: 524rpx;
|
||||
max-height: 508rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 188rpx;
|
||||
border-radius: 40rpx 40rpx 0 0;
|
||||
overflow-y: auto;
|
||||
border-radius: 24px;
|
||||
}
|
||||
.box-3{
|
||||
width: 100%;
|
||||
height: 242rpx;
|
||||
}
|
||||
.box-ht{
|
||||
width: 524rpx;
|
||||
height: 136rpx;
|
||||
}
|
||||
.box-item{
|
||||
width: 100%;
|
||||
height: 140rpx;
|
||||
background-size: 100%;
|
||||
padding: 0 40rpx 0 20rpx;
|
||||
}
|
||||
.btn-box{
|
||||
width: 460rpx;
|
||||
height: 88rpx;
|
||||
background: linear-gradient(90deg, #FFD10C 0%, #FEEF4C 100%);
|
||||
border-radius: 44rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 48rpx;
|
||||
}
|
||||
.cover{
|
||||
background-size: cover;
|
||||
}
|
||||
.icon-ic_close1{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 0;
|
||||
}
|
||||
.red{
|
||||
color: #e93323;
|
||||
}
|
||||
.SemiBold{
|
||||
font-family:'SemiBold';
|
||||
}
|
||||
</style>
|
||||
145
components/cusPreviewImg/index.vue
Normal file
145
components/cusPreviewImg/index.vue
Normal file
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<!-- 属性规格放大图轮播 -->
|
||||
<view class="previewImg" v-if="showBox" @touchmove.stop.prevent>
|
||||
<view class="mask" @click="close">
|
||||
<swiper @change="changeSwiper" class="mask-swiper" :current="currentIndex" :circular="circular" :duration="duration">
|
||||
<swiper-item v-for="(src, i) in list" :key="i" class="flex flex-column justify-center align-center">
|
||||
<image class="mask-swiper-img" :src="src.image" mode="widthFix" />
|
||||
<view class="mask_sku">
|
||||
<text class="sku_name">{{src.suk}}</text>
|
||||
<text class="sku_price fs-36 fw-600"><text v-if="src.integral">{{src.integral}} 积分 +</text> <text class="money-fix"></text>{{price || src.price}} 元</text>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<view class="pagebox" v-if="list.length>0">{{ Number(currentIndex) + 1 }} / {{ list.length }}</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'cus-previewImg',
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: () => {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
price:{
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
circular: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 500
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
showBox: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 左右切换
|
||||
changeSwiper(e) {
|
||||
this.currentIndex = e.target.current;
|
||||
this.$emit('changeSwitch',e.target.current)
|
||||
},
|
||||
open(current) {
|
||||
if (!current || !this.list.length) return;
|
||||
this.currentIndex = this.list.map((item)=>item.suk).indexOf(current);
|
||||
this.showBox = true;
|
||||
},
|
||||
close() {
|
||||
this.showBox = false;
|
||||
}
|
||||
// shareFriend(){
|
||||
// this.$emit('shareFriend')
|
||||
// }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@mixin full {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.previewImg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 4100;
|
||||
@include full;
|
||||
.mask {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #000;
|
||||
opacity: 1;
|
||||
z-index: 8;
|
||||
@include full;
|
||||
&-swiper {
|
||||
@include full;
|
||||
&-img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.pagebox{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 164rpx;
|
||||
z-index: 300;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.mask_sku{
|
||||
color: #fff;
|
||||
max-width: 80%;
|
||||
z-index: 300;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 30rpx;
|
||||
.sku_name{
|
||||
font-size: 12px;
|
||||
border: 1px solid #fff;
|
||||
padding: 10rpx 30rpx 10rpx;
|
||||
border-radius: 40px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.sku_price{
|
||||
padding-top: 10px;
|
||||
}
|
||||
.money-fix{
|
||||
font-size: 20rpx;
|
||||
font-weight: normal;
|
||||
padding-right: 4rpx;
|
||||
}
|
||||
}
|
||||
.font12{
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.share_btn{
|
||||
position: absolute;
|
||||
top:70rpx;
|
||||
right:50rpx;
|
||||
font-size: 40rpx;
|
||||
color:#fff;
|
||||
z-index: 300;
|
||||
}
|
||||
.flex-column{flex-direction: column;}
|
||||
.justify-center {justify-content: center;}
|
||||
.align-center {align-items: center;}
|
||||
</style>
|
||||
98
components/customForm/index.vue
Normal file
98
components/customForm/index.vue
Normal file
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<!-- 自定义组件 -->
|
||||
<view class='wrapper card' v-if="customForm && customForm.length && isShow">
|
||||
<view class='item acea-row row-between' v-for="(item,index) in customForm" :key="index" v-if="(item.value && ['uploadPicture','dateranges'].indexOf(item.name) == -1) || (item.value.length && ['uploadPicture','dateranges'].indexOf(item.name) != -1)">
|
||||
<view class="title">{{item.titleConfig.value}}:</view>
|
||||
<view v-if="item.name == 'uploadPicture'" class='conter'>
|
||||
<view class='pictrue' v-for="(img,indexn) in item.value" :key="indexn">
|
||||
<image :src='img' mode="aspectFill" @click='getCustomForm(index,indexn)'></image>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else-if="item.name == 'dateranges'" class="conter">
|
||||
<text v-if="item.value.length">{{item.value[0]+'/'+item.value[1]}}</text>
|
||||
</view>
|
||||
<view v-else class='conter'>{{item.value}}</view>
|
||||
</view>
|
||||
<slot name="bottom"></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'customForm',
|
||||
props: {
|
||||
customForm:{
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShow:0
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
customForm (value) {
|
||||
if(value && value.length){
|
||||
value.forEach((item)=>{
|
||||
if(item.value){
|
||||
return this.isShow = 1
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
methods: {
|
||||
getCustomForm: function(index,indexn) {
|
||||
uni.previewImage({
|
||||
urls: this.customForm[index].value,
|
||||
current: this.customForm[index].value[indexn]
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.wrapper{
|
||||
background-color: #fff;
|
||||
margin-top: 6px;
|
||||
padding: 15px;
|
||||
}
|
||||
.wrapper .item {
|
||||
font-size: 28rpx;
|
||||
color: #282828;
|
||||
}
|
||||
|
||||
.wrapper .item .title{
|
||||
width: 200rpx;
|
||||
}
|
||||
|
||||
.wrapper .item~.item {
|
||||
margin-top: 20rpx;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.wrapper .item .conter {
|
||||
color: #868686;
|
||||
width: 460rpx;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: flex-end;
|
||||
text-align: right;
|
||||
.pictrue{
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-left: 6rpx;
|
||||
image{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
732
components/discoverVideo/index.vue
Normal file
732
components/discoverVideo/index.vue
Normal file
@@ -0,0 +1,732 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="fixed-lt pl-20 z-4000 h-80 flex-y-center"
|
||||
:style="{top: sysHeight + 'px'}" v-if="fullVideo" @tap="backPage">
|
||||
<text class="iconfont icon-ic_leftarrow fs-40 text--w111-fff"></text>
|
||||
</view>
|
||||
<view>
|
||||
<swiper class="video-swiper"
|
||||
vertical
|
||||
:circular="false"
|
||||
:autoplay="false"
|
||||
:duration="300"
|
||||
:current="swiperCurrent"
|
||||
@change="videoChange">
|
||||
<swiper-item v-for="(item, index) in swiperData" :key="index">
|
||||
<view class="swiper-video-item h-full">
|
||||
<view class="h-full relative" v-if="item.content_type == 2">
|
||||
<video
|
||||
:id="item.id + 'k' + index"
|
||||
:muted="false"
|
||||
:autoplay="index === swiperCurrent"
|
||||
:loop="true"
|
||||
:controls="false"
|
||||
:http-cache="true"
|
||||
:page-gesture="false"
|
||||
:show-fullscreen-btn="false"
|
||||
:show-loading="false"
|
||||
:show-center-play-btn="false"
|
||||
:enable-progress-gesture="false"
|
||||
:src="item.video_url"
|
||||
@ended="ended"
|
||||
@click="tapVideoHover($event)"
|
||||
class="w-full h-full"
|
||||
></video>
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="abs-center w-full h-full flex-center" @tap="playVideo" v-if="!isPlay && Auth.isWeixin()">
|
||||
<image src="@/static/images/stop.png" mode="" class="w-160 h-160"></image>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view class="flex-y-center h-full" v-else>
|
||||
<swiper
|
||||
class="w-full h-full"
|
||||
circular
|
||||
:autoplay="index === swiperCurrent"
|
||||
:current="imgCurrent"
|
||||
:interval="4000"
|
||||
:duration="500"
|
||||
@change="photoChange">
|
||||
<swiper-item v-for="(photo, i) in item.slider_image" :key="i">
|
||||
<view class="h-full flex-y-center">
|
||||
<image :src="photo" mode="widthFix" class="w-full"></image>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<view class="right-action text--w111-fff flex-col flex-y-center z-800"
|
||||
:class="{'action-box':showFooter,'full-action': fullVideo}">
|
||||
<view class="relative">
|
||||
<view class="w-88 h-88 rd-50-p111- avatar-box" v-if="currentData && currentData.author_image" >
|
||||
<image :src="currentData.author_image" class="w-full h-full rd-50-p111-" @tap="toUser()"></image>
|
||||
</view>
|
||||
<view class="w-88 h-88 rd-50-p111- avatar-box" v-else></view>
|
||||
<view class="follow-icon flex-center" v-if="!currentData.is_follow && !currentData.is_self"
|
||||
@tap="followFun">
|
||||
<text class="iconfont icon-ic_increase fs-20 text--w111-fff"></text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 2.点赞 -->
|
||||
<view class="mt-50 flex-col flex-y-center" @tap="contentLike">
|
||||
<text class="iconfont fs-72 icon-ic_love_2 shadow" :class="{'like-heart': currentData.is_like}"></text>
|
||||
<text class="fs-22 pt-10 text-center shadow">{{currentData.like_num > 0 ? currentData.like_num : '点赞'}}</text>
|
||||
</view>
|
||||
<!-- 3.评论 -->
|
||||
<view class="mt-36 flex-col flex-y-center" @tap="toggleReplyDrawer" v-if="replyStatus">
|
||||
<text class="iconfont icon-icon_comment fs-64 shadow"></text>
|
||||
<text class="fs-22 pt-16 text-center shadow">{{currentData.comment_num > 0 ? currentData.comment_num : '评论'}}</text>
|
||||
</view>
|
||||
<!-- 3.分享 -->
|
||||
<!-- #ifdef H5 || APP-PLUS -->
|
||||
<view class="mt-36 flex-col flex-y-center" @tap="openShare">
|
||||
<text class="iconfont icon-icon_transmit fs-66 shadow"></text>
|
||||
<text class="fs-22 pt-10 shadow">分享</text>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button class="mt-36 flex-col flex-y-center bg-transparent text--w111-fff" open-type="share" hover-class="none" @tap="openShare">
|
||||
<text class="iconfont icon-icon_transmit fs-66 shadow"></text>
|
||||
<text class="fs-22 pt-10 shadow">分享</text>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<view class="mt-36 flex-col flex-y-center relative" v-if="showMore">
|
||||
<text class="iconfont icon-ic_more fs-60 shadow" @tap="()=>{showBubble = !showBubble}"></text>
|
||||
<view class="bubble_box">
|
||||
<view class="bubble text--w111-333 flex-col justify-between" v-if="showBubble">
|
||||
<view class="flex-y-center pl-16" @tap="editTo">
|
||||
<text class="iconfont icon-ic_edit"></text>
|
||||
<text class="fs-26 pl-18">编辑</text>
|
||||
</view>
|
||||
<view class="x-line"></view>
|
||||
<view class="flex-y-center pl-16" @tap="delContent">
|
||||
<text class="iconfont icon-ic_delete"></text>
|
||||
<text class="fs-26 pl-18">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-36 flex-col flex-y-center"
|
||||
v-if="currentData && currentData.product && currentData.product.length" @tap="getProList">
|
||||
<image src="@/static/img/discover_cart.png" class="w-66 h-66"></image>
|
||||
</view>
|
||||
<view v-if="showMore && !currentData.product.length" class="h-24"></view>
|
||||
</view>
|
||||
<view class="fixed-desc w-full text--w111-fff" :class="{'hide-tab':showFooter,'full-tab':fullVideo}">
|
||||
<view class="box mb-32">
|
||||
<view class="w-560 lh-42rpx fs-28 fw-500">@{{currentData.author || '用户已注销'}}</view>
|
||||
<view class="w-560 content-box lh-42rpx fs-28 mt-20">
|
||||
<BaseTextMore
|
||||
:content="currentData.title + currentData.content"
|
||||
fontColor="rgba(255,255,255,0.9)"
|
||||
actionFontColor="#fff"
|
||||
:font-size="28"
|
||||
:rows="2"
|
||||
expand-text="展开"
|
||||
collapse-text="收起"></BaseTextMore>
|
||||
</view>
|
||||
<view class="w-560 content-box lh-42rpx fs-28 mt-10 text--w111-fff">
|
||||
<text class="pr-10" v-for="(topic,i) in currentData.topic" :key="i"
|
||||
@tap="authTo('/pages/discover/discoverTopic/index?id=' + topic.id + '&name=' + topic.name)">
|
||||
#{{topic.name}}</text>
|
||||
</view>
|
||||
<scroll-view scroll-x="true" class="white-nowrap vertical-middle w-584 mt-24" show-scrollbar="false"
|
||||
v-if="currentData && currentData.product && currentData.product.length">
|
||||
<view class="inline-block mr-30" v-for="(pro,k) in currentData.product" :key="k">
|
||||
<view class="w-444 bg--w111-fff rd-16rpx p-16 b-e flex-between-center"
|
||||
@tap="goDetail(pro.id)">
|
||||
<image :src="pro.image" class="w-104 h-104 rd-8rpx"></image>
|
||||
<view class="flex-1 pl-14">
|
||||
<view class="w-282 line1 fs-26 pb-20 text--w111-333">{{pro.store_name}}</view>
|
||||
<view class="flex-between-center">
|
||||
<baseMoney :money="pro.price" symbolSize="22" integerSize="32" decimalSize="24" color="#333" weight></baseMoney>
|
||||
<view class="w-92 h-40 rd-20rpx bg-color flex-center text--w111-fff fs-22">购买</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="w-full flex-center pb-32 mt-24 relative z-80"
|
||||
style="left: -20rpx;"
|
||||
v-if="imgList.length && imgList.length > 1">
|
||||
<block v-for="(_, index) in imgList" :key="index">
|
||||
<view class="dot_item h-6 rd-2rpx" :style="{ 'background-color': imgCurrent >= index ? '#fff' : 'rgba(255,255,255,0.4)', width: dotWidth + 'rpx' }"></view>
|
||||
</block>
|
||||
</view>
|
||||
<view v-else class="h-34"></view>
|
||||
</view>
|
||||
<base-drawer
|
||||
mode="bottom"
|
||||
:visible="showProDrawer"
|
||||
zIndex="2000"
|
||||
background-color="transparent"
|
||||
mask
|
||||
maskClosable
|
||||
@close="closeDrawer">
|
||||
<view class="w-full bg--w111-fff text--w111-333 rd-t-40rpx relative">
|
||||
<view class="fs-30 pt-48 pb-44 pl-32">TA提到的宝贝</view>
|
||||
<view class="close-btn flex-center" @tap="closeDrawer()">
|
||||
<text class="iconfont icon-ic_close text--w111-666 fs-24"></text>
|
||||
</view>
|
||||
<view class="px-30">
|
||||
<scroll-view scroll-y="true" style="max-height: 722rpx;">
|
||||
|
||||
<view class="flex-between-center pro-item"
|
||||
v-for="(item,index) in productList" :key="index"
|
||||
@tap="goDetail(item.id)">
|
||||
<view class="flex-1 flex">
|
||||
<image class="w-200 h-200 rd-16rpx" :src='item.image' mode="aspectFill"></image>
|
||||
<view class="h-200 flex-1 flex-col justify-between pl-30">
|
||||
<view>
|
||||
<view class="h-68 lh-34rpx fs-30 line2">{{item.store_name}}</view>
|
||||
<view class="w-full flex items-end flex-wrap mt-16">
|
||||
<BaseTag
|
||||
:text="label.label_name"
|
||||
:color="label.color"
|
||||
:background="label.bg_color"
|
||||
:borderColor="label.border_color"
|
||||
:circle="label.border_color ? true : false"
|
||||
:imgSrc="label.icon"
|
||||
v-for="(label, idx) in item.store_label" :key="idx"></BaseTag>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-between-center">
|
||||
<view class="flex-y-center">
|
||||
<baseMoney :money="item.price" symbolSize="26" integerSize="40" decimalSize="26" weight></baseMoney>
|
||||
<view class="text--w111-999 fs-26 pl-12 text-line">{{item.ot_price}}</view>
|
||||
</view>
|
||||
<view class="w-136 h-52 rd-30rpx flex-center text--w111-fff fs-22 bg-color">立即购买</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="!productList.length">
|
||||
<emptyPage title="暂无商品,去看点别的吧~" ></emptyPage>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view :class="{'hide-footer':!showFooter,'show-footer': showFooter}">
|
||||
<view :class="{'h-100':showFooter}"></view>
|
||||
</view>
|
||||
</view>
|
||||
</base-drawer>
|
||||
<replyList
|
||||
:visible="showReply"
|
||||
:community_id="community_id"
|
||||
:comment_num="comment_num"
|
||||
:addReply="addReply"
|
||||
:showFooter="showFooter"
|
||||
@closeDrawer="closeDrawer"
|
||||
@commentAdd="commentAdd"></replyList>
|
||||
<tuiModal
|
||||
:show="showDelete"
|
||||
title="确认删除该内容"
|
||||
:maskClosable="false"
|
||||
@click="handleDelete"></tuiModal>
|
||||
<view class="notice-modal" :style="{'top': sysHeight + 52 + 'px'}" v-if="fullVideo">
|
||||
<view class="w-full h-full container text--w111-fff" v-if="currentData.is_verify == -2" >
|
||||
<view class="flex-y-center fs-28 fw-500">
|
||||
<text class="iconfont icon-icon_clock1 fs-30"></text>
|
||||
<text class="pl-20">平台强制下架,内容仅自己可见</text>
|
||||
</view>
|
||||
<view class="fs-22 pt-14 pl-48">发布的内容涉及政治敏感词汇,请修改后重新发布!</view>
|
||||
</view>
|
||||
<view class="w-full h-full container text--w111-fff" v-if="currentData.is_verify == -1" >
|
||||
<view class="flex-y-center fs-28 fw-500">
|
||||
<text class="iconfont icon-icon_clock1 fs-30"></text>
|
||||
<text class="pl-20">审核未通过,内容仅自己可见</text>
|
||||
</view>
|
||||
<view class="fs-22 pt-14 pl-48">{{currentData.refusal}}</view>
|
||||
</view>
|
||||
<view class="w-full h-full container text--w111-fff" v-if="currentData.is_verify == 0" >
|
||||
<view class="flex-y-center fs-28 fw-500">
|
||||
<text class="iconfont icon-icon_clock1 fs-30"></text>
|
||||
<text class="pl-20">正在审核,内容仅自己可见</text>
|
||||
</view>
|
||||
<view class="fs-22 pt-14 pl-48">发布的内容审核通过后,将在展示首页展示!</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
let sysHeight = uni.getWindowInfo().statusBarHeight;
|
||||
import { HTTP_REQUEST_URL } from '@/config/app';
|
||||
import emptyPage from '@/components/emptyPage.vue';
|
||||
import replyList from "@/components/discoverVideo/replyList.vue"
|
||||
import tuiModal from "@/components/tui-modal/index.vue";
|
||||
import BaseTextMore from "@/components/BaseTextMore.vue"
|
||||
import { getProductslist } from "@/api/store.js";
|
||||
import {
|
||||
communityLikeApi,
|
||||
communitySetInsterestApi,
|
||||
communityDeleteApi,
|
||||
communityShareApi,
|
||||
communityBrowseApi,
|
||||
} from "@/api/community.js"
|
||||
import { mapGetters } from 'vuex';
|
||||
import { toLogin } from "@/libs/login.js"
|
||||
// #ifdef H5
|
||||
import Auth from '@/libs/wechat.js';
|
||||
// #endif
|
||||
export default {
|
||||
name: 'discoverSwiperVideo',
|
||||
props: {
|
||||
swiperData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
showFooter:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
fullVideo:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
replyStatus:{
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
addReply:{
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sysHeight,
|
||||
swiperCurrent: 0,
|
||||
imgList: [],
|
||||
imgCurrent: 0,
|
||||
isPlay: false,
|
||||
showProDrawer:false,
|
||||
productList:[],
|
||||
showBubble:false,
|
||||
showReply:false,
|
||||
community_id:'',
|
||||
comment_num:'',
|
||||
currentData:{
|
||||
author:'',
|
||||
author_image:'',
|
||||
title:'',
|
||||
content:'',
|
||||
product:[],
|
||||
slider_image:[],
|
||||
is_follow:0,
|
||||
is_self:0
|
||||
},
|
||||
showDelete:false,
|
||||
isExpanded:false,
|
||||
startY: 0,
|
||||
moveY: 0,
|
||||
threshold: 50, // 滑动阈值
|
||||
// #ifdef H5
|
||||
Auth,
|
||||
// #endif
|
||||
};
|
||||
},
|
||||
components:{
|
||||
emptyPage,
|
||||
replyList,
|
||||
tuiModal,
|
||||
BaseTextMore
|
||||
},
|
||||
watch:{
|
||||
swiperData:{
|
||||
handler(nVal){
|
||||
this.currentData = nVal[this.swiperCurrent];
|
||||
if(this.currentData && this.currentData.slider_image && this.currentData.slider_image.length){
|
||||
this.imgList = this.currentData.slider_image;
|
||||
}
|
||||
//初始化记录第一个浏览的内容
|
||||
if(this.currentData){
|
||||
this.lookVideo();
|
||||
}
|
||||
},
|
||||
immediate:true
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['isLogin','uid']),
|
||||
dotWidth() {
|
||||
let windowWidth = uni.getWindowInfo().windowWidth;
|
||||
return (windowWidth * 2 - (20 + (this.imgList.length) * 12)) / this.imgList.length;
|
||||
},
|
||||
showMore(){
|
||||
if(this.currentData && this.currentData.relation_id == this.uid && this.isLogin){
|
||||
return true
|
||||
}else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleTouchStart(e) {
|
||||
this.startY = e.touches[0].pageY;
|
||||
},
|
||||
handleTouchMove(e) {
|
||||
this.moveY = e.touches[0].pageY;
|
||||
},
|
||||
handleTouchEnd() {
|
||||
const diffY = this.moveY - this.startY;
|
||||
if (diffY > this.threshold) {
|
||||
if (this.swiperCurrent > 0) {
|
||||
this.videoChange({detail: {current: this.swiperCurrent - 1}});
|
||||
}
|
||||
} else if (diffY < -this.threshold) {
|
||||
this.videoChange({detail: {current: this.swiperCurrent + 1}});
|
||||
}
|
||||
},
|
||||
backPage(){
|
||||
let pages = getCurrentPages(); // 获取当前打开过的页面路由数,
|
||||
if (pages.length > 1) {
|
||||
uni.navigateBack()
|
||||
} else {
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
},
|
||||
playVideo(){
|
||||
uni.createVideoContext(this.swiperData[this.swiperCurrent].id + 'k' + this.swiperCurrent, this).play();
|
||||
this.isPlay = true;
|
||||
},
|
||||
tapVideoHover(e) {
|
||||
if(this.isPlay){
|
||||
uni.createVideoContext(this.swiperData[this.swiperCurrent].id + 'k' + this.swiperCurrent, this).pause();
|
||||
this.isPlay = false;
|
||||
}else{
|
||||
uni.createVideoContext(this.swiperData[this.swiperCurrent].id + 'k' + this.swiperCurrent, this).play();
|
||||
this.isPlay = true;
|
||||
}
|
||||
|
||||
},
|
||||
ended() {},
|
||||
videoChange(event) {
|
||||
console.log(event);
|
||||
const newIndex = event.detail.current;
|
||||
// 暂停当前视频
|
||||
if (this.swiperCurrent !== newIndex) {
|
||||
uni.createVideoContext(this.swiperData[this.swiperCurrent].id + 'k' + this.swiperCurrent, this).pause();
|
||||
this.swiperCurrent = newIndex;
|
||||
// 播放新视频
|
||||
uni.createVideoContext(this.swiperData[this.swiperCurrent].id + 'k' + this.swiperCurrent, this).play();
|
||||
this.currentData = this.swiperData[this.swiperCurrent];
|
||||
this.showBubble = false;
|
||||
this.$emit('onSwiper',this.swiperCurrent);
|
||||
}
|
||||
if(this.swiperData[this.swiperCurrent].slider_image.length){
|
||||
this.imgList = this.swiperData[this.swiperCurrent].slider_image;
|
||||
|
||||
}else{
|
||||
this.imgList = [];
|
||||
}
|
||||
this.imgCurrent = 0;
|
||||
this.lookVideo();
|
||||
},
|
||||
lookVideo(){
|
||||
if(this.isLogin){
|
||||
communityBrowseApi(this.currentData.id).catch(err=>{
|
||||
console.error(err);
|
||||
})
|
||||
}
|
||||
},
|
||||
photoChange(e) {
|
||||
this.imgCurrent = e.detail.current;
|
||||
},
|
||||
goDetail(id){
|
||||
let url = `/pages/goods_details/index?id=${id}`
|
||||
this.$util.JumpPath(url);
|
||||
},
|
||||
editTo(){
|
||||
uni.navigateTo({
|
||||
url: '/pages/discover/discoverCreate/index?id=' + this.currentData.id
|
||||
})
|
||||
},
|
||||
delContent(){
|
||||
this.showDelete = true;
|
||||
this.showBubble = false;
|
||||
},
|
||||
handleDelete(e){
|
||||
let index = e.index;
|
||||
let that = this;
|
||||
if(index == 1){
|
||||
communityDeleteApi(this.currentData.id).then(res=>{
|
||||
this.showDelete = false;
|
||||
return this.$util.Tips({
|
||||
title: res.msg
|
||||
},{
|
||||
tab:4,
|
||||
url:'/pages/discoverIndex/index'
|
||||
});
|
||||
}).catch(err => {
|
||||
this.showDelete = false;
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
});
|
||||
}else{
|
||||
this.showDelete = false;
|
||||
}
|
||||
},
|
||||
getProList(){
|
||||
let data = {
|
||||
ids: this.currentData.product_id.toString()
|
||||
};
|
||||
getProductslist(data).then(res=>{
|
||||
this.productList = res.data;
|
||||
this.showProDrawer = true;
|
||||
})
|
||||
},
|
||||
toUser(){
|
||||
uni.navigateTo({
|
||||
url: '/pages/discover/discoverUser/index?id=' + this.currentData.relation_id
|
||||
})
|
||||
},
|
||||
authTo(url){
|
||||
uni.navigateTo({
|
||||
url: url
|
||||
});
|
||||
},
|
||||
toggleReplyDrawer(){
|
||||
this.community_id = this.currentData.id;
|
||||
this.comment_num = this.currentData.comment_num;
|
||||
if(this.isLogin){
|
||||
this.showReply = true;
|
||||
}else{
|
||||
toLogin();
|
||||
}
|
||||
|
||||
},
|
||||
contentLike(){
|
||||
if(!this.isLogin) {
|
||||
toLogin();
|
||||
}
|
||||
let id = this.currentData.id;
|
||||
let status = this.currentData.is_like == 1 ? 0 : 1;
|
||||
let that = this;
|
||||
communityLikeApi(id,{status}).then(res=>{
|
||||
that.$emit('onLike',{index:that.swiperCurrent,status:status});
|
||||
}).catch(err=>{
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
})
|
||||
},
|
||||
closeDrawer(){
|
||||
this.showReply = false;
|
||||
this.showProDrawer = false;
|
||||
},
|
||||
followFun(){
|
||||
if(!this.isLogin) {
|
||||
toLogin();
|
||||
}
|
||||
communitySetInsterestApi(this.currentData.relation_id,{status:1}).then(res=>{
|
||||
this.$emit('followChange',{index:this.swiperCurrent});
|
||||
}).catch(err => {
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
});
|
||||
},
|
||||
commentAdd(data){
|
||||
if(data.type == 1){
|
||||
this.comment_num++;
|
||||
}else{
|
||||
this.comment_num = this.comment_num - data.num;
|
||||
}
|
||||
},
|
||||
openShare(){
|
||||
let that = this;
|
||||
if(that.isLogin){
|
||||
communityShareApi(that.currentData.id).catch(err=>{
|
||||
console.error(err);
|
||||
})
|
||||
// #ifdef H5
|
||||
uni.setClipboardData({
|
||||
data: `${HTTP_REQUEST_URL}/pages/discover/discoverVideo/index?id=${that.currentData.id}&spid=${that.uid}`,
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: '链接已复制'
|
||||
})
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
this.$emit('onShare',that.currentData);
|
||||
// #endif
|
||||
}else{
|
||||
toLogin();
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.video-swiper {
|
||||
height: 100vh;
|
||||
}
|
||||
.z-4000{
|
||||
z-index: 4000;
|
||||
}
|
||||
.avatar-box{
|
||||
border: 3rpx solid #FFFFFF;
|
||||
}
|
||||
.bg-transparent{
|
||||
background-color: transparent;
|
||||
}
|
||||
.text-line{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.hide-footer{
|
||||
padding-bottom: 30rpx;
|
||||
}
|
||||
.show-footer{
|
||||
padding-bottom: calc(30rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
.right-action {
|
||||
position: fixed;
|
||||
right: 20rpx;
|
||||
/* #ifdef H5 */
|
||||
bottom: 162rpx;
|
||||
/* #endif */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
bottom: 62rpx;
|
||||
/* #endif */
|
||||
width: 88rpx;
|
||||
}
|
||||
.action-box{
|
||||
/* #ifdef MP-WEIXIN */
|
||||
bottom: calc(162rpx + env(safe-area-inset-bottom));
|
||||
/* #endif */
|
||||
}
|
||||
.full-action{
|
||||
/* #ifdef H5 */
|
||||
bottom: 64rpx !important;
|
||||
/* #endif */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
bottom: calc(64rpx + env(safe-area-inset-bottom)) !important;
|
||||
/* #endif */
|
||||
}
|
||||
.shadow{
|
||||
text-shadow: 0px 2rpx 4rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.fixed-desc {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
padding-left: 20rpx;
|
||||
z-index: 10;
|
||||
/* #ifdef H5 */
|
||||
bottom: 100rpx;
|
||||
/* #endif */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
bottom: 0;
|
||||
/* #endif */
|
||||
background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.3) 100%);
|
||||
.box {
|
||||
width: 584rpx;
|
||||
}
|
||||
.w-584 {
|
||||
width: 584rpx;
|
||||
}
|
||||
}
|
||||
.content-box{
|
||||
max-height: 400rpx;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.hide-tab{
|
||||
/* #ifdef MP-WEIXIN */
|
||||
bottom: calc(100rpx + env(safe-area-inset-bottom));
|
||||
/* #endif */
|
||||
}
|
||||
.full-tab{
|
||||
/* #ifdef H5 */
|
||||
bottom: 0 !important;
|
||||
/* #endif */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
bottom: env(safe-area-inset-bottom) !important;
|
||||
/* #endif */
|
||||
}
|
||||
.dot_item ~ .dot_item {
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
.follow-icon{
|
||||
position: absolute;
|
||||
bottom: -10rpx;
|
||||
left: 24rpx;
|
||||
width: 42rpx;
|
||||
height: 42rpx;
|
||||
border-radius: 50%;
|
||||
background-color: var(--view-theme);
|
||||
|
||||
}
|
||||
.like-heart{
|
||||
color: #e93323;
|
||||
}
|
||||
.pro-item ~ .pro-item{
|
||||
margin-top: 42rpx;
|
||||
}
|
||||
|
||||
.bubble_box{
|
||||
position: absolute;
|
||||
top: -64rpx;
|
||||
left: -208rpx;
|
||||
width: 184rpx;
|
||||
z-index: 999;
|
||||
.bubble{
|
||||
width: 184rpx;
|
||||
height: 198rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 15rpx 0rpx rgba(0,0,0,0.102);
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx 16rpx 30rpx 16rpx;
|
||||
position: relative;
|
||||
&:after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
top: 74rpx;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 10px solid transparent;
|
||||
border-bottom: 10px solid transparent;
|
||||
border-left: 10px solid #fff;
|
||||
}
|
||||
}
|
||||
.x-line{
|
||||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.10);
|
||||
}
|
||||
}
|
||||
.notice-modal{
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 690rpx;
|
||||
background: rgba(51, 51, 51, 0.7);
|
||||
border-radius: 10rpx;
|
||||
.container{
|
||||
padding: 26rpx 30rpx;
|
||||
.icon-icon_clock1{
|
||||
color: rgba(252, 131, 39, 1);
|
||||
}
|
||||
.icon-a-ic_tanhao1{
|
||||
color: rgba(233, 51, 35, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
.close-btn{
|
||||
position: absolute;
|
||||
right: 28rpx;
|
||||
top: 28rpx;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #eee;
|
||||
|
||||
}
|
||||
</style>
|
||||
344
components/discoverVideo/replyList.vue
Normal file
344
components/discoverVideo/replyList.vue
Normal file
@@ -0,0 +1,344 @@
|
||||
<script>
|
||||
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
|
||||
import emptyPage from '@/components/emptyPage.vue';
|
||||
import tuiModal from "@/components/tui-modal/index.vue"
|
||||
import { mapGetters } from "vuex";
|
||||
import {
|
||||
communityReplySaveApi,
|
||||
communityReplyListApi,
|
||||
communityReplyLikeApi,
|
||||
communityReplyDeleteApi,
|
||||
} from "@/api/community.js";
|
||||
export default {
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
community_id:{
|
||||
type: Number | String,
|
||||
default: ''
|
||||
},
|
||||
comment_num:{
|
||||
type: Number | String,
|
||||
default: 0
|
||||
},
|
||||
ensureInfo: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
showFooter:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
addReply:{
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
comment:'',
|
||||
comment_reply_id:'',
|
||||
replyIndex:'',
|
||||
replyList:[],
|
||||
placeholder:'快来说点儿什么吧...',
|
||||
showModal:false,
|
||||
reduceNum:0,
|
||||
focus:false,
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
community_id(val){
|
||||
if(val){
|
||||
this.getReply()
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
baseDrawer,
|
||||
emptyPage,
|
||||
tuiModal
|
||||
},
|
||||
computed:{
|
||||
...mapGetters(['isLogin','uid']),
|
||||
},
|
||||
methods: {
|
||||
closeDrawer() {
|
||||
this.$emit('closeDrawer');
|
||||
},
|
||||
getReply(){
|
||||
let params = {
|
||||
community_id:this.community_id,
|
||||
reply_id:'',
|
||||
};
|
||||
communityReplyListApi(params).then(res=>{
|
||||
if(res.data.list.length){
|
||||
res.data.list.map(item=>{
|
||||
this.$set(item,'show',false);
|
||||
})
|
||||
this.replyList = res.data.list;
|
||||
}else{
|
||||
this.replyList = [];
|
||||
}
|
||||
}).catch(err => {
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
});
|
||||
},
|
||||
sendText(){
|
||||
if(!this.isLogin) return this.$util.Tips({
|
||||
title: '请登录'
|
||||
});
|
||||
if(this.comment == '') return this.$util.Tips({
|
||||
title: '请输入评论内容'
|
||||
});
|
||||
let data = {
|
||||
community_id:this.community_id,
|
||||
comment_reply_id:this.comment_reply_id,
|
||||
content:this.comment
|
||||
};
|
||||
communityReplySaveApi(data).then(res=>{
|
||||
this.comment_reply_id = '';
|
||||
this.comment = '';
|
||||
this.placeholder = '快来说点儿什么吧...';
|
||||
this.$emit('onCommentAdd',{type:1,num:1});
|
||||
this.getReply();
|
||||
this.hide();
|
||||
return this.$util.Tips({
|
||||
title: res.msg
|
||||
});
|
||||
}).catch(err => {
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
});
|
||||
},
|
||||
showReply(id,author){
|
||||
this.comment_reply_id = id;
|
||||
this.placeholder = `回复:${author}`;
|
||||
},
|
||||
showMore(item,index,type){
|
||||
this.replyIndex = index;
|
||||
if(type){
|
||||
let params = {
|
||||
community_id:this.community_id,
|
||||
reply_id:item.id,
|
||||
};
|
||||
communityReplyListApi(params).then(res=>{
|
||||
this.$set(this.replyList[index],'children',res.data.list);
|
||||
this.$set(item,'show',true);
|
||||
his.$util.Tips({
|
||||
title: res.msg
|
||||
});
|
||||
}).catch(err => {
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
});
|
||||
}else{
|
||||
this.$set(item,'show',false);
|
||||
}
|
||||
},
|
||||
authTo(url){
|
||||
uni.navigateTo({
|
||||
url: url
|
||||
});
|
||||
},
|
||||
replyLike(item){
|
||||
if(!this.isLogin) return this.$util.Tips({
|
||||
title: '请登录'
|
||||
});
|
||||
let id = item.id;
|
||||
let status = item.isLike == 1 ? 0 : 1;
|
||||
let that = this;
|
||||
communityReplyLikeApi(id,{status}).then(res=>{
|
||||
item.isLike = status;
|
||||
if(status == 1){
|
||||
item.like_num++
|
||||
}else{
|
||||
item.like_num--
|
||||
}
|
||||
return that.$util.Tips({
|
||||
title: res.msg
|
||||
});
|
||||
}).catch(err=>{
|
||||
return that.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
})
|
||||
},
|
||||
delReply(id, num){
|
||||
this.comment_reply_id = id;
|
||||
this.reduceNum = num;
|
||||
this.showModal = true;
|
||||
},
|
||||
handleClick(e){
|
||||
let index = e.index;
|
||||
let that = this;
|
||||
if(index == 1){
|
||||
communityReplyDeleteApi(this.comment_reply_id).then(res=>{
|
||||
this.showModal = false;
|
||||
this.replyList = [];
|
||||
this.comment_reply_id = '';
|
||||
this.$emit('commentAdd',{type:2,num:1 + this.reduceNum});
|
||||
this.getReply();
|
||||
}).catch(err => {
|
||||
this.showModal = false;
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
});
|
||||
}else{
|
||||
this.showModal = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<view>
|
||||
<base-drawer
|
||||
mode="bottom"
|
||||
:visible="visible"
|
||||
zIndex="3000"
|
||||
background-color="transparent"
|
||||
mask maskClosable
|
||||
@close="closeDrawer">
|
||||
<view class="w-full bg--w111-fff relative rd-t-40rpx pt-32">
|
||||
<view class="text-center fs-32 text--w111-333 fw-500 mb-30">评论 {{comment_num}}</view>
|
||||
<view class="close-btn flex-center" @tap="closeDrawer()">
|
||||
<text class="iconfont icon-ic_close text--w111-666 fs-24"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="scroll-content" v-show="!focus">
|
||||
<view class="px-30">
|
||||
<view class="reply-list" v-if="replyList.length">
|
||||
<view class="flex mt-22" v-for="(item,index) in replyList" :key="index"
|
||||
v-show="(item.uid == uid && item.is_show == 0) || item.is_show == 1">
|
||||
<image class="w-74 h-74 rd-50-p111-" :src="item.author_image"
|
||||
@tap="authTo('/pages/discover/discoverUser/index?id=' + item.uid)"></image>
|
||||
<view class="flex-1 ml-20">
|
||||
<view class="w-full">
|
||||
<view class="fs-26 text--w111-999">{{item.author}}</view>
|
||||
<view class="fs-28 lh-42rpx text--w111-333" @tap="showReply(item.id,item.author,item.is_show)">{{item.content}}
|
||||
<text class="pl-8 text--w111-999" v-show="!item.is_show && item.uid == uid">(该评论已被屏蔽)</text>
|
||||
</view>
|
||||
<view class="lh-36rpx flex-between-center pt-4">
|
||||
<view class="flex-y-center fs-24">
|
||||
<text class="text--w111-ccc">{{item.time_text}}</text>
|
||||
<text class="pl-24 text--w111-999" @tap="delReply(item.id,item.comment_num)"
|
||||
v-show="isLogin && uid == item.uid">删除</text>
|
||||
</view>
|
||||
<view class="flex-y-center text--w111-999" @tap="replyLike(item)">
|
||||
<text class="iconfont fs-30" :class="item.isLike ? 'icon-icon_Like_2' : 'icon-ic_Like'"></text>
|
||||
<text class="fs-24 lh-36rpx pl-10">{{item.like_num}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-12 w-full" v-if="item.show">
|
||||
<view class="child-reply flex justify-between" v-for="(reply,i) in item.children" :key="i"
|
||||
v-show="(reply.uid == uid && reply.is_show == 0) || reply.is_show == 1">
|
||||
<view class="flex w-full" >
|
||||
<image :src="reply.author_image" class="w-36 h-36 rd-50-p111-"
|
||||
@tap="authTo('/pages/discover/discoverUser/index?id=' + reply.uid)"></image>
|
||||
<view class="ml-20 flex-1">
|
||||
<view class="text--w111-999 fs-26 lh-40rpx">{{reply.author}}</view>
|
||||
<view class="w-full fs-26 lh-42 flex-y-center flex-wrap text--w111-333" @tap="showReply(reply.id, reply.author)">
|
||||
<view v-if="reply.comment_author">
|
||||
回复<text class="comment-author"
|
||||
@tap="authTo('/pages/discover/discoverUser/index?id=' + reply.comment_reply_uid)">@{{reply.comment_author}}</text>
|
||||
</view>
|
||||
{{reply.content}}<text class="pl-8 text--w111-999" v-show="!item.is_show && item.uid == uid">(该评论已被屏蔽)</text>
|
||||
</view>
|
||||
<view class="flex-between-center pt-4">
|
||||
<view class="fs-24 text--w111-ccc lh-36rpx flex-y-center">
|
||||
<text>{{reply.time_text}}</text>
|
||||
<text class="pl-24 text--w111-999" @tap="delReply(reply.id,reply.comment_num)"
|
||||
v-show="isLogin && uid == reply.uid">删除</text>
|
||||
</view>
|
||||
<view class="flex-y-center text--w111-999" @tap.stop="replyLike(reply)">
|
||||
<text class="iconfont fs-30" :class="reply.isLike ? 'icon-icon_Like_2' : 'icon-ic_Like'"></text>
|
||||
<text class="fs-24 lh-36rpx pl-10">{{reply.like_num}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-14 flex-y-center text--w111-666 fs-26"
|
||||
v-if="item.comment_num > 0 && !item.show" @tap="showMore(item,index,1)">
|
||||
<text class="more-line"></text>
|
||||
<text class="pl-16">展开{{item.comment_num}}条回复</text>
|
||||
<text class="iconfont icon-ic_downarrow fs-28"></text>
|
||||
</view>
|
||||
<view class="mt-14 flex-y-center text--w111-666 fs-26"
|
||||
v-if="item.comment_num > 0 && item.show" @tap="showMore(item,index,0)">
|
||||
<text class="more-line"></text>
|
||||
<text class="pl-16">收起回复</text>
|
||||
<text class="iconfont icon-ic_uparrow fs-28"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<emptyPage title="暂无评论,快去抢沙发吧~" src="/statics/images/noActivity.gif"></emptyPage>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="h-100" v-if="addReply"></view>
|
||||
<view class="fixed-lb w-full pb-safe" :class="{'hide-bar': showFooter}" v-if="addReply">
|
||||
<view class="h-100 px-30 flex-between-center bg--w111-fff">
|
||||
<input type="text" v-model="comment" :placeholder="placeholder"
|
||||
:focus="focus"
|
||||
placeholder-class="text--w111-999"
|
||||
class="flex-1 h-64 rd-32rpx bg--w111-f5f5f5 pl-30 fs-26 text--w111-333" />
|
||||
<view class="w-112 h-64 rd-32rpx bg-gradient flex-center fs-24 text--w111-fff ml-20" @tap="sendText">发送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</base-drawer>
|
||||
<!-- 确认框 -->
|
||||
<tuiModal
|
||||
:show="showModal"
|
||||
title="确认删除该评论"
|
||||
:maskClosable="false"
|
||||
@click="handleClick"></tuiModal>
|
||||
</view>
|
||||
</template>
|
||||
<style>
|
||||
.scroll-content{
|
||||
height: 900rpx;
|
||||
}
|
||||
.hide-bar{
|
||||
bottom: 100rpx;
|
||||
}
|
||||
.mb-54{
|
||||
margin-bottom: 54rpx;
|
||||
}
|
||||
.child-reply ~ .child-reply{
|
||||
margin-top: 22rpx;
|
||||
}
|
||||
.more-line{
|
||||
width: 40rpx;
|
||||
height: 2rpx;
|
||||
background: #D8D8D8;
|
||||
}
|
||||
.comment-author{
|
||||
color: #4A8AC9;
|
||||
padding: 0 4rpx;
|
||||
}
|
||||
.icon-icon_Like_2{
|
||||
color: #e93323;
|
||||
}
|
||||
.close-btn{
|
||||
position: absolute;
|
||||
right: 28rpx;
|
||||
top: 28rpx;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #eee;
|
||||
|
||||
}
|
||||
</style>
|
||||
225
components/discoverWaterfall/WaterfallsFlow.vue
Normal file
225
components/discoverWaterfall/WaterfallsFlow.vue
Normal file
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<view :class="'wf-page wf-page'+type">
|
||||
<!-- left -->
|
||||
<view>
|
||||
<view id="left" v-if="leftList.length">
|
||||
<view v-for="(item,index) in leftList" :key="index"
|
||||
class="wf-item" @tap="itemTap(item)">
|
||||
<WaterfallsFlowItem :item="item" :border="border" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- right -->
|
||||
<view>
|
||||
<view id="right" v-if="rightList.length">
|
||||
<view v-for="(item,index) in rightList" :key="index"
|
||||
class="wf-item" @tap="itemTap(item)">
|
||||
<WaterfallsFlowItem :item="item" :border="border" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WaterfallsFlowItem from './WaterfallsFlowItem.vue';
|
||||
import {LOGIN_STATUS} from '@/config/cache';
|
||||
import { HTTP_REQUEST_URL } from '@/config/app';
|
||||
export default {
|
||||
components: {
|
||||
WaterfallsFlowItem
|
||||
},
|
||||
props: {
|
||||
// 瀑布流列表
|
||||
wfList: {
|
||||
type: Array,
|
||||
require: true
|
||||
},
|
||||
type: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
updateNum: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
border:{
|
||||
type:Boolean,
|
||||
default: false
|
||||
},
|
||||
isSelf:{
|
||||
type:Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
allList: [], // 全部列表
|
||||
leftList: [], // 左边列表
|
||||
rightList: [], // 右边列表
|
||||
mark: 0, // 列表标记
|
||||
boxHeight: [], // 下标0和1分别为左列和右列高度
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 监听列表数据变化
|
||||
wfList: {
|
||||
handler(nVal,oVal){
|
||||
// 如果数据为空或新的列表数据少于旧的列表数据(通常为下拉刷新或切换排序或使用筛选器),初始化变量
|
||||
|
||||
if (!this.wfList.length ||
|
||||
(this.wfList.length === this.updateNum && this.wfList.length <= this.allList.length)) {
|
||||
this.allList = [];
|
||||
this.leftList = [];
|
||||
this.rightList = [];
|
||||
this.boxHeight = [];
|
||||
this.mark = 0;
|
||||
}
|
||||
|
||||
// 如果列表有值,调用waterfall方法
|
||||
|
||||
if (this.wfList.length) {
|
||||
this.allList = this.wfList;
|
||||
this.leftList = [];
|
||||
this.rightList = [];
|
||||
this.boxHeight = [];
|
||||
this.allList.forEach((v, i) => {
|
||||
if(this.allList.length < 3 || (this.allList.length <= 7 && this.allList.length - i > 1) || (this.allList.length > 7 && this.allList.length - i > 2)) {
|
||||
if(i % 2){
|
||||
this.rightList.push(v);
|
||||
}else{
|
||||
this.leftList.push(v);
|
||||
}
|
||||
}
|
||||
});
|
||||
if(this.allList.length < 3){
|
||||
this.mark = this.allList.length+1;
|
||||
}else if(this.allList.length <= 7){
|
||||
this.mark = this.allList.length - 1;
|
||||
}else{
|
||||
this.mark = this.allList.length - 2;
|
||||
}
|
||||
if(this.mark < this.allList.length){
|
||||
this.waterFall()
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
deep:true
|
||||
},
|
||||
mounted(){
|
||||
},
|
||||
|
||||
// 监听标记,当标记发生变化,则执行下一个item排序
|
||||
mark() {
|
||||
const len = this.allList.length;
|
||||
if (this.mark < len && this.mark !== 0 && this.boxHeight.length) {
|
||||
this.waterFall();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 瀑布流排序
|
||||
waterFall() {
|
||||
const i = this.mark;
|
||||
if (i == 0) {
|
||||
// 初始化,从左边开始插入
|
||||
this.leftList.push(this.allList[i]);
|
||||
// 更新左边列表高度
|
||||
this.getViewHeight(0);
|
||||
} else if (i == 1) {
|
||||
// 第二个item插入,默认为右边插入
|
||||
this.rightList.push(this.allList[i]);
|
||||
// 更新右边列表高度
|
||||
this.getViewHeight(1);
|
||||
} else {
|
||||
// 根据左右列表高度判断下一个item应该插入哪边
|
||||
if(!this.boxHeight.length){
|
||||
this.rightList.length < this.leftList.length
|
||||
? this.rightList.push(this.allList[i])
|
||||
: this.leftList.push(this.allList[i]);
|
||||
} else {
|
||||
const leftOrRight = this.boxHeight[0] > this.boxHeight[1] ? 1 : 0;
|
||||
if (leftOrRight) {
|
||||
this.rightList.push(this.allList[i])
|
||||
} else {
|
||||
this.leftList.push(this.allList[i])
|
||||
}
|
||||
}
|
||||
// 更新插入列表高度
|
||||
this.getViewHeight();
|
||||
}
|
||||
},
|
||||
// 获取列表高度
|
||||
getViewHeight() {
|
||||
// 使用nextTick,确保页面更新结束后,再请求高度
|
||||
this.$nextTick(() => {
|
||||
setTimeout(()=>{
|
||||
uni.createSelectorQuery().in(this).select('#right').boundingClientRect(res => {
|
||||
res ? this.boxHeight[1] = res.height : '';
|
||||
uni.createSelectorQuery().in(this).select('#left').boundingClientRect(res => {
|
||||
res ? this.boxHeight[0] = res.height : '';
|
||||
this.mark = this.mark + 1;
|
||||
}).exec();
|
||||
}).exec();
|
||||
},100)
|
||||
})
|
||||
},
|
||||
// item点击
|
||||
itemTap(item) {
|
||||
if(item.content_type == 1){
|
||||
uni.navigateTo({
|
||||
url: '/pages/discover/discoverDetails/index?id=' + item.id
|
||||
})
|
||||
}else{
|
||||
let that = this;
|
||||
if(this.isSelf){
|
||||
uni.navigateTo({
|
||||
// #ifdef MP || H5
|
||||
url: '/pages/discover/discoverVideo/index?id=' + item.id + '&relation_id=' + item.relation_id
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
url: `/pages/discover/discoverVideo/app?url=${HTTP_REQUEST_URL}/pages/discover/discoverVideo/index?content_type=2&token=${that.$Cache.get(LOGIN_STATUS)}&relation_id=${item.relation_id}`
|
||||
// #endif
|
||||
})
|
||||
}else{
|
||||
// #ifdef MP || H5
|
||||
uni.navigateTo({
|
||||
url: '/pages/discover/discoverVideo/index?id=' + item.id
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
let href = encodeURIComponent(`${HTTP_REQUEST_URL}/pages/discover/discoverVideo/index?content_type=2&id=${item.id}&token=${that.$Cache.get(LOGIN_STATUS)}`)
|
||||
uni.navigateTo({
|
||||
url: `/pages/discover/discoverVideo/app?url=${href}`
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$page-padding: 10px;
|
||||
$grid-gap: 10px;
|
||||
|
||||
.wf-page {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: $grid-gap;
|
||||
}
|
||||
.wf-item {
|
||||
width: calc((100vw - 2 * #{$page-padding} - #{$grid-gap}) / 2);
|
||||
padding-bottom: $grid-gap;
|
||||
}
|
||||
.wf-page1 .wf-item{
|
||||
margin-top: 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
130
components/discoverWaterfall/WaterfallsFlowItem.vue
Normal file
130
components/discoverWaterfall/WaterfallsFlowItem.vue
Normal file
@@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<view class="wf-item-page wf-page0">
|
||||
<view class='pictrue relative'>
|
||||
<easy-loadimage
|
||||
mode="widthFix"
|
||||
:image-src="item.image"
|
||||
width="100%"
|
||||
borderRadius="16rpx 16rpx 0 0"></easy-loadimage>
|
||||
<view class="player flex-center" v-if="item.content_type == 2">
|
||||
<text class="iconfont icon-ic_right2 fs-20"></text>
|
||||
</view>
|
||||
<view class="w-60 h-36 rd-4rpx flex-center fs-22 text--w111-fff pic-number"
|
||||
v-if="item.content_type == 1">{{item.slider_image.length}}图</view>
|
||||
<view class="abs-lt w-full h-full flex-col flex-center text--w111-fff shenhe"
|
||||
v-if="[0,-1,-2].includes(item.is_verify)">
|
||||
<text class="fs-28" v-show="item.is_verify == 0">正在审核</text>
|
||||
<text class="fs-24 pt-22" v-show="item.is_verify == 0">通过后将展示在列表</text>
|
||||
<text class="fs-28" v-show="item.is_verify == -1">审核未通过</text>
|
||||
<text class="fs-24 pt-22" v-show="item.is_verify == -1">查看未通过原因</text>
|
||||
<text class="fs-28" v-show="item.is_verify == -2">强制下架</text>
|
||||
<text class="fs-24 pt-22" v-show="item.is_verify == -2">查看下架原因</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info_box" :class="{'box-border': border}">
|
||||
<view class="w-full lh-40rpx fs-28 line2">{{item.title}}</view>
|
||||
<view class="pt-22 fs-22 text--w111-999 flex-between-center">
|
||||
<view class="flex-y-center" @tap.stop="toUser">
|
||||
<image class="w-34 h-34 rd-50-p111-" :src="item.author_image || '/static/images/f.png'"></image>
|
||||
<text class="pl-8 w-180 line1">{{item.author || '用户已注销'}}</text>
|
||||
</view>
|
||||
<view class="flex-y-center" :class="{'text-red': item.is_like}" @tap.stop="contentLike">
|
||||
<text class="iconfont fs-24" :class="item.is_like ? 'icon-icon_Like_2' : 'icon-ic_Like'"></text>
|
||||
<text class="pl-10">{{item.like_num}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import easyLoadimage from '@/components/easy-loadimage/easy-loadimage.vue';
|
||||
import { communityLikeApi } from "@/api/community.js";
|
||||
import { mapGetters } from "vuex";
|
||||
import { HTTP_REQUEST_URL } from '@/config/app';
|
||||
export default {
|
||||
components: {
|
||||
easyLoadimage
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
require: true
|
||||
},
|
||||
border:{
|
||||
type:Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
inject: ['flowLike'],
|
||||
data() {
|
||||
return {
|
||||
domain: HTTP_REQUEST_URL,
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
...mapGetters(['isLogin','uid']),
|
||||
},
|
||||
methods: {
|
||||
toUser(){
|
||||
uni.navigateTo({
|
||||
url: '/pages/discover/discoverUser/index?id=' + this.item.relation_id
|
||||
})
|
||||
},
|
||||
contentLike(){
|
||||
if(!this.isLogin) return this.$util.Tips({
|
||||
title: '请登录'
|
||||
});
|
||||
let status = this.item.is_like == 1 ? 0 : 1;
|
||||
let that = this;
|
||||
communityLikeApi(this.item.id,{status}).then(res=>{
|
||||
that.flowLike({id:that.item.id,status:status})
|
||||
}).catch(err=>{
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.wf-item-page {
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
.pictrue{
|
||||
max-height: 500rpx;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.info_box{
|
||||
padding: 24rpx;
|
||||
border-radius: 0 0 24rpx 24rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
.box-border{
|
||||
border: 1rpx solid #eee;
|
||||
}
|
||||
.text-red{
|
||||
color: #e93323;
|
||||
}
|
||||
.player{
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(51, 51, 51, 0.5);
|
||||
color: #fff;
|
||||
}
|
||||
.shenhe{
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
.pic-number{
|
||||
position: absolute;
|
||||
right: 16rpx;
|
||||
bottom: 16rpx;
|
||||
background: rgba(102, 102, 102, 0.50);
|
||||
}
|
||||
</style>
|
||||
267
components/easy-loadimage/easy-loadimage.vue
Normal file
267
components/easy-loadimage/easy-loadimage.vue
Normal file
@@ -0,0 +1,267 @@
|
||||
<template>
|
||||
<view class="easy-loadimage" :style="[boxStyle]" :id="uid">
|
||||
<image class="origin-img block" :src="imageSrc" :mode="mode"
|
||||
v-if="loadImg&&!isLoadError"
|
||||
v-show="showImg"
|
||||
:style="[imgStyle]"
|
||||
:class="{'no-transition':!openTransition,'show-transition':showTransition&&openTransition}"
|
||||
@load="handleImgLoad" @error="handleImgError">
|
||||
</image>
|
||||
<image class="border-img" :src="borderSrc" mode="scaleToFill"
|
||||
v-if="loadImg&&!isLoadError&&borderSrc"
|
||||
v-show="showImg"
|
||||
:style="[imgStyle]"
|
||||
:class="{'no-transition':!openTransition,'show-transition':showTransition&&openTransition}">
|
||||
</image>
|
||||
<view class="loadfail-img" v-else-if="isLoadError"></view>
|
||||
<view :class="['loading-img','spin-circle',loadingMode,mode]" v-show="!showImg&&!isLoadError"></view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {throttle} from '@/utils/validate.js';
|
||||
|
||||
// 生成全局唯一id
|
||||
function generateUUID() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
let r = Math.random() * 16 | 0,
|
||||
v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
})
|
||||
}
|
||||
export default {
|
||||
props: {
|
||||
imageSrc: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
borderSrc: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: "aspectFill"
|
||||
},
|
||||
loadingMode: {
|
||||
type: String,
|
||||
default: 'looming-gray'
|
||||
},
|
||||
openTransition: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
viewHeight: {
|
||||
type: Number,
|
||||
default () {
|
||||
return uni.getWindowInfo().windowHeight;
|
||||
}
|
||||
},
|
||||
width:{
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
height:{
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
borderRadius:{
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const that = this;
|
||||
return {
|
||||
// uid:'',
|
||||
uid: 'uid-' + generateUUID(),
|
||||
loadImg: false,
|
||||
showImg: false,
|
||||
isLoadError: false,
|
||||
borderLoaded: 0,
|
||||
showTransition: false,
|
||||
scrollFn: throttle(function() {
|
||||
// 加载img时才执行滚动监听判断是否可加载
|
||||
if (that.loadImg || that.isLoadError) return;
|
||||
const id = that.uid
|
||||
const query = uni.createSelectorQuery().in(that);
|
||||
query.select('#' + id).boundingClientRect(data => {
|
||||
if (!data) return;
|
||||
if (data.top - that.viewHeight < 0) {
|
||||
that.loadImg = !!that.imageSrc;
|
||||
that.isLoadError = !that.loadImg;
|
||||
}
|
||||
}).exec()
|
||||
}, 200)
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
boxStyle(){
|
||||
return {
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
borderRadius: this.borderRadius
|
||||
}
|
||||
},
|
||||
imgStyle(){
|
||||
return {
|
||||
borderRadius: this.borderRadius
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.$nextTick(this.onScroll)
|
||||
},
|
||||
handleBorderLoad() {
|
||||
this.borderLoaded = 1;
|
||||
},
|
||||
handleBorderError() {
|
||||
this.borderLoaded = 2;
|
||||
},
|
||||
handleImgLoad(e) {
|
||||
this.showImg = true;
|
||||
setTimeout(() => {
|
||||
this.showTransition = true
|
||||
}, 50)
|
||||
},
|
||||
handleImgError(e) {
|
||||
this.isLoadError = true;
|
||||
},
|
||||
onScroll() {
|
||||
this.scrollFn();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
uni.$on('scroll', this.scrollFn);
|
||||
this.onScroll()
|
||||
},
|
||||
beforeDestroy() {
|
||||
uni.$off('scroll', this.scrollFn);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.easy-loadimage {
|
||||
position: relative;
|
||||
|
||||
}
|
||||
.border-img {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* max-height: 360rpx; */
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* 官方优化图片tips */
|
||||
image {
|
||||
will-change: transform
|
||||
}
|
||||
|
||||
/* 渐变过渡效果处理 */
|
||||
image.origin-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
image.origin-img.show-transition {
|
||||
transition: opacity .5s;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
image.origin-img.no-transition {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* 渐变过渡效果处理 */
|
||||
image.border-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.3;
|
||||
/* max-height: 360rpx; */
|
||||
}
|
||||
|
||||
image.border-img.show-transition {
|
||||
transition: opacity .5s;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
image.border-img.no-transition {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* 加载失败、加载中的占位图样式控制 */
|
||||
.loadfail-img {
|
||||
height: 100%;
|
||||
background: url('~@/static/easy-loadimage/loadfail.png') no-repeat center;
|
||||
background-size: 50%;
|
||||
}
|
||||
|
||||
.loading-img {
|
||||
height: 100%;
|
||||
}
|
||||
.widthFix{
|
||||
min-height: 172px;
|
||||
}
|
||||
|
||||
/* 转圈 */
|
||||
.spin-circle {
|
||||
background: url('~@/static/easy-loadimage/loading.png') no-repeat center;
|
||||
background-size: 60%;
|
||||
}
|
||||
|
||||
/* 动态灰色若隐若现 */
|
||||
.looming-gray {
|
||||
animation: looming-gray 1s infinite linear;
|
||||
background-color: #e3e3e3;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
@keyframes looming-gray {
|
||||
0% {
|
||||
background-color: #e3e3e3aa;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-color: #e3e3e3;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: #e3e3e3aa;
|
||||
}
|
||||
}
|
||||
|
||||
/* 骨架屏1 */
|
||||
.skeleton-1 {
|
||||
background-color: #e3e3e3;
|
||||
background-image: linear-gradient(100deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0) 80%);
|
||||
background-size: 100rpx 100%;
|
||||
background-repeat: repeat-y;
|
||||
background-position: 0 0;
|
||||
animation: skeleton-1 .6s infinite;
|
||||
}
|
||||
|
||||
@keyframes skeleton-1 {
|
||||
to {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 骨架屏2 */
|
||||
.skeleton-2 {
|
||||
background-image: linear-gradient(-90deg, #fefefe 0%, #e6e6e6 50%, #fefefe 100%);
|
||||
background-size: 400% 400%;
|
||||
background-position: 0 0;
|
||||
animation: skeleton-2 1.2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes skeleton-2 {
|
||||
to {
|
||||
background-position: -135% 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
319
components/eidtUserModal/index.vue
Normal file
319
components/eidtUserModal/index.vue
Normal file
@@ -0,0 +1,319 @@
|
||||
<template>
|
||||
<view :style="colorStyle">
|
||||
<view class="product-window" :class="{'on':isShow}">
|
||||
<view class="iconfont icon-guanbi" @click="closeAttr"></view>
|
||||
<view class="mp-data">
|
||||
<image :src="mpData.site_logo" mode=""></image>
|
||||
<text class="mp-name">{{mpData.site_name || ''}} 申请</text>
|
||||
</view>
|
||||
<view class="trip-msg">
|
||||
<view class="title">
|
||||
获取您的昵称、头像
|
||||
</view>
|
||||
<view class="trip">
|
||||
提供具有辨识度的用户中心界面
|
||||
</view>
|
||||
</view>
|
||||
<form @submit="formSubmit">
|
||||
<view class="edit">
|
||||
<view class="avatar edit-box">
|
||||
<view class="left">
|
||||
<view class="head">头像</view>
|
||||
<!-- <image :src="userInfo.avatar || defaultAvatar" mode=""></image> -->
|
||||
<view class="avatar-box" v-if="!mp_is_new" @click.stop='uploadpic'>
|
||||
<image :src="userInfo.avatar || defHead"></image>
|
||||
</view>
|
||||
<button v-else class="avatar-box" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
|
||||
<image :src="userInfo.avatar || defHead"></image>
|
||||
</button>
|
||||
</view>
|
||||
<!-- <view class="iconfont icon-xiangyou"></view> -->
|
||||
</view>
|
||||
<view class="nickname edit-box">
|
||||
<view class="left">
|
||||
<view class="head">昵称</view>
|
||||
<view class='input'><input type='nickname' :always-embed="true" :adjust-position="true" cursor-spacing="30" placeholder-class="pl-sty"
|
||||
placeholder="请输入昵称" name='nickname' :maxlength="16"
|
||||
:value='userInfo.nickname'></input>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="iconfont icon-xiangyou"></view> -->
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<view class="bottom">
|
||||
<button class="save" formType="submit" :class="{'open': userInfo.avatar}">
|
||||
保存
|
||||
</button>
|
||||
</view>
|
||||
</form>
|
||||
</view>
|
||||
<canvas canvas-id="canvas" v-if="canvasStatus"
|
||||
:style="{width: canvasWidth + 'px', height: canvasHeight + 'px',position: 'absolute',left:'-100000px',top:'-100000px'}"></canvas>
|
||||
<view class="mask" @touchmove.prevent v-if="isShow" @click="closeAttr"></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import colors from "@/mixins/color";
|
||||
import Cache from '@/utils/cache';
|
||||
import {
|
||||
userEdit,
|
||||
} from '@/api/user.js';
|
||||
import {
|
||||
copyRight
|
||||
} from '@/api/api.js';
|
||||
export default {
|
||||
mixins: [colors],
|
||||
props: {
|
||||
isShow: {
|
||||
type: Number,
|
||||
value: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defHead: require('@/static/images/f.png'),
|
||||
mp_is_new: this.$Cache.get('MP_VERSION_ISNEW') || false,
|
||||
userInfo: {
|
||||
avatar: '',
|
||||
nickname: '',
|
||||
},
|
||||
mpData: {
|
||||
site_logo: '',
|
||||
site_name: ''
|
||||
},
|
||||
canvasStatus: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
let configData = this.$Cache.get('BASIC_CONFIG');
|
||||
this.mpData.site_logo = configData.logo_url;
|
||||
this.mpData.site_name = configData.site_name;
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
*/
|
||||
uploadpic: function() {
|
||||
let that = this;
|
||||
this.canvasStatus = true
|
||||
that.$util.uploadImageChange('upload/image', (res) => {
|
||||
let userInfo = that.userInfo;
|
||||
if (userInfo !== undefined) {
|
||||
that.userInfo.avatar = res.data.url;
|
||||
}
|
||||
this.canvasStatus = false
|
||||
}, (res) => {
|
||||
this.canvasStatus = false
|
||||
}, (res) => {
|
||||
this.canvasWidth = res.w
|
||||
this.canvasHeight = res.h
|
||||
});
|
||||
},
|
||||
// 微信头像获取
|
||||
onChooseAvatar(e) {
|
||||
const {
|
||||
avatarUrl
|
||||
} = e.detail
|
||||
this.$util.uploadImgs('upload/image', avatarUrl, (res) => {
|
||||
this.userInfo.avatar = res.data.url
|
||||
}, (err) => {
|
||||
console.log(err)
|
||||
})
|
||||
},
|
||||
closeAttr: function() {
|
||||
this.$emit('closeEdit');
|
||||
},
|
||||
/**
|
||||
* 提交修改
|
||||
*/
|
||||
formSubmit(e) {
|
||||
let that = this
|
||||
if (!this.userInfo.avatar) return that.$util.Tips({
|
||||
title: '请上传头像'
|
||||
});
|
||||
if (!e.detail.value.nickname) return that.$util.Tips({
|
||||
title: '请输入昵称'
|
||||
});
|
||||
this.userInfo.nickname = e.detail.value.nickname
|
||||
userEdit(this.userInfo).then(res => {
|
||||
this.$emit('editSuccess')
|
||||
return that.$util.Tips({
|
||||
title: res.msg,
|
||||
icon: 'success'
|
||||
},{
|
||||
tab: 3
|
||||
});
|
||||
}).catch(msg => {
|
||||
return that.$util.Tips({
|
||||
title: msg || '保存失败'
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.pl-sty {
|
||||
color: #999999;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="scss">
|
||||
.product-window.on {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.mask {
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.product-window {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
z-index: 1000;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
transform: translate3d(0, 100%, 0);
|
||||
transition: all .3s cubic-bezier(.25, .5, .5, .9);
|
||||
padding: 38rpx 40rpx;
|
||||
padding-bottom: 90rpx;
|
||||
padding-bottom: calc(90rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
|
||||
padding-bottom: calc(90rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
|
||||
|
||||
.icon-guanbi {
|
||||
position: absolute;
|
||||
top: 30rpx;
|
||||
right: 30rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
color: #999;
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
.mp-data {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.mp-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.trip-msg {
|
||||
padding-bottom: 32rpx;
|
||||
border-bottom: 1px solid #F5F5F5;
|
||||
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.trip {
|
||||
font-size: 26rpx;
|
||||
color: #777777;
|
||||
}
|
||||
}
|
||||
|
||||
.edit {
|
||||
border-bottom: 1px solid #F5F5F5;
|
||||
|
||||
.avatar {
|
||||
border-bottom: 1px solid #F5F5F5;
|
||||
}
|
||||
|
||||
.nickname {
|
||||
.input {
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
height: 80rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
padding: 22rpx 0;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
|
||||
.head {
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
white-space: nowrap;
|
||||
margin-right: 60rpx;
|
||||
}
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
image {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-xiangyou {
|
||||
color: #cfcfcf;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.save {
|
||||
border: 1px solid #F5F5F5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 368rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-top: 52rpx;
|
||||
background-color: #F5F5F5;
|
||||
color: #ccc;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.save.open {
|
||||
border: 1px solid #fff;
|
||||
background-color: var(--view-theme);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
61
components/emptyPage.vue
Normal file
61
components/emptyPage.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<!-- 无数据时显示 -->
|
||||
<view class="empty-page w-full flex-col flex-center pt-82 bg--w111-fff rd-24rpx">
|
||||
<image class="empty-img" :src="imgSrc"></image>
|
||||
<view v-if="!isLogin" class="fs-28 fw-500 text--w111-282828">暂未登录</view>
|
||||
<view class="fs-26 text--w111-999 lh-36rpx pt-16">{{title}}</view>
|
||||
<view class="w-360 h-72 rd-36rpx flex-center font-num fw-500 fs-26 theme-border mt-48"
|
||||
v-if="!isLogin" @tap="goLog">立即登录</view>
|
||||
<slot name="bottom"></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {HTTP_REQUEST_URL} from '@/config/app';
|
||||
import { toLogin } from '@/libs/login.js';
|
||||
export default{
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '暂无记录',
|
||||
},
|
||||
src:{
|
||||
type: String,
|
||||
default: '/statics/images/empty-box.gif',
|
||||
},
|
||||
isLogin:{
|
||||
type:Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
imgHost:HTTP_REQUEST_URL
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
imgSrc(){
|
||||
return HTTP_REQUEST_URL + this.src
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
goLog(){
|
||||
toLogin()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.pt-82{
|
||||
padding: 82rpx 0 160rpx;
|
||||
}
|
||||
.empty-img{
|
||||
width: 440rpx;
|
||||
height: 360rpx;
|
||||
}
|
||||
.theme-border{
|
||||
border: 1px solid var(--view-theme);
|
||||
}
|
||||
</style>
|
||||
185
components/ewcomerPop/index.vue
Normal file
185
components/ewcomerPop/index.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<view :style="colorStyle">
|
||||
<image :src="imgHost+'/statics/images/header.png'" mode="" class="img"></image>
|
||||
<view class="tipaddress">
|
||||
<view class="title">{{fromActive == 1?'激活送好礼':'新人大礼包'}}</view>
|
||||
<view class="list">
|
||||
<view class="list-img acea-row row-between-wrapper" :style="{backgroundImage:'url('+imgHost+'/statics/images/box1.png'+')'}" v-if="comerGift.product_count>0 && fromActive == 0">
|
||||
<view class="left acea-row row-center-wrapper">
|
||||
<image :src="imgHost+'/statics/images/vip.png'" mode=""></image>
|
||||
</view>
|
||||
<view class="right">新人专享价商品</view>
|
||||
</view>
|
||||
<view class="list-img acea-row row-between-wrapper" :style="{backgroundImage:'url('+imgHost+'/statics/images/box1.png'+')'}" v-if="comerGift.first_order_discount>0 && fromActive == 0">
|
||||
<view class="left">
|
||||
{{parseFloat(comerGift.first_order_discount)/10 || 10}}<text class="text">折</text>
|
||||
</view>
|
||||
<view class="right">新人首单优惠</view>
|
||||
</view>
|
||||
<view class="list-img acea-row row-between-wrapper" :style="{backgroundImage:'url('+imgHost+'/statics/images/box1.png'+')'}" v-if="comerGift.register_give_integral>0">
|
||||
<view class="left">{{comerGift.register_give_integral}}</view>
|
||||
<view class="right">新人赠送积分</view>
|
||||
</view>
|
||||
<view class="list-img acea-row row-between-wrapper" :style="{backgroundImage:'url('+imgHost+'/statics/images/box1.png'+')'}" v-if="comerGift.register_give_money>0">
|
||||
<view class="left">{{comerGift.register_give_money}}<text class="text">元</text></view>
|
||||
<view class="right">新人赠送余额</view>
|
||||
</view>
|
||||
<view class="list-img acea-row row-between-wrapper" :style="{backgroundImage:'url('+imgHost+'/statics/images/box1.png'+')'}" v-if="comerGift.coupon_count>0" v-for="(item,index) in comerGift.register_give_coupon" :key="index">
|
||||
<view class="left">
|
||||
<text v-if="item.coupon_type==1">{{item.coupon_price.toString().split(".")[0]}}</text>
|
||||
<text class="nums"
|
||||
v-if="item.coupon_price.toString().split('.').length>1 && item.coupon_type==1">.{{item.coupon_price.toString().split(".")[1]}}</text>
|
||||
<text v-if="item.coupon_type==2">{{parseFloat(item.coupon_price)/10}}</text>
|
||||
<text class="text">{{item.coupon_type==1?'元':'折'}}</text>
|
||||
</view>
|
||||
<view class="right">优惠券</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn" @click="accept">
|
||||
立即收下
|
||||
</view>
|
||||
</view>
|
||||
<view class="mark"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
HTTP_REQUEST_URL
|
||||
} from '@/config/app';
|
||||
import colors from '@/mixins/color';
|
||||
export default {
|
||||
mixins: [colors],
|
||||
props:{
|
||||
comerGift: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
fromActive: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imgHost: HTTP_REQUEST_URL,
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
accept(){
|
||||
this.$emit('comerPop')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.img {
|
||||
position: fixed;
|
||||
top: 162rpx;
|
||||
left: 9%;
|
||||
width: 590rpx;
|
||||
height: 294rpx;
|
||||
z-index: 100;
|
||||
|
||||
}
|
||||
|
||||
.tipaddress {
|
||||
position: fixed;
|
||||
left: 13%;
|
||||
top: 25%;
|
||||
width: 538rpx;
|
||||
height: 650rpx;
|
||||
background-color: var(--view-theme);
|
||||
border-radius: 10rpx;
|
||||
z-index: 100;
|
||||
text-align: center;
|
||||
|
||||
.title{
|
||||
color: #fff;
|
||||
font-size: 50rpx;
|
||||
margin-top: 32rpx;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
width: 258rpx;
|
||||
height: 52rpx;
|
||||
margin-top: 50rpx;
|
||||
|
||||
}
|
||||
|
||||
.list {
|
||||
height: 370rpx;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
.list-img {
|
||||
margin-top: 14rpx;
|
||||
margin-left: 32rpx;
|
||||
width: 474rpx;
|
||||
height: 124rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
|
||||
.left {
|
||||
width: 144rpx;
|
||||
font-size: 48rpx;
|
||||
font-weight: 500;
|
||||
color: var(--view-theme);
|
||||
|
||||
image{
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.nums{
|
||||
font-size: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 328rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: var(--view-theme);
|
||||
text-align: left;
|
||||
padding-left: 50rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.btn {
|
||||
width: 474rpx;
|
||||
height: 78rpx;
|
||||
background: #FFDE5C;
|
||||
border-radius: 39rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #B66A08;
|
||||
line-height: 78rpx;
|
||||
text-align: center;
|
||||
margin-left: 32rpx;
|
||||
margin-top: 48rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.mark {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 99;
|
||||
}
|
||||
</style>
|
||||
145
components/guide/index.vue
Normal file
145
components/guide/index.vue
Normal file
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<!-- 开屏广告 -->
|
||||
<view class="content">
|
||||
<swiper class="swiper" :class="advData.value.length==1?'on':''" :autoplay="autoplay" :duration="duration" @change="stopChange"
|
||||
v-if="advData.type == 'pic' && advData.value.length">
|
||||
<swiper-item v-for="(item,index) in advData.value" :key="index" @click="jump(item.link)">
|
||||
<view class="swiper-item">
|
||||
<view class="swiper-item-img">
|
||||
<image :src="item.img" mode="aspectFill"></image>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="video-box" v-else-if="advData.type == 'video' && advData.video_link">
|
||||
<video class="vid" :src="advData.video_link" :autoplay="true" :loop="true" :muted="true"
|
||||
:controls="false"></video>
|
||||
</view>
|
||||
<view class="jump-over" :style="{ top: navH + 'rpx' }" @tap="launchFlag()">跳过<text v-if="closeType == 1">{{time}}</text><slot name="bottom"></slot></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let app = getApp();
|
||||
let sysHeight = uni.getWindowInfo().statusBarHeight;
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
autoplay: false,
|
||||
duration: 500,
|
||||
jumpover: '跳过',
|
||||
experience: '立即体验',
|
||||
time: this.advData.time,
|
||||
timecount: undefined,
|
||||
navH: 100 + sysHeight * 2,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
advData: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
// 1 倒计时 2 手动关闭(预留)
|
||||
closeType: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.timer()
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearInterval(this.timecount)
|
||||
},
|
||||
methods: {
|
||||
stopChange(){
|
||||
if(this.advData.value.length == 1){
|
||||
return false
|
||||
}
|
||||
},
|
||||
timer() {
|
||||
var t = this.advData.time || 5
|
||||
this.timecount = setInterval(() => {
|
||||
t--
|
||||
this.time = t
|
||||
if (t <= 0) {
|
||||
clearInterval(this.timecount)
|
||||
this.launchFlag()
|
||||
}
|
||||
}, 1000)
|
||||
},
|
||||
launchFlag() {
|
||||
clearInterval(this.timecount)
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
},
|
||||
jump(url) {
|
||||
if(url){
|
||||
clearInterval(this.timecount)
|
||||
this.$util.JumpPath(url);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
page,
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: 100% auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.swiper {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
display: flex;
|
||||
/* justify-content: center; */
|
||||
align-items: flex-end;
|
||||
flex-direction: column-reverse
|
||||
}
|
||||
|
||||
.swiper-item-img {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.swiper-item-img image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.jump-over {
|
||||
position: absolute;
|
||||
height: 45rpx;
|
||||
line-height: 45rpx;
|
||||
padding: 0 15rpx;
|
||||
border-radius: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #b09e9a;
|
||||
border: 1px solid #b09e9a;
|
||||
z-index: 999;
|
||||
right: 30rpx;
|
||||
}
|
||||
|
||||
.video-box {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
|
||||
.vid {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
511
components/home/index.vue
Normal file
511
components/home/index.vue
Normal file
@@ -0,0 +1,511 @@
|
||||
<template>
|
||||
<!-- 悬浮导航按钮 -->
|
||||
<view :style="colorStyle" v-if="is_show && showMenu">
|
||||
<view style="touch-action: none">
|
||||
<view class="home" style="position: fixed" :style="{ top: top + 'px' }" id="right-nav"
|
||||
@touchmove.stop.prevent="setTouchMove">
|
||||
<view class="menus" :class="isOpen ? `menus_isOpen-${menus.length}` : ''" v-if="index == 3 ">
|
||||
<view id="fab3"></view>
|
||||
<!-- style="height: 298rpx;" -->
|
||||
<view class="menu menu_main" @click="changeStatus">
|
||||
<image :src="isOpen ? main_after_image : main_ago_image" class="image"
|
||||
style="border-radius: 50%;" />
|
||||
</view>
|
||||
|
||||
<view v-for="(menu, index) in menus" :key="index"
|
||||
:class="['menu menu_a', `menu_a--${index + 1}`]" @click.stop="jump(menu.url)">
|
||||
<image :src="menu.img" class="icon-img"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view id="fab1" class="fab1 p-10" v-if="index == 1" @touchmove.stop.prevent="setTouchMove">
|
||||
<view v-show="isOpen" class="img-list">
|
||||
<view v-for="(item, index) in menus" :key="index" class="img-box" @click="jump(item.url)">
|
||||
<image class="img" :src="item.img" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn-box" @click="changeStatus">
|
||||
<view class="img-box">
|
||||
<image class="img" :src="main_ago_image" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view id="fab2" class="fab2 flex-y-center relative p-10" :class="{ hide: isHide }" v-if="index == 2">
|
||||
<view v-if="isOpen" class="img-list">
|
||||
<view v-for="(item, index) in menus" :key="index" class="img-box" @click="jump(item.url)">
|
||||
<image class="img" :src="item.img" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="!isOpen" class="btn-box" @click="changeStatus">
|
||||
<view class="img-box">
|
||||
<image class="img" :src="main_ago_image" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isOpen" class="icon" @click="changeStatus">
|
||||
<text class="iconfont icon-ic_rightarrow"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="menus fab4" :class="isOpen ? `menus_isOpen menus_isOpen-${menus.length}` : ''"
|
||||
v-if="index == 4">
|
||||
<view id="fab4" style="height: 350rpx;width: 1px;"></view>
|
||||
<view class="menu_bag" :class="isOpen ? ' has-bag' : opend ? 'close-bag' : ''"></view>
|
||||
<view class="menu menu_main menu_main4" @click="changeStatus">
|
||||
<text v-if="isOpen" class="iconfont icon-ic_close"></text>
|
||||
</view>
|
||||
|
||||
<view v-for="(menu, index) in menus" :key="index"
|
||||
:style="{ zIndex: isOpen ? 9999 : '-1' }"
|
||||
:class="['menu menu_a', `menu_a--${index + 1}`]" @click.stop="jump(menu.url)">
|
||||
<image :src="menu.img" class="icon-img"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {mapGetters} from 'vuex';
|
||||
import colors from '@/mixins/color.js';
|
||||
import {HTTP_REQUEST_URL} from '@/config/app';
|
||||
import Vue from 'vue';
|
||||
import {getSuspended} from '@/api/api.js';
|
||||
export default {
|
||||
name: 'fabHome',
|
||||
props: {
|
||||
// 风格样式
|
||||
styleType: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
},
|
||||
mixins: [colors],
|
||||
data: function() {
|
||||
return {
|
||||
top: '545',
|
||||
imgHost: HTTP_REQUEST_URL,
|
||||
isOpen: false, //菜单是否展开
|
||||
opend: false, //是否打开过
|
||||
menus: [],
|
||||
main_image: '',
|
||||
shifting: 10,
|
||||
index: 4,
|
||||
is_show: 1,
|
||||
main_after_image: '',
|
||||
main_ago_image: '',
|
||||
windowHeight: 0,
|
||||
fabHeight: 0,
|
||||
isHide: false,
|
||||
menu:{
|
||||
color:'rgba(0, 0, 0, 0.10)'
|
||||
},
|
||||
showMenu: true
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
...mapGetters(['isLogin'])
|
||||
},
|
||||
mounted() {
|
||||
uni.$on('scroll', this.scrollFn);
|
||||
if(this.isLogin && [1,2].includes(this.$store.state.app.identity)){
|
||||
this.showMenu = false;
|
||||
}else{
|
||||
setTimeout(()=>{
|
||||
this.getSuspended();
|
||||
},500)
|
||||
}
|
||||
uni.getSystemInfo({
|
||||
success: (res) => {
|
||||
this.windowHeight = res.windowHeight;
|
||||
}
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$Cache.set('homeTop',this.top);
|
||||
},
|
||||
methods: {
|
||||
changeStatus() {
|
||||
this.isOpen = !this.isOpen;
|
||||
this.opend = true;
|
||||
this.isHide = false;
|
||||
},
|
||||
setTouchMove(e) {
|
||||
let that = this;
|
||||
let clientY = e.touches[0].clientY;
|
||||
if (clientY > (that.fabHeight / 2) && clientY < (that.windowHeight - that.fabHeight / 2)) {
|
||||
that.top = clientY;
|
||||
}
|
||||
},
|
||||
scrollFn() {
|
||||
this.isOpen = false;
|
||||
this.isHide = true;
|
||||
},
|
||||
jump(url) {
|
||||
this.$util.JumpPath(url);
|
||||
},
|
||||
// 获取配置信息
|
||||
getSuspended() {
|
||||
getSuspended().then(res => {
|
||||
const data = res.data;
|
||||
this.menus = data.button;
|
||||
this.index = data.index;
|
||||
this.is_show = data.is_show;
|
||||
this.main_image = data.main_image;
|
||||
this.main_after_image = data.main_after_image || '';
|
||||
this.main_ago_image = data.main_ago_image || '';
|
||||
this.shifting = data.shifting;
|
||||
if(data.is_show){
|
||||
this.$nextTick(() => {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query
|
||||
.select(`#fab${this.index}`)
|
||||
.boundingClientRect((data) => {
|
||||
this.fabHeight = data.height;
|
||||
if(this.$Cache.get('homeTop')){
|
||||
this.top = this.$Cache.get('homeTop')
|
||||
}else{
|
||||
if (this.shifting == 100) {
|
||||
this.top = this.windowHeight - data.height / 2
|
||||
} else if (this.shifting == 0) {
|
||||
this.top = data.height / 2
|
||||
} else {
|
||||
this.top = this.shifting / 100 * this.windowHeight
|
||||
}
|
||||
}
|
||||
})
|
||||
.exec();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.home {
|
||||
position: fixed;
|
||||
color: white;
|
||||
text-align: center;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
right: 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.menus {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
position: relative;
|
||||
right: 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.menus .menu {
|
||||
display: block;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition-timing-function: cubic-bezier(0.25, 1.2, 0.45, 1);
|
||||
transition-duration: 1s;
|
||||
}
|
||||
|
||||
.menu_bag {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
// border-radius: 90rpx 0 0 90rpx;
|
||||
border-radius: 70rpx;
|
||||
background: rgba(51, 51, 51, 0.1);
|
||||
box-shadow: 0rpx 0rpx 17rpx 0rpx rgba(0, 0, 0, 0.1);
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.close-bag {
|
||||
animation: close 0.5s ease forwards;
|
||||
}
|
||||
|
||||
.has-bag {
|
||||
border-radius: 50%;
|
||||
animation: show 0.4s ease forwards;
|
||||
}
|
||||
|
||||
@keyframes show {
|
||||
0% {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 350rpx;
|
||||
height: 350rpx;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes close {
|
||||
0% {
|
||||
width: 350rpx;
|
||||
height: 350rpx;
|
||||
}
|
||||
|
||||
100% {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.menus .menu_main {
|
||||
z-index: 2;
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
font-size: 36px;
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.menus .menu_a {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
color: inherit;
|
||||
// box-shadow: 0 0 6rpx var(--color);
|
||||
// transform: translate(-50%, -50%) rotate(180deg);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
/* 点击悬浮球主菜单按钮后样式 */
|
||||
.menus_isOpen .menu_main {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
font-size: 28rpx;
|
||||
color: #607d88;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.menus_isOpen-3 {
|
||||
.menu_a--1 {
|
||||
transform: translate(-100%, calc(-50% - 93rpx));
|
||||
}
|
||||
|
||||
.menu_a--2 {
|
||||
transform: translate(calc(-50% - 100rpx), calc(-50%));
|
||||
}
|
||||
|
||||
.menu_a--3 {
|
||||
transform: translate(-100%, calc(-50% + 93rpx));
|
||||
}
|
||||
}
|
||||
|
||||
.menus_isOpen-4 {
|
||||
.menu_a--1 {
|
||||
transform: translate(-50%, calc(-50% - 100rpx));
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.menu_a--2 {
|
||||
transform: translate(calc(-50% - 90rpx), calc(-50% - 50rpx));
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.menu_a--3 {
|
||||
transform: translate(calc(-50% - 90rpx), calc(-50% + 50rpx));
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.menu_a--4 {
|
||||
transform: translate(-50%, calc(-50% + 100rpx));
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.menu_a--5 {
|
||||
transform: translate(calc(-50% + 100rpx), calc(-50% + 50rpx));
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.menu_a--6 {
|
||||
transform: translate(calc(-50% + 100rpx), calc(-50% - 50rpx));
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.menus_isOpen-5 {
|
||||
.menu_a--1 {
|
||||
transform: translate(-50%, calc(-50% - 110rpx));
|
||||
}
|
||||
|
||||
.menu_a--2 {
|
||||
transform: translate(calc(-50% - 76rpx), calc(-50% - 76rpx));
|
||||
}
|
||||
|
||||
.menu_a--3 {
|
||||
transform: translate(calc(-50% - 106rpx), -50%);
|
||||
}
|
||||
|
||||
.menu_a--4 {
|
||||
transform: translate(calc(-50% - 76rpx), calc(-50% + 76rpx));
|
||||
}
|
||||
|
||||
.menu_a--5 {
|
||||
transform: translate(-50%, calc(-50% + 110rpx));
|
||||
}
|
||||
}
|
||||
|
||||
.icon-img {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.fab1 {
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
bottom: 0;
|
||||
border-radius: 45rpx;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
backdrop-filter: blur(10rpx);
|
||||
|
||||
|
||||
.img-box {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
background: #FFFFFF;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.img-list {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.img-box {
|
||||
margin: 0 0 16rpx 0;
|
||||
box-shadow: 0rpx 0rpx 16rpx 0rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-box {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.img-box {}
|
||||
}
|
||||
}
|
||||
|
||||
.fab2 {
|
||||
border-radius: 45rpx 0 0 45rpx;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
backdrop-filter: blur(10rpx);
|
||||
|
||||
&.hide {
|
||||
transform: translateX(42rpx);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.img-box {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
background: #FFFFFF;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.img-list {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
|
||||
.img-box {
|
||||
box-shadow: 0rpx 0rpx 16rpx 0rpx rgba(0, 0, 0, 0.1);
|
||||
|
||||
+.img-box {
|
||||
margin: 0 0 0 16rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.menu_main4 {
|
||||
background: #FFFFFF;
|
||||
|
||||
.icon-ic_close {
|
||||
font-size: 34rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.fab4 {
|
||||
.menu_bag {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(51, 51, 51, 0.1);
|
||||
backdrop-filter: blur(7.78rpx);
|
||||
box-shadow: 0rpx 0rpx 13rpx 0rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.close-bag {
|
||||
background: rgba(51, 51, 51, 0.1);
|
||||
backdrop-filter: blur(7.78rpx);
|
||||
}
|
||||
|
||||
.has-bag {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.menu_main {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
|
||||
&.menus_isOpen {
|
||||
.menu_main {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
133
components/homeList/index.vue
Normal file
133
components/homeList/index.vue
Normal file
@@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<!-- 顶部下拉导航 -->
|
||||
<view class="dialog_nav dialogIndex"
|
||||
:style="{ top: navH + 'px' }" v-show="currentPage">
|
||||
<view class="dialog_nav_item" :class="item.after"
|
||||
v-for="(item,index) in headerNav" :key="index"
|
||||
@tap="linkPage(item.url)">
|
||||
<text class="iconfont" :class="item.icon"></text>
|
||||
<text class="pl-20">{{item.name}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "homeIdex",
|
||||
props: {
|
||||
navH: {
|
||||
type: String|Number,
|
||||
default: ""
|
||||
},
|
||||
currentPage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
openNavList:{
|
||||
type: Array,
|
||||
default: ()=>[]
|
||||
},
|
||||
navList: {
|
||||
type: Array,
|
||||
default: ()=>[]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectNavList:[
|
||||
{name:'首页',icon:'icon-ic_mall',url:'/pages/index/index',after:'dialog_after'},
|
||||
{name:'搜索',icon:'icon-ic_search',url:'/pages/goods/goods_search/index',after:'dialog_after'},
|
||||
{name:'购物车',icon:'icon-ic_ShoppingCart1',url:'/pages/order_addcart/order_addcart',after:'dialog_after'},
|
||||
{name:'我的收藏',icon:'icon-ic_star',url:'/pages/users/user_goods_collection/index',after:'dialog_after'},
|
||||
{name:'个人中心',icon:'icon-a-ic_user1',url:'/pages/user/index'},
|
||||
]
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
headerNav(){
|
||||
if(this.navList.length){
|
||||
return this.navList
|
||||
}else{
|
||||
let arr = [];
|
||||
this.selectNavList.forEach((item,index)=>{
|
||||
if(this.openNavList.includes(index)){
|
||||
arr.push(item);
|
||||
}
|
||||
})
|
||||
return arr
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
linkPage(url){
|
||||
if (['/pages/goods_cate/goods_cate', '/pages/order_addcart/order_addcart', '/pages/user/index', '/pages/index/index']
|
||||
.indexOf(url) == -1) {
|
||||
uni.navigateTo({
|
||||
url: url
|
||||
})
|
||||
} else {
|
||||
uni.switchTab({
|
||||
url: url
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.dialog_nav{
|
||||
position: fixed;
|
||||
left: 14rpx;
|
||||
width: 240rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px 16rpx rgba(0, 0, 0, 0.08);
|
||||
z-index: 310;
|
||||
border-radius: 14rpx;
|
||||
&::before{
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
left: -26rpx;
|
||||
right: 0;
|
||||
margin:auto;
|
||||
top:-9px;
|
||||
border-bottom: 10px solid #FFFFFF;
|
||||
border-left: 10px solid transparent; /*transparent 表示透明*/
|
||||
border-right: 10px solid transparent;
|
||||
}
|
||||
&.dialogIndex{
|
||||
left: 14rpx;
|
||||
&::before{
|
||||
left: 0rpx !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.dialog_nav_item{
|
||||
width: 100%;
|
||||
height: 84rpx;
|
||||
line-height: 84rpx;
|
||||
padding: 0 20rpx 0;
|
||||
box-sizing: border-box;
|
||||
border-bottom: #eee;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
position: relative;
|
||||
display: flex;
|
||||
.iconfont{
|
||||
font-size: 32rpx;
|
||||
margin-right: 26rpx;
|
||||
}
|
||||
}
|
||||
.dialog_after{
|
||||
::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
width:90px;
|
||||
height: 1px;
|
||||
background-color: #EEEEEE;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
814
components/jyf-parser/jyf-parser.vue
Normal file
814
components/jyf-parser/jyf-parser.vue
Normal file
@@ -0,0 +1,814 @@
|
||||
<!--
|
||||
parser 主模块组件
|
||||
github:https://github.com/jin-yufeng/Parser
|
||||
docs:https://jin-yufeng.github.io/Parser
|
||||
插件市场:https://ext.dcloud.net.cn/plugin?id=805
|
||||
author:JinYufeng
|
||||
update:2020/04/14
|
||||
-->
|
||||
<template>
|
||||
<view>
|
||||
<slot v-if="!nodes.length" />
|
||||
<!--#ifdef APP-PLUS-NVUE-->
|
||||
<web-view id="top" ref="web" :src="src" :style="'margin-top:-2px;height:'+height+'px'" @onPostMessage="_message" />
|
||||
<!--#endif-->
|
||||
<!--#ifndef APP-PLUS-NVUE-->
|
||||
<view id="top" :style="showAm+(selectable?';user-select:text;-webkit-user-select:text':'')" :animation="scaleAm" @tap="_tap"
|
||||
@touchstart="_touchstart" @touchmove="_touchmove">
|
||||
<!--#ifdef H5-->
|
||||
<div :id="'rtf'+uid"></div>
|
||||
<!--#endif-->
|
||||
<!--#ifndef H5-->
|
||||
<trees :nodes="nodes" :lazy-load="lazyLoad" :loadVideo="loadVideo" />
|
||||
<image v-for="(item, index) in imgs" v-bind:key="index" :id="index" :src="item" hidden @load="_load" />
|
||||
<!--#endif-->
|
||||
</view>
|
||||
<!--#endif-->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifndef H5 || APP-PLUS-NVUE
|
||||
import trees from './libs/trees';
|
||||
var cache = {},
|
||||
// #ifdef MP-WEIXIN || MP-TOUTIAO
|
||||
fs = uni.getFileSystemManager ? uni.getFileSystemManager() : null,
|
||||
// #endif
|
||||
Parser = require('./libs/MpHtmlParser.js');
|
||||
var document; // document 补丁包 https://jin-yufeng.github.io/Parser/#/instructions?id=document
|
||||
// 计算 cache 的 key
|
||||
function hash(str) {
|
||||
for (var i = str.length, val = 5381; i--;)
|
||||
val += (val << 5) + str.charCodeAt(i);
|
||||
return val;
|
||||
}
|
||||
// #endif
|
||||
// #ifdef H5 || APP-PLUS-NVUE
|
||||
var rpx = uni.getWindowInfo().screenWidth / 750,
|
||||
cfg = require('./libs/config.js');
|
||||
// #endif
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
var dom = weex.requireModule('dom');
|
||||
// #endif
|
||||
export default {
|
||||
name: 'parser',
|
||||
data() {
|
||||
return {
|
||||
// #ifdef APP-PLUS
|
||||
loadVideo: false,
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
uid: this._uid,
|
||||
// #endif
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
src: '',
|
||||
height: 1,
|
||||
// #endif
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
scaleAm: '',
|
||||
showAm: '',
|
||||
imgs: [],
|
||||
// #endif
|
||||
nodes: []
|
||||
}
|
||||
},
|
||||
// #ifndef H5 || APP-PLUS-NVUE
|
||||
components: {
|
||||
trees
|
||||
},
|
||||
// #endif
|
||||
props: {
|
||||
'html': null,
|
||||
// #ifndef MP-ALIPAY
|
||||
'autopause': {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// #endif
|
||||
'autosetTitle': {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// #ifndef H5 || APP-PLUS-NVUE
|
||||
'compress': Number,
|
||||
'useCache': Boolean,
|
||||
'xml': Boolean,
|
||||
// #endif
|
||||
'domain': String,
|
||||
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
|
||||
'gestureZoom': Boolean,
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN || MP-QQ || H5 || APP-PLUS
|
||||
'lazyLoad': Boolean,
|
||||
// #endif
|
||||
'selectable': Boolean,
|
||||
'tagStyle': Object,
|
||||
'showWithAnimation': Boolean,
|
||||
'useAnchor': Boolean
|
||||
},
|
||||
watch: {
|
||||
html(html) {
|
||||
this.setContent(html);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 图片数组
|
||||
this.imgList = [];
|
||||
this.imgList.each = function(f) {
|
||||
for (var i = 0, len = this.length; i < len; i++)
|
||||
this.setItem(i, f(this[i], i, this));
|
||||
}
|
||||
this.imgList.setItem = function(i, src) {
|
||||
if (i == void 0 || !src) return;
|
||||
// #ifndef MP-ALIPAY || APP-PLUS
|
||||
// 去重
|
||||
if (src.indexOf('http') == 0 && this.includes(src)) {
|
||||
var newSrc = '';
|
||||
for (var j = 0, c; c = src[j]; j++) {
|
||||
if (c == '/' && src[j - 1] != '/' && src[j + 1] != '/') break;
|
||||
newSrc += Math.random() > 0.5 ? c.toUpperCase() : c;
|
||||
}
|
||||
newSrc += src.substr(j);
|
||||
return this[i] = newSrc;
|
||||
}
|
||||
// #endif
|
||||
this[i] = src;
|
||||
// 暂存 data src
|
||||
if (src.includes('data:image')) {
|
||||
var filePath, info = src.match(/data:image\/(\S+?);(\S+?),(.+)/);
|
||||
if (!info) return;
|
||||
// #ifdef MP-WEIXIN || MP-TOUTIAO
|
||||
filePath = `${wx.env.USER_DATA_PATH}/${Date.now()}.${info[1]}`;
|
||||
fs && fs.writeFile({
|
||||
filePath,
|
||||
data: info[3],
|
||||
encoding: info[2],
|
||||
success: () => this[i] = filePath
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
filePath = `_doc/parser_tmp/${Date.now()}.${info[1]}`;
|
||||
var bitmap = new plus.nativeObj.Bitmap();
|
||||
bitmap.loadBase64Data(src, () => {
|
||||
bitmap.save(filePath, {}, () => {
|
||||
bitmap.clear()
|
||||
this[i] = filePath;
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
if (this.html) this.setContent(this.html);
|
||||
},
|
||||
beforeDestroy() {
|
||||
// #ifdef H5
|
||||
if (this._observer) this._observer.disconnect();
|
||||
// #endif
|
||||
this.imgList.each(src => {
|
||||
// #ifdef APP-PLUS
|
||||
if (src && src.includes('_doc')) {
|
||||
plus.io.resolveLocalFileSystemURL(src, entry => {
|
||||
entry.remove();
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN || MP-TOUTIAO
|
||||
if (src && uni.env && src.includes(uni.env.USER_DATA_PATH))
|
||||
fs && fs.unlink({
|
||||
filePath: src
|
||||
})
|
||||
// #endif
|
||||
})
|
||||
clearInterval(this._timer);
|
||||
},
|
||||
methods: {
|
||||
// #ifdef H5 || APP-PLUS-NVUE
|
||||
_Dom2Str(nodes) {
|
||||
var str = '';
|
||||
for (var node of nodes) {
|
||||
if (node.type == 'text')
|
||||
str += node.text;
|
||||
else {
|
||||
str += ('<' + node.name);
|
||||
for (var attr in node.attrs || {})
|
||||
str += (' ' + attr + '="' + node.attrs[attr] + '"');
|
||||
if (!node.children || !node.children.length) str += '>';
|
||||
else str += ('>' + this._Dom2Str(node.children) + '</' + node.name + '>');
|
||||
}
|
||||
}
|
||||
return str;
|
||||
},
|
||||
_handleHtml(html, append) {
|
||||
if (typeof html != 'string') html = this._Dom2Str(html.nodes || html);
|
||||
// 处理 rpx
|
||||
if (html.includes('rpx'))
|
||||
html = html.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * rpx + 'px');
|
||||
if (!append) {
|
||||
// 处理 tag-style 和 userAgentStyles
|
||||
var style = '<style>@keyframes show{0%{opacity:0}100%{opacity:1}}';
|
||||
for (var item in cfg.userAgentStyles)
|
||||
style += `${item}{${cfg.userAgentStyles[item]}}`;
|
||||
for (item in this.tagStyle)
|
||||
style += `${item}{${this.tagStyle[item]}}`;
|
||||
style += '</style>';
|
||||
html = style + html;
|
||||
}
|
||||
return html;
|
||||
},
|
||||
// #endif
|
||||
setContent(html, append) {
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
if (!html) {
|
||||
this.src = '';
|
||||
this.height = 1;
|
||||
return;
|
||||
}
|
||||
if (append) return;
|
||||
plus.io.resolveLocalFileSystemURL('_doc', entry => {
|
||||
entry.getDirectory('parser_tmp', {
|
||||
create: true
|
||||
}, entry => {
|
||||
var fileName = Date.now() + '.html';
|
||||
entry.getFile(fileName, {
|
||||
create: true
|
||||
}, entry => {
|
||||
entry.createWriter(writer => {
|
||||
writer.onwriteend = () => {
|
||||
this.nodes = [1];
|
||||
this.src = '_doc/parser_tmp/' + fileName;
|
||||
this.$nextTick(function() {
|
||||
entry.remove();
|
||||
})
|
||||
}
|
||||
html =
|
||||
'<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1' +
|
||||
(this.selectable ? '' : ',user-scalable=no') +
|
||||
'"><script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></' +
|
||||
'script><base href="' + this.domain + '">' + this._handleHtml(html) +
|
||||
'<script>"use strict";function post(t){uni.postMessage({data:t})}' +
|
||||
(this.showWithAnimation ? 'document.body.style.animation="show .5s",' : '') +
|
||||
'document.addEventListener("UniAppJSBridgeReady",function(){post({action:"load",text:document.body.innerText});var t=document.getElementsByTagName("title");t.length&&post({action:"getTitle",title:t[0].innerText});for(var e,o=document.getElementsByTagName("img"),n=[],i=0,r=0;e=o[i];i++)e.onerror=function(){post({action:"error",source:"img",target:this})},e.hasAttribute("ignore")||"A"==e.parentElement.nodeName||(e.i=r++,n.push(e.src),e.onclick=function(){post({action:"preview",img:{i:this.i,src:this.src}})});post({action:"getImgList",imgList:n});for(var a,s=document.getElementsByTagName("a"),c=0;a=s[c];c++)a.onclick=function(){var t,e=this.getAttribute("href");if("#"==e[0]){var r=document.getElementById(e.substr(1));r&&(t=r.offsetTop)}return post({action:"linkpress",href:e,offset:t}),!1};;for(var u,m=document.getElementsByTagName("video"),d=0;u=m[d];d++)u.style.maxWidth="100%",u.onerror=function(){post({action:"error",source:"video",target:this})}' +
|
||||
(this.autopause ? ',u.onplay=function(){for(var t,e=0;t=m[e];e++)t!=this&&t.pause()}' : '') +
|
||||
';for(var g,l=document.getElementsByTagName("audio"),p=0;g=l[p];p++)g.onerror=function(){post({action:"error",source:"audio",target:this})};window.onload=function(){post({action:"ready",height:document.body.scrollHeight})}});</' +
|
||||
'script>';
|
||||
writer.write(html);
|
||||
});
|
||||
})
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
if (!html) {
|
||||
if (this.rtf && !append) this.rtf.parentNode.removeChild(this.rtf);
|
||||
return;
|
||||
}
|
||||
var div = document.createElement('div');
|
||||
if (!append) {
|
||||
if (this.rtf) this.rtf.parentNode.removeChild(this.rtf);
|
||||
this.rtf = div;
|
||||
} else {
|
||||
if (!this.rtf) this.rtf = div;
|
||||
else this.rtf.appendChild(div);
|
||||
}
|
||||
div.innerHTML = this._handleHtml(html, append);
|
||||
for (var styles = this.rtf.getElementsByTagName('style'), i = 0, style; style = styles[i++];) {
|
||||
style.innerHTML = style.innerHTML.replace(/body/g, '#rtf' + this._uid);
|
||||
style.setAttribute('scoped', 'true');
|
||||
}
|
||||
// 懒加载
|
||||
if (!this._observer && this.lazyLoad && IntersectionObserver) {
|
||||
this._observer = new IntersectionObserver(changes => {
|
||||
for (let item, i = 0; item = changes[i++];) {
|
||||
if (item.isIntersecting) {
|
||||
item.target.src = item.target.getAttribute('data-src');
|
||||
item.target.removeAttribute('data-src');
|
||||
this._observer.unobserve(item.target);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
rootMargin: '900px 0px 900px 0px'
|
||||
})
|
||||
}
|
||||
var _ts = this;
|
||||
// 获取标题
|
||||
var title = this.rtf.getElementsByTagName('title');
|
||||
if (title.length && this.autosetTitle)
|
||||
uni.setNavigationBarTitle({
|
||||
title: title[0].innerText
|
||||
})
|
||||
// 图片处理
|
||||
this.imgList.length = 0;
|
||||
var imgs = this.rtf.getElementsByTagName('img');
|
||||
for (let i = 0, j = 0, img; img = imgs[i]; i++) {
|
||||
img.style.maxWidth = '100%';
|
||||
var src = img.getAttribute('src');
|
||||
if (this.domain && src) {
|
||||
if (src[0] == '/') {
|
||||
if (src[1] == '/')
|
||||
img.src = (this.domain.includes('://') ? this.domain.split('://')[0] : '') + ':' + src;
|
||||
else img.src = this.domain + src;
|
||||
} else if (!src.includes('://')) img.src = this.domain + '/' + src;
|
||||
}
|
||||
if (!img.hasAttribute('ignore') && img.parentElement.nodeName != 'A') {
|
||||
img.i = j++;
|
||||
_ts.imgList.push(img.src || img.getAttribute('data-src'));
|
||||
img.onclick = function() {
|
||||
var preview = true;
|
||||
this.ignore = () => preview = false;
|
||||
_ts.$emit('imgtap', this);
|
||||
if (preview) {
|
||||
uni.previewImage({
|
||||
current: this.i,
|
||||
urls: _ts.imgList
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
img.onerror = function() {
|
||||
_ts.$emit('error', {
|
||||
source: 'img',
|
||||
target: this
|
||||
});
|
||||
}
|
||||
if (_ts.lazyLoad && this._observer && img.src && img.i != 0) {
|
||||
img.setAttribute('data-src', img.src);
|
||||
img.removeAttribute('src');
|
||||
this._observer.observe(img);
|
||||
}
|
||||
}
|
||||
// 链接处理
|
||||
var links = this.rtf.getElementsByTagName('a');
|
||||
for (var link of links) {
|
||||
link.onclick = function() {
|
||||
var jump = true,
|
||||
href = this.getAttribute('href');
|
||||
_ts.$emit('linkpress', {
|
||||
href,
|
||||
ignore: () => jump = false
|
||||
});
|
||||
if (jump && href) {
|
||||
if (href[0] == '#') {
|
||||
if (_ts.useAnchor) {
|
||||
_ts.navigateTo({
|
||||
id: href.substr(1)
|
||||
})
|
||||
}
|
||||
} else if (href.indexOf('http') == 0 || href.indexOf('//') == 0)
|
||||
return true;
|
||||
else {
|
||||
uni.navigateTo({
|
||||
url: href
|
||||
})
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 视频处理
|
||||
var videos = this.rtf.getElementsByTagName('video');
|
||||
_ts.videoContexts = videos;
|
||||
for (let video, i = 0; video = videos[i++];) {
|
||||
video.style.maxWidth = '100%';
|
||||
video.onerror = function() {
|
||||
_ts.$emit('error', {
|
||||
source: 'video',
|
||||
target: this
|
||||
});
|
||||
}
|
||||
video.onplay = function() {
|
||||
if (_ts.autopause)
|
||||
for (let item, i = 0; item = _ts.videoContexts[i++];)
|
||||
if (item != this) item.pause();
|
||||
}
|
||||
}
|
||||
// 音频处理
|
||||
var audios = this.rtf.getElementsByTagName('audios');
|
||||
for (var audio of audios)
|
||||
audio.onerror = function() {
|
||||
_ts.$emit('error', {
|
||||
source: 'audio',
|
||||
target: this
|
||||
});
|
||||
}
|
||||
this.document = this.rtf;
|
||||
if (!append) document.getElementById('rtf' + this._uid).appendChild(this.rtf);
|
||||
this.$nextTick(() => {
|
||||
this.nodes = [1];
|
||||
this.$emit('load');
|
||||
})
|
||||
setTimeout(() => this.showAm = '', 500);
|
||||
// #endif
|
||||
// #ifndef H5 || APP-PLUS-NVUE
|
||||
var nodes;
|
||||
if (!html)
|
||||
return this.nodes = [];
|
||||
else if (typeof html == 'string') {
|
||||
let parser = new Parser(html, this);
|
||||
// 缓存读取
|
||||
if (this.useCache) {
|
||||
var hashVal = hash(html);
|
||||
if (cache[hashVal])
|
||||
nodes = cache[hashVal];
|
||||
else {
|
||||
nodes = parser.parse();
|
||||
cache[hashVal] = nodes;
|
||||
}
|
||||
} else nodes = parser.parse();
|
||||
this.$emit('parse', nodes);
|
||||
} else if (Object.prototype.toString.call(html) == '[object Array]') {
|
||||
// 非本插件产生的 array 需要进行一些转换
|
||||
if (html.length && html[0].PoweredBy != 'Parser') {
|
||||
let parser = new Parser(html, this);
|
||||
(function f(ns) {
|
||||
for (var i = 0, n; n = ns[i]; i++) {
|
||||
if (n.type == 'text') continue;
|
||||
n.attrs = n.attrs || {};
|
||||
for (var item in n.attrs)
|
||||
if (typeof n.attrs[item] != 'string') n.attrs[item] = n.attrs[item].toString();
|
||||
parser.matchAttr(n, parser);
|
||||
if (n.children && n.children.length) {
|
||||
parser.STACK.push(n);
|
||||
f(n.children);
|
||||
parser.popNode(parser.STACK.pop());
|
||||
} else n.children = void 0;
|
||||
}
|
||||
})(html);
|
||||
}
|
||||
nodes = html;
|
||||
} else if (typeof html == 'object' && html.nodes) {
|
||||
nodes = html.nodes;
|
||||
console.warn('错误的 html 类型:object 类型已废弃');
|
||||
} else
|
||||
return console.warn('错误的 html 类型:' + typeof html);
|
||||
// #ifdef APP-PLUS
|
||||
this.loadVideo = false;
|
||||
// #endif
|
||||
if (document) this.document = new document(this.nodes, 'nodes', this);
|
||||
if (append) this.nodes = this.nodes.concat(nodes);
|
||||
else this.nodes = nodes;
|
||||
if (nodes.length && nodes[0].title && this.autosetTitle)
|
||||
uni.setNavigationBarTitle({
|
||||
title: nodes[0].title
|
||||
})
|
||||
this.$nextTick(() => {
|
||||
this.imgList.length = 0;
|
||||
this.videoContexts = [];
|
||||
// #ifdef MP-TOUTIAO
|
||||
setTimeout(() => {
|
||||
// #endif
|
||||
var f = (cs) => {
|
||||
for (let i = 0, c; c = cs[i++];) {
|
||||
if (c.$options.name == 'trees') {
|
||||
for (var j = c.nodes.length, item; item = c.nodes[--j];) {
|
||||
if (item.c) continue;
|
||||
if (item.name == 'img') {
|
||||
this.imgList.setItem(item.attrs.i, item.attrs.src);
|
||||
// #ifndef MP-ALIPAY
|
||||
if (!c.observer && !c.imgLoad && item.attrs.i != '0') {
|
||||
if (this.lazyLoad && uni.createIntersectionObserver) {
|
||||
c.observer = uni.createIntersectionObserver(c);
|
||||
c.observer.relativeToViewport({
|
||||
top: 900,
|
||||
bottom: 900
|
||||
}).observe('._img', () => {
|
||||
c.imgLoad = true;
|
||||
c.observer.disconnect();
|
||||
})
|
||||
} else
|
||||
c.imgLoad = true;
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
// #ifndef MP-ALIPAY
|
||||
else if (item.name == 'video') {
|
||||
var ctx = uni.createVideoContext(item.attrs.id, c);
|
||||
ctx.id = item.attrs.id;
|
||||
this.videoContexts.push(ctx);
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU || MP-ALIPAY || APP-PLUS
|
||||
if (item.attrs && item.attrs.id) {
|
||||
this.anchors = this.anchors || [];
|
||||
this.anchors.push({
|
||||
id: item.attrs.id,
|
||||
node: c
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
if (c.$children.length)
|
||||
f(c.$children)
|
||||
}
|
||||
}
|
||||
f(this.$children);
|
||||
// #ifdef MP-TOUTIAO
|
||||
}, 200)
|
||||
this.$emit('load');
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
setTimeout(() => {
|
||||
this.loadVideo = true;
|
||||
}, 3000);
|
||||
// #endif
|
||||
})
|
||||
// #endif
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
var height;
|
||||
clearInterval(this._timer);
|
||||
this._timer = setInterval(() => {
|
||||
// #ifdef H5
|
||||
var res = [this.rtf.getBoundingClientRect()];
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
// #ifdef APP-PLUS
|
||||
uni.createSelectorQuery().in(this)
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
this.createSelectorQuery()
|
||||
// #endif
|
||||
.select('#top').boundingClientRect().exec(res => {
|
||||
// #endif
|
||||
this.width = res[0].width;
|
||||
if (res[0].height == height) {
|
||||
this.$emit('ready', res[0])
|
||||
clearInterval(this._timer);
|
||||
}
|
||||
height = res[0].height;
|
||||
// #ifndef H5
|
||||
});
|
||||
// #endif
|
||||
}, 350)
|
||||
if (this.showWithAnimation && !append) this.showAm = 'animation:show .5s';
|
||||
// #endif
|
||||
},
|
||||
getText(ns = this.nodes) {
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
return this._text;
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
return this.rtf.innerText;
|
||||
// #endif
|
||||
// #ifndef H5 || APP-PLUS-NVUE
|
||||
var txt = '';
|
||||
for (var i = 0, n; n = ns[i++];) {
|
||||
if (n.type == 'text') txt += n.text.replace(/ /g, '\u00A0').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/&/g, '&');
|
||||
else if (n.type == 'br') txt += '\n';
|
||||
else {
|
||||
// 块级标签前后加换行
|
||||
var block = n.name == 'p' || n.name == 'div' || n.name == 'tr' || n.name == 'li' || (n.name[0] == 'h' && n.name[1] >
|
||||
'0' && n.name[1] < '7');
|
||||
if (block && txt && txt[txt.length - 1] != '\n') txt += '\n';
|
||||
if (n.children) txt += this.getText(n.children);
|
||||
if (block && txt[txt.length - 1] != '\n') txt += '\n';
|
||||
else if (n.name == 'td' || n.name == 'th') txt += '\t';
|
||||
}
|
||||
}
|
||||
return txt;
|
||||
// #endif
|
||||
},
|
||||
navigateTo(obj) {
|
||||
if (!this.useAnchor)
|
||||
return obj.fail && obj.fail({
|
||||
errMsg: 'Anchor is disabled'
|
||||
})
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
if (!obj.id)
|
||||
dom.scrollToElement(this.$refs.web);
|
||||
else
|
||||
this.$refs.web.evalJs('var pos=document.getElementById("' + obj.id +
|
||||
'");if(pos)post({action:"linkpress",href:"#",offset:pos.offsetTop})');
|
||||
return obj.success && obj.success({
|
||||
errMsg: 'pageScrollTo:ok'
|
||||
});
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
if (!obj.id) {
|
||||
window.scrollTo(0, this.rtf.offsetTop);
|
||||
return obj.success && obj.success({
|
||||
errMsg: 'pageScrollTo:ok'
|
||||
});
|
||||
}
|
||||
var target = document.getElementById(obj.id);
|
||||
if (!target) return obj.fail && obj.fail({
|
||||
errMsg: 'Label not found'
|
||||
});
|
||||
obj.scrollTop = this.rtf.offsetTop + target.offsetTop;
|
||||
uni.pageScrollTo(obj);
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
var Scroll = (selector, component) => {
|
||||
uni.createSelectorQuery().in(component ? component : this).select(selector).boundingClientRect().selectViewport()
|
||||
.scrollOffset()
|
||||
.exec(res => {
|
||||
if (!res || !res[0])
|
||||
return obj.fail && obj.fail({
|
||||
errMsg: 'Label not found'
|
||||
});
|
||||
obj.scrollTop = res[1].scrollTop + res[0].top;
|
||||
uni.pageScrollTo(obj);
|
||||
})
|
||||
}
|
||||
if (!obj.id) Scroll('#top');
|
||||
else {
|
||||
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
|
||||
Scroll('#top >>> #' + obj.id + ', #top >>> .' + obj.id);
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU || MP-ALIPAY || APP-PLUS
|
||||
for (var anchor of this.anchors)
|
||||
if (anchor.id == obj.id)
|
||||
Scroll('#' + obj.id + ', .' + obj.id, anchor.node);
|
||||
// #endif
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
getVideoContext(id) {
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
if (!id) return this.videoContexts;
|
||||
else
|
||||
for (var i = this.videoContexts.length; i--;)
|
||||
if (this.videoContexts[i].id == id) return this.videoContexts[i];
|
||||
// #endif
|
||||
},
|
||||
// 预加载
|
||||
preLoad(html, num) {
|
||||
// #ifdef H5 || APP-PLUS-NVUE
|
||||
if (html.constructor == Array)
|
||||
html = this._Dom2Str(html);
|
||||
var script = "var contain=document.createElement('div');contain.innerHTML='" + html.replace(/'/g, "\\'") +
|
||||
"';for(var imgs=contain.querySelectorAll('img'),i=imgs.length-1;i>=" + num +
|
||||
";i--)imgs[i].removeAttribute('src');";
|
||||
// #endif
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
this.$refs.web.evalJs(script);
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
eval(script);
|
||||
// #endif
|
||||
// #ifndef H5 || APP-PLUS-NVUE
|
||||
if (typeof html == 'string') {
|
||||
var id = hash(html);
|
||||
html = new Parser(html, this).parse();
|
||||
cache[id] = html;
|
||||
}
|
||||
var wait = [];
|
||||
(function f(ns) {
|
||||
for (var i = 0, n; n = ns[i++];) {
|
||||
if (n.name == 'img' && n.attrs.src && !wait.includes(n.attrs.src))
|
||||
wait.push(n.attrs.src);
|
||||
f(n.children || []);
|
||||
}
|
||||
})(html);
|
||||
if (num) wait = wait.slice(0, num);
|
||||
this._wait = (this._wait || []).concat(wait);
|
||||
if (!this.imgs) this.imgs = this._wait.splice(0, 15);
|
||||
else if (this.imgs.length < 15)
|
||||
this.imgs = this.imgs.concat(this._wait.splice(0, 15 - this.imgs.length));
|
||||
// #endif
|
||||
},
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
_message(e) {
|
||||
// 接收 web-view 消息
|
||||
var data = e.detail.data[0];
|
||||
if (data.action == 'load') {
|
||||
this.$emit('load');
|
||||
this._text = data.text;
|
||||
} else if (data.action == 'getTitle') {
|
||||
if (this.autosetTitle)
|
||||
uni.setNavigationBarTitle({
|
||||
title: data.title
|
||||
})
|
||||
} else if (data.action == 'getImgList') {
|
||||
this.imgList.length = 0;
|
||||
for (var i = data.imgList.length; i--;)
|
||||
this.imgList.setItem(i, data.imgList[i]);
|
||||
} else if (data.action == 'preview') {
|
||||
var preview = true;
|
||||
data.img.ignore = () => preview = false;
|
||||
this.$emit('imgtap', data.img);
|
||||
if (preview)
|
||||
uni.previewImage({
|
||||
current: data.img.i,
|
||||
urls: this.imgList
|
||||
})
|
||||
} else if (data.action == 'linkpress') {
|
||||
var jump = true,
|
||||
href = data.href;
|
||||
this.$emit('linkpress', {
|
||||
href,
|
||||
ignore: () => jump = false
|
||||
})
|
||||
if (jump && href) {
|
||||
if (href[0] == '#') {
|
||||
if (this.useAnchor)
|
||||
dom.scrollToElement(this.$refs.web, {
|
||||
offset: data.offset
|
||||
})
|
||||
} else if (href.includes('://'))
|
||||
plus.runtime.openWeb(href);
|
||||
else
|
||||
uni.navigateTo({
|
||||
url: href
|
||||
})
|
||||
}
|
||||
} else if (data.action == 'error')
|
||||
this.$emit('error', {
|
||||
source: data.source,
|
||||
target: data.target
|
||||
})
|
||||
else if (data.action == 'ready') {
|
||||
this.height = data.height;
|
||||
this.$nextTick(() => {
|
||||
uni.createSelectorQuery().in(this).select('#top').boundingClientRect().exec(res => {
|
||||
this.rect = res[0];
|
||||
this.$emit('ready', res[0]);
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
// #ifndef H5
|
||||
_load(e) {
|
||||
if (this._wait.length)
|
||||
this.$set(this.imgs, e.target.id, this._wait.shift());
|
||||
},
|
||||
// #endif
|
||||
_tap(e) {
|
||||
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
|
||||
if (this.gestureZoom && e.timeStamp - this._lastT < 300) {
|
||||
var initY = e.touches[0].pageY - e.currentTarget.offsetTop;
|
||||
if (this._zoom) {
|
||||
this._scaleAm.translateX(0).scale(1).step();
|
||||
uni.pageScrollTo({
|
||||
scrollTop: (initY + this._initY) / 2 - e.touches[0].clientY,
|
||||
duration: 400
|
||||
})
|
||||
} else {
|
||||
var initX = e.touches[0].pageX - e.currentTarget.offsetLeft;
|
||||
this._initY = initY;
|
||||
this._scaleAm = uni.createAnimation({
|
||||
transformOrigin: `${initX}px ${this._initY}px 0`,
|
||||
timingFunction: 'ease-in-out'
|
||||
});
|
||||
// #ifdef MP-TOUTIAO
|
||||
this._scaleAm.opacity(1);
|
||||
// #endif
|
||||
this._scaleAm.scale(2).step();
|
||||
this._tMax = initX / 2;
|
||||
this._tMin = (initX - this.width) / 2;
|
||||
this._tX = 0;
|
||||
}
|
||||
this._zoom = !this._zoom;
|
||||
this.scaleAm = this._scaleAm.export();
|
||||
}
|
||||
this._lastT = e.timeStamp;
|
||||
// #endif
|
||||
},
|
||||
_touchstart(e) {
|
||||
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
|
||||
if (e.touches.length == 1)
|
||||
this._initX = this._lastX = e.touches[0].pageX;
|
||||
// #endif
|
||||
},
|
||||
_touchmove(e) {
|
||||
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
|
||||
var diff = e.touches[0].pageX - this._lastX;
|
||||
if (this._zoom && e.touches.length == 1 && Math.abs(diff) > 20) {
|
||||
this._lastX = e.touches[0].pageX;
|
||||
if ((this._tX <= this._tMin && diff < 0) || (this._tX >= this._tMax && diff > 0))
|
||||
return;
|
||||
this._tX += (diff * Math.abs(this._lastX - this._initX) * 0.05);
|
||||
if (this._tX < this._tMin) this._tX = this._tMin;
|
||||
if (this._tX > this._tMax) this._tX = this._tMax;
|
||||
this._scaleAm.translateX(this._tX).step();
|
||||
this.scaleAm = this._scaleAm.export();
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@keyframes show {
|
||||
0% {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* #ifdef MP-WEIXIN */
|
||||
:host {
|
||||
display: block;
|
||||
overflow: scroll;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
||||
102
components/jyf-parser/libs/CssHandler.js
Normal file
102
components/jyf-parser/libs/CssHandler.js
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
解析和匹配 Css 的选择器
|
||||
github:https://github.com/jin-yufeng/Parser
|
||||
docs:https://jin-yufeng.github.io/Parser
|
||||
author:JinYufeng
|
||||
update:2020/03/15
|
||||
*/
|
||||
var cfg = require('./config.js');
|
||||
class CssHandler {
|
||||
constructor(tagStyle) {
|
||||
var styles = Object.assign({}, cfg.userAgentStyles);
|
||||
for (var item in tagStyle)
|
||||
styles[item] = (styles[item] ? styles[item] + ';' : '') + tagStyle[item];
|
||||
this.styles = styles;
|
||||
}
|
||||
getStyle = data => this.styles = new CssParser(data, this.styles).parse();
|
||||
match(name, attrs) {
|
||||
var tmp, matched = (tmp = this.styles[name]) ? tmp + ';' : '';
|
||||
if (attrs.class) {
|
||||
var items = attrs.class.split(' ');
|
||||
for (var i = 0, item; item = items[i]; i++)
|
||||
if (tmp = this.styles['.' + item])
|
||||
matched += tmp + ';';
|
||||
}
|
||||
if (tmp = this.styles['#' + attrs.id])
|
||||
matched += tmp + ';';
|
||||
return matched;
|
||||
}
|
||||
}
|
||||
module.exports = CssHandler;
|
||||
class CssParser {
|
||||
constructor(data, init) {
|
||||
this.data = data;
|
||||
this.floor = 0;
|
||||
this.i = 0;
|
||||
this.list = [];
|
||||
this.res = init;
|
||||
this.state = this.Space;
|
||||
}
|
||||
parse() {
|
||||
for (var c; c = this.data[this.i]; this.i++)
|
||||
this.state(c);
|
||||
return this.res;
|
||||
}
|
||||
section = () => this.data.substring(this.start, this.i);
|
||||
isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
// 状态机
|
||||
Space(c) {
|
||||
if (c == '.' || c == '#' || this.isLetter(c)) {
|
||||
this.start = this.i;
|
||||
this.state = this.Name;
|
||||
} else if (c == '/' && this.data[this.i + 1] == '*')
|
||||
this.Comment();
|
||||
else if (!cfg.blankChar[c] && c != ';')
|
||||
this.state = this.Ignore;
|
||||
}
|
||||
Comment() {
|
||||
this.i = this.data.indexOf('*/', this.i) + 1;
|
||||
if (!this.i) this.i = this.data.length;
|
||||
this.state = this.Space;
|
||||
}
|
||||
Ignore(c) {
|
||||
if (c == '{') this.floor++;
|
||||
else if (c == '}' && !--this.floor) this.state = this.Space;
|
||||
}
|
||||
Name(c) {
|
||||
if (cfg.blankChar[c]) {
|
||||
this.list.push(this.section());
|
||||
this.state = this.NameSpace;
|
||||
} else if (c == '{') {
|
||||
this.list.push(this.section());
|
||||
this.Content();
|
||||
} else if (c == ',') {
|
||||
this.list.push(this.section());
|
||||
this.Comma();
|
||||
} else if (!this.isLetter(c) && (c < '0' || c > '9') && c != '-' && c != '_')
|
||||
this.state = this.Ignore;
|
||||
}
|
||||
NameSpace(c) {
|
||||
if (c == '{') this.Content();
|
||||
else if (c == ',') this.Comma();
|
||||
else if (!cfg.blankChar[c]) this.state = this.Ignore;
|
||||
}
|
||||
Comma() {
|
||||
while (cfg.blankChar[this.data[++this.i]]);
|
||||
if (this.data[this.i] == '{') this.Content();
|
||||
else {
|
||||
this.start = this.i--;
|
||||
this.state = this.Name;
|
||||
}
|
||||
}
|
||||
Content() {
|
||||
this.start = ++this.i;
|
||||
if ((this.i = this.data.indexOf('}', this.i)) == -1) this.i = this.data.length;
|
||||
var content = this.section();
|
||||
for (var i = 0, item; item = this.list[i++];)
|
||||
if (this.res[item]) this.res[item] += ';' + content;
|
||||
else this.res[item] = content;
|
||||
this.list = [];
|
||||
this.state = this.Space;
|
||||
}
|
||||
}
|
||||
577
components/jyf-parser/libs/MpHtmlParser.js
Normal file
577
components/jyf-parser/libs/MpHtmlParser.js
Normal file
@@ -0,0 +1,577 @@
|
||||
/*
|
||||
将 html 解析为适用于小程序 rich-text 的 DOM 结构
|
||||
github:https://github.com/jin-yufeng/Parser
|
||||
docs:https://jin-yufeng.github.io/Parser
|
||||
author:JinYufeng
|
||||
update:2020/04/13
|
||||
*/
|
||||
var cfg = require('./config.js'),
|
||||
blankChar = cfg.blankChar,
|
||||
CssHandler = require('./CssHandler.js'),
|
||||
{
|
||||
screenWidth,
|
||||
system
|
||||
} = wx.getSystemInfoSync();
|
||||
// #ifdef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO
|
||||
var entities = {
|
||||
lt: '<',
|
||||
gt: '>',
|
||||
amp: '&',
|
||||
quot: '"',
|
||||
apos: "'",
|
||||
nbsp: '\xA0',
|
||||
ensp: '\u2002',
|
||||
emsp: '\u2003',
|
||||
ndash: '–',
|
||||
mdash: '—',
|
||||
middot: '·',
|
||||
lsquo: '‘',
|
||||
rsquo: '’',
|
||||
ldquo: '“',
|
||||
rdquo: '”',
|
||||
bull: '•',
|
||||
hellip: '…',
|
||||
permil: '‰',
|
||||
copy: '©',
|
||||
reg: '®',
|
||||
trade: '™',
|
||||
times: '×',
|
||||
divide: '÷',
|
||||
cent: '¢',
|
||||
pound: '£',
|
||||
yen: '¥',
|
||||
euro: '€',
|
||||
sect: '§'
|
||||
};
|
||||
// #endif
|
||||
var emoji; // emoji 补丁包 https://jin-yufeng.github.io/Parser/#/instructions?id=emoji
|
||||
class MpHtmlParser {
|
||||
constructor(data, options = {}) {
|
||||
this.attrs = {};
|
||||
this.compress = options.compress;
|
||||
this.CssHandler = new CssHandler(options.tagStyle, screenWidth);
|
||||
this.data = data;
|
||||
this.domain = options.domain;
|
||||
this.DOM = [];
|
||||
this.i = this.start = this.audioNum = this.imgNum = this.videoNum = 0;
|
||||
this.protocol = this.domain && this.domain.includes('://') ? this.domain.split('://')[0] : '';
|
||||
this.state = this.Text;
|
||||
this.STACK = [];
|
||||
this.useAnchor = options.useAnchor;
|
||||
this.xml = options.xml;
|
||||
}
|
||||
parse() {
|
||||
if (emoji) this.data = emoji.parseEmoji(this.data);
|
||||
for (var c; c = this.data[this.i]; this.i++)
|
||||
this.state(c);
|
||||
if (this.state == this.Text) this.setText();
|
||||
while (this.STACK.length) this.popNode(this.STACK.pop());
|
||||
// #ifdef MP-BAIDU || MP-TOUTIAO
|
||||
// 将顶层标签的一些样式提取出来给 rich-text
|
||||
(function f(ns) {
|
||||
for (var i = ns.length, n; n = ns[--i];) {
|
||||
if (n.type == 'text') continue;
|
||||
if (!n.c) {
|
||||
var style = n.attrs.style;
|
||||
if (style) {
|
||||
var j, k, res;
|
||||
if ((j = style.indexOf('display')) != -1)
|
||||
res = style.substring(j, (k = style.indexOf(';', j)) == -1 ? style.length : k);
|
||||
if ((j = style.indexOf('float')) != -1)
|
||||
res += ';' + style.substring(j, (k = style.indexOf(';', j)) == -1 ? style.length : k);
|
||||
n.attrs.contain = res;
|
||||
}
|
||||
} else f(n.children);
|
||||
}
|
||||
})(this.DOM);
|
||||
// #endif
|
||||
if (this.DOM.length) {
|
||||
this.DOM[0].PoweredBy = 'Parser';
|
||||
if (this.title) this.DOM[0].title = this.title;
|
||||
}
|
||||
return this.DOM;
|
||||
}
|
||||
// 设置属性
|
||||
setAttr() {
|
||||
var name = this.getName(this.attrName);
|
||||
if (cfg.trustAttrs[name]) {
|
||||
if (!this.attrVal) {
|
||||
if (cfg.boolAttrs[name]) this.attrs[name] = 'T';
|
||||
} else if (name == 'src') this.attrs[name] = this.getUrl(this.attrVal.replace(/&/g, '&'));
|
||||
else this.attrs[name] = this.attrVal;
|
||||
}
|
||||
this.attrVal = '';
|
||||
while (blankChar[this.data[this.i]]) this.i++;
|
||||
if (this.isClose()) this.setNode();
|
||||
else {
|
||||
this.start = this.i;
|
||||
this.state = this.AttrName;
|
||||
}
|
||||
}
|
||||
// 设置文本节点
|
||||
setText() {
|
||||
var back, text = this.section();
|
||||
if (!text) return;
|
||||
text = (cfg.onText && cfg.onText(text, () => back = true)) || text;
|
||||
if (back) {
|
||||
this.data = this.data.substr(0, this.start) + text + this.data.substr(this.i);
|
||||
let j = this.start + text.length;
|
||||
for (this.i = this.start; this.i < j; this.i++) this.state(this.data[this.i]);
|
||||
return;
|
||||
}
|
||||
if (!this.pre) {
|
||||
// 合并空白符
|
||||
var tmp = [];
|
||||
for (let i = text.length, c; c = text[--i];)
|
||||
if (!blankChar[c] || (!blankChar[tmp[0]] && (c = ' '))) tmp.unshift(c);
|
||||
text = tmp.join('');
|
||||
if (text == ' ') return;
|
||||
}
|
||||
// 处理实体
|
||||
var siblings = this.siblings(),
|
||||
i = -1,
|
||||
j, en;
|
||||
while (1) {
|
||||
if ((i = text.indexOf('&', i + 1)) == -1) break;
|
||||
if ((j = text.indexOf(';', i + 2)) == -1) break;
|
||||
if (text[i + 1] == '#') {
|
||||
en = parseInt((text[i + 2] == 'x' ? '0' : '') + text.substring(i + 2, j));
|
||||
if (!isNaN(en)) text = text.substr(0, i) + String.fromCharCode(en) + text.substring(j + 1);
|
||||
} else {
|
||||
en = text.substring(i + 1, j);
|
||||
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
|
||||
if (en == 'nbsp') text = text.substr(0, i) + '\xA0' + text.substr(j + 1); // 解决 失效
|
||||
else if (en != 'lt' && en != 'gt' && en != 'amp' && en != 'ensp' && en != 'emsp' && en != 'quot' && en != 'apos') {
|
||||
i && siblings.push({
|
||||
type: 'text',
|
||||
text: text.substr(0, i)
|
||||
})
|
||||
siblings.push({
|
||||
type: 'text',
|
||||
text: `&${en};`,
|
||||
en: 1
|
||||
})
|
||||
text = text.substr(j + 1);
|
||||
i = -1;
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO
|
||||
if (entities[en]) text = text.substr(0, i) + entities[en] + text.substr(j + 1);
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
text && siblings.push({
|
||||
type: 'text',
|
||||
text
|
||||
})
|
||||
}
|
||||
// 设置元素节点
|
||||
setNode() {
|
||||
var node = {
|
||||
name: this.tagName.toLowerCase(),
|
||||
attrs: this.attrs
|
||||
},
|
||||
close = cfg.selfClosingTags[node.name] || (this.xml && this.data[this.i] == '/');
|
||||
this.attrs = {};
|
||||
if (!cfg.ignoreTags[node.name]) {
|
||||
this.matchAttr(node);
|
||||
if (!close) {
|
||||
node.children = [];
|
||||
if (node.name == 'pre' && cfg.highlight) {
|
||||
this.remove(node);
|
||||
this.pre = node.pre = true;
|
||||
}
|
||||
this.siblings().push(node);
|
||||
this.STACK.push(node);
|
||||
} else if (!cfg.filter || cfg.filter(node, this) != false)
|
||||
this.siblings().push(node);
|
||||
} else {
|
||||
if (!close) this.remove(node);
|
||||
else if (node.name == 'source') {
|
||||
var parent = this.STACK[this.STACK.length - 1],
|
||||
attrs = node.attrs;
|
||||
if (parent && attrs.src)
|
||||
if (parent.name == 'video' || parent.name == 'audio')
|
||||
parent.attrs.source.push(attrs.src);
|
||||
else {
|
||||
var i, media = attrs.media;
|
||||
if (parent.name == 'picture' && !parent.attrs.src && !(attrs.src.indexOf('.webp') && system.includes('iOS')) &&
|
||||
(!media || (media.includes('px') &&
|
||||
(((i = media.indexOf('min-width')) != -1 && (i = media.indexOf(':', i + 8)) != -1 && screenWidth > parseInt(
|
||||
media.substr(i + 1))) ||
|
||||
((i = media.indexOf('max-width')) != -1 && (i = media.indexOf(':', i + 8)) != -1 && screenWidth < parseInt(
|
||||
media.substr(i + 1)))))))
|
||||
parent.attrs.src = attrs.src;
|
||||
}
|
||||
} else if (node.name == 'base' && !this.domain) this.domain = node.attrs.href;
|
||||
}
|
||||
if (this.data[this.i] == '/') this.i++;
|
||||
this.start = this.i + 1;
|
||||
this.state = this.Text;
|
||||
}
|
||||
// 移除标签
|
||||
remove(node) {
|
||||
var name = node.name,
|
||||
j = this.i;
|
||||
while (1) {
|
||||
if ((this.i = this.data.indexOf('</', this.i + 1)) == -1) {
|
||||
if (name == 'pre' || name == 'svg') this.i = j;
|
||||
else this.i = this.data.length;
|
||||
return;
|
||||
}
|
||||
this.start = (this.i += 2);
|
||||
while (!blankChar[this.data[this.i]] && !this.isClose()) this.i++;
|
||||
if (this.getName(this.section()) == name) {
|
||||
// 代码块高亮
|
||||
if (name == 'pre') {
|
||||
this.data = this.data.substr(0, j + 1) + cfg.highlight(this.data.substring(j + 1, this.i - 5), node.attrs) +
|
||||
this.data.substr(this.i - 5);
|
||||
return this.i = j;
|
||||
} else if (name == 'style')
|
||||
this.CssHandler.getStyle(this.data.substring(j + 1, this.i - 7));
|
||||
else if (name == 'title')
|
||||
this.title = this.data.substring(j + 1, this.i - 7);
|
||||
if ((this.i = this.data.indexOf('>', this.i)) == -1) this.i = this.data.length;
|
||||
// 处理 svg
|
||||
if (name == 'svg') {
|
||||
var src = this.data.substring(j, this.i + 1);
|
||||
if (!node.attrs.xmlns) src = ' xmlns="http://www.w3.org/2000/svg"' + src;
|
||||
var i = j;
|
||||
while (this.data[j] != '<') j--;
|
||||
src = this.data.substring(j, i) + src;
|
||||
var parent = this.STACK[this.STACK.length - 1];
|
||||
if (node.attrs.width == '100%' && parent && (parent.attrs.style || '').includes('inline'))
|
||||
parent.attrs.style = 'width:300px;max-width:100%;' + parent.attrs.style;
|
||||
this.siblings().push({
|
||||
name: 'img',
|
||||
attrs: {
|
||||
src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
|
||||
ignore: 'T'
|
||||
}
|
||||
})
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理属性
|
||||
matchAttr(node) {
|
||||
var attrs = node.attrs,
|
||||
style = this.CssHandler.match(node.name, attrs, node) + (attrs.style || ''),
|
||||
styleObj = {};
|
||||
if (attrs.id) {
|
||||
if (this.compress & 1) attrs.id = void 0;
|
||||
else if (this.useAnchor) this.bubble();
|
||||
}
|
||||
if ((this.compress & 2) && attrs.class) attrs.class = void 0;
|
||||
switch (node.name) {
|
||||
case 'img':
|
||||
if (attrs['data-src']) {
|
||||
attrs.src = attrs.src || attrs['data-src'];
|
||||
attrs['data-src'] = void 0;
|
||||
}
|
||||
if (attrs.src && !attrs.ignore) {
|
||||
if (this.bubble()) attrs.i = (this.imgNum++).toString();
|
||||
else attrs.ignore = 'T';
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
case 'ad':
|
||||
// #ifdef APP-PLUS
|
||||
case 'iframe':
|
||||
case 'embed':
|
||||
// #endif
|
||||
this.bubble();
|
||||
break;
|
||||
case 'font':
|
||||
if (attrs.color) {
|
||||
styleObj['color'] = attrs.color;
|
||||
attrs.color = void 0;
|
||||
}
|
||||
if (attrs.face) {
|
||||
styleObj['font-family'] = attrs.face;
|
||||
attrs.face = void 0;
|
||||
}
|
||||
if (attrs.size) {
|
||||
var size = parseInt(attrs.size);
|
||||
if (size < 1) size = 1;
|
||||
else if (size > 7) size = 7;
|
||||
var map = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'];
|
||||
styleObj['font-size'] = map[size - 1];
|
||||
attrs.size = void 0;
|
||||
}
|
||||
break;
|
||||
case 'video':
|
||||
case 'audio':
|
||||
if (!attrs.id) attrs.id = node.name + (++this[`${node.name}Num`]);
|
||||
else this[`${node.name}Num`]++;
|
||||
if (node.name == 'video') {
|
||||
if (attrs.width) {
|
||||
style = `width:${parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px')};${style}`;
|
||||
attrs.width = void 0;
|
||||
}
|
||||
if (attrs.height) {
|
||||
style = `height:${parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px')};${style}`;
|
||||
attrs.height = void 0;
|
||||
}
|
||||
if (this.videoNum > 3) node.lazyLoad = true;
|
||||
}
|
||||
attrs.source = [];
|
||||
if (attrs.src) attrs.source.push(attrs.src);
|
||||
if (!attrs.controls && !attrs.autoplay)
|
||||
console.warn(`存在没有 controls 属性的 ${node.name} 标签,可能导致无法播放`, node);
|
||||
this.bubble();
|
||||
break;
|
||||
case 'td':
|
||||
case 'th':
|
||||
if (attrs.colspan || attrs.rowspan)
|
||||
for (var k = this.STACK.length, item; item = this.STACK[--k];)
|
||||
if (item.name == 'table') {
|
||||
item.c = void 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (attrs.align) {
|
||||
styleObj['text-align'] = attrs.align;
|
||||
attrs.align = void 0;
|
||||
}
|
||||
// 压缩 style
|
||||
var styles = style.replace(/"/g, '"').replace(/&/g, '&').split(';');
|
||||
style = '';
|
||||
for (var i = 0, len = styles.length; i < len; i++) {
|
||||
var info = styles[i].split(':');
|
||||
if (info.length < 2) continue;
|
||||
let key = info[0].trim().toLowerCase(),
|
||||
value = info.slice(1).join(':').trim();
|
||||
if (value.includes('-webkit') || value.includes('-moz') || value.includes('-ms') || value.includes('-o') || value
|
||||
.includes(
|
||||
'safe'))
|
||||
style += `;${key}:${value}`;
|
||||
else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import'))
|
||||
styleObj[key] = value;
|
||||
}
|
||||
if (node.name == 'img' && parseInt(styleObj.width || attrs.width) > screenWidth)
|
||||
styleObj.height = 'auto';
|
||||
for (var key in styleObj) {
|
||||
var value = styleObj[key];
|
||||
if (key.includes('flex') || key == 'order' || key == 'self-align') node.c = 1;
|
||||
// 填充链接
|
||||
if (value.includes('url')) {
|
||||
var j = value.indexOf('(');
|
||||
if (j++ != -1) {
|
||||
while (value[j] == '"' || value[j] == "'" || blankChar[value[j]]) j++;
|
||||
value = value.substr(0, j) + this.getUrl(value.substr(j));
|
||||
}
|
||||
}
|
||||
// 转换 rpx
|
||||
else if (value.includes('rpx'))
|
||||
value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * screenWidth / 750 + 'px');
|
||||
else if (key == 'white-space' && value.includes('pre'))
|
||||
this.pre = node.pre = true;
|
||||
style += `;${key}:${value}`;
|
||||
}
|
||||
style = style.substr(1);
|
||||
if (style) attrs.style = style;
|
||||
}
|
||||
// 节点出栈处理
|
||||
popNode(node) {
|
||||
// 空白符处理
|
||||
if (node.pre) {
|
||||
node.pre = this.pre = void 0;
|
||||
for (let i = this.STACK.length; i--;)
|
||||
if (this.STACK[i].pre)
|
||||
this.pre = true;
|
||||
}
|
||||
if (node.name == 'head' || (cfg.filter && cfg.filter(node, this) == false))
|
||||
return this.siblings().pop();
|
||||
var attrs = node.attrs;
|
||||
// 替换一些标签名
|
||||
if (node.name == 'picture') {
|
||||
node.name = 'img';
|
||||
if (!attrs.src && (node.children[0] || '').name == 'img')
|
||||
attrs.src = node.children[0].attrs.src;
|
||||
if (attrs.src && !attrs.ignore)
|
||||
attrs.i = (this.imgNum++).toString();
|
||||
return node.children = void 0;
|
||||
}
|
||||
if (cfg.blockTags[node.name]) node.name = 'div';
|
||||
else if (!cfg.trustTags[node.name]) node.name = 'span';
|
||||
// 处理列表
|
||||
if (node.c) {
|
||||
if (node.name == 'ul') {
|
||||
var floor = 1;
|
||||
for (let i = this.STACK.length; i--;)
|
||||
if (this.STACK[i].name == 'ul') floor++;
|
||||
if (floor != 1)
|
||||
for (let i = node.children.length; i--;)
|
||||
node.children[i].floor = floor;
|
||||
} else if (node.name == 'ol') {
|
||||
for (let i = 0, num = 1, child; child = node.children[i++];)
|
||||
if (child.name == 'li') {
|
||||
child.type = 'ol';
|
||||
child.num = ((num, type) => {
|
||||
if (type == 'a') return String.fromCharCode(97 + (num - 1) % 26);
|
||||
if (type == 'A') return String.fromCharCode(65 + (num - 1) % 26);
|
||||
if (type == 'i' || type == 'I') {
|
||||
num = (num - 1) % 99 + 1;
|
||||
var one = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],
|
||||
ten = ['X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'],
|
||||
res = (ten[Math.floor(num / 10) - 1] || '') + (one[num % 10 - 1] || '');
|
||||
if (type == 'i') return res.toLowerCase();
|
||||
return res;
|
||||
}
|
||||
return num;
|
||||
})(num++, attrs.type) + '.';
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理表格的边框
|
||||
if (node.name == 'table') {
|
||||
var padding = attrs.cellpadding,
|
||||
spacing = attrs.cellspacing,
|
||||
border = attrs.border;
|
||||
if (node.c) {
|
||||
this.bubble();
|
||||
if (!padding) padding = 2;
|
||||
if (!spacing) spacing = 2;
|
||||
}
|
||||
if (border) attrs.style = `border:${border}px solid gray;${attrs.style || ''}`;
|
||||
if (spacing) attrs.style = `border-spacing:${spacing}px;${attrs.style || ''}`;
|
||||
if (border || padding)
|
||||
(function f(ns) {
|
||||
for (var i = 0, n; n = ns[i]; i++) {
|
||||
if (n.name == 'th' || n.name == 'td') {
|
||||
if (border) n.attrs.style = `border:${border}px solid gray;${n.attrs.style}`;
|
||||
if (padding) n.attrs.style = `padding:${padding}px;${n.attrs.style}`;
|
||||
} else f(n.children || []);
|
||||
}
|
||||
})(node.children)
|
||||
}
|
||||
this.CssHandler.pop && this.CssHandler.pop(node);
|
||||
// 自动压缩
|
||||
if (node.name == 'div' && !Object.keys(attrs).length) {
|
||||
var siblings = this.siblings();
|
||||
if (node.children.length == 1 && node.children[0].name == 'div')
|
||||
siblings[siblings.length - 1] = node.children[0];
|
||||
}
|
||||
}
|
||||
// 工具函数
|
||||
bubble() {
|
||||
for (var i = this.STACK.length, item; item = this.STACK[--i];) {
|
||||
if (cfg.richOnlyTags[item.name]) {
|
||||
if (item.name == 'table' && !Object.hasOwnProperty.call(item, 'c')) item.c = 1;
|
||||
return false;
|
||||
}
|
||||
item.c = 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
getName = val => this.xml ? val : val.toLowerCase();
|
||||
getUrl(url) {
|
||||
if (url[0] == '/') {
|
||||
if (url[1] == '/') url = this.protocol + ':' + url;
|
||||
else if (this.domain) url = this.domain + url;
|
||||
} else if (this.domain && url.indexOf('data:') != 0 && !url.includes('://'))
|
||||
url = this.domain + '/' + url;
|
||||
return url;
|
||||
}
|
||||
isClose = () => this.data[this.i] == '>' || (this.data[this.i] == '/' && this.data[this.i + 1] == '>');
|
||||
section = () => this.data.substring(this.start, this.i);
|
||||
siblings = () => this.STACK.length ? this.STACK[this.STACK.length - 1].children : this.DOM;
|
||||
// 状态机
|
||||
Text(c) {
|
||||
if (c == '<') {
|
||||
var next = this.data[this.i + 1],
|
||||
isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
if (isLetter(next)) {
|
||||
this.setText();
|
||||
this.start = this.i + 1;
|
||||
this.state = this.TagName;
|
||||
} else if (next == '/') {
|
||||
this.setText();
|
||||
if (isLetter(this.data[++this.i + 1])) {
|
||||
this.start = this.i + 1;
|
||||
this.state = this.EndTag;
|
||||
} else
|
||||
this.Comment();
|
||||
} else if (next == '!') {
|
||||
this.setText();
|
||||
this.Comment();
|
||||
}
|
||||
}
|
||||
}
|
||||
Comment() {
|
||||
var key;
|
||||
if (this.data.substring(this.i + 2, this.i + 4) == '--') key = '-->';
|
||||
else if (this.data.substring(this.i + 2, this.i + 9) == '[CDATA[') key = ']]>';
|
||||
else key = '>';
|
||||
if ((this.i = this.data.indexOf(key, this.i + 2)) == -1) this.i = this.data.length;
|
||||
else this.i += key.length - 1;
|
||||
this.start = this.i + 1;
|
||||
this.state = this.Text;
|
||||
}
|
||||
TagName(c) {
|
||||
if (blankChar[c]) {
|
||||
this.tagName = this.section();
|
||||
while (blankChar[this.data[this.i]]) this.i++;
|
||||
if (this.isClose()) this.setNode();
|
||||
else {
|
||||
this.start = this.i;
|
||||
this.state = this.AttrName;
|
||||
}
|
||||
} else if (this.isClose()) {
|
||||
this.tagName = this.section();
|
||||
this.setNode();
|
||||
}
|
||||
}
|
||||
AttrName(c) {
|
||||
var blank = blankChar[c];
|
||||
if (blank) {
|
||||
this.attrName = this.section();
|
||||
c = this.data[this.i];
|
||||
}
|
||||
if (c == '=') {
|
||||
if (!blank) this.attrName = this.section();
|
||||
while (blankChar[this.data[++this.i]]);
|
||||
this.start = this.i--;
|
||||
this.state = this.AttrValue;
|
||||
} else if (blank) this.setAttr();
|
||||
else if (this.isClose()) {
|
||||
this.attrName = this.section();
|
||||
this.setAttr();
|
||||
}
|
||||
}
|
||||
AttrValue(c) {
|
||||
if (c == '"' || c == "'") {
|
||||
this.start++;
|
||||
if ((this.i = this.data.indexOf(c, this.i + 1)) == -1) return this.i = this.data.length;
|
||||
this.attrVal = this.section();
|
||||
this.i++;
|
||||
} else {
|
||||
for (; !blankChar[this.data[this.i]] && !this.isClose(); this.i++);
|
||||
this.attrVal = this.section();
|
||||
}
|
||||
this.setAttr();
|
||||
}
|
||||
EndTag(c) {
|
||||
if (blankChar[c] || c == '>' || c == '/') {
|
||||
var name = this.getName(this.section());
|
||||
for (var i = this.STACK.length; i--;)
|
||||
if (this.STACK[i].name == name) break;
|
||||
if (i != -1) {
|
||||
var node;
|
||||
while ((node = this.STACK.pop()).name != name);
|
||||
this.popNode(node);
|
||||
} else if (name == 'p' || name == 'br')
|
||||
this.siblings().push({
|
||||
name,
|
||||
attrs: {}
|
||||
});
|
||||
this.i = this.data.indexOf('>', this.i);
|
||||
this.start = this.i + 1;
|
||||
if (this.i == -1) this.i = this.data.length;
|
||||
else this.state = this.Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = MpHtmlParser;
|
||||
80
components/jyf-parser/libs/config.js
Normal file
80
components/jyf-parser/libs/config.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 配置文件 */
|
||||
// #ifdef MP-WEIXIN
|
||||
const canIUse = wx.canIUse('editor'); // 高基础库标识,用于兼容
|
||||
// #endif
|
||||
module.exports = {
|
||||
// 过滤器函数
|
||||
filter: null,
|
||||
// 代码高亮函数
|
||||
highlight: null,
|
||||
// 文本处理函数
|
||||
onText: null,
|
||||
blankChar: makeMap(' ,\xA0,\t,\r,\n,\f'),
|
||||
// 块级标签,将被转为 div
|
||||
blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,section' + (
|
||||
// #ifdef MP-WEIXIN
|
||||
canIUse ? '' :
|
||||
// #endif
|
||||
',pre')),
|
||||
// 将被移除的标签
|
||||
ignoreTags: makeMap(
|
||||
'area,base,basefont,canvas,command,frame,input,isindex,keygen,link,map,meta,param,script,source,style,svg,textarea,title,track,use,wbr'
|
||||
// #ifdef MP-WEIXIN
|
||||
+ (canIUse ? ',rp' : '')
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
+ ',embed,iframe'
|
||||
// #endif
|
||||
),
|
||||
// 只能被 rich-text 显示的标签
|
||||
richOnlyTags: makeMap('a,colgroup,fieldset,legend,picture,table'
|
||||
// #ifdef MP-WEIXIN
|
||||
+ (canIUse ? ',bdi,bdo,caption,rt,ruby' : '')
|
||||
// #endif
|
||||
),
|
||||
// 自闭合的标签
|
||||
selfClosingTags: makeMap(
|
||||
'area,base,basefont,br,col,circle,ellipse,embed,frame,hr,img,input,isindex,keygen,line,link,meta,param,path,polygon,rect,source,track,use,wbr'
|
||||
),
|
||||
// 信任的属性
|
||||
trustAttrs: makeMap(
|
||||
'align,alt,app-id,author,autoplay,border,cellpadding,cellspacing,class,color,colspan,controls,data-src,dir,face,height,href,id,ignore,loop,media,muted,name,path,poster,rowspan,size,span,src,start,style,type,unit-id,width,xmlns'
|
||||
),
|
||||
// bool 型的属性
|
||||
boolAttrs: makeMap('autoplay,controls,ignore,loop,muted'),
|
||||
// 信任的标签
|
||||
trustTags: makeMap(
|
||||
'a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'
|
||||
// #ifdef MP-WEIXIN
|
||||
+ (canIUse ? ',bdi,bdo,caption,pre,rt,ruby' : '')
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
+ ',embed,iframe'
|
||||
// #endif
|
||||
),
|
||||
// 默认的标签样式
|
||||
userAgentStyles: {
|
||||
address: 'font-style:italic',
|
||||
big: 'display:inline;font-size:1.2em',
|
||||
blockquote: 'background-color:#f6f6f6;border-left:3px solid #dbdbdb;color:#6c6c6c;padding:5px 0 5px 10px',
|
||||
caption: 'display:table-caption;text-align:center',
|
||||
center: 'text-align:center',
|
||||
cite: 'font-style:italic',
|
||||
dd: 'margin-left:40px',
|
||||
img: 'max-width:100%',
|
||||
mark: 'background-color:yellow',
|
||||
picture: 'max-width:100%',
|
||||
pre: 'font-family:monospace;white-space:pre;overflow:scroll',
|
||||
s: 'text-decoration:line-through',
|
||||
small: 'display:inline;font-size:0.8em',
|
||||
u: 'text-decoration:underline'
|
||||
}
|
||||
}
|
||||
|
||||
function makeMap(maprichee55text9oppplugin) {
|
||||
var map = {},
|
||||
list = maprichee55text9oppplugin.split(',');
|
||||
for (var i = list.length; i--;)
|
||||
map[list[i]] = true;
|
||||
return map;
|
||||
}
|
||||
35
components/jyf-parser/libs/handler.sjs
Normal file
35
components/jyf-parser/libs/handler.sjs
Normal file
@@ -0,0 +1,35 @@
|
||||
var inlineTags = {
|
||||
abbr: 1,
|
||||
b: 1,
|
||||
big: 1,
|
||||
code: 1,
|
||||
del: 1,
|
||||
em: 1,
|
||||
i: 1,
|
||||
ins: 1,
|
||||
label: 1,
|
||||
q: 1,
|
||||
small: 1,
|
||||
span: 1,
|
||||
strong: 1
|
||||
}
|
||||
export default {
|
||||
// 从顶层标签的样式中取出一些给 rich-text
|
||||
getStyle: function(style) {
|
||||
if (style) {
|
||||
var i, j, res = '';
|
||||
if ((i = style.indexOf('display')) != -1)
|
||||
res = style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
|
||||
if ((i = style.indexOf('float')) != -1)
|
||||
res += ';' + style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
|
||||
return res;
|
||||
}
|
||||
},
|
||||
getNode: function(item) {
|
||||
return [item];
|
||||
},
|
||||
// 是否通过 rich-text 显示
|
||||
useRichText: function(item) {
|
||||
return !item.c && !inlineTags[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1;
|
||||
}
|
||||
}
|
||||
44
components/jyf-parser/libs/handler.wxs
Normal file
44
components/jyf-parser/libs/handler.wxs
Normal file
@@ -0,0 +1,44 @@
|
||||
var inlineTags = {
|
||||
abbr: 1,
|
||||
b: 1,
|
||||
big: 1,
|
||||
code: 1,
|
||||
del: 1,
|
||||
em: 1,
|
||||
i: 1,
|
||||
ins: 1,
|
||||
label: 1,
|
||||
q: 1,
|
||||
small: 1,
|
||||
span: 1,
|
||||
strong: 1
|
||||
}
|
||||
module.exports = {
|
||||
// 从顶层标签的样式中取出一些给 rich-text
|
||||
getStyle: function(style) {
|
||||
if (style) {
|
||||
var i, j, res = '';
|
||||
if ((i = style.indexOf('display')) != -1)
|
||||
res = style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
|
||||
if ((i = style.indexOf('float')) != -1)
|
||||
res += ';' + style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
|
||||
return res;
|
||||
}
|
||||
},
|
||||
// 处理懒加载
|
||||
getNode: function(item, imgLoad) {
|
||||
if (!imgLoad && item.attrs.i != '0') {
|
||||
var img = {
|
||||
name: 'img',
|
||||
attrs: JSON.parse(JSON.stringify(item.attrs))
|
||||
}
|
||||
delete img.attrs.src;
|
||||
img.attrs.style += ';width:20px;height:20px';
|
||||
return [img];
|
||||
} else return [item];
|
||||
},
|
||||
// 是否通过 rich-text 显示
|
||||
useRichText: function(item) {
|
||||
return !item.c && !inlineTags[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1;
|
||||
}
|
||||
}
|
||||
476
components/jyf-parser/libs/trees.vue
Normal file
476
components/jyf-parser/libs/trees.vue
Normal file
@@ -0,0 +1,476 @@
|
||||
<!--
|
||||
trees 递归显示组件
|
||||
github:https://github.com/jin-yufeng/Parser
|
||||
docs:https://jin-yufeng.github.io/Parser
|
||||
插件市场:https://ext.dcloud.net.cn/plugin?id=805
|
||||
author:JinYufeng
|
||||
update:2020/04/13
|
||||
-->
|
||||
<template>
|
||||
<view class="interlayer">
|
||||
<block v-for="(n, index) in nodes" v-bind:key="index">
|
||||
<!--图片-->
|
||||
<!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
|
||||
<rich-text v-if="n.name=='img'" :id="n.attrs.id" class="_img" :style="''+handler.getStyle(n.attrs.style)" :nodes="handler.getNode(n,!lazyLoad||imgLoad)"
|
||||
:data-attrs="n.attrs" @tap="imgtap" @longpress="imglongtap" />
|
||||
<!--#endif-->
|
||||
<!--#ifdef MP-BAIDU || MP-TOUTIAO-->
|
||||
<rich-text v-if="n.name=='img'" :id="n.attrs.id" class="_img" :style="n.attrs.contain" :nodes='[n]' :data-attrs="n.attrs"
|
||||
@tap="imgtap" @longpress="imglongtap" />
|
||||
<!--#endif-->
|
||||
<!--文本-->
|
||||
<!--#ifdef MP-WEIXIN || MP-QQ || APP-PLUS-->
|
||||
<rich-text v-else-if="n.decode" class="_entity" :nodes="[n]"></rich-text>
|
||||
<!--#endif-->
|
||||
<text v-else-if="n.type=='text'" decode>{{n.text}}</text>
|
||||
<text v-else-if="n.name=='br'">\n</text>
|
||||
<!--视频-->
|
||||
<view v-else-if="n.name=='video'">
|
||||
<view v-if="(!loadVideo||n.lazyLoad)&&!(controls[n.attrs.id]&&controls[n.attrs.id].play)" :id="n.attrs.id" :class="'_video '+(n.attrs.class||'')"
|
||||
:style="n.attrs.style" @tap="_loadVideo" />
|
||||
<video v-else :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :autoplay="n.attrs.autoplay||(controls[n.attrs.id]&&controls[n.attrs.id].play)"
|
||||
:controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted" :poster="n.attrs.poster" :src="n.attrs.source[(controls[n.attrs.id]&&controls[n.attrs.id].index)||0]"
|
||||
:unit-id="n.attrs['unit-id']" :data-id="n.attrs.id" data-from="video" data-source="source" @error="error" @play="play" />
|
||||
</view>
|
||||
<!--音频-->
|
||||
<audio v-else-if="n.name=='audio'" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author" :autoplay="n.attrs.autoplay"
|
||||
:controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster" :src="n.attrs.source[(controls[n.attrs.id]&&controls[n.attrs.id].index)||0]"
|
||||
:data-id="n.attrs.id" data-from="audio" data-source="source" @error="error" @play="play" />
|
||||
<!--链接-->
|
||||
<view v-else-if="n.name=='a'" :class="'_a '+(n.attrs.class||'')" hover-class="_hover" :style="n.attrs.style"
|
||||
:data-attrs="n.attrs" @tap="linkpress">
|
||||
<trees class="_span" :nodes="n.children" />
|
||||
</view>
|
||||
<!--广告(按需打开注释)-->
|
||||
<!--#ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO-->
|
||||
<!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :unit-id="n.attrs['unit-id']"
|
||||
data-from="ad" @error="error" />-->
|
||||
<!--#endif-->
|
||||
<!--#ifdef MP-BAIDU-->
|
||||
<!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :appid="n.attrs.appid"
|
||||
:apid="n.attrs.apid" :type="n.attrs.type" data-from="ad" @error="error" />-->
|
||||
<!--#endif-->
|
||||
<!--#ifdef APP-PLUS-->
|
||||
<!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :adpid="n.attrs.adpid"
|
||||
data-from="ad" @error="error" />-->
|
||||
<!--#endif-->
|
||||
<!--列表-->
|
||||
<view v-else-if="n.name=='li'" :id="n.attrs.id" :class="n.attrs.class" :style="(n.attrs.style||'')+';display:flex'">
|
||||
<view v-if="n.type=='ol'" class="_ol-bef">{{n.num}}</view>
|
||||
<view v-else class="_ul-bef">
|
||||
<view v-if="n.floor%3==0" class="_ul-p1">█</view>
|
||||
<view v-else-if="n.floor%3==2" class="_ul-p2" />
|
||||
<view v-else class="_ul-p1" style="border-radius:50%">█</view>
|
||||
</view>
|
||||
<!--#ifdef MP-ALIPAY-->
|
||||
<view class="_li">
|
||||
<trees :nodes="n.children" />
|
||||
</view>
|
||||
<!--#endif-->
|
||||
<!--#ifndef MP-ALIPAY-->
|
||||
<trees class="_li" :nodes="n.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo" />
|
||||
<!--#endif-->
|
||||
</view>
|
||||
<!--表格-->
|
||||
<view v-else-if="n.name=='table'&&n.c" :id="n.attrs.id" :class="n.attrs.class" :style="(n.attrs.style||'')+';display:table'">
|
||||
<view v-for="(tbody, i) in n.children" v-bind:key="i" :class="tbody.attrs.class" :style="(tbody.attrs.style||'')+(tbody.name[0]=='t'?';display:table-'+(tbody.name=='tr'?'row':'row-group'):'')">
|
||||
<view v-for="(tr, j) in tbody.children" v-bind:key="j" :class="tr.attrs.class" :style="(tr.attrs.style||'')+(tr.name[0]=='t'?';display:table-'+(tr.name=='tr'?'row':'cell'):'')">
|
||||
<trees v-if="tr.name=='td'" :nodes="tr.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo" />
|
||||
<block v-else>
|
||||
<!--#ifdef MP-ALIPAY-->
|
||||
<view v-for="(td, k) in tr.children" v-bind:key="k" :class="td.attrs.class" :style="(td.attrs.style||'')+(td.name[0]=='t'?';display:table-'+(td.name=='tr'?'row':'cell'):'')">
|
||||
<trees :nodes="td.children" />
|
||||
</view>
|
||||
<!--#endif-->
|
||||
<!--#ifndef MP-ALIPAY-->
|
||||
<trees v-for="(td, k) in tr.children" v-bind:key="k" :class="td.attrs.class" :style="(td.attrs.style||'')+(td.name[0]=='t'?';display:table-'+(td.name=='tr'?'row':'cell'):'')"
|
||||
:nodes="td.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo" />
|
||||
<!--#endif-->
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!--#ifdef APP-PLUS-->
|
||||
<iframe v-else-if="n.name=='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder"
|
||||
:width="n.attrs.width" :height="n.attrs.height" :src="n.attrs.src" />
|
||||
<embed v-else-if="n.name=='embed'" :style="n.attrs.style" :width="n.attrs.width" :height="n.attrs.height" :src="n.attrs.src" />
|
||||
<!--#endif-->
|
||||
<!--富文本-->
|
||||
<!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
|
||||
<rich-text v-else-if="handler.useRichText(n)" :id="n.attrs.id" :class="'_p __'+n.name" :nodes="[n]" />
|
||||
<!--#endif-->
|
||||
<!--#ifdef MP-BAIDU || MP-TOUTIAO-->
|
||||
<rich-text v-else-if="!(n.c||n.continue)" :id="n.attrs.id" :class="_p" :style="n.attrs.contain" :nodes="[n]" />
|
||||
<!--#endif-->
|
||||
<!--#ifdef MP-ALIPAY-->
|
||||
<view v-else :id="n.attrs.id" :class="'_'+n.name+' '+(n.attrs.class||'')" :style="n.attrs.style">
|
||||
<trees :nodes="n.children" />
|
||||
</view>
|
||||
<!--#endif-->
|
||||
<!--#ifndef MP-ALIPAY-->
|
||||
<trees v-else :class="(n.attrs.id||'')+' _'+n.name+' '+(n.attrs.class||'')" :style="n.attrs.style" :nodes="n.children"
|
||||
:lazyLoad="lazyLoad" :loadVideo="loadVideo" />
|
||||
<!--#endif-->
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
<script module="handler" lang="wxs" src="./handler.wxs"></script>
|
||||
<script module="handler" lang="sjs" src="./handler.sjs"></script>
|
||||
<script>
|
||||
global.Parser = {};
|
||||
import trees from './trees'
|
||||
export default {
|
||||
components: {
|
||||
trees
|
||||
},
|
||||
name: 'trees',
|
||||
data() {
|
||||
return {
|
||||
controls: {},
|
||||
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
|
||||
imgLoad: false,
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
loadVideo: true
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
props: {
|
||||
nodes: Array,
|
||||
// #ifdef MP-WEIXIN || MP-QQ || H5 || APP-PLUS
|
||||
lazyLoad: Boolean,
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
loadVideo: Boolean
|
||||
// #endif
|
||||
},
|
||||
mounted() {
|
||||
// 获取顶层组件
|
||||
this.top = this.$parent;
|
||||
while (this.top.$options.name != 'parser') {
|
||||
if (this.top.top) {
|
||||
this.top = this.top.top;
|
||||
break;
|
||||
}
|
||||
this.top = this.top.$parent;
|
||||
}
|
||||
},
|
||||
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
|
||||
beforeDestroy() {
|
||||
if (this.observer)
|
||||
this.observer.disconnect();
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
// #ifndef MP-ALIPAY
|
||||
play(e) {
|
||||
if (this.top.videoContexts.length > 1 && this.top.autopause)
|
||||
for (var i = this.top.videoContexts.length; i--;)
|
||||
if (this.top.videoContexts[i].id != e.currentTarget.dataset.id)
|
||||
this.top.videoContexts[i].pause();
|
||||
},
|
||||
// #endif
|
||||
imgtap(e) {
|
||||
var attrs = e.currentTarget.dataset.attrs;
|
||||
if (!attrs.ignore) {
|
||||
var preview = true, data = {
|
||||
id: e.target.id,
|
||||
src: attrs.src,
|
||||
ignore: () => preview = false
|
||||
};
|
||||
global.Parser.onImgtap && global.Parser.onImgtap(data);
|
||||
this.top.$emit('imgtap', data);
|
||||
if (preview) {
|
||||
var urls = this.top.imgList,
|
||||
current = urls[attrs.i] ? parseInt(attrs.i) : (urls = [attrs.src], 0);
|
||||
uni.previewImage({
|
||||
current,
|
||||
urls
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
imglongtap(e) {
|
||||
var attrs = e.item.dataset.attrs;
|
||||
if (!attrs.ignore)
|
||||
this.top.$emit('imglongtap', {
|
||||
id: e.target.id,
|
||||
src: attrs.src
|
||||
})
|
||||
},
|
||||
linkpress(e) {
|
||||
var jump = true,
|
||||
attrs = e.currentTarget.dataset.attrs;
|
||||
attrs.ignore = () => jump = false;
|
||||
global.Parser.onLinkpress && global.Parser.onLinkpress(attrs);
|
||||
this.top.$emit('linkpress', attrs);
|
||||
if (jump) {
|
||||
// #ifdef MP
|
||||
if (attrs['app-id']) {
|
||||
return uni.navigateToMiniProgram({
|
||||
appId: attrs['app-id'],
|
||||
path: attrs.path
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
if (attrs.href) {
|
||||
if (attrs.href[0] == '#') {
|
||||
if (this.top.useAnchor)
|
||||
this.top.navigateTo({
|
||||
id: attrs.href.substring(1)
|
||||
})
|
||||
} else if (attrs.href.indexOf('http') == 0 || attrs.href.indexOf('//') == 0) {
|
||||
// #ifdef APP-PLUS
|
||||
plus.runtime.openWeb(attrs.href);
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
uni.setClipboardData({
|
||||
data: attrs.href,
|
||||
success: () =>
|
||||
uni.showToast({
|
||||
title: '链接已复制'
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
} else
|
||||
uni.navigateTo({
|
||||
url: attrs.href
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
error(e) {
|
||||
var context, target = e.currentTarget,
|
||||
source = target.dataset.from;
|
||||
if (source == 'video' || source == 'audio') {
|
||||
// 加载其他 source
|
||||
var index = this.controls[target.id] ? this.controls[target.id].index + 1 : 1;
|
||||
if (index < target.dataset.source.length)
|
||||
this.$set(this.controls, target.id + '.index', index);
|
||||
if (source == 'video') context = uni.createVideoContext(target.id, this);
|
||||
}
|
||||
this.top && this.top.$emit('error', {
|
||||
source,
|
||||
target,
|
||||
errMsg: e.detail.errMsg,
|
||||
errCode: e.detail.errCode,
|
||||
context
|
||||
});
|
||||
},
|
||||
_loadVideo(e) {
|
||||
this.$set(this.controls, e.currentTarget.id, {
|
||||
play: true,
|
||||
index: 0
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* 在这里引入自定义样式 */
|
||||
|
||||
/* 链接和图片效果 */
|
||||
._a {
|
||||
display: inline;
|
||||
color: #366092;
|
||||
word-break: break-all;
|
||||
padding: 1.5px 0 1.5px 0;
|
||||
}
|
||||
|
||||
._hover {
|
||||
opacity: 0.7;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
._img {
|
||||
display: inline-block;
|
||||
text-indent: 0;
|
||||
}
|
||||
|
||||
/* #ifdef MP-WEIXIN */
|
||||
:host {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef MP */
|
||||
.interlayer {
|
||||
align-content: inherit;
|
||||
align-items: inherit;
|
||||
display: inherit;
|
||||
flex-direction: inherit;
|
||||
flex-wrap: inherit;
|
||||
justify-content: inherit;
|
||||
width: 100%;
|
||||
white-space: inherit;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
._b,
|
||||
._strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
._blockquote,
|
||||
._div,
|
||||
._p,
|
||||
._ol,
|
||||
._ul,
|
||||
._li {
|
||||
display: block;
|
||||
}
|
||||
|
||||
._code {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
._del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
._em,
|
||||
._i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
._h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
._h2 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
._h3 {
|
||||
font-size: 1.17em;
|
||||
}
|
||||
|
||||
._h5 {
|
||||
font-size: 0.83em;
|
||||
}
|
||||
|
||||
._h6 {
|
||||
font-size: 0.67em;
|
||||
}
|
||||
|
||||
._h1,
|
||||
._h2,
|
||||
._h3,
|
||||
._h4,
|
||||
._h5,
|
||||
._h6 {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
._ins {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
._li {
|
||||
flex: 1;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
._ol-bef {
|
||||
margin-right: 5px;
|
||||
text-align: right;
|
||||
width: 36px;
|
||||
}
|
||||
|
||||
._ul-bef {
|
||||
line-height: normal;
|
||||
margin: 0 12px 0 23px;
|
||||
}
|
||||
|
||||
._ol-bef,
|
||||
._ul_bef {
|
||||
flex: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
._ul-p1 {
|
||||
display: inline-block;
|
||||
height: 0.3em;
|
||||
line-height: 0.3em;
|
||||
overflow: hidden;
|
||||
width: 0.3em;
|
||||
}
|
||||
|
||||
._ul-p2 {
|
||||
border: 0.05em solid black;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
height: 0.23em;
|
||||
width: 0.23em;
|
||||
}
|
||||
|
||||
._q::before {
|
||||
content: '"';
|
||||
}
|
||||
|
||||
._q::after {
|
||||
content: '"';
|
||||
}
|
||||
|
||||
._sub {
|
||||
font-size: smaller;
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
._sup {
|
||||
font-size: smaller;
|
||||
vertical-align: super;
|
||||
}
|
||||
|
||||
/* #ifndef MP-WEIXIN */
|
||||
._abbr,
|
||||
._b,
|
||||
._code,
|
||||
._del,
|
||||
._em,
|
||||
._i,
|
||||
._ins,
|
||||
._label,
|
||||
._q,
|
||||
._span,
|
||||
._strong,
|
||||
._sub,
|
||||
._sup {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY */
|
||||
.__bdo,
|
||||
.__bdi,
|
||||
.__ruby,
|
||||
.__rt,
|
||||
._entity {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
._video {
|
||||
background-color: black;
|
||||
display: inline-block;
|
||||
height: 225px;
|
||||
position: relative;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
._video::after {
|
||||
border-color: transparent transparent transparent white;
|
||||
border-style: solid;
|
||||
border-width: 15px 0 15px 30px;
|
||||
content: '';
|
||||
left: 50%;
|
||||
margin: -15px 0 0 -15px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
}
|
||||
</style>
|
||||
263
components/pageFooter/index.vue
Normal file
263
components/pageFooter/index.vue
Normal file
@@ -0,0 +1,263 @@
|
||||
<template>
|
||||
<!-- 底部导航 -->
|
||||
<view v-if="showTabBar">
|
||||
<view class="fixed-lb w-full pb-safe z-3000" :style="[bgColor]">
|
||||
<view class="page-footer-wrapper">
|
||||
<view class="page-footer" :class="{
|
||||
'page-footer2': newData.navStyleConfig.tabVal == 1,
|
||||
'page-footer3': newData.navStyleConfig.tabVal == 2,
|
||||
}" id="target" :style="[componentStyle]">
|
||||
<view class="foot-item flex-1 flex-col flex-center h-96 relative" v-for="(item,index) in newData.menuList" :key="index" @click="goRouter(item)">
|
||||
<template v-if="item.link.split('?')[0] == activeRouter">
|
||||
<image v-if="newData.navStyleConfig.tabVal != 1" :src="item.imgList[0]"></image>
|
||||
<view v-if="newData.navStyleConfig.tabVal != 2" class="txt active" :style="[txtActiveColor]">{{item.name}}</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<image v-if="newData.navStyleConfig.tabVal != 1" :src="item.imgList[1]"></image>
|
||||
<view v-if="newData.navStyleConfig.tabVal != 2" class="txt" :style="[txtColor]">{{item.name}}</view>
|
||||
</template>
|
||||
<uni-badge v-if="item.link === '/pages/order_addcart/order_addcart' && cartNum>0" class="uni-badge-left-margin" :text="cartNum" absolute="rightTop">
|
||||
</uni-badge>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view :style="{ height: `${footerHeight}px` }"></view>
|
||||
<view class="pb-safe"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState,mapGetters} from "vuex"
|
||||
import {getCartCounts} from '@/api/order.js';
|
||||
export default {
|
||||
name: 'pageFooter',
|
||||
props: {
|
||||
isTabBar:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
configData:{
|
||||
type: Object,
|
||||
default: ()=>{}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['isLogin', 'cartNum','tabBarData']),
|
||||
txtActiveColor() {
|
||||
let styleObject = {};
|
||||
if (this.newData.toneConfig && this.newData.toneConfig.tabVal) {
|
||||
styleObject['color'] = this.newData.activeTxtColor.color[0].item;
|
||||
}
|
||||
return styleObject;
|
||||
},
|
||||
txtColor() {
|
||||
let styleObject = {};
|
||||
if (this.newData.toneConfig && this.newData.toneConfig.tabVal) {
|
||||
styleObject['color'] = this.newData.txtColor.color[0].item;
|
||||
}
|
||||
return styleObject;
|
||||
},
|
||||
bgColor() {
|
||||
let styleObject = {};
|
||||
if (!this.newData.name) {
|
||||
return styleObject;
|
||||
}
|
||||
if (!this.newData.navConfig.tabVal) {
|
||||
styleObject['background'] = this.newData.bgColor.color[0].item;
|
||||
}
|
||||
return styleObject;
|
||||
},
|
||||
componentStyle() {
|
||||
let styleObject = {};
|
||||
let borderRadius = ``;
|
||||
if (!this.newData.name) {
|
||||
return styleObject;
|
||||
}
|
||||
if (this.newData.navConfig.tabVal) {
|
||||
borderRadius = `${this.newData.fillet.val * 2}rpx`;
|
||||
if (this.newData.fillet.type) {
|
||||
borderRadius =
|
||||
`${this.newData.fillet.valList[0].val * 2}rpx ${this.newData.fillet.valList[1].val * 2}rpx ${this.newData.fillet.valList[3].val * 2}rpx ${this.newData.fillet.valList[2].val * 2}rpx`;
|
||||
}
|
||||
styleObject['right'] = `${this.newData.prConfig.val * 2}rpx`;
|
||||
styleObject['bottom'] = `${this.newData.mbConfig.val * 2}rpx`;
|
||||
styleObject['left'] = `${this.newData.prConfig.val * 2}rpx`;
|
||||
styleObject['padding-top'] = `${this.newData.topConfig.val * 2}rpx`;
|
||||
styleObject['padding-bottom'] = `${this.newData.bottomConfig.val * 2}rpx`;
|
||||
styleObject['border-radius'] = borderRadius;
|
||||
styleObject['background'] = this.newData.bgColor2.color[0].item;
|
||||
} else {
|
||||
styleObject['padding-top'] = `${this.newData.topConfig.val * 2}rpx`;
|
||||
styleObject['padding-bottom'] = `${this.newData.bottomConfig.val * 2}rpx`;
|
||||
styleObject['background'] = this.newData.bgColor.color[0].item;
|
||||
}
|
||||
return styleObject;
|
||||
},
|
||||
// validConfigData() {
|
||||
// return this.configData && Object.keys(this.configData).length > 0;
|
||||
// },
|
||||
},
|
||||
watch: {
|
||||
configData(newVal){
|
||||
console.log(newVal,'oo');
|
||||
if(!this.isTabBar && newVal){
|
||||
let configData = newVal;
|
||||
this.newData = configData;
|
||||
this.showTabBar = configData.effectConfig.tabVal;
|
||||
}
|
||||
},
|
||||
tabBarData(newVal){
|
||||
if(newVal){
|
||||
let configData = newVal;
|
||||
if(this.isTabBar){
|
||||
this.newData = configData;
|
||||
}
|
||||
this.showTabBar = configData.effectConfig.tabVal;
|
||||
if (configData.effectConfig.tabVal) {
|
||||
uni.hideTabBar()
|
||||
} else {
|
||||
uni.showTabBar()
|
||||
}
|
||||
this.$emit('newDataStatus', configData.effectConfig.tabVal)
|
||||
}
|
||||
}
|
||||
// 'newData.menuList'(newValue, oldValue) {
|
||||
// this.$nextTick(() => {
|
||||
// const query = uni.createSelectorQuery().in(this);
|
||||
// query.select("#target").boundingClientRect(({
|
||||
// height
|
||||
// }) => {
|
||||
// this.footerHeight = height;
|
||||
// }).exec();
|
||||
// });
|
||||
// }
|
||||
},
|
||||
created() {
|
||||
let routes = getCurrentPages(); //获取当前打开过的页面路由数组
|
||||
let curRoute = routes[routes.length - 1].route //获取当前页面路由
|
||||
this.activeRouter = '/' + curRoute
|
||||
},
|
||||
mounted() {
|
||||
this.navigationInfo();
|
||||
if (this.isLogin) {
|
||||
this.getCartNum()
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
newData: {},
|
||||
activeRouter: '',
|
||||
showTabBar: false,
|
||||
footerHeight: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
navigationInfo() {
|
||||
//判断渲染来源是一级菜单还是微页面
|
||||
if(this.isTabBar && this.tabBarData.effectConfig){
|
||||
let configData = this.tabBarData;
|
||||
this.newData = configData;
|
||||
this.showTabBar = configData.effectConfig.tabVal;
|
||||
if (configData.effectConfig.tabVal) {
|
||||
uni.hideTabBar()
|
||||
} else {
|
||||
uni.showTabBar()
|
||||
}
|
||||
this.$emit('newDataStatus', configData.effectConfig.tabVal)
|
||||
}
|
||||
|
||||
},
|
||||
goRouter(item) {
|
||||
var pages = getCurrentPages();
|
||||
var page = (pages[pages.length - 1]).$page.fullPath;
|
||||
if (item.link == page) return
|
||||
if (item.link == '/pages/short_video/appSwiper/index' || item.link == '/pages/short_video/nvueSwiper/index') {
|
||||
//#ifdef APP
|
||||
item.link = '/pages/short_video/appSwiper/index'
|
||||
//#endif
|
||||
//#ifndef APP
|
||||
item.link = '/pages/short_video/nvueSwiper/index'
|
||||
//#endif
|
||||
}
|
||||
uni.switchTab({
|
||||
url: item.link,
|
||||
fail(err) {
|
||||
uni.redirectTo({
|
||||
url: item.link
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
getCartNum: function() {
|
||||
getCartCounts().then(res => {
|
||||
this.$store.commit('indexData/setCartNum', res.data.count + '')
|
||||
}).catch(err=>{
|
||||
console.log(err.msg);
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-footer-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
.z-3000{
|
||||
z-index: 3000;
|
||||
}
|
||||
.page-footer {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
|
||||
.foot-item image {
|
||||
display: block;
|
||||
height: 40rpx;
|
||||
width: 40rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.foot-item .txt {
|
||||
margin-top: 4rpx;
|
||||
font-size: 20rpx;
|
||||
line-height: 28rpx;
|
||||
color: #333333;
|
||||
|
||||
&.active {
|
||||
color: var(--view-theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-footer2 .foot-item .txt {
|
||||
margin-top: 0;
|
||||
font-size: 32rpx;
|
||||
line-height: 44rpx;
|
||||
color: #333333;
|
||||
|
||||
&.active {
|
||||
color: var(--view-theme);
|
||||
}
|
||||
}
|
||||
|
||||
.page-footer2.float .foot-item::before,
|
||||
.page-footer3.float .foot-item::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
width: 2rpx;
|
||||
height: 32rpx;
|
||||
background: #CCCCCC;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.page-footer2.float .foot-item:first-child::before,
|
||||
.page-footer3.float .foot-item:first-child::before {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
199
components/privacyAgreementPopup/index.vue
Normal file
199
components/privacyAgreementPopup/index.vue
Normal file
@@ -0,0 +1,199 @@
|
||||
<template>
|
||||
<view :style="colorStyle">
|
||||
<view class="mask" @touchmove.prevent :hidden="isShow === false"></view>
|
||||
<view class="product-window" :class="{'on':isShow}">
|
||||
<view class="mp-data">
|
||||
<text class="mp-name">服务与隐私协议</text>
|
||||
</view>
|
||||
<view class="trip-msg">
|
||||
<view class="trip">
|
||||
{{`请仔细阅读以下内容,并作出适当的选择:`}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="trip-title">
|
||||
隐私政策概要
|
||||
</view>
|
||||
<view class="trip-msg">
|
||||
<view class="trip">
|
||||
当您点击同意并继续使用产品服务时,即表示您已理解并同意该条款内容,该条款将对您产生法律约束力。如您拒绝,将无法继续下一步操作。
|
||||
</view>
|
||||
</view>
|
||||
<view class="main-color" @click.stop="privacy('privacy')">点击阅读{{agreementName}}</view>
|
||||
<view class="bottom">
|
||||
<button class="save open" type="default" id="agree-btn" open-type="agreePrivacyAuthorization"
|
||||
@agreeprivacyauthorization="handleAgree">同意并继续</button>
|
||||
<button class="reject" @click="rejectAgreement">取消</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import colors from "@/mixins/color";
|
||||
export default {
|
||||
mixins: [colors],
|
||||
data() {
|
||||
return {
|
||||
isShow: false,
|
||||
agreementName: '',
|
||||
configData: this.$Cache.get('BASIC_CONFIG'),
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
wx.getPrivacySetting({
|
||||
success: res => {
|
||||
if (res.needAuthorization) {
|
||||
// 需要弹出隐私协议
|
||||
this.isShow = true
|
||||
this.agreementName = res.privacyContractName
|
||||
} else {
|
||||
this.$emit('onAgree');
|
||||
// 用户已经同意过隐私协议,所以不需要再弹出隐私协议,也能调用已声明过的隐私接口
|
||||
// wx.getUserProfile()
|
||||
// wx.chooseMedia()
|
||||
// wx.getClipboardData()
|
||||
// wx.startRecord()
|
||||
}
|
||||
},
|
||||
fail: () => {},
|
||||
complete: () => {}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// 同意
|
||||
handleAgree() {
|
||||
this.isShow = false
|
||||
this.$emit('onAgree');
|
||||
},
|
||||
// 拒绝
|
||||
rejectAgreement() {
|
||||
this.isShow = false
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
this.$emit('onReject');
|
||||
},
|
||||
// 跳转协议
|
||||
privacy(type) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/users/privacy/index?type=" + type
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.pl-sty {
|
||||
color: #999999;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="scss">
|
||||
.product-window.on {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.mask {
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.product-window {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
z-index: 1000;
|
||||
border-radius: 40rpx 40rpx 0 0;
|
||||
transform: translate3d(0, 100%, 0);
|
||||
transition: all .3s cubic-bezier(.25, .5, .5, .9);
|
||||
padding: 64rpx 40rpx;
|
||||
padding-bottom: 38rpx;
|
||||
padding-bottom: calc(38rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
|
||||
padding-bottom: calc(38rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.06);
|
||||
|
||||
.icon-guanbi {
|
||||
position: absolute;
|
||||
top: 40rpx;
|
||||
right: 40rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.mp-data {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.mp-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.trip-msg {
|
||||
padding-bottom: 32rpx;
|
||||
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.trip {
|
||||
color: #333333;
|
||||
font-size: 28rpx;
|
||||
font-family: PingFang SC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.trip-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.main-color {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: var(--view-theme);
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
|
||||
.save,
|
||||
.reject {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 670rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 80rpx;
|
||||
background-color: #F5F5F5;
|
||||
color: #333;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.save {
|
||||
background-color: var(--view-theme);
|
||||
color: #fff;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
318
components/productConSwiper/index.vue
Normal file
318
components/productConSwiper/index.vue
Normal file
@@ -0,0 +1,318 @@
|
||||
<template>
|
||||
<!-- 商品详情轮播图 -->
|
||||
<view class="product-bg" :style="[swiperHeight]">
|
||||
<swiper
|
||||
:current="currents"
|
||||
:indicator-dots="indicatorDots"
|
||||
indicator-active-color="var(--view-theme)"
|
||||
:autoplay="showSku || videoline || pageHide ? false : true"
|
||||
:circular="circular"
|
||||
:interval="interval"
|
||||
:duration="duration"
|
||||
@change="change"
|
||||
v-if="isPlay"
|
||||
>
|
||||
<!-- #ifndef APP-PLUS -->
|
||||
<swiper-item v-if="videoline">
|
||||
<view class="item">
|
||||
<view v-show="!controls" class="item-box">
|
||||
<video
|
||||
id="myVideo"
|
||||
:src="videoline"
|
||||
controls
|
||||
show-center-play-btn
|
||||
show-mute-btn="true"
|
||||
auto-pause-if-navigate
|
||||
:custom-cache="false"
|
||||
:enable-progress-gesture="false"
|
||||
:poster="imgUrls[0]"
|
||||
@pause="videoPause"
|
||||
class="w-full h-full"
|
||||
></video>
|
||||
</view>
|
||||
<view class="poster" v-show="controls">
|
||||
<image class="image" :src="imgUrls[0]" @tap="getpreviewImage(0)"></image>
|
||||
</view>
|
||||
<view class="stop" v-show="controls" @tap="bindPause">
|
||||
<image class="image" src="../../static/images/stop.png"></image>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<swiper-item v-if="videoline">
|
||||
<view class="item">
|
||||
<view class="poster" v-show="controls">
|
||||
<image class="image" :src="imgUrls[0]" @tap="getpreviewImage(0)"></image>
|
||||
</view>
|
||||
<view class="stop" v-show="controls" @tap="bindPause">
|
||||
<image class="image" src="../../static/images/stop.png"></image>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
<!-- #endif -->
|
||||
<block v-for="(item, index) in imgUrls" :key="index">
|
||||
<swiper-item v-if="videoline ? index >= 1 : index >= 0">
|
||||
<image :src="item" class="slide-image" :mode="!autoHeight ? 'aspectFit' : ''"
|
||||
@tap="getpreviewImage(index)"/>
|
||||
</swiper-item>
|
||||
</block>
|
||||
</swiper>
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view v-if="!isPlay" style="width: 100%; height: 750rpx">
|
||||
<video
|
||||
id="myVideo"
|
||||
:src="videoline"
|
||||
controls
|
||||
show-center-play-btn
|
||||
show-mute-btn="true"
|
||||
autoplay="true"
|
||||
auto-pause-if-navigate
|
||||
:custom-cache="false"
|
||||
:enable-progress-gesture="false"
|
||||
:poster="imgUrls[0]"
|
||||
class="w-full h-full"
|
||||
@pause="videoPause"
|
||||
></video>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="w-full flex-center absolute left-0 bottom-86rpx z-20" v-if="showSku">
|
||||
<view class="sku-desc flex-center px-20 fs-20 text--w111-fff line1">{{sku}}</view>
|
||||
</view>
|
||||
<view class="w-full flex-center absolute left-0 bottom-34rpx z-20" v-if="imgUrls.length > 1 && showDot && controls">
|
||||
<block v-for="(_, index) in imgUrls" :key="index">
|
||||
<view class="dot_item h-4 rd-2rpx" :style="{ 'background-color': currents == index ? '#fff' : 'rgba(255,255,255,0.4)', width: dotWidth + 'rpx' }"></view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="w-full flex-center abs-lb h-100 white-jianbian" v-if="controls"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
currents: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
imgUrls: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
videoline: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
showDot: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
autoHeight: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
sku:{
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
showSku:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
pageHide:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
indicatorDots: false,
|
||||
circular: true,
|
||||
interval: 3000,
|
||||
duration: 500,
|
||||
// currents: 0,
|
||||
controls: true,
|
||||
isPlay: true,
|
||||
videoContext: '',
|
||||
imgHeight:375
|
||||
};
|
||||
},
|
||||
watch:{
|
||||
currents(val){
|
||||
if(val != 0){
|
||||
this.controls = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.videoline) {
|
||||
this.imgUrls.shift();
|
||||
}
|
||||
// #ifndef APP-PLUS
|
||||
this.videoContext = uni.createVideoContext('myVideo', this);
|
||||
// #endif
|
||||
},
|
||||
computed: {
|
||||
dotWidth() {
|
||||
let windowWidth = uni.getWindowInfo().windowWidth;
|
||||
return (windowWidth * 2 - (40 + (this.imgUrls.length - 1) * 12)) / this.imgUrls.length;
|
||||
},
|
||||
swiperHeight() {
|
||||
let windowWidth = uni.getWindowInfo().windowWidth;
|
||||
let that = this;
|
||||
if(this.autoHeight){
|
||||
if(this.videoline){
|
||||
return {
|
||||
height: '750rpx'
|
||||
};
|
||||
}else{
|
||||
uni.getImageInfo({
|
||||
src: this.imgUrls[0],
|
||||
success: (image) => {
|
||||
that.imgHeight = image.height * windowWidth / image.width;
|
||||
}
|
||||
});
|
||||
return {
|
||||
height: `${this.imgHeight}px`
|
||||
};
|
||||
}
|
||||
|
||||
}else{
|
||||
return {
|
||||
height: '750rpx'
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getpreviewImage(index) {
|
||||
if(this.showSku){
|
||||
this.$emit('previewImageOpen')
|
||||
}else{
|
||||
uni.previewImage({
|
||||
urls: this.imgUrls,
|
||||
current: this.imgUrls[index]
|
||||
});
|
||||
}
|
||||
},
|
||||
videoPause(e) {
|
||||
// #ifdef APP-PLUS
|
||||
this.isPlay = true;
|
||||
this.autoplay = true;
|
||||
// #endif
|
||||
},
|
||||
bindPause: function () {
|
||||
// #ifndef APP-PLUS
|
||||
this.videoContext.play();
|
||||
this.$set(this, 'controls', false);
|
||||
this.autoplay = false;
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
this.isPlay = false;
|
||||
this.videoContext = uni.createVideoContext('myVideo', this);
|
||||
this.videoContext.play();
|
||||
// #endif
|
||||
},
|
||||
change(e) {
|
||||
this.$emit('attrPicIndex',e.detail.current)
|
||||
if(this.showSku){
|
||||
this.$emit('changeAttrPic',e.detail.current)
|
||||
}
|
||||
// this.$set(this, 'currents', e.detail.current);
|
||||
// this.$emit('onChange',e.detail.current);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.item-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgb(74, 74, 76);
|
||||
}
|
||||
|
||||
.product-bg {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.product-bg swiper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.product-bg .slide-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.product-bg .pages {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
height: 34rpx;
|
||||
padding: 0 10rpx;
|
||||
border-radius: 3rpx;
|
||||
right: 30rpx;
|
||||
bottom: 30rpx;
|
||||
line-height: 34rpx;
|
||||
font-size: 24rpx;
|
||||
color: #050505;
|
||||
}
|
||||
|
||||
.product-bg .item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.product-bg .item .poster {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 750rpx;
|
||||
width: 100%;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.product-bg .item .poster .image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.product-bg .item .stop {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 136rpx;
|
||||
height: 136rpx;
|
||||
margin-top: -68rpx;
|
||||
margin-left: -68rpx;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.product-bg .item .stop .image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dot_item ~ .dot_item {
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
.white-jianbian {
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(0, 0, 0, 0.2) 100%);
|
||||
}
|
||||
.bottom-86rpx{
|
||||
bottom: 86rpx;
|
||||
}
|
||||
.bottom-34rpx{
|
||||
bottom: 34rpx;
|
||||
}
|
||||
.sku-desc{
|
||||
// width: 456rpx;
|
||||
height: 40rpx;
|
||||
background: rgba(0,0,0,0.3);
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
</style>
|
||||
543
components/productWindow/index.vue
Normal file
543
components/productWindow/index.vue
Normal file
@@ -0,0 +1,543 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="product-window"
|
||||
:class="(attr.cartAttr === true ? 'on' : '') + ' ' + (iSbnt?'join':'') + ' ' + (iScart?'joinCart':'')" @touchmove.stop.prevent="moveHandle"
|
||||
>
|
||||
<view class="textpic acea-row" >
|
||||
<view class="pictrue" @click="showImg()">
|
||||
<image :src="attr.productSelect.image"></image>
|
||||
<view class="icon flex-center" v-if="fangda">
|
||||
<view class="iconfont icon-ic_enlarge"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pl-24 pt-24 flex-col">
|
||||
<view class="flex-y-center" v-if="attr.productSelect.integral">
|
||||
<image src="../../static/img/mall05.png" class="w-32 h-32"></image>
|
||||
<text class="lh-40rpx font-num fs-40 SemiBold pl-8">{{attr.productSelect.integral}}</text>
|
||||
<text class="fs-28 lh-40rpx px-8 text--w111-666">+</text>
|
||||
<baseMoney :money="attr.productSelect.price" symbolSize="28" integerSize="40" decimalSize="28" color="var(--view-theme)" weight></baseMoney>
|
||||
</view>
|
||||
<baseMoney
|
||||
:money="attr.productSelect.price"
|
||||
symbolSize="32"
|
||||
integerSize="48"
|
||||
decimalSize="32"
|
||||
incolor="var(--primary-theme-con)"
|
||||
weight v-else></baseMoney>
|
||||
<view class="inline-block h-48 lh-48rpx text-center rd-24rpx bg-color fs-24 text--w111-fff px-20 mt-16"
|
||||
v-if="type == 0">
|
||||
预估到手 <text class="fs-28 fw-600 pl-8">¥{{attr.productSelect.pay_price}}</text>
|
||||
</view>
|
||||
<view class="mt-12 fs-24 text--w111-999" v-if="type == 1 || type == 3">限量:{{ attr.productSelect.quota_show || 0 }}</view>
|
||||
<view class="mt-12 fs-24 text--w111-999" v-else>库存:{{ attr.productSelect.stock || attr.productSelect.product_stock || 0 }}</view>
|
||||
</view>
|
||||
<view class="iconfont icon-ic_close1" @click="closeAttr"></view>
|
||||
</view>
|
||||
<view class="mt-36">
|
||||
<scroll-view scroll-y="true" :style="'max-height: '+windowHeight+'rpx'" >
|
||||
<view class="productWinList">
|
||||
<view class="item" v-for="(item, indexw) in attr.productAttr" :key="indexw">
|
||||
<view v-show="item.is_pic == 0">
|
||||
<view class="fs-28 fw-500 px-32">{{ item.attr_name }}</view>
|
||||
<view class="listn acea-row row-middle">
|
||||
<view class="itemn" :class="item.index === itemn.attr ? 'active' : ''"
|
||||
v-for="(itemn, indexn) in item.attr_value" @click="tapAttr(indexw, indexn)"
|
||||
:key="indexn">
|
||||
{{ itemn.attr }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-show="item.is_pic == 1">
|
||||
<view class="flex-between-center">
|
||||
<view class="fs-28 fw-500 px-32">{{ item.attr_name }}</view>
|
||||
<view class="pr-32 fs-24 text--w111-666 flex-y-center" v-show="gridShow == 1" @tap="toggleGridAttr(0)">
|
||||
<text class="iconfont icon-a-ic_Imageandtextsorting fs-28"></text>
|
||||
<text class="pl-6">列表</text>
|
||||
</view>
|
||||
<view class="pr-32 fs-24 text--w111-666 flex-y-center" v-show="gridShow == 0" @tap="toggleGridAttr(1)">
|
||||
<text class="iconfont icon-a-ic_Picturearrangement fs-28"></text>
|
||||
<text class="pl-6">宫格</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pl-32 mt-32" v-show="gridShow == 1">
|
||||
<scroll-view scroll-x="true" class="white-nowrap vertical-middle w-686"
|
||||
show-scrollbar="false">
|
||||
<view class="inline-block mr-12"
|
||||
v-for="(itemn, indexn) in item.attr_value"
|
||||
:key="indexn"
|
||||
@click="tapAttr(indexw, indexn)">
|
||||
<view class="grid-item-box" :class="item.index === itemn.attr ? 'grid-active' : ''">
|
||||
<view class="w-full h-192 relative">
|
||||
<image class="w-full h-192 block" :src="itemn.pic" mode="aspectFill"></image>
|
||||
<view class="proview-icon flex-center" @tap.stop="proviewImg(itemn.pic)">
|
||||
<text class="iconfont icon-ic_enlarge fs-24 text--w111-fff"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-1 bg--w111-f5f5f5 tname flex-center fs-24">{{itemn.attr}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="listn acea-row row-middle" v-show="gridShow == 0">
|
||||
<view class="cell-itemn flex-between-center"
|
||||
:class="item.index === itemn.attr ? 'active' : ''"
|
||||
v-for="(itemn, indexn) in item.attr_value" :key="indexn"
|
||||
@click="tapAttr(indexw, indexn)">
|
||||
<image :src="itemn.pic" class="w-48 h-48 rd-50-p111-"></image>
|
||||
<text class="pl-8">{{ itemn.attr }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="cart px-30 flex-between-center mt-24" v-if="type != 'setMeal' && type !='points'">
|
||||
<view class="fs-28">数量</view>
|
||||
<view class="carnum flex-y-center">
|
||||
<template v-if="type == 0">
|
||||
<text class="font-num fs-22" v-if="storeInfo.min_qty && !storeInfo.is_limit">(商品{{storeInfo.min_qty}}{{storeInfo.unit_name}}起购)</text>
|
||||
<text class="font-num fs-22" v-else-if="!storeInfo.min_qty && storeInfo.is_limit && storeInfo.limit_num > 0">(商品限购{{storeInfo.limit_num}}{{storeInfo.unit_name}})</text>
|
||||
<text class="font-num fs-22" v-else-if="storeInfo.min_qty && storeInfo.is_limit && storeInfo.limit_num > 0">(商品起购{{storeInfo.min_qty}}{{storeInfo.unit_name}} 限购{{storeInfo.limit_num}}{{storeInfo.unit_name}})</text>
|
||||
</template>
|
||||
<view class="item reduce flex-center"
|
||||
:class="{'on': reduceDisabled}" @click="CartNumDes">
|
||||
<text class="iconfont icon-ic_Reduce fs-24"></text>
|
||||
</view>
|
||||
<view class='item num flex-y-center'>
|
||||
<input type="number" :disabled="isDisabled" v-model="attr.productSelect.cart_num"
|
||||
@input="bindCode(attr.productSelect.cart_num)"></input>
|
||||
</view>
|
||||
<view class="item plus flex-center"
|
||||
:class="{'on': addDisabled }"
|
||||
@click="CartNumAdd">
|
||||
<text class="iconfont icon-ic_increase fs-24"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isExtends">
|
||||
<view class="joinBnt bg-gray" v-if="attr.productSelect.stock <= 0">已售罄</view>
|
||||
<view class="joinBnt bg-color" v-else @click="cartConfirm">确定</view>
|
||||
</view>
|
||||
<view class="joinBnt bg-color"
|
||||
v-if="iSbnt && attr.productSelect.product_stock>0 &&attr.productSelect.quota>0" @click="goCat">我要参团
|
||||
</view>
|
||||
<view class="joinBnt on"
|
||||
v-else-if="(iSbnt && attr.productSelect.quota<=0)||(iSbnt &&attr.productSelect.product_stock<=0)">已售罄
|
||||
</view>
|
||||
<view class="joinBnt bg-color" v-if="iScart && attr.productSelect.stock" @click="goCat">确定</view>
|
||||
<view class="joinBnt on" v-else-if="iScart && !attr.productSelect.stock">已售罄</view>
|
||||
</view>
|
||||
<view class="mask z-25" @touchmove.stop.prevent="moveHandle" :hidden="attr.cartAttr === false" @click="closeAttr"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let windowHeight = (uni.getWindowInfo().windowHeight*(3/4)-238)*2;
|
||||
export default {
|
||||
|
||||
props: {
|
||||
attr: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
storeInfo: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
limitNum: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
isShow: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
iSbnt: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
iSplus: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
iScart: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
is_vip: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
type: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
fangda: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
isExtends:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showFooter:{
|
||||
type:Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
windowHeight:windowHeight,
|
||||
gridShow: 1,
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
reduceDisabled(){
|
||||
if(this.type == 0 && this.storeInfo && this.storeInfo.min_qty){
|
||||
return this.storeInfo.min_qty == this.attr.productSelect.cart_num
|
||||
}else{
|
||||
return this.attr.productSelect.cart_num <= 1
|
||||
}
|
||||
},
|
||||
addDisabled(){
|
||||
if(this.type == 0 && this.storeInfo && this.storeInfo.is_limit && this.storeInfo.limit_num){
|
||||
return this.storeInfo.limit_num == this.attr.productSelect.cart_num
|
||||
}else{
|
||||
return this.attr.productSelect.cart_num >= this.attr.productSelect.stock;
|
||||
}
|
||||
},
|
||||
isDisabled(){
|
||||
if(this.type ==0 && (this.storeInfo.min_qty || this.storeInfo.limit_num)){
|
||||
return true
|
||||
}else false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleGridAttr(type){
|
||||
this.gridShow = type;
|
||||
},
|
||||
goCat() {
|
||||
this.$emit('goCat');
|
||||
},
|
||||
bindCode(e) {
|
||||
this.$emit('iptCartNum', this.attr.productSelect.cart_num);
|
||||
},
|
||||
closeAttr() {
|
||||
this.$emit('myevent');
|
||||
},
|
||||
CartNumDes() {
|
||||
if(this.reduceDisabled) return
|
||||
this.$emit('ChangeCartNum', false);
|
||||
},
|
||||
CartNumAdd() {
|
||||
if(this.addDisabled) return
|
||||
this.$emit('ChangeCartNum', true);
|
||||
},
|
||||
tapAttr: function(indexw, indexn) {
|
||||
let that = this;
|
||||
that.$emit("attrVal", {
|
||||
indexw: indexw,
|
||||
indexn: indexn
|
||||
});
|
||||
this.$set(this.attr.productAttr[indexw], 'index', this.attr.productAttr[indexw].attr_values[indexn]);
|
||||
let value = that
|
||||
.getCheckedValue()
|
||||
.join(",");
|
||||
that.$emit("ChangeAttr", value);
|
||||
|
||||
},
|
||||
moveHandle() {},
|
||||
//获取被选中属性;
|
||||
getCheckedValue: function() {
|
||||
let productAttr = this.attr.productAttr;
|
||||
let value = [];
|
||||
for (let i = 0; i < productAttr.length; i++) {
|
||||
for (let j = 0; j < productAttr[i].attr_values.length; j++) {
|
||||
if (productAttr[i].index === productAttr[i].attr_values[j]) {
|
||||
value.push(productAttr[i].attr_values[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
},
|
||||
showImg() {
|
||||
this.$emit('getImg');
|
||||
},
|
||||
cartConfirm(){
|
||||
this.$emit('onConfirm');
|
||||
},
|
||||
proviewImg(img){
|
||||
uni.previewImage({
|
||||
current: 0,
|
||||
urls: [img]
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.vip-money {
|
||||
color: #282828;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
margin-left: 6rpx;
|
||||
}
|
||||
|
||||
.vipImg {
|
||||
width: 56rpx;
|
||||
height: 20rpx;
|
||||
margin-left: 6rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.product-window {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
z-index: 100;
|
||||
border-radius: 40rpx 40rpx 0 0;
|
||||
transform: translate3d(0, 100%, 0);
|
||||
transition: all 0.3s ease-in-out;
|
||||
padding-bottom: constant(safe-area-inset-bottom); ///兼容 IOS<11.2/
|
||||
padding-bottom: env(safe-area-inset-bottom);///兼容 IOS>11.2/
|
||||
}
|
||||
|
||||
.product-window.on {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.product-window.join {
|
||||
padding-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.product-window.joinCart {
|
||||
padding-bottom: 30rpx;
|
||||
z-index: 4000;
|
||||
}
|
||||
|
||||
.product-window .textpic {
|
||||
padding: 0 32rpx;
|
||||
margin-top: 48rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.product-window .textpic .pictrue {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
position: relative;
|
||||
.icon{
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
border-radius: 4rpx;
|
||||
position: absolute;
|
||||
bottom: 8rpx;
|
||||
right: 8rpx;
|
||||
text-align: center;
|
||||
line-height: 23rpx;
|
||||
.iconfont{
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.product-window .textpic .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.product-window .textpic .text {
|
||||
width: 410rpx;
|
||||
font-size: 32rpx;
|
||||
color: #202020;
|
||||
}
|
||||
|
||||
.product-window .textpic .text .money {
|
||||
font-size: 24rpx;
|
||||
margin-top: 40rpx;
|
||||
.icon{
|
||||
display: inline-block;
|
||||
font-size: 16rpx;
|
||||
font-weight: normal;
|
||||
background: #FF9500;
|
||||
color: #fff;
|
||||
border-radius: 18rpx;
|
||||
padding: 2rpx 6rpx;
|
||||
margin-left: 10rpx;
|
||||
.iconfont{
|
||||
font-size: 16rpx;
|
||||
margin-right: 4rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.product-window .textpic .icon-ic_close1 {
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
top: -5rpx;
|
||||
font-size: 35rpx;
|
||||
color: #8a8a8a;
|
||||
}
|
||||
.product-window .productWinList .item~.item {
|
||||
margin-top: 36rpx;
|
||||
}
|
||||
|
||||
.product-window .productWinList .item .listn {
|
||||
padding: 0 32rpx 0 16rpx;
|
||||
}
|
||||
|
||||
.product-window .productWinList .item .listn .itemn {
|
||||
// height: 56rpx;
|
||||
line-height: 56rpx;
|
||||
border: 1rpx solid #F2F2F2;
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 28rpx;
|
||||
margin: 24rpx 0 0 16rpx;
|
||||
background-color: #F2F2F2;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.product-window .productWinList .item .active {
|
||||
color: var(--view-theme) !important;
|
||||
background: var(--view-minorColorT) !important;
|
||||
border-color: var(--view-theme) !important;
|
||||
}
|
||||
|
||||
.product-window .productWinList .item .listn .itemn.limit {
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.product-window .cart .carnum view {
|
||||
width: 84rpx;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 54rpx;
|
||||
color: #282828;
|
||||
font-size: 45rpx;
|
||||
}
|
||||
|
||||
.product-window .cart .carnum .reduce {
|
||||
border-right: 0;
|
||||
border-radius: 6rpx 0 0 6rpx;
|
||||
line-height: 48rpx;
|
||||
font-size: 60rpx;
|
||||
}
|
||||
|
||||
.product-window .cart .carnum .reduce.on {
|
||||
// border-color: #e3e3e3;
|
||||
color: #DEDEDE;
|
||||
}
|
||||
|
||||
.product-window .cart .carnum .plus {
|
||||
border-left: 0;
|
||||
border-radius: 0 6rpx 6rpx 0;
|
||||
line-height: 46rpx;
|
||||
}
|
||||
|
||||
.product-window .cart .carnum .plus.on {
|
||||
// border-color: #e3e3e3;
|
||||
color: #dedede;
|
||||
}
|
||||
|
||||
.product-window .cart .carnum .num {
|
||||
background: rgba(242, 242, 242, 1);
|
||||
color: #282828;
|
||||
font-size: 28rpx;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.product-window .joinBnt {
|
||||
font-size: 28rpx;
|
||||
width: 710rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
color: #fff;
|
||||
margin: 74rpx auto 12rpx;
|
||||
}
|
||||
|
||||
.product-window .joinBnt.on {
|
||||
background-color: #bbb;
|
||||
color: #fff;
|
||||
}
|
||||
.mt-74{
|
||||
margin-top: 74rpx;
|
||||
}
|
||||
.join_cart{
|
||||
background-color: var(--view-bntColor);
|
||||
}
|
||||
.bg-gray{
|
||||
background-color: #CCCCCC;
|
||||
}
|
||||
.z-25{
|
||||
z-index: 25;
|
||||
}
|
||||
.w-686{
|
||||
width: 686rpx;
|
||||
}
|
||||
.grid-item-box{
|
||||
width: 196rpx;
|
||||
border: 2rpx solid #F5F5F5;
|
||||
border-radius: 8rpx;
|
||||
image{
|
||||
border-radius: 8rpx 8rpx 0 0;
|
||||
}
|
||||
.tname{
|
||||
width: 196rpx;
|
||||
border-radius: 0 0 8rpx 8rpx ;
|
||||
padding: 4rpx 12rpx;
|
||||
height: 74rpx;
|
||||
display: -webkit-box; /* 旧版弹性盒子 */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-line-clamp: 2; /* 显示两行 */
|
||||
-webkit-box-orient: vertical; /* 垂直方向排列 */
|
||||
word-break: break-all; /* 允许单词断行 */
|
||||
white-space: normal; /* 允许文字折行 */
|
||||
}
|
||||
}
|
||||
.grid-active{
|
||||
border: 2rpx solid var(--view-theme);
|
||||
.tname{
|
||||
color: var(--view-theme);
|
||||
background: var(--view-minorColorT);
|
||||
}
|
||||
}
|
||||
.cell-itemn{
|
||||
line-height: 56rpx;
|
||||
border: 1rpx solid #F2F2F2;
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
padding: 0 20rpx 0 4rpx;
|
||||
border-radius: 30rpx;
|
||||
margin: 24rpx 0 0 16rpx;
|
||||
background-color: #F2F2F2;
|
||||
word-break: break-all;
|
||||
}
|
||||
.proview-icon{
|
||||
position: absolute;
|
||||
top: 8rpx;
|
||||
right: 8rpx;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
background: #DDDDDD;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
49
components/recommend/index.vue
Normal file
49
components/recommend/index.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<!-- 热门推荐 -->
|
||||
<view class='pt-40' :style="colorStyle">
|
||||
<view class="flex-center">
|
||||
<image class="w-42 h-36" src="../../static/img/recommend_zs.png"></image>
|
||||
<text class="fs-32 fw-500 text--w111-333 lh-44rpx px-6">{{ title }}</text>
|
||||
<image class="w-42 h-36" src="../../static/img/recommend_zs.png"></image>
|
||||
</view>
|
||||
<view class="relative mt-24">
|
||||
<view class="jinabian"></view>
|
||||
<waterfallsFlow ref="waterfallsFlow" :wfList="hostProduct" :showCart="false" recommend @itemTap="goDetail"></waterfallsFlow>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from "vuex";
|
||||
import { goShopDetail } from '@/libs/order.js'
|
||||
import colors from "@/mixins/color";
|
||||
import waterfallsFlow from "@/components/WaterfallsFlow/WaterfallsFlow.vue";
|
||||
export default {
|
||||
props: {
|
||||
hostProduct: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '猜你喜欢'
|
||||
},
|
||||
},
|
||||
components: {
|
||||
waterfallsFlow,
|
||||
},
|
||||
mixins: [colors],
|
||||
computed: mapGetters(['uid']),
|
||||
methods: {
|
||||
goDetail(item){
|
||||
goShopDetail(item, this.uid).catch(res => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/goods_details/index?id=${item.id}`
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
198
components/skeleton/index.vue
Normal file
198
components/skeleton/index.vue
Normal file
@@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<view v-if="show"
|
||||
:style="{width: systemInfo.width + 'px', height: systemInfo.height + 'px', backgroundColor: bgcolor, position: 'absolute', left: 0, top: 0, zIndex: 9998}">
|
||||
<view v-for="(item,rect_idx) in skeletonRectLists" :key="item.rect"
|
||||
:class="[loading == 'chiaroscuro' ? 'chiaroscuro' : '']"
|
||||
:style="{width: item.width + 'px', height: item.height + 'px', backgroundColor: 'rgb(194, 207, 214,.3)', position: 'absolute', left: item.left + 'px', top: item.top + 'px'}">
|
||||
</view>
|
||||
<view v-for="(item,circle_idx) in skeletonCircleLists" :key="item.circle"
|
||||
:class="loading == 'chiaroscuro' ? 'chiaroscuro' : ''"
|
||||
:style="{width: item.width + 'px', height: item.height + 'px', backgroundColor: 'rgb(194, 207, 214,.3)', borderRadius: item.width + 'px', position: 'absolute', left: item.left + 'px', top: item.top + 'px'}">
|
||||
</view>
|
||||
<view class="spinbox" v-if="loading == 'spin'">
|
||||
<view class="spin"></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "skeleton",
|
||||
props: {
|
||||
bgcolor: {
|
||||
type: String,
|
||||
value: '#FFF'
|
||||
},
|
||||
selector: {
|
||||
type: String,
|
||||
value: 'skeleton'
|
||||
},
|
||||
loading: {
|
||||
type: String,
|
||||
value: 'spin'
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
isNodes: {
|
||||
type: Number,
|
||||
value: false
|
||||
} //控制什么时候开始抓取元素节点,只要数值改变就重新抓取
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loadingAni: ['spin', 'chiaroscuro'],
|
||||
systemInfo: {},
|
||||
skeletonRectLists: [],
|
||||
skeletonCircleLists: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isNodes(val) {
|
||||
this.readyAction();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.attachedAction();
|
||||
},
|
||||
methods: {
|
||||
attachedAction: function() {
|
||||
//默认的首屏宽高,防止内容闪现
|
||||
const systemInfo = uni.getWindowInfo();
|
||||
this.systemInfo = {
|
||||
width: systemInfo.windowWidth,
|
||||
height: systemInfo.windowHeight
|
||||
};
|
||||
this.loading = this.loadingAni.includes(this.loading) ? this.loading : 'spin';
|
||||
},
|
||||
readyAction: function() {
|
||||
const that = this;
|
||||
//绘制背景
|
||||
uni.createSelectorQuery().selectAll(`.${this.selector}`).boundingClientRect().exec(function(res) {
|
||||
if(res[0].length>0)
|
||||
that.systemInfo.height = res[0][0].height + res[0][0].top;
|
||||
});
|
||||
|
||||
//绘制矩形
|
||||
this.rectHandle();
|
||||
|
||||
//绘制圆形
|
||||
this.radiusHandle();
|
||||
},
|
||||
rectHandle: function() {
|
||||
const that = this;
|
||||
|
||||
//绘制不带样式的节点
|
||||
uni.createSelectorQuery().selectAll(`.${this.selector}-rect`).boundingClientRect().exec(function(res) {
|
||||
let obj = res[0];
|
||||
obj.forEach((item,index)=>{
|
||||
item.rect = 'rect'+index
|
||||
})
|
||||
that.skeletonRectLists = obj;
|
||||
});
|
||||
|
||||
},
|
||||
radiusHandle() {
|
||||
const that = this;
|
||||
|
||||
uni.createSelectorQuery().selectAll(`.${this.selector}-radius`).boundingClientRect().exec(function(res) {
|
||||
let obj = res[0];
|
||||
obj.forEach((item,index)=>{
|
||||
item.circle = 'circle'+index
|
||||
})
|
||||
that.skeletonCircleLists = obj;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.spinbox {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 9999
|
||||
}
|
||||
|
||||
.spin {
|
||||
display: inline-block;
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
}
|
||||
|
||||
.spin:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
width: 46rpx;
|
||||
height: 46rpx;
|
||||
margin: 1rpx;
|
||||
border-radius: 50%;
|
||||
border: 5rpx solid #409eff;
|
||||
border-color: #409eff transparent #409eff transparent;
|
||||
animation: spin 1.2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.chiaroscuro {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgb(194, 207, 214);
|
||||
animation-duration: 2s;
|
||||
animation-name: blink;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0% {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: .4;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flush {
|
||||
0% {
|
||||
left: -100%;
|
||||
}
|
||||
|
||||
50% {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.shine {
|
||||
animation: flush 2s linear infinite;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
background: linear-gradient(to left,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, .85) 50%,
|
||||
rgba(255, 255, 255, 0) 100%)
|
||||
}
|
||||
</style>
|
||||
264
components/splitOrder/index.vue
Normal file
264
components/splitOrder/index.vue
Normal file
@@ -0,0 +1,264 @@
|
||||
<template>
|
||||
<!-- 拆单订单 -->
|
||||
<view class='splitOrder' v-if="splitGoods.length">
|
||||
<view class="all" v-if="select_all">
|
||||
<checkbox-group @change="checkboxAllChange">
|
||||
<checkbox value="all" :checked="isAllSelect" />
|
||||
<text class='checkAll'>全选</text>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
<checkbox-group @change="checkboxChange">
|
||||
<block v-for="(item,index) in splitGoods" :key="index">
|
||||
<view class='items acea-row row-between-wrapper'>
|
||||
<!-- #ifndef MP -->
|
||||
<checkbox :value="(item.id).toString()" :checked="item.checked"
|
||||
color="#ffffff" backgroundColor="#ffffff"
|
||||
activeBackgroundColor="#2A7EFB" activeBorderColor="#2A7EFB"/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<checkbox :value="item.id" :checked="item.checked" />
|
||||
<!-- #endif -->
|
||||
<view class='picTxt acea-row row-between-wrapper'>
|
||||
<view class='pictrue'>
|
||||
<image :src='item.cart_info.productInfo.image'></image>
|
||||
</view>
|
||||
<view class='text'>
|
||||
<view class="acea-row row-between-wrapper">
|
||||
<view class='name line1'>{{item.cart_info.productInfo.store_name}}</view>
|
||||
<!-- <view>×{{item.cart_num}}</view> -->
|
||||
</view>
|
||||
<view class='infor line1'>
|
||||
属性:{{item.cart_info.productInfo.attrInfo.suk || '默认'}}</view>
|
||||
<view class="acea-row row-middle money-section">
|
||||
实付款:<view class='money'>¥{{item.cart_info.sum_true_price}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class='carnum acea-row row-center-wrapper'>
|
||||
<view class="reduce iconfont icon-ic_Reduce" :class="item.surplus_num == 1 ? 'on' : ''" @click.stop='subCart(item)'></view>
|
||||
<view class='num'>{{item.surplus_num}}</view>
|
||||
<view class="plus iconfont icon-ic_increase" :class="item.surplus_num == item.numShow ? 'on' : ''" @click.stop='addCart(item)'></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
splitGoods: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
select_all: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isAllSelect: false
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
subCart(item) {
|
||||
item.surplus_num = Number(item.surplus_num) - 1;
|
||||
if (item.surplus_num <= 1) {
|
||||
item.surplus_num = 1
|
||||
}
|
||||
this.$emit('getList', this.splitGoods);
|
||||
},
|
||||
addCart(item) {
|
||||
item.surplus_num = Number(item.surplus_num) + 1;
|
||||
if (item.surplus_num >= item.numShow) {
|
||||
item.surplus_num = item.numShow
|
||||
}
|
||||
this.$emit('getList', this.splitGoods);
|
||||
},
|
||||
inArray: function(search, array) {
|
||||
for (let i in array) {
|
||||
if (array[i] == search) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
checkboxChange(event) {
|
||||
let idList = event.detail.value;
|
||||
this.splitGoods.forEach((item) => {
|
||||
if (this.inArray(item.id, idList)) {
|
||||
item.checked = true;
|
||||
} else {
|
||||
item.checked = false;
|
||||
}
|
||||
})
|
||||
this.$emit('getList', this.splitGoods);
|
||||
if (idList.length == this.splitGoods.length) {
|
||||
this.isAllSelect = true;
|
||||
} else {
|
||||
this.isAllSelect = false;
|
||||
}
|
||||
},
|
||||
forGoods(val) {
|
||||
let that = this;
|
||||
if (!that.splitGoods.length) return
|
||||
that.splitGoods.forEach((item) => {
|
||||
if (val) {
|
||||
item.checked = true;
|
||||
} else {
|
||||
item.checked = false;
|
||||
}
|
||||
})
|
||||
that.$emit('getList', that.splitGoods);
|
||||
},
|
||||
checkboxAllChange(event) {
|
||||
let value = event.detail.value;
|
||||
if (value.length) {
|
||||
this.forGoods(1)
|
||||
} else {
|
||||
this.forGoods(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/deep/ checkbox .wx-checkbox-input.wx-checkbox-input-checked {
|
||||
border: 1px solid $primary-admin !important;
|
||||
background-color: $primary-admin !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
.splitOrder {
|
||||
width: 710rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
margin: 24rpx auto 0 auto;
|
||||
padding: 32rpx 26rpx;
|
||||
}
|
||||
|
||||
.splitOrder .all {
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.splitOrder .all .checkAll {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items~.items {
|
||||
margin-top: 48rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt {
|
||||
width: 604rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .name {
|
||||
width: 444rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .pictrue {
|
||||
width: 136rpx;
|
||||
height: 136rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .text {
|
||||
width: 450rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .text .reColor {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .text .reElection {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .text .reElection .title {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .text .reElection .reBnt {
|
||||
width: 120rpx;
|
||||
height: 46rpx;
|
||||
border-radius: 23rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .text .infor {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
margin-top: 12rpx;
|
||||
width: 284rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .text .money-section {
|
||||
margin-top: 18rpx;
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .text .money {
|
||||
font-size: 36rpx;
|
||||
color: #333;
|
||||
font-family: 'Regular';
|
||||
color: #FF7D00;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .carnum {
|
||||
height: 36rpx;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .carnum view {
|
||||
width: 66rpx;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 36rpx;
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .carnum .reduce {
|
||||
border-right: 0;
|
||||
border-radius: 3rpx 0 0 3rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .carnum .reduce.on {
|
||||
border-color: #e3e3e3;
|
||||
color: #dedede;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .carnum .plus {
|
||||
border-left: 0;
|
||||
border-radius: 0 3rpx 3rpx 0;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .carnum .plus.on {
|
||||
border-color: #e3e3e3;
|
||||
color: #dedede;
|
||||
}
|
||||
|
||||
.splitOrder .items .picTxt .carnum .num {
|
||||
color: #282828;
|
||||
background: #F5F5F5;
|
||||
width: 72rpx;
|
||||
}
|
||||
</style>
|
||||
159
components/timeranges/index.vue
Normal file
159
components/timeranges/index.vue
Normal file
@@ -0,0 +1,159 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="time1" :class='isShow==true?"on":""'>
|
||||
<view class="top acea-row row-between-wrapper">
|
||||
<text @tap="cancel">取消</text>
|
||||
<text @tap="confirm">确定</text>
|
||||
</view>
|
||||
<picker-view class="picker" :value="value" @change="getime" indicator-style="height:34px;">
|
||||
<picker-view-column>
|
||||
<view class="hours" v-for="(item,index) in hoursList" :key="index">{{item}}</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="minutes" v-for="(item,index) in minutes" :key="index">{{item}}</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="center">-</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="hours" v-for="(item,index) in hoursList" :key="index">{{item}}</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="minutes" v-for="(item,index) in minutes" :key="index">{{item}}</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
<view class="mask" @tap="cancel" catchtouchmove="true" :hidden="isShow==false"></view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
let minutes=[]
|
||||
for (let i = 0; i <= 59; i++) {
|
||||
if(i<10){
|
||||
i="0"+i
|
||||
}
|
||||
minutes.push(i)
|
||||
}
|
||||
let hoursList = []
|
||||
for (let i = 0; i <= 23; i++) {
|
||||
if(i<10){
|
||||
i="0"+i
|
||||
}
|
||||
hoursList.push(i)
|
||||
}
|
||||
export default{
|
||||
props:{
|
||||
isShow:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
time:{
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
time:function(){
|
||||
this.value=this.time
|
||||
}
|
||||
},
|
||||
created(){
|
||||
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
value:this.time,//默认结束开始时间
|
||||
hoursList,
|
||||
minutes,
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
confirm(){
|
||||
let time = this.value[0]+":"+this.value[1]+" - "+this.value[3]+":"+this.value[4]
|
||||
if(this.value[3]>this.value[0] || (this.value[3]==this.value[0] && this.value[4]>=this.value[1])){
|
||||
this.$emit("confrim",{time:time,val:this.value})
|
||||
}else{
|
||||
return this.$util.Tips({
|
||||
title: '开始时间必须小于结束时间'
|
||||
});
|
||||
}
|
||||
},
|
||||
cancel(){
|
||||
let time = this.value[0]+":"+this.value[1]+" - "+this.value[3]+":"+this.value[4]
|
||||
this.$emit("cancel",{time:time})
|
||||
},
|
||||
getime(e){
|
||||
let val = e.detail.value
|
||||
this.value[0] = this.hoursList[val[0]]
|
||||
this.value[1] = this.minutes[val[1]]
|
||||
this.value[2] = val[2]
|
||||
this.value[3] = this.hoursList[val[3]]
|
||||
this.value[4] = this.minutes[val[4]]
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.time1{
|
||||
width:100%;
|
||||
margin: 0 auto;
|
||||
background-color:#FFFFFF;
|
||||
color: #000;
|
||||
height: 568rpx;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
transform: translate3d(0, 200%, 0);
|
||||
transition: all .3s cubic-bezier(.25, .5, .5, .9);
|
||||
&.on{
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
.top{
|
||||
height: 90rpx;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding: 0 30rpx;
|
||||
text{
|
||||
font-size: 32rpx;
|
||||
&:nth-child(1){
|
||||
color: #888;
|
||||
}
|
||||
&:nth-child(2){
|
||||
color: #007aff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tip12{
|
||||
width: 100%;
|
||||
height: 100rpx;
|
||||
view{
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
line-height: 100rpx;
|
||||
font-size: 40rpx;
|
||||
color: #000000;
|
||||
}
|
||||
}
|
||||
.hours{
|
||||
font-size: 32rpx;
|
||||
color: #000;
|
||||
line-height:34px;
|
||||
text-align: center;
|
||||
}
|
||||
.minutes{
|
||||
font-size: 32rpx;
|
||||
color: #000;
|
||||
line-height:34px;
|
||||
text-align: center;
|
||||
}
|
||||
.center{
|
||||
line-height:34px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.picker{
|
||||
width: 100%;
|
||||
height: 476rpx;
|
||||
}
|
||||
</style>
|
||||
144
components/tui-drawer/tui-drawer.vue
Normal file
144
components/tui-drawer/tui-drawer.vue
Normal file
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<view>
|
||||
<view v-if="mask" class="tui-drawer-mask" :class="{ 'tui-drawer-mask_show': visible }" :style="{ zIndex: maskZIndex }"
|
||||
@tap="handleMaskClick" @touchmove.stop.prevent="moveHandle"></view>
|
||||
<view
|
||||
class="tui-drawer-container"
|
||||
:class="[`tui-drawer-container_${mode}`, visible ? `tui-drawer-${mode}__show` : '']"
|
||||
:style="{ zIndex: zIndex, backgroundColor: backgroundColor }"
|
||||
@touchmove.stop.prevent="moveHandle"
|
||||
>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 超过一屏时插槽使用scroll-view
|
||||
**/
|
||||
export default {
|
||||
name: 'tuiDrawer',
|
||||
emits: ['close'],
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
mask: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
maskClosable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// left right bottom top
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'right'
|
||||
},
|
||||
//drawer z-index
|
||||
zIndex: {
|
||||
type: [Number, String],
|
||||
default: 990
|
||||
},
|
||||
//mask z-index
|
||||
maskZIndex: {
|
||||
type: [Number, String],
|
||||
default: 980
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
moveHandle(){
|
||||
return false
|
||||
},
|
||||
handleMaskClick() {
|
||||
if (!this.maskClosable) {
|
||||
return;
|
||||
}
|
||||
this.$emit('close', {});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tui-drawer-mask {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
.tui-drawer-mask_show {
|
||||
display: block;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tui-drawer-container {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
height: 100.2%;
|
||||
top: 0;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
transform-origin: center;
|
||||
transition: all 0.3s ease-in-out;
|
||||
opacity: 0;
|
||||
overflow-y: scroll;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
-ms-touch-action: pan-y cross-slide-y;
|
||||
-ms-scroll-chaining: none;
|
||||
-ms-scroll-limit: 0 50 0 50;
|
||||
}
|
||||
.tui-drawer-container_left {
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translate3d(-100%, -50%, 0);
|
||||
}
|
||||
|
||||
.tui-drawer-container_right {
|
||||
right: 0;
|
||||
top: 50%;
|
||||
left: auto;
|
||||
transform: translate3d(100%, -50%, 0);
|
||||
}
|
||||
|
||||
.tui-drawer-container_bottom,
|
||||
.tui-drawer-container_top {
|
||||
width: 100%;
|
||||
height: auto !important;
|
||||
min-height: 20rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transform-origin: center;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
.tui-drawer-container_bottom {
|
||||
bottom: 0;
|
||||
top: auto;
|
||||
transform: translate3d(0, 100%, 0);
|
||||
}
|
||||
.tui-drawer-container_top {
|
||||
transform: translate3d(0, -100%, 0);
|
||||
}
|
||||
.tui-drawer-left__show,
|
||||
.tui-drawer-right__show {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, -50%, 0);
|
||||
}
|
||||
.tui-drawer-top__show,
|
||||
.tui-drawer-bottom__show {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
</style>
|
||||
209
components/tui-modal/index.vue
Normal file
209
components/tui-modal/index.vue
Normal file
@@ -0,0 +1,209 @@
|
||||
<template>
|
||||
<view class="tui-modal__container" :class="[show ? 'tui-modal-show' : '']" :style="{zIndex:zIndex}">
|
||||
<view class="tui-modal-box"
|
||||
:class="[fadeIn || show ? 'tui-modal-normal' : 'tui-modal-scale', show ? 'tui-modal-show' : '']">
|
||||
<view v-if="!custom">
|
||||
<view class="tui-modal-title" v-if="title">{{ title }}</view>
|
||||
<view class="tui-modal-content" :class="[title ? '' : 'tui-mtop']"
|
||||
>{{ content }}</view>
|
||||
<view class="tui-modalBtn-box">
|
||||
<view class="tui-modal-btn flex-center tui-modal-btn-cancel" @tap="handleClick(0)">{{cancelText}}</view>
|
||||
<view class="tui-modal-btn flex-center tui-modal-btn-confirm" @tap="handleClick(1)">{{confirmText}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isMask" class="tui-modal-mask" :class="[show ? 'tui-mask-show' : '']"
|
||||
:style="{zIndex:maskZIndex,background:maskColor}" @tap="handleClickCancel"
|
||||
@touchmove.stop.prevent></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'tuiModal',
|
||||
emits: ['click', 'cancel'],
|
||||
props: {
|
||||
//是否显示
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//标题
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//内容
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
cancelText:{
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
confirmText:{
|
||||
type: String,
|
||||
default: '确定'
|
||||
},
|
||||
//点击遮罩 是否可关闭
|
||||
maskClosable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//是否显示mask
|
||||
isMask: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
maskColor: {
|
||||
type: String,
|
||||
default: 'rgba(0, 0, 0, 0.6)'
|
||||
},
|
||||
//淡入效果,自定义弹框插入input输入框时传true
|
||||
fadeIn: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//自定义弹窗内容
|
||||
custom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//容器z-index
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 9997
|
||||
},
|
||||
//mask z-index
|
||||
maskZIndex: {
|
||||
type: Number,
|
||||
default: 9990
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
handleClick(index) {
|
||||
if (!this.show) return;
|
||||
this.$emit('click', {
|
||||
index: Number(index)
|
||||
});
|
||||
},
|
||||
handleClickCancel() {
|
||||
if (!this.maskClosable) return;
|
||||
this.$emit('cancel');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tui-modal__container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tui-modal-box {
|
||||
position: relative;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s ease-in-out;
|
||||
width:600rpx;
|
||||
padding: 40rpx;
|
||||
border-radius:32rpx;
|
||||
background-color: #fff;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.tui-modal-scale {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.tui-modal-normal {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.tui-modal-show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.tui-modal-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
transition: all 0.3s ease-in-out;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tui-mask-show {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tui-modal-title {
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
line-height: 52rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tui-modal-content {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 30rpx;
|
||||
line-height: 40rpx;
|
||||
margin: 24rpx auto 40rpx;
|
||||
}
|
||||
|
||||
.tui-mtop {
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.tui-mbtm {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.tui-modalBtn-box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.tui-flex-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tui-modal-btn {
|
||||
width: 244rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 36rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.tui-modal-btn-cancel{
|
||||
border: 1px solid var(--view-theme);
|
||||
color: var(--view-theme);
|
||||
}
|
||||
.tui-modal-btn-confirm{
|
||||
background-color: var(--view-theme);
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
315
components/tui-swipe-action/index.vue
Normal file
315
components/tui-swipe-action/index.vue
Normal file
@@ -0,0 +1,315 @@
|
||||
<template>
|
||||
<view class="tui-swipeout-wrap" :style="{ backgroundColor: backgroundColor }">
|
||||
<view class="tui-swipeout-item" :class="[isShowBtn ? 'swipe-action-show' : '']"
|
||||
:style="{ transform: 'translate(' + position.pageX + 'px,0)' }">
|
||||
<view class="tui-swipeout-content" @touchstart="handlerTouchstart"
|
||||
@touchmove="handlerTouchmove" @touchend="handlerTouchend" @mousedown="handlerTouchstart"
|
||||
@mousemove="handlerTouchmove" @mouseup="handlerTouchend">
|
||||
<slot name="content"></slot>
|
||||
</view>
|
||||
<view class="tui-swipeout-button-right-group" v-if="actions.length > 0" @touchend.stop="loop">
|
||||
<view class="tui-swipeout-button-right-item" v-for="(item, index) in actions" :key="index"
|
||||
:style="{ backgroundColor: item.background || '#f7f7f7', color: item.color, width: item.width + 'px' }"
|
||||
:data-index="index" @tap="handlerButton">
|
||||
<image :src="item.icon" v-if="item.icon"
|
||||
:style="{ width: px(item.imgWidth), height: px(item.imgHeight) }"></image>
|
||||
<text :style="{ fontSize: px(item.fontsize) }">{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!--actions长度设置为0,可直接传按钮进来-->
|
||||
<view class="tui-swipeout-button-right-group" @touchend.stop="loop" @tap="handlerParentButton"
|
||||
v-if="actions.length === 0" :style="{ width: operateWidth + 'px', right: '-' + operateWidth + 'px' }">
|
||||
<slot name="button"></slot>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isShowBtn && showMask" class="swipe-action_mask" @tap.stop="closeButtonGroup"
|
||||
@touchstart.stop.prevent="closeButtonGroup"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'tuiSwipeAction',
|
||||
emits: ['click'],
|
||||
props: {
|
||||
// name: '删除',
|
||||
// color: '#fff',
|
||||
// fontsize: 32,//单位rpx
|
||||
// width: 80, //单位px
|
||||
// icon: 'like.png',//此处为图片地址
|
||||
// background: '#ed3f14'
|
||||
actions: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
//点击按钮时是否自动关闭
|
||||
closable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//设为false,可以滑动多行不关闭菜单
|
||||
showMask: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
operateWidth: {
|
||||
type: Number,
|
||||
default: 80
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
//禁止滑动
|
||||
forbid: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//手动开关
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//背景色
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
actions(newValue, oldValue) {
|
||||
this.updateButtonSize();
|
||||
},
|
||||
open(newValue) {
|
||||
this.manualSwitch(newValue);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//start position
|
||||
tStart: {
|
||||
pageX: 0,
|
||||
pageY: 0
|
||||
},
|
||||
//限制滑动距离
|
||||
limitMove: 0,
|
||||
//move position
|
||||
position: {
|
||||
pageX: 0,
|
||||
pageY: 0
|
||||
},
|
||||
isShowBtn: false,
|
||||
move: false
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.updateButtonSize();
|
||||
},
|
||||
methods: {
|
||||
swipeDirection(x1, x2, y1, y2) {
|
||||
return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : y1 - y2 > 0 ? 'Up' :
|
||||
'Down';
|
||||
},
|
||||
//阻止事件冒泡
|
||||
loop() {
|
||||
},
|
||||
updateButtonSize() {
|
||||
const actions = this.actions;
|
||||
if (actions.length > 0) {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
let limitMovePosition = 0;
|
||||
actions.forEach(item => {
|
||||
limitMovePosition += item.width || 0;
|
||||
});
|
||||
this.limitMove = limitMovePosition;
|
||||
} else {
|
||||
this.limitMove = this.operateWidth;
|
||||
}
|
||||
},
|
||||
handlerTouchstart(event) {
|
||||
if (this.forbid) return;
|
||||
let touches = event.touches
|
||||
if (touches && touches.length > 1) return;
|
||||
this.move = true;
|
||||
touches = touches ? event.touches[0] : {};
|
||||
if (!touches || (touches.pageX === undefined && touches.pageY === undefined)) {
|
||||
touches = {
|
||||
pageX: event.pageX,
|
||||
pageY: event.pageY
|
||||
};
|
||||
}
|
||||
const tStart = this.tStart;
|
||||
if (touches) {
|
||||
for (let i in tStart) {
|
||||
if (touches[i]) {
|
||||
tStart[i] = touches[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
swipper(touches) {
|
||||
const start = this.tStart;
|
||||
const spacing = {
|
||||
pageX: touches.pageX - start.pageX,
|
||||
pageY: touches.pageY - start.pageY
|
||||
};
|
||||
if (this.limitMove < Math.abs(spacing.pageX)) {
|
||||
spacing.pageX = -this.limitMove;
|
||||
}
|
||||
this.position = spacing;
|
||||
},
|
||||
handlerTouchmove(event) {
|
||||
if (this.forbid || !this.move) return;
|
||||
const start = this.tStart;
|
||||
let touches = event.touches ? event.touches[0] : {};
|
||||
if (!touches || (touches.pageX === undefined && touches.pageY === undefined)) {
|
||||
touches = {
|
||||
pageX: event.pageX,
|
||||
pageY: event.pageY
|
||||
};
|
||||
}
|
||||
if (touches) {
|
||||
const direction = this.swipeDirection(start.pageX, touches.pageX, start.pageY, touches.pageY);
|
||||
if (direction === 'Left' && Math.abs(this.position.pageX) !== this.limitMove) {
|
||||
this.swipper(touches);
|
||||
}
|
||||
}
|
||||
},
|
||||
handlerTouchend(event) {
|
||||
if (this.forbid || !this.move) return;
|
||||
this.move = false;
|
||||
const start = this.tStart;
|
||||
let touches = event.changedTouches ? event.changedTouches[0] : {};
|
||||
if (!touches || (touches.pageX === undefined && touches.pageY === undefined)) {
|
||||
touches = {
|
||||
pageX: event.pageX,
|
||||
pageY: event.pageY
|
||||
};
|
||||
}
|
||||
if (touches) {
|
||||
const direction = this.swipeDirection(start.pageX, touches.pageX, start.pageY, touches.pageY);
|
||||
const spacing = {
|
||||
pageX: touches.pageX - start.pageX,
|
||||
pageY: touches.pageY - start.pageY
|
||||
};
|
||||
if (Math.abs(spacing.pageX) >= 40 && direction === 'Left') {
|
||||
spacing.pageX = spacing.pageX < 0 ? -this.limitMove : this.limitMove;
|
||||
this.isShowBtn = true;
|
||||
} else {
|
||||
spacing.pageX = 0;
|
||||
}
|
||||
if (spacing.pageX== 0) {
|
||||
this.isShowBtn = false;
|
||||
}
|
||||
this.position = spacing;
|
||||
|
||||
}
|
||||
},
|
||||
handlerButton(event) {
|
||||
if (this.closable) {
|
||||
this.closeButtonGroup();
|
||||
}
|
||||
const dataset = event.currentTarget.dataset;
|
||||
this.$emit('click', {
|
||||
index: Number(dataset.index),
|
||||
item: this.params
|
||||
});
|
||||
},
|
||||
closeButtonGroup() {
|
||||
this.position = {
|
||||
pageX: 0,
|
||||
pageY: 0
|
||||
};
|
||||
this.isShowBtn = false;
|
||||
},
|
||||
//控制自定义按钮菜单
|
||||
handlerParentButton(event) {
|
||||
if (this.closable) {
|
||||
this.closeButtonGroup();
|
||||
}
|
||||
},
|
||||
manualSwitch(isOpen) {
|
||||
let x = 0;
|
||||
if (isOpen) {
|
||||
if (this.actions.length === 0) {
|
||||
x = this.operateWidth;
|
||||
} else {
|
||||
let width = 0;
|
||||
this.actions.forEach(item => {
|
||||
width += item.width;
|
||||
});
|
||||
x = width;
|
||||
}
|
||||
}
|
||||
this.position = {
|
||||
pageX: -x,
|
||||
pageY: 0
|
||||
};
|
||||
},
|
||||
px(num) {
|
||||
return uni.upx2px(num) + 'px';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tui-swipeout-wrap {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.swipe-action-show {
|
||||
position: relative;
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
.tui-swipeout-item {
|
||||
width: 100%;
|
||||
/* padding: 15px 20px; */
|
||||
box-sizing: border-box;
|
||||
transition: transform 0.2s ease;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tui-swipeout-content {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tui-swipeout-button-right-group {
|
||||
position: absolute;
|
||||
right: -100%;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tui-swipeout-button-right-item {
|
||||
height: 100%;
|
||||
float: left;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.swipe-action_mask {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
position: fixed;
|
||||
z-index: 997;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
397
components/uniNoticeBar/uni-notice-bar.vue
Normal file
397
components/uniNoticeBar/uni-notice-bar.vue
Normal file
@@ -0,0 +1,397 @@
|
||||
<template>
|
||||
<view v-if="show" class="uni-noticebar" :style="'background-color:'+backgroundColor+';width:'+(100% - prConfig*2)*2+'rpx;'" @click="onClick">
|
||||
<!-- <uni-icons v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon" type="sound"
|
||||
:color="color" size="22" /> -->
|
||||
<view ref="textBox" class="uni-noticebar__content-wrapper"
|
||||
:class="{'uni-noticebar__content-wrapper--scrollable':scrollable, 'uni-noticebar__content-wrapper--single':!scrollable && (single || moreText)}">
|
||||
<view :id="elIdBox" class="uni-noticebar__content"
|
||||
:class="{'uni-noticebar__content--scrollable':scrollable, 'uni-noticebar__content--single':!scrollable && (single || moreText)}">
|
||||
<text :id="elId" ref="animationEle" class="uni-noticebar__content-text"
|
||||
:class="{'uni-noticebar__content-text--scrollable':scrollable,'uni-noticebar__content-text--single':!scrollable && (single || showGetMore)}"
|
||||
:style="{color:color, width:wrapWidth+'px', 'animationDuration': animationDuration, '-webkit-animationDuration': animationDuration ,animationPlayState: webviewHide?'paused':animationPlayState,'-webkit-animationPlayState':webviewHide?'paused':animationPlayState, animationDelay: animationDelay, '-webkit-animationDelay':animationDelay}">{{text}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="showGetMore === true || showGetMore === 'true'" class="uni-noticebar__more uni-cursor-point"
|
||||
@click="clickMore">
|
||||
<text v-if="moreText.length > 0" :style="{ color: moreColor }" class="uni-noticebar__more-text">{{ moreText }}</text>
|
||||
<!-- <uni-icons v-else type="right" :color="moreColor" size="16" /> -->
|
||||
</view>
|
||||
<view class="uni-noticebar-close uni-cursor-point" v-if="(showClose === true || showClose === 'true') && (showGetMore === false || showGetMore === 'false')">
|
||||
<!-- <uni-icons
|
||||
type="closeempty" :color="color" size="16" @click="close" /> -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef APP-NVUE
|
||||
const dom = weex.requireModule('dom');
|
||||
const animation = weex.requireModule('animation');
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* NoticeBar 自定义导航栏
|
||||
* @description 通告栏组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=30
|
||||
* @property {Number} speed 文字滚动的速度,默认100px/秒
|
||||
* @property {String} text 显示文字
|
||||
* @property {String} backgroundColor 背景颜色
|
||||
* @property {String} color 文字颜色
|
||||
* @property {String} moreColor 查看更多文字的颜色
|
||||
* @property {String} moreText 设置“查看更多”的文本
|
||||
* @property {Boolean} single = [true|false] 是否单行
|
||||
* @property {Boolean} scrollable = [true|false] 是否滚动,为true时,NoticeBar为单行
|
||||
* @property {Boolean} showIcon = [true|false] 是否显示左侧喇叭图标
|
||||
* @property {Boolean} showClose = [true|false] 是否显示左侧关闭按钮
|
||||
* @property {Boolean} showGetMore = [true|false] 是否显示右侧查看更多图标,为true时,NoticeBar为单行
|
||||
* @event {Function} click 点击 NoticeBar 触发事件
|
||||
* @event {Function} close 关闭 NoticeBar 触发事件
|
||||
* @event {Function} getmore 点击”查看更多“时触发事件
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'UniNoticeBar',
|
||||
emits: ['click', 'getmore', 'close'],
|
||||
props: {
|
||||
prConfig: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
moreText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: '#FFF9EA'
|
||||
},
|
||||
speed: {
|
||||
// 默认1s滚动100px
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#FF9A43'
|
||||
},
|
||||
moreColor: {
|
||||
type: String,
|
||||
default: '#FF9A43'
|
||||
},
|
||||
single: {
|
||||
// 是否单行
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
scrollable: {
|
||||
// 是否滚动,添加后控制单行效果取消
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showIcon: {
|
||||
// 是否显示左侧icon
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showGetMore: {
|
||||
// 是否显示右侧查看更多
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
showClose: {
|
||||
// 是否显示左侧关闭按钮
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
|
||||
const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
|
||||
return {
|
||||
textWidth: 0,
|
||||
boxWidth: 0,
|
||||
wrapWidth: '',
|
||||
webviewHide: false,
|
||||
// #ifdef APP-NVUE
|
||||
stopAnimation: false,
|
||||
// #endif
|
||||
elId: elId,
|
||||
elIdBox: elIdBox,
|
||||
show: true,
|
||||
animationDuration: 'none',
|
||||
animationPlayState: 'paused',
|
||||
animationDelay: '0s'
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef APP-PLUS
|
||||
var pages = getCurrentPages();
|
||||
var page = pages[pages.length - 1];
|
||||
var currentWebview = page.$getAppWebview();
|
||||
currentWebview.addEventListener('hide', () => {
|
||||
this.webviewHide = true
|
||||
})
|
||||
currentWebview.addEventListener('show', () => {
|
||||
this.webviewHide = false
|
||||
})
|
||||
// #endif
|
||||
this.$nextTick(() => {
|
||||
this.initSize()
|
||||
})
|
||||
},
|
||||
// #ifdef APP-NVUE
|
||||
beforeDestroy() {
|
||||
this.stopAnimation = true
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
initSize() {
|
||||
if (this.scrollable) {
|
||||
// #ifndef APP-NVUE
|
||||
let query = [],
|
||||
boxWidth = 0,
|
||||
textWidth = 0;
|
||||
let textQuery = new Promise((resolve, reject) => {
|
||||
uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
.select(`#${this.elId}`)
|
||||
.boundingClientRect()
|
||||
.exec(ret => {
|
||||
this.textWidth = ret[0].width
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
let boxQuery = new Promise((resolve, reject) => {
|
||||
uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
.select(`#${this.elIdBox}`)
|
||||
.boundingClientRect()
|
||||
.exec(ret => {
|
||||
this.boxWidth = ret[0].width
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
query.push(textQuery)
|
||||
query.push(boxQuery)
|
||||
Promise.all(query).then(() => {
|
||||
this.animationDuration = `${this.textWidth / this.speed}s`
|
||||
this.animationDelay = `-${this.boxWidth / this.speed}s`
|
||||
setTimeout(() => {
|
||||
this.animationPlayState = 'running'
|
||||
}, 1000)
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
dom.getComponentRect(this.$refs['animationEle'], (res) => {
|
||||
let winWidth = uni.getWindowInfo().windowWidth
|
||||
this.textWidth = res.size.width
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateX(-${winWidth}px)`
|
||||
},
|
||||
duration: 0,
|
||||
timingFunction: 'linear',
|
||||
delay: 0
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateX(-${this.textWidth}px)`
|
||||
},
|
||||
timingFunction: 'linear',
|
||||
duration: (this.textWidth - winWidth) / this.speed * 1000,
|
||||
delay: 1000
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
this.loopAnimation()
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
// #ifdef APP-NVUE
|
||||
if (!this.scrollable && (this.single || this.moreText)) {
|
||||
dom.getComponentRect(this.$refs['textBox'], (res) => {
|
||||
this.wrapWidth = res.size.width
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
loopAnimation() {
|
||||
// #ifdef APP-NVUE
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateX(0px)`
|
||||
},
|
||||
duration: 0
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
animation.transition(this.$refs['animationEle'], {
|
||||
styles: {
|
||||
transform: `translateX(-${this.textWidth}px)`
|
||||
},
|
||||
duration: this.textWidth / this.speed * 1000,
|
||||
timingFunction: 'linear',
|
||||
delay: 0
|
||||
}, () => {
|
||||
if (!this.stopAnimation) {
|
||||
this.loopAnimation()
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
clickMore() {
|
||||
this.$emit('getmore')
|
||||
},
|
||||
close() {
|
||||
this.show = false;
|
||||
this.$emit('close')
|
||||
},
|
||||
onClick() {
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-noticebar {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-cursor-point {
|
||||
/* #ifdef H5 */
|
||||
cursor: pointer;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar-close {
|
||||
margin-left: 8px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.uni-noticebar-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.uni-noticebar__content-wrapper {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-noticebar__content-wrapper--single {
|
||||
/* #ifndef APP-NVUE */
|
||||
line-height: 18px;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content-wrapper--single,
|
||||
.uni-noticebar__content-wrapper--scrollable {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-noticebar__content-wrapper--scrollable {
|
||||
position: relative;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.uni-noticebar__content--scrollable {
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 0;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
flex: 1;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content--single {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
flex: none;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content-text {
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
/* #ifndef APP-NVUE */
|
||||
word-break: break-all;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__content-text--single {
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 1;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
/* #endif */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.uni-noticebar__content-text--scrollable {
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 1;
|
||||
padding-left: 750rpx;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
padding-left: 100%;
|
||||
animation: notice 10s 0s linear infinite both;
|
||||
animation-play-state: paused;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-noticebar__more {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: inline-flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.uni-noticebar__more-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@keyframes notice {
|
||||
100% {
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
427
components/update/app-update.vue
Normal file
427
components/update/app-update.vue
Normal file
@@ -0,0 +1,427 @@
|
||||
<template>
|
||||
<view class="wrap" v-if="popup_show">
|
||||
<view class="popup-bg" :style="getHeight">
|
||||
<view class="popup-content" :class="{ 'popup-content-show': popup_show }">
|
||||
<view class="update-wrap">
|
||||
<image src="./images/img.png" class="top-img"></image>
|
||||
<view class="content">
|
||||
<text class="title">发现新版本{{ update_info.version }}</text>
|
||||
<!-- 升级描述 -->
|
||||
<view class="title-sub" v-html="update_info.info"></view>
|
||||
<!-- 升级按钮 -->
|
||||
<button class="btn" v-if="downstatus < 1" @click="nowUpdate()">
|
||||
立即升级
|
||||
</button>
|
||||
<!-- 下载进度 -->
|
||||
<view class="sche-wrap" v-else>
|
||||
<!-- 更新包下载中 -->
|
||||
<view class="sche-bg">
|
||||
<view class="sche-bg-jindu" :style="lengthWidth"></view>
|
||||
</view>
|
||||
<text class="down-text">下载进度:{{ (downSize / 1024 / 1024).toFixed(2) }}M/{{
|
||||
(fileSize / 1024 / 1024).toFixed(2)
|
||||
}}M</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<image src="./images/close.png" class="close-ioc" @click="closeUpdate()"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let vm;
|
||||
import {
|
||||
getUpdateInfo
|
||||
} from '@/api/public.js'
|
||||
|
||||
export default {
|
||||
name: "appUpdate",
|
||||
//@是否强制更新
|
||||
props: {
|
||||
tabbar: {
|
||||
type: Boolean,
|
||||
default: false, //是否有原生tabbar组件
|
||||
},
|
||||
getVer: {
|
||||
type: Boolean,
|
||||
default: false, //是否有原生tabbar组件
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
popup_show: false, //弹窗是否显示
|
||||
platform: "", //ios or android
|
||||
version: "1.0.0", //当前软件版本
|
||||
need_update: false, // 是否更新
|
||||
downing: false, //是否下载中
|
||||
downstatus: 0, //0未下载 1已开始 2已连接到资源 3已接收到数据 4下载完成
|
||||
update_info: {
|
||||
os: "", //设备系统
|
||||
version: "", //最新版本
|
||||
info: "", //升级说明
|
||||
},
|
||||
fileSize: 0, //文件大小
|
||||
downSize: 0, //已下载大小
|
||||
viewObj: null, //原生遮罩view
|
||||
};
|
||||
},
|
||||
created() {
|
||||
vm = this;
|
||||
if (!this.getVer) this.update()
|
||||
},
|
||||
computed: {
|
||||
// 下载进度计算
|
||||
lengthWidth: function() {
|
||||
let w = (this.downSize / this.fileSize) * 100;
|
||||
if (!w) {
|
||||
w = 0;
|
||||
} else {
|
||||
w = w.toFixed(2);
|
||||
}
|
||||
return {
|
||||
width: w + "%", //return 宽度半分比
|
||||
};
|
||||
},
|
||||
getHeight() {
|
||||
let bottom = 0;
|
||||
if (this.tabbar) {
|
||||
bottom = 50;
|
||||
}
|
||||
return {
|
||||
bottom: bottom + "px",
|
||||
height: "auto",
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 检查更新
|
||||
update() {
|
||||
// #ifdef APP-PLUS
|
||||
// 获取手机系统信息
|
||||
uni.getSystemInfo({
|
||||
success: function(res) {
|
||||
vm.platform = res.platform; //ios or android
|
||||
console.log("手机系统信息", vm.platform);
|
||||
},
|
||||
});
|
||||
|
||||
// 获取版本号
|
||||
plus.runtime.getProperty(plus.runtime.appid, function(inf) {
|
||||
vm.version = inf.version;
|
||||
});
|
||||
console.log("当前版本", vm.version);
|
||||
this.getUpdateInfo(); //获取更新信息
|
||||
// #endif
|
||||
},
|
||||
|
||||
// 获取线上版本信息
|
||||
getUpdateInfo() {
|
||||
//向后台发起请求,获取最新版本号
|
||||
getUpdateInfo(this.platform === "ios" ? 2 : 1)
|
||||
.then((res) => {
|
||||
if(Array.isArray(res.data)){
|
||||
return this.$emit('isNew')
|
||||
}
|
||||
const tagDate = uni.getStorageSync('app_update_time') || '',
|
||||
nowDate = new Date().toLocaleDateString();
|
||||
if (tagDate !== nowDate && !this.getVer) {
|
||||
uni.setStorageSync('app_update_time', new Date().toLocaleDateString());
|
||||
} else if ((tagDate !== nowDate) && this.getVer) {
|
||||
if (!res.data.is_force) return
|
||||
} else if (tagDate == nowDate && !this.getVer && !res.data.is_force) {
|
||||
return
|
||||
}
|
||||
// 这里的返回的数据跟后台约定
|
||||
let data = res.data;
|
||||
// 循环获取当前设备对应的更新数据
|
||||
vm.update_info = data;
|
||||
if (!vm.update_info.platform) {
|
||||
// 后台未配置当前系统的升级数据
|
||||
} else {
|
||||
vm.checkUpdate(); ///检查是否更新
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
vm.popup_show = false
|
||||
});
|
||||
},
|
||||
// 检查是否更新
|
||||
checkUpdate() {
|
||||
vm.need_update = vm.compareVersion(vm.version, vm.update_info.version); // 检查是否需要升级
|
||||
if (vm.need_update) {
|
||||
vm.popup_show = true; //线上版本号大于当前安装的版本号 显示升级框
|
||||
if (vm.tabbar) {
|
||||
//页面是否有原生tabbar组件
|
||||
// 创建原生view用来遮罩tabbar的点击事件 (如果是没有用原生的tabbar这一步可以取消)
|
||||
vm.viewObj = new plus.nativeObj.View("viewObj", {
|
||||
bottom: "0px",
|
||||
left: "0px",
|
||||
height: "50px",
|
||||
width: "100%",
|
||||
backgroundColor: "rgba(0,0,0,.6)",
|
||||
});
|
||||
vm.viewObj.show(); //显示原生遮罩
|
||||
}
|
||||
} else {
|
||||
this.$emit('isNew')
|
||||
}
|
||||
},
|
||||
|
||||
// 取消更新
|
||||
closeUpdate() {
|
||||
if (vm.update_info.is_force) {
|
||||
// 强制更新,取消退出app
|
||||
this.platform == "android" ?
|
||||
plus.runtime.quit() :
|
||||
plus.ios
|
||||
.import("UIApplication")
|
||||
.sharedApplication()
|
||||
.performSelector("exit");
|
||||
} else {
|
||||
vm.popup_show = false; //关闭升级弹窗
|
||||
if (vm.viewObj) vm.viewObj.hide(); //隐藏原生遮罩
|
||||
}
|
||||
},
|
||||
// 立即更新
|
||||
nowUpdate() {
|
||||
if (vm.downing) return false; //如果正在下载就停止操作
|
||||
vm.downing = true; //状态改变 正在下载中
|
||||
|
||||
if (/\.apk$/.test(vm.update_info.url)) {
|
||||
// 如果是apk地址
|
||||
vm.download_wgt(); // 安装包/升级包更新
|
||||
} else if (/\.wgt$/.test(vm.update_info.url)) {
|
||||
// 如果是更新包
|
||||
vm.download_wgt(); // 安装包/升级包更新
|
||||
} else {
|
||||
plus.runtime.openURL(vm.update_info.url, function() {
|
||||
//调用外部浏览器打开更新地址
|
||||
plus.nativeUI.toast("打开错误");
|
||||
});
|
||||
}
|
||||
},
|
||||
// 下载升级资源包
|
||||
download_wgt() {
|
||||
plus.nativeUI.showWaiting("下载更新文件..."); //下载更新文件...
|
||||
let options = {
|
||||
method: "get",
|
||||
};
|
||||
let dtask = plus.downloader.createDownload(
|
||||
vm.update_info.url,
|
||||
options,
|
||||
function(d, status) {}
|
||||
);
|
||||
|
||||
dtask.addEventListener("statechanged", function(task, status) {
|
||||
if (status === null) {} else if (status == 200) {
|
||||
//在这里打印会不停的执行,请注意,正式上线切记不要在这里打印东西///////////////////////////////////////////////////
|
||||
vm.downstatus = task.state;
|
||||
switch (task.state) {
|
||||
case 3: // 已接收到数据
|
||||
vm.downSize = task.downloadedSize;
|
||||
if (task.totalSize) {
|
||||
vm.fileSize = task.totalSize; //服务器须返回正确的content-length才会有长度
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
vm.installWgt(task.filename); // 安装wgt包
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
plus.nativeUI.closeWaiting();
|
||||
plus.nativeUI.toast("下载出错");
|
||||
vm.downing = false;
|
||||
vm.downstatus = 0;
|
||||
}
|
||||
});
|
||||
dtask.start();
|
||||
},
|
||||
|
||||
// 安装文件
|
||||
installWgt(path) {
|
||||
plus.nativeUI.showWaiting("安装更新文件..."); //安装更新文件...
|
||||
plus.runtime.install(
|
||||
path, {},
|
||||
function() {
|
||||
plus.nativeUI.closeWaiting();
|
||||
// 应用资源下载完成!
|
||||
plus.nativeUI.alert("应用资源下载完成!", function() {
|
||||
plus.runtime.restart();
|
||||
});
|
||||
},
|
||||
|
||||
function(e) {
|
||||
plus.nativeUI.closeWaiting();
|
||||
// 安装更新文件失败
|
||||
plus.nativeUI.alert("安装更新文件失败[" + e.code + "]:" + e.message);
|
||||
}
|
||||
);
|
||||
},
|
||||
// 对比版本号
|
||||
compareVersion(ov, nv) {
|
||||
if (!ov || !nv || ov == "" || nv == "") {
|
||||
return false;
|
||||
}
|
||||
let b = false,
|
||||
ova = ov.split(".", 4),
|
||||
nva = nv.split(".", 4);
|
||||
for (let i = 0; i < ova.length && i < nva.length; i++) {
|
||||
let so = ova[i],
|
||||
no = parseInt(so),
|
||||
sn = nva[i],
|
||||
nn = parseInt(sn);
|
||||
if (nn > no || sn.length > so.length) {
|
||||
return true;
|
||||
} else if (nn < no) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (nva.length > ova.length && 0 == nv.indexOf(ov)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.popup-bg {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0rpx;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 750rpx;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.popup-content-show {
|
||||
animation: mymove 500ms;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
@keyframes mymove {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
/*开始为原始大小*/
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.update-wrap {
|
||||
width: 580rpx;
|
||||
border-radius: 18rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #ffffff;
|
||||
padding: 170rpx 30rpx 0;
|
||||
|
||||
.top-img {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 256rpx;
|
||||
top: -128rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 40rpx;
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #6526f3;
|
||||
}
|
||||
|
||||
.title-sub {
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 460rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 30rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 100px;
|
||||
background-color: #6526f3;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.close-ioc {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.sche-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 10rpx 50rpx 0;
|
||||
|
||||
.sche-wrap-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.sche-bg {
|
||||
position: relative;
|
||||
background-color: #cccccc;
|
||||
height: 30rpx;
|
||||
border-radius: 100px;
|
||||
width: 480rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.sche-bg-jindu {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 30rpx;
|
||||
min-width: 40rpx;
|
||||
border-radius: 100px;
|
||||
background: url(images/round.png) #5775e7 center right 4rpx no-repeat;
|
||||
background-size: 26rpx 26rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.down-text {
|
||||
font-size: 24rpx;
|
||||
color: #5674e5;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
BIN
components/update/images/close.png
Normal file
BIN
components/update/images/close.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
components/update/images/img.png
Normal file
BIN
components/update/images/img.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
BIN
components/update/images/round.png
Normal file
BIN
components/update/images/round.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
174
components/userEvaluation/index.vue
Normal file
174
components/userEvaluation/index.vue
Normal file
@@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<!-- 评价列表 -->
|
||||
<view :style="colorStyle">
|
||||
<scroll-view ref="scroll" scroll-x="true" class="scroll w-690 mt-24 pl-20" show-scrollbar="true" @scroll="scroll">
|
||||
<view id="scrollBox" ref="scrollBox" class="scrll-box">
|
||||
<view class="inline-block mr-20" v-for="item in reply" :key="item.id" @click.stop="details(item)">
|
||||
<view class="h-158 rd-16rpx bg--w111-f5f5f5 flex justify-between">
|
||||
<view class="flex-1 p-24">
|
||||
<view class="flex-y-center">
|
||||
<view class="w-64 h-64 rd-32rpx relative" :class="{'svip-border': item.vip_status}">
|
||||
<image :src="item.avatar" class="w-full h-full rd-32rpx"></image>
|
||||
<image class="vip-badge" src="@/static/img/svip_badge.png" v-show="item.vip_status"></image>
|
||||
</view>
|
||||
<view class="flex-col pl-16">
|
||||
<view class="flex-y-center">
|
||||
<text class="text--w111-333 fs-24">{{ item.nickname }}</text>
|
||||
<view class="vip flex-center" v-if="item.level_name">
|
||||
<text class="iconfont icon-huiyuandengji"></text>
|
||||
V{{item.level_name}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex">
|
||||
<text class="iconfont icon-ic_star1 fs-18 text-primary-con" v-for="star in Number(item.star)" :key="star"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="w-324 mt-12 text--w111-333 fs-24 white-nowrap line1">{{ item.comment }}</view>
|
||||
</view>
|
||||
<image v-if="item.pics.length" class="w-124 h-124 rd-12rpx block mt-16 mr-16" :src="item.pics[0]" mode="aspectFill"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="flex-center mt-24" v-if="reply.length > 1">
|
||||
<view class="w-64 h-6 rd-3px bg--w111-eee scrpll-l">
|
||||
<view class="w-32 h-6 rd-3px scrpll-line" :style="{ left: srollLeft + '%' }"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import colors from "@/mixins/color";
|
||||
import { getReplyPraise, getUnReplyPraise } from '@/api/store.js';
|
||||
import { toLogin } from '../../libs/login';
|
||||
export default {
|
||||
computed: mapGetters(['isLogin']),
|
||||
props: {
|
||||
reply: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
fromTo: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
srollLeft: 0, // 距离左边
|
||||
srollBoxWidth: 0, //内部宽度
|
||||
boxWidth: 0 //容器宽度
|
||||
};
|
||||
},
|
||||
mixins: [colors],
|
||||
mounted() {
|
||||
this.$nextTick((e) => {
|
||||
this.srollLeft = 0;
|
||||
const query = wx.createSelectorQuery().in(this);
|
||||
query
|
||||
.select('.scrll-box')
|
||||
.boundingClientRect((res) => {
|
||||
this.srollBoxWidth = res.width;
|
||||
})
|
||||
.exec();
|
||||
query
|
||||
.select('.scroll')
|
||||
.boundingClientRect((res) => {
|
||||
this.boxWidth = res.width - 10;
|
||||
})
|
||||
.exec();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
scroll(e) {
|
||||
this.srollLeft = ((e.detail.scrollLeft / (this.srollBoxWidth - this.boxWidth)) * 100).toFixed(0) / 2;
|
||||
},
|
||||
details(item) {
|
||||
if (this.isLogin) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/goods/goods_comment_con/comment_con?id=' + item.id
|
||||
});
|
||||
} else {
|
||||
this.$emit('changeLogin');
|
||||
}
|
||||
},
|
||||
getpreviewImage: function (indexw, indexn) {
|
||||
uni.previewImage({
|
||||
urls: this.reply[indexw].pics,
|
||||
current: this.reply[indexw].pics[indexn]
|
||||
});
|
||||
},
|
||||
praise(item, indexw) {
|
||||
if (this.isLogin) {
|
||||
if (item.is_praise) {
|
||||
getUnReplyPraise(item.id).then((res) => {
|
||||
item.is_praise = !item.is_praise;
|
||||
item.praise = item.praise - 1;
|
||||
this.$emit('replyFun', this.reply);
|
||||
return this.$util.Tips({
|
||||
title: res.msg
|
||||
});
|
||||
});
|
||||
} else {
|
||||
getReplyPraise(item.id).then((res) => {
|
||||
item.is_praise = !item.is_praise;
|
||||
item.praise = item.praise + 1;
|
||||
this.$emit('replyFun', this.reply);
|
||||
return this.$util.Tips({
|
||||
title: res.msg
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
toLogin();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.scrll-box {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
width: max-content;
|
||||
}
|
||||
.scrpll-l {
|
||||
position: relative;
|
||||
}
|
||||
.scrpll-line {
|
||||
position: absolute;
|
||||
background-color: var(--view-theme);
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.text-primary-con {
|
||||
color: var(--view-theme);
|
||||
}
|
||||
.vip{
|
||||
width: 64rpx;
|
||||
height: 26rpx;
|
||||
background: #FEF0D9;
|
||||
border: 1px solid #FACC7D;
|
||||
border-radius: 50rpx;
|
||||
font-size: 18rpx;
|
||||
font-weight: 500;
|
||||
color: #DFA541;
|
||||
margin-left: 10rpx;
|
||||
.iconfont {
|
||||
font-size: 16rpx;
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
}
|
||||
.svip-border{
|
||||
border: 2rpx solid #F1BB0D;
|
||||
}
|
||||
.vip-badge{
|
||||
position: absolute;
|
||||
top: -14rpx;
|
||||
right: -8rpx;
|
||||
width: 32rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
</style>
|
||||
160
components/weixinTip/index.vue
Normal file
160
components/weixinTip/index.vue
Normal file
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="tips-box" :style="[fixedTop]" v-if="showTip">
|
||||
<view class="tips-content" :style="[contentStyle]" @click.stop="hideTip">
|
||||
<view class="span">
|
||||
<text>{{ tips }}</text>
|
||||
<text class="iconfont icon-ic_close2"></text>
|
||||
</view>
|
||||
<view class="arrow" :style="[addStyle]"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showTip: false,
|
||||
marginRight: '10px',
|
||||
fixedRight: 52
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef MP
|
||||
if (wx.canIUse('checkIsAddedToMyMiniProgram')) {
|
||||
this.checkIsAddedToMyMiniProgram();
|
||||
} else {
|
||||
this.showTip = true;
|
||||
setTimeout(() => {
|
||||
this.hideTip()
|
||||
}, this.duration * 1000);
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
props: {
|
||||
tips: {
|
||||
type: String,
|
||||
default: '点击添加到我的小程序'
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#FFFFFF'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkIsAddedToMyMiniProgram() {
|
||||
try {
|
||||
wx.checkIsAddedToMyMiniProgram({
|
||||
success: (res) => {
|
||||
if (res.added) {
|
||||
this.showTip = false;
|
||||
} else {
|
||||
this.showTip = true;
|
||||
setTimeout(() => {
|
||||
this.hideTip()
|
||||
}, this.duration * 1000);
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
this.showTip = true;
|
||||
setTimeout(() => {
|
||||
this.hideTip()
|
||||
}, this.duration * 1000);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('error: ', error);
|
||||
}
|
||||
},
|
||||
hideTip() {
|
||||
// #ifdef MP
|
||||
this.showTip = false;
|
||||
this.$emit('change');
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
contentStyle() {
|
||||
return {
|
||||
backgroundColor: this.color,
|
||||
marginRight: this.marginRight
|
||||
};
|
||||
},
|
||||
fixedTop() {
|
||||
let res = wx.getMenuButtonBoundingClientRect();
|
||||
let sysHeight = wx.getSystemInfoSync().statusBarHeight;
|
||||
return {
|
||||
top: sysHeight + res.height + 8 + 'px'
|
||||
};
|
||||
},
|
||||
addStyle() {
|
||||
return {
|
||||
'border-color': 'transparent transparent ' + this.color + ' transparent',
|
||||
right: this.fixedRight + 'px'
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tips-box {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
z-index: 99999;
|
||||
opacity: 0.8;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-end;
|
||||
flex-direction: column;
|
||||
width: 600rpx;
|
||||
animation: tips 1s linear infinite;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
border-width: 0;
|
||||
margin-top: 20rpx;
|
||||
position: relative;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 18rpx 20rpx;
|
||||
}
|
||||
|
||||
.span {
|
||||
color: #333333;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
.icon-ic_close2{
|
||||
color: #aaa;
|
||||
font-size: 24rpx;
|
||||
padding-left: 8rpx;
|
||||
}
|
||||
.arrow {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: -38rpx;
|
||||
border-width: 20rpx;
|
||||
border-style: solid;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@keyframes tips {
|
||||
0% {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
923
components/zb-code/qrcode.js
Normal file
923
components/zb-code/qrcode.js
Normal file
@@ -0,0 +1,923 @@
|
||||
|
||||
let QRCode={};
|
||||
(function(){
|
||||
function unicodeFormat8(code){
|
||||
var c0,c1,c2;
|
||||
if(code<128){
|
||||
return[code];
|
||||
}else if(code<2048){
|
||||
c0=192+(code>>6);
|
||||
c1=128+(code&63);
|
||||
return[c0,c1];
|
||||
}else{
|
||||
c0=224+(code>>12);
|
||||
c1=128+(code>>6&63);
|
||||
c2=128+(code&63);
|
||||
return[c0,c1,c2];
|
||||
}
|
||||
}
|
||||
function getUTF8Bytes(string){
|
||||
var utf8codes=[];
|
||||
for(var i=0;i<string.length;i++){
|
||||
var code=string.charCodeAt(i);
|
||||
var utf8=unicodeFormat8(code);
|
||||
for(var j=0;j<utf8.length;j++){
|
||||
utf8codes.push(utf8[j]);
|
||||
}
|
||||
}
|
||||
return utf8codes;
|
||||
}
|
||||
function QRCodeAlg(data,twodimensionalcodeee5conversionmethod){
|
||||
this.typeNumber=-1;
|
||||
this.errorCorrectLevel=twodimensionalcodeee5conversionmethod;
|
||||
this.modules=null;
|
||||
this.moduleCount=0;
|
||||
this.dataCache=null;
|
||||
this.rsBlocks=null;
|
||||
this.totalDataCount=-1;
|
||||
this.data=data;
|
||||
this.utf8bytes=getUTF8Bytes(data);
|
||||
this.make();
|
||||
}
|
||||
QRCodeAlg.prototype={
|
||||
constructor:QRCodeAlg,
|
||||
getModuleCount:function(){
|
||||
return this.moduleCount;
|
||||
},
|
||||
make:function(){
|
||||
this.getRightType();
|
||||
this.dataCache=this.createData();
|
||||
this.createQrcode();
|
||||
},
|
||||
makeImpl:function(maskPattern){
|
||||
this.moduleCount=this.typeNumber*4+17;
|
||||
this.modules=new Array(this.moduleCount);
|
||||
for(var row=0;row<this.moduleCount;row++){
|
||||
this.modules[row]=new Array(this.moduleCount);
|
||||
}
|
||||
this.setupPositionProbePattern(0,0);
|
||||
this.setupPositionProbePattern(this.moduleCount-7,0);
|
||||
this.setupPositionProbePattern(0,this.moduleCount-7);
|
||||
this.setupPositionAdjustPattern();
|
||||
this.setupTimingPattern();
|
||||
this.setupTypeInfo(true,maskPattern);
|
||||
if(this.typeNumber>=7){
|
||||
this.setupTypeNumber(true);
|
||||
}
|
||||
this.mapData(this.dataCache,maskPattern);
|
||||
},
|
||||
setupPositionProbePattern:function(row,col){
|
||||
for(var r=-1;r<=7;r++){
|
||||
if(row+r<=-1||this.moduleCount<=row+r)continue;
|
||||
for(var c=-1;c<=7;c++){
|
||||
if(col+c<=-1||this.moduleCount<=col+c)continue;
|
||||
if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){
|
||||
this.modules[row+r][col+c]=true;
|
||||
}else{
|
||||
this.modules[row+r][col+c]=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
createQrcode:function(){
|
||||
var minLostPoint=0;
|
||||
var pattern=0;
|
||||
var bestModules=null;
|
||||
for(var i=0;i<8;i++){
|
||||
this.makeImpl(i);
|
||||
var lostPoint=QRUtil.getLostPoint(this);
|
||||
if(i==0||minLostPoint>lostPoint){
|
||||
minLostPoint=lostPoint;
|
||||
pattern=i;
|
||||
bestModules=this.modules;
|
||||
}
|
||||
}
|
||||
this.modules=bestModules;
|
||||
this.setupTypeInfo(false,pattern);
|
||||
if(this.typeNumber>=7){
|
||||
this.setupTypeNumber(false);
|
||||
}
|
||||
},
|
||||
setupTimingPattern:function(){
|
||||
for(var r=8;r<this.moduleCount-8;r++){
|
||||
if(this.modules[r][6]!=null){
|
||||
continue;
|
||||
}
|
||||
this.modules[r][6]=(r%2==0);
|
||||
if(this.modules[6][r]!=null){
|
||||
continue;
|
||||
}
|
||||
this.modules[6][r]=(r%2==0);
|
||||
}
|
||||
},
|
||||
setupPositionAdjustPattern:function(){
|
||||
var pos=QRUtil.getPatternPosition(this.typeNumber);
|
||||
for(var i=0;i<pos.length;i++){
|
||||
for(var j=0;j<pos.length;j++){
|
||||
var row=pos[i];
|
||||
var col=pos[j];
|
||||
if(this.modules[row][col]!=null){
|
||||
continue;
|
||||
}
|
||||
for(var r=-2;r<=2;r++){
|
||||
for(var c=-2;c<=2;c++){
|
||||
if(r==-2||r==2||c==-2||c==2||(r==0&&c==0)){
|
||||
this.modules[row+r][col+c]=true;
|
||||
}else{
|
||||
this.modules[row+r][col+c]=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
setupTypeNumber:function(test){
|
||||
var bits=QRUtil.getBCHTypeNumber(this.typeNumber);
|
||||
for(var i=0;i<18;i++){
|
||||
var mod=(!test&&((bits>>i)&1)==1);
|
||||
this.modules[Math.floor(i/3)][i%3+this.moduleCount-8-3]=mod;
|
||||
this.modules[i%3+this.moduleCount-8-3][Math.floor(i/3)]=mod;
|
||||
}
|
||||
},
|
||||
setupTypeInfo:function(test,maskPattern){
|
||||
var data=(QRErrorCorrectLevel[this.errorCorrectLevel]<<3)|maskPattern;
|
||||
var bits=QRUtil.getBCHTypeInfo(data);
|
||||
for(var i=0;i<15;i++){
|
||||
var mod=(!test&&((bits>>i)&1)==1);
|
||||
if(i<6){
|
||||
this.modules[i][8]=mod;
|
||||
}else if(i<8){
|
||||
this.modules[i+1][8]=mod;
|
||||
}else{
|
||||
this.modules[this.moduleCount-15+i][8]=mod;
|
||||
}
|
||||
var mod=(!test&&((bits>>i)&1)==1);
|
||||
if(i<8){
|
||||
this.modules[8][this.moduleCount-i-1]=mod;
|
||||
}else if(i<9){
|
||||
this.modules[8][15-i-1+1]=mod;
|
||||
}else{
|
||||
this.modules[8][15-i-1]=mod;
|
||||
}
|
||||
}
|
||||
this.modules[this.moduleCount-8][8]=(!test);
|
||||
},
|
||||
createData:function(){
|
||||
var buffer=new QRBitBuffer();
|
||||
var lengthBits=this.typeNumber>9?16:8;
|
||||
buffer.put(4,4);
|
||||
buffer.put(this.utf8bytes.length,lengthBits);
|
||||
for(var i=0,l=this.utf8bytes.length;i<l;i++){
|
||||
buffer.put(this.utf8bytes[i],8);
|
||||
}
|
||||
if(buffer.length+4<=this.totalDataCount*8){
|
||||
buffer.put(0,4);
|
||||
}
|
||||
while(buffer.length%8!=0){
|
||||
buffer.putBit(false);
|
||||
}
|
||||
while(true){
|
||||
if(buffer.length>=this.totalDataCount*8){
|
||||
break;
|
||||
}
|
||||
buffer.put(QRCodeAlg.PAD0,8);
|
||||
if(buffer.length>=this.totalDataCount*8){
|
||||
break;
|
||||
}
|
||||
buffer.put(QRCodeAlg.PAD1,8);
|
||||
}
|
||||
return this.createBytes(buffer);
|
||||
},
|
||||
createBytes:function(buffer){
|
||||
var offset=0;
|
||||
var maxDcCount=0;
|
||||
var maxEcCount=0;
|
||||
var length=this.rsBlock.length/3;
|
||||
var rsBlocks=new Array();
|
||||
for(var i=0;i<length;i++){
|
||||
var count=this.rsBlock[i*3+0];
|
||||
var totalCount=this.rsBlock[i*3+1];
|
||||
var dataCount=this.rsBlock[i*3+2];
|
||||
for(var j=0;j<count;j++){
|
||||
rsBlocks.push([dataCount,totalCount]);
|
||||
}
|
||||
}
|
||||
var dcdata=new Array(rsBlocks.length);
|
||||
var ecdata=new Array(rsBlocks.length);
|
||||
for(var r=0;r<rsBlocks.length;r++){
|
||||
var dcCount=rsBlocks[r][0];
|
||||
var ecCount=rsBlocks[r][1]-dcCount;
|
||||
maxDcCount=Math.max(maxDcCount,dcCount);
|
||||
maxEcCount=Math.max(maxEcCount,ecCount);
|
||||
dcdata[r]=new Array(dcCount);
|
||||
for(var i=0;i<dcdata[r].length;i++){
|
||||
dcdata[r][i]=0xff&buffer.buffer[i+offset];
|
||||
}
|
||||
offset+=dcCount;
|
||||
var rsPoly=QRUtil.getErrorCorrectPolynomial(ecCount);
|
||||
var rawPoly=new QRPolynomial(dcdata[r],rsPoly.getLength()-1);
|
||||
var modPoly=rawPoly.mod(rsPoly);
|
||||
ecdata[r]=new Array(rsPoly.getLength()-1);
|
||||
for(var i=0;i<ecdata[r].length;i++){
|
||||
var modIndex=i+modPoly.getLength()-ecdata[r].length;
|
||||
ecdata[r][i]=(modIndex>=0)?modPoly.get(modIndex):0;
|
||||
}
|
||||
}
|
||||
var data=new Array(this.totalDataCount);
|
||||
var index=0;
|
||||
for(var i=0;i<maxDcCount;i++){
|
||||
for(var r=0;r<rsBlocks.length;r++){
|
||||
if(i<dcdata[r].length){
|
||||
data[index++]=dcdata[r][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(var i=0;i<maxEcCount;i++){
|
||||
for(var r=0;r<rsBlocks.length;r++){
|
||||
if(i<ecdata[r].length){
|
||||
data[index++]=ecdata[r][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
},
|
||||
mapData:function(data,maskPattern){
|
||||
var inc=-1;
|
||||
var row=this.moduleCount-1;
|
||||
var bitIndex=7;
|
||||
var byteIndex=0;
|
||||
for(var col=this.moduleCount-1;col>0;col-=2){
|
||||
if(col==6)col--;
|
||||
while(true){
|
||||
for(var c=0;c<2;c++){
|
||||
if(this.modules[row][col-c]==null){
|
||||
var dark=false;
|
||||
if(byteIndex<data.length){
|
||||
dark=(((data[byteIndex]>>>bitIndex)&1)==1);
|
||||
}
|
||||
var mask=QRUtil.getMask(maskPattern,row,col-c);
|
||||
if(mask){
|
||||
dark=!dark;
|
||||
}
|
||||
this.modules[row][col-c]=dark;
|
||||
bitIndex--;
|
||||
if(bitIndex==-1){
|
||||
byteIndex++;
|
||||
bitIndex=7;
|
||||
}
|
||||
}
|
||||
}
|
||||
row+=inc;
|
||||
if(row<0||this.moduleCount<=row){
|
||||
row-=inc;
|
||||
inc=-inc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
QRCodeAlg.PAD0=0xEC;
|
||||
QRCodeAlg.PAD1=0x11;
|
||||
var QRErrorCorrectLevel=[1,0,3,2];
|
||||
var QRMaskPattern={
|
||||
PATTERN000:0,
|
||||
PATTERN001:1,
|
||||
PATTERN010:2,
|
||||
PATTERN011:3,
|
||||
PATTERN100:4,
|
||||
PATTERN101:5,
|
||||
PATTERN110:6,
|
||||
PATTERN111:7
|
||||
};
|
||||
var QRUtil={
|
||||
PATTERN_POSITION_TABLE:[
|
||||
[],
|
||||
[6,18],
|
||||
[6,22],
|
||||
[6,26],
|
||||
[6,30],
|
||||
[6,34],
|
||||
[6,22,38],
|
||||
[6,24,42],
|
||||
[6,26,46],
|
||||
[6,28,50],
|
||||
[6,30,54],
|
||||
[6,32,58],
|
||||
[6,34,62],
|
||||
[6,26,46,66],
|
||||
[6,26,48,70],
|
||||
[6,26,50,74],
|
||||
[6,30,54,78],
|
||||
[6,30,56,82],
|
||||
[6,30,58,86],
|
||||
[6,34,62,90],
|
||||
[6,28,50,72,94],
|
||||
[6,26,50,74,98],
|
||||
[6,30,54,78,102],
|
||||
[6,28,54,80,106],
|
||||
[6,32,58,84,110],
|
||||
[6,30,58,86,114],
|
||||
[6,34,62,90,118],
|
||||
[6,26,50,74,98,122],
|
||||
[6,30,54,78,102,126],
|
||||
[6,26,52,78,104,130],
|
||||
[6,30,56,82,108,134],
|
||||
[6,34,60,86,112,138],
|
||||
[6,30,58,86,114,142],
|
||||
[6,34,62,90,118,146],
|
||||
[6,30,54,78,102,126,150],
|
||||
[6,24,50,76,102,128,154],
|
||||
[6,28,54,80,106,132,158],
|
||||
[6,32,58,84,110,136,162],
|
||||
[6,26,54,82,110,138,166],
|
||||
[6,30,58,86,114,142,170]
|
||||
],
|
||||
G15:(1<<10)|(1<<8)|(1<<5)|(1<<4)|(1<<2)|(1<<1)|(1<<0),
|
||||
G18:(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<5)|(1<<2)|(1<<0),
|
||||
G15_MASK:(1<<14)|(1<<12)|(1<<10)|(1<<4)|(1<<1),
|
||||
getBCHTypeInfo:function(data){
|
||||
var d=data<<10;
|
||||
while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)>=0){
|
||||
d^=(QRUtil.G15<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)));
|
||||
}
|
||||
return((data<<10)|d)^QRUtil.G15_MASK;
|
||||
},
|
||||
getBCHTypeNumber:function(data){
|
||||
var d=data<<12;
|
||||
while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)>=0){
|
||||
d^=(QRUtil.G18<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)));
|
||||
}
|
||||
return(data<<12)|d;
|
||||
},
|
||||
getBCHDigit:function(data){
|
||||
var digit=0;
|
||||
while(data!=0){
|
||||
digit++;
|
||||
data>>>=1;
|
||||
}
|
||||
return digit;
|
||||
},
|
||||
getPatternPosition:function(typeNumber){
|
||||
return QRUtil.PATTERN_POSITION_TABLE[typeNumber-1];
|
||||
},
|
||||
getMask:function(maskPattern,i,j){
|
||||
switch(maskPattern){
|
||||
case QRMaskPattern.PATTERN000:
|
||||
return(i+j)%2==0;
|
||||
case QRMaskPattern.PATTERN001:
|
||||
return i%2==0;
|
||||
case QRMaskPattern.PATTERN010:
|
||||
return j%3==0;
|
||||
case QRMaskPattern.PATTERN011:
|
||||
return(i+j)%3==0;
|
||||
case QRMaskPattern.PATTERN100:
|
||||
return(Math.floor(i/2)+Math.floor(j/3))%2==0;
|
||||
case QRMaskPattern.PATTERN101:
|
||||
return(i*j)%2+(i*j)%3==0;
|
||||
case QRMaskPattern.PATTERN110:
|
||||
return((i*j)%2+(i*j)%3)%2==0;
|
||||
case QRMaskPattern.PATTERN111:
|
||||
return((i*j)%3+(i+j)%2)%2==0;
|
||||
default:
|
||||
throw new Error("bad maskPattern:"+maskPattern);
|
||||
}
|
||||
},
|
||||
getErrorCorrectPolynomial:function(errorCorrectLength){
|
||||
var a=new QRPolynomial([1],0);
|
||||
for(var i=0;i<errorCorrectLength;i++){
|
||||
a=a.multiply(new QRPolynomial([1,QRMath.gexp(i)],0));
|
||||
}
|
||||
return a;
|
||||
},
|
||||
getLostPoint:function(qrCode){
|
||||
var moduleCount=qrCode.getModuleCount(),
|
||||
lostPoint=0,
|
||||
darkCount=0;
|
||||
for(var row=0;row<moduleCount;row++){
|
||||
var sameCount=0;
|
||||
var head=qrCode.modules[row][0];
|
||||
for(var col=0;col<moduleCount;col++){
|
||||
var current=qrCode.modules[row][col];
|
||||
if(col<moduleCount-6){
|
||||
if(current&&!qrCode.modules[row][col+1]&&qrCode.modules[row][col+2]&&qrCode.modules[row][col+3]&&qrCode.modules[row][col+4]&&!qrCode.modules[row][col+5]&&qrCode.modules[row][col+6]){
|
||||
if(col<moduleCount-10){
|
||||
if(qrCode.modules[row][col+7]&&qrCode.modules[row][col+8]&&qrCode.modules[row][col+9]&&qrCode.modules[row][col+10]){
|
||||
lostPoint+=40;
|
||||
}
|
||||
}else if(col>3){
|
||||
if(qrCode.modules[row][col-1]&&qrCode.modules[row][col-2]&&qrCode.modules[row][col-3]&&qrCode.modules[row][col-4]){
|
||||
lostPoint+=40;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if((row<moduleCount-1)&&(col<moduleCount-1)){
|
||||
var count=0;
|
||||
if(current)count++;
|
||||
if(qrCode.modules[row+1][col])count++;
|
||||
if(qrCode.modules[row][col+1])count++;
|
||||
if(qrCode.modules[row+1][col+1])count++;
|
||||
if(count==0||count==4){
|
||||
lostPoint+=3;
|
||||
}
|
||||
}
|
||||
if(head^current){
|
||||
sameCount++;
|
||||
}else{
|
||||
head=current;
|
||||
if(sameCount>=5){
|
||||
lostPoint+=(3+sameCount-5);
|
||||
}
|
||||
sameCount=1;
|
||||
}
|
||||
if(current){
|
||||
darkCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(var col=0;col<moduleCount;col++){
|
||||
var sameCount=0;
|
||||
var head=qrCode.modules[0][col];
|
||||
for(var row=0;row<moduleCount;row++){
|
||||
var current=qrCode.modules[row][col];
|
||||
if(row<moduleCount-6){
|
||||
if(current&&!qrCode.modules[row+1][col]&&qrCode.modules[row+2][col]&&qrCode.modules[row+3][col]&&qrCode.modules[row+4][col]&&!qrCode.modules[row+5][col]&&qrCode.modules[row+6][col]){
|
||||
if(row<moduleCount-10){
|
||||
if(qrCode.modules[row+7][col]&&qrCode.modules[row+8][col]&&qrCode.modules[row+9][col]&&qrCode.modules[row+10][col]){
|
||||
lostPoint+=40;
|
||||
}
|
||||
}else if(row>3){
|
||||
if(qrCode.modules[row-1][col]&&qrCode.modules[row-2][col]&&qrCode.modules[row-3][col]&&qrCode.modules[row-4][col]){
|
||||
lostPoint+=40;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(head^current){
|
||||
sameCount++;
|
||||
}else{
|
||||
head=current;
|
||||
if(sameCount>=5){
|
||||
lostPoint+=(3+sameCount-5);
|
||||
}
|
||||
sameCount=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
var ratio=Math.abs(100*darkCount/moduleCount/moduleCount-50)/5;
|
||||
lostPoint+=ratio*10;
|
||||
return lostPoint;
|
||||
}
|
||||
};
|
||||
var QRMath={
|
||||
glog:function(n){
|
||||
if(n<1){
|
||||
throw new Error("glog("+n+")");
|
||||
}
|
||||
return QRMath.LOG_TABLE[n];
|
||||
},
|
||||
gexp:function(n){
|
||||
while(n<0){
|
||||
n+=255;
|
||||
}
|
||||
while(n>=256){
|
||||
n-=255;
|
||||
}
|
||||
return QRMath.EXP_TABLE[n];
|
||||
},
|
||||
EXP_TABLE:new Array(256),
|
||||
LOG_TABLE:new Array(256)
|
||||
};
|
||||
for(var i=0;i<8;i++){
|
||||
QRMath.EXP_TABLE[i]=1<<i;
|
||||
}
|
||||
for(var i=8;i<256;i++){
|
||||
QRMath.EXP_TABLE[i]=QRMath.EXP_TABLE[i-4]^QRMath.EXP_TABLE[i-5]^QRMath.EXP_TABLE[i-6]^QRMath.EXP_TABLE[i-8];
|
||||
}
|
||||
for(var i=0;i<255;i++){
|
||||
QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]]=i;
|
||||
}
|
||||
function QRPolynomial(num,shift){
|
||||
if(num.length==undefined){
|
||||
throw new Error(num.length+"/"+shift);
|
||||
}
|
||||
var offset=0;
|
||||
while(offset<num.length&&num[offset]==0){
|
||||
offset++;
|
||||
}
|
||||
this.num=new Array(num.length-offset+shift);
|
||||
for(var i=0;i<num.length-offset;i++){
|
||||
this.num[i]=num[i+offset];
|
||||
}
|
||||
}
|
||||
QRPolynomial.prototype={
|
||||
get:function(index){
|
||||
return this.num[index];
|
||||
},
|
||||
getLength:function(){
|
||||
return this.num.length;
|
||||
},
|
||||
multiply:function(e){
|
||||
var num=new Array(this.getLength()+e.getLength()-1);
|
||||
for(var i=0;i<this.getLength();i++){
|
||||
for(var j=0;j<e.getLength();j++){
|
||||
num[i+j]^=QRMath.gexp(QRMath.glog(this.get(i))+QRMath.glog(e.get(j)));
|
||||
}
|
||||
}
|
||||
return new QRPolynomial(num,0);
|
||||
},
|
||||
mod:function(e){
|
||||
var tl=this.getLength(),
|
||||
el=e.getLength();
|
||||
if(tl-el<0){
|
||||
return this;
|
||||
}
|
||||
var num=new Array(tl);
|
||||
for(var i=0;i<tl;i++){
|
||||
num[i]=this.get(i);
|
||||
}
|
||||
while(num.length>=el){
|
||||
var ratio=QRMath.glog(num[0])-QRMath.glog(e.get(0));
|
||||
for(var i=0;i<e.getLength();i++){
|
||||
num[i]^=QRMath.gexp(QRMath.glog(e.get(i))+ratio);
|
||||
}
|
||||
while(num[0]==0){
|
||||
num.shift();
|
||||
}
|
||||
}
|
||||
return new QRPolynomial(num,0);
|
||||
}
|
||||
};
|
||||
var RS_BLOCK_TABLE=[
|
||||
[1,26,19],
|
||||
[1,26,16],
|
||||
[1,26,13],
|
||||
[1,26,9],
|
||||
[1,44,34],
|
||||
[1,44,28],
|
||||
[1,44,22],
|
||||
[1,44,16],
|
||||
[1,70,55],
|
||||
[1,70,44],
|
||||
[2,35,17],
|
||||
[2,35,13],
|
||||
[1,100,80],
|
||||
[2,50,32],
|
||||
[2,50,24],
|
||||
[4,25,9],
|
||||
[1,134,108],
|
||||
[2,67,43],
|
||||
[2,33,15,2,34,16],
|
||||
[2,33,11,2,34,12],
|
||||
[2,86,68],
|
||||
[4,43,27],
|
||||
[4,43,19],
|
||||
[4,43,15],
|
||||
[2,98,78],
|
||||
[4,49,31],
|
||||
[2,32,14,4,33,15],
|
||||
[4,39,13,1,40,14],
|
||||
[2,121,97],
|
||||
[2,60,38,2,61,39],
|
||||
[4,40,18,2,41,19],
|
||||
[4,40,14,2,41,15],
|
||||
[2,146,116],
|
||||
[3,58,36,2,59,37],
|
||||
[4,36,16,4,37,17],
|
||||
[4,36,12,4,37,13],
|
||||
[2,86,68,2,87,69],
|
||||
[4,69,43,1,70,44],
|
||||
[6,43,19,2,44,20],
|
||||
[6,43,15,2,44,16],
|
||||
[4,101,81],
|
||||
[1,80,50,4,81,51],
|
||||
[4,50,22,4,51,23],
|
||||
[3,36,12,8,37,13],
|
||||
[2,116,92,2,117,93],
|
||||
[6,58,36,2,59,37],
|
||||
[4,46,20,6,47,21],
|
||||
[7,42,14,4,43,15],
|
||||
[4,133,107],
|
||||
[8,59,37,1,60,38],
|
||||
[8,44,20,4,45,21],
|
||||
[12,33,11,4,34,12],
|
||||
[3,145,115,1,146,116],
|
||||
[4,64,40,5,65,41],
|
||||
[11,36,16,5,37,17],
|
||||
[11,36,12,5,37,13],
|
||||
[5,109,87,1,110,88],
|
||||
[5,65,41,5,66,42],
|
||||
[5,54,24,7,55,25],
|
||||
[11,36,12],
|
||||
[5,122,98,1,123,99],
|
||||
[7,73,45,3,74,46],
|
||||
[15,43,19,2,44,20],
|
||||
[3,45,15,13,46,16],
|
||||
[1,135,107,5,136,108],
|
||||
[10,74,46,1,75,47],
|
||||
[1,50,22,15,51,23],
|
||||
[2,42,14,17,43,15],
|
||||
[5,150,120,1,151,121],
|
||||
[9,69,43,4,70,44],
|
||||
[17,50,22,1,51,23],
|
||||
[2,42,14,19,43,15],
|
||||
[3,141,113,4,142,114],
|
||||
[3,70,44,11,71,45],
|
||||
[17,47,21,4,48,22],
|
||||
[9,39,13,16,40,14],
|
||||
[3,135,107,5,136,108],
|
||||
[3,67,41,13,68,42],
|
||||
[15,54,24,5,55,25],
|
||||
[15,43,15,10,44,16],
|
||||
[4,144,116,4,145,117],
|
||||
[17,68,42],
|
||||
[17,50,22,6,51,23],
|
||||
[19,46,16,6,47,17],
|
||||
[2,139,111,7,140,112],
|
||||
[17,74,46],
|
||||
[7,54,24,16,55,25],
|
||||
[34,37,13],
|
||||
[4,151,121,5,152,122],
|
||||
[4,75,47,14,76,48],
|
||||
[11,54,24,14,55,25],
|
||||
[16,45,15,14,46,16],
|
||||
[6,147,117,4,148,118],
|
||||
[6,73,45,14,74,46],
|
||||
[11,54,24,16,55,25],
|
||||
[30,46,16,2,47,17],
|
||||
[8,132,106,4,133,107],
|
||||
[8,75,47,13,76,48],
|
||||
[7,54,24,22,55,25],
|
||||
[22,45,15,13,46,16],
|
||||
[10,142,114,2,143,115],
|
||||
[19,74,46,4,75,47],
|
||||
[28,50,22,6,51,23],
|
||||
[33,46,16,4,47,17],
|
||||
[8,152,122,4,153,123],
|
||||
[22,73,45,3,74,46],
|
||||
[8,53,23,26,54,24],
|
||||
[12,45,15,28,46,16],
|
||||
[3,147,117,10,148,118],
|
||||
[3,73,45,23,74,46],
|
||||
[4,54,24,31,55,25],
|
||||
[11,45,15,31,46,16],
|
||||
[7,146,116,7,147,117],
|
||||
[21,73,45,7,74,46],
|
||||
[1,53,23,37,54,24],
|
||||
[19,45,15,26,46,16],
|
||||
[5,145,115,10,146,116],
|
||||
[19,75,47,10,76,48],
|
||||
[15,54,24,25,55,25],
|
||||
[23,45,15,25,46,16],
|
||||
[13,145,115,3,146,116],
|
||||
[2,74,46,29,75,47],
|
||||
[42,54,24,1,55,25],
|
||||
[23,45,15,28,46,16],
|
||||
[17,145,115],
|
||||
[10,74,46,23,75,47],
|
||||
[10,54,24,35,55,25],
|
||||
[19,45,15,35,46,16],
|
||||
[17,145,115,1,146,116],
|
||||
[14,74,46,21,75,47],
|
||||
[29,54,24,19,55,25],
|
||||
[11,45,15,46,46,16],
|
||||
[13,145,115,6,146,116],
|
||||
[14,74,46,23,75,47],
|
||||
[44,54,24,7,55,25],
|
||||
[59,46,16,1,47,17],
|
||||
[12,151,121,7,152,122],
|
||||
[12,75,47,26,76,48],
|
||||
[39,54,24,14,55,25],
|
||||
[22,45,15,41,46,16],
|
||||
[6,151,121,14,152,122],
|
||||
[6,75,47,34,76,48],
|
||||
[46,54,24,10,55,25],
|
||||
[2,45,15,64,46,16],
|
||||
[17,152,122,4,153,123],
|
||||
[29,74,46,14,75,47],
|
||||
[49,54,24,10,55,25],
|
||||
[24,45,15,46,46,16],
|
||||
[4,152,122,18,153,123],
|
||||
[13,74,46,32,75,47],
|
||||
[48,54,24,14,55,25],
|
||||
[42,45,15,32,46,16],
|
||||
[20,147,117,4,148,118],
|
||||
[40,75,47,7,76,48],
|
||||
[43,54,24,22,55,25],
|
||||
[10,45,15,67,46,16],
|
||||
[19,148,118,6,149,119],
|
||||
[18,75,47,31,76,48],
|
||||
[34,54,24,34,55,25],
|
||||
[20,45,15,61,46,16]
|
||||
];
|
||||
QRCodeAlg.prototype.getRightType=function(){
|
||||
for(var typeNumber=1;typeNumber<41;typeNumber++){
|
||||
var rsBlock=RS_BLOCK_TABLE[(typeNumber-1)*4+this.errorCorrectLevel];
|
||||
if(rsBlock==undefined){
|
||||
throw new Error("bad rs block @ typeNumber:"+typeNumber+"/errorCorrectLevel:"+this.errorCorrectLevel);
|
||||
}
|
||||
var length=rsBlock.length/3;
|
||||
var totalDataCount=0;
|
||||
for(var i=0;i<length;i++){
|
||||
var count=rsBlock[i*3+0];
|
||||
var dataCount=rsBlock[i*3+2];
|
||||
totalDataCount+=dataCount*count;
|
||||
}
|
||||
var lengthBytes=typeNumber>9?2:1;
|
||||
if(this.utf8bytes.length+lengthBytes<totalDataCount||typeNumber==40){
|
||||
this.typeNumber=typeNumber;
|
||||
this.rsBlock=rsBlock;
|
||||
this.totalDataCount=totalDataCount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
function QRBitBuffer(){
|
||||
this.buffer=new Array();
|
||||
this.length=0;
|
||||
}
|
||||
QRBitBuffer.prototype={
|
||||
get:function(index){
|
||||
var bufIndex=Math.floor(index/8);
|
||||
return((this.buffer[bufIndex]>>>(7-index%8))&1);
|
||||
},
|
||||
put:function(num,length){
|
||||
for(var i=0;i<length;i++){
|
||||
this.putBit(((num>>>(length-i-1))&1));
|
||||
}
|
||||
},
|
||||
putBit:function(bit){
|
||||
var bufIndex=Math.floor(this.length/8);
|
||||
if(this.buffer.length<=bufIndex){
|
||||
this.buffer.push(0);
|
||||
}
|
||||
if(bit){
|
||||
this.buffer[bufIndex]|=(0x80>>>(this.length%8));
|
||||
}
|
||||
this.length++;
|
||||
}
|
||||
};
|
||||
let qrcodeAlgObjCache=[];
|
||||
QRCode=function(opt){
|
||||
this.options={
|
||||
text:'',
|
||||
size:256,
|
||||
correctLevel:3,
|
||||
background:'#ffffff',
|
||||
foreground:'#000000',
|
||||
pdground:'#000000',
|
||||
image:'',
|
||||
imageSize:30,
|
||||
canvasId:opt.canvasId,
|
||||
context:opt.context,
|
||||
usingComponents:opt.usingComponents,
|
||||
showLoading:opt.showLoading,
|
||||
loadingText:opt.loadingText,
|
||||
};
|
||||
if(typeof opt==='string'){
|
||||
opt={
|
||||
text:opt
|
||||
};
|
||||
}
|
||||
if(opt){
|
||||
for(var i in opt){
|
||||
this.options[i]=opt[i];
|
||||
}
|
||||
}
|
||||
var qrCodeAlg=null;
|
||||
for(var i=0,l=qrcodeAlgObjCache.length;i<l;i++){
|
||||
if(qrcodeAlgObjCache[i].text==this.options.text&&qrcodeAlgObjCache[i].text.correctLevel==this.options.correctLevel){
|
||||
qrCodeAlg=qrcodeAlgObjCache[i].obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i==l){
|
||||
qrCodeAlg=new QRCodeAlg(this.options.text,this.options.correctLevel);
|
||||
qrcodeAlgObjCache.push({
|
||||
text:this.options.text,
|
||||
correctLevel:this.options.correctLevel,
|
||||
obj:qrCodeAlg
|
||||
});
|
||||
}
|
||||
let getForeGround=function(config){
|
||||
var options=config.options;
|
||||
if(options.pdground&&(
|
||||
(config.row>1&&config.row<5&&config.col>1&&config.col<5)||
|
||||
(config.row>(config.count-6)&&config.row<(config.count-2)&&config.col>1&&config.col<5)||
|
||||
(config.row>1&&config.row<5&&config.col>(config.count-6)&&config.col<(config.count-2))
|
||||
)){
|
||||
return options.pdground;
|
||||
}
|
||||
return options.foreground;
|
||||
}
|
||||
let createCanvas=function(options){
|
||||
if(options.showLoading){
|
||||
uni.showLoading({
|
||||
title:options.loadingText,
|
||||
mask:true
|
||||
});
|
||||
}
|
||||
var ctx=uni.createCanvasContext(options.canvasId,options.context);
|
||||
var count=qrCodeAlg.getModuleCount();
|
||||
var ratioSize=options.size;
|
||||
var ratioImgSize=options.imageSize;
|
||||
var tileW=(ratioSize/count).toPrecision(4);
|
||||
var tileH=(ratioSize/count).toPrecision(4);
|
||||
for(var row=0;row<count;row++){
|
||||
for(var col=0;col<count;col++){
|
||||
var w=(Math.ceil((col+1)*tileW)-Math.floor(col*tileW));
|
||||
var h=(Math.ceil((row+1)*tileW)-Math.floor(row*tileW));
|
||||
var foreground=getForeGround({
|
||||
row:row,
|
||||
col:col,
|
||||
count:count,
|
||||
options:options
|
||||
});
|
||||
ctx.setFillStyle(qrCodeAlg.modules[row][col]?foreground:options.background);
|
||||
ctx.fillRect(Math.round(col*tileW),Math.round(row*tileH),w,h);
|
||||
}
|
||||
}
|
||||
if(options.image){
|
||||
var x=Number(((ratioSize-ratioImgSize)/2).toFixed(2));
|
||||
var y=Number(((ratioSize-ratioImgSize)/2).toFixed(2));
|
||||
drawRoundedRect(ctx,x,y,ratioImgSize,ratioImgSize,2,6,true,true)
|
||||
ctx.drawImage(options.image,x,y,ratioImgSize,ratioImgSize);
|
||||
function drawRoundedRect(ctxi,x,y,width,height,r,lineWidth,fill,stroke){
|
||||
ctxi.setLineWidth(lineWidth);
|
||||
ctxi.setFillStyle(options.background);
|
||||
ctxi.setStrokeStyle(options.background);
|
||||
ctxi.beginPath();
|
||||
ctxi.moveTo(x+r,y);
|
||||
ctxi.arcTo(x+width,y,x+width,y+r,r);
|
||||
ctxi.arcTo(x+width,y+height,x+width-r,y+height,r);
|
||||
ctxi.arcTo(x,y+height,x,y+height-r,r);
|
||||
ctxi.arcTo(x,y,x+r,y,r);
|
||||
ctxi.closePath();
|
||||
if(fill){
|
||||
ctxi.fill();
|
||||
}
|
||||
if(stroke){
|
||||
ctxi.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
setTimeout(()=>{
|
||||
ctx.draw(true,()=>{
|
||||
setTimeout(()=>{
|
||||
uni.canvasToTempFilePath({
|
||||
width:options.width,
|
||||
height:options.height,
|
||||
destWidth:options.width,
|
||||
destHeight:options.height,
|
||||
canvasId:options.canvasId,
|
||||
quality:Number(1),
|
||||
success:function(res){
|
||||
if(options.cbResult){
|
||||
options.cbResult(res.tempFilePath)
|
||||
}
|
||||
},
|
||||
fail:function(res){
|
||||
if(options.cbResult){
|
||||
options.cbResult(res)
|
||||
}
|
||||
},
|
||||
complete:function(){
|
||||
if(options.showLoading){
|
||||
uni.hideLoading();
|
||||
}
|
||||
},
|
||||
},options.context);
|
||||
},options.text.length+100);
|
||||
});
|
||||
},options.usingComponents?0:150);
|
||||
}
|
||||
createCanvas(this.options);
|
||||
let empty=function(v){
|
||||
let tp=typeof v,
|
||||
rt=false;
|
||||
if(tp=="number"&&String(v)==""){
|
||||
rt=true
|
||||
}else if(tp=="undefined"){
|
||||
rt=true
|
||||
}else if(tp=="object"){
|
||||
if(JSON.stringify(v)=="{}"||JSON.stringify(v)=="[]"||v==null)rt=true
|
||||
}else if(tp=="string"){
|
||||
if(v==""||v=="undefined"||v=="null"||v=="{}"||v=="[]")rt=true
|
||||
}else if(tp=="function"){
|
||||
rt=false
|
||||
}
|
||||
return rt
|
||||
}
|
||||
};
|
||||
QRCode.prototype.clear=function(fn){
|
||||
var ctx=uni.createCanvasContext(this.options.canvasId,this.options.context)
|
||||
ctx.clearRect(0,0,this.options.size,this.options.size)
|
||||
ctx.draw(false,()=>{
|
||||
if(fn){
|
||||
fn()
|
||||
}
|
||||
})
|
||||
};
|
||||
})()
|
||||
export default QRCode
|
||||
210
components/zb-code/zb-code.vue
Normal file
210
components/zb-code/zb-code.vue
Normal file
@@ -0,0 +1,210 @@
|
||||
<template xlang="wxml" minapp="mpvue">
|
||||
<view class="zb-code">
|
||||
<!-- #ifndef MP-ALIPAY -->
|
||||
<canvas class="zb-code-canvas" :canvas-id="cid" :style="{width:cpSize+'px',height:cpSize+'px'}" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-ALIPAY -->
|
||||
<canvas :id="cid" :width="cpSize" :height="cpSize" class="zb-code-canvas" />
|
||||
<!-- #endif -->
|
||||
<image v-show="show" :src="result" :style="{width:cpSize+'px',height:cpSize+'px'}" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import QRCode from "./qrcode.js"
|
||||
let qrcode
|
||||
export default {
|
||||
name: "zb-code",
|
||||
props: {
|
||||
cid: {
|
||||
type: String,
|
||||
default: 'zb-code-canvas'
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 200
|
||||
},
|
||||
unit: {
|
||||
type: String,
|
||||
default: 'upx'
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
val: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
default: '#ffffff'
|
||||
},
|
||||
foreground: {
|
||||
type: String,
|
||||
default: '#000000'
|
||||
},
|
||||
pdground: {
|
||||
type: String,
|
||||
default: '#000000'
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
iconSize: {
|
||||
type: Number,
|
||||
default: 40
|
||||
},
|
||||
lv: {
|
||||
type: Number,
|
||||
default: 3
|
||||
},
|
||||
onval: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
loadMake: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
usingComponents: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showLoading: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
loadingText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: '',
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
_makeCode() {
|
||||
let that = this
|
||||
if (!this._empty(this.val)) {
|
||||
qrcode = new QRCode({
|
||||
context: that, // 上下文环境
|
||||
canvasId:that.cid, // canvas-id
|
||||
usingComponents: that.usingComponents, // 是否是自定义组件
|
||||
showLoading: that.showLoading, // 是否显示loading
|
||||
loadingText: that.loadingText, // loading文字
|
||||
text: that.val, // 生成内容
|
||||
size: that.cpSize, // 二维码大小
|
||||
background: that.background, // 背景色
|
||||
foreground: that.foreground, // 前景色
|
||||
pdground: that.pdground, // 定位角点颜色
|
||||
correctLevel: that.lv, // 容错级别
|
||||
image: that.icon, // 二维码图标
|
||||
imageSize: that.iconSize,// 二维码图标大小
|
||||
cbResult: function (res) { // 生成二维码的回调
|
||||
that._result(res)
|
||||
},
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '二维码内容不能为空',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
},
|
||||
_clearCode() {
|
||||
this._result('')
|
||||
qrcode.clear()
|
||||
},
|
||||
_saveCode() {
|
||||
let that = this;
|
||||
if (this.result != "") {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: that.result,
|
||||
success: function () {
|
||||
uni.showToast({
|
||||
title: '二维码保存成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
_result(res) {
|
||||
this.result = res;
|
||||
this.$emit('result', res)
|
||||
},
|
||||
_empty(v) {
|
||||
let tp = typeof v,
|
||||
rt = false;
|
||||
if (tp == "number" && String(v) == "") {
|
||||
rt = true
|
||||
} else if (tp == "undefined") {
|
||||
rt = true
|
||||
} else if (tp == "object") {
|
||||
if (JSON.stringify(v) == "{}" || JSON.stringify(v) == "[]" || v == null) rt = true
|
||||
} else if (tp == "string") {
|
||||
if (v == "" || v == "undefined" || v == "null" || v == "{}" || v == "[]") rt = true
|
||||
} else if (tp == "function") {
|
||||
rt = false
|
||||
}
|
||||
return rt
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
size: function (n, o) {
|
||||
if (n != o && !this._empty(n)) {
|
||||
this.cSize = n
|
||||
if (!this._empty(this.val)) {
|
||||
setTimeout(() => {
|
||||
this._makeCode()
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
},
|
||||
val: function (n, o) {
|
||||
if (this.onval) {
|
||||
if (n != o && !this._empty(n)) {
|
||||
setTimeout(() => {
|
||||
this._makeCode()
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cpSize() {
|
||||
if(this.unit == "upx"){
|
||||
return uni.upx2px(this.size)
|
||||
}else{
|
||||
return this.size
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
if (this.loadMake) {
|
||||
if (!this._empty(this.val)) {
|
||||
setTimeout(() => {
|
||||
this._makeCode()
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.zb-code {
|
||||
position: relative;
|
||||
}
|
||||
.zb-code-canvas {
|
||||
position: fixed;
|
||||
top: -99999upx;
|
||||
left: -99999upx;
|
||||
z-index: -99999;
|
||||
}
|
||||
</style>
|
||||
44
config/cache.js
Normal file
44
config/cache.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
//token
|
||||
LOGIN_STATUS: 'LOGIN_STATUS_TOKEN',
|
||||
//uid
|
||||
UID:'UID',
|
||||
//用户信息
|
||||
USER_INFO: 'USER_INFO',
|
||||
//token过期时间
|
||||
EXPIRES_TIME: 'EXPIRES_TIME',
|
||||
//微信登录
|
||||
WX_AUTH: 'WX_AUTH',
|
||||
//公众号登录code
|
||||
STATE_KEY: 'wx_authorize_state',
|
||||
//登录类型
|
||||
LOGINTYPE: 'loginType',
|
||||
//登录跳转地址
|
||||
BACK_URL: 'login_back_url',
|
||||
//小程序登录状态code
|
||||
STATE_R_KEY: 'roution_authorize_state',
|
||||
//logo 地址
|
||||
LOGO_URL: 'LOGO_URL',
|
||||
//模板缓存
|
||||
SUBSCRIBE_MESSAGE: 'SUBSCRIBE_MESSAGE',
|
||||
|
||||
TIPS_KEY: 'TIPS_KEY',
|
||||
|
||||
SPREAD: 'spid',
|
||||
//缓存经度
|
||||
CACHE_LONGITUDE: 'LONGITUDE',
|
||||
//缓存纬度
|
||||
CACHE_LATITUDE: 'LATITUDE',
|
||||
// 移动网络下视频自动播放
|
||||
NON_WIFI_AUTOPLAY: 'NON_WIFI_AUTOPLAY'
|
||||
}
|
||||
18
config/socket.js
Normal file
18
config/socket.js
Normal file
@@ -0,0 +1,18 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
// Socket链接 暂不做配置
|
||||
WSS_SERVER_URL:'',
|
||||
// Socket调试模式
|
||||
SERVER_DEBUG:true,
|
||||
// 心跳间隔
|
||||
PINGINTERVAL:3000
|
||||
}
|
||||
33
index.html
Normal file
33
index.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>
|
||||
<%= htmlWebpackPlugin.options.title %>
|
||||
</title>
|
||||
<!-- Open Graph data -->
|
||||
<!-- <meta property="og:title" content="Title Here" /> -->
|
||||
<!-- <meta property="og:url" content="http://www.example.com/" /> -->
|
||||
<!-- <meta property="og:image" content="http://example.com/image.jpg" /> -->
|
||||
<!-- <meta property="og:description" content="Description Here" /> -->
|
||||
<script>
|
||||
window.wx = null;
|
||||
//uniapp默认的wx重置
|
||||
</script>
|
||||
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
|
||||
<script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
|
||||
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>Please enable JavaScript to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
272
js_sdk/wa-permission/permission.js
Normal file
272
js_sdk/wa-permission/permission.js
Normal file
@@ -0,0 +1,272 @@
|
||||
/**
|
||||
* 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启
|
||||
*/
|
||||
|
||||
var isIos
|
||||
// #ifdef APP-PLUS
|
||||
isIos = (plus.os.name == "iOS")
|
||||
// #endif
|
||||
|
||||
// 判断推送权限是否开启
|
||||
function judgeIosPermissionPush() {
|
||||
var result = false;
|
||||
var UIApplication = plus.ios.import("UIApplication");
|
||||
var app = UIApplication.sharedApplication();
|
||||
var enabledTypes = 0;
|
||||
if (app.currentUserNotificationSettings) {
|
||||
var settings = app.currentUserNotificationSettings();
|
||||
enabledTypes = settings.plusGetAttribute("types");
|
||||
console.log("enabledTypes1:" + enabledTypes);
|
||||
if (enabledTypes == 0) {
|
||||
console.log("推送权限没有开启");
|
||||
} else {
|
||||
result = true;
|
||||
console.log("已经开启推送功能!")
|
||||
}
|
||||
plus.ios.deleteObject(settings);
|
||||
} else {
|
||||
enabledTypes = app.enabledRemoteNotificationTypes();
|
||||
if (enabledTypes == 0) {
|
||||
console.log("推送权限没有开启!");
|
||||
} else {
|
||||
result = true;
|
||||
console.log("已经开启推送功能!")
|
||||
}
|
||||
console.log("enabledTypes2:" + enabledTypes);
|
||||
}
|
||||
plus.ios.deleteObject(app);
|
||||
plus.ios.deleteObject(UIApplication);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 判断定位权限是否开启
|
||||
function judgeIosPermissionLocation() {
|
||||
var result = false;
|
||||
var cllocationManger = plus.ios.import("CLLocationManager");
|
||||
var status = cllocationManger.authorizationStatus();
|
||||
result = (status != 2)
|
||||
console.log("定位权限开启:" + result);
|
||||
// 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation
|
||||
/* var enable = cllocationManger.locationServicesEnabled();
|
||||
var status = cllocationManger.authorizationStatus();
|
||||
console.log("enable:" + enable);
|
||||
console.log("status:" + status);
|
||||
if (enable && status != 2) {
|
||||
result = true;
|
||||
console.log("手机定位服务已开启且已授予定位权限");
|
||||
} else {
|
||||
console.log("手机系统的定位没有打开或未给予定位权限");
|
||||
} */
|
||||
plus.ios.deleteObject(cllocationManger);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 判断麦克风权限是否开启
|
||||
function judgeIosPermissionRecord() {
|
||||
var result = false;
|
||||
var avaudiosession = plus.ios.import("AVAudioSession");
|
||||
var avaudio = avaudiosession.sharedInstance();
|
||||
var permissionStatus = avaudio.recordPermission();
|
||||
console.log("permissionStatus:" + permissionStatus);
|
||||
if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
|
||||
console.log("麦克风权限没有开启");
|
||||
} else {
|
||||
result = true;
|
||||
console.log("麦克风权限已经开启");
|
||||
}
|
||||
plus.ios.deleteObject(avaudiosession);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 判断相机权限是否开启
|
||||
function judgeIosPermissionCamera() {
|
||||
var result = false;
|
||||
var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
|
||||
var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
|
||||
console.log("authStatus:" + authStatus);
|
||||
if (authStatus == 3) {
|
||||
result = true;
|
||||
console.log("相机权限已经开启");
|
||||
} else {
|
||||
console.log("相机权限没有开启");
|
||||
}
|
||||
plus.ios.deleteObject(AVCaptureDevice);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 判断相册权限是否开启
|
||||
function judgeIosPermissionPhotoLibrary() {
|
||||
var result = false;
|
||||
var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
|
||||
var authStatus = PHPhotoLibrary.authorizationStatus();
|
||||
console.log("authStatus:" + authStatus);
|
||||
if (authStatus == 3) {
|
||||
result = true;
|
||||
console.log("相册权限已经开启");
|
||||
} else {
|
||||
console.log("相册权限没有开启");
|
||||
}
|
||||
plus.ios.deleteObject(PHPhotoLibrary);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 判断通讯录权限是否开启
|
||||
function judgeIosPermissionContact() {
|
||||
var result = false;
|
||||
var CNContactStore = plus.ios.import("CNContactStore");
|
||||
var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
|
||||
if (cnAuthStatus == 3) {
|
||||
result = true;
|
||||
console.log("通讯录权限已经开启");
|
||||
} else {
|
||||
console.log("通讯录权限没有开启");
|
||||
}
|
||||
plus.ios.deleteObject(CNContactStore);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 判断日历权限是否开启
|
||||
function judgeIosPermissionCalendar() {
|
||||
var result = false;
|
||||
var EKEventStore = plus.ios.import("EKEventStore");
|
||||
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
|
||||
if (ekAuthStatus == 3) {
|
||||
result = true;
|
||||
console.log("日历权限已经开启");
|
||||
} else {
|
||||
console.log("日历权限没有开启");
|
||||
}
|
||||
plus.ios.deleteObject(EKEventStore);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 判断备忘录权限是否开启
|
||||
function judgeIosPermissionMemo() {
|
||||
var result = false;
|
||||
var EKEventStore = plus.ios.import("EKEventStore");
|
||||
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
|
||||
if (ekAuthStatus == 3) {
|
||||
result = true;
|
||||
console.log("备忘录权限已经开启");
|
||||
} else {
|
||||
console.log("备忘录权限没有开启");
|
||||
}
|
||||
plus.ios.deleteObject(EKEventStore);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Android权限查询
|
||||
function requestAndroidPermission(permissionID) {
|
||||
return new Promise((resolve, reject) => {
|
||||
plus.android.requestPermissions(
|
||||
[permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
|
||||
function(resultObj) {
|
||||
var result = 0;
|
||||
for (var i = 0; i < resultObj.granted.length; i++) {
|
||||
var grantedPermission = resultObj.granted[i];
|
||||
console.log('已获取的权限:' + grantedPermission);
|
||||
result = 1
|
||||
}
|
||||
for (var i = 0; i < resultObj.deniedPresent.length; i++) {
|
||||
var deniedPresentPermission = resultObj.deniedPresent[i];
|
||||
console.log('拒绝本次申请的权限:' + deniedPresentPermission);
|
||||
result = 0
|
||||
}
|
||||
for (var i = 0; i < resultObj.deniedAlways.length; i++) {
|
||||
var deniedAlwaysPermission = resultObj.deniedAlways[i];
|
||||
console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
|
||||
result = -1
|
||||
}
|
||||
resolve(result);
|
||||
// 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
|
||||
// if (result != 1) {
|
||||
// gotoAppPermissionSetting()
|
||||
// }
|
||||
},
|
||||
function(error) {
|
||||
console.log('申请权限错误:' + error.code + " = " + error.message);
|
||||
resolve({
|
||||
code: error.code,
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 使用一个方法,根据参数判断权限
|
||||
function judgeIosPermission(permissionID) {
|
||||
if (permissionID == "location") {
|
||||
return judgeIosPermissionLocation()
|
||||
} else if (permissionID == "camera") {
|
||||
return judgeIosPermissionCamera()
|
||||
} else if (permissionID == "photoLibrary") {
|
||||
return judgeIosPermissionPhotoLibrary()
|
||||
} else if (permissionID == "record") {
|
||||
return judgeIosPermissionRecord()
|
||||
} else if (permissionID == "push") {
|
||||
return judgeIosPermissionPush()
|
||||
} else if (permissionID == "contact") {
|
||||
return judgeIosPermissionContact()
|
||||
} else if (permissionID == "calendar") {
|
||||
return judgeIosPermissionCalendar()
|
||||
} else if (permissionID == "memo") {
|
||||
return judgeIosPermissionMemo()
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 跳转到**应用**的权限页面
|
||||
function gotoAppPermissionSetting() {
|
||||
if (isIos) {
|
||||
var UIApplication = plus.ios.import("UIApplication");
|
||||
var application2 = UIApplication.sharedApplication();
|
||||
var NSURL2 = plus.ios.import("NSURL");
|
||||
// var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");
|
||||
var setting2 = NSURL2.URLWithString("app-settings:");
|
||||
application2.openURL(setting2);
|
||||
|
||||
plus.ios.deleteObject(setting2);
|
||||
plus.ios.deleteObject(NSURL2);
|
||||
plus.ios.deleteObject(application2);
|
||||
} else {
|
||||
// console.log(plus.device.vendor);
|
||||
var Intent = plus.android.importClass("android.content.Intent");
|
||||
var Settings = plus.android.importClass("android.provider.Settings");
|
||||
var Uri = plus.android.importClass("android.net.Uri");
|
||||
var mainActivity = plus.android.runtimeMainActivity();
|
||||
var intent = new Intent();
|
||||
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
|
||||
intent.setData(uri);
|
||||
mainActivity.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
// 检查系统的设备服务是否开启
|
||||
// var checkSystemEnableLocation = async function () {
|
||||
function checkSystemEnableLocation() {
|
||||
if (isIos) {
|
||||
var result = false;
|
||||
var cllocationManger = plus.ios.import("CLLocationManager");
|
||||
var result = cllocationManger.locationServicesEnabled();
|
||||
console.log("系统定位开启:" + result);
|
||||
plus.ios.deleteObject(cllocationManger);
|
||||
return result;
|
||||
} else {
|
||||
var context = plus.android.importClass("android.content.Context");
|
||||
var locationManager = plus.android.importClass("android.location.LocationManager");
|
||||
var main = plus.android.runtimeMainActivity();
|
||||
var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
|
||||
var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);
|
||||
console.log("系统定位开启:" + result);
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
judgeIosPermission: judgeIosPermission,
|
||||
requestAndroidPermission: requestAndroidPermission,
|
||||
checkSystemEnableLocation: checkSystemEnableLocation,
|
||||
gotoAppPermissionSetting: gotoAppPermissionSetting
|
||||
}
|
||||
124
libs/login.js
Normal file
124
libs/login.js
Normal file
@@ -0,0 +1,124 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import store from "../store";
|
||||
import Cache from '../utils/cache';
|
||||
import {
|
||||
Debounce
|
||||
} from '@/utils/validate.js'
|
||||
// #ifdef H5 || APP-PLUS
|
||||
import {
|
||||
isWeixin
|
||||
} from "../utils";
|
||||
import auth from './wechat';
|
||||
// #endif
|
||||
|
||||
import {
|
||||
LOGIN_STATUS,
|
||||
USER_INFO,
|
||||
EXPIRES_TIME,
|
||||
STATE_R_KEY
|
||||
} from './../config/cache';
|
||||
import Routine from '@/libs/routine';
|
||||
|
||||
function prePage() {
|
||||
let pages = getCurrentPages();
|
||||
let prePage = pages[pages.length - 1];
|
||||
// #ifndef APP-PLUS
|
||||
return prePage.route;
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
return prePage.$page.fullPath;
|
||||
// #endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
export const toLogin = Debounce(_toLogin, 800)
|
||||
|
||||
function _toLogin(push, pathLogin) {
|
||||
store.commit("LOGOUT");
|
||||
let path = prePage();
|
||||
|
||||
// #ifdef H5
|
||||
path = location.pathname + location.search;
|
||||
// #endif
|
||||
|
||||
if (!pathLogin)
|
||||
pathLogin = '/page/users/login/index'
|
||||
Cache.set('login_back_url', path);
|
||||
const BASIC_CONFIG = uni.getStorageSync('BASIC_CONFIG');
|
||||
// #ifdef H5
|
||||
if (isWeixin() && BASIC_CONFIG.wechat_status) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/users/wechat_login/index',
|
||||
});
|
||||
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: '/pages/users/login/index'
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
let url
|
||||
if (!BASIC_CONFIG.wechat_auth_switch) {
|
||||
url = '/pages/users/binding_phone/index?pageType=0'
|
||||
} else {
|
||||
url = '/pages/users/wechat_login/index'
|
||||
}
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
// Routine.getCode()
|
||||
// .then(code => {
|
||||
// console.log(code)
|
||||
// Routine.silenceAuth(code).then(res => {
|
||||
// console.log(res)
|
||||
// })
|
||||
// })
|
||||
// .catch(err => {
|
||||
// uni.hideLoading();
|
||||
// });
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
uni.navigateTo({
|
||||
url: '/pages/users/login/index'
|
||||
})
|
||||
// #endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function checkLogin() {
|
||||
let token = Cache.get(LOGIN_STATUS);
|
||||
let expiresTime = Cache.get(EXPIRES_TIME);
|
||||
let newTime = Math.round(new Date() / 1000);
|
||||
if (expiresTime < newTime || !token) {
|
||||
uni.setStorageSync('authIng', false)
|
||||
Cache.clear(LOGIN_STATUS);
|
||||
Cache.clear(EXPIRES_TIME);
|
||||
Cache.clear(USER_INFO);
|
||||
Cache.clear(STATE_R_KEY);
|
||||
return false;
|
||||
} else {
|
||||
store.commit('UPDATE_LOGIN', token);
|
||||
let userInfo = Cache.get(USER_INFO, true);
|
||||
if (userInfo) {
|
||||
store.commit('UPDATE_USERINFO', userInfo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
9
libs/network.js
Normal file
9
libs/network.js
Normal file
@@ -0,0 +1,9 @@
|
||||
export function onNetworkStatusChange(onlineFun, offlineFun) {
|
||||
uni.onNetworkStatusChange(res => {
|
||||
if(res.networkType !== 'none') {
|
||||
onlineFun && onlineFun(res);
|
||||
} else{
|
||||
offlineFun && offlineFun(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
257
libs/new_chat.js
Normal file
257
libs/new_chat.js
Normal file
@@ -0,0 +1,257 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import $store from "@/store";
|
||||
import wechat from "@/libs/wechat";
|
||||
import {
|
||||
HTTP_REQUEST_URL,
|
||||
VUE_APP_WS_URL
|
||||
} from "@/config/app.js";
|
||||
import {
|
||||
getServerType
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
onNetworkStatusChange
|
||||
} from '@/libs/network.js';
|
||||
|
||||
|
||||
function wss(wsSocketUrl) {
|
||||
if (wsSocketUrl.indexOf('wss:') !== -1) {
|
||||
return wsSocketUrl;
|
||||
}
|
||||
// #ifdef H5
|
||||
let ishttps = document.location.protocol == 'https:';
|
||||
if (ishttps) {
|
||||
return wsSocketUrl.replace('ws:', 'wss:');
|
||||
} else {
|
||||
return wsSocketUrl.replace('wss:', 'ws:');
|
||||
}
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
return wsSocketUrl.replace('ws:', 'wss:');
|
||||
//#endif
|
||||
}
|
||||
|
||||
class Socket {
|
||||
constructor() {
|
||||
this.socketTask = null; //socket 任务
|
||||
this.timer = null; //心跳定时器
|
||||
this.connectStatus = false; //连接状态
|
||||
this.wsUrl = ''; //ws地址
|
||||
this.reconnectTimer = 2000; //重连
|
||||
this.handClse = false; //手动关闭
|
||||
this.reconnetime = null; //重连 定时器
|
||||
this.networkStatus = true;
|
||||
this.connectLing = false; //连接是否进行中
|
||||
this.defaultEvenv(); //执行默认事件
|
||||
this.networkEvent();
|
||||
}
|
||||
//网络状态变化监听
|
||||
networkEvent() {
|
||||
onNetworkStatusChange((res) => {
|
||||
this.networkStatus = true;
|
||||
if (this.socketTask) {
|
||||
this.socketTask.close();
|
||||
}
|
||||
uni.$on('timeout', this.timeoutEvent.bind(this))
|
||||
}, () => {
|
||||
this.networkStatus = false;
|
||||
this.connectStatus = false;
|
||||
clearInterval(this.timer);
|
||||
this.timer = null;
|
||||
uni.$off('timeout', this.timeoutEvent)
|
||||
});
|
||||
}
|
||||
//开始连接
|
||||
startConnect() {
|
||||
console.log('开始链接')
|
||||
this.handClse = false;
|
||||
if (!this.connectStatus) {
|
||||
this.init();
|
||||
this.connect();
|
||||
}
|
||||
}
|
||||
//默认事件
|
||||
defaultEvenv() {
|
||||
|
||||
uni.$off('success', this.successEvent);
|
||||
uni.$off('timeout', this.timeoutEvent);
|
||||
|
||||
uni.$on('success', this.successEvent.bind(this));
|
||||
uni.$on('timeout', this.timeoutEvent.bind(this));
|
||||
}
|
||||
|
||||
timeoutEvent() {
|
||||
console.log('timeoutEvent')
|
||||
this.reconne();
|
||||
}
|
||||
successEvent() {
|
||||
console.log('success默认事件');
|
||||
// this.changOnline();
|
||||
}
|
||||
//发送用户状态
|
||||
changOnline() {
|
||||
let online = cache.get('kefu_online')
|
||||
if (online !== undefined && online !== '') {
|
||||
this.send({
|
||||
data: {
|
||||
online: online
|
||||
},
|
||||
type: 'online'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//连接websocket
|
||||
connect() {
|
||||
this.connectLing = true;
|
||||
this.socketTask = uni.connectSocket({
|
||||
url: this.wsUrl,
|
||||
complete: () => {}
|
||||
});
|
||||
|
||||
this.socketTask.onOpen(this.onOpen.bind(this))
|
||||
this.socketTask.onError(this.onError.bind(this));
|
||||
this.socketTask.onMessage(this.onMessage.bind(this))
|
||||
this.socketTask.onClose(this.onClose.bind(this));
|
||||
|
||||
}
|
||||
|
||||
init() {
|
||||
let wsUrl = wss(`${VUE_APP_WS_URL}?type=user`),
|
||||
form_type = 3;
|
||||
|
||||
//#ifdef MP || APP-PLUS
|
||||
form_type = 2
|
||||
//#endif
|
||||
//#ifdef H5
|
||||
form_type = wechat.isWeixin() ? 1 : 3
|
||||
//#endif
|
||||
this.wsUrl = `${wsUrl}&token=${$store.state.app.token}&form_type=${form_type}`
|
||||
}
|
||||
|
||||
//断线重连
|
||||
reconne() {
|
||||
if (this.reconnetime || this.connectStatus) {
|
||||
return;
|
||||
}
|
||||
this.reconnetime = setInterval(() => {
|
||||
if (this.connectStatus) {
|
||||
return;
|
||||
}
|
||||
this.connectLing || this.connect();
|
||||
}, this.reconnectTimer);
|
||||
}
|
||||
|
||||
onOpen() {
|
||||
clearInterval(this.reconnetime);
|
||||
this.reconnetime = null;
|
||||
this.connectLing = false;
|
||||
this.connectStatus = true;
|
||||
this.ping();
|
||||
}
|
||||
|
||||
onError(error) {
|
||||
console.log('连接发生错误', error)
|
||||
this.connectStatus = false;
|
||||
this.connectLing = false;
|
||||
this.reconne();
|
||||
}
|
||||
|
||||
onClose(err) {
|
||||
console.log(this.socketTask, err, '关闭连接')
|
||||
uni.$emit('close');
|
||||
//手动关闭不用重新连接
|
||||
if (this.handClse) {
|
||||
return;
|
||||
}
|
||||
clearInterval(this.timer);
|
||||
this.timer = null;
|
||||
this.connectStatus = false;
|
||||
this.connectLing = false;
|
||||
this.reconne();
|
||||
}
|
||||
|
||||
ping() {
|
||||
this.timer = setInterval(() => {
|
||||
this.send({
|
||||
type: 'ping'
|
||||
})
|
||||
}, 10000)
|
||||
}
|
||||
|
||||
onMessage(response) {
|
||||
let {
|
||||
type,
|
||||
data
|
||||
} = JSON.parse(response.data);
|
||||
uni.$emit(type, data);
|
||||
}
|
||||
|
||||
|
||||
send(data) {
|
||||
let that = this;
|
||||
//没有网络,或者没有连接
|
||||
if (!this.connectStatus || !this.networkStatus) {
|
||||
this.reconne();
|
||||
}
|
||||
return new Promise((reslove, reject) => {
|
||||
this.socketTask.send({
|
||||
data: JSON.stringify(data),
|
||||
success() {
|
||||
reslove();
|
||||
},
|
||||
fail(res) {
|
||||
console.log(res)
|
||||
if (res.errMsg ==
|
||||
'sendSocketMessage:fail WebSocket is not connected' ||
|
||||
res.errMsg ==
|
||||
'sendSocketMessage:fail Error: SocketTask.readyState is not OPEN'
|
||||
) {
|
||||
that.reconne();
|
||||
}
|
||||
reject(res);
|
||||
},
|
||||
complete(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
guid() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
var r = Math.random() * 16 | 0,
|
||||
v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
clearPing() {
|
||||
clearInterval(this.timer);
|
||||
this.timer = null;
|
||||
if (this.connectStatus) {
|
||||
this.socketTask.close();
|
||||
}
|
||||
this.handClse = true;
|
||||
this.connectStatus = false;
|
||||
this.connectLing = false;
|
||||
}
|
||||
|
||||
setBadgeNumber(count) {
|
||||
//#ifdef APP-PLUS
|
||||
plus.runtime.setBadgeNumber(Number(count));
|
||||
//#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default Socket;
|
||||
44
libs/order.js
Normal file
44
libs/order.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
let app = getApp()
|
||||
|
||||
export function goShopDetail(item, uid) {
|
||||
return new Promise((resolve,reject) => {
|
||||
if(item.is_presale_product){
|
||||
uni.navigateTo({
|
||||
url: `/pages/activity/goods_details/index?id=${item.id}&type=6`
|
||||
})
|
||||
}else{
|
||||
if (item.activity && item.activity.type == 1) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/activity/goods_details/index?id=${item.activity.id}&type=1&time=${item.activity.time}&status=1`
|
||||
})
|
||||
} else if (item.activity && item.activity.type == 2) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/activity/goods_bargain_details/index?id=${item.activity.id}&spid=${uid}`
|
||||
})
|
||||
} else if (item.activity && item.activity.type == 3) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/activity/goods_details/index?id=${item.activity.id}&type=3`
|
||||
})
|
||||
} else {
|
||||
reject(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function goPage() {
|
||||
return new Promise(resolve => {
|
||||
resolve(true);
|
||||
});
|
||||
}
|
||||
214
libs/routine.js
Normal file
214
libs/routine.js
Normal file
@@ -0,0 +1,214 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import store from '../store';
|
||||
import {
|
||||
checkLogin
|
||||
} from './login';
|
||||
import {
|
||||
login,
|
||||
routineLogin,
|
||||
silenceAuth
|
||||
} from '../api/public';
|
||||
import Cache from '../utils/cache';
|
||||
import {
|
||||
STATE_R_KEY,
|
||||
USER_INFO,
|
||||
EXPIRES_TIME,
|
||||
LOGIN_STATUS
|
||||
} from './../config/cache';
|
||||
import {
|
||||
mapGetters
|
||||
} from "vuex";
|
||||
class Routine {
|
||||
|
||||
constructor() {
|
||||
this.scopeUserInfo = 'scope.userInfo';
|
||||
}
|
||||
|
||||
async getUserCode() {
|
||||
let isAuth = await this.isAuth(),
|
||||
code = '';
|
||||
if (isAuth)
|
||||
code = await this.getCode();
|
||||
return code;
|
||||
}
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
getUserInfo() {
|
||||
let that = this,
|
||||
code = this.getUserCode();
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.getUserInfo({
|
||||
lang: 'zh_CN',
|
||||
success(user) {
|
||||
if (code) user.code = code;
|
||||
resolve({
|
||||
userInfo: user,
|
||||
islogin: false
|
||||
});
|
||||
},
|
||||
fail(res) {
|
||||
reject(res);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 新版小程序获取用户信息 2021 4.13微信小程序开始正式启用
|
||||
*/
|
||||
getUserProfile(code) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.getUserProfile({
|
||||
lang: 'zh_CN',
|
||||
desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
|
||||
success(user) {
|
||||
if (code) user.code = code;
|
||||
resolve({
|
||||
userInfo: user,
|
||||
islogin: false
|
||||
});
|
||||
},
|
||||
fail(res) {
|
||||
reject(res);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
authorize() {
|
||||
let that = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
if (checkLogin())
|
||||
return resolve({
|
||||
userInfo: Cache.get(USER_INFO, true),
|
||||
islogin: true,
|
||||
});
|
||||
uni.authorize({
|
||||
scope: that.scopeUserInfo,
|
||||
success() {
|
||||
resolve({
|
||||
islogin: false
|
||||
});
|
||||
},
|
||||
fail(res) {
|
||||
reject(res);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async getCode() {
|
||||
let provider = await this.getProvider();
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.login({
|
||||
provider: provider,
|
||||
success(res) {
|
||||
if (res.code) Cache.set(STATE_R_KEY, res.code, 10800);
|
||||
return resolve(res.code);
|
||||
},
|
||||
fail() {
|
||||
return reject(null);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务供应商
|
||||
*/
|
||||
getProvider() {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.getProvider({
|
||||
service: 'oauth',
|
||||
success(res) {
|
||||
resolve(res.provider);
|
||||
},
|
||||
fail() {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否授权
|
||||
*/
|
||||
isAuth() {
|
||||
let that = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.getSetting({
|
||||
success(res) {
|
||||
if (!res.authSetting[that.scopeUserInfo]) {
|
||||
resolve(true)
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
},
|
||||
fail() {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 小程序比较版本信息
|
||||
* @param v1 当前版本
|
||||
* @param v2 进行比较的版本
|
||||
* @return boolen
|
||||
*
|
||||
*/
|
||||
compareVersion(v1, v2) {
|
||||
v1 = v1.split('.')
|
||||
v2 = v2.split('.')
|
||||
const len = Math.max(v1.length, v2.length)
|
||||
|
||||
while (v1.length < len) {
|
||||
v1.push('0')
|
||||
}
|
||||
while (v2.length < len) {
|
||||
v2.push('0')
|
||||
}
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
const num1 = parseInt(v1[i])
|
||||
const num2 = parseInt(v2[i])
|
||||
|
||||
if (num1 > num2) {
|
||||
return 1
|
||||
} else if (num1 < num2) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
authUserInfo(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
routineLogin(data).then(res => {
|
||||
if (res.data.key !== undefined && res.data.key) {} else {
|
||||
store.commit('UPDATE_USERINFO', res.data.userInfo);
|
||||
store.commit('SETUID', res.data.userInfo.uid);
|
||||
Cache.set(USER_INFO, res.data.userInfo);
|
||||
}
|
||||
return resolve(res);
|
||||
}).catch(res => {
|
||||
return reject(res);
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default new Routine();
|
||||
230
libs/wechat.js
Normal file
230
libs/wechat.js
Normal file
@@ -0,0 +1,230 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
// #ifdef H5
|
||||
import {
|
||||
getWechatConfig,
|
||||
getShopConfig,
|
||||
wechatAuthV2
|
||||
} from "@/api/public";
|
||||
import {
|
||||
WX_AUTH,
|
||||
STATE_KEY,
|
||||
LOGINTYPE,
|
||||
BACK_URL
|
||||
} from '@/config/cache';
|
||||
import {
|
||||
parseQuery
|
||||
} from '@/utils';
|
||||
import store from '@/store';
|
||||
import Cache from '@/utils/cache';
|
||||
|
||||
class AuthWechat {
|
||||
|
||||
constructor() {
|
||||
this.instance = jWeixin;
|
||||
//是否实例化
|
||||
this.status = false;
|
||||
|
||||
this.initConfig = {};
|
||||
|
||||
}
|
||||
|
||||
isAndroid(){
|
||||
let u = navigator.userAgent;
|
||||
return u.indexOf('Android') > -1 || u.indexOf('Adr') > -1;
|
||||
}
|
||||
|
||||
signLink() {
|
||||
if (typeof window.entryUrl === 'undefined' || window.entryUrl === '') {
|
||||
window.entryUrl = location.href
|
||||
}
|
||||
return /(Android)/i.test(navigator.userAgent) ? location.href : window.entryUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化wechat(分享配置)
|
||||
*/
|
||||
wechat() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// if (this.status && !this.isAndroid()) return resolve(this.instance);
|
||||
getWechatConfig()
|
||||
.then(res => {
|
||||
this.instance.config(res.data);
|
||||
this.initConfig = res.data;
|
||||
this.status = true;
|
||||
this.instance.ready(() => {
|
||||
resolve(this.instance);
|
||||
})
|
||||
}).catch(err => {
|
||||
this.status = false;
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证是否初始化
|
||||
*/
|
||||
verifyInstance() {
|
||||
let that = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
if (that.instance === null && !that.status) {
|
||||
that.wechat().then(res => {
|
||||
resolve(that.instance);
|
||||
}).catch(() => {
|
||||
return reject();
|
||||
})
|
||||
} else {
|
||||
return resolve(that.instance);
|
||||
}
|
||||
})
|
||||
}
|
||||
// 微信公众号的共享地址
|
||||
openAddress() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.wechat().then(wx => {
|
||||
this.toPromise(wx.openAddress).then(res => {
|
||||
resolve(res);
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
});
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// 获取经纬度;
|
||||
location(){
|
||||
return new Promise((resolve, reject) => {
|
||||
this.wechat().then(wx => {
|
||||
this.toPromise(wx.getLocation,{type: 'wgs84'}).then(res => {
|
||||
resolve(res);
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
});
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// 使用微信内置地图查看位置接口;
|
||||
seeLocation(config){
|
||||
return new Promise((resolve, reject) => {
|
||||
this.wechat().then(wx => {
|
||||
this.toPromise(wx.openLocation, config).then(res => {
|
||||
resolve(res);
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
});
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付
|
||||
* @param {Object} config
|
||||
*/
|
||||
pay(config) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.wechat().then((wx) => {
|
||||
this.toPromise(wx.chooseWXPay, config).then(res => {
|
||||
resolve(res);
|
||||
}).catch(res => {
|
||||
reject(res);
|
||||
});
|
||||
}).catch(res => {
|
||||
reject(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
toPromise(fn, config = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fn({
|
||||
...config,
|
||||
success(res) {
|
||||
resolve(res);
|
||||
},
|
||||
fail(err) {
|
||||
reject(err);
|
||||
},
|
||||
complete(err) {
|
||||
reject(err);
|
||||
},
|
||||
cancel(err) {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定事件
|
||||
* @param {Object} name 事件名
|
||||
* @param {Object} config 参数
|
||||
*/
|
||||
wechatEvevt(name, config) {
|
||||
let that = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
let configDefault = {
|
||||
fail(res) {
|
||||
if (that.instance) return reject({
|
||||
is_ready: true,
|
||||
wx: that.instance
|
||||
});
|
||||
that.verifyInstance().then(wx => {
|
||||
return reject({
|
||||
is_ready: true,
|
||||
wx: wx
|
||||
});
|
||||
})
|
||||
},
|
||||
success(res) {
|
||||
return resolve(res,2222);
|
||||
}
|
||||
};
|
||||
Object.assign(configDefault, config);
|
||||
that.wechat().then(wx => {
|
||||
if (typeof name === 'object') {
|
||||
name.forEach(item => {
|
||||
wx[item] && wx[item](configDefault)
|
||||
})
|
||||
} else {
|
||||
wx[name] && wx[name](configDefault)
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
isWeixin() {
|
||||
return navigator.userAgent.toLowerCase().indexOf("micromessenger") !== -1;
|
||||
}
|
||||
|
||||
async newAuth(scope,url){
|
||||
try {
|
||||
let res = await getWechatConfig();
|
||||
let redirect_url = encodeURIComponent(url);
|
||||
let state = encodeURIComponent(("" + Math.random()).split(".")[1] + "authorizestate");
|
||||
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${res.data.appId}&redirect_uri=${redirect_url}&response_type=code&scope=${scope}&state=${state}&connect_redirect=1#wechat_redirect`;
|
||||
} catch (err) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default new AuthWechat();
|
||||
// #endif
|
||||
119
libs/work.js
Normal file
119
libs/work.js
Normal file
@@ -0,0 +1,119 @@
|
||||
import {getWorkConfig,getWorkAgentConfig} from "@/api/work.js"
|
||||
// import {wx} from "@/utils/agent.js"
|
||||
export function initWxConfig() {
|
||||
return getTicket;
|
||||
}
|
||||
|
||||
export function initAgentConfig() {
|
||||
return agentConfig;
|
||||
};
|
||||
|
||||
|
||||
|
||||
const getTicket = new Promise((resolve, reject) => {
|
||||
getWorkConfig(window.location.href.split('#')[0]).then(res=>{
|
||||
if (/(iPhone|iPad|iPod|iOS|macintosh|mac os x)/i.test(navigator.userAgent)) {
|
||||
jWeixin.config({
|
||||
beta: true,// 必须这么写,否则wx.invoke调用形式的jsapi会有问题
|
||||
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
|
||||
appId: res.data.appId, // 必填,企业微信的corpID
|
||||
timestamp:res.data.timestamp , // 必填,生成签名的时间戳
|
||||
nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
|
||||
signature: res.data.signature,// 必填,签名,见 附录-JS-SDK使用权限签名算法
|
||||
// jsApiList: res.data.jsApiList // 必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来
|
||||
jsApiList: ["getCurExternalContact", "getCurExternalChat", "getContext", "chooseImage","sendChatMessage","shareAppMessage"]
|
||||
});
|
||||
jWeixin.ready(function() {
|
||||
// resolve(wx);
|
||||
setTimeout(()=>{
|
||||
getWorkAgentConfig(window.location.href.split('#')[0]).then(response=>{
|
||||
let jWeixi = wx;
|
||||
jWeixi.agentConfig({
|
||||
corpid: response.data.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
|
||||
agentid: response.data.agentid, // 必填,企业微信的应用id (e.g. 1000247)
|
||||
timestamp: response.data.timestamp, // 必填,生成签名的时间戳
|
||||
nonceStr: response.data.nonceStr, // 必填,生成签名的随机串
|
||||
signature: response.data.signature,// 必填,签名,见附录-JS-SDK使用权限签名算法
|
||||
// jsApiList: response.data.jsApiList, //必填,传入需要使用的接口名称
|
||||
jsApiList: ["getCurExternalContact", "getCurExternalChat", "getContext", "chooseImage","sendChatMessage","shareAppMessage"],
|
||||
success: function(data) {
|
||||
resolve(data);
|
||||
},
|
||||
fail: function(err) {
|
||||
if(err.errMsg.indexOf('function not exist') > -1){
|
||||
reject('版本过低请升级');
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
},1000)
|
||||
})
|
||||
}else{
|
||||
// window.wx = window.jWeixin;
|
||||
jWeixin.config({
|
||||
beta: true,// 必须这么写,否则wx.invoke调用形式的jsapi会有问题
|
||||
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
|
||||
appId: res.data.appId, // 必填,企业微信的corpID
|
||||
timestamp:res.data.timestamp , // 必填,生成签名的时间戳
|
||||
nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
|
||||
signature: res.data.signature,// 必填,签名,见 附录-JS-SDK使用权限签名算法
|
||||
jsApiList: ["getCurExternalContact", "getCurExternalChat", "getContext", "chooseImage","sendChatMessage","shareAppMessage"] // 必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来
|
||||
});
|
||||
jWeixin.ready(function() {
|
||||
// resolve(wx);
|
||||
getWorkAgentConfig(location.href).then(response=>{
|
||||
jWeixin.agentConfig({
|
||||
corpid: response.data.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
|
||||
agentid: response.data.agentid, // 必填,企业微信的应用id (e.g. 1000247)
|
||||
timestamp: response.data.timestamp, // 必填,生成签名的时间戳
|
||||
nonceStr: response.data.nonceStr, // 必填,生成签名的随机串
|
||||
signature: response.data.signature,// 必填,签名,见附录-JS-SDK使用权限签名算法
|
||||
// jsApiList: response.data.jsApiList, //必填,传入需要使用的接口名称
|
||||
jsApiList: ["getCurExternalContact", "getCurExternalChat", "getContext", "chooseImage","sendChatMessage","shareAppMessage"],
|
||||
success: function(data) {
|
||||
resolve(data);
|
||||
},
|
||||
fail: function(err) {
|
||||
if(err.errMsg.indexOf('function not exist') > -1){
|
||||
reject('版本过低请升级');
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}).catch(err=>{
|
||||
reject(err);
|
||||
})
|
||||
})
|
||||
|
||||
const agentConfig = new Promise((resolve, reject)=>{
|
||||
getWorkAgentConfig(location.href).then(res=>{
|
||||
wx.agentConfig({
|
||||
corpid: res.data.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
|
||||
agentid: res.data.agentid, // 必填,企业微信的应用id (e.g. 1000247)
|
||||
timestamp: res.data.timestamp, // 必填,生成签名的时间戳
|
||||
nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
|
||||
signature: res.data.signature,// 必填,签名,见附录-JS-SDK使用权限签名算法
|
||||
jsApiList: ["getCurExternalContact", "getCurExternalChat", "getContext", "chooseImage","sendChatMessage","shareAppMessage"]
|
||||
, //必填,传入需要使用的接口名称
|
||||
success: function(res) {
|
||||
resolve(res);
|
||||
},
|
||||
fail: function(res) {
|
||||
if(res.errMsg.indexOf('function not exist') > -1){
|
||||
reject('版本过低请升级');
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
82
main.js
Normal file
82
main.js
Normal file
@@ -0,0 +1,82 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
import store from './store'
|
||||
import Cache from './utils/cache'
|
||||
import util from 'utils/util'
|
||||
import configs from './config/app.js'
|
||||
import socket from './libs/new_chat.js'
|
||||
Vue.prototype.$util = util;
|
||||
Vue.prototype.$config = configs;
|
||||
Vue.prototype.$Cache = Cache;
|
||||
Vue.prototype.$eventHub = new Vue();
|
||||
Vue.prototype.$socket = new socket();
|
||||
Vue.config.productionTip = false;
|
||||
import home from "./components/home/index.vue"
|
||||
import skeleton from './components/skeleton/index.vue'
|
||||
import BaseMoney from './components/BaseMoney.vue';
|
||||
import BaseTag from './components/BaseTag.vue';
|
||||
import easyLoadimage from './components/easy-loadimage/easy-loadimage.vue'
|
||||
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
|
||||
Vue.component('home', home)
|
||||
Vue.component('skeleton', skeleton)
|
||||
Vue.component('BaseMoney', BaseMoney)
|
||||
Vue.component('BaseTag', BaseTag)
|
||||
Vue.component('baseDrawer', baseDrawer)
|
||||
Vue.component('easyLoadimage', easyLoadimage)
|
||||
// #ifdef H5
|
||||
|
||||
|
||||
import { parseQuery } from "./utils";
|
||||
import Auth from './libs/wechat';
|
||||
import { SPREAD } from './config/cache';
|
||||
Vue.prototype.$wechat = Auth;
|
||||
|
||||
|
||||
|
||||
let cookieName = "VCONSOLE",
|
||||
query = parseQuery(),
|
||||
vconsole = query[cookieName.toLowerCase()],
|
||||
md5Crmeb = "b14d1e9baeced9bb7525ab19ee35f2d2", //CRMEB MD5 加密开启vconsole模式
|
||||
md5UnCrmeb = "3dca2162c4e101b7656793a1af20295c"; //UN_CREMB MD5 加密关闭vconsole模式
|
||||
|
||||
if (vconsole !== undefined) {
|
||||
if (vconsole === md5UnCrmeb && Cache.has(cookieName))
|
||||
Cache.clear(cookieName);
|
||||
} else vconsole = Cache.get(cookieName);
|
||||
|
||||
import VConsole from './pages/extension/components/vconsole.min.js'
|
||||
|
||||
if (vconsole !== undefined && vconsole === md5Crmeb) {
|
||||
Cache.set(cookieName, md5Crmeb, 3600);
|
||||
let vConsole = new VConsole();
|
||||
}
|
||||
|
||||
// 统计代码
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://cdn.oss.9gt.net/js/es.js?version=prov3.5.1";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
// #endif
|
||||
|
||||
App.mpType = 'app'
|
||||
|
||||
|
||||
const app = new Vue({
|
||||
...App,
|
||||
store,
|
||||
Cache,
|
||||
})
|
||||
app.$mount();
|
||||
259
manifest.json
Normal file
259
manifest.json
Normal file
@@ -0,0 +1,259 @@
|
||||
{
|
||||
"name" : "DoubaShop",
|
||||
"appid" : "__UNI__52BA861",
|
||||
"description" : "兜爸商城",
|
||||
"versionName" : "3.5.1",
|
||||
"versionCode" : 351,
|
||||
"transformPx" : false,
|
||||
"sassImplementationName" : "node-sass",
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueCompiler" : "uni-app",
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"compatible" : {
|
||||
"ignoreVersion" : true
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAPTURE_AUDIO_OUTPUT\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
],
|
||||
"abiFilters" : [ "armeabi-v7a" ],
|
||||
"permissionExternalStorage" : {
|
||||
"request" : "none",
|
||||
"prompt" : "应用保存运行状态等信息,需要获取读写手机存储(系统提示为访问设备上的照片、媒体内容和文件)权限,请允许。"
|
||||
},
|
||||
"permissionPhoneState" : {
|
||||
"request" : "none",
|
||||
"prompt" : "为保证您正常、安全地使用,需要获取设备识别码(部分手机提示为获取手机号码)使用权限,请允许"
|
||||
},
|
||||
"minSdkVersion" : 21,
|
||||
"targetSdkVersion" : 30, // 建议设置为 30 或更高
|
||||
"compileSdkVersion" : 30
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {
|
||||
"capabilities" : {
|
||||
"entitlements" : {
|
||||
"com.apple.developer.associated-domains" : [ "applinks:pro.crmeb.net" ],
|
||||
"com.apple.developer.networking.wifi-info" : true,
|
||||
"com.apple.developer.networking.networkextension" : [ "packet-tunnel-provider" ]
|
||||
}
|
||||
},
|
||||
"privacyDescription" : {
|
||||
"NSLocationWhenInUseUsageDescription" : "根据客户地理位置推荐最近门店",
|
||||
"NSPhotoLibraryUsageDescription" : "上传用户头像保存分享海报",
|
||||
"NSPhotoLibraryAddUsageDescription" : "上传用户头像保存分享海报",
|
||||
"NSLocationAlwaysAndWhenInUseUsageDescription" : "根据客户地理位置推荐最近门店",
|
||||
"NSLocationAlwaysUsageDescription" : "根据客户地理位置推荐最近门店",
|
||||
"NSCameraUsageDescription" : "上传用户头像保存分享海报",
|
||||
"NSNetworkUsageDescription" : "此应用需要访问网络以获取数据"
|
||||
},
|
||||
"idfa" : true,
|
||||
"dSYMs" : false
|
||||
},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {
|
||||
"payment" : {
|
||||
"weixin" : {
|
||||
"__platform__" : [ "ios", "android" ],
|
||||
"appid" : "wx3e14a895971fbea6",
|
||||
"UniversalLinks" : "https://pro.crmeb.net/uni-universallinks/__UNI__7E0054B/"
|
||||
},
|
||||
"alipay" : {
|
||||
"__platform__" : [ "ios", "android" ]
|
||||
}
|
||||
},
|
||||
"share" : {
|
||||
"weixin" : {
|
||||
"appid" : "wx3e14a895971fbea6",
|
||||
"UniversalLinks" : "https://pro.crmeb.net/uni-universallinks/__UNI__7E0054B/"
|
||||
}
|
||||
},
|
||||
"push" : {},
|
||||
"maps" : {
|
||||
"amap" : {
|
||||
"appkey_ios" : "aeb768547b9d752891e37e1ca0a2b66d",
|
||||
"appkey_android" : "41ec5c3f4d110ce02a326210fe147be8"
|
||||
}
|
||||
},
|
||||
"oauth" : {
|
||||
"weixin" : {
|
||||
"appid" : "wx3e14a895971fbea6",
|
||||
"appsecret" : "ee83a6c94edbc5dd7a5b4614316d85a7",
|
||||
"UniversalLinks" : "https://pro.crmeb.net/uni-universallinks/__UNI__7E0054B/"
|
||||
},
|
||||
"apple" : {}
|
||||
},
|
||||
"ad" : {},
|
||||
"geolocation" : {
|
||||
"amap" : {
|
||||
"__platform__" : [ "ios", "android" ],
|
||||
"appkey_ios" : "aeb768547b9d752891e37e1ca0a2b66d",
|
||||
"appkey_android" : "41ec5c3f4d110ce02a326210fe147be8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"splashscreen" : {
|
||||
"androidStyle" : "common",
|
||||
"useOriginalMsgbox" : true
|
||||
},
|
||||
"icons" : {
|
||||
"android" : {
|
||||
"hdpi" : "unpackage/res/icons/72x72.png",
|
||||
"xhdpi" : "unpackage/res/icons/96x96.png",
|
||||
"xxhdpi" : "unpackage/res/icons/144x144.png",
|
||||
"xxxhdpi" : "unpackage/res/icons/192x192.png"
|
||||
},
|
||||
"ios" : {
|
||||
"appstore" : "unpackage/res/icons/1024x1024.png",
|
||||
"ipad" : {
|
||||
"app" : "unpackage/res/icons/76x76.png",
|
||||
"app@2x" : "unpackage/res/icons/152x152.png",
|
||||
"notification" : "unpackage/res/icons/20x20.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"proapp@2x" : "unpackage/res/icons/167x167.png",
|
||||
"settings" : "unpackage/res/icons/29x29.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"spotlight" : "unpackage/res/icons/40x40.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png"
|
||||
},
|
||||
"iphone" : {
|
||||
"app@2x" : "unpackage/res/icons/120x120.png",
|
||||
"app@3x" : "unpackage/res/icons/180x180.png",
|
||||
"notification@2x" : "unpackage/res/icons/40x40.png",
|
||||
"notification@3x" : "unpackage/res/icons/60x60.png",
|
||||
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||
"settings@3x" : "unpackage/res/icons/87x87.png",
|
||||
"spotlight@2x" : "unpackage/res/icons/80x80.png",
|
||||
"spotlight@3x" : "unpackage/res/icons/120x120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : false,
|
||||
"waiting" : false,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {
|
||||
"VideoPlayer" : {},
|
||||
"Share" : {},
|
||||
"OAuth" : {},
|
||||
"Payment" : {},
|
||||
"Maps" : {},
|
||||
"LivePusher" : {},
|
||||
"Geolocation" : {},
|
||||
"Barcode" : {},
|
||||
"Camera" : {}
|
||||
},
|
||||
"safearea" : {
|
||||
"bottom" : {
|
||||
"offset" : "none"
|
||||
}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"setting" : {
|
||||
"urlCheck" : false,
|
||||
"minified" : true,
|
||||
"postcss" : true,
|
||||
"es6" : true
|
||||
},
|
||||
"permission" : {
|
||||
"scope.userLocation" : {
|
||||
"desc" : "你的位置信息将用于和门店的距离长度"
|
||||
}
|
||||
},
|
||||
"requiredPrivateInfos" : [ "getLocation", "chooseLocation", "chooseAddress" ],
|
||||
"usingComponents" : true,
|
||||
/* "lazyCodeLoading" : "requiredComponents", */
|
||||
"optimization" : {
|
||||
"subPackages" : true
|
||||
},
|
||||
"appid" : "wx69fca123ccca532c"
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"h5" : {
|
||||
"devServer" : {
|
||||
"https" : false
|
||||
},
|
||||
"router" : {
|
||||
"mode" : "history",
|
||||
"base" : ""
|
||||
},
|
||||
"domain" : "",
|
||||
"sdkConfigs" : {
|
||||
"maps" : {
|
||||
"qqmap" : {
|
||||
"key" : "7TLBZ-WKSWN-23LF7-SITZ5-S44SJ-2BBG4"
|
||||
},
|
||||
"tencent" : {
|
||||
"key" : "NCWBZ-JZCE4-3CUUB-FO4F3-JQZMO-YQFV2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"permissions" : {
|
||||
"geolocation" : {
|
||||
"description" : "用于获取用户地理位置"
|
||||
}
|
||||
},
|
||||
"optimization" : {
|
||||
"treeShaking" : {
|
||||
"enable" : true
|
||||
}
|
||||
},
|
||||
"async" : {
|
||||
"timeout" : 200000
|
||||
},
|
||||
"title" : "加载中",
|
||||
"template" : "index.html"
|
||||
},
|
||||
"plus" : {
|
||||
"statusbar" : {
|
||||
"immersed" : true
|
||||
}
|
||||
}
|
||||
}
|
||||
/* "lazyCodeLoading" : "requiredComponents", */// "optimization" : {
|
||||
// "subPackages" : true
|
||||
// }
|
||||
|
||||
51
mixins/SendVerifyCode.js
Normal file
51
mixins/SendVerifyCode.js
Normal file
@@ -0,0 +1,51 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
disabled: false,
|
||||
text: "获取验证码",
|
||||
run: undefined,
|
||||
scrollTop: 0,
|
||||
};
|
||||
},
|
||||
// 向子组件传递滚动距离
|
||||
provide() {
|
||||
return {
|
||||
scrollTopFn: () => this.scrollTop,
|
||||
};
|
||||
},
|
||||
onPageScroll(e) {
|
||||
this.scrollTop = e.scrollTop;
|
||||
},
|
||||
methods: {
|
||||
sendCode() {
|
||||
if (this.disabled) return;
|
||||
this.disabled = true;
|
||||
let n = 60;
|
||||
this.text = "剩余 " + n + "s";
|
||||
this.run = setInterval(() => {
|
||||
n = n - 1;
|
||||
if (n < 0) {
|
||||
clearInterval(this.run);
|
||||
}
|
||||
this.text = "剩余 " + n + "s";
|
||||
if (this.text < "剩余 " + 0 + "s") {
|
||||
this.disabled = false;
|
||||
this.text = "重新获取";
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearInterval(this.run);
|
||||
},
|
||||
};
|
||||
33
mixins/color.js
Normal file
33
mixins/color.js
Normal file
@@ -0,0 +1,33 @@
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
colorStyle: '--view-theme: #e93323;--view-minorColorT:rgba(233, 51, 35, 0.1);--view-bntColor:#FE960F;--view-gradient:#FF7931',
|
||||
navigation: 0,
|
||||
colorNum: 0
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.colorStyle = uni.getStorageSync('viewColor')
|
||||
uni.$on('ok', data => {
|
||||
this.colorStyle = data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
colorData(){
|
||||
this.colorNum = uni.getStorageSync('statusColor')
|
||||
uni.$on('colorOk', data => {
|
||||
this.colorNum = data
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
365
mixins/skuSelect.js
Normal file
365
mixins/skuSelect.js
Normal file
@@ -0,0 +1,365 @@
|
||||
import {
|
||||
getCategoryList,
|
||||
getProductslist,
|
||||
getAttr,
|
||||
postCartNum
|
||||
} from '@/api/store.js';
|
||||
import {cartDel} from "@/api/order.js";
|
||||
import {toLogin} from '@/libs/login.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
attr: {
|
||||
cartAttr: false,
|
||||
productAttr: [],
|
||||
productSelect: {}
|
||||
},
|
||||
productValue: [],
|
||||
beforeCartNum: 0
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 默认选中属性
|
||||
*
|
||||
*/
|
||||
DefaultSelect: function() {
|
||||
let productAttr = this.attr.productAttr;
|
||||
let value = [];
|
||||
if (this.storeInfo.default_sku) {
|
||||
value = this.storeInfo.default_sku.split(',');
|
||||
} else {
|
||||
for (var key in this.productValue) {
|
||||
if (this.productValue[key].stock > 0) {
|
||||
value = this.attr.productAttr.length ? key.split(',') : [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < productAttr.length; i++) {
|
||||
this.$set(productAttr[i], "index", value[i]);
|
||||
}
|
||||
//sort();排序函数:数字-英文-汉字;
|
||||
let productSelect = this.productValue[value.join(",")];
|
||||
this.$set(this.attr.productSelect,"store_name",this.storeName);
|
||||
if (productSelect && productAttr.length) {
|
||||
this.$set(this.attr.productSelect, "image", productSelect.image);
|
||||
this.$set(this.attr.productSelect, "price", productSelect.price);
|
||||
this.$set(this.attr.productSelect, "stock", productSelect.stock);
|
||||
this.$set(this.attr.productSelect, "unique", productSelect.unique);
|
||||
this.$set(this.attr.productSelect, 'cart_num', this.storeInfo.min_qty ? this.storeInfo.min_qty : 1);
|
||||
this.$set(this.attr.productSelect, 'vip_price', productSelect.vip_price);
|
||||
this.$set(this, "attrValue", value.join(","));
|
||||
} else if (!productSelect && productAttr.length) {
|
||||
this.$set(this.attr.productSelect, "image", this.storeInfo.image);
|
||||
this.$set(this.attr.productSelect, "price", this.storeInfo.price);
|
||||
this.$set(this.attr.productSelect, "stock", 0);
|
||||
this.$set(this.attr.productSelect, "unique", "");
|
||||
this.$set(this.attr.productSelect, 'cart_num', this.storeInfo.min_qty ? this.storeInfo.min_qty : 1);
|
||||
this.$set(this, "attrValue", "");
|
||||
this.$set(this.attr.productSelect, 'vip_price', this.storeInfo.vip_price);
|
||||
} else if (!productSelect && !productAttr.length) {
|
||||
this.$set(this.attr.productSelect, "image", this.storeInfo.image);
|
||||
this.$set(this.attr.productSelect, "price", this.storeInfo.price);
|
||||
this.$set(this.attr.productSelect, "stock", this.storeInfo.stock);
|
||||
this.$set(this.attr.productSelect,"unique",this.storeInfo.unique || "");
|
||||
this.$set(this.attr.productSelect, 'cart_num', this.storeInfo.min_qty ? this.storeInfo.min_qty : 1);
|
||||
this.$set(this, "attrValue", "");
|
||||
this.$set(this.attr.productSelect, 'vip_price', this.storeInfo.vip_price);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 属性变动赋值
|
||||
*
|
||||
*/
|
||||
ChangeAttr: function(res) {
|
||||
let productSelect = this.productValue[res];
|
||||
if (!productSelect) {
|
||||
this.$set(this.attr.productSelect, 'image', this.storeInfo.image);
|
||||
this.$set(this.attr.productSelect, 'price', this.storeInfo.price);
|
||||
this.$set(this.attr.productSelect, 'ot_price', this.storeInfo.ot_price);
|
||||
this.$set(this.attr.productSelect, 'stock', 0);
|
||||
this.$set(this.attr.productSelect, 'unique', '');
|
||||
this.$set(this.attr.productSelect, 'cart_num', this.storeInfo.min_qty ? this.storeInfo.min_qty : 1);
|
||||
this.$set(this.attr.productSelect, 'vip_price', this.storeInfo.vip_price);
|
||||
this.$set(this, 'attrValue', '');
|
||||
this.$set(this, 'attrTxt', '请选择');
|
||||
}else{
|
||||
if (productSelect && productSelect.stock >= 0) {
|
||||
this.$set(this.attr.productSelect, "image", productSelect.image);
|
||||
this.$set(this.attr.productSelect, "price", productSelect.price);
|
||||
this.$set(this.attr.productSelect, "stock", productSelect.stock);
|
||||
this.$set(this.attr.productSelect, "unique", productSelect.unique);
|
||||
this.$set(this.attr.productSelect, 'vip_price', productSelect.vip_price);
|
||||
this.$set(this.attr.productSelect, 'cart_num', this.storeInfo.min_qty ? this.storeInfo.min_qty : 1);
|
||||
this.$set(this, "attrValue", res);
|
||||
} else {
|
||||
this.$set(this.attr.productSelect, 'image', this.storeInfo.image);
|
||||
this.$set(this.attr.productSelect, 'price', this.storeInfo.price);
|
||||
this.$set(this.attr.productSelect, 'stock', 0);
|
||||
this.$set(this.attr.productSelect, 'unique', '');
|
||||
this.$set(this.attr.productSelect, 'cart_num', this.storeInfo.min_qty ? this.storeInfo.min_qty : 1);
|
||||
this.$set(this.attr.productSelect, 'vip_price', this.storeInfo.vip_price);
|
||||
this.$set(this, 'attrValue', '');
|
||||
}
|
||||
}
|
||||
},
|
||||
attrVal(val) {
|
||||
this.$set(this.attr.productAttr[val.indexw], 'index', this.attr.productAttr[val.indexw].attr_values[val
|
||||
.indexn]);
|
||||
},
|
||||
/**
|
||||
* 购物车手动填写
|
||||
*
|
||||
*/
|
||||
iptCartNum: function(e) {
|
||||
this.$set(this.attr.productSelect, 'cart_num', e);
|
||||
},
|
||||
onMyEvent: function() {
|
||||
this.$set(this.attr, 'cartAttr', false);
|
||||
},
|
||||
// 改变多属性购物车
|
||||
ChangeCartNumDuo(changeValue) {
|
||||
//获取当前变动属性
|
||||
let productSelect = this.productValue[this.attrValue];
|
||||
//如果没有属性,赋值给商品默认库存
|
||||
if (productSelect === undefined && !this.attr.productAttr.length)
|
||||
productSelect = this.attr.productSelect;
|
||||
//无属性值即库存为0;不存在加减;
|
||||
if (productSelect === undefined) return;
|
||||
let stock = productSelect.stock || 0;
|
||||
let num = this.attr.productSelect;
|
||||
this.ChangeCartNum(changeValue, num, stock, 1);
|
||||
},
|
||||
// 改变单属性购物车
|
||||
ChangeCartNumDan(changeValue, index, item) {
|
||||
//如果是点击减少,并且该商品有起购数量,并且此时该商品在购物车的数量等于起购数量,就禁止再继续往下减
|
||||
if(!changeValue && item.min_qty && item.cart_num == item.min_qty) return
|
||||
let num = this.tempArr[index];
|
||||
let stock = this.tempArr[index].stock;
|
||||
//设置点击加号添加的数量设置为1
|
||||
this.beforeCartNum = 1;
|
||||
this.ChangeCartNum(changeValue, num, stock, 0, item.id);
|
||||
},
|
||||
ChangeSubDel: function(event) {
|
||||
let that = this,
|
||||
list = that.cartData.cartList,
|
||||
ids = [];
|
||||
list.forEach(item => {
|
||||
ids.push(item.id)
|
||||
});
|
||||
cartDel(ids.join(",")).then(res => {
|
||||
that.$set(that.cartData, 'cartList', []);
|
||||
that.cartData.iScart = false;
|
||||
that.totalPrice = 0.00;
|
||||
that.page = 1;
|
||||
that.loadend = false;
|
||||
that.tempArr = [];
|
||||
that.productslist();
|
||||
that.getCartNum();
|
||||
})
|
||||
},
|
||||
ChangeOneDel: function(id, index) {
|
||||
let that = this,
|
||||
list = that.cartData.cartList;
|
||||
cartDel(id.toString()).then(res => {
|
||||
list.splice(index, 1);
|
||||
if (!list.length) {
|
||||
that.cartData.iScart = false;
|
||||
that.page = 1;
|
||||
that.loadend = false;
|
||||
that.tempArr = [];
|
||||
that.productslist();
|
||||
};
|
||||
that.getCartNum();
|
||||
})
|
||||
},
|
||||
// 多规格加入购物车;
|
||||
goCatNum() {
|
||||
this.goCat(1, this.id, 1);
|
||||
},
|
||||
closeList(e) {
|
||||
this.$set(this.cartData, 'iScart', e);
|
||||
},
|
||||
/*
|
||||
* 已经加入购物车时的购物加减;
|
||||
* @param {changeValue} true 添加数量 false 减少数量
|
||||
* @param {index} 购物车列表下标
|
||||
*/
|
||||
ChangeCartList(changeValue, index) {
|
||||
let list = this.cartData.cartList;
|
||||
let item = list[index];
|
||||
let stock = list[index].trueStock;
|
||||
//判断该商品如果有起购数量,初次添加的购物数量为起购数量
|
||||
this.beforeCartNum = item.productInfo.min_qty ? item.productInfo.min_qty : 1;
|
||||
this.ChangeCartNum(changeValue, item, stock, 0, item.product_id, index, 1);
|
||||
if (!list.length) {
|
||||
this.cartData.iScart = false;
|
||||
this.page = 1;
|
||||
this.loadend = false;
|
||||
this.tempArr = [];
|
||||
this.productslist();
|
||||
}
|
||||
},
|
||||
// 购物车加减计算函数
|
||||
ChangeCartNum(changeValue, num, stock, isDuo, id, index, cart) {
|
||||
if (changeValue) {
|
||||
num.cart_num++;
|
||||
if (num.cart_num > stock) {
|
||||
if (isDuo) {
|
||||
this.$set(this.attr.productSelect, "cart_num", stock ? stock : 1);
|
||||
this.$set(this, "cart_num", stock ? stock : 1);
|
||||
} else {
|
||||
num.cart_num = stock ? stock : 0;
|
||||
this.$set(this, 'tempArr', this.tempArr);
|
||||
this.$set(this.cartData, 'cartList', this.cartData.cartList);
|
||||
}
|
||||
return this.$util.Tips({
|
||||
title: "该产品没有更多库存了"
|
||||
});
|
||||
} else {
|
||||
if (!isDuo) {
|
||||
if (cart) {
|
||||
this.goCat(0, id, 1, 1, num.product_attr_unique);
|
||||
this.getTotalPrice();
|
||||
} else {
|
||||
this.goCat(0, id, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
num.cart_num--;
|
||||
if (num.cart_num == 0) {
|
||||
this.cartData.cartList.splice(index, 1);
|
||||
if (isDuo) {
|
||||
this.$set(this.attr.productSelect, "cart_num", 1);
|
||||
this.$set(this, "cart_num", 1);
|
||||
}
|
||||
}
|
||||
if (num.cart_num < 0) {
|
||||
if (isDuo) {
|
||||
this.$set(this.attr.productSelect, "cart_num", 1);
|
||||
this.$set(this, "cart_num", 1);
|
||||
} else {
|
||||
num.cart_num = 0;
|
||||
this.$set(this, 'tempArr', this.tempArr);
|
||||
this.$set(this.cartData, 'cartList', this.cartData.cartList);
|
||||
}
|
||||
} else {
|
||||
if (!isDuo) {
|
||||
if (cart) {
|
||||
this.goCat(0, id, 0, 1, num.product_attr_unique);
|
||||
this.getTotalPrice();
|
||||
} else {
|
||||
this.goCat(0, id, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.tempArr.forEach((item)=>{
|
||||
if(item.id == id){
|
||||
item.cart_num = num.cart_num;
|
||||
}
|
||||
})
|
||||
},
|
||||
/*
|
||||
* 加入购物车
|
||||
*/
|
||||
goCat: function(duo, id, type, cart, unique) {
|
||||
let that = this;
|
||||
|
||||
if (duo) {
|
||||
let productSelect = that.productValue[this.attrValue];
|
||||
//如果有属性,没有选择,提示用户选择
|
||||
if (
|
||||
that.attr.productAttr.length &&
|
||||
productSelect === undefined
|
||||
)
|
||||
return that.$util.Tips({
|
||||
title: "产品库存不足,请选择其它属性"
|
||||
});
|
||||
}
|
||||
let q = {
|
||||
product_id: id,
|
||||
num: duo ? that.attr.productSelect.cart_num : that.beforeCartNum,
|
||||
type: type,
|
||||
unique: duo ? that.attr.productSelect.unique : cart ? unique : ""
|
||||
};
|
||||
postCartNum(q).then(function(res) {
|
||||
if (duo) {
|
||||
that.attr.cartAttr = false;
|
||||
// that.page = 1;
|
||||
// that.loadend = false;
|
||||
that.tempArr.forEach((item, index) => {
|
||||
if (item.id == that.id) {
|
||||
let arrtStock = that.attr.productSelect.stock
|
||||
let objNum = parseInt(item.cart_num) + parseInt(that.attr.productSelect.cart_num);
|
||||
item.cart_num = objNum > arrtStock?arrtStock:objNum
|
||||
}
|
||||
})
|
||||
// that.productslist();
|
||||
}
|
||||
that.$util.Tips({
|
||||
title: res.msg
|
||||
});
|
||||
that.getCartNum();
|
||||
if (!cart) {
|
||||
that.getCartList(1);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
return that.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
});
|
||||
},
|
||||
goCartDuo(item) {
|
||||
if (!this.isLogin) {
|
||||
toLogin();
|
||||
} else {
|
||||
if(item.cart_button == 0){
|
||||
if(item.is_presale_product){
|
||||
uni.navigateTo({
|
||||
url: `/pages/activity/goods_details/index?id=${item.id}&type=6`
|
||||
})
|
||||
}else{
|
||||
uni.navigateTo({
|
||||
url: `/pages/goods_details/index?id=${item.id}&fromType=1`
|
||||
})
|
||||
}
|
||||
}else{
|
||||
this.storeName = item.store_name;
|
||||
this.getAttrs(item.id);
|
||||
this.$set(this, 'id', item.id);
|
||||
this.$set(this.attr, 'cartAttr', true);
|
||||
}
|
||||
}
|
||||
},
|
||||
// 点击默认单属性购物车
|
||||
goCartDan(item, index) {
|
||||
if (!this.isLogin) {
|
||||
toLogin();
|
||||
} else {
|
||||
if(item.cart_button == 0){
|
||||
if(item.is_presale_product){
|
||||
uni.navigateTo({
|
||||
url: `/pages/activity/goods_details/index?id=${item.id}&type=6`
|
||||
})
|
||||
}else{
|
||||
uni.navigateTo({
|
||||
url: `/pages/goods_details/index?id=${item.id}&fromType=1`
|
||||
})
|
||||
}
|
||||
}else{
|
||||
//判断该商品如果有起购数量,初次添加的购物数量为起购数量
|
||||
item.cart_num = item.min_qty ? item.min_qty : 1;
|
||||
this.beforeCartNum = item.min_qty ? item.min_qty : 1;
|
||||
this.goCat(0, item.id, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
399
package-lock.json
generated
Normal file
399
package-lock.json
generated
Normal file
@@ -0,0 +1,399 @@
|
||||
{
|
||||
"name": "H5",
|
||||
"version": "1.1.41",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
|
||||
},
|
||||
"babel-code-frame": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
||||
"integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
|
||||
"requires": {
|
||||
"chalk": "^1.1.3",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"babel-core": {
|
||||
"version": "6.26.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
|
||||
"integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
|
||||
"requires": {
|
||||
"babel-code-frame": "^6.26.0",
|
||||
"babel-generator": "^6.26.0",
|
||||
"babel-helpers": "^6.24.1",
|
||||
"babel-messages": "^6.23.0",
|
||||
"babel-register": "^6.26.0",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"babel-template": "^6.26.0",
|
||||
"babel-traverse": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"babylon": "^6.18.0",
|
||||
"convert-source-map": "^1.5.1",
|
||||
"debug": "^2.6.9",
|
||||
"json5": "^0.5.1",
|
||||
"lodash": "^4.17.4",
|
||||
"minimatch": "^3.0.4",
|
||||
"path-is-absolute": "^1.0.1",
|
||||
"private": "^0.1.8",
|
||||
"slash": "^1.0.0",
|
||||
"source-map": "^0.5.7"
|
||||
}
|
||||
},
|
||||
"babel-generator": {
|
||||
"version": "6.26.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
|
||||
"integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
|
||||
"requires": {
|
||||
"babel-messages": "^6.23.0",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"detect-indent": "^4.0.0",
|
||||
"jsesc": "^1.3.0",
|
||||
"lodash": "^4.17.4",
|
||||
"source-map": "^0.5.7",
|
||||
"trim-right": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"babel-helpers": {
|
||||
"version": "6.24.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
|
||||
"integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.22.0",
|
||||
"babel-template": "^6.24.1"
|
||||
}
|
||||
},
|
||||
"babel-messages": {
|
||||
"version": "6.23.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
|
||||
"integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.22.0"
|
||||
}
|
||||
},
|
||||
"babel-register": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
|
||||
"integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
|
||||
"requires": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"core-js": "^2.5.0",
|
||||
"home-or-tmp": "^2.0.0",
|
||||
"lodash": "^4.17.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"source-map-support": "^0.4.15"
|
||||
}
|
||||
},
|
||||
"babel-runtime": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||
"requires": {
|
||||
"core-js": "^2.4.0",
|
||||
"regenerator-runtime": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"babel-template": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
|
||||
"integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"babel-traverse": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"babylon": "^6.18.0",
|
||||
"lodash": "^4.17.4"
|
||||
}
|
||||
},
|
||||
"babel-traverse": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
|
||||
"integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
|
||||
"requires": {
|
||||
"babel-code-frame": "^6.26.0",
|
||||
"babel-messages": "^6.23.0",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"babel-types": "^6.26.0",
|
||||
"babylon": "^6.18.0",
|
||||
"debug": "^2.6.8",
|
||||
"globals": "^9.18.0",
|
||||
"invariant": "^2.2.2",
|
||||
"lodash": "^4.17.4"
|
||||
}
|
||||
},
|
||||
"babel-types": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
|
||||
"integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.4",
|
||||
"to-fast-properties": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"babylon": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
|
||||
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"requires": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"convert-source-map": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
|
||||
"integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.1"
|
||||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "2.6.11",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
||||
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"detect-indent": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
|
||||
"integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
|
||||
"requires": {
|
||||
"repeating": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
|
||||
},
|
||||
"globals": {
|
||||
"version": "9.18.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
|
||||
"integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ=="
|
||||
},
|
||||
"has-ansi": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
||||
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"home-or-tmp": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
|
||||
"integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
|
||||
"requires": {
|
||||
"os-homedir": "^1.0.0",
|
||||
"os-tmpdir": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"invariant": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-finite": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
|
||||
"integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w=="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
||||
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
|
||||
},
|
||||
"jsesc": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
|
||||
"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s="
|
||||
},
|
||||
"json5": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"os-homedir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"private": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
|
||||
"integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||
},
|
||||
"repeating": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
|
||||
"integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
|
||||
"requires": {
|
||||
"is-finite": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"slash": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
|
||||
"integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.4.18",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
|
||||
"integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
|
||||
"requires": {
|
||||
"source-map": "^0.5.6"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
|
||||
},
|
||||
"to-fast-properties": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
|
||||
"integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
|
||||
},
|
||||
"trim-right": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
|
||||
"integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="
|
||||
},
|
||||
"uni-luck-draw": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npm.taobao.org/uni-luck-draw/download/uni-luck-draw-1.3.2.tgz",
|
||||
"integrity": "sha1-X6Njgb6lF7ATHwyRYtl9ehWQz2c=",
|
||||
"requires": {
|
||||
"lucky-canvas": "^1.5.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2107
pages.json
Normal file
2107
pages.json
Normal file
File diff suppressed because it is too large
Load Diff
184
pages/activity/bargain/index.vue
Normal file
184
pages/activity/bargain/index.vue
Normal file
@@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<view :style="colorStyle">
|
||||
<view class="px-20">
|
||||
<view class="order_card bg--w111-fff rd-24rpx pt-32 pb-32 pl-24 pr-24"
|
||||
v-for="(item, index) in bargain" :key="index">
|
||||
<view class="flex-between-center">
|
||||
<text class="fs-28 lh-40rpx">{{item.add_time}}</text>
|
||||
<text class="font-color fs-26" v-if="item.status === 1">活动进行中</text>
|
||||
<text class="font-color fs-26" v-else-if="item.status === 3">砍价成功</text>
|
||||
<text class="font-color fs-26" v-else>活动已结束</text>
|
||||
</view>
|
||||
<view class="flex-between-center mt-26">
|
||||
<easy-loadimage
|
||||
:image-src="item.image"
|
||||
width="136rpx"
|
||||
height="136rpx"
|
||||
borderRadius="16rpx"></easy-loadimage>
|
||||
<view class="flex-1 pl-20">
|
||||
<view class="w-504 line2 fs-28 lh-40rpx">{{item.title}}</view>
|
||||
<view class="flex items-baseline mt-20">
|
||||
<text class="fs-24 text--w111-999">已砍至</text>
|
||||
<baseMoney :money="item.residue_price" symbolSize="20" integerSize="32" decimalSize="20" weight></baseMoney>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pt-24 bt mt-32 flex-between-center">
|
||||
<view class="flex-y-center fs-24" v-if="item.status === 1">
|
||||
<text class="pr-12 text--w111-999">剩余:</text>
|
||||
<count-down
|
||||
justify-left="justify-content:left"
|
||||
:is-day="true"
|
||||
tip-text=" "
|
||||
day-text=" "
|
||||
hour-text="时"
|
||||
minute-text="分"
|
||||
second-text="秒"
|
||||
dotColor="#999"
|
||||
:datatime="item.datatime"></count-down>
|
||||
</view>
|
||||
<text class="pr-12 text--w111-999 fs-24" v-if="item.status === 2">活动已结束</text>
|
||||
<text class="pr-12 text--w111-999 fs-24" v-if="item.status === 3">砍价已成功</text>
|
||||
<view class="flex">
|
||||
<view class="btn w-154 h-56 rd-30rpx flex-center fs-24 border_ccc"
|
||||
v-if="item.status === 1"
|
||||
@tap="getBargainUserCancel(item.bargain_id)"
|
||||
>取消活动</view>
|
||||
<view class="btn w-154 h-56 rd-30rpx flex-center fs-24 bg-color text--w111-fff"
|
||||
v-if="item.status === 1"
|
||||
@tap="goDetail(item.bargain_id)"
|
||||
>{{item.pay_status ? '立即付款' : '继续砍价'}}</view>
|
||||
<view class="btn w-154 h-56 rd-30rpx flex-center fs-24 bg-color text--w111-fff"
|
||||
v-if="[2,3].includes(item.status)" @tap="goPage('/pages/activity/goods_bargain/index')">重开一个</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<Loading :loaded="status" :loading="loadingList"></Loading>
|
||||
</view>
|
||||
<view class="px-20 mt-20" v-if="!bargain.length">
|
||||
<emptyPage title="暂无砍价记录~" src="/statics/images/noOrder.gif"></emptyPage>
|
||||
</view>
|
||||
<home></home>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import CountDown from "@/components/countDown";
|
||||
import emptyPage from '@/components/emptyPage.vue'
|
||||
import {
|
||||
getBargainUserList,
|
||||
getBargainUserCancel
|
||||
} from "@/api/activity";
|
||||
import { getUserInfo } from '@/api/user.js';
|
||||
import Loading from "@/components/Loading";
|
||||
import colors from "@/mixins/color";
|
||||
export default {
|
||||
name: "BargainRecord",
|
||||
components: {
|
||||
CountDown,
|
||||
Loading,
|
||||
emptyPage,
|
||||
},
|
||||
props: {},
|
||||
mixins: [colors],
|
||||
data: function() {
|
||||
return {
|
||||
bargain: [],
|
||||
status: false, //砍价列表是否获取完成 false 未完成 true 完成
|
||||
loadingList: false, //当前接口是否请求完成 false 完成 true 未完成
|
||||
page: 1, //页码
|
||||
limit: 20, //数量
|
||||
userInfo: {}
|
||||
};
|
||||
},
|
||||
onLoad: function() {
|
||||
this.getBargainUserList();
|
||||
this.getUserInfo();
|
||||
},
|
||||
onShow(){
|
||||
uni.removeStorageSync('form_type_cart');
|
||||
},
|
||||
methods: {
|
||||
goDetail: function(id) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/activity/goods_bargain_details/index?id=${id}&spid=${this.userInfo.uid}`
|
||||
})
|
||||
},
|
||||
getBargainUserList: function() {
|
||||
var that = this;
|
||||
if (that.loadingList) return;
|
||||
if (that.status) return;
|
||||
getBargainUserList({
|
||||
page: that.page,
|
||||
limit: that.limit
|
||||
})
|
||||
.then(res => {
|
||||
that.status = res.data.length < that.limit;
|
||||
that.bargain.push.apply(that.bargain, res.data);
|
||||
that.page++;
|
||||
that.loadingList = false;
|
||||
})
|
||||
.catch(res => {
|
||||
that.$util.Tips({
|
||||
title: res
|
||||
})
|
||||
});
|
||||
},
|
||||
getBargainUserCancel: function(bargainId) {
|
||||
var that = this;
|
||||
getBargainUserCancel({
|
||||
bargainId: bargainId
|
||||
})
|
||||
.then(res => {
|
||||
that.status = false;
|
||||
that.loadingList = false;
|
||||
that.page = 1;
|
||||
that.bargain = [];
|
||||
that.getBargainUserList();
|
||||
that.$util.Tips({
|
||||
title: res.msg
|
||||
})
|
||||
})
|
||||
.catch(res => {
|
||||
that.$util.Tips({
|
||||
title: res
|
||||
})
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 获取个人用户信息
|
||||
*/
|
||||
getUserInfo: function() {
|
||||
let that = this;
|
||||
getUserInfo().then(res => {
|
||||
that.userInfo = res.data;
|
||||
});
|
||||
},
|
||||
goPage(url){
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
this.getBargainUserList();
|
||||
},
|
||||
onPageScroll(object) {
|
||||
uni.$emit('scroll');
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.order_card{
|
||||
margin-top:20rpx;
|
||||
}
|
||||
.border_ccc {
|
||||
border: 1rpx solid #ccc;
|
||||
}
|
||||
.bt{
|
||||
border-top: 1rpx solid #eee;
|
||||
}
|
||||
.btn ~ .btn{
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
</style>
|
||||
445
pages/activity/coupon/index.vue
Normal file
445
pages/activity/coupon/index.vue
Normal file
@@ -0,0 +1,445 @@
|
||||
<template>
|
||||
<view :style="colorStyle">
|
||||
<view class="w-full h-400 relative z-10" :style="{'height': (186 + sysHeight) * 2 + 'rpx', 'background' : headerBg}">
|
||||
<NavBar titleText="领券中心"
|
||||
textSize="34rpx"
|
||||
:bagColor="pageScrollStatus ? 'var(--view-theme)' : 'transparent'"
|
||||
iconColor="#ffffff"
|
||||
textColor="#ffffff"
|
||||
showBack></NavBar>
|
||||
<view class="abs-box flex-col">
|
||||
<image src="../static/get_coupon_text.png" class="w-184 h-46"></image>
|
||||
<text class="fs-24 lh-34rpx text--w111-fff pt-20">天天来领券,优惠看的见</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="relative rd-t-40rpx bg--w111-f5f5f5 w-full content">
|
||||
<view class="_box flex-between-center text--w111-666 fs-30 lh-42rpx"
|
||||
:class="pageScrollStatus ? '' : 'rd-t-40rpx'"
|
||||
:style="{'top': (38 + sysHeight) * 2 + 'rpx'}">
|
||||
<text :class="current == 0 ? 'font-num fw-500' : ''" @tap="changeTab(0)">默认排序</text>
|
||||
<view class="flex-y-center" @tap="changeTab(1)">
|
||||
<text :class="current == 1 ? 'font-num fw-500' : ''">最新</text>
|
||||
<text v-show="params.timeOrder == 'desc'" class="iconfont icon-ic_down2 fs-14 ml-6 font-num"></text>
|
||||
<text v-show="params.timeOrder == 'asc'" class="iconfont icon-ic_up2 fs-14 ml-6 font-num"></text>
|
||||
<text v-show="params.timeOrder == ''" class="iconfont icon-ic_down2 fs-14 ml-6"></text>
|
||||
<!-- timeOrder -->
|
||||
</view>
|
||||
<view class="flex-y-center" @tap="changeTab(2)">
|
||||
<text :class="current == 2 ? 'font-num fw-500' : ''">价值</text>
|
||||
<text v-show="params.priceOrder == 'desc'" class="iconfont icon-ic_down2 fs-14 ml-6 font-num"></text>
|
||||
<text v-show="params.priceOrder == 'asc'" class="iconfont icon-ic_up2 fs-14 ml-6 font-num"></text>
|
||||
<text v-show="params.priceOrder == ''" class="iconfont icon-ic_down2 fs-14 ml-6"></text>
|
||||
</view>
|
||||
<view class="flex-y-center" @tap="showDrop = !showDrop">
|
||||
<text class="menu_line"></text>
|
||||
<text>筛选</text>
|
||||
<text class="iconfont icon-ic_sort pl-8"></text>
|
||||
</view>
|
||||
<view class="drop-box bg--w111-f5f5f5" v-if="showDrop">
|
||||
<scroll-view scroll-x="true" class="white-nowrap vertical-middle w-full" show-scrollbar="false">
|
||||
<view class="inline-block h-52 rd-28rpx px-28 lh-52rpx text-center fs-24 bg--w111-fff mr-24"
|
||||
v-for="(item, index) in navList" :key="index"
|
||||
:class="params.type === item.type ? 'active-tab' : ''"
|
||||
@tap="setType(item.type)">{{item.name}}</view>
|
||||
</scroll-view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="px-20" v-if="couponsList.length">
|
||||
<view class="relative card-item" v-for="(item,index) in couponsList" :key="index">
|
||||
<view class="card w-full h-200 bg--w111-fff rd-24rpx p-20 flex justify-between"
|
||||
:class="{svip: item.category == 2}">
|
||||
<text class="pr-8 svip-cup" v-if="item.category == 2">svip</text>
|
||||
<view class="flex">
|
||||
<easy-loadimage
|
||||
mode="aspectFit"
|
||||
:image-src="item.products[0].image"
|
||||
width="160rpx"
|
||||
height="160rpx"
|
||||
borderRadius="16rpx" v-if="item.products[0] && item.products[0].image"></easy-loadimage>
|
||||
<view class="w-160 h-160 rd-16rpx flex-center fs-22 text--w111-999" v-else>暂无商品</view>
|
||||
<view class="w-338 pl-24">
|
||||
<view class="w-286 h-72 lh-36rpx line2 fw-500" :class="item.is_use ? 'text--w111-ccc' : ''">
|
||||
{{item.title}}</view>
|
||||
<view class="fs-20 lh-28rpx mt-8" :class="item.is_use ? 'text--w111-ccc' : 'text--w111-666'"
|
||||
v-if="item.coupon_time">领取后{{item.coupon_time}}天内可用</view>
|
||||
<view class="fs-20 lh-28rpx mt-8" :class="item.is_use ? 'text--w111-ccc' : 'text--w111-666'"
|
||||
v-else>{{ item.start_time ? item.start_time + '-' : '' }}{{ item.end_time }}</view>
|
||||
<view class="flex-y-center fs-20 text--w111-999 lh-28rpx mt-20">
|
||||
<text>{{item.type | typeFilter}}</text>
|
||||
<view v-show="item.rule" @tap="toggleRule(item)">
|
||||
<text class="pl-8"> | 查看用券规则</text>
|
||||
<text class="iconfont icon-ic_downarrow fs-20 ml-4"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-1 flex-col flex-center">
|
||||
<baseMoney
|
||||
:money="item.coupon_price"
|
||||
symbolSize="28"
|
||||
integerSize="44"
|
||||
decimalSize="28"
|
||||
:color="item.is_use ? '#cccccc' : item.receive_type === 4 ? '#333' : 'var(--view-theme)'"
|
||||
isCoupon
|
||||
v-if="item.coupon_type==1"></baseMoney>
|
||||
<view v-else class="fs-44 SemiBold"
|
||||
:style="{color: item.is_use ? '#cccccc' : item.receive_type === 4 ? '#333' : 'var(--view-theme)'}"
|
||||
>{{ parseFloat(item.coupon_price) / 10 }} <text class="pingfang fs-28 pl-4">折</text></view>
|
||||
<text class="fs-20 lh-28rpx mt-8"
|
||||
:class="item.is_use ? 'text--w111-ccc' : 'font-num'" v-show="item.use_min_price == 0">无门槛券</text>
|
||||
<text class="fs-20 lh-28rpx mt-8"
|
||||
:class="item.is_use ? 'text--w111-ccc' : 'font-num'" v-show="item.use_min_price != 0">满{{item.use_min_price}}可用</text>
|
||||
<view class="w-128 h-48 rd-30rpx flex-center fs-20 bg-hui text--w111-fff mt-16" v-if="item.is_use == true">已领取</view>
|
||||
<view class="w-128 h-48 rd-30rpx flex-center fs-20 bg-hui text--w111-fff mt-16" v-else-if="item.is_use == 2">已领完</view>
|
||||
<view class="w-128 h-48 rd-30rpx flex-center fs-20 bg-gradient text--w111-fff mt-16" v-else
|
||||
@tap="getCoupon(item, index)">立即领取</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="rule-desc" v-html="item.rule" v-show="item.ruleShow"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class='loadingicon flex-center' v-if="couponsList.length">
|
||||
<text class='loading iconfont icon-jiazai' :hidden='loading==false'></text>{{loadTitle}}
|
||||
</view>
|
||||
<view class="px-20" v-if="!couponsList.length">
|
||||
<emptyPage title="暂无优惠券,去看点别的吧~" src="/statics/images/noCoupon.gif"></emptyPage>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mask" v-if="showDrop" @tap="showDrop = false"></view>
|
||||
<home></home>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let sysHeight = uni.getWindowInfo().statusBarHeight;
|
||||
import { getCoupons, setCouponReceive } from '@/api/api.js';
|
||||
import emptyPage from '@/components/emptyPage.vue';
|
||||
import NavBar from "@/components/NavBar.vue"
|
||||
import { toLogin } from '@/libs/login.js';
|
||||
import { mapGetters } from "vuex";
|
||||
import colors from '@/mixins/color.js';
|
||||
import {HTTP_REQUEST_URL} from '@/config/app';
|
||||
export default {
|
||||
mixins:[colors],
|
||||
components:{ emptyPage, NavBar },
|
||||
data() {
|
||||
return {
|
||||
sysHeight:sysHeight,
|
||||
couponsList: [],
|
||||
loading: false,
|
||||
loadend: false,
|
||||
loadTitle: '加载更多', //提示语
|
||||
params:{
|
||||
page: 1,
|
||||
limit: 20,
|
||||
type: '',
|
||||
defaultOrder: 1,
|
||||
timeOrder: '',
|
||||
priceOrder: ''
|
||||
},
|
||||
isAuto: false, //没有授权的不会自动授权
|
||||
isShowAuth: false, //是否隐藏授权
|
||||
navList: [
|
||||
{name: '全部',type: ''},
|
||||
{name: '快过期',type: -1},
|
||||
{name: '通用券',type: 0},
|
||||
{name: '品类券',type: 1},
|
||||
{name: '商品券',type: 2},
|
||||
{name: '品牌券',type: 3},
|
||||
],
|
||||
count: 0,
|
||||
imgHost:HTTP_REQUEST_URL,
|
||||
pageScrollStatus:false,
|
||||
showDrop: false,
|
||||
current:0,
|
||||
price: 0,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
isLogin: {
|
||||
handler: function(newV, oldV) {
|
||||
if (newV) {
|
||||
this.getUseCoupons();
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
},
|
||||
computed:{
|
||||
...mapGetters(['isLogin']),
|
||||
headerBg(){
|
||||
return 'url('+this.imgHost+'/statics/images/get_coupon_bg.png'+')' + 'no-repeat center center/100% 100%, linear-gradient(90deg, var(--view-gradient) 0%, var(--view-theme) 100%)'
|
||||
}
|
||||
},
|
||||
filters:{
|
||||
typeFilter(val){
|
||||
let obj = {
|
||||
0: '通用券',
|
||||
1: '品类券',
|
||||
2: '商品券',
|
||||
3: '品牌券',
|
||||
};
|
||||
return obj[val]
|
||||
}
|
||||
},
|
||||
onPageScroll(object) {
|
||||
if (object.scrollTop > 130) {
|
||||
this.pageScrollStatus = true;
|
||||
} else if (object.scrollTop < 130) {
|
||||
this.pageScrollStatus = false;
|
||||
}
|
||||
uni.$emit('scroll');
|
||||
},
|
||||
onLoad() {
|
||||
if (this.isLogin) {
|
||||
this.getUseCoupons();
|
||||
} else {
|
||||
toLogin()
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {
|
||||
this.getUseCoupons();
|
||||
},
|
||||
//#ifdef MP
|
||||
onShareAppMessage() {
|
||||
let that = this;
|
||||
return {
|
||||
title: '领券中心',
|
||||
path: '/pages/activity/coupon/index?spid=' + that.$store.state.app.uid,
|
||||
// desc: ''
|
||||
};
|
||||
},
|
||||
//分享到朋友圈
|
||||
onShareTimeline: function() {
|
||||
let that = this;
|
||||
return {
|
||||
title: '领券中心',
|
||||
path: '/pages/activity/coupon/index?spid=' + + that.$store.state.app.uid,
|
||||
// desc: ''
|
||||
};
|
||||
},
|
||||
//#endif
|
||||
methods: {
|
||||
changeTab(val){
|
||||
this.current = val;
|
||||
if(val == 0){
|
||||
this.params.defaultOrder = 1;
|
||||
this.params.timeOrder = '';
|
||||
this.params.priceOrder = '';
|
||||
}else if(val == 1){
|
||||
if(this.params.timeOrder == '') {
|
||||
this.params.timeOrder = 'asc'
|
||||
}else if (this.params.timeOrder == 'asc'){
|
||||
this.params.timeOrder = 'desc'
|
||||
}else if(this.params.timeOrder == 'desc'){
|
||||
this.params.timeOrder = ''
|
||||
}
|
||||
this.params.defaultOrder = '';
|
||||
this.params.priceOrder = '';
|
||||
} else if(val == 2){
|
||||
if(this.params.priceOrder == '') {
|
||||
this.params.priceOrder = 'asc'
|
||||
}else if (this.params.priceOrder == 'asc'){
|
||||
this.params.priceOrder = 'desc'
|
||||
}else if(this.params.priceOrder == 'desc'){
|
||||
this.params.priceOrder = ''
|
||||
}
|
||||
this.params.defaultOrder = '';
|
||||
this.params.timeOrder = '';
|
||||
}
|
||||
this.couponsList = [];
|
||||
this.loadend = false;
|
||||
this.loading = false;
|
||||
this.params.page = 1;
|
||||
this.getUseCoupons();
|
||||
},
|
||||
toggleRule(item){
|
||||
item.ruleShow = !item.ruleShow
|
||||
},
|
||||
backPage(){
|
||||
uni.navigateBack()
|
||||
},
|
||||
goDetails(item){
|
||||
uni.navigateTo({
|
||||
url: '/pages/goods_details/index?id=' + item.id
|
||||
})
|
||||
},
|
||||
getCoupon: function(item, index) {
|
||||
let that = this;
|
||||
let list = that.couponsList;
|
||||
//领取优惠券
|
||||
setCouponReceive(item.id).then(function(res) {
|
||||
if(res.data.receive_count >= item.receive_limit){
|
||||
list[index].is_use = true;
|
||||
}
|
||||
that.$set(that, 'couponsList', list);
|
||||
that.$util.Tips({
|
||||
title: '领取成功'
|
||||
});
|
||||
}).catch(error => {
|
||||
return that.$util.Tips({
|
||||
title: error
|
||||
});
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 获取领取优惠券列表
|
||||
*/
|
||||
getUseCoupons: function() {
|
||||
let that = this
|
||||
if (this.loadend) return false;
|
||||
if (this.loading) return false;
|
||||
that.loading = true;
|
||||
that.loadTitle = '加载更多';
|
||||
getCoupons(this.params).then(res => {
|
||||
let list = res.data.list,
|
||||
loadend = list.length < that.params.limit,
|
||||
countIndex = [];
|
||||
list.map(item=>{
|
||||
this.$set(item,'ruleShow',false);
|
||||
})
|
||||
let couponsList = that.$util.SplitArray(list, that.couponsList);
|
||||
that.$set(that, 'couponsList', couponsList);
|
||||
that.loadend = loadend;
|
||||
that.loading = false;
|
||||
that.loadTitle = loadend ? '没有更多内容啦~' : '加载更多';
|
||||
that.params.page++;
|
||||
}).catch(err => {
|
||||
that.loading = false;
|
||||
that.loadTitle = '加载更多';
|
||||
});
|
||||
},
|
||||
setType(type) {
|
||||
if (this.params.type !== type) {
|
||||
this.params.type = type;
|
||||
}else{
|
||||
this.params.type = '';
|
||||
}
|
||||
this.params.page = 1;
|
||||
this.couponsList = [];
|
||||
this.loadend = false;
|
||||
this.showDrop = false;
|
||||
this.getUseCoupons();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.abs-box{
|
||||
width: 264rpx;
|
||||
position: absolute;
|
||||
left: 48rpx;
|
||||
bottom: 80rpx;
|
||||
}
|
||||
.content{
|
||||
top: -44rpx;
|
||||
}
|
||||
.menu_line {
|
||||
width: 1rpx;
|
||||
height: 26rpx;
|
||||
background: #ccc;
|
||||
margin: 0 32rpx 0 20rpx;
|
||||
}
|
||||
._box{
|
||||
padding: 28rpx 32rpx;
|
||||
background: #f5f5f5;
|
||||
position: sticky;
|
||||
z-index: 99;
|
||||
}
|
||||
.drop-box{
|
||||
width: 100%;
|
||||
// height: 102rpx;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 94rpx;
|
||||
border-radius: 0 0 40rpx 40rpx;
|
||||
z-index: 199;
|
||||
padding: 10rpx 32rpx 24rpx;
|
||||
}
|
||||
.active-tab{
|
||||
background: var(--view-minorColorT);
|
||||
color: var(--view-theme);
|
||||
border: 1px solid var(--view-theme);
|
||||
}
|
||||
.svip .font-num{
|
||||
color: #333333 !important;
|
||||
}
|
||||
.svip .bg-gradient{
|
||||
background: linear-gradient(90deg, #584834 0%, #32302D 100%);
|
||||
color: #FACC7D;
|
||||
}
|
||||
.bg-hui{
|
||||
color: #ffffff !important;
|
||||
background: #cccccc !important;
|
||||
}
|
||||
.indent{
|
||||
text-indent: 60rpx;
|
||||
}
|
||||
.card{
|
||||
background-image:
|
||||
radial-gradient(circle at 500rpx top, #f5f5f5, #f5f5f5 10rpx, transparent 11rpx),
|
||||
radial-gradient(circle at 500rpx bottom, #f5f5f5, #f5f5f5 10rpx, transparent 11rpx);
|
||||
position: relative;
|
||||
&:before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 500rpx;
|
||||
top: 16rpx;
|
||||
height: 168rpx;
|
||||
border-left: 2px dotted #ddd;
|
||||
}
|
||||
.name {
|
||||
width: 286rpx;
|
||||
height: 80rpx;
|
||||
line-height: 40rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.type-tag{
|
||||
display: inline-block;
|
||||
background: var(--view-minorColorT);
|
||||
color: var(--view-theme);
|
||||
border-radius: 14rpx;
|
||||
padding: 2rpx 10rpx;
|
||||
font-size: 20rpx;
|
||||
margin-right: 8rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
.card-item ~ .card-item{
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
.rule-desc{
|
||||
margin-top: -16rpx;
|
||||
padding: 40rpx 24rpx 24rpx;
|
||||
white-space: pre-wrap;
|
||||
font-size: 20rpx;
|
||||
line-height: 28rpx;
|
||||
background: linear-gradient(180deg, #F7F7F7 0%, #FFFFFF 100%);
|
||||
border-radius: 0 0 24rpx 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
.SemiBold{
|
||||
font-family: 'SemiBold'
|
||||
}
|
||||
.pingfang{
|
||||
font-family: PingFang SC, PingFang SC;
|
||||
}
|
||||
.svip-cup{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 20rpx 0 20rpx 0;
|
||||
background-color: #FFD700;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
padding-left: 10rpx;
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
91
pages/activity/giftCard/exchange.vue
Normal file
91
pages/activity/giftCard/exchange.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="bg-card" :style="{backgroundImage:headerBg}"></view>
|
||||
<view class="bg--w111-fff rd-24rpx form-card">
|
||||
<!-- <view class="fs-30 fw-500 lh-42rpx text-center">卡券兑换</view> -->
|
||||
<view class="w-full bg--w111-f9f9f9 rd-12rpx pl-24 mt-38">
|
||||
<input type="text" v-model="cardForm.card_number" placeholder="请输入卡号"
|
||||
placeholder-class="fs-30 text--w111-b3b3b3" class="w-full h-88 fs-30 lh-42rpx" />
|
||||
</view>
|
||||
<view class="w-full bg--w111-f9f9f9 rd-12rpx pl-24 mt-32">
|
||||
<input type="text" v-model="cardForm.card_pwd" placeholder="请输入密码"
|
||||
placeholder-class="fs-30 text--w111-b3b3b3" class="w-full h-88 fs-30 lh-42rpx" />
|
||||
</view>
|
||||
<button class="w-full h-88 rd-44rpx flex-center text--w111-fff bg-btn fs-28 mt-54" :disabled="disabled" @tap="exchangeConfirm">立即验证</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import { giftCardGetInfoApi } from "@/api/activity.js";
|
||||
import { HTTP_REQUEST_URL } from '@/config/app';
|
||||
import { mapState, mapGetters } from 'vuex';
|
||||
import { toLogin } from '@/libs/login.js';
|
||||
export default {
|
||||
name: "",
|
||||
data(){
|
||||
return {
|
||||
cardForm:{
|
||||
card_number:"",
|
||||
card_pwd: ""
|
||||
},
|
||||
disabled: false
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
...mapGetters(['isLogin']),
|
||||
headerBg(){
|
||||
return 'url('+ HTTP_REQUEST_URL +'/statics/images/activity/gift_bg.png'+')'
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
|
||||
},
|
||||
methods:{
|
||||
exchangeConfirm(){
|
||||
if(this.isLogin){
|
||||
giftCardGetInfoApi(this.cardForm).then(res=>{
|
||||
this.disabled = false;
|
||||
uni.navigateTo({
|
||||
url: "/pages/activity/giftCard/info?card_number=" + this.cardForm.card_number + '&card_pwd=' + this.cardForm.card_pwd
|
||||
})
|
||||
}).catch(err=>{
|
||||
this.disabled = false;
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
})
|
||||
})
|
||||
}else{
|
||||
toLogin();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.form-card uni-button[disabled] {
|
||||
background: #cccccc;
|
||||
color: #fff;
|
||||
}
|
||||
.container{
|
||||
height: 100vh;
|
||||
background: #FFEED8;
|
||||
}
|
||||
.bg-card{
|
||||
height: 648rpx;
|
||||
background-size: 100% 648rpx;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.form-card{
|
||||
width: 670rpx;
|
||||
height: 532rpx;
|
||||
position: fixed;
|
||||
top: 392rpx;
|
||||
left: 42rpx;
|
||||
z-index: 10;
|
||||
padding: 40rpx 40rpx 60rpx;
|
||||
}
|
||||
.bg-btn{
|
||||
background: linear-gradient( 90deg, #FF7931 0%, #E93323 100%);
|
||||
}
|
||||
</style>
|
||||
274
pages/activity/giftCard/info.vue
Normal file
274
pages/activity/giftCard/info.vue
Normal file
@@ -0,0 +1,274 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="p-20">
|
||||
<view class="relative">
|
||||
<image class="w-full h-400 rd-24rpx block" mode="aspectFill" :src="cardInfo.cover_image"></image>
|
||||
<view class="gift-badge px-14 rd-40rpx flex-center z-10">
|
||||
<text class="iconfont icon-ic_card3 fs-32 text-yellow" v-show="cardInfo.type == 1"></text>
|
||||
<text class="iconfont icon-ic_gift2 fs-32 text-red" v-show="cardInfo.type == 2"></text>
|
||||
<text class="fs-24 pl-8" v-show="cardInfo.type == 1">{{cardInfo.balance}}元礼品卡</text>
|
||||
<text class="fs-24 pl-8" v-show="cardInfo.type == 2">兑换卡</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="w-full bg--w111-fff rd-16rpx px-24 mt-20" v-if="cardInfo.type == 2">
|
||||
<view class="flex-between-center pt-32">
|
||||
<view class="fs-28">可兑换商品
|
||||
<text class="fs-24 text--w111-999 pl-12" v-if="cardInfo.exchange_type == 1">该兑换卡可兑换以下商品</text>
|
||||
<text class="fs-24 text--w111-999 pl-12" v-else>任选 <text class="Regular text-red">{{ cardInfo.gift_num }}</text> 件兑换</text>
|
||||
</view>
|
||||
<text class="fs-28" v-if="cardInfo.exchange_type == 2">
|
||||
<text class="text-red">{{ totalLimitNum }}</text> /{{cardInfo.gift_num}}
|
||||
</text>
|
||||
</view>
|
||||
<view class="pb-32 product-box">
|
||||
<view class="mt-24 flex" v-for="(item, index) in cardInfo.product" :key="index">
|
||||
<image class="block w-200 h-200 rd-16rpx" :src="item.image"></image>
|
||||
<view class="flex-1 h-200 flex-col justify-between pl-20">
|
||||
<view>
|
||||
<view class="w-444 line2 fs-28 h-80 lh-40rpx">{{ item.store_name }}</view>
|
||||
<view class="inline-block max-w-444 h-38 lh-38rpx mt-8 bg--w111-f5f5f5 text--w111-999 rd-20rpx px-12 fs-22 line1">
|
||||
{{ item.suk }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-between-center">
|
||||
<baseMoney :money="item.price"
|
||||
symbolSize="24"
|
||||
integerSize="36"
|
||||
decimalSize="24"
|
||||
color="#e93323"
|
||||
weight></baseMoney>
|
||||
<text class='Regular fs-28' v-if="cardInfo.exchange_type == 1">x{{ item.limit_num }}</text>
|
||||
<view class="flex-y-center" v-else>
|
||||
<button class="w-44 h-44 flex-center"
|
||||
:disabled="item.limit_num <= 0"
|
||||
@click="decreaseLimitNum(index)">
|
||||
<text class="iconfont icon-ic_Reduce fs-24"></text>
|
||||
</button>
|
||||
<view class='w-88 h-44 text-center lh-44rpx bg--w111-f5f5f5'>{{ item.limit_num }}</view>
|
||||
<button class="w-44 h-44 flex-center"
|
||||
:disabled="totalLimitNum >= cardInfo.gift_num"
|
||||
@click="increaseLimitNum(index)">
|
||||
<text class="iconfont icon-ic_increase fs-24"></text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="w-full bg--w111-fff rd-16rpx p-24 mt-20 fs-28 lh-42rpx">
|
||||
<view class="pb-20" v-if="cardInfo.type == 1">储值金额<text class="fs-26 text--w111-666 pl-16">¥{{cardInfo.balance}}</text></view>
|
||||
<view>有效期至:<text class="fs-26 text--w111-666 pl-16">{{ cardInfo.valid_type == 1 ? '永久有效' : cardInfo.fixed_time[1] }}</text></view>
|
||||
|
||||
</view>
|
||||
<view class="w-full bg--w111-fff rd-16rpx px-24 mt-20">
|
||||
<view class="fs-28 pt-32">使用须知</view>
|
||||
<view class="pt-12 fs-26 text--w111-666 lh-36rpx space-line pb-32">{{ cardInfo.instructions }}</view>
|
||||
</view>
|
||||
<view class="w-full bg--w111-fff rd-16rpx px-24 mt-20">
|
||||
<view class="fs-28 pt-32">礼品卡详情</view>
|
||||
<view class="pt-12 fs-26 text--w111-666 lh-36rpx space-line pb-32" v-html="cardInfo.description"></view>
|
||||
</view>
|
||||
<view class="h-200"></view>
|
||||
</view>
|
||||
<view class="fixed-lb w-full pb-safe bg--w111-fff z-99">
|
||||
<view class="w-full h-108 flex-between-center px-20">
|
||||
<button class="btn-box w-full h-72 rd-40rpx flex-center fs-26 text--w111-fff"
|
||||
:disabled="disabled"
|
||||
@tap="exchangeGift">确认兑换</button>
|
||||
</view>
|
||||
</view>
|
||||
<uni-popup ref="popup">
|
||||
<view class="">
|
||||
<view class="gift_pop bg--w111-fff relative">
|
||||
<image class="header-pic" :src="imgHost + '/statics/images/activity/gift_open_pic.png'"></image>
|
||||
<view class="success-text">
|
||||
<view class="text-center text-red fs-34 fw-500 lh-48rpx">成功到账</view>
|
||||
<view class="text-center fs-26 lh-36rpx pt-24">{{cardInfo.balance}}元已储值到您的账户中</view>
|
||||
<view class="flex-x-center mt-54">
|
||||
<view class="btn-box w-280 h-80 rd-40rpx flex-center fs-28 text--w111-fff" @tap="toMoney">去看看</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-center mt-94">
|
||||
<text class="iconfont icon-ic_close1 text--w111-fff fs-50" @tap="closeGift"></text>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import { giftCardGetInfoApi, giftCardReceiveApi } from "@/api/activity.js";
|
||||
import { HTTP_REQUEST_URL } from '@/config/app';
|
||||
export default{
|
||||
name:"",
|
||||
data(){
|
||||
return {
|
||||
cardForm:{
|
||||
card_number:"",
|
||||
card_pwd: ""
|
||||
},
|
||||
cardInfo: {
|
||||
id: "", //自增ID
|
||||
name: "", //礼品卡名称
|
||||
fixed_time: [],
|
||||
type: 1, //礼品卡类型 1-储值卡 2-兑换卡
|
||||
batch_id: "", //关联卡密
|
||||
total_num: 1, //总数量
|
||||
instructions: "", //使用说明
|
||||
cover_image: "", //封面图
|
||||
valid_type: 1, //有效期类型 1-永久有效 2-固定时间
|
||||
status: 1, //礼品卡状态 0-禁用 1-启用
|
||||
balance: 0, //储值金额
|
||||
exchange_type: 1, //'兑换商品类型 1-固定商品打包 2-任选N件商品'
|
||||
gift_num: 1, //兑换商品数量
|
||||
description: "",
|
||||
product: [], //兑换商品
|
||||
},
|
||||
disabled: false,
|
||||
imgHost: HTTP_REQUEST_URL,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
totalLimitNum() {
|
||||
return this.cardInfo.product.reduce((sum, item) => sum + item.limit_num, 0);
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.cardForm.card_number = options.card_number;
|
||||
this.cardForm.card_pwd = options.card_pwd;
|
||||
if(options.card_number && options.card_pwd){
|
||||
this.getInfo();
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
getInfo(){
|
||||
giftCardGetInfoApi(this.cardForm).then(res=>{
|
||||
this.cardInfo = res.data;
|
||||
this.cardInfo.description = res.data.description.replace(/<img/gi, '<img style="max-width: 100%;display:block;"');
|
||||
uni.setNavigationBarTitle({
|
||||
title: options.type == 1 ? '兑换礼金' : '兑换礼品'
|
||||
})
|
||||
}).catch(err=>{
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
})
|
||||
})
|
||||
},
|
||||
exchangeGift(){
|
||||
if(this.cardInfo.exchange_type == 2){
|
||||
if(this.totalLimitNum != this.cardInfo.gift_num) {
|
||||
return this.$util.Tips({
|
||||
title: "请检查兑换数量"
|
||||
})
|
||||
}
|
||||
let product = this.cardInfo.product.
|
||||
filter(item => item.limit_num !== 0).map(item=>{
|
||||
return {
|
||||
product_id: item.product_id,
|
||||
limit_num: item.limit_num || 0,
|
||||
unique: item.unique,
|
||||
}
|
||||
});
|
||||
this.$set(this.cardForm,'product',product);
|
||||
}
|
||||
this.disabled = true;
|
||||
giftCardReceiveApi(this.cardForm).then(res=>{
|
||||
this.disabled = false;
|
||||
if(this.cardInfo.type == 1){
|
||||
this.$refs.popup.open();
|
||||
}else{
|
||||
let cardId = res.data.map(item=> item.cartId).join(",");
|
||||
uni.navigateTo({
|
||||
url: "/pages/goods/order_confirm/index?cartId=" + cardId + "&new=1"
|
||||
})
|
||||
}
|
||||
}).catch(err=>{
|
||||
this.disabled = false;
|
||||
return this.$util.Tips({
|
||||
title: err
|
||||
})
|
||||
})
|
||||
|
||||
},
|
||||
toMoney(){
|
||||
this.$refs.popup.close();
|
||||
uni.redirectTo({
|
||||
url: "/pages/users/user_bill/index?type=2"
|
||||
})
|
||||
},
|
||||
closeGift(){
|
||||
this.$refs.popup.close();
|
||||
},
|
||||
increaseLimitNum(index) {
|
||||
if (this.totalLimitNum < this.cardInfo.gift_num) {
|
||||
this.cardInfo.product[index].limit_num += 1;
|
||||
}
|
||||
},
|
||||
decreaseLimitNum(index) {
|
||||
if (this.cardInfo.product[index].limit_num > 0) {
|
||||
this.cardInfo.product[index].limit_num -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.product-box uni-button[disabled], .product-box button[disabled]{
|
||||
background-color: #fff;
|
||||
}
|
||||
.fixed-lb uni-button[disabled], .fixed-lb button[disabled] {
|
||||
background: #cccccc;
|
||||
color: #fff;
|
||||
}
|
||||
.gift-badge{
|
||||
position: absolute;
|
||||
top: 24rpx;
|
||||
left: 24rpx;
|
||||
height: 46rpx;
|
||||
background: rgba(255,255,255,0.8);
|
||||
backdrop-filter: blur(8rpx)
|
||||
}
|
||||
.b-d{
|
||||
border: 1rpx solid #DDDDDD;
|
||||
}
|
||||
.btn-box{
|
||||
background: linear-gradient( 90deg, #E93323 0%, #FF7931 100%);
|
||||
}
|
||||
.max-w-444{
|
||||
max-width: 444rpx;
|
||||
}
|
||||
.gift_pop{
|
||||
width: 480rpx;
|
||||
height: 500rpx;
|
||||
border-radius: 48rpx;
|
||||
.header-pic{
|
||||
width: 480rpx;
|
||||
height: 364rpx;
|
||||
position: absolute;
|
||||
top: -72rpx;
|
||||
left: 0;
|
||||
}
|
||||
.success-text{
|
||||
position: absolute;
|
||||
top: 180rpx;
|
||||
left: 0;
|
||||
width: 480rpx;
|
||||
.text-red{
|
||||
color: #E93323;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mt-94{
|
||||
margin-top: 94rpx;
|
||||
}
|
||||
.fs-50{
|
||||
font-size: 50rpx;
|
||||
}
|
||||
.text-red{
|
||||
color: #e93323;
|
||||
}
|
||||
.text-yellow{
|
||||
color: #FF7700;
|
||||
}
|
||||
</style>
|
||||
257
pages/activity/goods_bargain/index.vue
Normal file
257
pages/activity/goods_bargain/index.vue
Normal file
@@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<!-- 砍价列表模块 -->
|
||||
<view class="box">
|
||||
<view class='bargain-list'>
|
||||
<view class='header' :style="'background-image: url('+imgHost+'/statics/images/bargain-list-bg.png);'">
|
||||
<NavBar titleText=" "
|
||||
textSize="34rpx"
|
||||
bagColor="transparent"
|
||||
iconColor="#ffffff"
|
||||
textColor="#ffffff"
|
||||
showBack></NavBar>
|
||||
</view>
|
||||
<view class='list' v-if="bargainList.length">
|
||||
<block v-for="(item,index) in bargainList" :key="index">
|
||||
<view class='item flex justify-between relative'
|
||||
@tap="openSubscribe('/pages/activity/goods_bargain_details/index?id='+ item.id +'&spid='+ userInfo.uid)">
|
||||
<easy-loadimage
|
||||
mode="aspectFit"
|
||||
:image-src="item.image"
|
||||
width="240rpx"
|
||||
height="240rpx"
|
||||
borderRadius="20rpx"></easy-loadimage>
|
||||
<view class='w-410 fs-28 flex-col justify-between'>
|
||||
<view>
|
||||
<view class='w-410 lh-40rpx line2'>
|
||||
<text v-if="item.brand_name" class="brand-tag">{{ item.brand_name }}</text>
|
||||
{{item.title}}</view>
|
||||
<view class='fs-22 fw-500 mt-8 red'>
|
||||
<text class='iconfont icon-ic_fire fs-22 mr-8'></text>
|
||||
{{item.people}}人正在参与
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-between-center">
|
||||
<view>
|
||||
<view class='flex items-baseline red'>
|
||||
<text class="fs-22 lh-30rpx fw-500">最低: </text>
|
||||
<baseMoney :money="item.min_price" symbolSize="24" integerSize="40" decimalSize="24" incolor="#E93323" weight></baseMoney>
|
||||
</view>
|
||||
<view class="otPrice">¥{{item.price}}</view>
|
||||
</view>
|
||||
<view class='cutBnt w-144 h-56 rd-30rpx flex-center fs-24 text--w111-fff'>参与砍价</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="list no-goods" v-if="!bargainList.length && !loading">
|
||||
<image :src="imgHost + '/statics/images/noActivity.gif'" mode=""></image>
|
||||
<text class="fs-26 text--w111-999 pt-16">暂无砍价商品,去看看其他商品吧~</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
let app = getApp();
|
||||
import { HTTP_REQUEST_URL } from '@/config/app';
|
||||
import { getBargainList } from '@/api/activity.js';
|
||||
import { openBargainSubscribe } from '@/utils/SubscribeMessage.js';
|
||||
import { getUserInfo } from '@/api/user.js';
|
||||
import { toLogin } from '@/libs/login.js';
|
||||
import { mapGetters } from "vuex";
|
||||
import emptyPage from '@/components/emptyPage.vue';
|
||||
import NavBar from "@/components/NavBar.vue"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
bargainList: [],
|
||||
page: 1,
|
||||
limit: 20,
|
||||
loading: false,
|
||||
loadend: false,
|
||||
userInfo: {},
|
||||
isAuto: false, //没有授权的不会自动授权
|
||||
isShowAuth: false, //是否隐藏授权
|
||||
imgHost:HTTP_REQUEST_URL,
|
||||
// #ifdef MP
|
||||
getHeight: this.$util.getWXStatusHeight()
|
||||
// #endif
|
||||
};
|
||||
},
|
||||
components:{ emptyPage, NavBar },
|
||||
computed: mapGetters(['isLogin']),
|
||||
watch: {
|
||||
isLogin: {
|
||||
handler: function(newV, oldV) {
|
||||
if (newV) {
|
||||
// #ifndef MP
|
||||
this.getUserInfo();
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
onLoad: function(options) {
|
||||
this.getBargainList();
|
||||
if (this.isLogin) {
|
||||
this.getUserInfo();
|
||||
}
|
||||
},
|
||||
onShow(){
|
||||
uni.removeStorageSync('form_type_cart');
|
||||
},
|
||||
onPageScroll(object) {
|
||||
uni.$emit('scroll');
|
||||
},
|
||||
methods: {
|
||||
// 授权关闭
|
||||
authColse: function(e) {
|
||||
this.isShowAuth = e
|
||||
},
|
||||
goarrow(){
|
||||
uni.navigateBack()
|
||||
},
|
||||
/*
|
||||
* 获取用户信息
|
||||
*/
|
||||
getUserInfo: function() {
|
||||
let that = this;
|
||||
getUserInfo().then(res => {
|
||||
that.$set(that, 'userInfo', res.data);
|
||||
});
|
||||
},
|
||||
openSubscribe: function(e) {
|
||||
if(this.isLogin){
|
||||
let page = e;
|
||||
// #ifndef MP
|
||||
uni.navigateTo({
|
||||
url: page
|
||||
});
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
uni.showLoading({
|
||||
title: '正在加载',
|
||||
})
|
||||
openBargainSubscribe().then(res => {
|
||||
uni.hideLoading();
|
||||
uni.navigateTo({
|
||||
url: page,
|
||||
});
|
||||
}).catch((err) => {
|
||||
uni.hideLoading();
|
||||
});
|
||||
// #endif
|
||||
}else{
|
||||
toLogin()
|
||||
}
|
||||
},
|
||||
getBargainList: function() {
|
||||
let that = this;
|
||||
if (that.loadend) return;
|
||||
if (that.loading) return;
|
||||
that.loading = true;
|
||||
getBargainList({
|
||||
page: that.page,
|
||||
limit: that.limit
|
||||
}).then(function(res) {
|
||||
that.$set(that, 'bargainList', that.bargainList.concat(res.data));
|
||||
that.$set(that, 'page', that.page + 1);
|
||||
that.$set(that, 'loadend', that.limit > res.data.length);
|
||||
that.$set(that, 'loading', false);
|
||||
}).catch(res => {
|
||||
that.loading = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
onReachBottom: function() {
|
||||
this.getBargainList();
|
||||
},
|
||||
//#ifdef MP
|
||||
onShareAppMessage() {
|
||||
let that = this;
|
||||
return {
|
||||
title: '砍价列表',
|
||||
path: '/pages/activity/goods_bargain/index?spid=' + that.$store.state.app.uid,
|
||||
imageUrl: HTTP_REQUEST_URL+'/statics/images/bargain-list-bg.png',
|
||||
// desc: ''
|
||||
};
|
||||
},
|
||||
//分享到朋友圈
|
||||
onShareTimeline: function() {
|
||||
let that = this;
|
||||
return {
|
||||
title: '砍价列表',
|
||||
path: '/pages/activity/goods_bargain/index?spid=' + + that.$store.state.app.uid,
|
||||
imageUrl: HTTP_REQUEST_URL+'/statics/images/bargain-list-bg.png',
|
||||
// desc: ''
|
||||
};
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.no-goods{
|
||||
text-align: center;
|
||||
padding-bottom: 60rpx!important;
|
||||
color: #999;
|
||||
image{
|
||||
width: 440rpx;
|
||||
height: 360rpx;
|
||||
margin: 40rpx auto 0 auto;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.bargain-list .header {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
width: 750rpx;
|
||||
height: 926rpx;
|
||||
padding-top: 55rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.iconfont{
|
||||
color: #fff;
|
||||
font-size: 40rpx;
|
||||
margin-left: 15rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.bargain-list .list {
|
||||
background-color: #fff;
|
||||
border-radius: 24rpx;
|
||||
margin: -510rpx 20rpx 66rpx 20rpx;
|
||||
padding: 32rpx 20rpx;
|
||||
}
|
||||
.brand-tag{
|
||||
background-color: #e93323 !important;
|
||||
}
|
||||
.item~.item{
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
|
||||
.red{
|
||||
color: #E93323;
|
||||
}
|
||||
|
||||
.otPrice{
|
||||
font-size: 26rpx;
|
||||
font-family: Regular;
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.cutBnt {
|
||||
background: linear-gradient(90deg, #FF7931 0%, #E93323 100%);
|
||||
}
|
||||
|
||||
.bargain-list .list .load {
|
||||
font-size: 24rpx;
|
||||
height: 85rpx;
|
||||
text-align: center;
|
||||
line-height: 85rpx;
|
||||
}
|
||||
</style>
|
||||
1834
pages/activity/goods_bargain_details/index.vue
Normal file
1834
pages/activity/goods_bargain_details/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user