代码更新

This commit is contained in:
jia 2023-09-20 17:00:55 +08:00
parent 997e8a8784
commit 48e28824c0
237 changed files with 65095 additions and 0 deletions

26
.gitignore vendored Normal file
View File

@ -0,0 +1,26 @@
.DS_Store
node_modules
/dist
.hbuilderx
unpackage
# local env files
.env.local
.env.*.local
# 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

526
App.vue Normal file
View File

@ -0,0 +1,526 @@
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
// #ifdef APP-PLUS
let jpushModule = uni.requireNativePlugin("JG-JPush");
const mp = uni.requireNativePlugin('uniMP');
// #endif
import {
checkLogin
} from "./libs/login";
import {
HTTP_REQUEST_URL
} from './config/app';
import {
getconfig,
history
} from '@/api/public.js'
import Routine from './libs/routine.js';
export default {
data() {
return {
audioTeam: []
}
},
globalData: {
spid: 0,
code: 0,
isLogin: false,
userInfo: {},
MyMenus: [],
balance_func_status: 0, //
recharge_switch: 0, //
store_user_min_recharge: 0, //
yue_pay_status: 0, //
alipay_open: 0, //
routine_logo: '', //logo
share_pic: '',
site_logo: '',
site_name: '', //
fid: '', //id
uid: '',
hide_mer_status: 0,
member_status: 0,
copy_command_status: 0, //
arrival_notice: 0, //
is_phone_login: 0,
auto_arrival: 0,
mer_location: 0,
statusBarHeight: 0,
mer_location: 0,
store_street_theme: 1,
sys_intention_agree: '',
copyright_status: '',
copyright_context: '',
copyright_image: '',
open_update_info: 0,
recommend_switch: 0,
svip_switch_status: 0,
community_reply_status: 0,
community_reply_auth: 0,
margin_ico_switch: 0,
margin_ico: '',
community_app_switch: [],
navigation: {},
imgColor: '',
...uni.getStorageSync('GLOBAL_DATA') || {}
},
onLaunch: function(option) {
this.globalData.statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px';
this.globalData.uid = this.$store.state.app.uid;
let appkey = uni.getStorage({
key: 'launchFlag'
})
if (appkey) {
setTimeout(() => {
this.$store.dispatch('INIT_CONFIG');
}, 6000)
}
// #ifdef APP-PLUS
//uni
mp.onUniMPEventReceive(ret => {
console.log('小程序事件: ', ret);
if (ret.event == 'closeApp') {
mp.closeUniMP(ret.fromAppid, (ret) => {
console.log('closeUniMP: ' + JSON.stringify(ret));
});
}
});
// #endif
let that = this;
// #ifdef MP
if (HTTP_REQUEST_URL == '') {
console.error(
"请配置根目录下的config.js文件中的 'HTTP_REQUEST_URL'\n\n请修改开发者工具中【详情】->【AppID】改为自己的Appid\n\n请前往后台【小程序】->【小程序配置】填写自己的 appId and AppSecret"
);
return false;
}
if (option.query.hasOwnProperty('scene')) {
switch (option.scene) {
//
case 1047:
// console.log(option, 'val')
let val = that.$util.getUrlParams(decodeURIComponent(option.query.scene));
that.globalData.code = val;
that.globalData.uid = val
break;
//
case 1048:
that.globalData.code = option.query.scene;
break;
//
case 1049:
that.globalData.code = option.query.scene;
break;
//
case 1001:
that.globalData.spid = option.query.scene;
break;
}
}
// #endif
//
uni.getSystemInfo({
success: function(res) {
that.globalData.navHeight = res.statusBarHeight * (750 / res.windowWidth) + 91;
}
});
// #ifdef MP
let menuButtonInfo = uni.getMenuButtonBoundingClientRect();
that.globalData.navH = menuButtonInfo.top * 2 + menuButtonInfo.height / 2;
const version = uni.getSystemInfoSync().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
that.getConfigData()
//#ifdef APP-PLUS
this.checknetwork()
jpushModule.setLoggerEnable(true);
jpushModule.initJPushService()
jpushModule.addConnectEventListener(result => {
let connectEnable = result.connectEnable
// console.log("jpush", connectEnable)
})
//
// jpushModule.setAlias({
// 'alias': uni.getStorageSync('userId'),
// 'sequence': 1
// })
//
// jpushModule.addTagAliasListener(result => {
// let code = result.code
// let sequence = result.sequence
// let tags = result.tags
// let tag = result.tag
// let tagEnable = result.tagEnable
// let alias = result.alias
// console.log(alias, '')
// })
//
jpushModule.addNotificationListener(result => {
let notificationEventType = result.notificationEventType
let messageID = result.messageID
let title = result.title
let content = result.content
let extras = result.extras
console.log("通知", result)
if (result.extras.type == 'ORDER_CREATE') {
if (this.audioTeam.length > 0) {
this.audioTeam.push(result.extras.type);
} else {
this.audio()
this.audioTeam.push(result.extras.type);
}
}
//
if (notificationEventType == 'notificationOpened') {
uni.navigateTo({
url: result.extras.route
})
}
})
// jpushModule.addCustomMessageListener(result => {
// let messageID = result.messageID
// let content = result.content
// let extras = result.extras
// console.log("", result)
// })
//#endif
},
onShow() {
let that = this
// H5
if (this.$store.state.app.token) {
//
// #ifdef H5
history({
page: location.pathname + location.search,
}).then(() => {});
//#endif
};
// #ifndef H5
setTimeout(() => {
if (that.globalData.copy_command_status == 1) {
uni.getClipboardData({
success: function(res) {
if (/^(\/@[1-9]{1}).*\*\//.test(res.data)) {
that.$store.commit("PARSE_PWD", res.data)
}
},
fail: function(res) {
//
}
})
}
}, 1500)
// #endif
},
mounted() {
},
methods: {
//
checknetwork() {
uni.onNetworkStatusChange(function(res) {
if (res.isConnected) {
uni.reLaunch({
url: '/pages/index/index'
})
} else {
uni.showModal({
title: '系统提示',
content: '当前设备无网络或网络较差',
cancelText: '取消',
confirmText: '确定',
success: (res) => {
if (res.confirm) {
uni.reLaunch({
url: '/pages/index/index'
})
} else {
// #ifdef H5
uni.navigateTo({
url: '/pages/users/login/login_copy'
})
// #endif
// #ifdef APP-PLUS
plus.runtime.quit()
// #endif
}
}
})
}
})
},
/**
* 语音播报
*
*
*/
async audio() {
const innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = true;
innerAudioContext.src = `/static/audio/order.mp3`;
innerAudioContext.onPlay(() => {
console.log('开始播放')
});
innerAudioContext.onEnded(() => {
console.log('语音播报结束')
innerAudioContext.destroy() //
if (this.audioTeam.length > 1) {
this.audioTeam.splice(0, 1);
console.log('队列中');
this.audio()
} else {
console.log('队列为零');
this.audioTeam = []
}
});
innerAudioContext.onError(() => {
console.log('语音播报失败')
innerAudioContext.destroy() //
});
},
//
setOpenShare: function(data) {
let that = this;
let href = location.href;
href = href.indexOf("?") === -1 ? href + "?spid=" + this.globalData.uid : href + "&spid=" + this
.globalData
.uid;
if (that.$wechat.isWeixin()) {
let configAppMessage = {
desc: data.share_info,
title: data.share_title,
link: href,
imgUrl: data.share_pic
};
that.$wechat.wechatEvevt(["updateAppMessageShareData", "updateTimelineShareData"],
configAppMessage);
}
},
//
getConfigData() {
getconfig().then(res => {
uni.$emit('update', res.data)
this.$store.commit('GLOBAL_DATA', res.data);
this.globalData.balance_func_status = res.data.balance_func_status
this.globalData.recharge_switch = res.data.recharge_switch
this.globalData.routine_logo = res.data.routine_logo
this.globalData.share_pic = res.data.share_pic
this.globalData.community_reply_status = res.data.community_reply_status
this.globalData.site_logo = res.data.site_logo
this.globalData.login_logo = res.data.login_logo
this.globalData.site_name = res.data.site_name
this.globalData.store_user_min_recharge = res.data.store_user_min_recharge
this.globalData.yue_pay_status = res.data.yue_pay_status
this.globalData.sys_intention_agree = res.data.sys_intention_agree
this.globalData.mer_intention_open = res.data.mer_intention_open
this.globalData.alipay_open = res.data.alipay_open
this.globalData.hide_mer_status = res.data.hide_mer_status
this.globalData.mer_location = res.data.mer_location
this.globalData.arrival_notice = res.data.procudt_increase_status
this.globalData.auto_arrival = res.data.sys_extension_type
this.globalData.member_status = res.data.member_status
this.globalData.copy_command_status = res.data.copy_command_status
this.globalData.is_phone_login = res.data.is_phone_login
this.globalData.mer_location = res.data.mer_location
this.globalData.store_street_theme = res.data.store_street_theme
this.globalData.copyright_status = res.data.copyright_status
this.globalData.copyright_image = res.data.copyright_image
this.globalData.copyright_context = res.data.copyright_context
this.globalData.open_update_info = res.data.open_update_info
this.globalData.recommend_switch = res.data.recommend_switch
this.globalData.svip_switch_status = res.data.svip_switch_status
this.globalData.navigation = res.data.navigation
this.globalData.community_app_switch = res.data.community_app_switch
this.globalData.community_reply_auth = res.data.community_reply_auth
this.globalData.margin_ico_switch = res.data.margin_ico_switch
this.globalData.margin_ico = res.data.margin_ico
// console.log(res.data.global_theme.theme + "")
this.$store.commit("VIEW_COLOR", res.data.global_theme.theme)
this.$store.commit("KEY_COLOR", '_' + res.data.global_theme.type)
try {
uni.setStorageSync('SUBSCRIBE_MESSAGE', res.data.tempid);
} catch (e) {
// error
}
// #ifdef H5
this.setOpenShare(res.data);
// #endif
}).catch(err => {});
}
},
onHide: function() {
//console.log('App Hide')
},
watch: {
// H5
$route(n) {
if (this.$store.state.app.token) {
//
history({
page: location.pathname + location.search,
}).then(() => {});
}
},
}
}
</script>
<style lang="scss">
/* #ifndef APP-PLUS-NVUE || APP-NVUE */
@import "@/plugin/animate/animate.min.css";
@import 'static/css/base.css';
@import 'static/iconfont/iconfont.css';
@import 'static/iconfont/iconlihai.css';
@import 'static/iconfont/icontan.css';
@import 'static/css/style.scss';
view {
box-sizing: border-box;
}
.custom_style {
color: #fff;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 24rpx;
&_icon {
background-image: url('static/tabbar_icon/d.png');
background-repeat: no-repeat;
background-size: cover;
font-size: 80rpx;
width: 100rpx;
height: 100rpx;
border-radius: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-top: -50rpx;
// box-shadow: 0px 5px 10px 1px rgba(32, 161, 98, 0.3);
}
.custom_style-txt {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 5rpx;
}
}
.bg-color-red {
background-color: #e93323 !important;
}
.syspadding {
padding-top: var(--status-bar-height);
}
.flex {
display: flex;
}
.uni-scroll-view::-webkit-scrollbar {
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
display: none
}
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
::-moz-scrollbar {
width: 0;
height: 0;
color: transparent;
}
.empty-txt {
line-height: 100rpx;
font-size: 22rpx;
color: #999;
text-align: center;
}
.product-con .conter img {
display: block;
}
.open-location {
height: 100vh;
}
uni-tabbar {
bottom: 0;
}
/*#endif*/
</style>

27
androidPrivacy.json Normal file
View File

@ -0,0 +1,27 @@
{
"version" : "1",
"prompt" : "template",
"title" : "服务协议与隐私政策",
"message" : "\t请务必审慎阅读、充分理解“服务协议与 隐私政策”各条款,包括但不限于:为了 向你提供即时通讯、内容分享等服务,我 们需要收集你的设备信息、操作日志、OAID等个 人信息。你可以在“设置”中查看、变更、删除个人信息并管理你的授权。<br/>\r\r\t你可以阅读 <a href=\"https://shop.lihaink.cn/pages/users/user_about/index?from=sys_user_agree\">《用户协议》</a> 与 <a href=\"https://shop.lihaink.cn/pages/users/user_about/index?from=sys_userr_privacy\">《隐私政策》</a>了解详细信息。如你同意,请点击“我同意”开始接受我们的服务。",
"buttonAccept" : "同意并接受",
"buttonRefuse" : "暂不同意",
"second" : {
"title" : "确认提示",
"message" : "进入应用前,你需先同意<a href=\"https://shop.lihaink.cn/pages/users/user_about/index?from=sys_user_agree\">《用户协议》</a> 与 <a href=\"https://shop.lihaink.cn/pages/users/user_about/index?from=sys_userr_privacy\">《隐私政策》</a>,否则将退出应用。",
"buttonAccept" : "同意并继续",
"buttonRefuse" : "退出应用"
},
"styles" : {
"backgroundColor" : "#fff",
"borderRadius" : "5px",
"title" : {
"color" : "#000"
},
"buttonAccept" : {
"color" : "#fff"
},
"buttonRefuse" : {
"color" : "#ccc"
}
}
}

264
api/activity.js Normal file
View File

@ -0,0 +1,264 @@
// +----------------------------------------------------------------------
// | 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('store/product/group/lst', data, {
noAuth: true
});
}
/**
* 拼团参与人
*
*/
export function getCombinationUser(data) {
return request.get('store/product/group/count', data, {
noAuth: true
});
}
/**
* 活动分类
*
*/
export function getActivitycategory(type) {
return request.get('product/spu/active/category/' + type, {}, {
noAuth: true
});
}
/**
* 拼团详情
*
*/
export function getCombinationDetail(id) {
return request.get('store/product/group/detail/' + id, {}, {
noAuth: true
});
}
/**
* 拼团 开团
*/
export function getCombinationPink(id) {
return request.get("store/product/group/get/" + id);
}
/**
* 拼团 取消开团
*/
export function postCombinationRemove(data) {
return request.post("store/product/group/cancel", data);
}
/**
* 秒杀产品详情
* @param int id
*/
export function getSeckillDetail(id) {
return request.get('store/product/seckill/detail/' + id, {}, {
noAuth: true
});
}
/**
* 拼团海报
* @param object data
*
*/
export function getCombinationPoster(data) {
return request.post('combination/poster', data)
}
/**
* 获取秒杀小程序二维码
*/
export function seckillCode(id, data) {
return request.get("seckill/code/" + id, data);
}
/**
* 获取拼团小程序二维码
*/
export function scombinationCode(id) {
return request.get("combination/code/" + id);
}
/**
* 秒杀产品时间区间
*
*/
export function getSeckillIndexTime() {
return request.get('store/product/seckill/select', {}, {
noAuth: true
});
}
/**
* 秒杀产品列表
* @param int time
* @param object data
*/
export function getSeckillList(data) {
return request.get('store/product/seckill/lst', data, {
noAuth: true
});
}
/**
* 预售列表
*/
export function getPresellList(data) {
return request.get('store/product/presell/lst', data, {
noAuth: true
});
}
/**
* 助力列表
*/
export function getAssistList(data) {
return request.get('store/product/assist/lst', data, {
noAuth: true
});
}
/**
* 助力列表 -- 发起助力
*/
export function initiateAssistApi(id) {
return request.post('store/product/assist/create/' + id);
}
/**
* 助力详情
*/
export function getAssistDetail(id) {
return request.get('store/product/assist/detail/' + id);
}
/**
* 助力好友
*/
export function assistHelpList(id, data) {
return request.get('store/product/assist/user/' + id, data);
}
/**
* 预售协议
*/
export function presellAgreement() {
return request.get('store/product/presell/agree');
}
/**
* 已助力成功数据
*/
export function assistUserData() {
return request.get('store/product/assist/count', {}, {
noAuth: true
});
}
/**
* 为好友助力
*/
export function postAssistHelp(id) {
return request.post('store/product/assist/set/' + id);
}
/**
* 获取助力查看分享次数
*/
export function getAssistUser(id) {
return request.get('store/product/assist/share/' + id);
}
/**
* 助力记录列表
*/
export function getBargainUserList(data) {
return request.get('store/product/assist/set/lst', data);
}
/**
* 助力记录列表 -- 取消
*/
export function getBargainUserCancel(id) {
return request.post('store/product/assist/set/delete/' + id);
}
/**
* 活动专题列表
*/
export function getTopicList(id, data) {
return request.get(`activity/lst/${id}`, data, {
noAuth: true
});
}
/**
* 活动专题详情
*/
export function getTopicDetail(id) {
return request.get(`activity/info/${id}`,{}, {
noAuth: true
});
}
/**
* 活动专题商品
*/
export function getTopicProLst(data) {
return request.get(`product/spu/labels`,data, {
noAuth: true
});
}
/**
* 获取本地服务商户列表
*/
export function getMerchantServiceLst(data) {
return request.get(`store/merchant/local`,data, {
noAuth: true
});
}
/**
* 获取优惠券列表
*/
export function getCouponLst(data) {
return request.get(`coupon/getlst`,data, {
noAuth: true
});
}
/**
* 获取优惠券列表
*/
export function getNewPeopleCouponLst(data) {
return request.get(`coupon/new_people`,data, {
noAuth: true
});
}
/**
* 获取热卖排行列表
*/
export function hotRankingApi(data) {
return request.get(`product/spu/get_hot_ranking`,data, {
noAuth: true
});
}
/**
* 热卖排行列表分类
*/
export function spuTop(data) {
return request.get(`store/product/category/hotranking`, {}, {
noAuth: true
});
}
/**
* 热卖排行列表
*/
export function spuTopList(data) {
return request.get(`product/spu/get_hot_ranking`, data, {
noAuth: true
});
}

296
api/admin.js Normal file
View File

@ -0,0 +1,296 @@
// +----------------------------------------------------------------------
// | 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(merId, id, data) {
return request.post("admin/" + merId + "/price/" + id, data, {
login: true
});
}
/**
* 同意先货后款
*/
export function postconfirm(merId, data) {
return request.post("admin/" + merId + "/confirm", data, {
login: true
});
}
/**
* 先货后款订单结算
*/
export function postsettle(merId, data) {
return request.post("admin/" + merId + "/settle", data, {
login: true
});
}
/**
* 订单备注
*/
export function setAdminOrderRemark(merId, id, data) {
return request.post("admin/" + merId + "/mark/" + id, data, {
login: true
});
}
/**
* 订单详情
*/
export function getAdminOrderDetail(merId, orderId) {
return request.get("admin/" + merId + "/order/" + orderId, {}, {
login: true
});
}
/**
* 订单发货信息获取
*/
export function getAdminOrderDelivery(orderId) {
return request.get("admin/order/delivery/gain/" + orderId, {}, {
login: true
});
}
/**
* 订单发货保存
*/
export function setAdminOrderDelivery(merId, id, data) {
return request.post("admin/" + merId + "/delivery/" + id, data, {
login: true
});
}
/**
* 订单统计图
*/
export function getStatisticsTime(data) {
return request.get("admin/order/time", data, {
login: true
});
}
/**
* 线下付款订单确认付款
*/
export function setOfflinePay(merId, data) {
return request.post("admin/" + merId + "/order/offline", data, {
login: true
});
}
/**
* 订单确认退款
*/
export function setOrderRefund(merId, data) {
return request.post("admin/" + merId + "/order/refund", data, {
login: true
});
}
/**
* 获取快递公司
* @returns {*}
*/
export function getLogistics() {
return request.get("logistics", {}, {
login: false
});
}
/**
* 订单核销
* @returns {*}
*/
export function orderVerific(merId, id, data) {
return request.post(`verifier/${merId}/${id}`, data);
}
/**
* 核销订单详情
* @returns {*}
*/
export function verifierOrder(mer_id, code) {
return request.get("verifier/" + mer_id + "/order/" + code);
}
/**
* 订单统计数
* @returns {*}
*/
export function orderStatistics(mer_id, data) {
return request.get("admin/" + mer_id + "/statistics", data);
}
/**
* 订单
* @returns {*}
*/
export function orderStat(data) {
return request.get("admin/1/statistics", data);
}
/**
* 每日成交额
* @returns {*}
*/
export function orderPrice(where, mer_id) {
return request.get("admin/" + mer_id + "/order_price", where, {
login: true
});
}
/**
* 订单列表
* @returns {*}
*/
export function getOrderList(where, merId) {
return request.get(`admin/${merId}/order_list`, where, {
login: true
});
}
/**
* 退款订单列表
* @returns {*}
*/
export function getRefundOrderList(where, merId) {
return request.get(`server/${merId}/refund/lst`, where, {
login: true
});
}
/**
* 营业额统计
* @returns {*}
*/
export function turnoverStatistics(where, merId) {
return request.get(`admin/${merId}/pay_price`, where, {
login: true
});
}
/**
* 订单统计
* @returns {*}
*/
export function orderNumberStatistics(where, merId) {
return request.get(`admin/${merId}/pay_number`, where, {
login: true
});
}
/**
* 获取订单打印默认配置
* @returns {*}
*/
export function orderDeliveryInfo(merId) {
return request.get(`admin/${merId}/mer_form`);
}
/**
* 获取电子面单列表
* @returns {*}
*/
export function orderExportTemp(data) {
return request.get("store/expr/temps", data);
}
/**
* 是否开始电子面单和同城配送
* @returns {*}
*/
export function getTempAndDelivery(merId) {
return request.get(`admin/${merId}/delivery_config`);
}
/**
* 获取同城配送门店列表
* @returns {*}
*/
export function getDeliveryStoreLst(merId) {
return request.get(`admin/${merId}/delivery_options`);
}
/**
* 退款订单信息
* @returns {*}
*/
export function getRefundOrderInfo(merId, id) {
return request.get(`server/${merId}/refund/get/${id}`);
}
/**
* 提交退款订单信息
* @returns {*}
*/
export function refundOrderSubmit(merId, id, data) {
return request.post(`server/${merId}/refund/status/${id}`, data, {
login: true
});
}
/**
* 退款单确认收货
* @returns {*}
*/
export function refundOrderReceive(merId, id) {
return request.post(`server/${merId}/refund/confirm/${id}`, {}, {
login: true
});
}
/**
* 退款单详情
*/
export function getRefundOrderDetail(merId, orderId) {
return request.get(`server/${merId}/refund/detail/${orderId}`, {}, {
login: true
});
}
/**
* 添加退款单备注信息
*/
export function setRefundMark(merId, orderId, data) {
return request.post(`server/${merId}/refund/mark/${orderId}`, data, {
login: true
});
}
/**
* 去核销
* @param object data
*/
export function orderCancellation(merId, id) {
return request.post(`admin/${merId}/verify/${id}`);
}
/**
* 去核销
* @param object data
*/
export function purchaseOrder(where, merId) {
return request.get(`admin/${merId}/purchaseOrder`, where, {
login: true
});
}
/**
* 商家物流取件二维码
* @param object data
*/
export function logisticsCode(id) {
return request.get(`order/logistics_code/${id}`);
}

293
api/api.js Normal file
View File

@ -0,0 +1,293 @@
import request from "@/utils/request.js";
/**
* 获取云仓分类
*
*/
export function cloudWarehouse(data) {
return request.get("store/product/cloudWarehouse", data);
}
/**
* 获取云仓分类
*
*/
export function getCityCloundShop(data) {
return request.get("city/get_cloud_shop", data);
}
/**
* 商品扫码枪查询商品是否存在
*
*/
export function seachBarCodeAPI(data) {
return request.get("micro/seach_bar_code", data);
}
/**
* 获取里海云仓商品
*
*/
export function getProductSpuAPI(id, param) {
return request.get(`product/spu/cloud_merchant/${id}`, param, { noAuth: true });
}
//获取云仓库店铺id
export function get_cloud_shop(street_code) {
return request.get(`city/get_cloud_shop?street_code=${street_code}`, {}, { noAuth: true });
}
export function post_product_import(id) {
return request.post(`micro/product_import`, { id: id }, { noAuth: true });
}
/**
* 公共接口 优惠券接口 , 行业此讯 , 手机号码注册
*
*/
/**
* 获取主页数据 无需授权
*
*/
export function getIndexData() {
return request.get("common/home", {}, { noAuth: true });
}
/**
* 获取app版本
*/
export function getAppVersion() {
return request.get('appVersion', {}, { 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);
}
/**
* 商铺优惠券列表
* @param object data
*/
export function getShopCoupons(id) {
return request.get('coupon/store/' + id, {}, { noAuth: true })
}
/**
* 商品优惠券列表
* @param object data
*/
export function getCoupons(data) {
return request.get('coupon/product', data, { noAuth: true })
}
/**
* 我的优惠券
* @param int types 0全部 1未使用 2已使用
*/
export function getUserCoupons(data) {
return request.get('coupon/list', data)
}
/**
* 文章分类列表
*
*/
export function getArticleCategoryList() {
return request.get('article/category/lst', {}, { noAuth: true })
}
export function getArticleCategoryLists() {
return request.get('article/category/lst?is_home='+1, {}, { noAuth: true })
}
/**
* 文章列表
* @param int cid
*
*/
export function getArticleList(cid, data) {
return request.get('article/lst/' + 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/detail/' + 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(phone, reset, key, code) {
return request.post('register/verify', {
phone: phone,
type: reset === undefined ? 'reset' : reset,
key: key,
code: code
}, { 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切换公众号登陆 */
export function switchH5Login(data) {
return request.post("user/switch", data);
}
/** 绑定手机号 */
export function bindingPhone(data) {
return request.post('user/binding', data);
}
/** 修改手机号 */
export function modifyPhone(data) {
return request.post('user/change/phone', data);
}
/** 修改密码 */
export function modifyPassword(data) {
return request.post('user/change/password', 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('system/city/lst', {}, { noAuth: true });
}
export function getCityV2(pid) {
return request.get('v2/system/city/lst/' + pid, {}, { noAuth: true });
}
export function getCityList(address) {
return request.get('v2/system/city', { address }, { noAuth: true });
}
/** 获取小程序直播列表 */
export function getLiveList(page, limit) {
return request.get('wechat/live', { page, limit }, { noAuth: true });
}
/* APP登录 */
export function wechatAppAuth(data) {
return request.post("auth/app", data, { noAuth: true });
}
/* APPLE登录 */
export function appleAppAuth(data) {
return request.post("auth/apple", data, { noAuth: true });
}
/* 小程序获取手机号解密 */
export function appletsDecrypt(data) {
return request.post("user/mp/binding", data);
}
/**
* 获取首页DIY
*/
export function getDiy(data) {
return request.get('diy', data, { noAuth: true });
}
/**
* 获取首页微页面
*/
export function getPageDiy(data) {
return request.get(`micro`, data, {
noAuth: true
});
}
/**
* 滑块信息
* @param {Object} data
*/
export function getAjcaptcha(data) {
return request.get("ajcaptcha", data, {
noAuth: true
});
}
/**
* 滑块验证
* @param {Object} data
*/
export function ajcaptchaCheck(data) {
return request.post("ajcheck", data, {
noAuth: true
});
}
/**
* 获取所在的地区数据
* @param {Object} data
*/
export function village(data) {
return request.get('v2/system/geo/lst', data, { noAuth: true });
}
/**
* 获取所在的村队数据
* @param {Object} data
*/
export function brigade(data) {
return request.get('v2/system/brigade', data, { noAuth: true });
}

101
api/article.js Normal file
View File

@ -0,0 +1,101 @@
// import request from "@/utils/request.js";
import request from "@/utils/request.js";
import http from "@/utils/http.js";
// export const postShopInfo = (params, config = {}) => request.post('/edcapi/Shop_shopDeatil', params, config)
// // get请求获取菜单注意get请求的配置等都在第二个参数中详见前面解释
/**
*
*/
/**
* 文创文章
*/
export const getCulturalArticleAPI = (data) => http.get('/cultural/article', data, { noAuth: true })
/**
* 全民打卡
*/
export const getTravelPunchcardAPI = (data) => request.get('/cultural/punchcard', data, { noAuth: true })
/**
* 官网攻略
*/
export const getTravelWebStrategyAPI = (data) => request.get('/cultural/WebStrategy', data, { noAuth: true })
/**
* 热门活动
*/
export const getTravelHotPartyAPI = (data) => request.get('/cultural/hotparty', data, { noAuth: true })
/**
* 获取banner
*/
export const getSlideAPI = (data) => request.get('/Slide/get_slide', data, { noAuth: true })
/**
* 获取文章
*/
export const getIndexArticleList = (data) => http.get('/article/indexs', data, { noAuth: true })
export const getIndexArticleDetails = (data) => request.get('/article/details', data, { noAuth: true })
export const postIndexArticleDetails = (data) => request.post('/article/post', data)
export const getIndexArticleEdit = (data) => request.get('/article/edit', data)
export const postIndexArticleEdit = (data, params) => request.post('/article/put', data, {
params: params
})
// 投诉
export const postComplaintAPI = (data) => request.post('/index/complaint', data)
//评论
export const getArticleComment = (data) => request.get('/article_comment/index', data)
export const getArticleCommentOneAPI = (data) => request.get('/article_comment/one_list', data)
export const postArticleComment = (data) => request.post('/article_comment/post', data, { noVerify: true })
// 评论审核
export const getCommentListAPI = (data) => request.get('/Personal/getCommentList', data)
export const oneCAlickAuditAPI = (data) => request.get('/Personal/oneCAlickAudit', data)
export const delCommentAPI = (data) => request.get('/Personal/delComment', data)
/**
* 获取分类
*/
export const getCategory = (data) => request.get('/common/category', data, { noAuth: true })
//我的文章
export const getMyIndexArticleList = (data) => request.get('/my_article/index', data)
export const getMyIndexArticleDetails = (data) => request.get('/my_article/details', data)
// 工作区
export const getWorkArticleCount = (data) => request.get('/getWorkArticleCount', data)
// export function getWorkArticleCount(data) {
// return request.get('/getWorkArticleCount', data);
// }
//首页
export const getArticleListAPI = (data) => http.get('/getArticleList', data)
// 首页文章
export const getHomeListAPI = (data) => http.get('/article/hot_list', data)
//获取朋友圈分类信息
export const getFriendcirclelist = (data) => request.get('/Personal/getlist', data, {
noVerify: true
})
/** 发布图文*/
export const createPlantApi = (data) => request.post('/Personal/addOrEditNews', data)
//图文详情
export const PlantApi = (data) => request.get('/Personal/getdetails', data)
//获取说说评论
export const replyLstApi = (data) => request.get('/Personal/getpinglun', data, { noAuth: true })
/**发布评论*/
export const replyCreateApi = (data) => request.post('/Personal/newsComment', data)
// 删除说说
// export const deletePlantApi = (data) => request.post('/Personal/newsComment', data)
//朋友圈s
export const getfriendsList = (data) => request.get('/Personal/getalllist')
export const getCategoryListAPI = (data) => request.get('/common/category', data, { noAuth: true })
export const getNoticeListAPI = (data) => request.get('/Notice/list')
export const getNoticeInfoAPI = (data) => request.get('/Notice/info', data)
export const getArea = (data) => request.get('city/get_area', data, { noAuth: true })
export const getStreet = (data) => request.get('city/get_street', data, { noAuth: true })
export const getVillage = (data) => request.get('city/get_village', data, { noAuth: true })
export const getbrigadeAPI = (data) => request.get('common/get_brigade', data, { noAuth: true })
export const postBindingAPI = (data) => request.post('Userinfo/Binding', data, { noAuth: true, noVerify: true })

143
api/community.js Normal file
View File

@ -0,0 +1,143 @@
// +----------------------------------------------------------------------
// | 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 getTopicList() {
return request.get('community/category/lst', {}, {
noAuth: true
});
}
/**已购商品列表*/
export function boughtLstApi(data) {
return request.get('community/pay_product/lst', data);
}
/** 收藏图文列表*/
export function collectLstApi(data) {
return request.get('community/rela_product/lst', data);
}
/** 浏览图文列表*/
export function browseLstApi(data) {
return request.get('community/hist_product/lst', data);
}
/** 发布图文*/
export function createPlantApi(data) {
return request.post('community/create', data);
}
/*图文编辑*/
export function updatePlantApi(id, data) {
return request.post(`community/update/${id}`, data);
}
/*删除图文*/
export function deletePlantApi(id) {
return request.post(`community/delete/${id}`);
}
/** 图文详情*/
export function plantDetailApi(id) {
return request.get(`community/show/${id}`, {}, {
noAuth: true
});
}
/** 订单关联图文商品*/
export function orderAssociatePlantApi(orderId) {
return request.get(`community/order/${orderId}`, {}, {
noAuth: true
});
}
/**评论列表*/
export function replyLstApi(id, data) {
return request.get(`community/${id}/reply`, data, {
noAuth: true
});
}
/**发布评论*/
export function replyCreateApi(id, data) {
return request.post(`community/reply/create/${id}`, data);
}
/**点赞评论*/
export function starCommentApi(id, data) {
return request.post(`community/reply/start/${id}`, data);
}
/**关注用户*/
export function followAuthorApi(id, data) {
return request.post(`community/fans/${id}`, data);
}
/**全部图文列表*/
export function graphicLstApi(data) {
return request.get(`community/lst`, data, {
noAuth: true
});
}
/**视频列表*/
export function videoList(data) {
return request.get(`community/video_lst`, data, {
noAuth: true
});
}
/**自己的视频列表*/
export function deoList(id) {
return request.get(`community/show/${id}`);
}
export function myVideoList(id,data) {
return request.get(`community/user/community_video/${id}`, data, {
noAuth: true
});
}
/**文章点赞*/
export function graphicStartApi(id, status) {
return request.post(`community/start/${id}`, status);
}
/**用户详情*/
export function userInfoApi(id) {
return request.get(`community/user/info/${id}`);
}
/**关注人的文章列表*/
export function focusArticleLst(data) {
return request.get(`community/focuslst`, data, {
noAuth: true
});
}
/**用户的文章列表*/
export function userArticleLst(id, data) {
return request.get(`community/user/community/${id}`, data);
}
/**赞过的图文*/
export function starArticleLst(data) {
return request.get(`community/start/lst`, data);
}
/**我的关注*/
export function myFocusLst(data) {
return request.get(`community/focus/lst`, data);
}
/**我的粉丝*/
export function myFansLst(data) {
return request.get(`community/fans/lst`, data);
}
/**热门搜索*/
export function hotSearchLst() {
return request.get(`common/commuunity/hot_keyword`,{}, {
noAuth: true
});
}
/**热门搜索*/
export function graphicProApi(id) {
return request.get(`product/spu/get/${id}`,{
noAuth: true
});
}
/*视频分享二维码*/
export function getVideoCode(id, data) {
return request.get(`community/qrcode/${id}`, data, {
noAuth: true
});
}

3
api/lihai.js Normal file
View File

@ -0,0 +1,3 @@
import http from "@/utils/http.js";
export const getSlideAPI = (data) => http.get('/Slide/get_slide', data, { noAuth: true })

337
api/order.js Normal file
View File

@ -0,0 +1,337 @@
// +----------------------------------------------------------------------
// | 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(data) {
return request.get("user/cart/count", data);
}
/**
* 获取购物车列表
*
*/
export function getCartList(data) {
return request.get("user/cart/lst", data);
}
/**
* 修改购物车数量
* @param int cartId 购物车id
* @param int number 修改数量
*/
export function changeCartNum(cartId, data) {
return request.post("user/cart/change/" + cartId, data);
}
/**
* 清除购物车
* @param object ids
*/
export function cartDel(data) {
return request.post('user/cart/delete', data);
}
/**
* 订单列表
* @param object data
*/
export function getOrderList(data) {
return request.get('order/list', data);
}
/**
* 订单产品信息
* @param string unique
*/
export function orderProduct(orderId) {
return request.get('reply/product/' + orderId);
}
/**
* 订单评价
* @param object data
*
*/
export function orderComment(id, data) {
return request.post('reply/' + id, data);
}
/**
* 订单支付
* @param object data
*/
export function orderPay(id, data) {
return request.post('order/pay/' + id, data);
}
/**
* 订单统计数据
*/
export function orderData(data) {
return request.get('order/number', data)
}
/**
* 订单取消
* @param string id
*
*/
// export function orderCancel(id){
// return request.post('order/cancel',{id:id});
// }
/**
* 未支付订单取消
* @param string id
*
*/
export function unOrderCancel(id) {
return request.post('order/cancel/' + id);
}
/**
* 删除已完成订单
* @param string uni
*
*/
export function orderDel(id) {
return request.post('order/del/' + id);
}
/**
* 已付款订单详情
* @param string uni
*/
export function getOrderDetail(uni) {
return request.get('order/detail/' + uni);
}
/**
* 未付款订单详情
* @param string uni
*/
export function groupOrderDetail(uni,product_type) {
return request.get('order/group_order_detail/' + uni+'?product_type=' + product_type);
}
// 支付状态订单
export function getPayOrder(uni) {
return request.get('order/status/' + uni);
}
/**
* 再次下单
* @param string uni
*
*/
export function orderAgain(data) {
return request.post('user/cart/again', data);
}
/**
* 订单收货
* @param string uni
*
*/
export function orderTake(uni) {
return request.post('order/take/' + uni);
}
/**
* 订单查询物流信息
* @returns {*}
*/
export function express(id) {
return request.post("order/express/" + id);
}
/**
* 退款单查询物流信息
* @returns {*}
*/
export function refundOrderExpress(merId, id) {
return request.get(`server/${merId}/refund/express/${id}`);
}
/**
* 获取退款理由
*
*/
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(data) {
return request.post('order/check', data);
}
/**
* 订单确认获取订单详细信息
* @param string cartId
*/
export function getOrderConfirm(data) {
return request.post('v2/order/check', data);
}
/**
* 获取当前金额能使用的优惠卷
* @param string price
*
*/
export function getCouponsOrderPrice(price, data) {
return request.get('coupons/order/' + price, data)
}
/**
* 计算订单金额
* @param key
* @param data
* @returns {*}
*/
export function postOrderComputed(key, data) {
return request.post("/order/computed/" + key, data);
}
// 生成订单
export function orderCreate(data) {
return request.post("order/create", data, { noAuth: true });
}
// 新的生成订单
export function createOrder(data) {
return request.post("v2/order/create", data, { noAuth: true });
}
// 未支付订单
export function groupOrderList(data) {
return request.get("order/group_order_list", data, { noAuth: true });
}
// 批量退款列表
export function refundBatch(id) {
return request.get("refund/batch_product/" + id, { noAuth: true });
}
// 退款商品
export function refundProduct(id, data) {
return request.get("refund/product/" + id, data, { noAuth: true });
}
// 申请退款
export function refundApply(id, data) {
return request.post("refund/apply/" + id, data, { noAuth: true });
}
// 退款理由
export function refundMessage() {
return request.get("common/refund_message", { noAuth: true });
}
// 退款列表
export function refundList(data) {
return request.get("refund/list", data, { noAuth: true });
}
// 退款详情
export function refundDetail(id) {
return request.get("refund/detail/" + id, { noAuth: true });
}
// 物流列表
export function expressList() {
return request.get("common/express");
}
// 退回商品提交
export function refundBackGoods(id, data) {
return request.post("refund/back_goods/" + id, data, { noAuth: true });
}
// 退款记录删除
export function refundDel(id) {
return request.post("refund/del/" + id, { noAuth: true });
}
// 退款记录删除
export function refundExpress(id) {
return request.get("refund/express/" + id, { noAuth: true });
}
// 核销二维码
export function verifyCode(id) {
return request.get("order/verify_code/" + id);
}
/**
* 预售尾款支付
* @param object data
*/
export function presellOrderPay(id, data) {
return request.post('presell/pay/' + id, data);
}
/**
* 发票订单
* @param object data
*/
export function receiptOrder(data) {
return request.get('user/receipt/order', data);
}
/**
* 发票订单
* @param object data
*/
export function getReceiptOrder(id) {
return request.get('user/receipt/order/' + id);
}
/**
* 发票订单
* @param object data
*/
export function getCallBackUrlApi(key) {
return request.get('common/pay_key/' + key, {}, { noAuth: true });
}
/**
* 发票订单
* @param object data
*/
export function develiveryDetail(id) {
return request.get(`order/delivery/${id}`);
}
/**
* 订单申请开票
* @param object data
*/
export function applyInvoiceApi(id, data) {
return request.post(`order/receipt/${id}`, data);
}
/**
* 退款单取消申请
* @param object data
*/
export function refundCancelApi(id) {
return request.post(`refund/cancel/${id}`);
}
/**
* 售后
* @param object data
*/
export function refundlist(data) {
return request.get(`refund/list`,data);
}

323
api/product.js Normal file
View File

@ -0,0 +1,323 @@
// +----------------------------------------------------------------------
// | 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 const getProductDetailsAPI = (data) => request.get('micro/product_details', data)
/**
*商品列表
*/
export const spuInfo = (id, data) => request.get('product/spu/street/' + id, data)
/**
* 线下导入
*/
export function postImport(merid, data) {
return request.post(`server/${merid}/product/stockIn`, data);
}
/**
* 获取商户基本信息 http://127.0.0.1:8324/api/store/merchant/info?id=4
*/
export const merchantInfoAPI = (data) => request.get('store/merchant/info', data)
/**
* 修改商户基本信息
*/
export const merchantUpdateAPI = (data) => request.post('store/merchant/update', data)
/**
* 商品列表
*/
export function productLstApi(merId, data) {
return request.get(`server/${merId}/product/lst`, data, {
login: true
});
}
/**
* 商品列表 -- 删除
*/
export function productDeleteApi(merId, id) {
return request.post(`server/${merId}/product/delete/${id}`, {}, {
login: true
});
}
/**
* 商品列表 -- 上下架
*/
export function productOffApi(merId, id, data) {
return request.post(`server/${merId}/product/status/${id}`, data, {
login: true
});
}
/*
售罄商品 -- 列表头部
*/
export function productTitle(merId, data) {
return request.get(`server/${merId}/product/title`, data, {
login: true
});
}
/*
回收站商品彻底删除
*/
export function productDestory(merId, id, data) {
return request.post(`server/${merId}/product/destory/${id}`, data, {
login: true
});
}
/*
还原
*/
export function productRestore(merId, id) {
return request.post(`server/${merId}/product/restore/${id}`, {}, {
login: true
});
}
/*
添加或修改商品 获取商品品牌
*/
export function categoryBrandlist(merId) {
return request.get(`server/${merId}/category/brandlist`, {}, {
login: true
});
}
/*
添加修改商品, 获取商户分类
*/
export function categorySelect(merId) {
return request.get(`server/${merId}/category/select`, {}, {
login: true
})
}
/*
添加修改商品 获取平台分类
*/
export function categoryList(merId) {
return request.get(`server/${merId}/category/list`, {}, {
login: true
})
}
/*
商品管理 添加商品
*/
export function productCreate(merId, data) {
return request.post(`server/${merId}/product/create`, data, {
login: true
})
}
/**
* 商品列表 -- 设置推荐
*/
export function productRecommendApi(merId, id, data) {
return request.post(`server/${merId}/product/good/${id}`, data, {
login: true
});
}
/*
获取规格列表
*/
export function attrList(merId, data) {
return request.get(`server/${merId}/attr/lst`, data, {
login: true
})
}
/*
请求运费模板
*/
export function templateList(merId, data) {
return request.get(`server/${merId}/template/lst`, data, {
login: true
})
}
/*
运费模板 -- 删除
*/
export function templateDelete(merId, data) {
return request.post(`server/${merId}/template/delete`, data, {
login: true
})
}
/**
* 运费模板 -- 详情
*/
export function templateDetail(merId, id) {
return request.get(`server/${merId}/template/detail/${id}`, {}, {
login: true
});
}
/*
运费模板 -- 添加
*/
export function templateCreate(merId, data) {
return request.post(`server/${merId}/template/create`, data, {
login: true
});
}
/*
运费模板 -- 编辑
*/
export function templateUpdate(merId, id, data) {
return request.post(`server/${merId}/template/update/${id}`, data, {
login: true
});
}
/**
* 店铺分类 -- 列表
*/
export function storeClassifyLst(merId) {
return request.get(`server/${merId}/category/lst`, {}, {
login: true
});
}
/**
* 店铺分类 -- 列表(删除)
*/
export function storeClassifyDel(merId, id) {
return request.post(`server/${merId}/category/delete/${id}`, {}, {
login: true
});
}
/**
* 上级分类 -- 商户列表
*/
export function merClassifyLst(merId) {
return request.get(`server/${merId}/category/select`, {}, {
login: true
});
}
/**
* 店铺分类 -- 添加
*/
export function merClassifyAdd(merId, data) {
return request.post(`server/${merId}/category/create`, data, {
login: true
});
}
/**
* 店铺分类 -- 详情
*/
export function merClassifyDetail(merId, id) {
return request.get(`server/${merId}/category/detail/${id}`, {}, {
login: true
});
}
/**
* 店铺分类 -- 编辑
*/
export function merClassifyUpdate(merId, id, data) {
return request.post(`server/${merId}/category/update/${id}`, data, {
login: true
});
}
/**
* 商品规格项目 -- 列表
*/
export function specificationLst(merId, data) {
return request.get(`server/${merId}/attr/lst`, data, {
login: true
});
}
/**
* 商品规格项目 -- 删除
*/
export function specificationDel(merId, data) {
return request.post(`server/${merId}/attr/delete`, data, {
login: true
});
}
/**
* 商品规格项目 -- 添加
*/
export function specificationAdd(merId, data) {
return request.post(`server/${merId}/attr/create`, data, {
login: true
});
}
/**
* 商品规格项目 -- 编辑
*/
export function specificationUpdate(merId, id, data) {
return request.post(`server/${merId}/attr/update/${id}`, data, {
login: true
});
}
/**
* 商品规格项目 -- 详情
*/
export function specificationDetail(merId, id) {
return request.get(`server/${merId}/attr/detail/${id}`, {}, {
login: true
});
}
/*
请求商品详情
*/
export function productDetail(merId, id) {
return request.get(`server/${merId}/product/detail/${id}`, {}, {
login: true
});
}
/*
编辑商品
*/
export function productUpdate(merId, id, data) {
return request.post(`server/${merId}/product/update/${id}`, data, {
login: true
});
}
/*
添加商品 -- 获取送货方式信息
*/
export function getDeliveryType(merId) {
return request.get(`server/${merId}/product/config`, {}, {
login: true
});
}
/*
商品 -- 获取交易协议内容
*/
export function business() {
return request.get(`business/agree?type=business_apply_agree`, {}, {
noAuth: true
});
}
/*
商品 -- 获取交易申请记录
*/
export function intention(data) {
return request.get(`intention/lst`, data);
}
/*
商品 -- 同意提交申请
*/
export function intentionbus(data) {
return request.post(`intention/business`, {});
}

144
api/public.js Normal file
View File

@ -0,0 +1,144 @@
// +----------------------------------------------------------------------
// | 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
}
);
}
/**
* 获取微信sdk配置
* @returns {*}
*/
export function wechatAuth(code, spread, login_type) {
return request.get(
"auth/wechat", {
code,
spread,
login_type
}, {
noAuth: true
}
);
}
export function commonAuth(data) {
return request.post(
"auth", 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("auth/mp", data, {
noAuth: true
});
}
/**
* 绑定小程序账号
* @param data object 小程序用户登陆信息
*/
export function bindMp(data) {
return request.post("auth/bindMp", data, {
noAuth: true
});
}
/**
* 绑定极光id
* @param data object 小程序用户登陆信息
*/
export function bindJG(data) {
return request.post("auth/bindJg", data, {
noAuth: true
});
}
/**
* 分享
* @returns {*}
*/
export function getShare() {
return request.get("share", {}, {
noAuth: true
});
}
/**
* 获取关注海报
* @returns {*}
*/
export function follow() {
return request.get("wechat/follow", {}, {
noAuth: true
});
}
/**
* 获取图片base64
* @retins {*}
* */
export function imageBase64(image, code) {
return request.post(
"common/base64", {
image: image,
code: code
}, {
noAuth: true
}
);
}
// 配置
export function getconfig(data) {
return request.get("config",data,{noAuth: true});
}
// 浏览记录
export function history(data) {
return request.post("common/visit",data);
}
export function getSubscribe(){
return request.get("subscribe", {}, {
noAuth: true
});
}
export function getVersion() {
return request.get("version",{},{noAuth: true});
}
/**
* 获取组件底部菜单
* @param data object 获取组件底部菜单
*/
export function getNavigation(data) {
return request.get("navigation", data, {
noAuth: true
});
}

43
api/release.js Normal file
View 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";
/**
* 获取发布管理转售商品列表
* @param numType boolean true 购物车数量,false=购物车产品数量
*/
export function getResale(data) {
return request.get("community/resale/lst", data);
}
/**
* 清除发布管理转售商品
* @param object ids
*/
export function getResaledelete(id) {
return request.post('community/resale/delete/'+ id);
}
/**
* 用户是否同意转售商品折扣价
* @param object ids
*/
export function getResalecheck(id,data) {
return request.post('community/resale/check/'+ id,data);
}
/**
* 获取转售商品详情
* @param object ids
*/
export function getResaleid(id) {
return request.get('community/resale/' + id);
}

25
api/requesta.js Normal file
View File

@ -0,0 +1,25 @@
import request from "@/utils/requesta.js";
export function getCityCloundShop(data) {
return request.get("city/get_cloud_shop", data);
}
export function cloudWarehouse(data) {
return request.get("store/product/cloudWarehouse", data);
}
/**
* 供销市场标签
* @returns {*}
*/
export function supMenuApi(data) {
return request.get('intention/v2/cate', data);
}
/**
* 获取购物车列表
*
*/
export function getCartList(data) {
return request.get("user/cart/lst", data);
}
export function getCartCounts(data) {
return request.get("user/cart/count", data);
}

56
api/sale.js Normal file
View File

@ -0,0 +1,56 @@
// +----------------------------------------------------------------------
// | 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 supplychain(data) {
return request.get("community/supplychain/list", data);
}
//普通商家发布委托商品
export function entrustchain(data) {
return request.post("community/entrust", data);
}
//获取委托商品列表
export function entrustlist(data) {
return request.get("community/entrust/list", data);
}
//供应链商家是否同意委托
export function checkchain(id,data) {
return request.post("community/entrust/check/"+id, data);
}
//供应链商家申请结束委托
export function finishchain(id,data) {
return request.post("community/entrust/apply/finish/"+id, data);
}
//商家申请结束委托
export function finishentrust(id,data) {
return request.post("community/entrust/finish/"+id, data);
}
//委托商品加入购物车
export function addEntrustCart(data) {
return request.post("community/entrust/addEntrustCart", data);
}
//获取委托商品详情
export function entrustdetail(id) {
return request.get("community/entrust/"+id);
}
//编辑委托商品详情
export function editentrust(id,data) {
return request.post("community/entrust/edit/"+id, data);
}

93
api/short-video.js Normal file
View File

@ -0,0 +1,93 @@
// +----------------------------------------------------------------------
// | 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
);
}

582
api/store.js Normal file
View File

@ -0,0 +1,582 @@
import request from "@/utils/request.js";
/**
* 扫码查询商品
*
*/
export function microSeachBarCode(data) {
return request.get('micro/seach_bar_code', data);
}
/**
* 获取收款二维码
* @returns {*}
*/
export function createtApi(data) {
return request.post('v2/micropay/create', data);
}
/**
* 添加扫码商品
* @returns {*}
*/
export function addCartApi(data) {
return request.post('v2/micropay/addCart', data);
}
/**
* 获取产品详情
* @param int id
*
*/
export function getProductDetail(id, data) {
return request.get('store/product/detail/' + id, data, {
noAuth: true
});
}
/**
* 获取预览商品详情
* @param int id
*
*/
export function getPreviewProDetail(data) {
return request.get('store/product/preview', data, {
noAuth: true
});
}
/**
* 产品分享二维码 推广员
* @param int id
*/
export function getProductCode(id, data) {
return request.get('store/product/qrcode/' + id, data);
}
/**
* 添加收藏
* @param int id
* @param string category product=普通产品,product_seckill=秒杀产品
*/
export function collectAdd(data) {
return request.post('user/relation/create', data);
}
/**
* 删除收藏产品
* @param int id
* @param string category product=普通产品,product_seckill=秒杀产品
*/
export function collectDel(data) {
return request.post('user/relation/delete', data);
}
/**
* 购车添加
*
*/
export function postCartAdd(data) {
return request.post('user/cart/create', data);
}
/**
* 获取分类列表
*
*/
export function getCategoryList() {
return request.get('store/product/category/lst', {}, {
noAuth: true
});
}
/**
* 获取产品列表
* @param object data
*/
export function getProductslist(data) {
if (data.brand_id && Array.isArray(data.brand_id)) {
data = {
...data
}
data.brand_id = data.brand_id.toString()
}
return request.get('product/spu/lst', data, {
noAuth: true
});
}
/**
* 获取优惠券商品列表
* @param object data
*/
export function getCouponProductlist(data) {
if (data.brand_id && Array.isArray(data.brand_id)) {
data = {
...data
}
data.brand_id = data.brand_id.toString()
}
return request.get('product/spu/coupon_product', data, {
noAuth: true
});
}
/**
* 获取品牌列表
* @param object data
*/
export function getBrandlist(data) {
return request.get('store/product/brand/lst', data, {
noAuth: true
});
}
/**
* 获取推荐产品
*
*/
export function getProductHot(page, limit) {
return request.get("product/spu/recommend", {
page: page === undefined ? 1 : page,
limit: limit === undefined ? 10 : limit
}, {
noAuth: true
});
}
/**
* 获取商户推荐产品
*
*/
export function getMerProductHot(id, data) {
return request.get(`product/spu/recommend`, {
page: data.page === undefined ? 1 : data.page,
limit: data.limit === undefined ? 10 : data.limit,
mer_id: id || ''
}, {
noAuth: true
});
}
/**
* 批量收藏
*
* @param object id
* @param string category
*/
export function collectAll(data) {
return request.post('user/relation/batch/create', data);
}
/**
* 首页产品的轮播图和产品信息
* @param int type
*
*/
export function getGroomList(type, data) {
return request.get('product/spu/hot/' + type, data, {
noAuth: true
});
}
/**
* 获取商品收藏列表
* @param object data
*/
export function getCollectUserList(data) {
return request.get('user/relation/product/lst', data)
}
/**
* 获取商品收藏列表 -- 删除
* @param object data
*/
export function userCollectDel(data) {
return request.post('user/relation/batch/delete', data)
}
/**
* 获取产品评论
* @param int id
* @param object data
*
*/
export function getReplyList(id, data) {
return request.get('store/product/reply/lst/' + id, data, {
noAuth: true
})
}
/**
* 产品评价数量和好评度
* @param int id
*/
export function getReplyConfig(id) {
return request.get('reply/config/' + id);
}
/**
* 获取搜索关键字获取
*
*/
export function getSearchKeyword() {
return request.get('common/hot_keyword', {}, {
noAuth: true
});
}
/**
* 门店列表
* @returns {*}
*/
export function storeListApi(data) {
return request.get("store_list", data, {
noAuth: true
});
}
/**
* 商户列表
* @returns {*}
*/
export function storeMerchantList(data) {
return request.get("store/merchant/lst", data, {
noAuth: true
});
}
/**
* 获取商铺详情
* @param {Object} id 商铺id
* @param {Object} data 商铺数据
*/
export function getStoreDetail(id, data) {
return request.get("store/merchant/detail/" + id, data, {
noAuth: true
});
}
/**
* 获取商铺商品列表
* @param {Object} id 商铺 id
* @param {Object} data 商铺商品列表数据
*/
export function getStoreGoods(id, data) {
return request.get("product/spu/merchant/" + id, data, {
noAuth: true
});
}
/**
* 获取商铺分类列表
* @param {Object} id 商铺 id
* @param {Object} data
*/
export function getStoreCategory(id, data) {
return request.get("store/merchant/category/lst/" + id, data, {
noAuth: true
});
}
/**
* 关注商铺
* @param {Object} type_id 商铺 id
*/
export function followStore(type_id) {
return request.post("user/relation/create", {
type: 10,
type_id: type_id
});
}
/**
* 取消商铺关注
* @param {Object} type_id 商铺 id
*/
export function unfollowStore(type_id) {
return request.post("user/relation/delete", {
type: 10,
type_id: type_id
});
}
/**
* 获取商铺优惠券
* @param {Object} id
*/
export function getStoreCoupon(id) {
return request.get("coupon/store/" + id, {
noAuth: true
});
}
/**
* 获取商铺优惠券
*/
export function getMerchantLst(data) {
return request.get("user/relation/merchant/lst", data, {
noAuth: true
});
}
/**
* 物流信息
*/
export function express(id) {
return request.post("ordero/express/" + id, {
noAuth: true
});
}
/**
* 子集分类
* @returns {*}
*/
export function storeCategory(pid) {
return request.get("store/product/category", pid, {
noAuth: true
});
}
/**
* 分销说明
* @returns {*}
*/
export function bagExplain() {
return request.get("store/product/bag/explain");
}
/**
* 分销礼包推荐列表
* @returns {*}
*/
export function bagRecommend() {
return request.get("product/spu/bag/recommend");
}
/**
* 分销礼包列表
* @returns {*}
*/
export function productBag(data) {
return request.get("product/spu/bag", data, {
noAuth: true
});
}
/**
* 商铺二维码
* @returns {*}
*/
export function merchantQrcode(id, data) {
return request.get("store/merchant/qrcode/" + id, data, {
noAuth: true
});
}
/**
* 推荐商品
* @returns {*}
*/
export function merchantProduct(id, data) {
if (data.brand_id && Array.isArray(data.brand_id)) {
data = {
...data
}
data.brand_id = data.brand_id.toString()
}
return request.get("product/spu/merchant/" + id, data, {
noAuth: true
});
}
/**
* 推荐商品banner
* @returns {*}
*/
export function getHotBanner(type) {
return request.get("common/hot_banner/" + type, {}, {
noAuth: true
});
}
/**
* 商户入驻表单
* @returns {*}
*/
export function create(data) {
return request.post("intention/create", data);
}
/**
* 商户入驻短信验证码
* @returns {*}
*/
export function verify(data) {
return request.post("auth/verify", data);
}
/**
* 获取秒杀商品详情
* @param int id
*
*/
export function getSeckillProductDetail(id) {
return request.get('store/product/seckill/detail/' + id, {}, {
noAuth: true
});
}
/**
* 直播推荐列表
* @returns {*}
*/
export function getLiveList(data) {
return request.get(`broadcast/hot`, data, {
noAuth: true
});
}
/**
* 直播列表
* @returns {*}
*/
export function getBroadcastListApi(data) {
return request.get("broadcast/lst", data, {
noAuth: true
});
}
/**
* 商户分类
* @returns {*}
*/
export function merClassifly() {
return request.get("intention/cate", {}, {
noAuth: true
});
}
/**
* 获取预售商品详情
* @param int id
*
*/
export function getPresellProductDetail(id) {
return request.get('store/product/presell/detail/' + id, {}, {
noAuth: true
});
}
/**
* 获取商户申请记录
* @param int id
*
*/
export function getApplicationRecordList(data) {
return request.get('intention/lst', data);
}
/**
* 获取商户申请详情
* @param int id
*
*/
export function getGoodsDetails(id) {
return request.get('intention/detail/' + id, {});
}
/**
* 修改入驻信息
* @param int id
*
*/
export function updateGoodsRecord(id, data) {
return request.post('intention/update/' + id, data);
}
/**
* 获取定位详细地址
* @param int id
*
*/
export function getGeocoder(data) {
return request.get(`lbs/geocoder?location=${data.lat},${data.long}`, {}, {
noAuth: true
});
}
/**
* 获取店铺类型
* @param int id
*
*/
export function getStoreTypeApi() {
return request.get('intention/type', {
sift_store: 0
}, {
noAuth: true
});
}
/**
* 到货通知
*
*/
export function arrivalNoticeApi(data) {
return request.post('store/product/increase_take', data);
}
/*
获取图片验证码
*/
export function getCaptcha() {
return request.get('captcha');
}
/*
获取店铺资质
*/
export function storeCertificate(data) {
return request.post(`store/certificate/${data.merId}`, data)
}
/**
* 本地服务列表
* @returns {*}
*/
export function storeServiceList(id, data) {
return request.get(`product/spu/local/${id}`, data, {
noAuth: true
});
}
/**
* 复制口令
* @returns {*}
*/
export function copyPasswordApi(data) {
return request.get(`product/spu/copy`, data, {
noAuth: true
});
}
/**
* 口令搜索
* @returns {*}
*/
export function copyPasswordSearch(data) {
return request.get(`command/copy`, data, {
noAuth: true
});
}
/**
* 套餐列表
* @returns {*}
*/
export function getDiscountsLst(data) {
return request.get(`discounts/lst`, data, {
noAuth: true
});
}
/**
* 套餐--立即购买
* @returns {*}
*/
export function discountsCartAdd(data) {
return request.post('user/cart/batchCreate', data);
}
/**
* 商品--价格说明
* @returns {*}
*/
export function priceRuleApi(id) {
return request.get(`store/product/price_rule/${id}`, {}, {
noAuth: true
});
}
/**
* 供销市场标签
* @returns {*}
*/
export function supMenuApi(data) {
return request.get('intention/v2/cate', data);
}
/**
* 供销市场标签
* @returns {*}
*/
export function supAgoodsApi(data) {
return request.get('store/merchant/lst', data);
}
// /api/store / merchant / lst ? page = 1 & limit = 10 & order = & category_id = 22 & type_id = 10 & street_id = &
// credit_buy =
// /api/region/:street_id/merchant
/**
* 附近商家
* @returns {*}
*/
// export function supAgoodsApi(data) {
// return request.get('store/merchant/lst', data);
// }
export function vicinityStoreApi(data) {
return request.get(`region/${data}/merchant`);
}
/*
商家入驻 -- 获取商户入驻申请协议内容
*/
export function agreeiness() {
return request.get(`business/agree?type=sys_intention_agree`, {}, { noAuth: true });
}

88
api/trading-floor.js Normal file
View File

@ -0,0 +1,88 @@
// +----------------------------------------------------------------------
// | 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 getCommunityList(data) {
return request.get('community/lst', data, {
noAuth: true
});
}
/**
* 商品详情
*
*/
export function getCommunityshow(data) {
return request.get('community/show/' + data, {}, {
noAuth: true
});
}
/**
* 可转售的订单列表
*
*/
export function getCommunitygetOrderList(data) {
return request.get('community/product/lst', data, {
noAuth: true
});
}
/**
* 发起转售
*
*/
export function getCommunitycreate(data) {
return request.post(`community/create`, data, {
login: true
});
}
/**
* 修改转售
*
*/
export function getCommunityUpdate(data) {
return request.post(`community/update`, data, {
login: true
});
}
/**
* 加入购物车
*
*/
export function getCommunityaddCart(data) {
return request.post('community/addCart', data, {
noAuth: true
});
}
//商品宝贝详情
export function getProductDetail(id) {
return request.get('store/product/detail/' + id,
);
}
//获取转售商品详情
export function getresaleDetail(id) {
return request.get('community/resale/' + id,
);
}
//编辑转售商品
export function getresaleEdit(id,data) {
return request.post('community/resale/edit/' + id,data
);
}

18
api/uniMP.js Normal file
View 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>
// +----------------------------------------------------------------------
import request from "@/utils/request.js";
/**
* 获取供销平台版本信息
*/
export function getGXconfig(data) {
return request.get("global/config", data);
}

59
api/upload.js Normal file
View File

@ -0,0 +1,59 @@
// import base from "@/config/baseUrl";
// let baseUrl = 'https://ceshi.excellentkk.cn/api';
import { HTTP_REQUEST_URL_TWO, HTTP_REQUEST_URL_THREE, HEADER } from '@/config/app';
let header = HEADER;
function uploads(src, type) {
return new Promise((resolve, reject) => {
// console.log('上传', type === 'img' ? '图片' : '视频', '', src)
let a = uni.uploadFile({
// url: base.baseUrl + '/upload?token=',
url: HTTP_REQUEST_URL_TWO + '/api' + '/upload?token=',
filePath: src,
name: 'file',
success: (res) => {
let data = JSON.parse(res.data)
if (data.code != 1) {
uni.$u.toast(data.msg)
return false
} else {
resolve(data.data.url) // 返回线上地址
}
},
fail: (err) => {
reject(err)
// console.log('upload-上传失败', err)
}
});
})
}
function oaUploads(src, type) {
return new Promise((resolve, reject) => {
// console.log('上传', type === 'img' ? '图片' : '视频', '', src)
let a = uni.uploadFile({
url: HTTP_REQUEST_URL_THREE + '/api/v1/index/upload',
filePath: src,
name: 'file',
header: header,
success: (res) => {
let data = JSON.parse(res.data)
if (data.code == 200) {
resolve(data.data) // 返回线上地址
} else {
uni.$u.toast(data.msg)
return false
}
},
fail: (err) => {
reject(err)
// console.log('upload-上传失败', err)
}
});
})
}
export {
uploads,
oaUploads
}

723
api/user.js Normal file
View File

@ -0,0 +1,723 @@
// +----------------------------------------------------------------------
// | 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 Cache from '@/utils/cache'
/**
* 获取版本信息
*/
export function Appversion(data) {
return request.get(`app/version`, data, {
noAuth: true
});
}
/**
* 提交提现
*/
export function postCreateApplyAPI(merId, data) {
return request.post(`admin/${merId}/create_apply`, data);
}
/**
* 申请提现
*/
export function getAdminApplyAPI(merId, data) {
return request.get(`admin/${merId}/apply`, data);
}
/**
* 提现记录
*/
export function getAdminApplyListAPI(merId) {
return request.get(`admin/${merId}/lis_apply`);
}
/**
* 获取用户信息
*
*/
export function getUserInfo() {
return request.get('user');
}
/**
* 头像
*
*/
export function editAvatar(data) {
return request.post('user/change/info', data);
}
// 修改昵称
export function updateInfo(data) {
return request.post('user/change/avatar', data);
}
/**
* h5用户登录
* @param data object 用户账号密码
*/
export function loginH5(data) {
return request.post("auth/login", data, {
noAuth: true
});
}
/**
* h5用户手机号登录
* @param data object 用户手机号 也只能
*/
export function loginMobile(data) {
return request.post("auth/smslogin", data, {
noAuth: true
});
}
/**
* h5用户手机号登录
* @param data object 用户手机号 也只能
*/
export function loginMpPhone(data) {
return request.post("auth/mp_phone", 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("auth/verify", data, {
noAuth: true
});
}
/**
* h5用户手机号注册
* @param data object 用户手机号 验证码 密码
*/
export function register(data) {
return request.post("auth/register", data, {
noAuth: true
});
}
/**
* 用户手机号修改密码
* @param data object 用户手机号 验证码 密码
*/
export function registerReset(data) {
return request.post("/register/reset", data, {
noAuth: true
});
}
/**
* 用户手机号忘记密码
*/
export function registerForget(data) {
return request.post("user/change_pwd", data, {
noAuth: true
});
}
/**
* 获取用户中心菜单
*
*/
export function getMenuList() {
return request.get("common/menus", {}, { noAuth: true });
}
/*
* 签到用户信息
* */
export function getSignUser() {
return request.get("user/sign/info");
}
/**
* 获取签到配置
*
*/
export function getSignConfig() {
return request.get('sign/config')
}
/**
* 获取签到列表
* @param object data
*/
export function getSignList(data) {
return request.get('user/sign/lst', data);
}
/**
* 用户签到
*/
export function setSignIntegral() {
return request.post('user/sign/create')
}
/**
* 签到列表(年月)
* @param object data
*
*/
export function getSignMonthList(data) {
return request.get('user/sign/month', data)
}
/**
* 活动状态
*
*/
export function userActivity() {
return request.get('user/activity');
}
/*
* 资金明细types|0=全部,1=消费,2=充值,3=返佣
* */
export function getCommissionInfo(q, types) {
return request.get("user/bill", q);
}
/*
* 提现列表
* */
export function extractLst(data) {
return request.get("user/extract/lst", data);
}
/*
* 积分记录
* */
export function getIntegralList(data) {
return request.get("user/integral/lst", data);
}
/**
* 获取分销海报图片
*
*/
export function spreadBanner() {
//#ifdef H5
return request.get('user/spread_image', {
type: 'wechat'
});
//#endif
//#ifdef MP
return request.get('user/spread_image', {
type: 'routine'
});
//#endif
}
/**
*
* 获取推广用户一级和二级
* @param object data
*/
export function spreadPeople(data) {
return request.get('user/spread_list', data);
}
/**
*
* 推广佣金/提现总和
* @param int type
*/
export function spreadCount(type) {
return request.get('spread/count/' + type);
}
/*
* 推广数据
* */
export function getSpreadInfo() {
return request.get("/commission");
}
/**
*
* 推广订单
* @param object data
*/
export function spreadOrder(data) {
return request.get('user/spread_order', data);
}
/*
* 获取推广人排行
* */
export function getRankList(data) {
return request.get("user/spread_top", data);
}
/*
* 获取佣金排名
* */
export function getBrokerageRank(q) {
return request.get("user/brokerage_top", q);
}
/**
* 提现申请
* @param object data
*/
export function extractCash(data) {
return request.post('user/extract/create', data)
}
/**
* 提现银行/提现最低金额
*
*/
export function extractBank() {
return request.get('user/extract/banklst');
}
/**
* 会员等级列表
*
*/
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('user/address/lst', data);
}
/**
* 设置默认地址
* @param int id
*/
export function setAddressDefault(id) {
return request.post('user/address/update/' + id)
}
/**
* 修改 添加地址
* @param object data
*/
export function editAddress(data) {
return request.post('user/address/create', data);
}
/**
* 删除地址
* @param int id
*
*/
export function delAddress(id) {
return request.post('user/address/delete/' + id)
}
/**
* 获取单个地址
* @param int id
*/
export function getAddressDetail(id) {
return request.get('user/address/detail/' + id);
}
/**
* 修改用户信息
* @param object
*/
export function userEdit(data) {
return request.post('user/edit', data);
}
/*
* 退出登录
* */
export function getLogout() {
return request.post("logout");
}
/**
* 佣金转入
*
*/
export function rechargeBrokerage(data) {
return request.post('user/recharge/brokerage', data)
}
/**
* 小程序充值
*
*/
export function rechargeRoutine(data) {
return request.post('recharge/routine', data)
}
/*
* 公众号充值
* */
export function rechargeWechat(data) {
return request.post("user/recharge", data);
}
/**
* 获取默认地址
*
*/
export function getAddressDefault() {
return request.get('address/default');
}
/**
* 充值金额选择
*/
export function getRechargeApi() {
return request.get("common/recharge_quota");
}
/**
* 登陆记录
*/
export function setVisit(data) {
return request.post('user/set_visit', {
...data
}, {
noAuth: true
});
}
/**
* 客服列表
*/
export function serviceList(data) {
return request.get("service/list", data);
}
/**
* 客服列表
*/
export function serviceLogin(key, data) {
return request.post("service/scan_login/" + key, data);
}
/**
* 客服获取客户列表
*/
export function serviceUserList(mer_id, data) {
return request.get("service/user_list/" + mer_id, data);
}
/**
* 用户获取聊天记录详情
*/
export function getChatRecord(to_uid, data) {
return request.get("service/history/" + to_uid, data);
}
/**
* 客服获取聊天记录详情
*/
export function getMerHistory(userid, mer_id, data) {
return request.get("service/mer_history/" + mer_id + '/' + userid, data);
}
/**
* 静默绑定推广人
* @param {Object} puid
*/
export function spread(puid) {
Cache.set("spread", puid || 0);
return request.post("user/spread", {
spread_spid: puid
});
}
/**
* 反馈类型
*/
export function feedbackType() {
return request.get("common/feedback_type");
}
/**
* 提交反馈
*/
export function feedback(data) {
return request.post("user/feedback", {
...data
});
}
/**
* 反馈列表
*/
export function feedbackList(data) {
return request.get("user/feedback/list", data);
}
/**
* 反馈列表
*/
export function feedbackDetail(id) {
return request.get("user/feedback/detail/" + id);
}
/**
* 浏览记录
*/
export function historyList(data) {
return request.get("user/history", data);
}
/**
* 删除浏览记录
*/
export function historyDelete(id) {
return request.post("user/history/delete/" + id);
}
/**
* 批量删除浏览记录
*/
export function historyBatchDelete(data) {
return request.post("user/history/batch/delete", data);
}
/**
* 批量收藏浏览记录
*/
export function historyBatchCollect(data) {
return request.post("user/relation/batch/create", data);
}
/**
* 佣金记录
*/
export function brokerage_list(data) {
return request.get("user/brokerage_list", data);
}
/**
* 佣金数据
*/
export function spreadInfo() {
return request.get("user/spread_info");
}
// 图片验证码
export function getCaptcha() {
return request.get('captcha', {}, {
noAuth: true
});
}
// 用户账户列表
export function userAcc() {
return request.get('user/account', {}, {
noAuth: true
});
}
// 创建发票
export function invoiceSave(data) {
return request.post('user/receipt/create', data);
}
// 编辑发票
export function invoiceUpdate(id, data) {
return request.post('user/receipt/update/' + id, data);
}
// 获取默认发票
export function invoiceDefault(id) {
return request.post('user/receipt/is_default/' + id);
}
// 发票抬头--列表
export function invoice(data) {
return request.get('user/receipt/lst', data);
}
// 发票抬头--删除
export function invoiceDelete(id) {
return request.post('user/receipt/delete/' + id);
}
// 发票--详情
export function invoiceDetail(id) {
return request.get('user/receipt/detail/' + id);
}
/**
* 新版分享海报信息获取
*
*/
export function spreadMsg(data) {
return request.get('user/v2/spread_image', data);
}
/**
* 图片链接转base64
*
*/
export function imgToBase(data) {
return request.post('common/base64', data);
}
/**
* 获取协议
*
*/
export function getAgreementApi(key) {
return request.get('agreement/' + key, {}, { noAuth: true });
}
/**
* 获取协议
*
*/
export function getIntegralInfo() {
return request.get('user/integral/info');
}
/**
* 获取店铺列表
*
*/
export function getStoreList(data) {
return request.get('user/services', data);
}
/*
获取佣金说明
*/
export function commissionDescription() {
return request.get('agreement/sys_extension_agree')
}
/*
获取用户分销等级信息
*/
export function getBrokerageInfo() {
return request.get('user/brokerage/info')
}
/*
获取用户分销等级表格数据
*/
export function getBrokerageGrade() {
return request.get('user/brokerage/all')
}
/*
分销员升级提醒
*/
export function brokerageNotice(data) {
return request.get(`user/brokerage/notice`, data)
}
/*
口令解析
*/
export function pwdResolution(data) {
return request.get(`command/copy?key=${data}`)
}
/*
获取佣金说明
*/
export function getInstructions(key) {
return request.get(`agreement/${key}`)
}
/*
会员信息
*/
export function memberInfo() {
return request.get('user/member/info')
}
/**
* 成长值记录
* @param object data
*
*/
export function growthValueRecord(data) {
return request.get('user/member/log', data)
}
/**
* 协议规则列表
* @param object data
*
*/
export function cacheLst() {
return request.get('agreement_lst', {}, { noAuth: true })
}
/**
* 协议规则列表对应的数据
* @param object data
*
*/
export function cacheInfo(key) {
return request.get(`agreement/${key}`, {}, { noAuth: true })
}
/**
* 注销账户
* @param object data
*
*/
export function userOut(data) {
return request.post(`user/cancel`, data)
}
/**
* 获取聊天用户信息
* @param object data
*
*/
export function serviceUser(merId, uid) {
return request.get(`service/user/${merId}/${uid}`)
}
/**
* 保存聊天用户备注
* @param object data
*
*/
export function serviceSaveMark(merId, uid, mark) {
return request.post(`service/mark/${merId}/${uid}`, { mark })
}
/**
* 获取会员卡类型
* @param object data
*
*/
export function memberCard() {
return request.get(`svip/pay_lst`)
}
/**
* 开通付费会员--支付
* @param object data
*
*/
export function memberCardCreate(id, data) {
return request.post(`svip/pay/${id}`, data)
}
/**
* 付费会员权益
* @param object data
*
*/
export function memberEquity() {
return request.get(`svip/user_info`, {}, { noAuth: true })
}
/**
* 付费会员优惠券
* @param object data
*
*/
export function memberCouponLst() {
return request.get(`svip/coupon_lst`, {}, { noAuth: true })
}
/**
* 付费会员优惠券--领取
* @param object data
*
*/
export function receiveMemberCoupon(id) {
return request.post(`svip/coupon_receive/${id}`)
}
/**
* 付费会员--会员商品
* @param object data
*
*/
export function groomList(data) {
return request.get(`svip/product_lst`, data, { noAuth: true })
}
/**
* 客服聊天--撤回消息
* @param object data
*
*/
export function chatReverstApi(id) {
return request.post(`service/recall/${id}`)
}
/**
* 客服聊天--判断店铺是否有在线客服
* @param object data
*
*/
export function hasServiceApi(id) {
return request.get(`has_service/${id}`)
}
/**
* 银行卡提现--银行卡信息
* @param object data
*
*/
export function getBankInfo() {
return request.get(`user/extract/history_bank`)
}
// 商户账单管理
export function getBillDetil() {
return request.get(`mer/financial_record`)
}

365
components/Authorize.vue Normal file
View File

@ -0,0 +1,365 @@
<template>
<view>
<view class='mask' v-if='isShowAuth && code' @click='close'></view>
<view class='Popup' v-if='isShowAuth && code' :style="'top:'+top+'px;'">
<!-- <view class="logo-auth">
<image class="image" :src='routine_logo' mode="aspectFit"></image>
</view> -->
<!--#ifdef H5-->
<text v-if="isWeixin" class='title'>授权提醒</text>
<text v-else class='title'>{{title}}</text>
<!--#endif-->
<!--#ifdef APP-PLUS-->
<text class='title'>用户登录</text>
<!--#endif-->
<!--#ifdef MP-->
<text class='title'>{{title}}</text>
<!--#endif-->
<!--#ifdef H5-->
<text v-if="isWeixin" class='tip'>请授权头像等信息以便为您提供更好的服务</text>
<text v-else class='tip'>{{info}}</text>
<!--#endif-->
<!--#ifdef APP-PLUS-->
<text class='tip'>请登录将为您提供更好的服务</text>
<!--#endif-->
<!--#ifdef MP-->
<text class='tip'>{{info}}</text>
<!--#endif-->
<view class='bottom flex'>
<text class='item' @click='close'>随便逛逛</text>
<!-- #ifdef MP -->
<button class="item grant" hover-class="none" @tap="getUserProfile"><text
class="text">去授权</text></button>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<button class="item grant" @tap="toWecahtAuth">
<text class="text">去登录</text>
</button>
<!-- #endif -->
<!-- #ifdef H5 -->
<button class="item grant" @tap="toWecahtAuth">
<text v-if="isWeixin" class="text">去授权</text>
<text v-else class="text">去登录</text>
</button>
<!-- #endif -->
</view>
</view>
<!-- #ifdef MP -->
<editUserModal :isShow="editModal" @closeEdit="closeEdit" @editSuccess="editSuccess"></editUserModal>
<!-- #endif -->
</view>
</template>
<script>
const app = getApp();
import Cache from '../utils/cache';
import {
getLogo,
commonAuth
} from '../api/public';
import {
LOGO_URL,
USER_INFO,
EXPIRES_TIME
} from '../config/cache';
import {
mapGetters
} from 'vuex';
import Routine from '../libs/routine';
import {
configMap
} from '@/utils/index';
import Auth from '../libs/wechat';
import {
toLogin
} from '../libs/login';
// #ifdef MP
import editUserModal from '@/components/eidtUserModal/index.vue'
// #endif
export default {
name: 'Authorize',
props: {
isAuto: {
type: Boolean,
default: true
},
isGoIndex: {
type: Boolean,
default: true
},
isShowAuth: {
type: Boolean,
default: false
}
},
components: {
// #ifdef MP
editUserModal
// #endif
},
data() {
return {
title: '用户登录',
info: '请登录,将为您提供更好的服务!',
//#ifdef H5
isWeixin: this.$wechat.isWeixin(),
//#endif
//#ifdef MP
title: '授权提醒',
info: '请授权头像等信息,以便为您提供更好的服务!',
//#endif
canUseGetUserProfile: false,
code: null,
top: 0,
mp_is_new: this.$Cache.get('MP_VERSION_ISNEW') || false,
editModal: false, //
}
},
computed: {
...mapGetters(['isLogin', 'userInfo', 'viewColor']),
...configMap(['routine_logo'])
},
watch: {
isLogin(n) {
n === true && this.$emit('onLoadFun', this.userInfo);
},
isShowAuth(n) {
this.getCode(this.isShowAuth)
}
},
created() {
// console.log('title' + this.title)
this.top = uni.getSystemInfoSync().windowHeight / 2 - 70
if (wx.getUserProfile) {
this.canUseGetUserProfile = true
}
this.setAuthStatus();
this.getCode(this.isShowAuth)
},
methods: {
// #ifdef MP
editSuccess() {
this.editModal = false
this.$emit('onLoadFun', this.userInfo);
},
closeEdit() {
this.editModal = false
},
// #endif
setAuthStatus() {
//#ifdef MP
Routine.authorize().then(res => {
if (res.islogin === false)
this.$emit('onLoadFun', this.userInfo);
}).catch(res => {
if (this.isAuto)
this.$emit('authColse', true);
})
//#endif
},
getCode(n) {
// #ifdef MP
if (n) {
uni.showLoading({
title: '正在登录中'
});
Routine.getCode().then(code => {
uni.hideLoading();
this.code = code;
}).catch(e => {
uni.hideLoading();
uni.showToast({
title: '登录失败',
duration: 2000
});
})
} else {
this.code = null;
}
// #endif
// #ifndef MP
if (n) {
this.code = 1;
}
// #endif
},
toWecahtAuth() {
toLogin(true);
},
getUserProfile() {
// console.log(11);
toLogin(true);
uni.navigateTo({
url: '/pages/users/login/login_copy'
})
// console.log(22);
return
let self = this;
Routine.getUserProfile()
.then(res => {
let userInfo = res.userInfo;
userInfo.code = this.code;
userInfo.spread = app.globalData.spid; //广ID
userInfo.spread_code = app.globalData.code; //广ID
commonAuth({
auth: {
type: 'routine',
auth: userInfo
}
}).then(res => {
if (res.data.status == 200) {
let time = res.data.result.expires_time - Cache.time();
self.$store.commit('UPDATE_USERINFO', res.data.result.user);
self.$store.commit('LOGIN', {
token: res.data.result.token,
time: time
});
self.$store.commit('SETUID', res.data.result.user.uid);
Cache.set(EXPIRES_TIME, res.data.result.expires_time, time);
Cache.set(USER_INFO, res.data.result.user, time);
this.$emit('onLoadFun', res.data.result.user);
if (res.data.result.user.isNew && this.mp_is_new) {
this.editModal = true;
}
} else {
uni.setStorageSync('auth_token', res.data.result.key);
return uni.navigateTo({
url: '/pages/users/login/login_copy'
})
}
}).catch(res => {
uni.hideLoading();
uni.showToast({
title: res.message,
icon: 'none',
duration: 2000,
});
});
})
.catch(res => {
uni.hideLoading();
});
},
close() {
let pages = getCurrentPages(),
currPage = pages[pages.length - 1];
this.$emit('authColse', false);
if (this.isGoIndex) {
uni.switchTab({
url: '/pages/index/index'
});
} else {
this.$emit('authColse', false);
}
},
}
}
</script>
<style scoped lang='scss'>
.Popup {
flex: 1;
align-items: center;
justify-content: center;
width: 500rpx;
background-color: #fff;
position: fixed;
top: 500rpx;
left: 125rpx;
z-index: 1000;
border-radius: 8px;
overflow: hidden;
}
.Popup {
.logo-auth {
z-index: -1;
position: absolute;
left: 50%;
top: 0%;
transform: translate(-50%, -50%);
width: 150rpx;
height: 150rpx;
display: flex;
align-items: center;
justify-content: center;
border: 8rpx solid #fff;
border-radius: 50%;
background: #fff;
}
.image {
height: 42rpx;
margin-top: -54rpx;
}
}
.Popup .title {
font-size: 28rpx;
color: #000;
text-align: center;
margin-top: 30rpx;
align-items: center;
justify-content: center;
width: 500rpx;
display: flex;
}
.Popup .tip {
font-size: 22rpx;
color: #555;
padding: 0 24rpx;
margin-top: 25rpx;
display: flex;
align-items: center;
justify-content: center;
}
.Popup .bottom .item {
width: 250rpx;
height: 80rpx;
background-color: #eeeeee;
text-align: center;
line-height: 80rpx;
margin-top: 54rpx;
font-size: 24rpx;
color: #666;
.text {
font-size: 24rpx;
color: #666;
}
}
.Popup .bottom .item.on {
width: 500rpx;
}
.flex {
display: flex;
flex-direction: row;
}
.Popup .bottom .item.grant {
font-weight: bold;
background-color: #E93323;
/* background-color: var(--view-theme); */
border-radius: 0;
padding: 0;
.text {
font-size: 28rpx;
color: #fff;
}
}
.mask {
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.65);
z-index: 99;
}
</style>

101
components/BaseMoney.vue Normal file
View File

@ -0,0 +1,101 @@
<template>
<view :class="{ line: line, weight: weight }"
:style="{color: '#' + incolor,fontWeight: fontWeight, display:(discount || inline) ? 'inline-block' : 'block', fontFamily: line?'Futura-Light':'Futura' }"
class="base-money">
<text v-if="!discount" class="symbol" :style="{'font-size': symbolSize +'rpx'}"></text><text class="integer"
:style="{'font-size': integerSize +'rpx'}">{{ integer }}</text>
<text v-if="digits && decimal != '00' && decimal != '0'" class="decimal"
:style="{'font-size': decimalSize +'rpx'}">.{{ decimal }}</text>
</view>
</template>
<script>
export default {
name: 'BaseMoney',
props: {
// 0
digits: {
type: Number,
default: 2
},
fontWeight: {
type: Number | String,
default: 'inherit'
},
money: {
type: String,
default: ""
},
// 线
line: {
type: Boolean,
default: false
},
//
weight: {
type: Boolean,
default: false
},
incolor: {
type: String,
default: '424242'
},
symbolSize: {
type: String,
default: '20'
},
integerSize: {
type: String,
default: '26'
},
decimalSize: {
type: String,
default: '24'
},
discount: {
type: Boolean,
default: false
},
inline: {
type: Boolean,
default: false
}
},
data() {
return {
integer: 0,
decimal: 0
};
},
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].length == 2 && value[1].charAt(1) != 0) ? value[1] : (value[1].charAt(
0) || 0);
}
},
immediate: true
}
}
}
</script>
<style lang="scss" scoped>
.base-money {
font-family: Futura;
// display: inline-block;
&.line {
text-decoration: line-through;
}
&.weight {
font-weight: 500;
}
}
</style>

View File

@ -0,0 +1,66 @@
<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>
正在加载中
</view>
<view v-else>
上拉加载更多
</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
export default {
name: "Loading",
props: {
loaded: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
}
}
};
</script>
<style>
.Loads {
height: 80upx;
font-size: 25upx;
color: #000;
}
.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>

View File

@ -0,0 +1,165 @@
<template>
<view>
<view class="priceChange" :class="change === true ? 'on' : ''">
<view class="priceTitle">
{{ status == 0 ? "一键改价" : status == 1 ? "订单备注" : "立即退款" }}
<span class="iconfont icon-guanbi" @click="close"></span>
</view>
<view class="listChange" v-if="status == 0">
<view class="item acea-row row-between-wrapper">
<view>商品总价(¥)</view>
<view class="money">
<input
type="digit"
class="color_black"
v-model="orderInfo.total_price"
@input="setValue"
/>
</view>
</view>
<view class="item acea-row row-between-wrapper">
<view>实际支付邮费(¥)</view>
<view class="money">
<input
type="digit"
class="color_black"
v-model="orderInfo.pay_postage"
@input="setValue"
/>
</view>
</view>
<view
class="item acea-row row-between-wrapper"
>
<view>实际支付金额(¥)</view>
<view class="money">
{{ Number(this.orderInfo.total_price) + Number(this.orderInfo.pay_postage) - Number(this.orderInfo.coupon_price) - Number(this.orderInfo.integral_price)}}<span class="iconfont icon-suozi"></span>
</view>
</view>
<view v-if="orderInfo.coupon_price>0" class="item acea-row row-between-wrapper">
<view>优惠金额(¥)</view>
<view class="money">
{{ orderInfo.coupon_price }}<span class="iconfont icon-suozi"></span>
</view>
</view>
<view v-if="orderInfo.integral_price>0" class="item acea-row row-between-wrapper">
<view>积分抵扣(¥)</view>
<view class="money">
{{ orderInfo.integral_price }}<span class="iconfont icon-suozi"></span>
</view>
</view>
</view>
<view class="listChange" v-else>
<textarea
:placeholder="orderInfo.remark ? orderInfo.remark : '请填写备注信息...'"
v-model="remark"
></textarea>
</view>
<view class="modify" @click="save">
{{
status == 0 ? "立即修改" : "确认提交"
}}
</view>
</view>
<view class="mask" @touchmove.prevent v-show="change === true"></view>
</view>
</template>
<style>
.priceChange{position:fixed;width:580upx;background-color:#fff;border-radius:10upx;top:50%;left:50%;margin-left:-290upx;margin-top:-335upx;z-index:666;transition:all 0.3s ease-in-out 0s;transform: scale(0);opacity:0;}
.priceChange.on{opacity:1;transform: scale(1);}
.priceChange .priceTitle{background:url("~@/static/images/pricetitle.jpg") no-repeat;background-size:100% 100%;width:100%;height:160upx;border-radius:10upx 10upx 0 0;text-align:center;font-size:40upx;color:#fff;line-height:160upx;position:relative;}
.priceChange .priceTitle .iconfont{position:absolute;font-size:40upx;right:26upx;top:23upx;width:40upx;height:40upx;line-height:40upx;}
.priceChange .listChange{padding:0 40upx;}
.priceChange .listChange textarea{box-sizing: border-box;}
.priceChange .listChange .item{height:103upx;border-bottom:1px solid #e3e3e3;font-size:32upx;color:#333;}
.priceChange .listChange .item .money{color:#666;width:200upx;text-align:right;}
.priceChange .listChange .item .money .color_black{color: #333;}
.priceChange .listChange .item .money .iconfont{font-size:32upx;margin-left:20upx;}
.priceChange .listChange .item .money input{width:100%;height:100%;text-align:right;color:#ccc;}
.priceChange .listChange .item .money input.on{color:#666;}
.priceChange .modify{font-size:32upx;color:#fff;width:490upx;height:90upx;text-align:center;line-height:90upx;border-radius:45upx;background-color:#2291f8;margin:53upx auto;}
.priceChange .modify1{font-size:32upx;color:#312b2b;width:490upx;height:90upx;text-align:center;line-height:90upx;border-radius:45upx;background-color:#eee;margin:30upx auto 0 auto;}
.priceChange .listChange textarea {
border: 1px solid #eee;
width: 100%;
height: 200upx;
margin-top: 50upx;
border-radius: 10upx;
color: #333;
padding: 20upx;
}
</style>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
export default {
name: "PriceChange",
components: {},
props: {
change: Boolean,
orderInfo: Object,
status: String
},
data: function() {
return {
focus: false,
price: 0,
actual_price: 0,
refund_price: 0,
remark: ""
};
},
watch: {
orderInfo: function(nVal) {
this.price = this.orderInfo.pay_price;
this.actual_price = this.orderInfo.total_price + this.orderInfo.pay_postage - this.orderInfo.coupon_price
this.refund_price = this.orderInfo.pay_price;
this.remark = this.orderInfo.remark;
}
},
mounted: function() {
},
methods: {
priceChange: function() {
this.focus = true;
},
close: function() {
this.price = this.orderInfo.pay_price;
this.$emit("closechange", false);
},
setValue: function(){
this.price = this.orderInfo.total_price + this.orderInfo.pay_postage - this.orderInfo.coupon_price
},
save: function() {
let that = this;
that.$emit("savePrice", {
price: that.price,
refund_price: that.refund_price,
type: 1,
remark: that.remark,
orderInfo: that.orderInfo
});
},
refuse: function() {
let that = this;
that.$emit("savePrice", {
price: that.price,
refund_price: that.refund_price,
type: 2,
remark: that.remark
});
}
}
};
</script>

View File

@ -0,0 +1,195 @@
<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" @goShop="goShop"/>
</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" @goShop="goShop"/>
</view>
</view>
</view>
</view>
</template>
<script>
import WaterfallsFlowItem from '../WaterfallsFlowItem/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'
},
},
data() {
return {
allList: [], //
leftList: [], //
rightList: [], //
mark: 0, //
boxHeight: [], // 01
};
},
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;
}
.wf-item-page{
padding-bottom: 20rpx;
}
</style>

View File

@ -0,0 +1,208 @@
<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-itema" @tap="itemTap(item)">
<WaterfallsFlowItem :item="item" :isStore="isStore" :type="type" @goShop="goShop"/>
</view>
</view>
</view>
<!-- right -->
<view>
<view id="right" v-if="rightList.length">
<view v-for="(item,index) in rightList" :key="index"
class="wf-itemb" @tap="itemTap(item)">
<WaterfallsFlowItem :item="item" :isStore="isStore" :type="type" @goShop="goShop"/>
</view>
</view>
</view>
</view>
</template>
<script>
import WaterfallsFlowItem from '../WaterfallsFlowItem/WaterfallsFlowItemo.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'
},
},
data() {
return {
allList: [], //
leftList: [], //
rightList: [], //
mark: 0, //
boxHeight: [], // 01
};
},
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: 5px;
.wf-page {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: $grid-gap;
}
.wf-itema {
width: 356rpx;
padding-bottom: $grid-gap;
}
.wf-itemb {
width: 356rpx;
padding-bottom: $grid-gap;
}
.wf-page1 .wf-item{
margin-top: 20rpx;
background-color: #fff;
border-radius: 20rpx;
padding-bottom: 0;
}
.wf-item-page{
padding-bottom: 20rpx;
}
</style>

View File

@ -0,0 +1,207 @@
<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-itema" @tap="itemTap(item)">
<WaterfallsFlowItem :item="item" :isStore="isStore" :heightx="251" :type="type" @goShop="goShop"/>
</view>
</view>
</view>
<!-- right -->
<view>
<view id="right" v-if="rightList.length">
<view v-for="(item,index) in rightList" :key="index"
class="wf-itemb" @tap="itemTap(item)">
<WaterfallsFlowItem :item="item" :isStore="isStore" :heightx="336" :type="type" @goShop="goShop"/>
</view>
</view>
</view>
</view>
</template>
<script>
import WaterfallsFlowItem from '../WaterfallsFlowItem/WaterfallsFlowItems.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'
},
},
data() {
return {
allList: [], //
leftList: [], //
rightList: [], //
mark: 0, //
boxHeight: [], // 01
};
},
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
},
// 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: 5px;
.wf-page {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: $grid-gap;
}
.wf-itema {
width: 356rpx;
padding-bottom: $grid-gap;
}
.wf-itemb {
width: 356rpx;
padding-bottom: $grid-gap;
}
.wf-page1 .wf-item{
margin-top: 20rpx;
background-color: #fff;
border-radius: 20rpx;
padding-bottom: 0;
}
.wf-item-page{
padding-bottom: 20rpx;
}
</style>

View File

@ -0,0 +1,347 @@
<template>
<view v-if="type == 0" class="wf-item-page wf-page0" :style="viewColor">
<view class='pictrue'>
<easy-loadimage mode="widthFix" :image-src="item.image"></easy-loadimage>
<view v-if="item.stock == 0" class="sell_out">已售罄</view>
<view v-if="item.border_pic" :style="{ backgroundImage: `url(${item.border_pic})` }" class="border-picture"></view>
</view>
<view class="text">
<view class='name line2'>{{item.store_name}}</view>
<view class="acea-row row-middle">
<view class='money'><text class='num'>{{item.price}}</text></view>
</view>
<view v-if="item.show_svip_info && item.show_svip_info.show_svip_price && item.svip_price" class="acea-row row-middle svip">
<text class='vip-money'>{{item.svip_price}}</text>
<view class="vipImg">
<image src="/static/images/svip.png"></image>
</view>
</view>
<view class="item_tags">
<text v-if="item.product_type == 0 && item.merchant.type_name" class="font-bg-red b-color">{{item.merchant.type_name}}</text>
<text v-else-if="item.product_type == 0 && item.merchant.is_trader" class="font-bg-red b-color">自营</text>
<text v-if="item.product_type != 0" :class="'font_bg-red type'+item.product_type">{{item.product_type == 1 ? "秒杀" : item.product_type == 2 ? "预售" : item.product_type == 3 ? "助力" : item.product_type == 4 ? "拼团" : ""}}</text>
<text class="tags_item ticket" v-if="item.issetCoupon">领券</text>
<text class="tags_item delivery" v-if="item.delivery_free == 1">包邮</text>
</view>
</view>
</view>
<view v-else-if="type == 1" class="wf-page1" :style="viewColor">
<view class='pictrue'>
<easy-loadimage mode="widthFix" :image-src="item.image"></easy-loadimage>
<view v-if="item.stock == 0" class="sell_out">已售罄</view>
<view v-if="item.border_pic" :style="{ backgroundImage: `url(${item.border_pic})` }" class="border-picture"></view>
</view>
<view class='text'>
<view class='name line2'>{{item.store_name}}</view>
<view class='money'>
<text class='num'>{{item.price}}</text>
</view>
<view v-if="item.show_svip_info.show_svip && item.show_svip_info.show_svip_price" class="acea-row row-middle svip">
<text class='vip-money'>{{item.svip_price}}</text>
<view class="vipImg">
<image src="/static/images/svip.png"></image>
</view>
</view>
<view class="item_tags acea-row">
<text v-if="item.merchant.type_name && item.product_type == 0" class="font-bg-red b-color">{{item.merchant.type_name}}</text>
<text v-else-if="item.merchant.is_trader && item.product_type == 0" class="font-bg-red b-color">自营</text>
<text v-if="item.product_type != 0" :class="'font_bg-red type'+item.product_type">{{item.product_type == 1 ? "秒杀" : item.product_type == 2 ? "预售" : item.product_type == 3 ? "助力" : item.product_type == 4 ? "拼团" : ""}}</text>
<text class="tags_item ticket" v-if="item.issetCoupon">领券</text>
<text class="tags_item delivery" v-if="item.delivery_free == 1">包邮</text>
</view>
<view class="score">{{item.rate}}评分 {{item.reply_count}}条评论</view>
<view class="company" v-if="item.merchant" @click.stop="goShop(item.merchant.mer_id)">
<text class="line1">{{item.merchant.mer_name}}</text>
<view class="flex" v-if="isStore != '1'">
进店
<text class="iconfont icon-xiangyou"></text>
</view>
</view>
</view>
<!-- 返佣 -->
<block v-if="item.max_extension>0 && (item.product_type == 0 || item.product_type == 2)">
<view class="foot-bar">
<text class="iconfont icon-fenxiang"></text>
最高赚 ¥{{item.max_extension}}
</view>
</block>
</view>
</template>
<script>
import easyLoadimage from '@/components/easy-loadimage/easy-loadimage.vue'
import {mapGetters} from "vuex";
export default {
components:{easyLoadimage},
computed: mapGetters(['viewColor']),
props: {
item: {
type: Object,
require: true
},
type: {
type: Number|String,
default: 0
},
isStore: {
type: [String, Number],
default: '1'
},
isLogin: {
type: Boolean,
require: false
}
},
data(){
return {
}
},
methods: {
goShop(id) {
this.$emit('goShop', id);
},
authOpen(){
this.$emit('authOpen');
},
followToggle(item){
this.$emit('followToggle', item);
}
}
}
</script>
<style lang="scss" scoped>
.wf-item-page {
background: #fff;
overflow: hidden;
border-radius: 16rpx;
padding-bottom: 20rpx;
}
.wf-page0 .coupon{
background:rgba(255,248,247,1);
border:1px solid rgba(233,51,35,1);
border-radius:4rpx;
font-size:20rpx;
margin-left: 18rpx;
padding: 1rpx 4rpx;
}
.wf-page0 .pictrue{
width: 100%!important;
height: 345rpx;
position: relative;
/deep/image,/deep/.easy-loadimage,uni-image{
height: 345rpx;
border-radius: 16rpx 16rpx 0 0;
}
.border-picture {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 16rpx 16rpx 0 0;
background: center/cover no-repeat;
}
}
.loadfail-img{
width: 100%;
height: 360rpx;
}
.svip{
margin: 5rpx 0 15rpx;
}
.vip-money {
color: #282828;
font-size: 22rpx;
margin-left: 6rpx;
font-weight: bold;
}
.vipImg {
width: 65rpx;
height: 28rpx;
margin-left: 4rpx;
image {
width: 100%;
height: 100%;
display: block;
}
}
.wf-page0 .name {
color: #282828;
margin: 20rpx 0 10rpx 0;
font-size: 13px;
overflow:hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
text-align: left;
}
.wf-page0 .text{
padding: 0 20rpx;
}
.wf-page0 .money {
font-size: 20rpx;
font-weight: bold;
color: var(--view-priceColor);
}
.b-color {
background-color: var(--view-theme);
border: 1px solid var(--view-theme);
}
.wf-page0 .money .num {
font-size: 34rpx;
}
.wf-page1 .wf-item{
.name{
font-size: 13px;
overflow:hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
text-align: left;
}
}
.wf-page1 .pictrue {
position: relative;
height: 345rpx;
width: 100%!important;
/deep/image,/deep/.easy-loadimage,uni-image{
height: 345rpx;
border-radius: 20rpx 20rpx 0 0;
}
.border-picture {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 20rpx 20rpx 0 0;
background: center/cover no-repeat;
}
}
.sell_out {
display: flex;
width: 150rpx;
height: 150rpx;
align-items: center;
justify-content: center;
border-radius: 100%;
background: rgba(0,0,0,.6);
color: #fff;
font-size: 30rpx;
position: absolute;
top: 50%;
left: 50%;
margin: -75rpx 0 0 -75rpx;
&::before{
content: "";
display: block;
width: 140rpx;
height: 140rpx;
border-radius: 100%;
border: 1px dashed #fff;
position: absolute;
top: 5rpx;
left: 5rpx;
}
}
.loading-img{
height: 345rpx;
max-height: 360rpx;
}
.wf-page1 .text {
padding: 20rpx 17rpx 26rpx 17rpx;
font-size: 30rpx;
color: #222;
}
.wf-page1 .text .money {
display: flex;
align-items: center;
font-size: 26rpx;
font-weight: bold;
margin-top: 8rpx;
color: var(--view-priceColor);
}
.wf-page1 .text .money .num {
font-size: 34rpx;
}
.item_tags{
margin-top: 8rpx;
display: flex;
}
.item_tags .tags_item {
display: flex;
font-size: 20rpx;
text-align: center;
border-radius: 5rpx;
padding: 0 4rpx;
height: 28rpx;
align-items: center;
justify-content: center;
margin-right: 8rpx;
}
.item_tags .tags_item.ticket{
color: var(--view-theme);
border: 1px solid var(--view-theme);
}
.item_tags .tags_item.delivery{
color: #FF9000;
border: 1px solid #FF9000;
}
.wf-page1 .text .money .ticket-big {
display: flex;
align-items: center;
justify-content: center;
max-width: 163rpx;
padding: 0 6rpx;
height: 28rpx;
margin-left: 10rpx;
background-image: url(~static/images/yh.png);
background-size: 100% 100%;
font-size: 20rpx;
font-weight: normal;
}
.wf-page1 .text .score {
margin-top: 10rpx;
color: #737373;
font-size: 20rpx;
}
.wf-page1 .text .company {
display: flex;
align-items: center;
color: #737373;
font-size: 20rpx;
margin-top: 10rpx;
.line1{
max-width: 200rpx;
}
.flex {
display: flex;
align-items: center;
margin-left: 10rpx;
color: #282828;
.iconfont {
font-size: 16rpx;
margin-top: 4rpx;
}
}
}
.foot-bar {
width: 100%;
height: 52rpx;
display: flex;
align-items: center;
justify-content: center;
background-image: linear-gradient(-90deg, var(--view-bntColor21) 0%, var(--view-bntColor22) 100%);
border-radius: 0px 0px 16rpx 16rpx;
color: #fff;
font-size: 24rpx;
.icon-fenxiang {
font-size: 24rpx;
margin-right: 10rpx;
}
}
</style>

View File

@ -0,0 +1,219 @@
<template>
<view class="wf-item-page" @click="gogogo(item)">
<view class='pictrue'>
<!-- <image :src="item.image[0]" mode="widthFix" class="item-img" /> -->
<image :src="item.image" mode="aspectFill" class="item-img"></image>
<!-- <easy-loadimage mode="widthFix" :image-src="item.image[0]"></easy-loadimage> -->
</view>
<view class="title">{{item.store_name}}</view>
<!-- <view class="tag">
<view class="tag-one">
自营商品
</view>
<view class="tag-two">
<text class="tag-twoa"></text>
<text class="tag-twob">满20包邮</text>
</view>
</view> -->
<view class="relase">
<view class="relase-one">
{{item.rate}}
</view>
<view class="relase-two">
{{item.reply_count}}评论
</view>
</view>
<view class="price">
<span></span>{{item.price.split('.')[0]}}.<text>{{item.price.split('.')[1]}}</text>
</view>
<view class="item-info">
<view class="info-title" style="margin-right: 10rpx;">
{{item.merchant.mer_name}}
</view>
<view class="info-img">
<image src="@/static/images/you.png" mode="aspectFit"></image>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
item: {
type: Object,
require: true
}
},
methods: {
gogogo(item) {
uni.navigateTo({
url: '/pages/goods_details/index?id=' + item.product_id
})
},
}
}
</script>
<style lang="scss" scoped>
.wf-item-page {
background: #fff;
overflow: hidden;
border-radius: 5px;
}
.pictrue {
width: 100% !important;
height: 345rpx;
image {
width: 100%;
height: 345rpx;
}
}
.item-info {}
.title {
font-size: 30rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
margin: 12px 0;
padding-right: 12rpx;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin-left: 21rpx;
}
.tag {
display: flex;
margin-left: 21rpx;
.tag-one {
text-align: center;
padding: 2rpx 9rpx;
border-radius: 11rpx 11rpx 11rpx 11rpx;
border: 1px solid #3274F9;
font-size: 19rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
margin-right: 15rpx;
}
.tag-two {
.tag-twoa {
width: 130rpx;
text-align: center;
padding-left: 15rpx;
padding-right: 7rpx;
border-radius: 11rpx 0px 0px 0rpx;
border: 1px solid #F84221;
font-size: 19rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
}
.tag-twob {
width: 130rpx;
text-align: center;
padding: 2rpx 9rpx;
border-radius: 0px 11rpx 11rpx 0px;
border: 1px solid #F84221;
font-size: 19rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
}
}
}
.relase {
display: flex;
margin-left: 21rpx;
margin-top: 12rpx;
height: 26rpx;
line-height: 26rpx;
.relase-one {
// font-style: italic;
transform: skewX(-15deg);
font-size: 26rpx;
font-family: SF Pro Display-Regular Italic, SF Pro Display;
font-weight: 600;
color: #FF6D20;
}
.relase-two {
font-size: 23rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 500;
color: #B3B3B3;
margin-left: 13rpx;
}
}
.price {
margin-left: 21rpx;
margin-bottom: 10rpx;
color: #F84221;
font-size: 44rpx;
font-weight: 600;
span {
color: #F84221;
font-size: 30rpx;
font-weight: 500;
}
text {
color: #F84221;
font-size: 37rpx;
font-weight: 400;
}
}
.item-info {
margin-left: 21rpx;
margin-bottom: 25rpx;
display: flex;
width: 280rpx;
height: 39rpx;
line-height: 39rpx;
background: #F4F7FE;
border-radius: 19rpx 19rpx;
opacity: 1;
font-size: 23rpx;
padding-left: 11rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #737373;
.info-img {
width: 21rpx;
height: 21rpx;
margin-top: 5rpx;
image {
width: 100%;
height: 100%;
}
}
}
</style>

View File

@ -0,0 +1,121 @@
<template>
<view class="wf-item-page">
<view class='pictrue'>
<!-- <image :src="item.image[0]" mode="widthFix" class="item-img" /> -->
<image :src="item.image[0]" mode="aspectFill" class="item-img"></image>
<!-- <easy-loadimage mode="widthFix" :image-src="item.image[0]"></easy-loadimage> -->
</view>
<view class="goods_item_img" v-if="item.video_link.length>0">
<image src="@/static/images/sp.png" mode="aspectFit"></image>
</view>
<view class="title">{{item.title}}</view>
<view class="item-info">
<image :src="(item.author && item.author.avatar) || '/static/images/f.png'" mode="aspectFit"
class="info-avatar" />
<view class="info-nickname">{{ item.author.nickname }}</view>
</view>
</view>
</template>
<script>
import {
string
} from '../../plugin/clipboard/clipboard'
export default {
props: {
item: {
type: Object,
require: true
},
heightx: {
type: string,
require: true
}
},
data() {
return {
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.wf-item-page {
background: #fff;
overflow: hidden;
border-radius: 5px;
position: relative;
}
.pictrue {
width: 100% !important;
height: 345rpx;
image{
width: 100% ;
height: 345rpx;
}
}
.item-info {
display: flex;
align-items: center;
padding: 5px;
}
.goods_item_img {
position: absolute;
top: 20rpx;
right: 18rpx;
width: 52rpx;
height: 52rpx;
z-index: 1 !important;
image {
width: 100%;
height: 100%;
}
}
.title {
font-size: 30rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
margin: 12px 0;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
padding: 0 5px;
}
.info-avatar {
width: 49rpx;
height: 49rpx;
border-radius: 50%;
margin-right: 5px;
}
.info-nickname {
font-size: 12px;
color: #333;
}
</style>

180
components/adc/index.vue Normal file
View File

@ -0,0 +1,180 @@
<template>
<view>
<view class="address-window" :class="address.address==true?'on':''">
<view class='title'>选择地址<text class='iconfont icon-guanbi' @tap='close'></text></view>
<view class='list'>
<view class='item acea-row row-between-wrapper' :class='active==index?"font-color":""' v-for="(item,index) in addressList"
@tap='tapAddress(index,item.id)' :key='index'>
<text class='iconfont icon-ditu' :class='active==index?"font-color":""'></text>
<view class='address'>
<view class='name' :class='active==index?"font-color":""'>{{item.real_name}}<text class='phone'>{{item.phone}}</text></view>
<view class='line1'>{{item.province}}{{item.city}}{{item.district}}{{item.detail}}</view>
</view>
<text class='iconfont icon-complete' :class='active==index?"font-color":""'></text>
</view>
</view>
<!-- 无地址 -->
<view class='pictrue' v-if="!is_loading && !addressList.length">
<image src='../../static/images/noAddress.png'></image>
</view>
<view class='addressBnt bg-color' @tap='goAddressPages'>选择其地址</view>
</view>
<view class='mask' catchtouchmove="true" :hidden='address.address==false' @tap='close'></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import {
getAddressList
} from '@/api/user.js';
export default {
props: {
pagesUrl: {
type: String,
default: '',
},
address: {
type: Object,
default: function() {
return {
address: true,
addressId: 0,
};
}
},
isLog: {
type: Boolean,
default: false,
},
},
data() {
return {
active: 0,
//
addressList: [],
is_loading: true
};
},
methods: {
tapAddress: function(e, addressid) {
this.active = e;
this.$emit('OnChangeAddress', addressid);
},
close: function() {
this.$emit('changeClose');
this.$emit('changeTextareaStatus');
},
goAddressPages: function() {
this.$emit('changeClose');
this.$emit('changeTextareaStatus');
uni.navigateTo({
url: this.pagesUrl
});
},
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>
<style scoped lang="scss">
.address-window {
background-color: #fff;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 101;
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-window .list .item {
margin-left: 30rpx;
padding-right: 30rpx;
border-bottom: 1px solid #eee;
height: 129rpx;
font-size: 25rpx;
color: #333;
}
.address-window .list .item .iconfont {
font-size: 37rpx;
color: #2c2c2c;
}
.address-window .list .item .iconfont.icon-complete {
font-size: 30rpx;
color: #fff;
}
.address-window .list .item .address {
width: 560rpx;
}
.address-window .list .item .address .name {
font-size: 28rpx;
font-weight: bold;
color: #282828;
margin-bottom: 4rpx;
}
.address-window .list .item .address .name .phone {
margin-left: 18rpx;
}
.address-window .addressBnt {
font-size: 30rpx;
font-weight: bold;
color: #fff;
width: 690rpx;
height: 86rpx;
border-radius: 43rpx;
text-align: center;
line-height: 86rpx;
margin: 85rpx auto;
}
.address-window .pictrue {
width: 414rpx;
height: 336rpx;
margin: 0 auto;
}
.address-window .pictrue image {
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,598 @@
<template>
<view :style="viewColor">
<view class="add_invoicing" :class="invoice.invoice==true?'on':''">
<view class='title'>选择发票<text class='iconfont icon-guanbi' @tap='close'></text></view>
<form @submit="formSubmit" report-submit="true">
<view class="panel">
<view v-if="receipt_title_type == '1'" class="acea-row row-middle">
<view>发票类型</view>
<input name="receipt_type" :value="typeName" disabled="true" />
</view>
<view v-if="receipt_title_type == '2'" class="acea-row row-middle">
<view>发票类型</view>
<input name="receipt_type" :value="typeName" disabled="true" @click="callType" />
<text class="iconfont icon-xiangyou"></text>
</view>
<view class="acea-row row-middle">
<view>抬头类型</view>
<radio-group name="receipt_title_type" @change="changeHeader">
<label>
<radio value="1" :checked="receipt_title_type == '1' ? true : false" /><text>个人</text>
</label>
<label>
<radio value="2" :checked="receipt_title_type == '2' ? true : false" /><text>企业</text>
</label>
</radio-group>
</view>
<view class="acea-row row-middle">
<view>发票抬头</view>
<input v-if="receipt_title_type == 1" name="receipt_title" :value="receipt_title" :maxlength="20" placeholder="需要开具发票的姓名"/>
<input v-else name="receipt_title" :value="receipt_title" :maxlength="20" placeholder="需要开具发票的企业名称"/>
<text class="iconfont icon-xiangyou" @click="callTitle" ></text>
</view>
<view v-show="receipt_title_type == '2'" class="acea-row row-middle">
<view>税号</view>
<input name="duty_paragraph" :value="duty_paragraph" placeholder="纳税人识别号" />
</view>
<view class="acea-row row-middle">
<view>邮箱</view>
<input name="email" :value="email" placeholder="您的联系邮箱" />
</view>
</view>
<view v-show="receipt_title_type == '2' && receipt_type == '2'" class="panel">
<view class="acea-row row-middle">
<view>开户银行</view>
<input name="bank_name" :value="bank_name" placeholder="您的开户银行" />
</view>
<view class="acea-row row-middle">
<view>银行账号</view>
<input name="bank_code" :value="bank_code" placeholder="您的银行账号" />
</view>
<view class="acea-row row-middle">
<view>企业地址</view>
<input name="address" :value="address" placeholder="您所在的企业地址" />
</view>
<view class="acea-row row-middle">
<view>企业电话</view>
<input name="tel" :value="tel" placeholder="您的企业电话" />
</view>
</view>
<view class="btn-wrap">
<button class="button" form-type="submit">提交申请</button>
<button class="back" @tap="noInvoice">不开发票</button>
</view>
</form>
<view :class="{ mask: popupType || popupTitle }"></view>
<view class="popup" :class="{ on: popupType }">
<view class="title">发票类型选择<text class="iconfont icon-guanbi" @click="closeType"></text></view>
<scroll-view scroll-y="true">
<radio-group name="invoice-type" @change="changeType">
<label v-for="item in invoiceTypeList" :key="item.type" class="acea-row row-middle">
<view class="text">
<view>{{ item.name }}</view>
<view class="info">{{ item.info }}</view>
</view>
<radio :value="item.type" :checked="receipt_type == item.type ? true : false" />
</label>
</radio-group>
</scroll-view>
<button @tap="closeType">确定</button>
</view>
<view class="popup" :class="{ on: popupTitle }">
<view class="title">抬头选择<text class="iconfont icon-guanbi" @click="closeTitle"></text></view>
<scroll-view v-if="invoiceList.length > 0" scroll-y="true">
<radio-group name="invoice-title" @change="changeTitle">
<template v-for="item in invoiceList">
<label :key="item.user_receipt_id" class="acea-row row-middle">
<view class="text">
<view class="acea-row row-middle">
<view class="name">{{ item.receipt_title }}</view>
<view v-if="item.is_default" class="label">默认</view>
</view>
<view class="type" :class="{ special: item.receipt_type == '2'}">{{ item.receipt_type == 1 ? '普通发票' : '专用发票'}}</view>
</view>
<radio :value="item.user_receipt_id" :checked="item.user_receipt_id == invoice_id ? true : false" />
</label>
</template>
</radio-group>
</scroll-view>
<view v-else class="nothing">
<image src="../../static/images/noInvoice.png"></image>
<view class="nothing_text">您还没有添加发票信息哟~</view>
</view>
<button v-if="invoice.add" @tap="addTitle">添加新的抬头</button>
<button v-else @tap="close" class="btn-default">不开发票</button>
</view>
</view>
<view class='mask' catchtouchmove="true" :hidden='invoice.invoice==false' @tap='close'></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { invoiceDefault, invoice, invoiceDetail } from '@/api/user.js';
import { mapGetters } from "vuex";
export default {
props: {
invoice: {
type: Object,
default: function() {
return {
invoice: false,
mer_id: 0,
};
}
}
},
computed: { ...mapGetters(['viewColor'])},
data() {
return {
id: '',
receipt_title_type: '1',
receipt_type: '1',
drawer_phone: '',
receipt_title: '',
duty_paragraph: '',
tel: '',
address: '',
bank_name: '',
bank_code: '',
is_default: 0,
email: '',
isDefault: [],
typeName: '增值税电子普通发票',
popupType: false,
popupTitle: false,
invoiceTypeList: [{
type: '1',
name: '增值税电子普通发票',
info: '默认发送至所提供的电子邮件'
},
{
type: '2',
name: '增值税专用发票',
info: '纸质发票开出后将以邮寄形式交付'
}
],
special_invoice: true,
invoice_func: true,
invoiceList: [],
invoice_checked: '',
invoice_id: '',
order_id: '',
news: '',
cartId: '',
pinkId: '',
couponId: '',
addressId: '',
invoiceData: {},
formvalidate: false
}
},
watch: {
},
onLoad(option) {
this.news = option.news;
this.cartId = option.cartId;
this.pinkId = option.pinkId;
this.couponId = option.couponId;
this.addressId = option.addressId;
if (option.special_invoice == 'false') {
this.$set(this, 'special_invoice', false);
}
},
onShow(){
this.getInvoiceDefault();
this.popupTitle = false;
},
methods: {
getInvoiceList() {
let params = {
// receipt_title_type: this.receipt_title_type,
// receipt_type: this.receipt_type
}
invoice().then(res => {
for (let i = 0; i < res.data.length; i++) {
res.data[i].user_receipt_id = res.data[i].user_receipt_id.toString();
if (res.data[i].is_default) {
this.invoice_id = res.data[i].user_receipt_id;
}
}
this.$set(this, 'invoiceList', res.data);
}).catch(err => {
this.$util.Tips({
title: err
});
});
},
getInvoiceDefault() {
let params = {
is_default: 1,
// receipt_title_type: this.receipt_title_type,
// receipt_type: this.receipt_type
}
invoice(params).then(res => {
let data = res.data[0];
this.typeName = data.receipt_type == '1' ? '增值税电子普通发票' : '增值税专用发票'
this.receipt_title_type = data.receipt_title_type;
this.receipt_type = data.receipt_type ;
this.receipt_title = data.receipt_title;
// this.drawer_phone = res.data.drawer_phone;
this.email = data.email;
this.duty_paragraph = data.duty_paragraph;
this.bank_name = data.bank_name;
this.bank_code = data.bank_code;
this.address = data.address;
this.tel = data.tel;
this.invoice_id = data.user_receipt_id.toString();
}).catch(err => {});
},
getInvoiceDetail(id){
invoiceDetail(id).then(res => {
uni.hideLoading();
this.receipt_title_type = res.data.receipt_title_type;
this.receipt_type = res.data.receipt_type;
this.typeName = this.receipt_type == '1' ? '增值税电子普通发票' : '增值税专用发票'
this.receipt_title = res.data.receipt_title;
this.email = res.data.email;
this.duty_paragraph = res.data.duty_paragraph;
this.bank_name = res.data.bank_name;
this.bank_code = res.data.bank_code;
this.address = res.data.address;
this.tel = res.data.tel;
this.is_default = res.data.is_default;
}).catch(err => {
uni.hideLoading();
this.$util.Tips({
title: err
});
});
},
close: function() {
if(this.formvalidate){
this.$emit('changeInvoiceClose',this.invoiceData)
}else{
this.$emit('changeInvoiceClose','');
}
},
noInvoice: function(){
uni.setStorage({
key:'invoice_Data',
data:{},
success: function(){}
})
this.$emit('changeInvoiceClose','');
},
callType() {
this.popupType = true;
},
changeType(e) {
this.receipt_type = e.detail.value;
this.typeName = this.invoiceTypeList.find(value => {
return value.type == this.receipt_type;
}).name;
},
closeType() {
this.popupType = false;
},
callTitle() {
this.popupTitle = true;
},
changeTitle(e) {
this.invoice_id = e.detail.value.toString();
this.getInvoiceDetail(e.detail.value)
this.popupTitle = false;
},
addTitle() {
this.popupType = false;
this.popupTitle = false;
uni.navigateTo({
url: '/pages/users/user_invoice_form/index?mer_id='+this.invoice.mer_id
});
},
closeTitle() {
this.popupTitle = false;
},
changeHeader(e) {
this.receipt_title_type = e.detail.value;
if(e.detail.value == 1){
this.receipt_type = 1;
this.typeName = '增值税电子普通发票'
}
this.receipt_type
},
changeDefault(e) {
this.is_default = e.detail.value.length ? 1 : 0;
},
//
formSubmit(e) {
let that = this,
value = e.detail.value;
if (!value.receipt_title_type) return that.$util.Tips({
title: '请填写发票抬头'
});
if (!value.email) return that.$util.Tips({
title: '请填写邮箱'
});
if (!/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(value.email)) return that.$util.Tips({
title: '请输入正确的邮箱'
});
if(value.receipt_title_type == 2){
if (!value.duty_paragraph) return that.$util.Tips({
title: '请填写税号'
});
if(value.receipt_type == '增值税专用发票'){
if (!value.bank_name) return that.$util.Tips({
title: '请填写开户行'
});
if (!value.bank_code) return that.$util.Tips({
title: '请填写银行账号'
});
if (!value.address) return that.$util.Tips({
title: '请填写企业地址'
});
if (!value.tel) return that.$util.Tips({
title: '请填写企业电话'
});
if(!/^(\d{9}|\d{14}|\d{18})$/.test(value.bank_code)){
return this.$util.Tips({
title: '请输入正确的银行账号'
});
}
if(!/(^(\d{3,4})?\d{7,8})$|(13[0-9]{9})/.test(value.tel)){
return this.$util.Tips({
title: '请输入正确的电话号码'
});
}
}
}
that.formvalidate = true;
value.mer_id = that.invoice.mer_id;
value.receipt_type = that.receipt_type;
that.invoiceData = value
uni.setStorage({
key:'invoice_Data',
data: [that.invoiceData],
success: function(){
}
})
that.$emit('changeInvoiceClose',that.invoiceData)
}
}
}
</script>
<style lang="scss" scoped>
.add_invoicing{
position: fixed;
bottom: 0;
width: 100%;
left: 0;
background-color: #fff;
z-index: 77;
border-radius: 16rpx 16rpx 0 0;
padding-bottom: 20rpx;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
}
.add_invoicing.on {
transform: translate3d(0, 0, 0);
}
.add_invoicing .title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
height: 123rpx;
line-height: 123rpx;
position: relative;
}
.add_invoicing .title .iconfont {
position: absolute;
right: 30rpx;
color: #8a8a8a;
font-size: 35rpx;
}
form {
font-size: 28rpx;
color: #282828;
}
form input, form radio-group {
flex: 1;
text-align: right;
}
form input {
font-size: 26rpx;
}
form label {
margin-right: 50rpx;
}
form radio {
margin-right: 8rpx;
}
form checkbox-group {
height: 90rpx;
}
form checkbox {
margin-right: 20rpx;
}
/deep/radio .uni-radio-input.uni-radio-input-checked {
border: 1px solid var(--view-theme) !important;
background-color: var(--view-theme) !important
}
form button {
height: 76rpx;
border-radius: 38rpx;
margin: 16rpx 30rpx;
background-color: var(--view-theme);
font-size: 30rpx;
line-height: 76rpx;
color: #FFFFFF;
}
.panel {
padding-right: 30rpx;
padding-left: 30rpx;
background-color: #FFFFFF;
}
.panel~.panel {
margin-top: 14rpx;
}
.panel .acea-row {
height: 90rpx;
}
.panel .acea-row~.acea-row {
border-top: 1px solid #EEEEEE;
}
.input-placeholder {
font-size: 26rpx;
color: #BBBBBB;
}
.icon-xiangyou {
margin-left: 25rpx;
font-size: 18rpx;
color: #BFBFBF;
}
.btn-wrap {
width: 100%;
border-top: 1px solid #F5F5F5;
}
.btn-wrap .button{
height: 86rpx;
line-height: 86rpx;
border-radius: 50rpx;
}
.btn-wrap .back {
border-radius: 50rpx;
height: 86rpx;
line-height: 86rpx;
border: 1rpx solid var(--view-theme);
background: none;
color: var(--view-theme);
}
.popup {
position: fixed;
bottom: 0;
left: 0;
z-index: 99;
width: 100%;
padding-bottom: 100rpx;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
background-color: #F5F5F5;
overflow: hidden;
transform: translateY(100%);
transition: 0.3s;
}
.popup.on {
transform: translateY(0);
}
.popup .title {
position: relative;
height: 137rpx;
font-size: 32rpx;
line-height: 137rpx;
text-align: center;
}
.popup scroll-view {
height: 466rpx;
padding-right: 30rpx;
padding-left: 30rpx;
box-sizing: border-box;
}
.popup label {
padding: 35rpx 30rpx;
border-radius: 16rpx;
margin-bottom: 20rpx;
background-color: #FFFFFF;
}
.popup .text {
flex: 1;
min-width: 0;
font-size: 28rpx;
color: #282828;
}
.popup .info {
margin-top: 10rpx;
font-size: 22rpx;
color: #909090;
}
.popup .icon-guanbi {
position: absolute;
top: 50%;
right: 30rpx;
z-index: 2;
transform: translateY(-50%);
font-size: 30rpx;
color: #707070;
cursor: pointer;
}
.popup button {
height: 86rpx;
border-radius: 43rpx;
margin-right: 30rpx;
margin-left: 30rpx;
background-color: var(--view-theme);
font-size: 30rpx;
line-height: 86rpx;
color: #FFFFFF;
}
button.btn-default{
background-color: transparent;
color: var(--view-theme);
border: 1px solid var(--view-theme);
}
.popup .text .acea-row {
display: inline-flex;
max-width: 100%;
}
.popup .name {
flex: 1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 30rpx;
}
.popup .label {
width: 70rpx;
height: 28rpx;
border: 1px solid #E93323;
margin-left: 18rpx;
font-size: 16rpx;
line-height: 26rpx;
text-align: center;
color: #E93323;
}
.popup .type {
width: 124rpx;
height: 42rpx;
margin-top: 14rpx;
background-color: #FCF0E0;
font-size: 24rpx;
line-height: 42rpx;
text-align: center;
color: #D67300;
}
.popup .type.special {
background-color: #FDE9E7;
color: #E93323;
}
.nothing {
margin: 50rpx 0;
text-align: center;
image, uni-image{
width: 400rpx;
height: 260rpx;
}
}
.nothing_text{
margin-top: 20rpx;
color: #999999;
}
</style>

View File

@ -0,0 +1,342 @@
<template>
<view :style="viewColor">
<view class="product-window" :class="(attr.cartAttr === true ? 'on' : '') + ' ' + (iSbnt || destri?'join':'') + ' ' + (isPresell ?'presell-window':'product-window')">
<view class="textpic acea-row row-between-wrapper">
<view class="pictrue">
<image :src="(attr.productSelect&&attr.productSelect.image) ? attr.productSelect.image : ''" @click="loookImg"></image>
</view>
<view class="text">
<view class="line1">
{{ attr.productSelect.store_name }}
</view>
<view v-if="isPresell" class="money presell_price">
<view>
预售价
<text class="num">{{ attr.productSelect.price }}</text>
<text v-if="presell_type === 2">定金¥<text class="num">{{ attr.productSelect.down_price }}</text></text>
</view>
<text class="stock" v-if='isShow'>库存: {{ attr.productSelect.stock }}</text>
<text class='stock' v-if="limitNum">限量: {{attr.productSelect.quota_show}}</text>
</view>
<view v-else class="money">
<view class="acea-row row-middle">
<view class="acea-row row-middle">
<text></text><text class="num">{{ attr.productSelect.price }}</text>
<view v-if="attr.productSelect && attr.productSelect.svip_price" class="acea-row row-middle">
<text class='vip-money'>{{attr.productSelect.svip_price}}</text>
<view class="vipImg">
<image src="/static/images/svip.png"></image>
</view>
</view>
</view>
</view>
<view class="stock_count">
<text class="stock" v-if='isShow'>库存: {{ attr.productSelect.stock }}</text>
<text class='stock' v-if="limitNum">限量: {{attr.productSelect.quota_show}}</text>
</view>
</view>
</view>
<view class="iconfont icon-guanbi" @click="closeAttr"></view>
</view>
<view class="productWinList">
<view class="item" v-for="(item, indexw) in attr.productAttr" :key="indexw">
<view class="title">{{ item.attr_name }}</view>
<view class="listn acea-row row-middle">
<view class="itemn" :class="item.index === itemn.attr ? 'on' : ''" v-for="(itemn, indexn) in item.attr_value"
@click="tapAttr(indexw, indexn)" :key="indexn">
{{ itemn.attr }}
</view>
</view>
</view>
</view>
<view class="joinBnt b-color" v-if="destri && attr.productSelect.stock>0" @click="goCat">确定</view>
<view class="joinBnt on" v-else-if="destri && attr.productSelect.stock<=0">已售罄</view>
<view class="joinBnt on" v-else-if="(iSbnt && attr.productSelect.stock<=0)">已售罄</view>
</view>
<view class="mask" @touchmove.prevent :hidden="attr.cartAttr === false" @click="closeAttr"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { mapGetters } from "vuex";
export default {
computed: mapGetters(['viewColor']),
props: {
attr: {
type: Object,
default: () => {}
},
limitNum: {
type: Number,
value: 0
},
isShow: {
type: Number,
value: 0
},
iSbnt: {
type: Number,
value: 0
},
iSplus: {
type: Number,
value: 0
},
destri: {
type: Number,
value: 0
},
isPresell: {
type: Number,
value: 0
},
presell_type: {
type: Number,
value: 1
},
image: {
type: String,
value: ''
}
},
data() {
return {};
},
mounted(){
},
methods: {
//
loookImg(){
let self = this
let arr = [self.attr.productSelect.image ? self.attr.productSelect.image : self.image]
uni.previewImage({
urls: arr,
});
},
goCat: function() {
this.$emit('goCat');
},
closeAttr: function() {
this.$emit('myevent');
},
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);
},
//
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;
}
}
}
</script>
<style scoped lang="scss">
.product-window {
position: fixed;
bottom: 0;
width: 100%;
left: 0;
background-color: #fff;
z-index: 10000;
border-radius: 16rpx 16rpx 0 0;
padding-bottom: 140rpx;
padding-bottom: calc(140rpx+ constant(safe-area-inset-bottom)); /// IOS<11.2/
padding-bottom: calc(140rpx + env(safe-area-inset-bottom)); /// IOS>11.2/
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
&.presell-window {
padding-bottom: 200rpx;
}
}
.product-window.on {
transform: translate3d(0, 0, 0);
}
.product-window.join {
padding-bottom: 30rpx;
}
.product-window .textpic {
padding: 0 80rpx 0 30rpx;
margin-top: 29rpx;
position: relative;
}
.product-window .textpic .pictrue {
width: 150rpx;
height: 150rpx;
}
.product-window .textpic .pictrue image {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.product-window .textpic .text {
width: 460rpx;
font-size: 32rpx;
color: #202020;
}
.product-window .textpic .text .money {
font-size: 24rpx;
margin-top: 40rpx;
color: var(--view-priceColor);
}
.product-window .textpic .text .money .num {
font-size: 36rpx;
}
.product-window .textpic .text .money .stock {
color: #999;
margin-left: 18rpx;
}
.vip-money {
color: #282828;
font-size: 22rpx;
margin-left: 6rpx;
}
.vipImg {
width: 65rpx;
height: 28rpx;
margin-left: 4rpx;
image {
width: 100%;
height: 100%;
display: block;
}
}
.product-window .textpic .text .presell_price {
color: #FF7F00;
.num {
display: inline-block;
margin-right: 20rpx;
}
.stock {
margin-left: 0;
}
}
.product-window .textpic .iconfont {
position: absolute;
right: 30rpx;
top: -5rpx;
font-size: 35rpx;
color: #8a8a8a;
}
.product-window .productWinList {
max-height: 395rpx;
overflow: auto;
margin-top: 36rpx;
}
.product-window .productWinList .item~.item {
margin-top: 36rpx;
}
.product-window .productWinList .item .title {
font-size: 30rpx;
color: #999;
padding: 0 30rpx;
}
.product-window .productWinList .item .listn {
padding: 0 30rpx 0 16rpx;
}
.product-window .productWinList .item .listn .itemn {
border: 1px solid #bbb;
font-size: 26rpx;
color: #282828;
padding: 7rpx 33rpx;
border-radius: 6rpx;
margin: 14rpx 0 0 14rpx;
}
.product-window .productWinList .item .listn .itemn.on {
color: #fff;
background-color: var(--view-theme);
border-color: var(--view-theme);
}
.product-window .cart {
margin-top: 36rpx;
padding: 0 30rpx;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.product-window .cart .title {
font-size: 30rpx;
color: #999;
line-height: 54rpx;
}
.product-window .cart .carnum {
height: 54rpx;
}
.product-window .cart .carnum view {
border: 1px solid #a4a4a4;
width: 84rpx;
text-align: center;
height: 100%;
line-height: 54rpx;
color: #a4a4a4;
font-size: 45rpx;
}
.product-window .cart .carnum .reduce {
border-right: 0;
border-radius: 6rpx 0 0 6rpx;
line-height: 48rpx;
}
.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 {
color: #282828;
font-size: 28rpx;
}
.product-window .joinBnt {
font-size: 30rpx;
width: 620rpx;
height: 86rpx;
border-radius: 50rpx;
text-align: center;
line-height: 86rpx;
color: #fff;
margin: 100rpx auto 0 auto;
&.b-color{
background-color: var(--view-theme);
}
}
.product-window .joinBnt.on {
background-color: #bbb;
color: #fff;
}
</style>

View File

@ -0,0 +1,188 @@
<template>
<view :style="viewColor">
<view class="address-window" :class="address.address==true?'on':''">
<view class='title'>选择地址<text class='iconfont icon-guanbi' @tap='close'></text></view>
<scroll-view scroll-y="true" class='list'>
<view class='item acea-row row-between-wrapper' :class='active==index?"t-color":""' v-for="(item,index) in addressList"
@tap='tapAddress(index,item.address_id)' :key='index'>
<text class='iconfont icon-ditu' :class='active==index?"t-color":""'></text>
<view class='address'>
<view class='name' :class='active==index?"t-color":""'>{{item.real_name}}<text class='phone'>{{item.phone}}</text></view>
<view class='line1'>{{item.province}}{{item.city}}{{item.district}}{{item.street || ''}}{{item.brigade}}{{item.detail}}</view>
</view>
<text class='iconfont icon-complete' :class='active==index?"t-color":""'></text>
</view>
</scroll-view>
<!-- 无地址 -->
<view class='pictrue' v-if="!is_loading && !addressList.length">
<image src='../../static/images/noAddress.png'></image>
<view>暂无地址</view>
</view>
<view class='addressBnt' @tap='goAddressPages'>添加新地址</view>
</view>
<view class='mask' catchtouchmove="true" :hidden='address.address==false' @tap='close'></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { getAddressList } from '@/api/user.js';
import { mapGetters } from "vuex";
export default {
props: {
pagesUrl: {
type: String,
default: '',
},
address: {
type: Object,
default: function() {
return {
address: true,
addressId: 0,
};
}
},
isLog: {
type: Boolean,
default: false,
},
},
computed: mapGetters(['viewColor']),
data() {
return {
active: 0,
//
addressList: [],
is_loading: true
};
},
methods: {
tapAddress: function(e, addressid) {
this.active = e;
this.$emit('OnChangeAddress', addressid);
},
close: function() {
this.$emit('changeClose');
this.$emit('changeTextareaStatus');
},
goAddressPages: function() {
this.$emit('changeClose');
this.$emit('changeTextareaStatus');
uni.navigateTo({
url: this.pagesUrl
});
},
getAddressList: function() {
let that = this;
getAddressList({
page: 1,
limit: 5
}).then(res => {
let addressList = res.data.list;
//
for (let i = 0; i < res.data.list.length; i++) {
if (addressList[i].address_id == that.address.addressId) {
that.active = i;
}
}
that.$set(that, 'addressList', addressList);
that.is_loading = false;
})
}
}
}
</script>
<style scoped lang="scss">
.address-window {
background-color: #fff;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 101;
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-window .list{
max-height: 650rpx;
}
.address-window .list .item {
margin-left: 30rpx;
padding-right: 30rpx;
border-bottom: 1px solid #eee;
height: 129rpx;
font-size: 25rpx;
color: #333;
}
.address-window .list .item .iconfont {
font-size: 37rpx;
color: #2c2c2c;
}
.address-window .list .item .iconfont.icon-complete {
font-size: 30rpx;
color: #fff;
}
.address-window .list .item .address {
width: 560rpx;
}
.address-window .list .item .address .name {
font-size: 28rpx;
font-weight: bold;
color: #282828;
margin-bottom: 4rpx;
}
.address-window .list .item .address .name .phone {
margin-left: 18rpx;
}
.address-window .addressBnt {
font-size: 30rpx;
font-weight: bold;
color: #fff;
width: 690rpx;
height: 86rpx;
border-radius: 43rpx;
text-align: center;
line-height: 86rpx;
margin: 85rpx auto;
background-color: var(--view-theme);
}
.address-window .pictrue {
text-align: center;
}
.address-window .pictrue image,.address-window .pictrue uni-image {
width: 414rpx;
height: 305rpx;
}
.address-window .pictrue view{
color: #999;
}
.t-color {
color: var(--view-theme)!important;
}
</style>

View File

@ -0,0 +1,85 @@
<template>
<view class="alert-wrapper" :style="viewColor">
<view class="alert-box">
<image :src="domain+'/static/diy/success'+keyColor+'.png'" mode=""></image>
<view class="txt">{{msg}}</view>
<view class="btn" @click="close">鎴戠煡閬撲簡</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { mapGetters } from "vuex";
import { HTTP_REQUEST_URL } from '@/config/app';
export default{
data() {
return {
domain: HTTP_REQUEST_URL,
}
},
props:{
msg:{
type:String,
default:''
},
},
computed: mapGetters(['viewColor','keyColor']),
methods:{
close(){
this.$emit('bindClose');
}
}
}
</script>
<style lang="scss">
.alert-wrapper{
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,.5);
z-index: 10;
.alert-box{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 500rpx;
height: 540rpx;
background-color: #fff;
border-radius: 10rpx;
font-size: 34rpx;
image{
width: 149rpx;
height: 230rpx;
}
.txt{
margin-bottom: 20rpx;
}
.btn{
width:340rpx;
height:90rpx;
line-height: 90rpx;
text-align: center;
background-image:linear-gradient(-90deg,var(--view-bntColor21) 0%,var(--view-bntColor22) 100%);
border-radius:45rpx;
color: #fff;
}
}
}
</style>

View File

@ -0,0 +1,340 @@
<template>
<view :style="viewColor">
<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.parent_id, index)">
{{item.name}}
<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.name}}</text>
<text v-if="item.id === activeId" class="iconfont icon-duihao2"></text>
</view>
</scroll-view>
</view>
</view>
<view class='mask' 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 CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import {getAddressList} from '@/api/user.js';
import { getCityV2,village } from '@/api/api.js';
import { mapGetters } from "vuex";
const CACHE_ADDRESS = {};
export default {
props: {
display: {
type: Boolean,
default: true
},
address: Array,
},
data() {
return {
active: 0,
//
addressList: [],
selectedArr: [],
selectedIndex: -1,
is_loading: false,
old: { scrollTop: 0 },
scrollTop: 0
};
},
computed:{
...mapGetters(['viewColor']),
activeId(){
return this.selectedIndex == -1 ? 0 : this.selectedArr[this.selectedIndex].id
},
showMore(){
return this.selectedArr.length ? this.selectedArr[this.selectedArr.length - 1].snum > 0 : 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){
if(this.selectedIndex == index) return;
if(pid === -1){
pid = this.selectedArr.length ? this.selectedArr[this.selectedArr.length -1].id : 0;
}
console.log(index)
this.selectedIndex = index;
this.loadAddress(pid);
},
loadAddress(pid,type){
if(CACHE_ADDRESS[pid]){
this.addressList = CACHE_ADDRESS[pid];
return ;
}
this.is_loading = true;
// getCityV2(pid).then(res=>{
// this.is_loading = false;
// CACHE_ADDRESS[pid] = res.data;
// this.addressList = res.data;
// })
if(type=='province'){
village({province_code:pid}).then(res=>{
this.is_loading = false;
CACHE_ADDRESS[pid] = res.data;
this.addressList = res.data;
})
}else if(type=='city'){
village({city_code:pid}).then(res=>{
this.is_loading = false;
CACHE_ADDRESS[pid] = res.data;
this.addressList = res.data;
})
}else if(type=='area'){
village({area_code:pid}).then(res=>{
if(res.data.length>0){
this.is_loading = false;
CACHE_ADDRESS[pid] = res.data;
this.addressList = res.data;
}else{
this.$emit('submit', [...this.selectedArr]);
this.$emit('changeClose');
}
})
}else if(type=='street'){
village({street_code:pid}).then(res=>{
if(res.data.length>0){
this.is_loading = false;
CACHE_ADDRESS[pid] = res.data;
this.addressList = res.data;
}else{
this.$emit('submit', [...this.selectedArr]);
this.$emit('changeClose');
}
})
}else{
village().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.parent_id){
// this.selectedArr = [item];
// }else{
// this.selectedArr.push(item);
// }
else if(!item.id){
this.selectedArr = [item];
}else{
if(this.selectedArr.length>4){
let arry=[]
arry.push(item)
this.selectedArr=arry
}else{
this.selectedArr.push(item);
}
}
if(item.type=="province"){
this.loadAddress(item.code,"province");
}else if(item.type=="city"){
this.loadAddress(item.code,"city");
}else if(item.type=="area"){
this.loadAddress(item.code,"area");
}else if(item.type=="street"){
this.loadAddress(item.code,"street");
} else {
this.$emit('submit', [...this.selectedArr]);
this.$emit('changeClose');
}
// if(item.snum){
// 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: #e28d54;
}
&: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: #e28d54;
.iconfont{
color: #e28d54;
}
}
}
}
}
</style>

495
components/associated.vue Normal file
View File

@ -0,0 +1,495 @@
<template>
<view class="containers" :style="viewColor">
<view class="header">
<view class="title">
<text :class="isActive == 0 ? 'on' : ''" @click="tabs(0)">已购</text>
<text :class="isActive == 1 ? 'on' : ''" @click="tabs(1)">收藏</text>
<text :class="isActive == 2 ? 'on' : ''" @click="tabs(2)">浏览</text>
</view>
<view class="search">
<text class="iconfont icon-xiazai5"></text>
<input type="text" placeholder="请输入商品名称" v-model="searchVal" @input="setValue" confirm-type="search"
@confirm="searchBut()" placeholder-class='placeholder'>
</view>
<view class="sub_title">{{isActive == 0 ? '已购宝贝' : isActive == 1 ?'收藏宝贝' : '浏览记录'}}</view>
<text class="iconfont icon-guanbi5" @click="close"></text>
</view>
<view class="main">
<scroll-view scroll-y="true">
<block v-if="isActive == 0">
<view v-if="bought.length" @touchmove="onTouchmove" id="goods">
<view class="picTxt acea-row" v-for="(item, index) in bought" :key="index">
<view class="checkbox">
<text @click.stop="goodsCheck(item,index)" v-if="item.check" class="iconfont icon-xuanzhong1"></text>
<text @click.stop="goodsCheck(item,index)" v-else :class="checkedArr.length >=5 ? 'disabled': ''"
class="iconfont icon-weixuanzhong"></text>
</view>
<view class='pictrue'>
<image :src='item.image'></image>
</view>
<view class='text'>
<view class='line2 name'>{{item.store_name}}</view>
<view class='money'><text>{{item.price}}</text></view>
</view>
</view>
</view>
<view v-else class="empty">
<image src="/static/images/no_thing.png"></image>
<text>暂无内容哦~</text>
</view>
</block>
<block v-if="isActive == 1">
<view v-if="collect.length" id="collect" @touchmove="onTouchmove1">
<view class="picTxt acea-row" v-for="(item, index) in collect" :key="index">
<view class="checkbox">
<text @click.stop="goodsCheck(item,index)" v-if="item.check" class="iconfont icon-xuanzhong1"></text>
<text @click.stop="goodsCheck(item,index)" v-else :class="checkedArr.length >=5 ? 'disabled': ''"
class="iconfont icon-weixuanzhong"></text>
</view>
<view class='pictrue'>
<image :src='item.image'></image>
</view>
<view class='text'>
<view class='line2 name'>{{item.store_name}}</view>
<view class='money'><text>{{item.price}}</text></view>
</view>
</view>
</view>
<view v-else class="empty">
<image src="/static/images/no_thing.png"></image>
<text>暂无内容哦~</text>
</view>
</block>
<block v-if="isActive == 2">
<view v-if="browse.length" id="browse" @touchmove="onTouchmove2">
<view class="picTxt acea-row" v-for="(item, index) in browse" :key="index">
<view class="checkbox">
<text @click.stop="goodsCheck(item,index)" v-if="item.check" class="iconfont icon-xuanzhong1"></text>
<text @click.stop="goodsCheck(item,index)" v-else :class="checkedArr.length >=5 ? 'disabled': ''"
class="iconfont icon-weixuanzhong"></text>
</view>
<view class='pictrue'>
<image :src='item.image'></image>
</view>
<view class='text'>
<view class='line2 name'>{{item.store_name}}</view>
<view class='money'><text>{{item.price}}</text></view>
</view>
</view>
</view>
<view v-else class="empty">
<image src="/static/images/no_thing.png"></image>
<text>暂无内容哦~</text>
</view>
</block>
</scroll-view>
<view class="foot_bar">
<button class="confirm_btn" @click="submit">确定({{checkedArr.length}})</button>
</view>
</view>
</view>
</template>
<script>
import Loading from '@/components/Loading/index.vue';
import { boughtLstApi, collectLstApi, browseLstApi } from "@/api/community";
import { mapGetters } from "vuex";
export default {
props: {
checkedObj: {
type: Array,
default: []
}
},
computed: mapGetters(['viewColor']),
components: { Loading },
data() {
return {
isActive: 0,
loadedb: false,
loadingb: false,
loadedc: false,
loadingc: false,
loadeds: false,
loadings: false,
whereb: {
page: 1,
limit: 10,
keyword: '',
},
wherec: {
page: 1,
limit: 10,
keyword: '',
},
wheres: {
page: 1,
limit: 10,
keyword: '',
},
searchVal: "",
checked: [],
list: [],
collect: [],
bought: [],
browse: [],
checkedArr: [],
};
},
watch: {
checkedObj: {
handler(n) {
// this.checkedArr = n
},
deep: true
}
},
mounted() {
this.checkedArr = this.checkedObj
this.getBounht();
this.getCollect();
this.getBrowse();
},
methods: {
//
close() {
this.$emit('close');
},
tabs(index) {
this.isActive = index
this.$set(this.whereb, 'keyword', '');
this.$set(this.wherec, 'keyword', '');
this.$set(this.wheres, 'keyword', '');
this.searchVal = ''
this.searchBut()
},
onTouchmove(e) {
if (this.loadendb) return;
if (this.loadingb) return;
const query = uni.createSelectorQuery().in(this);
query.select('#goods').boundingClientRect(data => {
if (data.bottom < 1500 && data.top < 0) {
this.getBounht();
}
}).exec();
//
},
onTouchmove1(e) {
if (this.loadendc) return;
if (this.loadingc) return;
const query = uni.createSelectorQuery().in(this);
query.select('#collect').boundingClientRect(data => {
if (data.bottom < 1500 && data.top < 0) {
this.getCollect();
}
}).exec();
//
},
onTouchmove2(e) {
if (this.loadends) return;
if (this.loadings) return;
const query = uni.createSelectorQuery().in(this);
query.select('#browse').boundingClientRect(data => {
if (data.bottom < 1500 && data.top < 0) {
this.getBrowse();
}
}).exec();
//
},
setValue: function(event) {
this.$set(this.whereb, 'keyword', event.detail.value);
this.$set(this.wherec, 'keyword', event.detail.value);
this.$set(this.wheres, 'keyword', event.detail.value);
},
searchBut() {
this.loadingb = this.loadingc = this.loadings = this.loadedb = this.loadedc = this.loadeds = false
this.whereb.page = this.wherec.page = this.wheres.page = 1
this.bought = this.collect = this.browse = []
this.isActive == 0 ? this.getBounht() : this.isActive == 1 ? this.getCollect() : this.getBrowse()
},
getBounht() {
var that = this;
if (that.loadingb || that.loadedb) return;
that.loadingb = true;
boughtLstApi(that.whereb).then(
res => {
that.loadingb = false;
that.loadedb = res.data.list.length < that.whereb.limit;
that.bought.push.apply(that.bought, res.data.list);
that.whereb.page = that.whereb.page + 1;
that.getInitchecked(that.bought);
},
error => {
that.$util.Tips({
title: error.msg
})
}
);
},
getCollect() {
var that = this;
if (that.loadingc || that.loadedc) return;
that.loadingc = true;
collectLstApi(that.wherec).then(
res => {
that.loadingc = false;
that.loadedc = res.data.list.length < that.wherec.limit;
that.collect.push.apply(that.collect, res.data.list);
that.wherec.page = that.wherec.page + 1;
that.getInitchecked(that.collect);
},
error => {
that.$util.Tips({
title: error.msg
})
}
);
},
getBrowse() {
var that = this;
if (that.loadings || that.loadeds) return;
that.loadings = true;
browseLstApi(that.wheres).then(
res => {
that.loadings = false;
that.loadeds = res.data.list.length < that.wheres.limit;
that.browse.push.apply(that.browse, res.data.list);
that.wheres.page = that.wheres.page + 1;
that.getInitchecked(that.browse);
},
error => {
that.$util.Tips({
title: error.msg
})
}
);
},
/*获取初始化选中的数据*/
getInitchecked(arr) {
let that = this;
arr.forEach((item, index) => {
that.$set(item, 'check', false);
that.checkedArr.forEach((val, i) => {
if ((item.spu_id == (val.spu && val.spu.spu_id)) || (item.spu_id == val.spu_id)) {
that.$set(item, 'check', true);
}
})
})
},
/*已选中的商品打钩*/
getCheckedGoods() {
this.checked = []
this.checkedArr.forEach((item, index) => {
this.check.push(item)
})
},
/*点击选中与否*/
goodsCheck(item, index) {
this.$set(item, 'check', !item.check);
if (item.check) {
this.checkedArr.push(item)
} else {
this.checkedArr.splice(this.checkedArr.findIndex(itemn => ((itemn.spu_id == item.spu_id) || (item.spu_id == (
itemn.spu && itemn.spu.spu_id)))), 1)
}
},
/*确定提交*/
submit() {
this.$emit('getProduct', this.checkedArr);
},
}
}
</script>
<style lang="scss" scoped>
.containers {
background: #ffffff;
border-radius: 16rpx 16rpx 0 0;
padding: 40rpx 0;
position: relative;
.header {
position: relative;
padding: 0 30rpx;
.title {
width: 100%;
text-align: center;
text {
position: relative;
margin: 0 50rpx;
color: #999999;
font-size: 30rpx;
&.on {
color: #333333;
font-weight: bold;
font-size: 34rpx;
&::after {
content: "";
display: inline-block;
width: 40rpx;
height: 5rpx;
background: var(--view-theme);
position: absolute;
bottom: -10rpx;
left: 10rpx;
}
}
}
}
.search {
margin-top: 44rpx;
background: #F5F5F5;
border-radius: 30rpx;
padding: 12rpx 30rpx 12rpx 66rpx;
position: relative;
.iconfont {
font-size: 24rpx;
color: #939393;
position: absolute;
top: 20rpx;
left: 30rpx;
}
.placeholder {
color: #999999;
font-size: 26rpx;
}
}
.sub_title {
color: #282828;
font-size: 26rpx;
margin-top: 30rpx;
}
.iconfont {
color: #8A8A8A;
font-size: 28rpx;
position: absolute;
top: 0;
right: 30rpx;
}
}
scroll-view {
height: 650rpx;
}
.main {
height: 650rpx;
margin: 40rpx 0 80rpx;
padding: 0 30rpx;
}
}
.picTxt {
width: 100%;
padding: 25rpx 0;
position: relative;
align-items: center;
justify-content: space-between;
margin-bottom: 10rpx;
.checkbox {
margin-right: 30rpx;
.iconfont {
font-size: 38rpx;
color: #CCCCCC;
}
.icon-xuanzhong1 {
color: var(--view-theme);
}
.disabled {
pointer-events: none;
cursor: default;
opacity: 0.3;
}
}
.pictrue {
width: 160rpx;
height: 160rpx;
image {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
}
.text {
width: 430rpx;
margin-left: 30rpx;
font-size: 28rpx;
color: #282828;
position: relative;
height: 160rpx;
.name {
color: #282828;
font-size: 28rpx;
}
.money {
position: absolute;
bottom: 0;
left: 0;
color: var(--view-priceColor);
font-size: 22rpx;
font-weight: bold;
text {
font-size: 26rpx;
}
}
}
}
.foot_bar {
width: 100%;
position: fixed;
// bottom: 54px;
left: 0;
padding: 20rpx 0;
z-index: 5;
.confirm_btn {
width: 710rpx;
height: 86rpx;
line-height: 86rpx;
color: #ffffff;
text-align: center;
font-size: 32rpx;
background: var(--view-theme);
border-radius: 43rpx;
margin: 0 auto;
}
}
.empty {
margin: 130rpx 0 150rpx;
text-align: center;
image,
uni-image {
display: inline-block;
width: 414rpx;
height: 305rpx;
}
text {
display: block;
color: #999999;
font-size: 26rpx;
}
}
</style>

324
components/bindmobile.vue Normal file
View File

@ -0,0 +1,324 @@
<template>
<view :style="viewColor">
<view class="container">
<view class="header">
<text class="title">绑定手机号</text>
<text class="iconfont icon-guanbi5" @tap="closePopup"></text>
</view>
<view class="main_counts">
<form report-submit='true'>
<view class="ChangePassword">
<view class="list">
<view class="item">
<input type='number' placeholder='输入手机号码' placeholder-class='placeholder' v-model="phone"></input>
</view>
<view class="item acea-row row-between-wrapper">
<input type='number' placeholder='输入验证码' placeholder-class='placeholder' class="codeIput" v-model="captcha"></input>
<button class="code" :class="disabled === true ? 'on' : ''" :disabled='disabled' @click="handleVerify">
{{ text }}
</button>
</view>
</view>
<button form-type="submit" @click="editPwd" class="confirmBnt">确认绑定</button>
<!-- #ifdef MP -->
<button v-if="!isCommuity" form-type="submit" class="getPhoneBtn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber"><text class="iconfont icon-weixin2"></text>使用微信绑定号码</button>
<!-- #endif -->
</view>
</form>
</view>
</view>
<Verify @success="success" :captchaType="'blockPuzzle'" :imgSize="{ width: '330px', height: '155px' }" ref="verify"></Verify>
<view class='mask' catchtouchmove="true" :hidden='popup.show==false' @tap="closePopup"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import sendVerifyCode from "@/mixins/SendVerifyCode";
import {
bindingPhone,
verifyCode, appletsDecrypt
} from '@/api/api.js';
import { registerVerify } from '@/api/user.js'
import {
mapGetters
} from "vuex";
import Verify from '@/components/verify/verify.vue';
export default {
props:{
isCommuity: {
type: Boolean,
default: false
}
},
mixins: [sendVerifyCode],
components: {
Verify
},
data() {
return {
phone:'',
captcha:'',
isAuto: false, //
isShowAuth: false, //
key: '',
codeVal: '',
popup: {
show: false
},
};
},
computed: mapGetters(['isLogin','viewColor']),
onLoad() {
},
methods: {
//
closePopup() {
this.$emit('close');
},
// #ifdef MP
getPhoneNumber(e) {
let that = this;
appletsDecrypt({
iv:e.detail.iv,
encryptedData:e.detail.encryptedData,
code:that.codeVal
}).then(res => {
that.$util.Tips({
title: '绑定成功!',
icon: 'success'
})
setTimeout(()=>{
uni.switchTab({
url: '/pages/user/index',
});
},2000)
})
},
// #endif
editPwd: function() {
let that = this;
if (!that.phone) return that.$util.Tips({
title: '请输入手机号码!'
});
if (!(/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.phone))) return that.$util.Tips({
title: '请输入正确的手机号码!'
});
if (!that.captcha) return that.$util.Tips({
title: '请填写验证码'
});
bindingPhone({
phone: that.phone,
sms_code: that.captcha
}).then(res => {
if (res.data !== undefined && res.data.is_bind) {
uni.showModal({
title: '是否绑定手机号',
content: res.msg,
confirmText: '绑定',
success(res) {
if (res.confirm) {
bindingPhone({
phone: that.phone,
captcha: that.captcha,
step: 1
}).then(res => {
that.$emit('close');
return that.$util.Tips({
title: res.msg,
icon: 'success'
});
}).catch(err => {
return that.$util.Tips({
title: err
});
})
} else if (res.cancel) {
return that.$util.Tips({
title: '您已取消绑定!'
}, {
tab: 5,
url: '/pages/users/user_info/index'
});
}
}
});
} else
that.$emit('close');
return that.$util.Tips({
title: '绑定成功!',
icon: 'success'
});
}).catch(err => {
return that.$util.Tips({
title: err
});
})
},
/**
* 发送验证码
*
*/
async code(data) {
let that = this;
if (!that.phone) return that.$util.Tips({
title: '请填写手机号码!'
});
if (!(/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.phone))) return that.$util.Tips({
title: '请输入正确的手机号码!'
});
this.disabled = true
await registerVerify({
phone:that.phone,
key:that.key,
code:that.captcha,
type: 'binding',
captchaType: 'blockPuzzle',
captchaVerification: data.captchaVerification
}).then(res => {
this.disabled = false
that.$util.Tips({
title: res.msg
});
that.sendCode();
}).catch(err => {
this.disabled = false
return that.$util.Tips({
title: err
});
});
},
success(data) {
this.$refs.verify.hide();
this.code(data);
},
handleVerify() {
let that = this;
if (!that.phone) return that.$util.Tips({
title: '请填写手机号码!'
});
if (!(/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.phone))) return that.$util.Tips({
title: '请输入正确的手机号码!'
});
this.$refs.verify.show();
}
}
}
</script>
<style lang="scss" scoped>
.container{
background-color: #ffffff;
border-radius: 16rpx 16rpx 0 0;
position: relative;
padding-bottom: 30rpx;
.header{
position: relative;
padding: 40rpx 30rpx;
text-align: center;
.title{
color: #282828;
font-size: 32rpx;
}
.iconfont{
color: #8A8A8A;
font-size: 28rpx;
position: absolute;
top: 0;
right: 0;
}
.icon-guanbi5 {
right: 20rpx;
color: #8a8a8a;
font-size: 30rpx;
line-height: 30rpx;
top: 20rpx;
background-color: transparent;
font-weight: normal;
}
}
}
.ChangePassword{
padding: 0 30rpx 100rpx;
}
.ChangePassword .phone {
font-size: 32rpx;
font-weight: bold;
text-align: center;
margin-top: 55rpx;
}
.ChangePassword .list .item {
height: 86rpx;
margin-bottom: 30rpx;
flex-direction: row;
}
.ChangePassword .list .item input {
height: 100%;
font-size: 32rpx;
border: 1px solid #DCDCDC;
border-radius: 43rpx;
padding: 0 40rpx;
}
.ChangePassword .list .item .placeholder {
color: #b9b9bc;
}
.ChangePassword .list .item input.codeIput {
max-width: 400rpx;
}
.ChangePassword .list .item .code {
font-size: 28rpx;
background-color: var(--view-minorColor);
color: var(--view-theme);
width: 230rpx;
height: 86rpx;
border-radius: 43rpx;
display: flex;
align-items: center;
justify-content: center;
}
.ChangePassword .list .item .code.on {
color: #b9b9bc;
}
.ChangePassword .confirmBnt {
font-size: 32rpx;
width: 580rpx;
height: 90rpx;
border-radius: 45rpx;
color: #fff;
margin: 60rpx auto 0 auto;
text-align: center;
line-height: 90rpx;
background-color: var(--view-theme);
}
.getPhoneBtn{
font-size: 32rpx;
width: 580rpx;
height: 90rpx;
border-radius: 45rpx;
border: 1px solid #3CB625;
color: #3CB625;
margin: 40rpx auto 0 auto;
text-align: center;
line-height: 90rpx;
.iconfont{
font-size: 32rpx;
margin-right: 12rpx;
}
}
/deep/.verifybox{
top: auto!important;
}
</style>

140
components/cash/index.vue Normal file
View File

@ -0,0 +1,140 @@
<template>
<view :style="viewColor">
<view class="payment" :class="pay_close ? 'on' : ''">
<view class="title acea-row row-center-wrapper">
选择提现方式<text class="iconfont icon-guanbi" @click='close'></text>
</view>
<radio-group @change="radioChange">
<label class="item acea-row row-between-wrapper" v-for="(item,index) in payMode" :key="index">
<view class="acea-row-left">
<view class="icon-left" :style="[{backgroundColor: item.bg_color}]">
<view class="iconfont" :class="item.icon"></view>
</view>
<view class="name">{{item.name}}</view>
</view>
<view>
<radio :value="item.id.toString()" :checked="item.id == order_id" />
</view>
</label>
</radio-group>
</view>
<view class="mask" ref="close" @click='close' v-if="pay_close"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { orderPay, presellOrderPay } from '@/api/order.js';
import { mapGetters } from "vuex";
export default {
props: {
payMode: {
type: Array,
default: function() {
return [];
}
},
pay_close: {
type: Boolean,
default: false,
},
order_id: {
type: String,
default: '0'
}
},
computed: mapGetters(['viewColor']),
data() {
return {
type: '0'
};
},
methods: {
close: function() {
this.$emit('payClose')
},
radioChange(e) {
this.type = e.detail.value
this.$emit('onChangeFun', {
action: 'payClose',
type: this.type
});
}
}
}
</script>
<style scoped lang="scss">
.payment {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
border-radius: 16rpx 16rpx 0 0;
background-color: #fff;
padding-bottom: 60rpx;
z-index: 99;
transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
transform: translate3d(0, 100%, 0);
}
.payment.on {
transform: translate3d(0, 0, 0);
}
/deep/radio .uni-radio-input.uni-radio-input-checked {
border: 1px solid var(--view-theme) !important;
background-color: var(--view-theme) !important
}
.payment .title {
text-align: center;
height: 123rpx;
font-size: 32rpx;
color: #282828;
font-weight: bold;
padding-right: 30rpx;
margin-left: 30rpx;
position: relative;
border-bottom: 1px solid #eee;
}
.payment .title .iconfont {
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
font-size: 43rpx;
color: #8a8a8a;
font-weight: normal;
}
.payment .item {
border-bottom: 1px solid #eee;
height: 130rpx;
margin-left: 30rpx;
padding-right: 30rpx;
}
.payment .item .acea-row-left{
.icon-left{
display: inline-block;
width: 56rpx;
height: 56rpx;
text-align: center;
line-height: 56rpx;
background-color: #FE960F;
margin-right: 20rpx;
border-radius: 50%;
.iconfont{
color: #FFF;
font-size: 36rpx;
}
}
.name{
display: inline-block;
}
}
</style>

View File

@ -0,0 +1,388 @@
<template>
<view>
<view class='coupon-list-window animated' :class='coupon.status==true?"slideInUp":""'>
<view class='title'>
<view class="item">优惠券</view>
</view>
<block v-if="couponArr.length">
<view class='coupon-list'>
<view class='item acea-row row-center-wrapper' v-for="(item,index) in couponArr" @click="getCouponUser(index,item)"
:key='index'>
<view class='money acea-row row-column row-center-wrapper'>
<view><text class='num'>{{item.coupon_price}}</text></view>
<view class="pic-num">{{item.use_min_price}}元可用</view>
</view>
<view class='text'>
<view class='condition line1'>
<span class='line-title' v-if='item.coupon.type===0'>店铺券</span>
<span class='line-title' v-else-if='item.coupon.type===1'>商品券</span>
<span>{{item.coupon_title}}</span>
</view>
<view class='data acea-row row-between-wrapper'>
<view>{{ item.start_time |timeYMD }} ~ {{ item.end_time |timeYMD}}</view>
<view class="iconfont icon-weixuanzhong" v-if="!item.checked"></view>
<view class='iconfont icon-xuanzhong1' v-else></view>
</view>
</view>
</view>
</view>
<view class="foot-box">
<view class="left">
已选择{{allNum}}可优惠<text>{{allCouponNum}}</text>
</view>
<view class="btn" @click="confirm">确定</view>
</view>
</block>
<!-- 无优惠券 -->
<view class='pictrue' v-else>
<image src='../../static/images/noCoupon.png'></image>
</view>
</view>
<view class='mask' catchtouchmove="true" :hidden='coupon.status==false' @click='close'></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import {
setCouponReceive
} from '@/api/api.js';
export default {
props: {
// 0=,1=使
openType: {
type: Number,
default: 0,
},
coupon: {
type: Object,
default: function() {
return {};
}
},
subCoupon: {
type: Object
}
},
filters: {
timeYMD: function(value) {
if(value){
var newDate=/\d{4}-(\d{1,2}\d{1,2}-\d{1,2}\d{1,2})/g.exec(value)
return newDate?.[1]||''
}
}
},
data() {
return {
couponArr: [],
couponData: {},
//
active: {},
allNum: 0,
allCouponNum: 0,
// id
use_store_coupon: 0,
//
pay_price: 0,
//
goodsOrder: ''
};
},
mounted() {
this.couponData = this.coupon
// 使
this.couponArr = JSON.parse(JSON.stringify(this.coupon.coupon))
// 使
this.goodsOrder = JSON.parse(JSON.stringify(this.coupon.order))
let tempObj = this.active[this.couponData.mer_id] = {}
tempObj.product = []
tempObj.store = ''
this.allActive()
},
methods: {
close: function() {
this.$emit('ChangCouponsClone');
},
// 使
getCouponUser: function(index, item) {
let self = this
// 1 0
if (item.coupon.type == 1) {
let order = this.goodsOrder
let orderToalPrice = 0
if (item.checked) {
/**
* 取消选中 并且删除 use_coupon_product里的值
* use_coupon_product 哪些商品可以用的券的id
* */
for (let key in order.use_coupon_product) {
if (order.use_coupon_product[key] == item.coupon_user_id) {
delete order.use_coupon_product[key]
}
}
item.checked = false
} else {
/**
* 选中
* @item.product 该优惠券可以使用的商品
* order.product_price 产品的价格 key是id
* */
for (let i = 0; i < item.product.length; i++) {
if (order.product_price[item.product[i].product_id]) {
orderToalPrice = order.product_price[item.product[i].product_id]
//使
if (orderToalPrice >= parseFloat(item.use_min_price)) {
//
if (!order.use_coupon_product[item.product[i].product_id]) {
item.checked = true
order.use_coupon_product[item.product[i].product_id] = item.coupon_user_id
} else {
//
this.couponArr.forEach(el => {
if (el.coupon_user_id == order.use_coupon_product[item.product[i].product_id]) {
el.checked = false
}
})
item.checked = true
order.use_coupon_product[item.product[i].product_id] = item.coupon_user_id
}
break
}
}
}
}
} else {
let order = this.couponData.order
//
if (item.checked) {
item.checked = false
// this.pay_price = order.total_price
} else {
this.couponArr.forEach(el => {
if (el.coupon.type == 0 && el.checked) {
el.checked = false
}
})
item.checked = true
}
this.pay_price = this.$util.$h.Sub(order.total_price, item.coupon_price)
}
this.allActive()
},
//
allActive() {
let tempObj = this.active[this.couponData.mer_id]
let sotreTotal = 0 //
let goodsTotal = 0 //
tempObj.product = []
tempObj.store = ''
this.couponArr.forEach(el => {
/**
* @el.coupon.type 0店铺 1商品
*/
if (el.coupon.type == 0 && el.checked) {
tempObj.store = el.coupon_user_id
sotreTotal = el.coupon_price
this.use_store_coupon = el.coupon_user_id
}
if (el.coupon.type == 1 && el.checked) {
tempObj.product.push(el.coupon_user_id)
goodsTotal = this.$util.$h.Add(goodsTotal, el.coupon_price)
}
})
if (tempObj.store) {
this.allNum = this.$util.$h.Add(tempObj.product.length, 1)
} else {
this.allNum = tempObj.product.length
}
let tempAllCouponNum = this.$util.$h.Add(sotreTotal, goodsTotal)
if (parseFloat(tempAllCouponNum) >= parseFloat(this.couponData.order.total_price)) {
this.allCouponNum = this.couponData.order.total_price
} else {
if(this.allNum !== 0 ){
if(sotreTotal || goodsTotal){
this.allCouponNum = tempAllCouponNum
}else{
this.allCouponNum = this.couponData.order.total_price
}
}else{
this.allCouponNum = tempAllCouponNum
}
}
},
//
confirm() {
//
this.couponData.order = this.goodsOrder
//
//
let tempTotal = 0
tempTotal = this.$util.$h.Sub(this.couponData.order.total_price, this.allCouponNum)
if (tempTotal > 0) {
this.couponData.order.pay_price = this.$util.$h.Add(tempTotal, this.couponData.order.postage_price)
} else {
//
if(this.allNum == 0){
this.couponData.order.pay_price = this.$util.$h.Add(this.couponData.order.total_price, this.couponData.order.postage_price)
}else{
this.couponData.order.pay_price = this.couponData.order.postage_price
}
}
//
this.couponData.order.coupon_price = this.allCouponNum
this.couponData.order.use_store_coupon = this.use_store_coupon
this.couponData.coupon = this.couponArr
this.active[this.coupon.mer_id].product = this.goodsOrder.use_coupon_product
this.subCoupon[this.coupon.mer_id] = this.active[this.coupon.mer_id]
this.$emit('ChangCoupons',this.couponData);
}
}
}
</script>
<style scoped lang="scss">
.animated {
animation-duration: .3s
}
.title {
display: flex;
.item {
position: relative;
flex: 1;
font-size: 28rpx;
color: #999999;
&::after {
content: ' ';
position: absolute;
left: 50%;
bottom: 18rpx;
width: 50rpx;
height: 5rpx;
background: transparent;
border-radius: 3px;
transform: translateX(-50%);
}
&.on {
color: #282828;
&::after {
background: $theme-color;
}
}
}
}
.coupon-list {
padding: 30rpx;
.item {
box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.06);
}
}
.coupon-list-window {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
border-radius: 16rpx 16rpx 0 0;
z-index: 555;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
}
.coupon-list-window.on {
animation: aminup;
}
.coupon-list-window .title {
height: 106rpx;
width: 100%;
text-align: center;
line-height: 106rpx;
font-size: 32rpx;
font-weight: bold;
position: relative;
border: 1px solid #f5f5f5;
}
.coupon-list-window .title .iconfont {
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
font-size: 35rpx;
color: #8a8a8a;
font-weight: normal;
}
.coupon-list-window .coupon-list {
margin: 0 0 0rpx 0;
height: 550rpx;
overflow: auto;
}
.coupon-list-window .pictrue {
width: 414rpx;
height: 336rpx;
margin: 0 auto 50rpx auto;
}
.coupon-list-window .pictrue image {
width: 100%;
height: 100%;
}
.pic-num {
color: #fff;
font-size: 24rpx;
}
.line-title {
width: 90rpx;
padding: 0 10rpx;
box-sizing: border-box;
background: rgba(255, 247, 247, 1);
border: 1px solid rgba(232, 51, 35, 1);
opacity: 1;
border-radius: 20rpx;
font-size: 20rpx;
color: #E83323;
margin-right: 12rpx;
}
.line-title.gray {
border-color: #BBB;
color: #bbb;
background-color: #F5F5F5;
}
.foot-box {
display: flex;
align-items: center;
justify-content: space-between;
height: 100rpx;
padding: 0 30rpx;
border-top: 1px solid #F5F5F5;
.btn {
width: 240rpx;
height: 70rpx;
line-height: 70rpx;
text-align: center;
background: $theme-color;
border-radius: 35rpx;
color: #fff;
font-size: 30rpx;
}
.left {
text {
color: $theme-color;
}
}
}
.coupon-list .item .text .data .iconfont {
font-size: 36rpx;
&.icon-weixuanzhong {
color: #BFBFBF;
}
&.icon-xuanzhong1 {
color: $theme-color;
}
}
</style>

View File

@ -0,0 +1,189 @@
<template>
<view :style="viewColor">
<!-- 选择送货方式 -->
<view class="mask-box">
<view class="bg" v-if="isShowBox"></view>
<view class="mask-content animated" :class="{slideInUp:isShowBox}">
<view class="title-bar">
配送方式
<view class="close" @click="closeShowBox"><text class="iconfont icon-guanbi"></text></view>
</view>
<view class="box">
<view class="check-item" v-for="(item,index) in radioList" :key="index"
:class="{on:index == radioIndex}">
<view>{{item.title}}</view>
<view class="radio" @click="bindCheck(item,index)">
<block v-if="index == newData.order.isTake">
<view class="iconfont icon-xuanzhong1"></view>
</block>
<block v-else>
<view class="iconfont icon-weixuanzhong"></view>
</block>
</view>
</view>
</view>
<view class="foot">
<view class="btn" @click="confirmBtn">确定</view>
</view>
</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import {
mapGetters
} from "vuex";
export default {
name: 'checkDelivery',
props: {
isShowBox: {
type: Boolean,
default: false
},
activeObj: {
type: Object,
default: function() {
return {}
}
},
deliveryName: {
type: String,
default: '快递配送'
},
radioList: {
type: Array,
default: [{
title: '快递配送',
check: true
},
{
title: '到店核销',
check: false
}
],
},
},
computed: mapGetters(['viewColor']),
data() {
return {
radioIndex: 0,
oldRadioIndex: '', //
newData: {}
}
},
created() {
this.newData = JSON.parse(JSON.stringify(this.activeObj))
},
methods: {
//
closeShowBox() {
this.$emit('close')
},
//
bindCheck(item, index) {
this.newData.order.isTake = index
},
confirmBtn() {
this.$emit('confirmBtn', this.newData)
}
}
}
</script>
<style lang="scss">
.mask-box {
.bg {
z-index: 30;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
}
.mask-content {
z-index: 40;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background-color: #fff;
border-radius: 16rpx 16rpx 0 0;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
.title-bar {
position: relative;
text-align: center;
padding: 30rpx 0;
margin-bottom: 20rpx;
font-size: 32rpx;
color: #282828;
.close {
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
.iconfont {
color: #8A8A8A;
}
}
}
.box {
padding: 0 30rpx;
.check-item {
display: flex;
align-items: center;
justify-content: space-between;
height: 40rpx;
margin-bottom: 50rpx;
font-size: 28rpx;
.iconfont {
font-size: 38rpx;
color: #CCCCCC;
&.icon-xuanzhong1 {
color: var(--view-theme);
}
}
}
}
.foot {
padding: 15rpx 30rpx;
border-top: 1px solid #F5F5F5;
.btn {
width: 100%;
height: 70rpx;
line-height: 70rpx;
text-align: center;
border-radius: 35rpx;
color: #fff;
font-size: 30rpx;
background: var(--view-theme);
}
}
}
}
.animated {
animation-duration: .3s
}
</style>

View File

@ -0,0 +1,317 @@
<template>
<view :style="viewColor">
<view class="navTabBox">
<view class="longTab">
<scroll-view scroll-x="true" style="white-space: nowrap; display: flex;" scroll-with-animation :scroll-left="tabLeft"
show-scrollbar="true">
<view class="longItem" :style='"width:"+isWidth+"px"' :data-index="index" :class="index===tabClick?'click':''"
v-for="(item,index) in tabTitle" :key="index" :id="'id'+index" @click="longClick(index,item.store_category_id)">{{item.cate_name}}
</view>
<view class="underlineBox" :style='"transform:translateX("+isLeft+"px);width:"+isWidth+"px"'>
<view class="underline bg-color-white"></view>
</view>
</scroll-view>
<view class='iconfont icon-xiangxia' style="padding: 8rpx 0 0 8rpx;" @click="tabsOpen = true"></view>
</view>
<view class="tabs-box" v-if="tabsOpen">
<view class="box-top">
<view class="">
切换分类
</view>
<view class="">
<view class='iconfont icon-xiangshang' @click="tabsOpen = false"></view>
</view>
</view>
<view class="all-tabs">
<view class="tabs-style" :class="index===tabClick?'active':''" v-for="(tab,index) in tabTitle" :key='index' @click="longClick(index,tab.store_category_id)">
<text class="line1">{{tab.cate_name}}</text>
</view>
</view>
</view>
</view>
<view class='mask' v-if="tabsOpen" @click="tabsOpen = false"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { mapGetters } from "vuex";
let app = getApp();
export default {
name: 'navTab',
props: {
tabTitle: {
type: Array,
default: () => {
[]
}
}
},
computed: mapGetters(['viewColor']),
data() {
return {
tabClick: 0, //
isLeft: 0, //线
isWidth: 0, //
tabLeft: 0,
swiperIndex: 0,
childIndex: 0,
childID: 0,
window: false,
tabsOpen: false
};
},
created() {
var that = this
//
uni.getSystemInfo({
success(e) {
that.isWidth = e.windowWidth / 5
}
})
},
methods: {
//
longClick(index, id) {
this.childIndex = 0;
if (this.tabTitle.length > 5) {
var tempIndex = index - 2;
tempIndex = tempIndex <= 0 ? 0 : tempIndex;
this.tabLeft = (index - 2) * this.isWidth //线
}
this.tabClick = index //
this.isLeft = index * this.isWidth //线
let obj = {
index: index,
pid: id
}
this.parentEmit(obj);
this.tabsOpen = false
},
parentEmit(obj) {
this.$emit('changeTab', obj);
}
}
}
</script>
<style lang="scss">
@keyframes bounce-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.navTabBox {
width: 750rpx;
padding: 0 40rpx;
color: rgba(255, 255, 255, 1);
position: relative;
.tabs-box {
position: absolute;
top: 0;
display: flex;
flex-direction: column;
width: 90%;
background-color: #FFFFFF;
border-radius: 24rpx;
z-index: 999;
animation: bounce-in .3s;
.box-top {
padding: 30rpx 20rpx 10rpx 20rpx;
display: flex;
justify-content: space-between;
color: #666;
font-size: 28rpx;
}
.all-tabs {
display: flex;
flex-wrap: wrap;
padding: 20rpx 0;
font-size: 24rpx;
.tabs-style {
display: flex;
justify-content: center;
background: #F2F2F2;
border-radius: 29px;
color: #282828;
width: 22%;
padding: 10rpx 20rpx;
white-space: nowrap;
border-radius: 30px;
margin: 10rpx;
}
.active {
background: var(--view-minorColor);
color: var(--view-theme);
border: 1px solid var(--view-theme);
}
}
}
.nav_toggle {
position: absolute;
top: 8rpx;
right: 20rpx;
}
.click {
color: white;
}
.longTab {
display: flex;
width: 95%;
/* #ifdef H5 */
padding-bottom: 20rpx;
/* #endif */
/* #ifdef MP */
padding-top: 12rpx;
padding-bottom: 12rpx;
/* #endif */
.longItem {
height: 50upx;
display: inline-block;
line-height: 50upx;
text-align: center;
font-size: 30rpx;
color: rgba(255, 255, 255, .8);
max-width: 160rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
overflow-x: scroll;
overflow-y: hidden;
/*解决ios上滑动不流畅*/
-webkit-overflow-scrolling: touch;
&.click {
font-weight: bold;
font-size: 30rpx;
color: #FFFFFF;
}
}
.underlineBox {
height: 3px;
width: 20%;
display: flex;
align-content: center;
justify-content: center;
transition: .5s;
.underline {
width: 60rpx;
height: 4rpx;
}
}
}
}
.bg-color-white {
background-color: #fff;
}
.child-box {
width: 100%;
position: relative;
background-color: #fff;
/* #ifdef H5 */
box-shadow: 0 2px 5px 1px rgba(0, 0, 0, 0.02);
/* #endif */
/* #ifdef MP */
box-shadow: 0 2rpx 3rpx 1rpx #f9f9f9;
/* #endif */
.wrapper {
display: flex;
align-items: center;
padding: 20rpx 0;
background: #fff;
}
.child-item {
flex-shrink: 0;
width: 140rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-left: 10rpx;
image {
width: 90rpx;
height: 90rpx;
border-radius: 50%;
}
.txt {
font-size: 24rpx;
color: #282828;
text-align: center;
margin-top: 10rpx;
}
&.on {
image {
border: 1px solid $theme-color-opacity;
}
.txt {
color: $theme-color;
}
}
}
}
.brand-wrapper {
flex: 1;
overflow: hidden;
width: 690rpx;
margin: 0 auto;
background: #ffffff;
border-radius: 12rpx;
padding: 25rpx;
.wrapper {
display: flex;
flex-wrap: wrap;
padding-bottom: 20rpx;
}
.item {
display: block;
width: 146rpx;
height: 58rpx;
line-height: 58rpx;
text-align: center;
background: rgba(242, 242, 242, 1);
border-radius: 28rpx;
margin-top: 25rpx;
padding: 0 10rpx;
margin-right: 19rpx;
color: #282828;
font-size: 24rpx;
&:nth-child(4n) {
margin-right: 0;
}
&.on {
background: rgba(255, 244, 243, 1);
border: 1px solid rgba(233, 51, 35, 1);
color: rgba(233, 51, 35, 1);
}
}
.btns {
display: flex;
align-items: center;
justify-content: center;
padding-top: 10rpx;
font-size: 22rpx;
color: #999;
.iconfont {
margin-left: 10rpx;
margin-top: 5rpx;
font-size: 20rpx;
}
}
.mask {
z-index: 300 !important;
}
.icon-xiangxia {
font-size: 20px;
}
}
</style>

482
components/comment.vue Normal file
View File

@ -0,0 +1,482 @@
<template>
<view :style="viewColor">
<view class="container" :class="isShow==true?'on':''" @click.stop="loseFocus">
<view class="main_content">
<view class="header">
<text class="title">评论 {{all}}</text>
<text class="iconfont icon-guanbi5" @click="close"></text>
</view>
<view class="main">
<scroll-view scroll-y="true">
<view v-if="list.length > 0" @touchmove="onTouchmove" id="reply">
<view class="common_list" v-for="(item, index) in list" :key="index">
<view class="commen_one">
<image :src="(item.author&&item.author.avatar) || '/static/images/f.png'" class="image"></image>
</view>
<view class="info_count">
<view class="info">
<view class="message" @click.stop="toReply(item,index)">
<view v-if="item.author" class="name">{{item.author.nickname}}</view>
<view class="desc">{{item.content}}</view>
<view class="time">{{item.create_time}}</view>
</view>
<view class="like" @click.stop="starComment(item)">
<view class="iconfont":class="item.relevance_id ? 'icon-yidianzan' : 'icon-dianzan1'"></view>
{{item.count_start}}
</view>
</view>
<view v-if="item.children && item.children.length > 0" class="reply_count">
<view v-for="(itemn,indexn) in item.children" :key="indexn" class="reply_list">
<view class="item">
<view class="item_count" @click.stop="toReply(itemn,index)">
<image class="image" :src="itemn.author && itemn.author.avatar || '/static/images/f.png'"></image>
<view v-if="itemn.author" class="name_two">{{itemn.author.nickname}}</view>
<view class="desc_two">
<text class="reply_user" v-if="itemn.reply">回复 @{{itemn.reply.nickname}} </text> {{itemn.content}}
</view>
<view class="time_two">{{itemn.create_time}}</view>
</view>
<view class="like_two" @click.stop="starComment(itemn)">
<view class="iconfont":class="itemn.relevance_id ? 'icon-yidianzan' : 'icon-dianzan1'"></view>
{{itemn.count_start}}
</view>
</view>
</view>
</view>
</view>
</view>
<view class="end"><text>到底了</text></view>
</view>
<Loading :loaded="loaded" :loading="loading"></Loading>
<view v-if="list.length == 0 && !loading" class="empty">
<image src="/static/images/no_commen.png"></image>
<text>暂无评论快去抢沙发吧~</text>
</view>
</scroll-view>
</view>
</view>
<view class="release_bar" :style="'bottom:'+bottom+'rpx;'">
<image class="image" :src="userInfo.avatar || '/static/images/f.png'"></image>
<view class="input_count">
<input type="text" :placeholder="placeholder" placeholder-style="color: #999999; font-size: 26rpx;" v-model="content" :focus="focus" confirm-type="search">
</view>
<button class="send" @click.stop="submitComment">发送</button>
</view>
</view>
<!-- 绑定手机号 -->
<uni-popup ref="bindmobile" type="bottom">
<bindmobile @close="closepoup" :isCommuity="true"></bindmobile>
</uni-popup>
<view class='mask' catchtouchmove="true" :hidden='isShow==false' @tap="close"></view>
<authorize @onLoadFun="onLoadFun" :isAuto="isAuto" :isShowAuth="isShowAuth" @authColse="authColse"></authorize>
</view>
</template>
<script>
import { replyLstApi, starCommentApi, replyCreateApi } from '@/api/community.js';
import Loading from '@/components/Loading/index.vue';
import bindmobile from '@/components/bindmobile.vue';
import { getUserInfo } from '@/api/user.js';
import { mapGetters } from "vuex";
import { configMap } from '@/utils';
import authorize from '@/components/Authorize';
export default {
props:{
isShow: {
type: Boolean,
default: false
},
bottom: {
type: Number,
default: 0
},
userInfo: {
type: Object,
default: () => {uid:0;avatar:""}
}
},
components: {
Loading,bindmobile,authorize
},
computed: configMap({community_reply_auth:0},mapGetters(['isLogin', 'viewColor'])),
data() {
return {
content: '',
id: "",
list: [],
loaded: false,
loading: false,
where: {
page: 1,
limit: 10
},
reply_id: "",
placeholder: "快来说点儿什么吧...",
isChild: false,
index: 0,
listIndex: 0,
focus: false,
all: 0,
isShowAuth: false, //
isAuto: false, //
};
},
methods: {
//
close() {
this.$emit('close');
},
onTouchmove(e){
if (this.loadend || this.loading) return;
const query = uni.createSelectorQuery().in(this);
query.select('#reply').boundingClientRect(data => {
// console.log(data)
if(data.bottom < 1500 && data.top < 0) {
this.getList();
}
}).exec();
//
},
//
onLoadFun() {
this.isShowAuth = false
},
//
authColse: function(e) {
this.isShowAuth = e
},
getData(item,index){
this.id = item.community_id
this.loading = this.loaded = false
this.where.page = 1
this.list = []
this.getList()
this.listIndex = index
},
getList(){
let that = this;
if(that.loading || that.loaded) return;
that.loading = true;
replyLstApi(that.id,that.where).then(res => {
that.loading = false;
that.all = res.data.all;
that.loaded = res.data.list.length < that.where.limit;
that.list.push.apply(that.list, res.data.list);
that.where.page = that.where.page + 1;
},
error => {
that.$util.Tips({
title: error.msg
})
}
);
},
/*发表评论*/
submitComment(){
let that = this;
if (that.isLogin === false) {
that.isAuto = true;
that.isShowAuth = true;
}else{
that.getUserInfo();
}
},
/**
* 获取个人用户信息
*/
getUserInfo: function() {
let that = this;
getUserInfo().then(res => {
/*判断是否绑定手机号*/
if(res.data.phone || that.community_reply_auth == 0){
that.createReply()
}else{
that.$refs.bindmobile.open()
}
});
},
createReply() {
let that = this;
let reply_id = that.reply_id ? that.reply_id : 0
replyCreateApi(that.id,{content: that.content,reply_id: reply_id}).then(res => {
that.$util.Tips({
title: res.message
});
if(res.data.status == 1){
if(that.isChild){
if(that.list[that.index]['children']){
that.list[that.index]['children'].push(res.data)
}else{
that.list[that.index]['children'] = [res.data]
}
}else{
that.list.unshift(res.data)
}
that.all++
}
that.content = ""
that.$util.Tips({
title: res.message
});
that.$emit('successFul',that.listIndex);
that.loseFocus()
}).catch(err => {
uni.showToast({
title: err,
icon: 'none'
})
});
},
toReply(item,index){
this.content = ""
this.placeholder = '回复:'+item.author.nickname
this.reply_id = item.reply_id
this.isChild = true
this.index = index;
this.focus = true;
},
loseFocus(){
this.focus = false;
this.reply_id = 0;
this.placeholder = "快来说点儿什么吧..."
this.isChild = false
// this.content = ""
},
/*点赞评论*/
starComment(item){
let that = this;
let status = item.relevance_id ? 0 : 1
starCommentApi(item.reply_id,{status: status}).then(res => {
if (res.status === 200) {
if(item.relevance_id){
item.count_start--;
item.count_start = item.count_start == 0 ? 0 : item.count_start
item.relevance_id = false
}else{
item.count_start++;
item.relevance_id = true
}
}
that.$util.Tips({
title: res.message
});
}).catch(err => {
uni.showToast({
title: err,
icon: 'none'
})
});
},
closepoup(){
this.$refs.bindmobile.close()
},
}
}
</script>
<style lang="scss" scoped>
.container{
display: block;
background: #ffffff;
border-radius: 16rpx 16rpx 0 0;
position: relative;
position: fixed;
bottom: 0;
padding-bottom: calc(0rpx+ constant(safe-area-inset-bottom)); /// IOS<11.2/
padding-bottom: calc(0rpx + env(safe-area-inset-bottom)); /// IOS>11.2/
width: 100%;
left: 0;
background-color: #f5f5f5;
z-index: 40;
border-radius: 16rpx 16rpx 0 0;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
&.on {
transform: translate3d(0, 0, 0);
}
.main_content{
padding: 24rpx 30rpx;
border-bottom: 1px solid #F5F5F5;
position: relative;
}
.header{
position: relative;
text-align: center;
.title{
color: #282828;
font-size: 36rpx;
font-weight: bold;
}
.iconfont{
color: #8A8A8A;
font-size: 36rpx;
position: absolute;
top: 4rpx;
right: 0;
}
}
}
scroll-view{
max-height: 60vh;
}
.main{
margin-top: 60rpx;
padding-bottom: 20rpx;
position: static;
.common_list{
position: relative;
padding-left: 94rpx;
margin-bottom: 20rpx;
.commen_one{
position: absolute;
top: 0;
left: 0;
.image,uni-image{
width: 74rpx;
height: 74rpx;
border-radius: 100%;
}
}
.info{
position: relative;
padding-right: 90rpx;
}
.name,.name_two{
color: #999999;
font-size: 26rpx;
}
.desc,.desc_two{
color: #282828;
font-size: 28rpx;
margin-top: 10rpx;
}
.desc_two{
font-size: 26rpx;
.reply_user{
font-size: 24rpx;
color: #4A8AC9;
margin: 0 6rpx;
}
}
.time,.time_two{
color: #BBBBBB;
font-size: 22rpx;
margin-top: 15rpx;
}
.like,.like_two{
color: #999999;
font-size: 26rpx;
text-align: center;
position: absolute;
top: 0;
right: 0;
width: 75rpx;
.icon-yidianzan{
color: var(--view-theme);
}
}
.reply_list{
margin-top: 20rpx;
.item{
padding-right: 140rpx;
position: relative;
}
.item_count{
position: relative;
padding-left: 56rpx;
.image,un-image{
width: 36rpx;
height: 36rpx;
border-radius: 100%;
position: absolute;
top: 0;
left: 0;
}
}
}
}
.end{
margin-top: 50rpx;
text-align: center;
text{
color: #999999;
font-size: 22rpx;
position: relative;
&::before,&::after{
content: "";
display: inline-block;
width: 22rpx;
height: 1rpx;
background: #999999;
position: absolute;
top: 18rpx;
opacity: .5;
}
&::before{
left: -30rpx;
}
&::after{
right: -30rpx;
}
}
}
}
.release_bar{
// position: absolute;
width: 100%;
left: 0;
/*#ifndef MP*/
bottom: 0;
/*#endif*/
/*#ifdef MP*/
bottom: 10rpx;
/*#endif*/
background: #ffffff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 15rpx 30rpx;
border-top: 1px solid #F5F5F5;
flex-direction: row;
.avatar,image,uni-image{
width: 54rpx;
height: 54rpx;
border-radius: 100%;
}
.input_count{
width: 480rpx;
background: #F7F7F7;
border-radius: 31rpx;
padding: 12rpx 30rpx;
}
.send{
font-size: 26rpx;
color: #ffffff;
padding: 12rpx 30rpx;
background-image: linear-gradient(126deg, var(--view-bntColor21) 0%, var(--view-bntColor22) 100%);
border-radius: 30rpx;
text-align: center;
}
}
.empty{
display: block;
margin: 130rpx 0 150rpx;
text-align: center;
image,uni-image{
display: inline-block;
width: 414rpx;
height: 305rpx;
}
text{
display: block;
color: #999999;
font-size: 26rpx;
}
}
</style>

View File

@ -0,0 +1,147 @@
<template>
<view :style="viewColor">
<view class='copy-list-window' :class='isCopy==true?"on":""'>
<button class="iconfont icon-guanbi" @click='close'></button>
<view class="title">
<text class="iconfont icon-xuanzhong11"></text>
{{title}}
</view>
<view class="copy-url">
<!-- #ifdef H5 -->
<text class="copy copy-data" :data-clipboard-text="copyUrl">{{copyUrl}}</text>
<!-- #endif -->
<!-- #ifndef H5 -->
<text>{{copyUrl}}</text>
<!-- #endif -->
</view>
<!-- #ifdef H5 -->
<button class="button copy-data" :data-clipboard-text="copyUrl">点击复制口令</button>
<!-- #endif -->
<!-- #ifndef H5 -->
<button class="button" @click="copyText">点击复制口令</button>
<!-- #endif -->
</view>
<view class='mask' catchtouchmove="true" :hidden='isCopy==false' @click='close'></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
// #ifdef H5
import ClipboardJS from "@/plugin/clipboard/clipboard.js";
// #endif
import { mapGetters } from "vuex";
export default {
props: {
isCopy: {
type: Boolean,
default: false,
},
copyUrl: {
type: String,
default: '',
}
},
computed: mapGetters(['viewColor']),
data() {
return {
title: '复制以下口令'
};
},
mounted(){
let that = this
// #ifdef H5
that.$nextTick(function() {
var clipboard = new ClipboardJS('.copy-data');
clipboard.on('success', function(e) {
that.$util.Tips({
title:'复制成功'
})
setTimeout(()=>{
that.$emit('close');
},500)
});
clipboard.on('error', function(e) {
that.$util.Tips({
title:'复制失败'
})
});
});
// #endif
},
methods: {
//#ifndef H5
copyText:function(){
let that = this;
uni.setClipboardData({ data: this.copyUrl });
setTimeout(()=>{
that.$emit('close');
},500)
},
// #endif
close: function(){
this.$emit('close');
}
}
}
</script>
<style scoped lang="scss">
.copy-list-window {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
border-radius: 16rpx 16rpx 0 0;
z-index: 555;
transform: translate3d(0, 100%, 0);
transition: all .1s cubic-bezier(.25, .5, .5, .9);
padding: 50rpx 30rpx 30rpx;
.icon-guanbi{
position: absolute;
top: 20rpx;
right: 20rpx;
color: #8A8A8A;
}
.button{
height: 76rpx;
border-radius: 38rpx;
margin: 30rpx 30rpx 0;
background-color: var(--view-theme);
font-size: 30rpx;
line-height: 76rpx;
color: #FFFFFF;
}
}
.copy-list-window.on {
transform: translate3d(0, 0, 0);
}
.copy-list-window .title {
width: 100%;
text-align: center;
font-size: 32rpx;
font-weight: bold;
font-family: 'PingFang SC';
.iconfont {
font-size: 30rpx;
color: #FBB324;
margin-right: 12rpx;
}
}
.copy-url{
margin-top: 30rpx;
background: #F5F5F5;
padding: 20rpx 25rpx;
color: #BBBBBB;
font-size: 28rpx;
}
</style>

View File

@ -0,0 +1,160 @@
<template>
<view class="time" :class="{themeColor : isView}" :style="justifyLeft+viewColor+'background-color:'+ bgColor +';color:'+ colors +';background-image:url('+bgImage+');'">
<text class="red" v-if="tipText">{{ tipText }}</text>
<text class="styleAll" v-if="isDay === true">{{ day }}</text>
<text class="timeTxt red" v-if="dayText">{{ dayText }}</text>
<text class="styleAll">{{ hour }}</text>
<text class="timeTxt red" v-if="hourText">{{ hourText }}</text>
<text class="styleAll">{{ minute }}</text>
<text class="timeTxt red" v-if="minuteText">{{ minuteText }}</text>
<text class="styleAll">{{ second }}</text>
<text class="timeTxt red" v-if="secondText">{{ secondText }}</text>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { mapGetters } from "vuex";
export default {
name: "countDown",
props: {
justifyLeft: {
type: String,
default: ""
},
//
tipText: {
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
},
id:{
type: String | Number,
default: ""
},
bgColor:{
type: String,
default: ""
},
colors:{
type: String,
default: ""
},
bgImage: {
type: String,
default: ""
},
isView: {
type: Boolean,
default: false
},
},
data: function() {
return {
day: "00",
hour: "00",
minute: "00",
second: "00"
};
},
computed:{
...mapGetters(['viewColor']),
},
created: function() {
this.show_time();
},
mounted: function() {},
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";
that.$emit('getProduct');
clearInterval(runTime)
uni.$emit('endTime',that.id)
}
}
runTime();
setInterval(runTime, 1000);
}
}
};
</script>
<style lang="scss" scoped>
.styleAll {
padding: 0 6rpx;
}
.red{
margin: 0 4rpx;
}
.themeColor .red{
color: var(--view-theme);
}
.time{
display: flex;
justify-content: center;
}
</style>

View File

@ -0,0 +1,238 @@
<template>
<view :style="viewColor">
<view class='coupon-list-window animated' :class='coupon.coupon==true?"slideInUp":""'>
<view class='title'>
<view class="item">优惠券<text class='iconfont icon-guanbi' @tap='close'></text></view>
</view>
<view class='coupon-list' v-if="coupon.list.length">
<view class='item acea-row row-center-wrapper' v-for="(item,index) in coupon.list" @click="getCouponUser(index,item)"
:key='index'>
<view class='money acea-row row-column row-center-wrapper' :style="{ 'background-image': `url(${domain}/static/diy/couponBg${keyColor}.png)` }">
<view><text class='num'>{{item.coupon_price}}</text></view>
<view class="pic-num">{{item.use_min_price}}元可用</view>
</view>
<view class='text'>
<view class='condition line1'>
<span class='line-title' v-if='item.type===0'>店铺券</span>
<span class='line-title' v-else-if='item.type===1'>商品券</span>
<span>{{item.title}}</span>
</view>
<view class='data acea-row row-between-wrapper'>
<block v-if="item.coupon_type == 1">
<view>{{ item.use_start_time |timeYMD }}-{{ item.use_end_time |timeYMD}}</view>
</block>
<block v-if="item.coupon_type == 0">
<view>领取后{{ item.coupon_time}}天内可用</view>
</block>
<view class='gray iconfont icon-yilingqu2' v-if="item.issue"></view>
<view class='bnt b-color' v-else>{{coupon.statusTile || '立即领取'}}</view>
</view>
</view>
</view>
</view>
<!-- 无优惠券 -->
<view class='pictrue' v-else>
<image src='../../static/images/noCoupon.png'></image>
</view>
</view>
<view class='mask' catchtouchmove="true" :hidden='coupon.coupon==false' @click='close'></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { setCouponReceive } from '@/api/api.js';
import { mapGetters } from "vuex";
import { HTTP_REQUEST_URL } from '@/config/app';
export default {
props: {
// 0=,1=使
openType: {
type: Number,
default: 0,
},
coupon: {
type: Object,
default: function() {
return {};
}
},
showTitle: {
type: Number,
default: 1,
},
isShop: {
type: Number,
default: 0,
},
},
filters: {
timeYMD: function (value) {
if(value){
var newDate=/\d{4}-\d{1,2}-\d{1,2}/g.exec(value)
return newDate[0]
}
}
},
computed: mapGetters(['viewColor','keyColor']),
data() {
return {
domain: HTTP_REQUEST_URL,
tabList:['商品券','店铺券'],
tabIndex:this.isShop,
couponArr:[],
};
},
mounted() {
this.$nextTick(function(){
this.couponArr = this.coupon.list
})
},
methods: {
close: function() {
this.$emit('ChangCouponsClone');
},
getCouponUser: function(index, item) {
let that = this;
if (item.issue) return true;
switch (this.openType) {
case 0:
//
setCouponReceive(item.coupon_id).then(res => {
item.issue = true
that.$emit('ChangCouponsUseState', index);
that.$util.Tips({
title: "领取成功"
});
that.$emit('ChangCoupons', item);
})
break;
case 1:
that.$emit('ChangCoupons', index);
break;
}
},
bindTab(item,index){
this.tabIndex = index
this.filterArray()
}
}
}
</script>
<style scoped lang="scss">
.animated{
animation-duration:.3s
}
.title{
display: flex;
border-radius: 16rpx 16rpx 0 0;
.item{
position: relative;
flex: 1;
font-size: 28rpx;
color: #999999;
&::after{
content: ' ';
position: absolute;
left: 50%;
bottom: 18rpx;
width:50rpx;
height:5rpx;
background:transparent;
border-radius:3px;
transform: translateX(-50%);
}
&.on{
color: #282828;
&::after{
background: var(--view-theme);
}
}
}
}
.b-color {
background-color: var(--view-theme);
}
.coupon-list{
padding: 30rpx;
.item{
box-shadow:0px 2px 10px 0px rgba(0, 0, 0, 0.06);
}
}
.coupon-list-window {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
border-radius: 16rpx 16rpx 0 0;
z-index: 555;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
}
.coupon-list-window.on {
animation: aminup ;
}
.coupon-list-window .title {
height: 106rpx;
width: 100%;
text-align: center;
line-height: 106rpx;
font-size: 32rpx;
font-weight: bold;
position: relative;
border: 1px solid #f5f5f5;
}
.coupon-list-window .title .iconfont {
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
font-size: 35rpx;
color: #8a8a8a;
font-weight: normal;
}
.coupon-list-window .coupon-list {
margin: 0 0 50rpx 0;
height: 550rpx;
overflow: auto;
}
.coupon-list-window .pictrue {
width: 414rpx;
height: 336rpx;
margin: 0 auto 50rpx auto;
}
.coupon-list-window .pictrue image {
width: 100%;
height: 100%;
}
.pic-num {
color: #fff;
font-size: 24rpx;
}
.line-title {
width: 90rpx;
padding: 0 10rpx;
box-sizing: border-box;
background: var(--view-minorColor);
border: 1px solid var(--view-theme);
opacity: 1;
border-radius: 20rpx;
font-size: 20rpx;
color: var(--view-theme);
margin-right: 12rpx;
}
.line-title.gray {
border-color: #BBB;
color: #bbb;
background-color: #F5F5F5;
}
</style>

129
components/cx-navTitle.vue Normal file
View File

@ -0,0 +1,129 @@
<template>
<!-- tab选项卡滑动切换 -->
<view class="my-tab" ref="myTabRef">
<view class="my-tab-item" v-for="(item, index) in tabs" :ref="`tab${item.name}Ref`"
:class="{ active: item.name === activeItem }" :key="index">
<view class="my-tab-text" ref="tabName" @click="tabClick(item,index)">
<view class="name">{{ item.label }}</view>
<view class="xian" v-if='isshow'></view>
</view>
</view>
</view>
</template>
<script>
/*
tabs -- 传入标签名 array类型 : tabs: [{name: "tabOne",label: "全部"},{...}]
activeItem -- 默认第一个class名 string
@tabClick -- 自定义点击事件 回传用到 做逻辑判断
标签大小默认颜色选中颜色下边框线等样式已在css中注释请根据注释修改即可
*/
export default {
name: "cx-navTitle",
props: {
tabs: { //
type: Array,
default: []
},
activeItem: { // class
type: String,
default: ''
},
show: {
type: Boolean,
default: ''
},
},
data() {
return {
isshow: true,
};
},
mounted() {
this.isshow = this.show
},
methods: {
// tab
tabClick(item, index) {
this.$emit('tabClick', item) //
//
this.scrollLeftTo(item.name);
},
//
scrollLeftTo(name) {
const ref = `tab${name}Ref`;
// myTabRefDOMmy-tab
const nav = this.$refs.myTabRef.$el;
// tabDOMmy-tab-item
const title = this.$refs[ref][0].$el;
//
// #ifdef H5
const to = title.offsetLeft - (nav.offsetWidth - title.offsetWidth) / 2;
nav.scrollLeft = to;
// #endif
},
},
};
</script>
<style lang="scss">
.my-tab {
width: 720rpx;
margin: 0 auto;
// height:80rpx;
// background: #ffffff;
// line-height:80rpx;
// border:1px solid red;
display: flex;
overflow-x: scroll;
padding-right: 0rpx;
scroll-behavior: smooth; //
font-size: 32rpx;
font-family: PingFang-SC-Heavy;
.my-tab-item {
padding: 20rpx 35rpx; // --
color: #707070; // --
// height: 0rpx;
text-align: center;
flex: 1 0 auto;
&.active {
color: #333333; // --
font-family: PingFang-SC-Heavy;
font-weight: 600;
position: relative;
.my-tab-text {
.xian {
position: relative;
top: 0rpx; //线 --
z-index: 8;
width: 26px;
margin: 0 auto;
border: 1rpx solid #F84221; //线 --
border-radius: 50rpx;
padding: 0rpx 30rpx;
opacity: 0.6; //线 --
}
.name {
position: relative;
z-index: 9;
font-size: 32rpx;
font-family: PingFang SC;
font-weight: 500;
color: #F84221;
color: #F84221;
}
}
}
}
}
//
::-webkit-scrollbar {
height: 0;
width: 0;
color: transparent;
}
</style>

View File

@ -0,0 +1,153 @@
<template>
<view :style="viewColor">
<!-- 选择送货方式 -->
<view class="mask-box">
<view class="bg" v-if="isShowDiscount"></view>
<view class="mask-content animated" :class="{slideInUp:isShowDiscount}">
<view class="title-bar">
优惠明细
<view class="close" @click="closeShowBox"><text class="iconfont icon-guanbi"></text></view>
</view>
<view class="box">
<view class="check-item">
<view>商品售价</view>
<view class="radio">
{{couponData.total_price}}
</view>
</view>
<view v-if="couponData.order_total_integral_price>0" class="check-item">
<view>积分抵扣</view>
<view class="radio">
-{{couponData.order_total_integral_price}}
</view>
</view>
<view v-if="couponData.total_platform_coupon_price>0" class="check-item">
<view>平台优惠金额</view>
<view class="radio">
-{{ couponData.total_platform_coupon_price }}
</view>
</view>
<view v-if="couponData.order_coupon_price>0" class="check-item">
<view>店铺优惠金额</view>
<view class="radio">
-{{ couponData.order_coupon_price }}
</view>
</view>
<view v-if="couponData.order_svip_discount>0" class="check-item">
<view>SVIP优惠金额</view>
<view class="radio">
-{{ couponData.order_svip_discount }}
</view>
</view>
<view v-if="couponData.total_coupon>0" class="check-item total">
<view>共优惠</view>
<view class="radio">
-{{ couponData.total_coupon}}
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { mapGetters } from "vuex";
export default{
name:'Discount',
props:{
isShowDiscount:{
type:Boolean,
default:false
},
couponData:{
type:Object,
default:function(){
return {}
}
}
},
computed: mapGetters(['viewColor']),
data(){
return {}
},
created() {},
methods:{
//
closeShowBox(){
this.$emit('close')
},
}
}
</script>
<style lang="scss">
.mask-box{
.bg{
z-index: 9;
position: fixed;
left: 0;
bottom: 100rpx;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
}
.mask-content{
z-index: 10;
position: fixed;
left: 0;
bottom: 100rpx;
width: 100%;
background-color: #f5f5f5;
border-radius: 16rpx 16rpx 0 0;
transform: translate3d(0, 200%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
.title-bar{
position: relative;
text-align: center;
padding: 30rpx 0;
margin-bottom: 20rpx;
font-size: 32rpx;
color: #282828;
.close{
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
.iconfont{
color: #8A8A8A;
}
}
}
.box{
padding: 0 30rpx 60rpx;
.check-item{
display: flex;
align-items: center;
justify-content: space-between;
height: 40rpx;
margin-bottom: 50rpx;
font-size: 28rpx;
&.total{
font-weight: bold;
font-size: 32rpx;
.radio{
color: var(--view-priceColor);
}
}
}
}
}
}
.animated {
animation-duration: .3s
}
</style>

View File

@ -0,0 +1,448 @@
<template>
<view
class="e-stat__select"
:style="{ width: width, minWidth: minWidth }">
<!-- 主体区域 -->
<view class="e-select-main">
<view
class="e-select"
:class="{ 'e-select-disabled': disabled }">
<view
class="e-select__input-box"
@click="toggleSelector">
<!-- 微信小程序input组件在部分安卓机型上会出现文字重影placeholder抖动问题2019年时微信小程序就有这个问题一直没修复估计短时间内也别指望修复了 -->
<input
class="e-select__input-text"
:placeholder="placeholder"
v-model="currentData"
@input="filter"
v-if="search && !disabled" />
<view
class="e-select__input-text"
v-else>
{{ currentData || currentData === 0 ? currentData : placeholder }}
</view>
<!-- 用一个更大的盒子包裹图标,便于点击 -->
<view
class="e-select-icon"
@click.stop="clearVal"
v-if="currentData && clear && !disabled">
<uni-icons
type="clear"
color="#e1e1e1"
size="18"></uni-icons>
</view>
<view
class="e-select-icon"
@click.stop="toggleSelector"
v-else>
<uni-icons
size="14"
color="#999"
type="top"
class="arrowAnimation"
:class="showSelector ? 'top' : 'bottom'"></uni-icons>
</view>
</view>
<!-- 全屏遮罩-->
<view
class="e-select--mask"
v-if="showSelector"
@click="toggleSelector" />
<!-- 选项列表 这里用v-show是因为微信小程序会报警告 [Component] slot "" is not foundv-if会导致开发工具不能正确识别到slot -->
<!-- https://developers.weixin.qq.com/community/minihome/doc/000c8295730700d1cd7c81b9656c00 -->
<view
class="e-select__selector"
v-show="showSelector">
<!-- 三角小箭头 -->
<view class="e-popper__arrow"></view>
<scroll-view
scroll-y="true"
:scroll-top="scrollTop"
class="e-select__selector-scroll"
:scroll-into-view="scrollToId"
:scroll-with-animation="scrollWithAnimation"
v-if="showSelector">
<view
class="e-select__selector-empty"
v-if="currentOptions.length === 0">
<text>{{ emptyTips }}</text>
</view>
<!-- 非空,渲染选项列表 -->
<view
v-else
class="e-select__selector-item"
:class="[
{ highlight: currentData == item[props.text] },
{
'e-select__selector-item-disabled': item[props.disabled],
},
]"
v-for="(item, index) in currentOptions"
:key="index"
@click="change(item, index)">
<text>{{ item[props.text] }}</text>
<view
id="scrollToId"
v-if="currentData == item[props.text]"></view>
</view>
</scroll-view>
<slot />
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'e-select',
data() {
return {
//
showSelector: false,
//
currentOptions: [],
//
currentData: '',
//
oldScrollTop: 0,
//
scrollTop: 0,
// id
scrollToId: '',
//
scrollWithAnimation: false,
};
},
props: {
//
options: {
type: Array,
default() {
return [];
},
},
//
props: {
type: Object,
default: function () {
return {
text: 'text',
value: 'value',
disabled: 'disabled',
};
},
},
// vue2 v-model
value: {
type: [String, Number],
default: '',
},
// vue3 v-model
modelValue: {
type: [String, Number],
default: '',
},
//
placeholder: {
type: String,
default: '请选择',
},
//
width: {
type: String,
default: '100%',
},
//
minWidth: {
type: String,
default: '120rpx',
},
//
emptyTips: {
type: String,
default: '暂无选项',
},
//
clear: {
type: Boolean,
default: false,
},
//
disabled: {
type: Boolean,
default: false,
},
//
search: {
type: Boolean,
default: true,
},
//
animation: {
type: Boolean,
default: true,
},
},
watch: {
options: {
handler() {
this.currentOptions = this.options;
this.initData();
},
immediate: true,
deep: true,
},
modelValue: {
handler() {
this.initData();
},
immediate: true,
},
value: {
handler() {
this.initData();
},
immediate: true,
},
},
methods: {
/** 处理数据此函数用于兼容vue2 vue3 */
initData() {
this.currentData = '';
// vue2
if (this.value || this.value === 0) {
for (let item of this.options) {
if (item[this.props.value] === this.value) {
this.currentData = item[this.props.text];
this.$emit('getText', this.currentData);
return;
}
}
}
// vue3
if (this.modelValue || this.modelValue === 0) {
for (let item of this.options) {
if (item[this.props.value] === this.modelValue) {
this.currentData = item[this.props.text];
this.$emit('getText', this.currentData);
return;
}
}
}
},
/** 过滤选项列表,会自动回到顶部 */
filter() {
this.$emit('getText', this.currentData);
if (this.currentData) {
this.currentOptions = this.options.filter((item) => {
return item[this.props.text].indexOf(this.currentData) > -1;
});
} else {
this.currentOptions = this.options;
}
// scrollTop
this.scrollTop = 1;
this.$nextTick(() => {
this.scrollTop = 0;
});
},
/** 改变值 */
change(item, index) {
if (item[this.props.disabled]) return;
const data = {
...item,
index,
};
this.$emit('change', data);
this.emit(data);
this.toggleSelector();
},
/** 传递父组件值 */
emit(item) {
this.$emit('input', item[this.props.value]);
this.$emit('update:modelValue', item[this.props.value]);
},
/** 清空值 */
clearVal() {
this.$emit('change', 'clear');
this.$emit('input', '');
this.$emit('update:modelValue', '');
},
/** 切换下拉显示 */
toggleSelector() {
if (this.disabled) return;
this.showSelector = !this.showSelector;
if (this.showSelector) {
this.currentOptions = this.options;
// scrollToIdscroll-to-view
this.scrollToId = '';
this.$nextTick(() => {
this.scrollToId = 'scrollToId';
// filter
if (this.animation) {
setTimeout(() => {
//
this.scrollWithAnimation = true;
}, 100);
}
});
} else {
//
this.scrollWithAnimation = false;
}
},
},
};
</script>
<style lang="scss" scoped>
.e-stat__select {
display: flex;
align-items: center;
cursor: pointer;
box-sizing: border-box;
width: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.e-select-main {
width: 100%;
}
.e-select-disabled {
background-color: #f5f7fa;
cursor: not-allowed;
}
.e-select {
font-size: 14px;
box-sizing: border-box;
border-radius: 4px;
padding: 0 5px;
position: relative;
display: flex;
user-select: none;
flex-direction: row;
align-items: center;
border: 1px solid #dcdfe6;
border-bottom: solid 1px #dddddd;
.e-select__input-box {
width: 100%;
min-height: 34px;
position: relative;
display: flex;
flex: 1;
flex-direction: row;
align-items: center;
.e-select-icon {
width: 50px;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.arrowAnimation {
transition: transform 0.3s;
}
.top {
transform: rotateZ(0deg);
}
.bottom {
transform: rotateZ(180deg);
}
.e-select__input-text {
color: #303030;
padding-left: 7px;
width: 100%;
color: #333;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
overflow: hidden;
}
.e-select__input-placeholder {
padding-left: 7px;
color: #666;
}
}
.e-select--mask {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
z-index: 999;
}
.e-select__selector {
box-sizing: border-box;
position: absolute;
top: calc(100% + 12px);
left: 0;
width: 100%;
background-color: #ffffff;
border: 1px solid #ebeef5;
border-radius: 6px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
z-index: 999;
padding: 4px 4px;
transition: all 2s;
.e-popper__arrow,
.e-popper__arrow::after {
position: absolute;
display: block;
width: 0;
height: 0;
left: 50%;
border-color: transparent;
border-style: solid;
border-width: 6px;
}
.e-popper__arrow {
filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
top: -6px;
left: 50%;
transform: translateX(-50%);
margin-right: 3px;
border-top-width: 0;
border-bottom-color: #ebeef5;
}
.e-popper__arrow::after {
content: ' ';
top: 1px;
margin-left: -6px;
border-top-width: 0;
border-bottom-color: #fff;
}
.e-select__selector-scroll {
max-height: 200px;
box-sizing: border-box;
.e-select__selector-empty,
.e-select__selector-item {
display: flex;
cursor: pointer;
line-height: 34px;
font-size: 14px;
text-align: center;
padding: 0px 10px;
}
.e-select__selector-item:hover {
background-color: #f9f9f9;
}
.e-select__selector-empty:last-child,
.e-select__selector-item:last-child {
border-bottom: none;
}
.e-select__selector-item-disabled {
color: #b1b1b1;
cursor: not-allowed;
}
.highlight {
color: #409eff;
font-weight: bold;
background-color: #f5f7fa;
border-radius: 3px;
}
}
}
}
</style>

View File

@ -0,0 +1,171 @@
<template>
<view class="easy-loadimage" :id="uid">
<image class="origin-img" :src="imageSrc" mode="aspectFill" v-if="loadImg&&!isLoadError" v-show="showImg"
:class="{'no-transition':!openTransition,'show-transition':showTransition&&openTransition}"
@load="handleImgLoad" @error="handleImgError">
</image>
<view class="loadfail-img" v-else-if="isLoadError"></view>
<view :class="['loading-img','spin-circle',loadingMode]" v-show="!showImg&&!isLoadError"></view>
</view>
</template>
<script>
import { throttle } from '@/libs/uniApi';
// 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,
},
mode:{
type: String,
},
loadingMode:{
type: String,
default:'looming-gray'
},
openTransition:{
type: Boolean,
default:true,
},
viewHeight:{
type:Number,
default() {
return uni.getSystemInfoSync().windowHeight;
}
}
},
data(){
const that = this;
return {
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)
}
},
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>
/* 官方优化图片tips */
image{
/* will-change: transform */
}
/* 渐变过渡效果处理 */
image.origin-img{
width: 100%;
height: 100%;
opacity: 0.3;
max-height: 360rpx;
}
image.origin-img.show-transition{
/* transition: opacity .5s; */
opacity: 1;
}
image.origin-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%;
}
/* 转圈 */
.spin-circle{
background: url('~@/static/easy-loadimage/loading.gif') no-repeat center;
background-size: 60%;
}
/* 动态灰色若隐若现 */
.looming-gray{
animation: looming-gray 1s infinite linear;
background-color: #e3e3e3;
}
@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>

View File

@ -0,0 +1,277 @@
<template>
<view :style="viewColor">
<view class="product-window" :class="{'on':isShow}">
<view class="iconfont icon-guanbi" @click="closeAttr"></view>
<view class="mp-data">
<image :src="routine_logo" mode=""></image>
<text class="mp-name">{{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>
<view class="nickname edit-box">
<view class="left">
<view class="head">昵称</view>
<view class='input'><input type='nickname' placeholder-class="pl-sty"
placeholder="请输入昵称" name='nickname' :maxlength="16"
:value='userInfo.nickname'></input>
</view>
</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 { mapGetters } from "vuex";
import { configMap } from '@/utils';
import Cache from '@/utils/cache';
import { editAvatar } from '@/api/user.js';
export default {
props: {
isShow: {
type: Number,
value: 0
}
},
data() {
return {
defHead: require('@/static/images/def_avatar.png'),
mp_is_new: this.$Cache.get('MP_VERSION_ISNEW') || false,
userInfo: {
avatar: '',
nickname: '',
},
canvasStatus: false,
};
},
computed: configMap({routine_logo: '',site_name: ''} ,mapGetters(['viewColor','keyColor'])),
mounted() {
},
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.path
}, (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
editAvatar(this.userInfo).then(res => {
this.$emit('editSuccess')
return that.$util.Tips({
title: res.message,
icon: 'success'
}, {
tab: 3
});
}).catch(msg => {
return that.$util.Tips({
title: msg || '保存失败'
}, {
tab: 3,
url: 1
});
});
}
}
}
</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: 20rpx 20rpx 0 0;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
padding: 38rpx 40rpx;
.icon-guanbi {
position: absolute;
top: 40rpx;
right: 40rpx;
font-size: 24rpx;
font-weight: bold;
color: #999;
}
.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: #07C160;
color: #fff;
}
}
}
</style>

45
components/emptyPage.vue Normal file
View File

@ -0,0 +1,45 @@
<template>
<view class="empty-box">
<image src="/static/images/empty-box.png"></image>
<view class="txt">{{title}}</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
export default{
props: {
title: {
type: String,
default: '暂无记录',
},
},
}
</script>
<style lang="scss">
.empty-box{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 200rpx;
image{
width: 414rpx;
height: 240rpx;
}
.txt{
font-size: 26rpx;
color: #999;
}
}
</style>

View File

@ -0,0 +1,216 @@
<template>
<view :style="viewColor">
<view class="guaranee_tel">
<view class="popup" :class="{ on: isGuarantee }">
<view class="title">保障说明<text class="iconfont icon-guanbi" @click="close"></text></view>
<view v-if="guarantee.length" class="content">
<view v-for="(item,index) in guarantee" class="item">
<view class="name"><image :src='item.image' class="image"></image>{{item.guarantee_name}}</view>
<view class="info" style="white-space: pre-line;">{{item.guarantee_info}}</view>
</view>
</view>
<button @tap="close">确定</button>
</view>
<view class="popup" :class="{ on: isShipping }">
<view class="title">运费说明<text class="iconfont icon-guanbi" @click="close"></text></view>
<view class="content" style="white-space: pre-line;">
{{shipping}}
</view>
<button @tap="close">确定</button>
</view>
</view>
<view class='mask' catchtouchmove="true" :hidden='showMask==false' @tap='close'></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { mapGetters } from "vuex";
export default {
props: {
shipping: {
type: String,
},
guarantee: {
type: Array,
}
},
computed: mapGetters(['viewColor']),
data() {
return {
isShipping: false,
isGuarantee: false,
showMask: false,
}
},
watch: {
},
onLoad(option) {
},
onShow(){
},
methods: {
showShippingTel() {
this.isShipping = true;
this.showMask = true;
},
showGuaranteeTel() {
this.isGuarantee = true;
this.showMask = true;
},
close: function() {
this.isShipping = false;
this.isGuarantee = false;
this.showMask = false;
}
}
}
</script>
<style scoped lang="scss">
.guaranee_tel{
position: fixed;
bottom: 0;
width: 100%;
left: 0;
background-color: #fff;
z-index: 300;
border-radius: 16rpx 16rpx 0 0;
padding-bottom: 20rpx;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
}
.guaranee_tel.on {
transform: translate3d(0, 0, 0);
}
.guaranee_tel .title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
height: 123rpx;
line-height: 123rpx;
position: relative;
}
.guaranee_tel .title .iconfont {
position: absolute;
right: 30rpx;
color: #8a8a8a;
font-size: 35rpx;
}
.popup {
position: fixed;
bottom: 0;
left: 0;
z-index: 99;
width: 100%;
padding-bottom: 40rpx;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
background-color: #F5F5F5;
overflow: hidden;
transform: translateY(100%);
transition: 0.3s;
}
.popup.on {
transform: translateY(0);
}
.popup .title {
position: relative;
height: 137rpx;
font-size: 32rpx;
line-height: 137rpx;
text-align: center;
}
.popup scroll-view {
height: 466rpx;
padding-right: 30rpx;
padding-left: 30rpx;
box-sizing: border-box;
}
.popup .icon-guanbi {
position: absolute;
top: 50%;
right: 30rpx;
z-index: 2;
transform: translateY(-50%);
font-size: 30rpx;
color: #707070;
cursor: pointer;
}
.popup .content{
padding: 0 50rpx;
color: #999999;
max-height: 800rpx;
overflow-y: scroll;
.item{
margin-bottom: 70rpx;
}
.image{
width: 30rpx;
height: 30rpx;
margin-right: 20rpx;
position: relative;
top: 4rpx;
}
.name{
color: #282828;
flex: 1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.info{
margin-top: 15rpx;
}
}
.popup button {
height: 86rpx;
border-radius: 43rpx;
margin-right: 30rpx;
margin-left: 30rpx;
background-image: linear-gradient(to right, var(--view-bntColor21) 0%, var(--view-bntColor22) 100%);;
font-size: 30rpx;
line-height: 86rpx;
color: #FFFFFF;
margin-top: 80rpx;
}
.popup .text .acea-row {
display: inline-flex;
max-width: 100%;
}
.popup .label {
width: 56rpx;
height: 28rpx;
border: 1px solid #E93323;
margin-left: 18rpx;
font-size: 20rpx;
line-height: 26rpx;
text-align: center;
color: #E93323;
}
.popup .type {
width: 124rpx;
height: 42rpx;
margin-top: 14rpx;
background-color: #FCF0E0;
font-size: 24rpx;
line-height: 42rpx;
text-align: center;
color: #D67300;
}
.popup .type.special {
background-color: #FDE9E7;
color: #E93323;
}
</style>

View File

@ -0,0 +1,185 @@
<template>
<view class='goodList' :style="viewColor">
<block v-for="(item,index) in bastList" :key="index">
<view @click="goDetail(item)" class='item acea-row' hover-class="none">
<view class='pictrue'>
<image :src='item.image'></image>
<text class="pictrue_log pictrue_log_class" v-if="item.activity && item.activity.type === '1'">秒杀</text>
<text class="pictrue_log pictrue_log_class" v-if="item.activity && item.activity.type === '2'">砍价</text>
<text class="pictrue_log pictrue_log_class" v-if="item.activity && item.activity.type === '3'">拼团</text>
</view>
<view class='underline'>
<view class='line1'>
{{item.store_name}}
</view>
<view class="item_line">
<text v-if="item.merchant.type_name && item.product_type == 0" class="font-bg-red bt-color">{{item.merchant.type_name}}</text>
<text v-else-if="item.merchant.is_trader && item.product_type == 0" class="font-bg-red bt-color">自营</text>
<text v-if="item.product_type != 0" :class="'font_bg-red bt-color type'+item.product_type">{{item.product_type == 1 ? "秒杀" : item.product_type == 2 ? "预售" : item.product_type == 3 ? "助力" : item.product_type == 4 ? "拼团" : ""}}</text>
<text v-if="item.issetCoupon" class="coupon">领券购买更优惠</text>
</view>
<view class='money'><text class='num'>{{item.price}}</text></view>
</view>
<view class='gobuy acea-row row-center-wrapper'>去购买</view>
</view>
</block>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import {mapGetters} from "vuex";
import { goShopDetail } from '@/libs/order.js'
import {initiateAssistApi} from '@/api/activity.js';
import { toLogin } from '@/libs/login.js';
export default {
computed: mapGetters(['uid','viewColor']),
props: {
status: {
type: Number,
default: 0,
},
bastList: {
type: Array,
default: function() {
return [];
}
},
isLogin:{
type: Boolean,
default: false
}
},
data() {
return {
};
},
methods: {
goDetail(item){
goShopDetail(item, this.uid).then(res => {
if (this.isLogin) {
initiateAssistApi(item.activity_id).then(res => {
let id = res.data.product_assist_set_id;
uni.hideLoading();
uni.navigateTo({
url: '/pages/activity/assist_detail/index?id=' + id
});
}).catch((err) => {
uni.showToast({
title: err,
icon: 'none'
})
});
} else {
// #ifdef H5 || APP-PLUS
toLogin();
// #endif
// #ifdef MP
this.$emit('isShowAuth', true);
this.$emit('isAuto', true);
// #endif
}
})
}
}
}
</script>
<style scoped lang='scss'>
.bt-color {
background-color: var(--view-theme);
border: 1rpx solid var(--view-theme);
&.type2{
background-color: #FD6523;
border: 1rpx solid #FD6523;
}
}
.goodList .item {
position: relative;
padding: 20rpx;
margin-bottom: 20rpx;
background: #fff;
justify-content: space-between;
border-radius: 16rpx;
}
.goodList .item .pictrue {
width: 180rpx;
height: 180rpx;
position: relative;
}
.goodList .item .pictrue image {
width: 100%;
height: 100%;
border-radius: 6rpx;
}
.goodList .item .pictrue .numPic {
position: absolute;
left: 7rpx;
top: 7rpx;
width: 50rpx;
height: 50rpx;
border-radius: 50%;
}
.goodList .item .underline{
width: 450rpx;
font-size: 30rpx;
color: #222;
position: relative;
}
.goodList .item .item_line{
margin-top: 10rpx;
}
.goodList .item .item_line .coupon{
font-size: 22rpx;
margin-left: 4rpx;
}
.goodList .item .money {
font-size: 26rpx;
font-weight: bold;
position: absolute;
bottom: 10rpx;
left: 0;
color: var(--view-priceColor);
}
.goodList .item .money .num {
font-size: 34rpx;
}
.goodList .item .vip-money {
font-size: 24rpx;
color: #282828;
font-weight: bold;
margin-top: 15rpx;
}
.goodList .item .vip-money image {
width: 46rpx;
height: 21rpx;
margin-left: 5rpx;
}
.goodList .item .vip-money .num {
font-size: 22rpx;
color: #aaa;
font-weight: normal;
margin: -2rpx 0 0 22rpx;
}
.goodList .item .gobuy {
position: absolute;
right: 30rpx;
padding: 6rpx 20rpx;
border-radius: 50%;
font-size: 22rpx;
bottom: 30rpx;
color: #fff;
background: var(--view-theme);
border-radius: 27rpx;
}
</style>

213
components/goodsCard.vue Normal file
View File

@ -0,0 +1,213 @@
<template>
<view>
<block>
<view class='lists'>
<view v-for="(item,index) in productList" class="card" :key="index" @click="godDetail(item)">
<view class='pictrue on'>
<u-image :src='item.image' width="336.45rpx" height="336.45rpx"> </u-image>
</view>
<view class="goods_content">
<view class='name line1'>
<text class="text-ellipsis">{{item.store_name}}</text>
</view>
<view class="item_tags">
<text v-if="item.merchant.type_name && item.product_type == 0"
class="store_type">{{item.merchant.type_name}}</text>
<text v-else-if="item.merchant.is_trader && item.product_type == 0"
class="store_type">自营</text>
<text v-if="item.product_type != 0"
:class="'font_bg-red bt-color type'+item.product_type">{{item.product_type == 1 ? "秒杀" : item.product_type == 2 ? "预售" : item.product_type == 3 ? "助力" : item.product_type == 4 ? "拼团" : ""}}</text>
<text class="tags_item ticket" v-if="item.issetCoupon">领券</text>
<text class="tags_item delivery" v-if="item.delivery_free == 1">包邮</text>
</view>
<view class="score"><text
style="font-style: italic;color: #FF6D20;margin-right: 20rpx;font-size: 30rpx;">{{item.rate}}</text>
{{item.reply_count}}评论
</view>
<view class='money'>
<text
class='num'>{{item.price.substring(0, item.price.length - 2)}}</text><text>{{item.price.slice(-2)}}</text>
</view>
<view class="company" v-if="item.merchant" @click.stop="goShop(item.mer_id)">
<text class="line1">{{item.merchant.mer_name}}</text>
<view class="flex">
<text class="iconfont icon-xiangyou"></text>
</view>
</view>
</view>
<!-- 返佣 -->
<!-- <block v-if="item.max_extension>0 && (item.product_type == 0 || item.product_type == 2)">
<view class="foot-bar on">
最高赚 ¥{{item.max_extension}}
</view>
</block> -->
</view>
</view>
<!-- <view class='noCommodity' v-if="productList.length==0">
<view class='pictrue' style=" margin: 60rpx auto;">
<image src='/static/images/noCart.png'></image>
<view>暂无商品</view>
</view>
<recommend v-if="recommend_switch == 1" :hostProduct="hostProduct" :isLogin="isLogin"></recommend>
</view> -->
</block>
</view>
</template>
<script>
import {
cloudWarehouse
} from '@/api/api.js'
import {
goShopDetail
} from '@/libs/order.js'
export default {
name: "goodsCard",
props: {
where: {
type: Object,
required: true
}
},
data() {
return {
is_switch: false,
productList: "",
};
},
mounted() {
this.$watch('where', (newValue, oldValue) => {
newValue.category_id ? this.get_product_list() : this.productList = []
}, {
deep: true
});
},
methods: {
test() {
// this.get_product_list()
// console.log(this.where)
},
godDetail(item) {
goShopDetail(item, this.uid).then(res => {
if (this.isLogin) {
initiateAssistApi(item.activity_id).then(res => {
let id = res.data.product_assist_set_id;
uni.hideLoading();
uni.navigateTo({
url: '/pages/activity/assist_detail/index?id=' + id
});
}).catch((err) => {
uni.showToast({
title: err,
icon: 'none'
})
});
} else {
this.isAuto = true;
this.isShowAuth = true
}
})
},
//
goShop(id) {
if (this.hide_mer_status != 1) {
uni.navigateTo({
url: `/pages/store/home/index?id=${id}`
})
}
},
get_product_list: function() {
let that = this;
cloudWarehouse(that.where).then(res => {
that.productList = res.data.list
}).catch(err => {
that.loading = false;
that.loadTitle = '加载更多';
});
},
}
}
</script>
<style lang="scss" scoped>
.lists {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
background-color: #F4F7FE;
.card {
border-radius: 21.03rpx 21.03rpx 21.03rpx 21.03rpx;
overflow: hidden;
margin-top: 20rpx;
background-color: white;
// width: 336.45rpx;
.store_type {
background: linear-gradient(to bottom, #6DD5FA, #3274F9);
color: white;
border-radius: 10.51rpx 10.51rpx 10.51rpx 10.51rpx;
padding: 2rpx 8rpx;
font-size: 22rpx;
}
.goods_content {
background-color: white;
padding: 25rpx 15rpx;
}
.name {
font-weight: bold;
.textellipsis {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
// font-weight: bold;
}
}
.item_tags {
margin: 5rpx 0;
}
.score {
color: #B3B3B3;
font-size: 22.78rpx;
}
.money {
color: red;
margin: 5rpx 0;
.num {
font-size: 36rpx;
font-weight: bold;
}
}
.company {
background-color: #F4F7FE;
display: flex;
justify-content: space-between;
padding: 5rpx 14rpx;
border-radius: 19.28rpx 19.28rpx 19.28rpx 19.28rpx;
}
// width: 40vw;
}
}
</style>

118
components/home/index.vue Normal file
View File

@ -0,0 +1,118 @@
<template>
<view style="touch-action: none;" :style="viewColor">
<view class="home" style="position:fixed;" :style="{ top: top + 'px', bottom: bottom }" id="right-nav"
@touchmove.stop.prevent="setTouchMove">
<view class="homeCon" :class="homeActive === true ? 'on' : ''" v-if="homeActive">
<navigator hover-class='none' url='/pages/index/index' open-type='switchTab'
class='iconfont icon-shouye-xianxing'></navigator>
<navigator hover-class='none' url='/pages/order_addcart/order_addcart' open-type='navigate'
class='iconfont icon-caigou-xianxing'></navigator>
<navigator hover-class='none' url='/pages/user/index' open-type='switchTab' class='iconfont icon-yonghu1'>
</navigator>
</view>
<view @click="open" class="pictrueBox">
<view class="pictrue">
<image :src="homeActive === true ? '/static/images/navbtn_open.gif' : '/static/images/navbtn_close.gif'"
class="image pictruea" />
</view>
</view>
</view>
</view>
</template>
<script>
import { mapGetters } from "vuex";
import { HTTP_REQUEST_URL } from '@/config/app';
export default {
name: "Home",
props: {},
data: function() {
return {
domain: HTTP_REQUEST_URL,
top: "",
bottom: ""
};
},
computed: mapGetters(["homeActive", "viewColor", "keyColor"]),
methods: {
setTouchMove(e) {
var that = this;
if (e.touches[0].clientY < 545 && e.touches[0].clientY > 66) {
that.top = e.touches[0].clientY
that.bottom = "auto";
}
},
open: function() {
this.homeActive ? this.$store.commit("CLOSE_HOME") : this.$store.commit("OPEN_HOME");
}
},
created() {
this.bottom = "50px";
}
};
</script>
<style scoped>
.pictrueBox {
width: 130rpx;
height: 120rpx;
}
/*返回主页按钮*/
.home {
position: fixed;
color: white;
text-align: center;
z-index: 9999;
right: 15rpx;
display: flex;
}
.home .homeCon {
border-radius: 50rpx;
opacity: 0;
height: 0;
color: #e93323;
width: 0;
}
.home .homeCon.on {
opacity: 1;
animation: bounceInRight 0.5s cubic-bezier(0.215, 0.610, 0.355, 1.000);
width: 300rpx;
height: 86rpx;
margin-bottom: 20rpx;
display: flex;
justify-content: center;
align-items: center;
background: var(--view-theme);
}
.home .homeCon .iconfont {
font-size: 48rpx;
color: #fff;
display: inline-block;
margin: 0 auto;
}
.home .pictrue {
width: 86rpx;
height: 86rpx;
border-radius: 50%;
margin: 0 auto;
background-color: var(--view-theme);
box-shadow: 0 5rpx 12rpx rgba(0, 0, 0, 0.5);
}
.home .pictrue .image {
width: 100%;
height: 100%;
}
.pictruea {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
vertical-align: middle;
}
</style>

176
components/index.vue Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,262 @@
<template>
<view class="orderGoods" :style="viewColor">
<view class='goodWrapper'>
<view class="title">{{cartInfo.length}}件商品</view>
<view v-for="(item,index) in cartInfo" :key="index">
<view class='item acea-row row-between-wrapper'>
<view class='pictrue' @click="jumpCon(item.product_id)">
<image :src='(item.cart_info.productAttr && item.cart_info.productAttr.image) || item.cart_info.product.image' ></image>
</view>
<view class='text'>
<view class='acea-row row-between-wrapper'>
<view class='name line1'>{{item.cart_info.product.store_name}}</view>
<view class='num'>x {{item.product_num}}</view>
</view>
<view class='attr line1' v-if="item.cart_info.productAttr.sku">{{item.cart_info.productAttr.sku}}</view>
<view class='money' >{{item.cart_info.productAttr.price}}</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { openOrderRefundSubscribe } from '@/utils/SubscribeMessage.js';
import { mapGetters } from "vuex";
export default {
props: {
evaluate: {
type: Number,
default: 0,
},
activityType: {
type: Number,
default: 0,
},
cartInfo: {
type: Array,
default: function() {
return [];
}
},
orderId: {
type: String,
default: '',
},
jump: {
type: Boolean,
default: false,
},
orderData: {
type: Object,
default: function() {
return {};
}
}
},
computed: mapGetters(['viewColor']),
data() {
return {
totalNmu:'',
isTimePay: false, //
};
},
watch:{
cartInfo:function(nVal,oVal){
let num = 0
nVal.forEach((item,index)=>{
num += item.cart_num
})
this.totalNmu = num
}
},
onShow() {
this.isPayBalance()
},
mounted() {},
methods: {
evaluateTap:function(unique,orderId){
uni.navigateTo({
url:`/pages/users/goods_comment_con/index?uni=${unique}&order_id=${orderId}`
})
},
//
isPayBalance(){
let that = this;
if(that.orderData.status === 10){
if(new Date() < new Date(that.orderData.presellOrder.final_start_time)){
that.isTimePay = false; //
}else if((new Date() >= new Date(that.orderData.presellOrder.final_start_time)) && (new Date() <= new Date(that.orderData.presellOrder.final_start_time)) ){
that.isTimePay = true; //
}
}
},
jumpCon:function(id){
if(this.jump){
if(this.activityType == 2){
uni.navigateTo({
url: `/pages/activity/presell_details/index?id=${id}`
})
}else{
uni.navigateTo({
url: `/pages/goods_details/index?id=${id}`
})
}
}
},
// 退
refund(item){
// #ifdef MP
openOrderRefundSubscribe().then(() => {
uni.hideLoading();
if(this.evaluate == 0){
uni.navigateTo({
url:'/pages/users/refund/confirm?order_id='+this.orderId+'&type=1'+'&ids='+item.order_product_id+'&refund_type=1'
})
}else{
uni.navigateTo({
url:'/pages/users/refund/select?order_id='+this.orderId+'&type=1'+'&ids='+item.order_product_id
})
}
}).catch(() => {
uni.hideLoading();
})
// #endif
// #ifdef H5
if(this.evaluate == 0){
uni.navigateTo({
url:'/pages/users/refund/confirm?order_id='+this.orderId+'&type=1'+'&ids='+item.order_product_id+'&refund_type=1'
})
}else{
uni.navigateTo({
url:'/pages/users/refund/select?order_id='+this.orderId+'&type=1'+'&ids='+item.order_product_id
})
}
// #endif
}
}
}
</script>
<style scoped lang="scss">
.orderGoods {
background-color: #fff;
}
.goodWrapper{
margin-top: 12rpx;
.title{
padding: 0 32rpx;
border-bottom: 1px solid #f0f0f0;
height: 86rpx;
line-height: 86rpx;
}
}
.right-btn-box{
position: absolute;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: flex-end;
&.event_box{
position: static;
}
.btn-item{
display: flex;
align-items: center;
justify-content: center;
width:140rpx;
height:46rpx;
margin-left: 20rpx;
border:1px solid rgba(187,187,187,1);
border-radius:23rpx;
font-size: 24rpx;
color: #282828;
&.on{
background:rgba(220,220,220,1);
border-color: rgba(220,220,220,1);
}
&.err{
background:rgba(247,247,247,1);
border-color: rgba(247,247,247,1);
color: #AAAAAA;
}
}
}
.event_bg{
background: #FF7F00;
}
.event_color{
color: #FF7F00;
}
.money {
color: var(--view-priceColor);
}
.presell_item{
height: auto;
padding-bottom: 15rpx;
}
.event_progress{
margin-top: 20rpx;
background: #fff;
.progress_name {
padding-left: 30rpx;
height: 60rpx;
line-height: 60rpx;
font-size: 24rpx;
font-weight: bold;
position: relative;
&::before{
content: "";
display: inline-block;
width: 5rpx;
height: 34rpx;
background: #E93323;
position: absolute;
top: 15rpx;
left: 0;
}
}
.align_right{
float: right;
font-weight: bold;
}
.progress_price{
padding: 20rpx 30rpx;
color: #999999;
font-size: 22rpx;
}
.progress_pay{
padding: 25rpx 30rpx;
background: var(--view-minorColor);
font-size: 26rpx;
color: #282828;
}
}
.event_name{
display: inline-block;
margin-right: 9rpx;
color: #fff;
font-size: 20rpx;
padding: 0 8rpx;
line-height: 30rpx;
text-align: center;
border-radius: 6rpx;
}
.event_ship{
font-size: 20rpx;
margin-top: 10rpx;
}
</style>

View File

@ -0,0 +1,815 @@
<!--
parser 主模块组件
githubhttps://github.com/jin-yufeng/Parser
docshttps://jin-yufeng.github.io/Parser
插件市场https://ext.dcloud.net.cn/plugin?id=805
authorJinYufeng
update2020/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-->
<image v-for="(item, index) in imgs" v-bind:key="index" :id="index" :src="item" hidden @load="_load" />
</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.getSystemInfoSync().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 && 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(/&nbsp;/g, '\u00A0').replace(/&lt;/g, '<').replace(/&gt;/g, '>')
.replace(/&amp;/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>

View File

@ -0,0 +1,111 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
/*
解析和匹配 Css 的选择器
githubhttps://github.com/jin-yufeng/Parser
docshttps://jin-yufeng.github.io/Parser
authorJinYufeng
update2020/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;
}
}

View File

@ -0,0 +1,586 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
/*
html 解析为适用于小程序 rich-text DOM 结构
githubhttps://github.com/jin-yufeng/Parser
docshttps://jin-yufeng.github.io/Parser
authorJinYufeng
update2020/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(/&amp;/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); // 解决 &nbsp; 失效
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(/&quot;/g, '"').replace(/&amp;/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;

View File

@ -0,0 +1,89 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
/* 配置文件 */
// #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(str) {
var map = {},
list = str.split(',');
for (var i = list.length; i--;)
map[list[i]] = true;
return map;
}

View 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>
// +----------------------------------------------------------------------
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;
}
}

View File

@ -0,0 +1,53 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
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;
}
}

View File

@ -0,0 +1,485 @@
<!--
trees 递归显示组件
githubhttps://github.com/jin-yufeng/Parser
docshttps://jin-yufeng.github.io/Parser
插件市场https://ext.dcloud.net.cn/plugin?id=805
authorJinYufeng
update2020/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>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
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>

View File

@ -0,0 +1,463 @@
<template>
<view class="m-tabbar-box" :style="tabbarBoxStyle" v-if="isShowTabBar">
<view class="m-tabbar__fill" v-if="fill || native" :class="{'m-tabbar__safe': (safeBottom || native)}"
:style="tabbarFillStyle"></view>
<view id="m-tabbar" class="m-tabbar" :class="{'fixed': (fixed || native), 'm-tabbar__safe': (safeBottom || native)}"
:style="tabbarStyle">
<view class="m-tabbar__border" v-if="borderStyle === 'black' "></view>
<view class="m-tabbar__flex">
<view @click="tabChange(index)" v-for="(item, index) in tabbarList" :key="index" class="m-tabbar__item" :class="{
'm-tabbar__item__active': index === currentIndex,
}">
<slot :name="`tabbar_index_${index}`">
<view class="m-tabbar__icon">
<view class="m-tabbar__badge" v-if="item.dot">{{item.dot}}</view>
<image :src="currentIndex === index ? item.selectedIconPath : item.iconPath" class="m-tabbar__icon_img" />
</view>
<view class="m-tabbar__label"
:style="{'color': index === currentIndex ? tabbarConfig.selectedColor : tabbarConfig.color }">
{{ item.text }}
</view>
</slot>
</view>
</view>
<view :style="{ paddingBottom: systemInfo.tabbarPaddingB + 'px', background: '#fff' }"></view>
</view>
</view>
</template>
<script>
const obj2strStyle = (obj) => {
let style = ''
for (let key in obj) {
style += `${key}:${obj[key]};`
}
return style
}
const padFirstSymbol = (str, smb) => {
if (str.startsWith(smb) || str.startsWith('http')) {
return str
}
return `/${str}`
}
const replaceTabbarList = (list) => {
if (!list.length > 0) {
return []
}
return list.map(item => {
if (item.iconPath) {
item.iconPath = padFirstSymbol(item.iconPath, '/')
}
if (item.pagePath) {
item.pagePath = padFirstSymbol(item.pagePath, '/')
}
if (item.selectedIconPath) {
item.selectedIconPath = padFirstSymbol(item.selectedIconPath, '/')
}
return item
})
}
// import base from '@/config/baseUrl.js';
import PageConfig from '@/pages.json'
export default {
emits: ['change', 'click'],
props: {
current: {
type: [Number, String],
default: 0
},
tabbar: {
type: Object,
default () {
return {}
}
},
fixed: {
type: Boolean,
default: false
},
fill: {
type: Boolean,
default: false
},
zIndex: {
type: [Number, String],
default: 9999
},
native: {
type: Boolean,
default: false
},
safeBottom: {
type: Boolean,
default: true
},
beforeChange: {
type: Function,
default: null
},
tabbarHeight: {
type: [Number, String],
default: 100
}
},
data() {
return {
systemInfo: {},
isShowTabBar: false,
currentIndex: 0,
beforeData: {},
reload: false
}
},
watch: {
current(val) {
this.currentIndex = val * 1
}
},
computed: {
tabbarConfig() {
const {
native,
reload
} = this
if (reload) {}
if (native) {
const {
tabBar
} = PageConfig
if (!tabBar) {
console.error('Native mode, Pages.json no tabbar config')
return {
borderStyle: 'black',
list: []
}
}
return tabBar
}
return this.tabbar
},
tabbarList() {
const {
reload
} = this
const {
list
} = this.tabbarConfig
if (reload) {}
if (list) {
return replaceTabbarList(list)
}
console.error('No tabbar config')
return []
},
borderStyle() {
const {
reload
} = this
const {
borderStyle
} = this.tabbarConfig
if (reload) {}
return borderStyle
},
tabbarBoxStyle() {
const {
zIndex,
reload
} = this
if (reload) {}
return obj2strStyle({
'z-index': zIndex,
})
},
tabbarFillStyle() {
const {
tabbarHeight,
safeBottom,
reload
} = this
if (reload) {}
return obj2strStyle({
'height': `${tabbarHeight}rpx`
})
},
tabbarStyle() {
const {
tabbarHeight,
reload
} = this
const {
backgroundColor
} = this.tabbarConfig
if (reload) {}
return obj2strStyle({
// 'height': `${tabbarHeight}rpx`,
'background-color': backgroundColor || '#fff',
})
},
tabbarItemStyle() {
const {
currentIndex,
reload
} = this
const {
color,
selectedColor
} = this.tabbarConfig
if (reload) {}
return obj2strStyle({
'color': currentIndex ? selectedColor : color
})
}
},
mounted() {
this.initTabbar()
this.getTabbarHeight()
},
methods: {
getTabbarHeight() {
var systemInfo = uni.getSystemInfoSync()
var data = {
...systemInfo,
tabbarH: 50, //tabbar--px
tabbarPaddingB: 0, //tabbar--px
device: systemInfo.system.indexOf('iOS') != -1 ? 'iOS' : 'Android', //
}
let modelArr = ['10,3', '10,6', 'X', 'XR', 'XS', '11', '12', '13', '14', '15', '16'];
let model = systemInfo.model;
model && modelArr.forEach(item => {
//iphoneXtabbarpadding-bottom
if (model.indexOf(item) != -1 && (model.indexOf('iPhone') != -1 || model.indexOf('iphone') != -1)) {
data.tabbarH = 70
data.tabbarPaddingB = 20
}
})
this.systemInfo = data
},
initTabbar() {
const {
current,
fill,
native,
tabbarList
} = this
this.currentIndex = current * 1
if (native) {
const currentPage = `/${getCurrentPages()[0].route}`
const currentIndex = tabbarList.findIndex(item => item.pagePath === currentPage)
this.currentIndex = currentIndex
if (tabbarList.length > 0) {
uni.hideTabBar()
}
}
setTimeout(() => {
this.isShowTabBar = true
})
},
reLoad() {
this.reload = true
setTimeout(() => {
this.reload = false
})
},
checkMaxIndex(index) {
if (!this.tabbarConfig.list[index]) {
console.error('Max tabbar index')
return false
}
return true
},
setTabBarBadge(obj) {
const {
index,
text
} = obj
if (this.checkMaxIndex(index)) {
this.tabbarConfig.list[index].dot = text
this.reLoad()
}
},
setTabBarItem(obj) {
const {
index,
text,
pagePath: newPagePath,
iconPath,
selectedIconPath
} = obj
const {
pagePath: oldPagePath
} = this.tabbarConfig.list[index]
if (this.checkMaxIndex(index)) {
this.tabbarConfig.list[index] = {
pagePath: newPagePath ? newPagePath : oldPagePath,
text,
iconPath,
selectedIconPath
}
this.reLoad()
}
},
showTabBar() {
this.isShowTabBar = true
},
hideTabBar() {
this.isShowTabBar = false
},
tabChange(index) {
const { currentIndex } = this
this.$emit('click', index)
if (index === currentIndex) {
index === 3 ? uni.$emit('resetLocation') : ''
return
}
this.beforeData = {
newIndex: index,
oldIndex: currentIndex,
next: this.jumpPage
}
if (this.beforeChange) {
this.beforeChange(this.jumpPage)
} else {
this.jumpPage()
}
},
jumpPage() {
const {
native,
beforeData,
tabbarList: list
} = this
const {
newIndex: index
} = beforeData
const {
pagePath: url,
openType
} = list[index]
if (url) {
if (native) {
uni.switchTab({
url
})
} else {
this.currentIndex = index
switch (openType) {
case 'navigate':
uni.navigateTo({
url
})
break;
case 'redirect':
uni.redirectTo({
url
})
break;
case 'reLaunch':
uni.reLaunch({
url
})
break;
case 'switchTab':
uni.switchTab({
url
})
break;
case 'navigateBack':
uni.navigateBack({
delta: 1
})
break;
default:
uni.reLaunch({
url
})
}
}
}
this.$emit('change', index)
}
}
};
</script>
<style lang="scss" scoped>
.m-tabbar-box {
position: relative;
z-index: 9999;
}
.m-tabbar {
position: relative;
&.fixed {
position: fixed;
bottom: 0;
left: 0;
width: 100vw;
}
&__safe {
// padding-bottom: env(safe-area-inset-bottom);
}
}
.m-tabbar__fill {
pointer-events: none;
opacity: 0;
}
.m-tabbar__flex {
display: flex;
flex-direction: row;
}
.m-tabbar__border {
background-color: rgba(0, 0, 0, 0.33);
width: 100%;
height: 1rpx;
transform: scaleY(0.5);
}
.m-tabbar__item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding: 4px 0 2px;
}
.m-tabbar__icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 6rpx;
position: relative;
&_img {
display: block;
width: 100%;
height: 100%;
}
.m-tabbar__badge {
color: #fff;
background-color: #f00;
border-radius: 20rpx;
font-size: 22rpx;
position: absolute;
right: -25rpx;
left: 40rpx;
padding: 2rpx 0;
width: 100%;
text-align: center;
white-space: nowrap;
}
}
.m-tabbar__label {
font-size: 24rpx;
}
</style>

234
components/mentioned.vue Normal file
View File

@ -0,0 +1,234 @@
<template>
<view :style="viewColor">
<view class="container" :class="popup.show==true?'on':''">
<view class="header">
<text class="title">TA提到的宝贝</text>
<text class="iconfont icon-guanbi5" @click="closePopup"></text>
</view>
<view class="main_count" :class="isHome ? 'mb90' : ''">
<scroll-view scroll-y="true">
<view v-for="(item, index) in list" :key="index" @click="goDetail(item.spu)" class="list">
<view class="pro_list">
<view class="picture">
<image :src="item.spu && item.spu.image" class="image"></image>
</view>
<view class="info">
<view class="name line2">{{item.spu && item.spu.store_name}}</view>
<view class="bottom">
<view class="price"><text>{{item.spu && item.spu.price}}</text></view>
<view class="buy-btn">立即购买</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
<view class='mask' style="height: 100vh;" catchtouchmove="true" :hidden='popup.show==false' @tap="closePopup">
</view>
</view>
</template>
<script>
import {
goShopDetail
} from '@/libs/order.js'
import {
mapGetters
} from "vuex";
export default {
computed: {
...mapGetters(['viewColor']),
},
props: {
list: {
type: Array,
default: []
},
uid: {
type: Number,
},
isHome: {
type: Boolean,
default: false
}
},
data() {
return {
popup: {
show: false
},
};
},
methods: {
//
closePopup() {
this.$set(this.popup, 'show', false);
this.$emit("closes")
},
showPopup() {
this.$set(this.popup, 'show', true);
},
goDetail(item) {
if (item.product_type === 1) {
uni.navigateTo({
url: `/pages/activity/goods_seckill_details/index?id=${item.product_id}&time=${item.stop_time}&spid=${this.uid}`
})
} else if (item.product_type === 2) {
uni.navigateTo({
url: `/pages/activity/presell_details/index?id=${item.activity_id}&spid=${this.uid}`
})
} else if (item.product_type === 0) {
uni.navigateTo({
url: `/pages/goods_details/index?id=${item.product_id}&spid=${this.uid}`
})
} else if (item.product_type === 4) {
uni.navigateTo({
url: `/pages/activity/combination_details/index?id=${item.activity_id}&spid=${this.uid}`
})
} else if (item.product_type === 40) {
uni.navigateTo({
url: `/pages/activity/combination_status/index?id=${item.activity_id}&spid=${this.uid}`
})
}
}
}
}
</script>
<style lang="scss" scoped>
.container {
position: fixed;
bottom: 0;
width: 100%;
left: 0;
background-color: #ffffff;
z-index: 77;
border-radius: 16rpx 16rpx 0 0;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
max-height: 1000rpx;
&.on {
transform: translate3d(0, 0, 0);
}
.header {
position: relative;
padding: 40rpx 30rpx;
.title {
color: #282828;
font-size: 30rpx;
}
.iconfont {
color: #8A8A8A;
font-size: 28rpx;
position: absolute;
top: 0;
right: 0;
}
.icon-guanbi5 {
right: 20rpx;
color: #8a8a8a;
font-size: 30rpx;
line-height: 30rpx;
top: 20rpx;
background-color: transparent;
font-weight: normal;
}
}
scroll-view {
max-height: 800rpx;
}
.main_count {
padding: 0 30rpx 30rpx;
max-height: 800rpx;
overflow-y: scroll;
/* #ifndef MP */
&.mb90 {
margin-bottom: 90rpx;
}
/* #endif */
.list {
margin-bottom: 40rpx;
height: auto;
flex-direction: row;
&:last-child {
margin-bottom: 0;
}
}
.pro_list {
display: flex;
flex-direction: row;
.picture,
.image,
uni-image {
width: 200rpx;
height: 200rpx;
border-radius: 16rpx;
}
.info {
margin-left: 30rpx;
position: relative;
.bottom {
display: flex;
justify-content: space-between;
align-items: center;
width: 460rpx;
position: absolute;
left: 0;
bottom: 10rpx;
flex-direction: row;
}
.name {
color: #282828;
font-size: 30rpx;
line-height: 45rpx;
display: -webkit-box;
width: 460rpx;
}
.price {
color: var(--view-priceColor);
font-size: 26rpx;
font-weight: bold;
flex-direction: row;
align-items: flex-end;
text {
font-size: 34rpx;
}
}
.buy-btn {
color: #fff;
background: var(--view-theme);
border-radius: 28.04rpx 28.04rpx 28.04rpx 28.04rpx;
width: 154.21rpx;
height: 57.83rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 22rpx;
}
}
}
}
}
</style>

View File

@ -0,0 +1,406 @@
.mpvue-calendar {
margin:auto;
width: 100%;
min-width:350px;
background: #fff;
user-select:none;
position: relative;
}
.calendar-tools{
height:40px;
font-size: 20px;
line-height: 40px;
color:#5e7a88;
box-shadow: 0px 4px 8px rgba(25, 47, 89, 0.1);
margin-bottom: 20px;
border-top: 1px solid rgba(200, 200, 200, .1);
}
.calendar-tools span{
cursor: pointer;
}
.calendar-prev{
width: 14.28571429%;
float:left;
text-align: center;
}
.calendar-prev img, .calendar-next img{
width: 34px;
height: 34px;
}
.calendar-info{
font-size:16px;
line-height: 1.3;
text-align: center;
width: 220px;
margin: 0 auto;
}
.calendar-info>div.mc-month{
margin:auto;
height:24px;
width:100px;
text-align: center;
color:#5e7a88;
overflow: hidden;
position: relative;
}
.calendar-info>div.mc-month .mc-month-inner{
position: absolute;
left:0;
top:0;
height:480px;
}
.month-transition{
transition:top .5s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.calendar-info .mc-month-text{
display:block;
font-size:28px;
height:40px;
width:200px;
overflow:hidden;
text-align:center;
}
.calendar-info>div.mc-month .mc-month-inner>span{
display: block;
font-size: 14px;
height:24px;
line-height:24px;
width:100px;
overflow: hidden;
text-align: center;
}
.calendar-info>div.mc-year{
font-size:10px;
line-height: 1;
color:#999;
}
.calendar-next{
width: 14.28571429%;
float:right;
text-align: center;
}
.mpvue-calendar table {
clear: both;
width: 100%;
margin-bottom:10px;
border-collapse: collapse;
color: #444444;
}
.mpvue-calendar td {
margin:2px !important;
padding: 4px;
width: 14.28571429%;
box-sizing: border-box;
text-align: center;
vertical-align: middle;
font-size:14px;
cursor: pointer;
position: relative;
vertical-align: top;
}
.mpvue-calendar td.mc-week{
font-size:10px;
pointer-events:none !important;
cursor: default !important;
}
.mpvue-calendar td.disabled {
color: #ccc;
}
.mpvue-calendar td.disabled div{
color: #ccc;
}
.mpvue-calendar td span{
display:block;
height:100%;
width:100%;
margin:0px auto;
border-radius:50%;
position: relative;
z-index: 3;
}
.mpvue-calendar td:not(.disabled) span.mc-date-red{
color:#ea6151;
}
.mc-today{
color: #3b75fb;
}
.mpvue-calendar td.selected span{
background-color: #3b75fb;
color: #fff;
border-radius: 50%;
}
.mpvue-calendar td .mc-text{
box-sizing: border-box;
height: 0.7em;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
position: absolute;
bottom: 0px;
left: 0;
right: 0;
text-align: center;
font-size: 0.7em;
line-height: 0.7em;
z-index: 4;
}
.mpvue-calendar td .isGregorianFestival,
.mpvue-calendar td .isTerm,
.mpvue-calendar td .isLunarFestival{
color:#ea6151;
}
.mpvue-calendar td.selected span.mc-date-red{
background-color: #3b75fb;
color: #fff;
}
.selected .mc-text {
color: #fff !important;
}
.mpvue-calendar .lunarStyle .mc-text{
overflow: visible;
bottom: 20%;
}
.mpvue-calendar thead td {
text-transform: uppercase;
height:30px;
vertical-align: middle;
}
.mc-head {
margin-bottom: 10px;
}
.mc-head div {
overflow: hidden;
}
.mc-head-box div {
flex:1;
text-align: center;
font-size: 18px;
}
.mc-head-box {
display: flex;
flex-direction: row;
justify-content: center;
align-content: space-between
}
.mc-body {
padding-bottom: 20px;
}
.mc-body tr {
display: flex;
flex-direction: row;
justify-content: center;
align-content: space-between;
}
.mc-dot {
width: 8px;
height: 8px;
background-color: #ea6151;
border-radius: 50%;
position: absolute;
bottom: -4px;
left: 50%;
margin-left: -4px;
z-index: 5;
}
.remark-text {
box-sizing: border-box;
height: 0.7em;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
position: absolute;
bottom: 0px;
left: 0;
right: 0;
text-align: center;
font-size: 0.7em;
line-height: 0.7em;
z-index: 5;
}
.slot-element{
line-height: normal;
position: absolute;
z-index: 5;
}
.mpvue-calendar-change{
position: absolute;
left:0px;
top:42px;
right:0px;
bottom:0px;
background:#fff;
display: flex;
justify-content: center;
align-items: center;
flex-wrap:wrap;
overflow: auto;
transition:all .5s cubic-bezier(0.075, 0.82, 0.165, 1);
opacity: 0;
pointer-events: none;
transform: translateY(-10px);
z-index: 9;
}
.mpvue-calendar-change.show{
opacity: 1;
pointer-events: auto;
transform: translateY(0px);
}
.mpvue-calendar-change span{
margin:4px 2%;
display: inline-block;
line-height: 30px;
border-radius: 20px;
text-align:center;
color:#999;
width: 20%;
float: left;
text-align: center;
border-radius: 40px;
box-sizing: border-box;
margin-bottom: 4%;
cursor: pointer;
}
.mpvue-calendar-change span.active{
background-color: #587dff;
box-shadow: 2px 2px 2px rgba(88, 125, 255, 0.7);
color:#fff;
}
.mpvue-calendar-change .calendar-week-switch-months{
height: 100%;
}
.mpvue-calendar-change .calendar-week-switch-months span {
margin-bottom: 10px;
margin-top: 0px;
}
.calendar-years, .calendar-months{
height: 50%;
width: 100%;
padding: 10px;
box-sizing: border-box;
position: relative;
}
.calendar-years:after {
content: '';
display: block;
width: 86%;
height: 1px;
background-color: #eee;
position: absolute;
bottom: 2%;
left: 7%;
}
/*range background*/
.mc-range-mode .selected .mc-range-bg{
content: '';
display: block;
width: 150%;
height: 100%;
background-color: #01a1ed;
position: relative;
top: -100%;
left: 50%;
}
.mpvue-calendar .mc-range-mode .selected .calendar-date{
background-color: transparent;
}
.mpvue-calendar .mc-range-mode .mc-range-row-last .calendar-date, .mpvue-calendar .mc-range-mode .mc-range-row-first .calendar-date{
border-radius: 4px;
background-color: #01a1ed;
}
.mpvue-calendar .mc-range-mode .mc-range-month-first.selected .calendar-date, .mpvue-calendar .mc-range-mode .mc-range-month-last.selected .calendar-date{
background-color: #01a1ed;
border-radius: 4px;
}
.mc-range-mode .mc-range-month-last .mc-range-bg{
background-color: transparent;
border-radius: 4px;
}
.mc-range-mode .mc-range-end .mc-range-bg, .mc-range-mode .mc-range-row-last .mc-range-bg{
display: none;
}
.mc-range-row-first.mc-range-end .mc-range-bg{
display: block;
margin-left: -50%;
width: 50%;
border-radius: 4px;
}
.mpvue-calendar .mc-range-row-first.mc-range-end.month-first-date .mc-range-bg{
margin-left: 0px;
}
.mc-range-row-last.mc-range-begin .mc-range-bg{
display: block;
width: 50%;
border-radius: 4px;
}
.mpvue-calendar .mc-range-mode .selected.mc-range-second-to-last span{
background-color: #01a1ed;
border-radius: 4px;
}
.mc-range-begin.mc-range-second-to-last{
background-color: #01a1ed;
border-radius: 4px;
}
.mpvue-calendar .mc-range-mode .mc-range-end span.calendar-date, .mpvue-calendar .mc-range-mode .mc-range-begin span.calendar-date{
background-color: #3b75fb;
color: #fff;
border-radius: 50%;
}
.mpvue-calendar .mc-range-mode .month-last-date.mc-range-begin .mc-range-bg{
display: block;
width: 50%;
border-radius: 4px;
}
.mpvue-calendar .mc-range-mode .month-first-date.mc-range-end .mc-range-bg{
display: block;
width: 50%;
border-radius: 4px;
left: 0px;
}
.calendar-wrapper .mpvue-calendar .mc-range-mode .mc-range-select-one div.mc-range-bg{
display: none;
}
.mc-range-mode .mc-range-second-to-last .mc-range-bg{
border-radius: 0px 25% 25% 0px;
}
.mc-today-element .calendar-date{
background-color: rgba(25, 47, 89, 0.1);
border-radius: 4px;
}
/*week switch*/
.mpvue-calendar .mc-range-mode.week-switch .month-last-date.mc-range-begin .mc-range-bg{
width: 150%;
border-radius: 0px 20% 20% 0px;
}
.mpvue-calendar .mc-range-mode.week-switch .mc-range-month-last .mc-range-bg{
background-color: #01a1ed;
border-radius: 0px 20% 20% 0px;
}
/*month range*/
.mpvue-calendar .month-range-mode{
border-bottom: 1px solid #f2f2f2;
position: relative;
}
.mpvue-calendar .mc-month-range-mode-head{
box-shadow: 0 4px 8px rgba(25,47,89,.1);
padding: 8px 0px;
position: sticky;
top: 0px;
background-color: #fff;
z-index: 9;
}
.month-range-mode .month-rang-head {
text-align: left;
margin: 10px 0px;
padding-left: 10px;
}
.month-range-mode .mc-last-month, .month-range-mode .mc-next-month{
opacity: 0 !important;
}
.month-text-background{
position: absolute;
font-size: 140px;
width: 100%;
height: 100%;
text-align: center;
line-height: 2.4;
}

View File

@ -0,0 +1,524 @@
/**
* @1900-2100区间内的公历农历互转
* @charset UTF-8
* @Author Jea杨(JJonline@JJonline.Cn)
* @Time 2014-7-21
* @Time 2016-8-13 Fixed 2033hexAttribution Annals
* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug
* @Version 1.0.2
* @公历转农历calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
* @农历转公历calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
*/
var calendar = {
/**
* 农历1900-2100的润大小信息表
* @Array Of Property
* @return Hex
*/
lunarInfo:[0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,//1900-1909
0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,//1910-1919
0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,//1920-1929
0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,//1930-1939
0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,//1940-1949
0x06ca0,0x0b550,0x15355,0x04da0,0x0a5b0,0x14573,0x052b0,0x0a9a8,0x0e950,0x06aa0,//1950-1959
0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,//1960-1969
0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b6a0,0x195a6,//1970-1979
0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,//1980-1989
0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,//1990-1999
0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,//2000-2009
0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,//2010-2019
0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,//2020-2029
0x05aa0,0x076a3,0x096d0,0x04afb,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,//2030-2039
0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0,//2040-2049
/**Add By JJonline@JJonline.Cn**/
0x14b63,0x09370,0x049f8,0x04970,0x064b0,0x168a6,0x0ea50, 0x06b20,0x1a6c4,0x0aae0,//2050-2059
0x0a2e0,0x0d2e3,0x0c960,0x0d557,0x0d4a0,0x0da50,0x05d55,0x056a0,0x0a6d0,0x055d4,//2060-2069
0x052d0,0x0a9b8,0x0a950,0x0b4a0,0x0b6a6,0x0ad50,0x055a0,0x0aba4,0x0a5b0,0x052b0,//2070-2079
0x0b273,0x06930,0x07337,0x06aa0,0x0ad50,0x14b55,0x04b60,0x0a570,0x054e4,0x0d160,//2080-2089
0x0e968,0x0d520,0x0daa0,0x16aa6,0x056d0,0x04ae0,0x0a9d4,0x0a2d0,0x0d150,0x0f252,//2090-2099
0x0d520],//2100
/**
* 公历每个月份的天数普通表
* @Array Of Property
* @return Number
*/
solarMonth:[31,28,31,30,31,30,31,31,30,31,30,31],
/**
* 天干地支之天干速查表
* @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
* @return Cn string
*/
Gan:["\u7532","\u4e59","\u4e19","\u4e01","\u620a","\u5df1","\u5e9a","\u8f9b","\u58ec","\u7678"],
/**
* 天干地支之地支速查表
* @Array Of Property
* @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
* @return Cn string
*/
Zhi:["\u5b50","\u4e11","\u5bc5","\u536f","\u8fb0","\u5df3","\u5348","\u672a","\u7533","\u9149","\u620c","\u4ea5"],
/**
* 天干地支之地支速查表<=>生肖
* @Array Of Property
* @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
* @return Cn string
*/
Animals:["\u9f20","\u725b","\u864e","\u5154","\u9f99","\u86c7","\u9a6c","\u7f8a","\u7334","\u9e21","\u72d7","\u732a"],
/**
* 24节气速查表
* @Array Of Property
* @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
* @return Cn string
*/
solarTerm:["\u5c0f\u5bd2","\u5927\u5bd2","\u7acb\u6625","\u96e8\u6c34","\u60ca\u86f0","\u6625\u5206","\u6e05\u660e","\u8c37\u96e8","\u7acb\u590f","\u5c0f\u6ee1","\u8292\u79cd","\u590f\u81f3","\u5c0f\u6691","\u5927\u6691","\u7acb\u79cb","\u5904\u6691","\u767d\u9732","\u79cb\u5206","\u5bd2\u9732","\u971c\u964d","\u7acb\u51ac","\u5c0f\u96ea","\u5927\u96ea","\u51ac\u81f3"],
/**
* 1900-2100各年的24节气日期速查表
* @Array Of Property
* @return 0x string For splice
*/
sTermInfo:['9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e','97bcf97c3598082c95f8c965cc920f',
'97bd0b06bdb0722c965ce1cfcc920f','b027097bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f','97bd0b06bdb0722c965ce1cfcc920f','b027097bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e','97bcf97c359801ec95f8c965cc920f','97bd0b06bdb0722c965ce1cfcc920f',
'b027097bd097c36b0b6fc9274c91aa','9778397bd19801ec9210c965cc920e','97b6b97bd19801ec95f8c965cc920f',
'97bd09801d98082c95f8e1cfcc920f','97bd097bd097c36b0b6fc9210c8dc2','9778397bd197c36c9210c9274c91aa',
'97b6b97bd19801ec95f8c965cc920e','97bd09801d98082c95f8e1cfcc920f','97bd097bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa','97b6b97bd19801ec95f8c965cc920e','97bcf97c3598082c95f8e1cfcc920f',
'97bd097bd097c36b0b6fc9210c8dc2','9778397bd097c36c9210c9274c91aa','97b6b97bd19801ec9210c965cc920e',
'97bcf97c3598082c95f8c965cc920f','97bd097bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e','97bcf97c3598082c95f8c965cc920f','97bd097bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e','97bcf97c359801ec95f8c965cc920f',
'97bd097bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e',
'97bcf97c359801ec95f8c965cc920f','97bd097bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e','97bcf97c359801ec95f8c965cc920f','97bd097bd07f595b0b6fc920fb0722',
'9778397bd097c36b0b6fc9210c8dc2','9778397bd19801ec9210c9274c920e','97b6b97bd19801ec95f8c965cc920f',
'97bd07f5307f595b0b0bc920fb0722','7f0e397bd097c36b0b6fc9210c8dc2','9778397bd097c36c9210c9274c920e',
'97b6b97bd19801ec95f8c965cc920f','97bd07f5307f595b0b0bc920fb0722','7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36c9210c9274c91aa','97b6b97bd19801ec9210c965cc920e','97bd07f1487f595b0b0bc920fb0722',
'7f0e397bd097c36b0b6fc9210c8dc2','9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f595b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c965cc920e','97bcf7f1487f595b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e','97bcf7f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa','97b6b97bd19801ec9210c965cc920e',
'97bcf7f1487f531b0b0bb0b6fb0722','7f0e397bd07f595b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b97bd19801ec9210c9274c920e','97bcf7f0e47f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa','97b6b97bd197c36c9210c9274c920e','97bcf7f0e47f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722','9778397bd097c36b0b6fc9210c8dc2','9778397bd097c36c9210c9274c920e',
'97b6b7f0e47f531b0723b0b6fb0722','7f0e37f5307f595b0b0bc920fb0722','7f0e397bd097c36b0b6fc9210c8dc2',
'9778397bd097c36b0b70c9274c91aa','97b6b7f0e47f531b0723b0b6fb0721','7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2','9778397bd097c36b0b6fc9274c91aa','97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f595b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722',
'9778397bd097c36b0b6fc9274c91aa','97b6b7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc920fb0722','9778397bd097c36b0b6fc9274c91aa','97b6b7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722','9778397bd097c36b0b6fc9274c91aa',
'97b6b7f0e47f531b0723b0787b0721','7f0e27f0e47f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722',
'9778397bd097c36b0b6fc9210c91aa','97b6b7f0e47f149b0723b0787b0721','7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722','9778397bd097c36b0b6fc9210c8dc2','977837f0e37f149b0723b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722','7f0e37f5307f595b0b0bc920fb0722','7f0e397bd097c35b0b6fc9210c8dc2',
'977837f0e37f14998082b0787b0721','7f07e7f0e47f531b0723b0b6fb0721','7f0e37f1487f595b0b0bb0b6fb0722',
'7f0e397bd097c35b0b6fc9210c8dc2','977837f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722','977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd097c35b0b6fc920fb0722',
'977837f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722','977837f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721',
'7f0e27f1487f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722','977837f0e37f14998082b0787b06bd',
'7f07e7f0e47f149b0723b0787b0721','7f0e27f0e47f531b0b0bb0b6fb0722','7f0e397bd07f595b0b0bc920fb0722',
'977837f0e37f14998082b0723b06bd','7f07e7f0e37f149b0723b0787b0721','7f0e27f0e47f531b0723b0b6fb0722',
'7f0e397bd07f595b0b0bc920fb0722','977837f0e37f14898082b0723b02d5','7ec967f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722','7f0e37f1487f595b0b0bb0b6fb0722','7f0e37f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721','7f07e7f0e47f531b0723b0b6fb0722','7f0e37f1487f531b0b0bb0b6fb0722',
'7f0e37f0e37f14898082b0723b02d5','7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721',
'7f0e37f1487f531b0b0bb0b6fb0722','7f0e37f0e37f14898082b072297c35','7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722','7f0e37f0e37f14898082b072297c35',
'7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722',
'7f0e37f0e366aa89801eb072297c35','7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f149b0723b0787b0721',
'7f0e27f1487f531b0b0bb0b6fb0722','7f0e37f0e366aa89801eb072297c35','7ec967f0e37f14998082b0723b06bd',
'7f07e7f0e47f149b0723b0787b0721','7f0e27f0e47f531b0723b0b6fb0722','7f0e37f0e366aa89801eb072297c35',
'7ec967f0e37f14998082b0723b06bd','7f07e7f0e37f14998083b0787b0721','7f0e27f0e47f531b0723b0b6fb0722',
'7f0e37f0e366aa89801eb072297c35','7ec967f0e37f14898082b0723b02d5','7f07e7f0e37f14998082b0787b0721',
'7f07e7f0e47f531b0723b0b6fb0722','7f0e36665b66aa89801e9808297c35','665f67f0e37f14898082b0723b02d5',
'7ec967f0e37f14998082b0787b0721','7f07e7f0e47f531b0723b0b6fb0722','7f0e36665b66a449801e9808297c35',
'665f67f0e37f14898082b0723b02d5','7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721',
'7f0e36665b66a449801e9808297c35','665f67f0e37f14898082b072297c35','7ec967f0e37f14998082b0787b06bd',
'7f07e7f0e47f531b0723b0b6fb0721','7f0e26665b66a449801e9808297c35','665f67f0e37f1489801eb072297c35',
'7ec967f0e37f14998082b0787b06bd','7f07e7f0e47f531b0723b0b6fb0721','7f0e27f1487f531b0b0bb0b6fb0722'],
/**
* 数字转中文速查表
* @Array Of Property
* @trans ['日','一','二','三','四','五','六','七','八','九','十']
* @return Cn string
*/
nStr1:["\u65e5","\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341"],
/**
* 日期转农历称呼速查表
* @Array Of Property
* @trans ['初','十','廿','卅']
* @return Cn string
*/
nStr2:["\u521d","\u5341","\u5eff","\u5345"],
/**
* 月份转农历称呼速查表
* @Array Of Property
* @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
* @return Cn string
*/
nStr3:["\u6b63","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u4e03","\u516b","\u4e5d","\u5341","\u51ac","\u814a"],
/**
* 返回农历y年一整年的总天数
* @param lunar Year
* @return Number
* @eg:var count = calendar.lYearDays(1987) ;//count=387
*/
lYearDays:function(y) {
var i, sum = 348;
for(i=0x8000; i>0x8; i>>=1) { sum += (calendar.lunarInfo[y-1900] & i)? 1: 0; }
return(sum+calendar.leapDays(y));
},
/**
* 返回农历y年闰月是哪个月若y年没有闰月 则返回0
* @param lunar Year
* @return Number (0-12)
* @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
*/
leapMonth:function(y) { //闰字编码 \u95f0
return(calendar.lunarInfo[y-1900] & 0xf);
},
/**
* 返回农历y年闰月的天数 若该年没有闰月则返回0
* @param lunar Year
* @return Number (02930)
* @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
*/
leapDays:function(y) {
if(calendar.leapMonth(y)) {
return((calendar.lunarInfo[y-1900] & 0x10000)? 30: 29);
}
return(0);
},
/**
* 返回农历y年m月非闰月的总天数计算m为闰月时的天数请使用leapDays方法
* @param lunar Year
* @return Number (-12930)
* @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
*/
monthDays:function(y,m) {
if(m>12 || m<1) {return -1}//月份参数从1至12参数错误返回-1
return( (calendar.lunarInfo[y-1900] & (0x10000>>m))? 30: 29 );
},
/**
* 返回公历(!)y年m月的天数
* @param solar Year
* @return Number (-128293031)
* @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
*/
solarDays:function(y,m) {
if(m>12 || m<1) {return -1} //若参数错误 返回-1
var ms = m-1;
if(ms==1) { //2月份的闰平规律测算后确认返回28或29
return(((y%4 == 0) && (y%100 != 0) || (y%400 == 0))? 29: 28);
}else {
return(calendar.solarMonth[ms]);
}
},
/**
* 农历年份转换为干支纪年
* @param lYear 农历年的年份数
* @return Cn string
*/
toGanZhiYear:function(lYear) {
var ganKey = (lYear - 3) % 10;
var zhiKey = (lYear - 3) % 12;
if(ganKey == 0) ganKey = 10;//如果余数为0则为最后一个天干
if(zhiKey == 0) zhiKey = 12;//如果余数为0则为最后一个地支
return calendar.Gan[ganKey-1] + calendar.Zhi[zhiKey-1];
},
/**
* 公历月日判断所属星座
* @param cMonth [description]
* @param cDay [description]
* @return Cn string
*/
toAstro:function(cMonth,cDay) {
var s = "\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf";
var arr = [20,19,21,21,21,22,23,23,23,23,22,22];
return s.substr(cMonth*2 - (cDay < arr[cMonth-1] ? 2 : 0),2) + "\u5ea7";//座
},
/**
* 传入offset偏移量返回干支
* @param offset 相对甲子的偏移量
* @return Cn string
*/
toGanZhi:function(offset) {
return calendar.Gan[offset%10] + calendar.Zhi[offset%12];
},
/**
* 传入公历(!)y年获得该年第n个节气的公历日期
* @param y公历年(1900-2100)n二十四节气中的第几个节气(1~24)从n=1(小寒)算起
* @return day Number
* @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
*/
getTerm:function(y,n) {
if(y<1900 || y>2100) {return -1;}
if(n<1 || n>24) {return -1;}
var _table = calendar.sTermInfo[y-1900];
var _info = [
parseInt('0x'+_table.substr(0,5)).toString() ,
parseInt('0x'+_table.substr(5,5)).toString(),
parseInt('0x'+_table.substr(10,5)).toString(),
parseInt('0x'+_table.substr(15,5)).toString(),
parseInt('0x'+_table.substr(20,5)).toString(),
parseInt('0x'+_table.substr(25,5)).toString()
];
var _calday = [
_info[0].substr(0,1),
_info[0].substr(1,2),
_info[0].substr(3,1),
_info[0].substr(4,2),
_info[1].substr(0,1),
_info[1].substr(1,2),
_info[1].substr(3,1),
_info[1].substr(4,2),
_info[2].substr(0,1),
_info[2].substr(1,2),
_info[2].substr(3,1),
_info[2].substr(4,2),
_info[3].substr(0,1),
_info[3].substr(1,2),
_info[3].substr(3,1),
_info[3].substr(4,2),
_info[4].substr(0,1),
_info[4].substr(1,2),
_info[4].substr(3,1),
_info[4].substr(4,2),
_info[5].substr(0,1),
_info[5].substr(1,2),
_info[5].substr(3,1),
_info[5].substr(4,2),
];
return parseInt(_calday[n-1]);
},
/**
* 传入农历数字月份返回汉语通俗表示法
* @param lunar month
* @return Cn string
* @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
*/
toChinaMonth:function(m) { // 月 => \u6708
if(m>12 || m<1) {return -1} //若参数错误 返回-1
var s = calendar.nStr3[m-1];
s+= "\u6708";//加上月字
return s;
},
/**
* 传入农历日期数字返回汉字表示法
* @param lunar day
* @return Cn string
* @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
*/
toChinaDay:function(d){ //日 => \u65e5
var s;
switch (d) {
case 10:
s = '\u521d\u5341'; break;
case 20:
s = '\u4e8c\u5341'; break;
break;
case 30:
s = '\u4e09\u5341'; break;
break;
default :
s = calendar.nStr2[Math.floor(d/10)];
s += calendar.nStr1[d%10];
}
return(s);
},
/**
* 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是立春
* @param y year
* @return Cn string
* @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
*/
getAnimal: function(y) {
return calendar.Animals[(y - 4) % 12]
},
/**
* 传入阳历年月日获得详细的公历农历object信息 <=>JSON
* @param y solar year
* @param m solar month
* @param d solar day
* @return JSON object
* @eg:console.log(calendar.solar2lunar(1987,11,01));
*/
solar2lunar:function (y,m,d) { //参数区间1900.1.31~2100.12.31
if(y<1900 || y>2100) {return -1;}//年份限定、上限
if(y==1900&&m==1&&d<31) {return -1;}//下限
if(!y) { //未传参 获得当天
var objDate = new Date();
}else {
var objDate = new Date(y,parseInt(m)-1,d)
}
var i, leap=0, temp=0;
//修正ymd参数
var y = objDate.getFullYear(),m = objDate.getMonth()+1,d = objDate.getDate();
var offset = (Date.UTC(objDate.getFullYear(),objDate.getMonth(),objDate.getDate()) - Date.UTC(1900,0,31))/86400000;
for(i=1900; i<2101 && offset>0; i++) { temp=calendar.lYearDays(i); offset-=temp; }
if(offset<0) { offset+=temp; i--; }
//是否今天
var isTodayObj = new Date(),isToday=false;
if(isTodayObj.getFullYear()==y && isTodayObj.getMonth()+1==m && isTodayObj.getDate()==d) {
isToday = true;
}
//星期几
var nWeek = objDate.getDay(),cWeek = calendar.nStr1[nWeek];
if(nWeek==0) {nWeek =7;}//数字表示周几顺应天朝周一开始的惯例
//农历年
var year = i;
var leap = calendar.leapMonth(i); //闰哪个月
var isLeap = false;
//效验闰月
for(i=1; i<13 && offset>0; i++) {
//闰月
if(leap>0 && i==(leap+1) && isLeap==false){
--i;
isLeap = true; temp = calendar.leapDays(year); //计算农历闰月天数
}
else{
temp = calendar.monthDays(year, i);//计算农历普通月天数
}
//解除闰月
if(isLeap==true && i==(leap+1)) { isLeap = false; }
offset -= temp;
}
if(offset==0 && leap>0 && i==leap+1)
if(isLeap){
isLeap = false;
}else{
isLeap = true; --i;
}
if(offset<0){ offset += temp; --i; }
//农历月
var month = i;
//农历日
var day = offset + 1;
//天干地支处理
var sm = m-1;
var gzY = calendar.toGanZhiYear(year);
//月柱 1900年1月小寒以前为 丙子月(60进制12)
var firstNode = calendar.getTerm(year,(m*2-1));//返回当月「节」为几日开始
var secondNode = calendar.getTerm(year,(m*2));//返回当月「节」为几日开始
//依据12节气修正干支月
var gzM = calendar.toGanZhi((y-1900)*12+m+11);
if(d>=firstNode) {
gzM = calendar.toGanZhi((y-1900)*12+m+12);
}
//传入的日期的节气与否
var isTerm = false;
var Term = null;
if(firstNode==d) {
isTerm = true;
Term = calendar.solarTerm[m*2-2];
}
if(secondNode==d) {
isTerm = true;
Term = calendar.solarTerm[m*2-1];
}
//日柱 当月一日与 1900/1/1 相差天数
var dayCyclical = Date.UTC(y,sm,1,0,0,0,0)/86400000+25567+10;
var gzD = calendar.toGanZhi(dayCyclical+d-1);
//该日期所属的星座
var astro = calendar.toAstro(m,d);
return {'lYear':year,'lMonth':month,'lDay':day,'Animal':calendar.getAnimal(year),'IMonthCn':(isLeap?"\u95f0":'')+calendar.toChinaMonth(month),'IDayCn':calendar.toChinaDay(day),'cYear':y,'cMonth':m,'cDay':d,'gzYear':gzY,'gzMonth':gzM,'gzDay':gzD,'isToday':isToday,'isLeap':isLeap,'nWeek':nWeek,'ncWeek':"\u661f\u671f"+cWeek,'isTerm':isTerm,'Term':Term,'astro':astro};
},
/**
* 传入农历年月日以及传入的月份是否闰月获得详细的公历农历object信息 <=>JSON
* @param y lunar year
* @param m lunar month
* @param d lunar day
* @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
* @return JSON object
* @eg:console.log(calendar.lunar2solar(1987,9,10));
*/
lunar2solar:function(y,m,d,isLeapMonth) { //参数区间1900.1.31~2100.12.1
var isLeapMonth = !!isLeapMonth;
var leapOffset = 0;
var leapMonth = calendar.leapMonth(y);
var leapDay = calendar.leapDays(y);
if(isLeapMonth&&(leapMonth!=m)) {return -1;}//传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
if(y==2100&&m==12&&d>1 || y==1900&&m==1&&d<31) {return -1;}//超出了最大极限值
var day = calendar.monthDays(y,m);
var _day = day;
//bugFix 2016-9-25
//if month is leap, _day use leapDays method
if(isLeapMonth) {
_day = calendar.leapDays(y,m);
}
if(y < 1900 || y > 2100 || d > _day) {return -1;}//参数合法性效验
//计算农历的时间差
var offset = 0;
for(var i=1900;i<y;i++) {
offset+=calendar.lYearDays(i);
}
var leap = 0,isAdd= false;
for(var i=1;i<m;i++) {
leap = calendar.leapMonth(y);
if(!isAdd) {//处理闰月
if(leap<=i && leap>0) {
offset+=calendar.leapDays(y);isAdd = true;
}
}
offset+=calendar.monthDays(y,i);
}
//转换闰月农历 需补充该年闰月的前一个月的时差
if(isLeapMonth) {offset+=day;}
//1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
var stmap = Date.UTC(1900,1,30,0,0,0);
var calObj = new Date((offset+d-31)*86400000+stmap);
var cY = calObj.getUTCFullYear();
var cM = calObj.getUTCMonth()+1;
var cD = calObj.getUTCDate();
return calendar.solar2lunar(cY,cM,cD);
}
};
export default calendar

View File

@ -0,0 +1,15 @@
@font-face {font-family: "iconfont";
src: url('data:font/truetype;charset=utf-8;base64,d09GRgABAAAAAASEAAsAAAAABuwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFY7d0f0Y21hcAAAAYAAAABTAAABhmJUzs9nbHlmAAAB1AAAALcAAADIzC0F5mhlYWQAAAKMAAAALwAAADYS7IZUaGhlYQAAArwAAAAcAAAAJAfeA4RobXR4AAAC2AAAAAwAAAAMDAAAAGxvY2EAAALkAAAACAAAAAgANgBkbWF4cAAAAuwAAAAfAAAAIAEOACluYW1lAAADDAAAAUUAAAJtPlT+fXBvc3QAAARUAAAALQAAAEOUPjuMeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2BkYWCcwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGByeMj5jYm7438AQw9zA0AAUZgTJAQDdSgvleJztkMERgDAIBPdIzMOxEB8W5MvuTRsRMHbhzSwHR/IBWIDiHE4FXYjQ6akyL6yZ13zT3IXd6jYGfO6S75q7xT81fm1Z9zlZXOsl+j5BD35IDU4AeJwVzUEOwUAYBeD/mfxTEso/mkEJoYluqgtajUjYsHEOSytncROJK/QErjNMd+8lL+8jEP3eqq8uNCPiokK1L4t1ihzVCSPMEekAep3mQCh4tpVm95JWz2QGj3iyiN3LZMJBODU49IMuDxk32YifuI89X4+xqwcsHUtEjfVVWt1p5MvWNs9RY4RowNLrJ7Tq8ZKNN7wmvMp8jBc7PDpW3RPfPrISV5ss4QEO9pxcdrix/gMMIyHOAHicY2BkYGAAYmNBZtV4fpuvDNwsDCBw/dlCBQT9fzMLA3MKkMvBwAQSBQDyNAlAAHicY2BkYGBu+N/AEMPCAAJAkpEBFTADAEcJAmwEAAAABAAAAAQAAAAAAAAAADYAZHicY2BkYGBgZpBlANEMDExAzAWEDAz/wXwGAAuHATgAeJxlj01OwzAQhV/6B6QSqqhgh+QFYgEo/RGrblhUavdddN+mTpsqiSPHrdQDcB6OwAk4AtyAO/BIJ5s2lsffvHljTwDc4Acejt8t95E9XDI7cg0XuBeuU38QbpBfhJto41W4Rf1N2MczpsJtdGF5g9e4YvaEd2EPHXwI13CNT+E69S/hBvlbuIk7/Aq30PHqwj7mXle4jUcv9sdWL5xeqeVBxaHJIpM5v4KZXu+Sha3S6pxrW8QmU4OgX0lTnWlb3VPs10PnIhVZk6oJqzpJjMqt2erQBRvn8lGvF4kehCblWGP+tsYCjnEFhSUOjDFCGGSIyujoO1Vm9K+xQ8Jee1Y9zed0WxTU/3OFAQL0z1xTurLSeTpPgT1fG1J1dCtuy56UNJFezUkSskJe1rZUQuoBNmVXjhF6XNGJPyhnSP8ACVpuyAAAAHicY2BigAAuBuyAmZGJkZmRhYEnKzMxryS/tDgjMS+dC8qpzC9lYAAAiPIJlAAAAA==');
}
.iconfont {
font-family:"iconfont" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-arrow-right:before { content: "\e602"; }
.icon-arrow-left:before { content: "\e501"; }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,394 @@
.mpvue-calendar {
margin:auto;
width: 100%;
min-width:300rpx;
background: #fff;
user-select:none;
position: relative;
}
.calendar-tools{
height:40px;
font-size: 20px;
line-height: 40px;
color:#5e7a88;
box-shadow: 0rpx 4rpx 8rpx rgba(25, 47, 89, 0.1);
margin-bottom: 30rpx;
border-top: 1px solid rgba(200, 200, 200, .1);
}
.calendar-prev{
width: 14.28571429%;
float:left;
text-align: center;
}
.calendar-prev img, .calendar-next img{
width: 34rpx;
height: 34rpx;
}
.calendar-info{
padding-top: 3px;
font-size:16px;
line-height: 1.3;
text-align: center;
width: 220rpx;
margin: 0 auto;
}
.calendar-info>div.mc-month{
margin:auto;
height:40rpx;
width:100px;
text-align: center;
color:#5e7a88;
overflow: hidden;
position: relative;
}
.calendar-info>div.mc-month .mc-month-inner{
position: absolute;
left:0;
top:0;
height:480rpx;
}
.month-transition{
transition:top .5s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.calendar-info .mc-month-text{
display:block;
font-size:28rpx;
height:40rpx;
width:200rpx;
overflow:hidden;
text-align:center;
}
.calendar-info>div.mc-month .mc-month-inner>span{
display: block;
font-size: 14px;
height:20px;
width:100px;
overflow: hidden;
text-align: center;
}
.calendar-info>div.mc-year{
font-size:10px;
line-height: 1;
color:#999;
}
.calendar-next{
width: 14.28571429%;
float:right;
text-align: center;
}
.mpvue-calendar table {
clear: both;
width: 100%;
margin-bottom:10px;
border-collapse: collapse;
color: #444444;
}
.mpvue-calendar td {
margin:2px !important;
padding:0px 0;
width: 14.28571429%;
height:88rpx;
text-align: center;
vertical-align: middle;
font-size:14px;
line-height: 125%;
cursor: pointer;
position: relative;
vertical-align: top;
}
.mpvue-calendar td.mc-week{
font-size:10px;
pointer-events:none !important;
cursor: default !important;
}
.mpvue-calendar td.disabled {
color: #ccc;
}
.mpvue-calendar td.disabled div{
color: #ccc;
}
.mpvue-calendar td span{
display:block;
height:76rpx;
width:76rpx;
font-size: 28rpx;
line-height:76rpx;
margin:0px auto;
position: relative;
z-index: 3;
}
.mpvue-calendar td:not(.disabled) span.mc-date-red{
color:#ea6151;
}
.mc-today{
color: #3b75fb;
}
.mpvue-calendar td.selected span{
background-color: #3b75fb;
color: #fff;
border-radius:50%;
}
.mpvue-calendar td .mc-text{
position: absolute;
top:28px;
left:0;
right:0;
text-align: center;
padding:2px;
font-size:20rpx;
line-height: 1.2;
color:#444;
z-index: 4;
}
.mpvue-calendar td .isGregorianFestival,
.mpvue-calendar td .isTerm,
.mpvue-calendar td .isLunarFestival{
color:#ea6151;
}
.mpvue-calendar td.selected span.mc-date-red{
background-color: #3b75fb;
color: #fff;
}
.selected .mc-text {
color: #fff !important;
}
.mpvue-calendar .lunarStyle span{
width: 80rpx;
height: 80rpx;
line-height:54rpx;
}
.mpvue-calendar .lunarStyle .mc-text{
top: 44rpx;
}
.mpvue-calendar thead td {
text-transform: uppercase;
height:30px;
vertical-align: middle;
}
.mc-head {
margin-bottom: 20rpx;
}
.mc-head div {
overflow: hidden;
}
.mc-head-box div {
flex:1;
text-align: center;
}
.mc-head-box {
display: flex;
flex-direction: row;
justify-content: center;
align-content: space-between
}
.mc-head-box div {
font-size: 28rpx;
}
.mc-body tr {
display: flex;
flex-direction: row;
justify-content: center;
align-content: space-between
}
.mc-dot {
width: 10rpx;
height: 10rpx;
background-color: #ea6151;
border-radius: 50%;
margin: 0 auto;
margin-top: 5rpx;
position: absolute;
bottom: -5rpx;
left: 50%;
margin-left: -5rpx;
z-index: 5;
}
.remark-text {
padding-left: 8rpx;
padding-right: 8rpx;
box-sizing: border-box;
height: 34rpx;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.slot-element{
line-height: normal;
position: absolute;
z-index: 5;
}
.mpvue-calendar-change{
position: absolute;
left:0rpx;
top:85rpx;
right:0rpx;
bottom:0rpx;
background:#fff;
display: flex;
justify-content: center;
align-items: center;
flex-wrap:wrap;
overflow: auto;
transition:all .5s cubic-bezier(0.075, 0.82, 0.165, 1);
opacity: 0;
pointer-events: none;
transform: translateY(-10px);
z-index: 9;
}
.mpvue-calendar-change.show{
opacity: 1;
pointer-events: auto;
transform: translateY(0px);
}
.mpvue-calendar-change span{
margin:4px 2%;
display: inline-block;
line-height: 30px;
border-radius: 20px;
text-align:center;
color:#999;
width: 20%;
float: left;
text-align: center;
border-radius: 40px;
box-sizing: border-box;
margin-bottom: 4%;
}
.mpvue-calendar-change span.active{
background-color: #587dff;
box-shadow: 2px 2px 2px rgba(88, 125, 255, 0.7);
color:#fff;
}
.mpvue-calendar-change .calendar-week-switch-months{
height: 100%;
padding: 10rpx 20rpx;
}
.mpvue-calendar-change .calendar-week-switch-months span {
margin-bottom: 20rpx;
margin-top: 0px;
font-size: 26rpx;
line-height: 40rpx;
}
.calendar-years, .calendar-months{
height: 50%;
width: 100%;
padding: 10px;
box-sizing: border-box;
position: relative;
}
.calendar-years:after {
content: '';
display: block;
width: 86%;
height: 1rpx;
background-color: #eee;
position: absolute;
bottom: 2%;
left: 7%;
}
/*range background*/
.mc-range-mode .selected .mc-range-bg{
content: '';
display: block;
width: 110rpx;
height: 80rpx;
background-color: #01a1ed;
position: absolute;
top: 0rpx;
left: 50%;
}
.mpvue-calendar .mc-range-mode .selected .calendar-date{
background-color: transparent;
}
.mpvue-calendar .mc-range-mode .mc-range-row-last span.calendar-date, .mpvue-calendar .mc-range-mode .mc-range-row-first span.calendar-date{
border-radius: 6rpx;
background-color: #01a1ed;
}
.mpvue-calendar .mc-range-mode .mc-range-month-first.selected .calendar-date, .mpvue-calendar .mc-range-mode .mc-range-month-last.selected .calendar-date{
border-radius: 6rpx;
background-color: #01a1ed;
}
.mc-range-mode .mc-range-month-last .mc-range-bg{
background-color: transparent;
border-radius: 6rpx;
}
.mc-range-mode .mc-range-end .mc-range-bg, .mc-range-mode .mc-range-row-last .mc-range-bg{
display: none;
}
.mpvue-calendar .mc-range-mode .mc-range-end span.calendar-date, .mpvue-calendar .mc-range-mode .mc-range-begin span.calendar-date{
background-color: #3b75fb;
color: #fff;
border-radius: 50%;
}
.mc-range-mode .mc-range-row-first.mc-range-end .mc-range-bg{
display: block;
border-radius: 6rpx;
width: 40rpx;
left: 5px;
}
.mpvue-calendar .mc-range-row-first.mc-range-end.month-first-date .mc-range-bg{
margin-left: 0px;
}
.mc-range-mode .mc-range-row-last.mc-range-begin .mc-range-bg{
display: block;
border-radius: 4rpx;
width: 40rpx;
right: 10px;
}
.mpvue-calendar .mc-range-mode .month-last-date.mc-range-begin .mc-range-bg{
display: block;
width: 40rpx;
border-radius: 6rpx;
}
.mpvue-calendar .mc-range-mode .month-first-date.mc-range-end .mc-range-bg{
display: block;
width: 40rpx;
border-radius: 6rpx;
left: 10rpx;
}
.mpvue-calendar .mc-range-mode .mc-range-select-one div.mc-range-bg{
display: none !important;
}
.mc-body .mc-today-element .calendar-date{
background-color: rgba(25, 47, 89, 0.1);
border-radius: 6rpx;
}
/*week switch*/
.mpvue-calendar .mc-range-mode.week-switch .month-last-date.mc-range-begin .mc-range-bg{
width: 130%;
border-radius: 0px 20% 20% 0px;
}
.mpvue-calendar .mc-range-mode.week-switch .mc-range-month-last .mc-range-bg{
background-color: #01a1ed;
border-radius: 0px 20% 20% 0px;
}
/*month range*/
.mpvue-calendar .month-range-mode{
border-bottom: 1px solid #f2f2f2;
position: relative;
}
.mpvue-calendar .mc-month-range-mode-head{
box-shadow: 0 4px 8px rgba(25,47,89,.1);
padding: 15rpx 0rpx;
position: sticky;
top: 0px;
background-color: #fff;
z-index: 9;
}
.month-range-mode .month-rang-head {
text-align: left;
margin: 20rpx 0px;
padding-left: 40rpx;
font-size: 28rpx;
}
.month-range-mode .mc-last-month, .month-range-mode .mc-next-month{
opacity: 0 !important;
}
.month-text-background{
position: absolute;
font-size: 140px;
width: 100%;
height: 100%;
text-align: center;
line-height: 2.4;
}

View File

@ -0,0 +1,291 @@
<template>
<view :style="viewColor">
<view class='coupon-list-window animated' :class='coupon.status==true?"slideInUp":""'>
<view class='title'>
<view class="item">{{couponTitle}}<text class='iconfont icon-guanbi' @tap='close'></text></view>
</view>
<block v-if="couponArr.length">
<view class='coupon-list'>
<view class='item acea-row row-center-wrapper' :class="item.disabled ? 'disabled' : ''"
v-for="(item,index) in couponArr" @click="getCouponUser(index,item)" :key='index'>
<view v-if="item.coupon.send_type == 5" class='money acea-row row-column row-center-wrapper vip-coupon'>
<view><text class='num'>{{item.coupon_price}}</text></view>
<view class="pic-num">{{item.use_min_price}}元可用</view>
</view>
<view v-else class='money acea-row row-column row-center-wrapper' :style="{ 'background-image': `url(${domain}/static/diy/couponBg${keyColor}.png)` }">
<view><text class='num'>{{item.coupon_price}}</text></view>
<view class="pic-num">{{item.use_min_price}}元可用</view>
</view>
<view class='text'>
<view class='condition line1'>
<span class='line-title' v-if='item.coupon.type===0'>店铺券</span>
<span class='line-title' v-else-if='item.coupon.type===1'>商品券</span>
<span>{{item.coupon_title}}</span>
</view>
<view class='data acea-row row-between-wrapper'>
<view>{{ item.start_time | timeYMD }} ~ {{ item.end_time | timeYMD}}</view>
<view class="iconfont icon-weixuanzhong" v-if="!item.checked"></view>
<view class='iconfont icon-xuanzhong1' v-else></view>
</view>
</view>
</view>
</view>
<view class="foot-box">
<view class="left">
已选择{{coupon_number}}可优惠<text>{{coupon_amount}}</text>
</view>
</view>
</block>
<!-- 无优惠券 -->
<view class='pictrue' v-else>
<image src='../../static/images/noCoupon.png'></image>
</view>
</view>
<view class='mask' catchtouchmove="true" :hidden='coupon.status==false' @click='close'></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { setCouponReceive } from '@/api/api.js';
import { mapGetters } from "vuex";
import { HTTP_REQUEST_URL } from '@/config/app';
export default {
props: {
// 0=,1=使
openType: {
type: Number,
default: 0,
},
coupon: {
type: Object,
default: function() {
return {};
}
},
coupon_amount: {
type: Number
},
coupon_number: {
type: Number
},
couponTitle: {
type: String,
default: '优惠券',
}
},
filters: {
timeYMD: function(value) {
if(value){
var newDate=/\d{4}-(\d{1,2}\d{1,2}-\d{1,2}\d{1,2})/g.exec(value)
return newDate?.[0]||''
}
}
},
computed: mapGetters(['viewColor','keyColor']),
data() {
return {
domain: HTTP_REQUEST_URL,
couponArr: [],
couponData: {},
//
active: {},
allNum: 0,
allCouponNum: 0,
// id
use_store_coupon: 0,
//
pay_price: 0,
//
goodsOrder: '',
moneyBg: '/static/images/couponBg',
};
},
watch: {
coupon:{
handler(nVal,oVal){
this.couponArr = JSON.parse(JSON.stringify(nVal.coupon))
},
immediate: true,
deep:true
}
},
mounted() {
this.couponData = this.coupon
// 使
this.couponArr = JSON.parse(JSON.stringify(this.coupon.coupon))
// 使
// this.goodsOrder = JSON.parse(JSON.stringify(this.coupon.order))
let tempObj = this.active[this.couponData.mer_id] = {}
tempObj.product = []
tempObj.store = ''
},
methods: {
close: function() {
this.$emit('ChangCouponsClone');
},
// 使
getCouponUser: function(index, item) {
this.$emit('getCoupon',item);
}
}
}
</script>
<style scoped lang="scss">
.animated {
animation-duration: .3s
}
.title {
display: flex;
.item {
position: relative;
flex: 1;
font-size: 28rpx;
color: #999999;
&::after {
content: ' ';
position: absolute;
left: 50%;
bottom: 18rpx;
width: 50rpx;
height: 5rpx;
background: transparent;
border-radius: 3px;
transform: translateX(-50%);
}
&.on {
color: #282828;
&::after {
background: var(--view-theme);
}
}
}
}
.coupon-list {
padding: 30rpx;
.item {
box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.06);
&.disabled{
pointer-events:none;
opacity: .6;
.iconfont{
background-color: #eee;
border-radius: 100%;
}
}
}
}
.coupon-list-window {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
border-radius: 16rpx 16rpx 0 0;
z-index: 555;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
}
.coupon-list-window.on {
animation: aminup;
}
.coupon-list-window .title {
height: 106rpx;
width: 100%;
text-align: center;
line-height: 106rpx;
font-size: 32rpx;
font-weight: bold;
position: relative;
border: 1px solid #f5f5f5;
}
.coupon-list-window .title .iconfont {
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
font-size: 35rpx;
color: #8a8a8a;
font-weight: normal;
}
.coupon-list-window .coupon-list {
margin: 0 0 0rpx 0;
height: 550rpx;
overflow: auto;
}
.coupon-list-window .pictrue {
width: 414rpx;
height: 336rpx;
margin: 0 auto 50rpx auto;
}
.coupon-list-window .pictrue image {
width: 100%;
height: 100%;
}
.pic-num {
color: #fff;
font-size: 24rpx;
}
.line-title {
width: 90rpx;
padding: 0 10rpx;
box-sizing: border-box;
background: rgba(255, 247, 247, 1);
border: 1px solid var(--view-theme);
opacity: 1;
border-radius: 20rpx;
font-size: 20rpx;
color: var(--view-theme);
margin-right: 12rpx;
}
.line-title.gray {
border-color: #BBB;
color: #bbb;
background-color: #F5F5F5;
}
.foot-box {
display: flex;
align-items: center;
justify-content: space-between;
height: 100rpx;
padding: 0 30rpx;
border-top: 1px solid #F5F5F5;
.btn {
width: 240rpx;
height: 70rpx;
line-height: 70rpx;
text-align: center;
background: var(--view-theme);;
border-radius: 35rpx;
color: #fff;
font-size: 30rpx;
}
.left {
text {
color: var(--view-priceColor);
}
}
}
.coupon-list .item .text .data .iconfont {
font-size: 36rpx;
&.icon-weixuanzhong {
color: #BFBFBF;
}
&.icon-xuanzhong1 {
color: var(--view-theme);;
}
}
</style>

View File

@ -0,0 +1,444 @@
<template>
<view class="orderGoods" :style="viewColor">
<view class='goodWrapper' :class="'item'+orderData.order_type">
<view v-if="orderData.order_type == 1" class="title acea-row row-between-wrapper">
<view class="item-status" :class="'status'+evaluate">{{evaluate == 0 ? '待核销' : '已核销'}}</view>
<view v-if="evaluate != 0 && orderData.verify_time" class="item-date">{{orderData.verify_time}}</view>
</view>
<view v-for="(item,index) in cartInfo" :key="index">
<view v-if="activityType === 2">
<view class='item presell_item'>
<view class="acea-row row-between-wrapper">
<view class='pictrue' @click="jumpCon(item)">
<image
:src='(item.cart_info.productAttr && item.cart_info.productAttr.image) || item.cart_info.product.image'>
</image>
</view>
<view class='text'>
<view class='acea-row row-between-wrapper'>
<view class='name line1' style="width: 360rpx;"><text
class="event_name event_bg">预售</text>{{item.cart_info.product.store_name}}
</view>
<view class='num'><text
class="p-color">{{item.cart_info.productPresellAttr.presell_price}}</text><br />x
{{item.product_num}}</view>
</view>
<view class='attr line1' v-if="item.cart_info.productAttr.sku" style="margin-top: 0;">
{{item.cart_info.productAttr.sku}}</view>
<view v-if="evaluate === 0 || evaluate === 10 || evaluate === 11"
class="event_ship event_color">发货时间
<!--全款预售-->
<text
v-if="item.cart_info.productPresell.presell_type === 1">{{ item.cart_info.productPresell.delivery_type === 1 ? '支付成功后' : '预售结束后' }}{{ item.cart_info.productPresell.delivery_day }}天内</text>
<!--定金预售-->
<text
v-if="item.cart_info.productPresell.presell_type === 2">{{ item.cart_info.productPresell.delivery_type === 1 ? '支付尾款后' : '预售结束后' }}{{ item.cart_info.productPresell.delivery_day }}天内</text>
</view>
<view class="right-btn-box event_box">
<view class="btn-item"
v-if="(item.is_refund ==0 && (evaluate != 10 && evaluate != 11) && orderData.refund_status || item.refund_num > 0)&&evaluate>=0 && evaluate != 1&& evaluate == 2"
@click.stop="refund(item)">申请退款</view>
<view class="btn-item err" v-if="item.is_refund ==1">退款中 x
{{item.product_num - item.refund_num}}</view>
<view class='btn-item err' v-if="item.is_refund >1">已退款 x
{{item.product_num - item.refund_num}}</view>
<view class='btn-item' v-if='item.is_reply==0 && evaluate==2 && item.is_refund==0'
@click.stop="evaluateTap(item.order_product_id,orderId)">去评价</view>
<view class='btn-item on' v-else-if="item.is_reply==1 && evaluate==2">已评价</view>
</view>
</view>
</view>
</view>
<view v-if="orderData.status >= 10" class="event_progress">
<view class="progress_list">
<view class="progress_name">阶段一 买家已付款</view>
<view class="progress_price">商品定金 <text
class="align_right">{{ orderData.pay_price }}</text></view>
<view class="progress_pay">定金实付款<text
class="align_right t-color">{{ orderData.pay_price }}</text></view>
</view>
<view class="progress_list">
<view class="progress_name">阶段二
<text
v-if="orderData.status == 10 && orderData.presellOrder.activeStatus == 0">未开始</text>
<text
v-if="orderData.status == 10 && orderData.presellOrder.activeStatus == 1">等待买家付尾款</text>
<text
v-if="orderData.status == 11 || orderData.presellOrder.activeStatus == 2">交易已关闭</text>
</view>
<view class="progress_price">商品尾款 <text
class="align_right">{{ orderData.presellOrder.pay_price }}</text></view>
<view class="progress_pay">尾款需付款<text
class="align_right t-color">{{ orderData.presellOrder.pay_price }}</text></view>
</view>
</view>
</view>
<view v-else class='item'>
<view class="acea-row row-between-wrapper">
<view class='pictrue' @click="jumpCon(item)">
<image
:src='(item.cart_info.productAttr && item.cart_info.productAttr.image) || item.cart_info.product.image'>
</image>
</view>
<view class='text'>
<view class='acea-row row-between-wrapper'>
<view class='name line1'><text v-if="item.product_type != 0 && item.product_type != 10"
:class="'font_bg-red type'+item.product_type">{{item.product_type == 1 ? "秒杀" : item.product_type == 2 ? "预售" : item.product_type == 3 ? "助力" : item.product_type == 4 ? "拼团" : ""}}</text>{{item.cart_info.product.store_name}}
</view>
<view class='num'>x {{item.product_num}}</view>
</view>
<view class='attr line1' v-if="item.cart_info.productAttr.sku">
{{item.cart_info.productAttr.sku}}</view>
<view class='money p-color' v-if="item.cart_info.product_type ==3">
{{item.cart_info.productAssistAttr.assist_price}}</view>
<view class='money p-color' v-else-if="item.cart_info.product_type ==4">
{{item.cart_info.activeSku.active_price}}</view>
<view class='money acea-row row-middle' v-else>
<text>{{item.cart_info.productAttr.price}}</text>
<image v-if="item.cart_info.productAttr.show_svip_price" class="svip-img"
src="/static/images/svip.png"></image>
</view>
</view>
</view>
<view class="right-btn-box">
<view class="btn-item err" v-if="item.is_refund ==1">退款中 x
{{item.product_num - item.refund_num}}</view>
<view class='btn-item err' v-if="item.is_refund >1">已退款 x {{item.product_num - item.refund_num}}
</view>
<view class="btn-item"
v-if="(item.is_refund ==0 && (evaluate != 10 && evaluate != 11) && orderData.refund_status || item.refund_num > 0)&& evaluate!=9 &&evaluate != 1&&evaluate !=4&& evaluate!=3 || evaluate==2"
@click.stop="refund(item)">申请退款</view>
<view class='btn-item'
v-if='item.is_reply==0 && evaluate!=2&& evaluate!=3&& evaluate!=7&& evaluate!=8&& evaluate!=9&& item.refund_num > 0'
@click.stop="evaluateTap(item.order_product_id,orderId)">去评价</view>
<view class='btn-item on' v-else-if="item.is_reply==1 && evaluate==2">已评价</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import {
openOrderRefundSubscribe
} from '@/utils/SubscribeMessage.js';
import {
goShopDetail
} from '@/libs/order.js'
import {
initiateAssistApi
} from '@/api/activity.js';
import {
mapGetters
} from "vuex";
export default {
props: {
evaluate: {
type: Number,
default: 0,
},
activityType: {
type: Number,
default: 0,
},
cartInfo: {
type: Array,
default: function() {
return [];
}
},
orderId: {
type: String,
default: '',
},
jump: {
type: Boolean,
default: false,
},
orderData: {
type: Object,
default: function() {
return {};
}
}
},
computed: mapGetters(['viewColor']),
data() {
return {
totalNmu: '',
isTimePay: false, //
};
},
watch: {
cartInfo: function(nVal, oVal) {
let num = 0
nVal.forEach((item, index) => {
num += item.cart_num
})
this.totalNmu = num
}
},
onShow() {
this.isPayBalance()
},
mounted() {},
methods: {
evaluateTap: function(unique, orderId) {
uni.navigateTo({
url: `/pages/users/goods_comment_con/index?uni=${unique}&order_id=${orderId}`
})
},
//
isPayBalance() {
let that = this;
if (that.orderData.status === 10) {
if (new Date() < new Date(that.orderData.presellOrder.final_start_time)) {
that.isTimePay = false; //
} else if ((new Date() >= new Date(that.orderData.presellOrder.final_start_time)) && (new Date() <=
new Date(that.orderData.presellOrder.final_start_time))) {
that.isTimePay = true; //
}
}
},
jumpCon: function(item) {
if (item.product_type == 4) item.activity_id = item.cart_info && item.cart_info.activeSku
.product_group_id
if (item.product_type == 3) item.activity_id = item.cart_info && item.cart_info.productAssistAttr
.product_assist_id
goShopDetail(item).then(res => {
initiateAssistApi(item.activity_id).then(res => {
let id = res.data.product_assist_set_id;
uni.hideLoading();
uni.navigateTo({
url: '/pages/activity/assist_detail/index?id=' + id
});
}).catch((err) => {
uni.showToast({
title: err,
icon: 'none'
})
});
})
},
// 退
refund(item) {
// #ifdef MP
openOrderRefundSubscribe().then(() => {
uni.hideLoading();
if (this.evaluate == 0 || this.evaluate == 9 || this.orderData.is_virtual == 1) {
uni.navigateTo({
url: '/pages/users/refund/confirm?order_id=' + this.orderId + '&type=1' +
'&ids=' + item.order_product_id + '&refund_type=1&order_type=' + this
.orderData.order_type
})
} else {
uni.navigateTo({
url: '/pages/users/refund/select?order_id=' + this.orderId +
'&type=1&order_type=' + this.orderData.order_type + '&ids=' + item
.order_product_id
})
}
}).catch(() => {
uni.hideLoading();
})
// #endif
// #ifdef H5 || APP-PLUS
if (this.evaluate == 0 || this.evaluate == 9 || this.orderData.is_virtual == 1) {
uni.navigateTo({
url: '/pages/users/refund/confirm?order_id=' + this.orderId + '&type=1' + '&ids=' + item
.order_product_id + '&refund_type=1&order_type=' + this.orderData.order_type
})
} else {
uni.navigateTo({
url: '/pages/users/refund/select?order_id=' + this.orderId + '&type=1&order_type=' + this
.orderData.order_type + '&ids=' + item.order_product_id
})
}
// #endif
}
}
}
</script>
<style scoped lang="scss">
.orderGoods {
background-color: #fff;
}
.p-color {
color: var(--view-priceColor);
}
.t-color {
color: var(--view-theme);
}
.svip-img {
width: 65rpx;
height: 28rpx;
margin: 4rpx 0 0 4rpx;
}
.title {
height: 86rpx;
position: relative;
padding: 0 30rpx;
&::after {
content: "";
width: 750rpx;
border-bottom: 2rpx dotted #D8D8D8;
position: absolute;
bottom: 0;
left: 0;
}
.item-status {
color: #999999;
font-size: 30rpx;
&.status0 {
color: #2291F8;
}
}
.item-date {
color: #666666;
font-size: 28rpx;
}
}
.right-btn-box {
display: flex;
align-items: center;
justify-content: flex-end;
&.event_box {
position: static;
}
.btn-item {
display: flex;
align-items: center;
justify-content: center;
width: 140rpx;
height: 46rpx;
margin-left: 10rpx;
border: 1px solid rgba(187, 187, 187, 1);
border-radius: 23rpx;
font-size: 24rpx;
color: #282828;
&.on {
background: rgba(220, 220, 220, 1);
border-color: rgba(220, 220, 220, 1);
}
&.err {
background: rgba(247, 247, 247, 1);
border-color: rgba(247, 247, 247, 1);
color: #AAAAAA;
}
}
}
.event_bg {
background: #FF7F00;
}
.event_color {
color: #FF7F00;
}
.presell_item {
height: auto;
padding-bottom: 15rpx;
}
.event_progress {
margin-top: 20rpx;
background: #fff;
.progress_name {
padding-left: 30rpx;
height: 60rpx;
line-height: 60rpx;
font-size: 24rpx;
font-weight: bold;
position: relative;
color: var(--view-theme);
&::before {
content: "";
display: inline-block;
width: 5rpx;
height: 34rpx;
background: var(--view-theme);
position: absolute;
top: 15rpx;
left: 0;
}
}
.align_right {
float: right;
font-weight: bold;
}
.progress_price {
padding: 20rpx 30rpx;
color: #999999;
font-size: 22rpx;
}
.progress_pay {
padding: 25rpx 30rpx;
background: var(--view-minorColor);
font-size: 26rpx;
color: #282828;
}
}
.event_name {
display: inline-block;
margin-right: 9rpx;
color: #fff;
font-size: 20rpx;
padding: 0 8rpx;
line-height: 30rpx;
text-align: center;
border-radius: 6rpx;
}
.event_ship {
font-size: 20rpx;
margin-top: 10rpx;
}
.goodWrapper.item1 {
&::after {
content: "";
display: block;
width: 750rpx;
height: 14rpx;
background: #F0F0F0;
}
}
</style>

View File

@ -0,0 +1,221 @@
<template>
<view class='productSort'>
<view class="title">
参与话题
<text class="iconfont icon-guanbi5" @click="close"></text>
</view>
<view class="con-box">
<view class='aside'>
<scroll-view scroll-y="true" style="height: 100%; overflow: hidden;">
<view v-for="(item,index) in productList" :key="item.category_id">
<view v-show="item.children && item.children.length > 0" class='item acea-row row-center-wrapper'
:class='index==navActive?"on":""' @click='tap(index,"b"+index)'><text
class="item_text">{{item.cate_name}}</text>
</view>
</view>
</scroll-view>
</view>
<view class='conter'>
<scroll-view scroll-y="true" style="height: 100%; overflow: hidden;">
<view v-for="(item,index) in childList" :key="item.topic_id">
<view class='list' @click.stop="confirmTopic(item)">
<view class='item acea-row'>
<view class='picture'>
<image :src='item.pic'></image>
</view>
<view class="name line1">{{item.topic_name}}</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
let app = getApp();
import { getTopicList } from '@/api/community.js';
export default {
data() {
return {
navlist: [],
productList: [],
navActive: 0,
childList: []
}
},
watch: {},
mounted() {
if (!this.productList.length) {
this.getAllCategory();
}
},
methods: {
//
close() {
this.$emit('close');
},
tap: function(index, id) {
this.navActive = index;
this.childList = this.productList[index].children
},
getAllCategory: function() {
let that = this;
let value = ""
getTopicList().then(res => {
let arr = [
// {category_id: "",count_use: 0,count_view: 0,pic: null,topic_id: '',topic_name: ""}
]
that.productList = res.data;
if (that.productList[0].children && that.productList[0].children.length > 0) {
that.productList[0].children = [...arr, ...that.productList[0].children]
} else {
that.productList[0].children = arr
}
that.childList = that.productList[0].children;
})
},
confirmTopic(item) {
this.$emit('getTopic', item);
}
}
}
</script>
<style scoped lang="scss">
.productSort {
display: flex;
flex-direction: column;
width: 100%;
height: 70vh;
background: #ffffff;
border-radius: 16rpx 16rpx 0 0;
.title {
text-align: center;
padding: 40rpx 0;
position: relative;
color: #333333;
font-size: 34rpx;
font-weight: bold;
.iconfont {
color: #8A8A8A;
font-size: 28rpx;
position: absolute;
right: 30rpx;
top: 42rpx;
font-weight: normal;
}
}
.con-box {
flex: 1;
display: flex;
overflow: hidden;
}
}
.productSort .aside {
overflow-y: auto;
overflow-x: hidden;
border-right: 1px solid #EEEEEE;
width: 202rpx;
height: 100%;
overflow: hidden;
}
.productSort .aside .item {
line-height: 100rpx;
width: 100%;
font-size: 26rpx;
color: #666666;
}
.productSort .aside .item_text {
padding-left: 20rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.productSort .aside .item.on {
width: 100%;
text-align: center;
font-weight: bold;
color: #333333;
}
.productSort .conter {
flex: 1;
height: 100%;
padding: 0 30rpx;
background-color: #ffffff;
margin-top: 20rpx;
}
.productSort .conter .list {
flex-wrap: wrap;
}
.productSort .conter .list .item {
margin-top: 26rpx;
margin-bottom: 40rpx;
align-items: center;
}
.productSort .conter .list .item .picture {
width: 88rpx;
height: 88rpx;
border-radius: 100%;
position: relative;
&::before {
content: "#";
display: block;
width: 88rpx;
height: 88rpx;
line-height: 88rpx;
border-radius: 100%;
color: #ffffff;
font-size: 40rpx;
text-align: center;
position: absolute;
top: 0;
left: 0;
background: rgba(0, 0, 0, .3);
}
}
.productSort .conter .listw:first-child .picture {
&::before {
content: "\\";
background: #D8D8D8;
}
}
.productSort .conter .list .item .picture image {
width: 100%;
height: 100%;
border-radius: 100%;
}
.productSort .conter .list .name {
margin-left: 30rpx;
font-size: 28rpx;
color: #282828;
font-weight: bold;
max-width: 300rpx;
}
</style>

View File

@ -0,0 +1,268 @@
<template>
<view>
<view class='password-window' :class='window==true?"on":""'>
<view class='passwordCount'>
<view class="title1 acea-row row-between-wrapper">
<image :src="userInfo.avatar" class="picture"></image>
<text class="name line1">{{userInfo.nickname}}</text>
给你分享了宝贝
</view>
<view class="banner">
<image :src="storeInfo.image"></image>
</view>
<view class="pro-info">
<view class="price acea-row">¥<text class="money">{{storeInfo.price}}</text>
<text v-if="storeInfo.product_type == 0" class="pro_type">普通商品</text>
</view>
<view class="name line1">{{storeInfo.store_name}}</view>
</view>
<button v-if="storeInfo.product_type != 3" class="go_btn" @click="goDetail(storeInfo)">查看详情</button>
<button v-if="storeInfo.product_type == 3" class="go_btn btn1" @click="goDetail(storeInfo)">帮他助力</button>
</view>
<view class='lid'>
<view class='iconfont icon-guanbi3' @click="close"></view>
</view>
</view>
<view class='mask' catchtouchmove="true" :hidden="window==false" style="z-index: 999;"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { pwdResolution } from '@/api/user.js'
import { mapGetters } from "vuex";
import {toLogin} from '@/libs/login.js';
import { goShopDetail } from '@/libs/order.js'
import {initiateAssistApi} from '@/api/activity.js';
export default {
props: {
isLogin:{
type: Boolean,
default: false
}
},
data() {
return {
window: false,
couponList: [],
userInfo: {
},
storeInfo: {
},
pwdInfo: {}
};
},
computed: mapGetters(["copyPwd", "uid"]),
watch: {
copyPwd:{
handler(nVal,oVal){
if(nVal)this.resolution(nVal)
},
immediate: true,
deep:true
}
},
mounted(){
},
beforeDestroy(){
},
methods: {
close:function(){
this.window = false
},
resolution(data){
let com = uni.getStorageSync('pwdKey')
pwdResolution(data).then(res => {
if(res.data.user && res.data.user.uid != this.uid && com !=res.data.com){
this.window = true;
this.pwdInfo = res.data;
this.userInfo = res.data.user;
this.storeInfo = res.data.data;
if(res.data.activity_id )this.storeInfo.activity_id = res.data.activity_id
if(res.data.product_type )this.storeInfo.product_type = res.data.product_type
this.$store.commit("PARSE_PWD", null)
uni.setStorageSync('pwdKey', res.data.com);
}
})
},
goDetail(item){
goShopDetail(item, this.uid).then(res => {
this.$store.commit("PARSE_PWD", null)
if (this.isLogin) {
initiateAssistApi(item.activity_id).then(res => {
let id = res.data.product_assist_set_id;
uni.hideLoading();
uni.navigateTo({
url: '/pages/activity/assist_detail/index?id=' + id
});
}).catch((err) => {
uni.showToast({
title: err,
icon: 'none'
})
});
} else {
// #ifdef H5 || APP-PLUS
toLogin();
// #endif
// #ifdef MP
this.$emit('isShowAuth', true);
this.$emit('isAuto', true);
// #endif
}
})
}
}
}
</script>
<style scoped lang="scss">
.password-window {
background-image: url('/static/images/passwordPop.png');
background-repeat: no-repeat;
background-size: 100% 100%;
background-color: #fff;
width: 580rpx;
height: 910rpx;
position: fixed;
top: 50%;
z-index: 1000;
left: 50%;
margin-left: -290rpx;
margin-top: -455rpx;
transform: translate3d(0, -200%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
border-radius: 24rpx;
padding: 25rpx 30rpx 40rpx;
}
.password-window.on {
transform: translate3d(0, 0, 0);
}
.passwordCount .title1{
width: 350rpx;
margin: 0 auto;
height: 42rpx;
background: #F1F1F1;
border-radius: 23rpx;
padding: 0 15rpx;
color: #666666;
font-size: 24rpx;
.picture{
width: 36rpx;
height: 36rpx;
border-radius: 100%;
image{
width: 36rpx;
height: 36rpx;
}
}
.name{
color: #282828;
font-weight: bold;
max-width: 100rpx;
margin: 0 10rpx;
}
}
.password-window .banner{
width: 520rpx;
height: 520rpx;
margin-top: 25rpx;
image{
width: 520rpx;
height: 520rpx;
border-radius: 16rpx;
}
}
.password-window .pro-info{
margin-top: 15rpx;
.price{
color: #E93323;
font-size: 26rpx;
justify-content: left;
align-items: center;
.money{
font-size: 42rpx;
}
}
.pro_type{
display: inline-block;
width: 100rpx;
height: 28rpx;
text-align: center;
line-height: 28rpx;
background: #FDEAE8;
margin-left: 30rpx;
font-size: 18rpx;
position: relative;
&::before{
content: "";
display: inline-block;
width: 0;
height: 0;
border-width: 15rpx 15rpx 15rpx 0;
border-style: solid;
border-color: transparent #FDEAE8 transparent transparent;
position: absolute;
left: -16rpx;
}
&::after{
content: "";
display: inline-block;
width: 6rpx;
height: 6rpx;
background: #fff;
border-radius: 100%;
position: absolute;
top: 12.5rpx;
left: -4rpx;
z-index: 10;
}
}
.name{
margin-top: 15rpx;
color: #282828;
font-size: 30rpx;
}
}
.password-window .lid {
position: absolute;
bottom: -100rpx;
left: 0;
width: 100%;
text-align: center;
}
.go_btn{
margin-top: 50rpx;
width: 520rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
background: #E93323;
color: #ffffff;
border-radius: 40rpx;
font-size: 28rpx;
&.btn1{
background: #FC8327
}
}
.password-window .lid .iconfont {
color: #fff;
font-size: 60rpx;
text-align: center;
margin-left: -30rpx;
}
</style>

View File

@ -0,0 +1,476 @@
<template>
<view>
<view class="payment" :class="pay_close ? 'on' : ''">
<view class="title acea-row row-center-wrapper">
选择付款方式<text class="iconfont icon-guanbi" @click='close'></text>
</view>
<view class="item acea-row row-between-wrapper" @click='goPay(item.number || 0 , item.value)'
v-for="(item,index) in payMode" :key="index" v-if="item.payStatus == 1">
<view class="left acea-row row-between-wrapper">
<view class="iconfont" :class="item.icon"></view>
<view class="text">
<view class="name">{{item.name}}</view>
<view class="info" v-if="item.number">
{{item.title}} <span class="money">{{ item.number }}</span>
</view>
<view class="info" v-else>{{item.title}}</view>
</view>
</view>
<view class="iconfont icon-xiangyou"></view>
</view>
</view>
<view class="mask" ref="close" @click='close' v-if="pay_close"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import {
orderPay,
presellOrderPay
} from '@/api/order.js';
export default {
props: {
payMode: {
type: Array,
default: function() {
return [];
}
},
pay_close: {
type: Boolean,
default: false,
},
order_id: {
type: String,
default: ''
},
totalPrice: {
type: String,
default: '0'
},
order_type: {
type: Number,
default: 0,
},
isCall: {
type: Boolean,
default: false
}
},
data() {
return {
};
},
methods: {
close: function() {
this.$emit('onChangeFun', {
action: 'payClose'
});
},
goPay: function(number, paytype) {
if (this.isCall) {
return this.$emit('onChangeFun', {
action: 'payCheck',
value: paytype
});
}
let that = this;
let type = ''
if (paytype == 'wechat') {
// #ifdef H5
type = this.$wechat.isWeixin() ? 'weixin' : 'h5';
// #endif
// #ifdef APP-PLUS
type = 'weixin';
// #endif
// #ifdef MP
type = 'routine';
// #endif
} else if (paytype == 'balance') {
type = 'balance';
console.log('123');
} else if (paytype == 'alipay') {
// #ifndef MP
type = 'alipay';
// #endif
// #ifdef MP
type = 'alipayQr';
// #endif
} else if (paytype == 'creditBuy') {
console.log('123123');
type = 'creditBuy'
}
if (!that.order_id) return that.$util.Tips({
title: '请选择要支付的订单'
});
if (paytype == 'balance' && parseFloat(number) < parseFloat(that.totalPrice)) return that.$util.Tips({
title: '余额不足!'
});
uni.showLoading({
title: '支付中'
});
let orderApi = that.order_type === 1 ? presellOrderPay : orderPay
orderApi(that.order_id, {
type: type,
// #ifdef H5
return_url: this.order_type == 98 ? 'http://' + window.location.host +
'/pages/users/order_list/indexCopy' : 'http://' + window.location.host +
'/pages/users/order_list/index',
// #endif
}).then(res => {
let status = res.data.status,
orderId = res.data.result.order_id,
jsConfig = res.data.result.config,
callback_key = res.data.result.pay_key,
goPages = this.order_type == 98 ? '/pages/users/order_list/indexCopy' :
'/pages/users/order_list/index'
switch (status) {
case 'ORDER_EXIST':
case 'EXTEND_ORDER':
case 'PAY_ERROR':
case 'error':
uni.hideLoading();
this.$emit('onChangeFun', {
action: 'payClose'
});
return that.$util.Tips({
title: res.message
});
break;
case 'success':
uni.hideLoading();
this.$emit('onChangeFun', {
action: 'payClose'
});
return that.$util.Tips({
title: '支付成功',
icon: 'success'
}, {
tab: 5,
url: goPages + '?status=2'
});
break;
case 'alipay':
case 'alipayQr':
uni.hideLoading();
this.$emit('onChangeFun', {
action: 'payClose'
});
uni.navigateTo({
url: '/pages/order_pay_back/index?keyCode=' + callback_key + '&url=' +
jsConfig,
})
return
break;
// #ifndef MP
case "wechat":
case "weixin":
case "weixinApp":
jsConfig.timeStamp = jsConfig.timestamp;
// #ifndef APP-PLUS
that.$wechat.pay(jsConfig).then(res => {
// console.log('success'+res.data)
this.$emit('onChangeFun', {
action: 'payClose'
});
uni.hideLoading();
return that.$util.Tips({
title: '支付成功',
icon: 'success'
}, {
tab: 5,
url: goPages + 'status=2'
});
}).catch(res => {
// console.log('catch'+res.data)
if (res.errMsg == 'chooseWXPay:cancel') {
if (that.isCall) {
return that.$util.Tips({
title: '取消支付'
});
} else {
return that.$util.Tips({
title: '取消支付'
}, {
tab: 5,
url: goPages + '?status=1'
});
}
}
})
// #endif
// #ifdef APP-PLUS
let mp_pay_name = ''
if (uni.requestOrderPayment) {
mp_pay_name = 'requestOrderPayment'
} else {
mp_pay_name = 'requestPayment'
}
console.log(mp_pay_name, jsConfig)
uni[mp_pay_name]({
provider: 'wxpay',
orderInfo: jsConfig,
success: (e) => {
this.$emit('onChangeFun', {
action: 'payClose'
});
return that.$util.Tips({
title: '支付成功',
icon: 'success'
}, {
tab: 5,
url: goPages + 'status=2'
});
},
fail: (e) => {
console.log(e)
if (that.isCall) {
return that.$util.Tips({
title: '取消支付'
});
} else {
return that.$util.Tips({
title: '取消支付'
}, {
tab: 5,
url: goPages + '?status=1'
});
}
},
complete: () => {
uni.hideLoading();
},
});
// #endif
break;
// #endif
// #ifdef MP
case "routine":
jsConfig.timeStamp = jsConfig.timestamp;
that.toPay = true;
let mp_pay_name = ''
if (uni.requestOrderPayment) {
mp_pay_name = 'requestOrderPayment'
} else {
mp_pay_name = 'requestPayment'
}
uni[mp_pay_name]({
...jsConfig,
success: function(res) {
uni.hideLoading();
that.$emit('onChangeFun', {
action: 'payClose'
});
if (that.BargainId || that.combinationId || that.pinkId || that
.seckillId)
return that.$util.Tips({
title: '支付成功',
icon: 'success'
}, {
tab: 5,
url: goPages + '?status=2'
});
return that.$util.Tips({
title: '支付成功',
icon: 'success'
}, {
tab: 5,
url: goPages + '?status=2'
});
},
fail: function(e) {
uni.hideLoading();
that.$emit('onChangeFun', {
action: 'payClose'
});
return that.$util.Tips({
title: '取消支付'
});
},
complete: function(e) {
uni.hideLoading();
//
if (res.errMsg == 'requestPayment:cancel') return that.$util
.Tips({
title: '取消支付'
});
that.$emit('onChangeFun', {
action: 'payClose'
});
},
})
break;
// #endif
case "balance":
uni.hideLoading();
that.$emit('onChangeFun', {
action: 'payClose'
});
//
return that.$util.Tips({
title: res.message
});
break;
// #ifdef H5
case 'h5':
let host = window.location.protocol + "//" + window.location.host;
let url = `${host}/pages/order_pay_status/index?order_id=${orderId}`
let eUrl = encodeURIComponent(url)
let jsurl = jsConfig.mweb_url || jsConfig.h5_url
let locations = `${jsurl}&redirect_url=${eUrl}`
setTimeout(() => {
location.href = locations;
}, 100);
break;
// #endif
// #ifdef APP-PLUS
case 'alipayApp':
uni.requestPayment({
provider: 'alipay',
orderInfo: jsConfig,
success: (e) => {
that.$emit('onChangeFun', {
action: 'payClose'
});
return that.$util.Tips({
title: '支付成功',
icon: 'success'
}, {
tab: 5,
url: goPages + 'status=2'
});
},
fail: (e) => {
return that.$util.Tips({
title: '取消支付'
});
},
complete: () => {
uni.hideLoading();
},
});
break;
// #endif
}
}).catch(err => {
uni.hideLoading();
return that.$util.Tips({
title: err
});
})
}
}
}
</script>
<style scoped lang="scss">
.payment {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
max-height: 600rpx;
border-radius: 16rpx 16rpx 0 0;
background-color: #fff;
padding-bottom: 60rpx;
z-index: 99999;
transition: all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);
transform: translate3d(0, 100%, 0);
}
.payment.on {
transform: translate3d(0, 0, 0);
}
.payment .title {
text-align: center;
height: 123rpx;
font-size: 32rpx;
color: #282828;
font-weight: bold;
padding-right: 30rpx;
margin-left: 30rpx;
position: relative;
border-bottom: 1px solid #eee;
}
.payment .title .iconfont {
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
font-size: 43rpx;
color: #8a8a8a;
font-weight: normal;
}
.payment .item {
border-bottom: 1px solid #eee;
height: 130rpx;
margin-left: 30rpx;
padding-right: 30rpx;
}
.payment .item .left {
width: 610rpx;
}
.payment .item .left .text {
width: 540rpx;
}
.payment .item .left .text .name {
font-size: 32rpx;
color: #282828;
}
.payment .item .left .text .info {
font-size: 24rpx;
color: #999;
}
.payment .item .left .text .info .money {
color: #ff9900;
}
.payment .item .left .iconfont {
font-size: 45rpx;
color: #09bb07;
}
.payment .item .left .iconfont.icon-zhifubao {
color: #00aaea;
}
.payment .item .left .iconfont.icon-yuezhifu {
color: #ff9900;
}
.payment .item .left .iconfont.icon-yuezhifu1 {
color: #eb6623;
}
.payment .item .iconfont {
font-size: 0.3rpx;
color: #999;
}
</style>

View File

@ -0,0 +1,170 @@
<template>
<view class='product-bg'>
<swiper :indicator-dots="indicatorDots" indicator-active-color="#e93323" :circular="circular"
:interval="interval" :duration="duration">
<block v-for="(item,index) in imgUrls" :key='index'>
<swiper-item>
<image :src="item" class="slide-image" mode="aspectFit" />
<!-- <view class="stop" v-if="isType == 2">
<image class="image" src="/static/images/stop.png"></image>
</view> -->
</swiper-item>
</block>
</swiper>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
export default {
props: {
imgUrls: {
type: Array,
default: function() {
return [];
}
},
videoline: {
type: String,
value: ""
},
isType: {
type: Number,
default: 1
}
},
data() {
return {
indicatorDots: true,
circular: true,
autoplay: true,
interval: 5000,
duration: 500,
currents: "1",
controls: true,
isPlay: true,
videoContext: ''
};
},
created() {},
watch: {
},
mounted() {
// #ifndef APP-PLUS
this.videoContext = uni.createVideoContext('myVideo', this);
// #endif
},
methods: {
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.$nextTick(() => {
this.videoContext.play();
})
// #endif
},
change: function(e) {
this.$set(this, 'currents', e.detail.current + 1);
}
}
}
</script>
<style scoped lang="scss">
.product-bg {
width: 710rpx;
height: 710rpx;
position: relative;
}
.product-bg swiper {
width: 100%;
height: 100%;
position: relative;
}
.product-bg .slide-image {
width: 100vw;
height: 100%;
border-radius: 16rpx;
}
.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;
}
#myVideo {
width: 100%;
height: 100%
}
.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%;
}
</style>

View File

@ -0,0 +1,248 @@
<template>
<view class="wf-page">
<!--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" :isAuth="isAuth" :uid="uid" :isShow="isShow" :tab="tab" @likeToggle="(item)=>likeToggle(false, index, item)"/>
</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" :isAuth="isAuth" :uid="uid" :isShow="isShow" :tab="tab" @likeToggle="(item)=>likeToggle(true, index, item)"/>
</view>
</view>
</view>
<authorize @onLoadFun="onLoadFun" :isAuto="isAuto" :isShowAuth="isShowAuth" @authColse="authColse"></authorize>
</view>
</template>
<script>
import WaterfallsFlowItem from '../plantWaterfallsFlowItem/WaterfallsFlowItem.vue'
import { graphicStartApi } from '@/api/community.js';
import authorize from '@/components/Authorize';
import { mapGetters } from "vuex";
export default {
components: {
WaterfallsFlowItem,
authorize,
},
props: {
//
wfList: {
type: Array,
require: true
},
updateNum: {
type: Number,
default: 10
},
isAuth: {
type: Boolean,
default: false
},
tab: {
type: Number,
default: 1
},
uid: {
type: Number,
default: 0
},
isShow: {
type: Boolean,
default: false
},
},
data() {
return {
allList: [], //
leftList: [], //
rightList: [], //
mark: 0, //
boxHeight: [], // 01
isShowAuth: false,
isAuto: false
};
},
watch: {
//
'wfList.length': {
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();
}
}
},
computed: {
...mapGetters(['isLogin']),
},
methods: {
//
waterFall() {
const i = this.mark;
if(!this.allList[i]) return ;
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)
},
giveStart(item){
let status = item.relevance_id ? 0 : 1
graphicStartApi(item.community_id,{status: status}).then(res => {
if(item.relevance_id){
item.relevance_id = !item.relevance_id;
item.count_start--;
item.count_start = item.count_start == 0 ? 0 : item.count_start
}else{
item.relevance_id = !item.relevance_id;
item.count_start++;
}
}).catch(err => {
uni.showToast({
title: err,
icon: 'none'
})
});
},
//
onLoadFun() {
this.isShowAuth = false
},
//
authColse: function(e) {
this.isShowAuth = e
},
//
authOpen: function() {
let that = this;
if (that.isLogin === false) {
this.isAuto = true;
this.isShowAuth = true
}
},
likeToggle(type, index){
if(this.isLogin == true){
if(type){
this.giveStart(this.rightList[index])
}else{
this.giveStart(this.leftList[index])
}
}else{
this.authOpen();
}
},
}
}
</script>
<style lang="scss" scoped>
$page-padding: 20rpx;
$grid-gap: 20rpx;
.wf-page {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: $grid-gap;
}
.wf-item {
width: calc((100vw - 2 * #{$page-padding} - #{$grid-gap}) / 2);
margin-bottom: $grid-gap;
background: #fff;
border-radius: 16rpx;
}
.wf-item-page{
padding-bottom: 20rpx;
}
</style>

View File

@ -0,0 +1,251 @@
<template>
<view v-if="item" @click="goDetail(item)" class="wf-page2" :style="viewColor">
<view class='pictrue skeleton-rect'>
<!-- <image :src='item.image[0]' mode="widthFix"></image> -->
<easy-loadimage class="image" mode="widthFix" :image-src="item.image[0]"></easy-loadimage>
<view v-if="isShow" class="plant-show">
<text v-if="item.is_type == 1" class="iconfont icon-tuwen1"></text>
<text v-else-if="item.is_type == 2" class="iconfont icon-shipin1"></text>
</view>
<view v-else-if="item.is_type == 2" class="video_img">
<image class="image" src="../../static/images/stop.png" mode=""></image>
</view>
<view v-if="isAuth && tab == 0 && item.status != 1" class="approval_status">
<view v-if="item.status == -1" class="approval_title">审核未通过</view>
<view v-else-if="item.status == -2" class="approval_title">已下架</view>
<view v-else-if="item.status == 0" class="approval_title">正在审核</view>
<text v-if="item.status == -1 || item.status == -2" class="approval_info">查看未通过原因</text>
<text v-if="item.status == 0" class="approval_info">通过后将展示在列表</text>
</view>
</view>
<view class='text'>
<view class='name skeleton-rect'>
<text class="text_name line2">{{item.title}}
</text>
</view>
<view class="count acea-row skeleton-rect">
<view v-if="!isAuth" class="author acea-row">
<image class="image" :src="(item.author && item.author.avatar) || '/static/images/f.png'" mode="widthFix"></image>
<text class="author_name line1">{{item.author && item.author.nickname}}</text>
</view>
<view v-else class="author acea-row">
<text class="author_time">
{{item.time}}
</text>
</view>
<view class="like">
<button class="like_count" hover-class="none" @click.stop="likeToggle(item)">
<text class="iconfont" :class="item.relevance_id ? 'icon-shoucang1' : 'icon-dianzan'"></text>
<text class="collect">{{item.count_start}}</text>
</button>
</view>
</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import easyLoadimage from '@/components/easy-loadimage/easy-loadimage.vue'
import { mapGetters } from "vuex";
export default {
components:{easyLoadimage},
computed: {...mapGetters(['viewColor'])},
props: {
item: {
type: Object,
require: true
},
type: {
type: Number,
default: 0
},
isAuth: {
type: Boolean,
default: false
},
uid: {
type: Number || String,
default: 0
},
tab: {
type: Number,
default: 1
},
isFind: {
type: Boolean,
default: false
},
isShow: {
type: Boolean,
default: false
},
},
data() {
return {
isShowAuth: false,
isAuto: false
};
},
methods: {
likeToggle(item){
this.$emit('likeToggle',item)
},
goDetail(item){
if(this.isFind){
uni.navigateTo({
url: '/pages/plantGrass/plant_featured/index?id='+item.topic_id
});
}else{
this.plantDeail(item)
}
},
plantDeail(item){
if(item.is_type == 1){
uni.navigateTo({
url: '/pages/plantGrass/plant_detail/index?id='+item.community_id
});
}else{
let user = this.isAuth ? 1 : 0;
// console.log(this.uid)
uni.navigateTo({
//#ifdef APP
url: '/pages/short_video/appSwiper/index?id='+item.community_id+'&user='+user+'&uid='+this.uid+'&tab='+this.tab
//#endif
//#ifndef APP
url: '/pages/short_video/nvueSwiper/index?id='+item.community_id+'&user='+user+'&uid='+this.uid+'&tab='+this.tab
//#endif
});
}
}
}
}
</script>
<style lang="scss" scoped>
.wf-page2 .pictrue{
width: 345rpx;
height: 345rpx;
border-radius: 16rpx;
position: relative;
/deep/image,/deep/.easy-loadimage,/deep/.image{
width: 100%;
max-width: 345rpx;
height: 345rpx;
border-radius: 16rpx;
}
.video_img{
width: 40rpx;
height: 40rpx;
position: absolute;
top: 10rpx;
right: 10rpx;
z-index: 100;
.image,image,uni-image{
width: 40rpx;
height: 40rpx;
}
}
.plant-show{
width: 42rpx;
height: 42rpx;
border-radius: 100%;
background: rgba(0,0,0,.5);
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 10rpx;
left: 10rpx;
.iconfont{
font-size: 20rpx;
color: #fff;
}
}
}
.loadfail-img{
width: 100%;
height: 345rpx;
}
.wf-page2 .text{
padding: 20rpx;
width: 345rpx;
.name{
color: #333333;
font-size: 28rpx;
font-weight: bold;
}
.count{
margin-top: 20rpx;
justify-content: space-between;
.author{
align-items: center;
}
.author_name{
margin-left: 10rpx;
max-width: 120rpx;
font-size: 24rpx;
color: #333333;
max-width: 180rpx;
}
.author_time{
color: #666666;
}
.like{
font-size: 24rpx;
color: #999999;
display: flex;
.like_count{
display: flex;
align-items: center;
}
.iconfont{
font-size: 30rpx;
}
.icon-shoucang1{
color: var(--view-priceColor);
}
.collect{
font-size: 24rpx;
margin-left: 5rpx;
}
}
}
}
.wf-page2 .author .image,.wf-page2 .author uni-image{
width: 46rpx;
height: 46rpx;
border-radius: 100%;
}
.approval_status{
width: 100%;
height: 100%;
background: rgba(0,0,0,.4);
position: absolute;
top: 0;
left: 0;
border-radius: 16rpx;
color: #fff;
text-align: center;
z-index: 5;
.approval_title{
font-size: 28rpx;
margin-top: 135rpx;
font-weight: bold;
}
.approval_info{
font-size: 24rpx;
margin-top: 24rpx;
}
}
</style>

View File

@ -0,0 +1,199 @@
<template>
<view class='product-bg'>
<swiper :indicator-dots="indicatorDots" indicator-active-color="#e93323" :autoplay="autoplay" :circular="circular"
:interval="interval" :duration="duration" @change="change" v-if="isPlay">
<!-- #ifndef APP-PLUS -->
<swiper-item v-if="videoline && videoline != '' && videoline != 'https:'">
<view class="item">
<video id="myVideo" :src='videoline && (videoline.substring(0,4) == "http" || videoline.substring(0,5) == "https") ? videoline : ("http:" + videoline)'
objectFit="cover" controls style="width:100%;height:100% " show-mute-btn="true"
auto-pause-if-navigate @ended="endedFun()"></video>
<view class="poster" v-if="controls">
<image class="image" :src="videoCoverImg"></image>
</view>
<view class="stop" v-if="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="videoCoverImg"></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>
<image :src="item" class="slide-image" @click='getpreviewImage(item)' />
</swiper-item>
</block>
</swiper>
<!-- #ifdef APP-PLUS -->
<view v-if="!isPlay" style="width: 100%; height: 750rpx;">
<video id="myVideo" :src='videoline && (videoline.substring(0,4) == "http" || videoline.substring(0,5) == "https") ? videoline : "http:" + videoline'
objectFit="cover" controls style="width:100%;height:100% " show-center-play-btn show-mute-btn="true"
auto-pause-if-navigate :enable-progress-gesture="false" :poster="videoCoverImg" @pause="videoPause" @ended="endedFun()"></video>
</view>
<!-- #endif -->
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
export default {
props: {
imgUrls: {
type: Array,
default: function() {
return [];
}
},
videoline: {
type: String,
value: ""
},
videoCoverImg: {
type: String,
}
},
data() {
return {
indicatorDots: true,
circular: true,
autoplay: true,
interval: 5000,
duration: 500,
currents: "1",
controls: true,
isPlay: true,
videoContext: ''
};
},
created() {
},
watch: {
},
mounted() {
// #ifndef APP-PLUS
this.videoContext = uni.createVideoContext('myVideo', this);
// #endif
},
methods: {
getpreviewImage: function(item) {
uni.previewImage({
urls: this.imgUrls,
current: item
});
},
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.$nextTick(()=>{
this.videoContext.play();
})
// #endif
},
change: function(e) {
this.$set(this, 'currents', e.detail.current + 1);
},
endedFun() {
this.controls = true
}
}
}
</script>
<style scoped lang="scss">
.product-bg {
width: 100%;
height: 750rpx;
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;
}
#myVideo {
width: 100%;
height: 100%
}
.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%;
}
</style>

View File

@ -0,0 +1,419 @@
<template>
<view :style="viewColor">
<view class="product-window" :class="(attr.cartAttr === true ? 'on' : '') + ' ' + (iSbnt || destri?'join':'') + ' ' + (isPresell ?'presell-window':'product-window')">
<view class="textpic acea-row row-between-wrapper">
<view class="pictrue">
<image :src="attr.productSelect.image ? attr.productSelect.image : image" @click="loookImg"></image>
</view>
<view class="text">
<view class="line1">
{{ attr.productSelect.store_name }}
</view>
<view v-if="isPresell" class="money presell_price">
<view>
预售价
<text class="num">{{ attr.productSelect.price }}</text>
<text v-if="presell_type === 2">定金¥<text class="num">{{ attr.productSelect.down_price }}</text></text>
</view>
<text class="stock" v-if='isShow'>库存: {{ attr.productSelect.stock }}</text>
<text class='stock' v-if="limitNum">限量: {{attr.productSelect.quota_show}}</text>
</view>
<view v-else class="money">
<view class="acea-row row-middle">
<view class="acea-row row-middle">
<text></text><text class="num">{{ attr.productSelect.price }}</text>
<view v-if="svipPrice" class="acea-row row-middle">
<text class='vip-money'>{{attr.productSelect.svip_price}}</text>
<view class="vipImg">
<image src="/static/images/svip.png"></image>
</view>
</view>
</view>
</view>
<view class="stock_count">
<text class="stock" v-if='isShow'>库存: {{ attr.productSelect.stock }}</text>
<text class='stock' v-if="limitNum">限量: {{attr.productSelect.quota_show}}</text>
</view>
</view>
</view>
<view class="iconfont icon-guanbi" @click="closeAttr"></view>
</view>
<view class="productWinList">
<view class="item" v-for="(item, indexw) in attr.productAttr" :key="indexw">
<view class="title">{{ item.attr_name }}</view>
<view class="listn acea-row row-middle">
<view class="itemn" :class="item.index === itemn.attr ? 'on' : ''" v-for="(itemn, indexn) in item.attr_value"
@click="tapAttr(indexw, indexn)" :key="indexn">
{{ itemn.attr }}
</view>
</view>
</view>
</view>
<view class="cart acea-row">
<view class="title">数量</view>
<view class="carnum acea-row row-left">
<view class="buy_limit" v-if="minCount>0 || maxCount>0">
(<text v-if="minCount>0">{{minCount}}件起购<text v-if="minCount>0 && maxCount>0"></text></text><text v-if="maxCount>0">最多{{maxCount}}</text>)
</view>
<view class="item reduce" :class="attr.productSelect.cart_num <= 1 ? 'on' : ''" @click="CartNumDes">
-
</view>
<view class='item num'>
<input type="number" v-model="attr.productSelect.cart_num" data-name="productSelect.cart_num" @input="bindCode(attr.productSelect.cart_num)" @keydown="btKeyDown" @keyup="btKeyUp"></input>
</view>
<view v-if="iSplus" class="item plus" :class=" attr.productSelect.cart_num >= attr.productSelect.stock || destri ? 'on' : ''"
@click="CartNumAdd">+</view>
<view v-else class='item plus' :class='(attr.productSelect.cart_num >= attr.productSelect.quota_show)
|| (attr.productSelect.cart_num >= attr.productSelect.product_stock)? "on":""'
@click='CartNumAdd'>+</view>
</view>
</view>
<view class="joinBnt b-color" v-if="destri && attr.productSelect.stock>0" @click="goCat">立即购买</view>
<view class="joinBnt on" v-else-if="destri && attr.productSelect.stock<=0">已售罄</view>
<view class="joinBnt b-color" v-if="iSbnt && attr.productSelect.stock>0"
@click="goCat">我要参团</view>
<view class="joinBnt on" v-else-if="(iSbnt && attr.productSelect.stock<=0)">已售罄</view>
</view>
<view class="mask" @touchmove.prevent :hidden="attr.cartAttr === false" @click="closeAttr"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { mapGetters } from "vuex";
export default {
props: {
attr: {
type: Object,
default: () => {}
},
limitNum: {
type: Number,
value: 0
},
isShow: {
type: Number,
value: 0
},
iSbnt: {
type: Number,
value: 0
},
iSplus: {
type: Number,
value: 0
},
destri: {
type: Number,
value: 0
},
isPresell: {
type: Number,
value: 0
},
presell_type: {
type: Number,
value: 1
},
image: {
type: String,
value: ''
},
maxCount: {
type: Number,
value: 0
},
minCount: {
type: Number,
value: 0
},
svipPrice: {
type: Boolean,
value: false
}
},
computed: mapGetters(['viewColor']),
data() {
return {};
},
mounted(){
},
methods: {
//
loookImg(){
let self = this
let arr = [self.attr.productSelect.image ? self.attr.productSelect.image : self.image]
uni.previewImage({
urls: arr,
});
},
goCat: function() {
this.$emit('goCat');
},
/**
* 购物车手动输入数量
*
*/
bindCode: function(e) {
let num = JSON.parse(JSON.stringify(e))
this.$emit('iptCartNum', num);
},
btKeyDown(e) {
e.target.value = e.target.value.replace(/[^\a-\z\A-\Z0-9\u4E00-\u9FA5]/g,"");
},
btKeyUp(e) {
e.target.value = e.target.value.replace(/[`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g,"")
},
closeAttr: function() {
this.$emit('myevent');
},
CartNumDes: function() {
if (!this.destri) {
this.$emit('ChangeCartNum', false);
}
},
CartNumAdd: function() {
if (!this.destri) {
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);
},
//
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;
}
}
}
</script>
<style scoped lang="scss">
.product-window {
position: fixed;
bottom: 0;
width: 100%;
left: 0;
background-color: #fff;
z-index: 77;
border-radius: 16rpx 16rpx 0 0;
padding-bottom: 140rpx;
padding-bottom: calc(140rpx+ constant(safe-area-inset-bottom)); /// IOS<11.2/
padding-bottom: calc(140rpx + env(safe-area-inset-bottom)); /// IOS>11.2/
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
&.presell-window {
padding-bottom: 200rpx;
}
}
.product-window.on {
transform: translate3d(0, 0, 0);
}
.product-window.join {
padding-bottom: 30rpx;
}
.product-window .textpic {
padding: 0 80rpx 0 30rpx;
margin-top: 29rpx;
position: relative;
}
.product-window .textpic .pictrue {
width: 150rpx;
height: 150rpx;
}
.product-window .textpic .pictrue image {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.product-window .textpic .text {
width: 460rpx;
font-size: 32rpx;
color: #202020;
}
.product-window .textpic .text .money {
font-size: 24rpx;
margin-top: 26rpx;
font-weight: 700;
color: var(--view-priceColor);
}
.product-window .stock_count{
margin-top: 5rpx;
}
.product-window .textpic .text .money .num {
font-size: 36rpx;
}
.product-window .textpic .text .money .stock {
color: #999;
margin-left: 18rpx;
font-weight: normal;
}
.product-window .textpic .text .presell_price {
color: #FF7F00;
.num {
display: inline-block;
margin-right: 20rpx;
}
.stock {
margin-left: 0;
}
}
.vip-money {
color: #282828;
font-size: 22rpx;
margin-left: 6rpx;
}
.vipImg {
width: 65rpx;
height: 28rpx;
margin-left: 4rpx;
image {
width: 100%;
height: 100%;
display: block;
}
}
.product-window .textpic .iconfont {
position: absolute;
right: 30rpx;
top: -5rpx;
font-size: 35rpx;
color: #8a8a8a;
}
.product-window .productWinList {
max-height: 395rpx;
overflow: auto;
margin-top: 36rpx;
}
.product-window .productWinList .item~.item {
margin-top: 36rpx;
}
.product-window .productWinList .item .title {
font-size: 30rpx;
color: #999;
padding: 0 30rpx;
}
.product-window .productWinList .item .listn {
padding: 0 30rpx 0 16rpx;
}
.product-window .productWinList .item .listn .itemn {
border: 1px solid #bbb;
font-size: 26rpx;
color: #282828;
padding: 7rpx 33rpx;
border-radius: 6rpx;
margin: 14rpx 0 0 14rpx;
}
.product-window .productWinList .item .listn .itemn.on {
color: #fff;
background-color: var(--view-theme);
border-color: var(--view-theme);
}
.product-window .cart {
margin-top: 36rpx;
padding: 0 30rpx;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.product-window .cart .title {
font-size: 30rpx;
color: #999;
line-height: 54rpx;
}
.product-window .cart .carnum {
height: 54rpx;
align-items: center;
}
.product-window .cart .carnum .buy_limit {
font-size: 22rpx;
color: var(--view-theme);
margin-right: 30rpx;
}
.product-window .cart .carnum .item {
width: 63rpx;
text-align: center;
height: 100%;
line-height: 42rpx;
color: #333333;
font-weight: 400;
font-size: 26rpx;
}
.product-window .cart .carnum .reduce {
border: 1px solid #a4a4a4;
width: 44rpx;
height: 42rpx;
// border-right: 0;
border-radius: 0 7rpx 7rpx 0;
line-height: 30rpx;
}
.product-window .cart .carnum .reduce.on {
border-color: #e3e3e3;
color: #dedede;
}
.product-window .cart .carnum .plus {
border: 1px solid #a4a4a4;
width: 44rpx;
height: 42rpx;
// border-right: 0;
border-radius: 0 7rpx 7rpx 0;
line-height: 30rpx
}
.product-window .cart .carnum .plus.on {
border-color: #e3e3e3;
color: #dedede;
}
.product-window .cart .carnum .num {
color: #282828;
font-size: 28rpx;
}
.product-window .joinBnt {
font-size: 30rpx;
width: 620rpx;
height: 86rpx;
border-radius: 50rpx;
text-align: center;
line-height: 86rpx;
color: #fff;
margin: 21rpx auto 0 auto;
&.b-color{
background-color: var(--view-theme);
}
}
.product-window .joinBnt.on {
background-color: #bbb;
color: #fff;
}
</style>

View File

@ -0,0 +1,627 @@
<template>
<view class="containers" :style="viewColor">
<view class="header">
<view class="search">
<text class="iconfont icon-xiazai5"></text>
<input type="text" placeholder="请输入商品名称" v-model="searchVal" @input="setValue" confirm-type="search"
@confirm="searchBut()" placeholder-class='placeholder'>
</view>
<view class="iconclose" @click="close">
<image src="@/static/images/wt_close.png" mode="aspectFit"></image>
</view>
</view>
<view class="main">
<scroll-view scroll-y="true" @touchmove.stop>
<block>
<view v-if="bought.length" @touchmove="onTouchmove" id="goods" class="goods">
<view class="picTxt acea-row" v-for="(item, i) in bought" :key="i">
<view class="checkbox">
<text @click.stop="goodsCheck(item)" v-if="item.check"
class="iconfont icon-xuanzhong1"></text>
<text @click.stop="goodsCheck(item)" v-else
:class="checkedArr.length >=5 ? 'disabled': ''"
class="iconfont icon-weixuanzhong"></text>
</view>
<view class='pictrue'>
<image :src='item.image'></image>
</view>
<view class='text'>
<view class='line2 name'>{{item.store_name}}</view>
<view class="picTxt_one" v-if="item.attrValue.length>0">
<picker class="slecte" v-if="item.attrValue.length>1"
@change="bindPickerChange($event,item.attrValue,i)" :value="index"
:range="item.attrValue" :range-key="'sku'">
<view class="uni-input">{{item.attrValue[index].sku}}</view>
</picker>
<view class="" style="margin-top: 10rpx;">
库存:{{item.attrValue[index].stock}}
</view>
</view>
</view>
<view class="picTxt_price">
<view class="price">
<span>委托价格</span>
<input type="text" :value="item.price" placeholder="输入出售价格"
@input="producrprice($event,i,item)" adjust-position=""
placeholder-style="color: #CCCCCC;" />
</view>
<view class="price_num">
<span>委托数量</span>
<subtractive v-if='item.number==0' style="margin-top: 10rpx;margin-left: 20rpx;"
class="step" :min="0" :max="item.attrValue[index].stock" :value="peicenumber"
:isMax="true" :isMin="true" index="11" @eventChange="numberChange($event,i)">
</subtractive>
<subtractive v-else style="margin-top: 10rpx;margin-left: 20rpx;" class="step"
:min="0" :max="item.attrValue[index].stock" :value="item.number" :isMax="true"
:isMin="true" index="11" @increment="incrementTotal($event,i,item)"
@eventChange="numberChange($event,i)"></subtractive>
</view>
</view>
</view>
</view>
<view v-else class="empty">
<image src="/static/images/no_thing.png"></image>
<text>暂无内容哦~</text>
</view>
</block>
</scroll-view>
<view class="foot_bar">
<button class="confirm_btn" @click="submit">确定({{checkedArr.length}})</button>
</view>
</view>
</view>
</template>
<script>
import Loading from '@/components/Loading/index.vue';
import subtractive from '@/components/subtractive/subtractive.vue';
import {
getCommunitygetOrderList
} from "@/api/trading-floor";
import {
mapGetters
} from "vuex";
export default {
props: {
checkedObj: {
type: Array,
default: []
}
},
computed: mapGetters(['viewColor']),
components: {
Loading,
subtractive
},
data() {
return {
isActive: 0,
loadedb: false,
loadingb: false,
loadedc: false,
loadingc: false,
loadeds: false,
loadings: false,
whereb: {
page: 1,
limit: 10,
keyword: '',
},
peicenumber: 0,
searchVal: "",
checked: [],
list: [],
bought: [],
checkedArr: [],
aryys: [],
// picker
storageCustomList: [{
CustGoodsCode: "TEST001",
CustGoodsName: "测试货主001",
IfBoxId: 0,
IfProductId: 0,
}, {
CustGoodsCode: "TEST002",
CustGoodsName: "测试货主002",
IfBoxId: 0,
IfProductId: 0,
}, {
CustGoodsCode: "TEST003",
CustGoodsName: "测试货主003",
IfBoxId: 0,
IfProductId: 0,
}],
index: 0,
pickerData: '请选择',
itstock: '',
};
},
watch: {
checkedObj: {
handler(n) {
this.checkedArr = n
},
deep: true
}
},
mounted() {
this.checkedArr = this.checkedObj
this.aryys = this.checkedObj
this.getBounht();
},
methods: {
//
producrprice(e, i, item) {
this.bought[i].price = e.detail.value
this.$set(item, 'check', false);
for (let i in this.checkedArr) {
if (this.checkedArr[i].product_id == item.product_id) {
this.checkedArr.splice(i, 1)
}
}
},
incrementTotal(e, i, item) {
this.$set(item, 'check', false);
for (let i in this.checkedArr) {
if (this.checkedArr[i].product_id == item.product_id) {
this.checkedArr.splice(i, 1)
}
}
},
// picker
bindPickerChange: function(e, storage, num) {
this.bought[num].attrValue[this.index].sku = storage[e.detail.value].sku
this.bought[num].attrValue[this.index].stock = storage[e.detail.value].stock
this.bought[num].product_attr_unique = storage[e.detail.value].unique
this.pickerData = storage[this.index] //
if (this.bought[num].attrValue[this.index].stock == 0) {
this.$util.Tips({
title: '库存不足'
});
}
},
//
close() {
this.$emit('close');
},
numberChange(data, i) {
this.peicenumber = data.number;
this.bought[i].number = data.number
},
tabs(index) {
this.isActive = index
this.$set(this.whereb, 'keyword', '');
this.searchVal = ''
this.searchBut()
},
onTouchmove(e) {
if (this.loadendb) return;
if (this.loadingb) return;
const query = uni.createSelectorQuery().in(this);
query.select('#goods').boundingClientRect(data => {
if (data.bottom < 1500 && data.top < 0) {
this.getBounht();
}
}).exec();
//
},
setValue: function(event) {
this.$set(this.whereb, 'keyword', event.detail.value);
if (!event.detail.value) {
this.whereb.page = 1
this.loadedb = false
this.getBounht()
}
},
searchBut() {
this.bought = []
this.whereb.page = 1
this.loadedb = false
this.getBounht()
},
getBounht() {
var that = this;
// console.log('1111111', that.loadingb, that.loadedb)
if (that.loadingb || that.loadedb) return;
that.loadingb = true;
getCommunitygetOrderList(that.whereb).then(
res => {
that.loadingb = false;
that.loadedb = res.data.list.length < that.whereb.limit;
that.bought.push.apply(that.bought, res.data.list);
that.whereb.page = that.whereb.page + 1;
that.getInitchecked(that.bought);
},
error => {
that.$util.Tips({
title: error.msg
})
}
);
},
/*获取初始化选中的数据*/
getInitchecked(arr) {
let that = this;
arr.forEach((item, index) => {
that.$set(item, 'check', false);
that.checkedArr.forEach((val, i) => {
if (item.product_id == val.product_id) {
that.$set(item, 'check', true);
that.$set(item, 'number', val.number);
that.$set(item, 'price', val.price);
that.peicenumber=val.number
}
})
})
},
/*已选中的商品打钩*/
getCheckedGoods() {
this.checked = []
this.checkedArr.forEach((item, index) => {
this.checkedArr.push(item)
})
},
/*点击选中与否*/
goodsCheck(item) {
this.$set(item, 'check', !item.check);
if (item.check) {
if (this.peicenumber == 0) {
item.number = 1
}
if (!item.product_attr_unique) {
item.product_attr_unique = item.attrValue[0].unique
}
this.checkedArr.push(item)
this.arrayUnique(this.checkedArr, 'product_id')
} else {
this.checkedArr.splice(this.checkedArr.findIndex(itemn => ((itemn.product_id == item.product_id))), 1)
}
},
//
arrayUnique(arr, name) {
let hash = {}
const result = arr.reduce((acc, cru, index) => {
if (!hash[cru[name]]) {
hash[cru[name]] = {
index: acc.length
}
acc.push(cru)
} else {
console.log(acc, hash[cru[name]])
acc.splice(hash[cru[name]]['index'], 1, cru)
}
return acc;
}, [])
this.checkedArr = result
},
/*确定提交*/
submit() {
this.$emit('getProduct', this.checkedArr);
},
}
}
</script>
<style lang="scss" scoped>
.containers {
background: #ffffff;
border-radius: 16rpx 16rpx 0 0;
padding: 40rpx 0;
position: relative;
.header {
position: relative;
padding: 0 30rpx;
.title {
width: 100%;
text-align: center;
text {
position: relative;
margin: 0 50rpx;
color: #999999;
font-size: 30rpx;
&.on {
color: #333333;
font-weight: bold;
font-size: 34rpx;
&::after {
content: "";
display: inline-block;
width: 40rpx;
height: 5rpx;
background: var(--view-theme);
position: absolute;
bottom: -10rpx;
left: 10rpx;
}
}
}
}
.iconclose {
width: 44rpx;
height: 44rpx;
line-height: 44rpx;
border-radius: 50%;
text-align: center;
position: absolute;
top: -150rpx;
right: 30rpx;
image {
width: 100%;
height: 100%;
}
}
.search {
margin-top: 44rpx;
background: #F5F5F5;
border-radius: 30rpx;
padding: 12rpx 30rpx 12rpx 66rpx;
position: relative;
.iconfont {
font-size: 24rpx;
color: #939393;
position: absolute;
top: 20rpx;
left: 30rpx;
}
.placeholder {
color: #999999;
font-size: 26rpx;
}
}
.sub_title {
color: #282828;
font-size: 26rpx;
margin-top: 30rpx;
}
.iconfont {
color: #8A8A8A;
font-size: 28rpx;
position: absolute;
top: 0;
right: 30rpx;
}
}
scroll-view {
height: 650rpx;
}
.main {
height: 650rpx;
margin: 40rpx 0 80rpx;
padding: 0 30rpx;
}
}
.picTxt {
width: 100%;
padding: 25rpx 0;
position: relative;
align-items: center;
justify-content: space-between;
border-top: 2rpx solid #E7E6E4;
.picTxt_one {
white-space: nowrap;
overflow: hidden;
}
.picTxt_one {
display: flex;
margin-top: 20rpx;
.slecte {
margin-right: 30rpx;
width: 280rpx;
height: 60rpx;
line-height: 60rpx;
text-align: center;
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #959595;
background-color: #E7E6E4;
border-radius: 10rpx 10rpx 10rpx 10rpx;
white-space: nowrap;
overflow: hidden;
}
}
.picTxt_price {
display: flex;
margin-top: 37rpx;
height: 70rpx;
line-height: 70rpx;
.price {
display: flex;
margin-right: 15rpx;
input {
width: 210rpx;
text-align: center;
height: 70rpx;
background: #F5F5F5;
border-radius: 7rpx 7rpx 7rpx 7rpx;
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
margin-left: 20rpx;
}
}
.price_num {
display: flex;
}
}
.checkbox {
margin-right: 30rpx;
.iconfont {
font-size: 38rpx;
color: #CCCCCC;
}
.icon-xuanzhong1 {
color: var(--view-theme);
}
.disabled {
pointer-events: none;
cursor: default;
opacity: 0.3;
}
}
.pictrue {
width: 160rpx;
height: 160rpx;
image {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
}
.text {
width: 430rpx;
margin-left: 30rpx;
font-size: 28rpx;
color: #282828;
position: relative;
height: 160rpx;
.name {
color: #282828;
font-size: 28rpx;
}
.money {
position: absolute;
bottom: 0;
left: 0;
color: var(--view-priceColor);
font-size: 22rpx;
font-weight: bold;
text {
font-size: 26rpx;
}
}
}
}
.foot_bar {
width: 100%;
position: fixed;
// bottom: 54px;
left: 0;
padding: 20rpx 0;
z-index: 5;
.confirm_btn {
width: 710rpx;
height: 86rpx;
line-height: 86rpx;
color: #ffffff;
text-align: center;
font-size: 32rpx;
background: var(--view-theme);
border-radius: 43rpx;
margin: 0 auto;
}
}
.empty {
margin: 130rpx 0 150rpx;
text-align: center;
image,
uni-image {
display: inline-block;
width: 414rpx;
height: 305rpx;
}
text {
display: block;
color: #999999;
font-size: 26rpx;
}
}
</style>

View File

@ -0,0 +1,119 @@
<template>
<view class='recommend'>
<view class="common-hd">
<view class="title">为你推荐</view>
</view>
<view class='recommendList' :class="indexP?'on':''">
<WaterfallsFlow :wfList='hostProduct' @itemTap="goDetail" :type="0" />
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import {mapGetters} from "vuex";
import { goShopDetail } from '@/libs/order.js'
import {initiateAssistApi} from '@/api/activity.js';
import {toLogin} from '@/libs/login.js';
import WaterfallsFlow from '@/components/WaterfallsFlow/WaterfallsFlow.vue'
export default {
components:{WaterfallsFlow},
computed: mapGetters(['uid']),
props: {
hostProduct: {
type: Array,
default: function() {
return [];
}
},
indexP:{
type: Boolean,
default: false
},
isLogin:{
type: Boolean,
default: false
}
},
data() {
return {
};
},
mounted() {
},
onPullDownRefresh(){
//
setTimeout(()=>{
const newList = this.hostProduct.reverse();
this.hostProduct = newList;
uni.stopPullDownRefresh();
},500)
},
methods: {
goDetail(item){
goShopDetail(item, this.uid).then(res => {
if (this.isLogin) {
initiateAssistApi(item.activity_id).then(res => {
let id = res.data.product_assist_set_id;
uni.hideLoading();
uni.navigateTo({
url: '/pages/activity/assist_detail/index?id=' + id
});
}).catch((err) => {
uni.showToast({
title: err,
icon: 'none'
})
});
} else {
// #ifdef H5 || APP-PLUS
toLogin();
// #endif
// #ifdef MP
this.$emit('isShowAuth', true);
this.$emit('isAuto', true);
// #endif
}
})
}
}
}
</script>
<style scoped lang="scss">
.common-hd {
display: flex;
align-items: center;
justify-content: center;
height: 118rpx;
.title {
padding: 0 80rpx;
font-size: 34rpx;
color: $theme-color;
font-weight: bold;
background-image: url("~@/static/images/index-title.png");
background-repeat: no-repeat;
background-size: 100% auto;
background-position: left center;
}
}
.recommend .recommendList {
padding: 0 20rpx;
min-height: 100rpx;
}
.recommend .recommendList.on{
padding: 0;
}
/deep/.looming-gray{
border-radius: 16rpx 16rpx 0 0;
}
</style>

View File

@ -0,0 +1,190 @@
<template>
<view class="mark" v-if="isShow" @click="close">
<view class="release">
<view class="release_content" v-for="(item,i) in list" :key="i" @click="navigtion(item)">
<view class="release_content_left">
<view :class="i==1?'release_imga':'release_img'">
<image :src="item.img" mode="aspectFit"></image>
</view>
<view class="title">
<view class="title1">
{{item.title1}}
</view>
<view class="title2">
{{item.title2}}
</view>
</view>
</view>
<view class="release_content_right ">
<text class="iconfont icon-xiangyou"></text>
</view>
</view>
<view class="release_close" @click="close">
<image src="@/static/images/trad-close.png" mode="aspectFit"></image>
</view>
</view>
</view>
</view>
</template>
<script>
import {
navigateTo
} from '../../libs/uniApi'
export default {
props: {
isShow: {
type: Boolean,
default: false
},
// bottomtruefalse
bottom: {
type: Boolean,
default: false
}
},
data() {
return {
list: [{
img: require('@/static/images/season.png'),
title1: '发布调货商品',
title2: '镇街店铺快捷调货',
},
{
img: require('@/static/images/discounts.png'),
title1: '发布打折商品',
title2: '发布店铺打折商品',
}
]
}
},
methods: {
navigtion(item) {
if (item.title1 =='发布调货商品') {
uni.navigateTo({
url: '/pages/trading_hall/transfer_goods/index'
})
} else {
uni.navigateTo({
url: '/pages/trading_hall/adddiscounts/index'
})
}
},
close() {
this.$emit('close')
},
cancel() {
this.$emit('cancel')
},
confirm() {
this.$emit('confirm')
},
}
}
</script>
<style lang="scss">
.mark {
position: fixed;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
left: 0;
bottom: 0;
top: 0;
right: 0;
display: flex;
justify-content: center;
align-items: center;
}
.release {
position: absolute;
bottom: 0px;
}
.release_content {
width: 694rpx;
height: 137rpx;
background: #FCF3EE;
border-radius: 14rpx 14rpx 14rpx 14rpx;
opacity: 1;
margin-bottom: 21rpx;
display: flex;
justify-content: space-between;
padding: 0 26rpx;
.release_content_left {
display: flex;
}
.release_content_right {
height: 137rpx;
line-height: 137rpx;
}
.release_img {
width: 111rpx;
height: 96rpx;
margin-top: 21rpx;
margin-right: 19rpx;
image {
width: 111rpx;
height: 96rpx;
}
}
.release_imga {
width: 76rpx;
height: 113rpx;
margin-top: 5rpx;
margin-right: 50rpx;
image {
width: 76rpx;
height: 113rpx;
}
}
.title {
margin-top: 23rpx;
}
.title1 {
font-size: 32rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
}
.title2 {
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #666666;
margin-top: 11rpx;
}
}
.release_close {
width: 248rpx;
height: 248rpx;
margin: 0 auto;
image {
width: 248rpx;
height: 248rpx;
}
}
</style>

351
components/rightSlider.vue Normal file
View File

@ -0,0 +1,351 @@
<template>
<view class="right-wrapper" @touchmove.stop.prevent="moveStop" :style="viewColor">
<view class="control-wrapper animated" :class="showBox?'slideInRight':''">
<view class="header">
<view class="title">价格区间</view>
<view class="input-wrapper">
<input placeholder="最低价" v-model="min" type="number"/>
<view class="line"></view>
<input placeholder="最高价" v-model="max" type="number"/>
</view>
</view>
<view class="store_type">
<view class="title">店铺类型</view>
<view class="brand-wrapper">
<view class="wrapper">
<view class="item line1" v-for="(item,index) in storeTypeList" :key="index" :class="item.check?'on':''" @tap="bindChenckType(item,index)">
{{item.name}}
</view>
</view>
</view>
</view>
<view class="content-box">
<view class="title">品牌</view>
<view class="brand-wrapper">
<scroll-view :style="{'height':isShow?'90%':'250rpx'}" :scroll-y="isShow">
<view class="wrapper">
<view class="item line1" v-for="(item,index) in list" :key="index" :class="item.check?'on':''" @tap="bindChenck(item)">
{{item.brand_name}}
</view>
</view>
</scroll-view>
<view class="btns" v-if="!isShow && list.length>9" @click="isShow = true">展开全部<text class="iconfont icon-xiangxia"></text></view>
<view class="btns" v-if="isShow && list.length>9" @click="isShow = false">收起<text class="iconfont icon-xiangshang"></text></view>
</view>
<view class="foot-btn">
<view class="btn-item" @click="reset">重置</view>
<view class="btn-item confirm" @click="confirm">确定</view>
</view>
</view>
</view>
<view class="right-bg" @click="close"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { mapGetters } from "vuex";
export default{
props: {
brandList: {
type: Array,
},
status:{
type:Boolean,
default:false
},
price_on:{
type:String,
default:''
},
price_off:{
type:String,
default:''
},
activeIndex:{
type:Number,
default:0
}
},
computed: mapGetters(['viewColor']),
data(){
return {
min: '',
max:'',
is_trader: '',
isShow:false,
list:[],
storeTypeList: [
{name: '全部', value: '',check: true},
{name: '自营', value: 'trader',check: false},
{name: '非自营', value: 'trader',check: false},
],
activeList:[],
showBox:false,
index: this.activeIndex
}
},
mounted() {
//
this.list = this.brandList
this.showBox = this.status
this.min = this.price_on
this.max = this.price_off
this.storeTypeList = [
{name: '全部', value: '',check: false},
{name: '自营', value: 'trader',check: false},
{name: '非自营', value: 'trader',check: false}
]
this.storeTypeList[this.index]['check'] = true
this.is_trader = this.storeTypeList[0]['check'] ? '' : this.storeTypeList[1]['check'] ? 1 : 0
},
methods:{
bindChenck(item){
item.check = !item.check
this.arrFilter()
},
bindChenckType(item,index){
this.storeTypeList = [
{name: '全部', value: '',check: false},
{name: '自营', value: 'trader',check: false},
{name: '非自营', value: 'trader',check: false},
]
this.storeTypeList[index]['check'] = true
this.is_trader = this.storeTypeList[0]['check'] ? '' : this.storeTypeList[1]['check'] ? 1 : 0
this.index = index
},
arrFilter(){
this.activeList = this.list.filter(item=>{
return item.check == true
})
},
reset(){
this.list.forEach((el,index)=>{
el.check = false
})
this.storeTypeList = [
{name: '全部', value: 'trader',check: true},
{name: '自营', value: 'trader',check: false},
{name: '非自营', value: 'trader',check: false}
]
this.min = this.max = ''
this.is_trader=''
this.index=0
this.arrFilter()
},
confirm(){
this.arrFilter()
let obj = {
brandList:this.activeList,
price_on:this.min,
price_off:this.max,
status:false,
is_trader: this.is_trader,
}
this.showBox = false
this.$emit('confirm',obj,this.index)
},
close(){
this.showBox = false
this.$emit('close')
},
moveStop(){}
}
}
</script>
<style lang="scss">
.slideInRight{
animation-duration:.5s
}
.right-wrapper{
z-index: 99;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
.control-wrapper{
z-index: 90;
position: absolute;
right: 0;
top: 0;
display: flex;
flex-direction: column;
width: 635rpx;
height: 100%;
background-color: #F5F5F5;
.header{
padding: 50rpx 26rpx 40rpx;
background-color: #fff;
.title{
font-size: 26rpx;
font-weight: bold;
color: #282828;
}
.input-wrapper{
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 28rpx;
input{
width:260rpx;
height:56rpx;
padding: 0 10rpx;
background:rgba(242,242,242,1);
border-radius:28rpx;
font-size: 22rpx;
text-align: center;
}
.line{
width:15rpx;
height:2rpx;
background:#7D7D7D;
}
}
}
.content-box{
position: relative;
flex: 1;
display: flex;
flex-direction: column;
margin-top: 20rpx;
padding: 0 26rpx;
background-color: #fff;
overflow: hidden;
.title{
padding: 40rpx 0 20rpx;
font-size: 26rpx;
font-weight: bold;
color: #282828;
}
.brand-wrapper{
flex: 1;
overflow: hidden;
.wrapper{
display: flex;
flex-wrap: wrap;
padding-bottom: 20rpx;
}
.item{
display: block;
width:186rpx;
height:56rpx;
line-height: 56rpx;
text-align: center;
background:rgba(242,242,242,1);
border-radius:28rpx;
margin-top: 25rpx;
padding: 0 10rpx;
margin-right: 12rpx;
&:nth-child(3n){
margin-right: 0;
}
&.on{
background: var(--view-minorColor);
border:1px solid var(--view-theme);
color: var(--view-theme);
}
}
.btns{
display: flex;
align-items: center;
justify-content: center;
padding-top: 10rpx;
font-size: 22rpx;
color: #999;
.iconfont{
margin-left: 10rpx;
margin-top: 5rpx;
font-size: 20rpx;
}
}
}
.foot-btn{
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 30rpx;
.btn-item{
display: flex;
align-items: center;
justify-content: center;
width:286rpx;
height:68rpx;
background:rgba(255,255,255,1);
border:1px solid rgba(170,170,170,1);
border-radius:34rpx;
font-size: 26rpx;
color: #282828;
&.confirm{
background: var(--view-theme);
border-color: var(--view-theme);
color: #fff;
}
}
}
}
.store_type{
position: relative;
margin-top: 20rpx;
padding: 0 26rpx;
background-color: #fff;
overflow: hidden;
.title{
padding: 40rpx 0 20rpx;
font-size: 26rpx;
font-weight: bold;
color: #282828;
}
.brand-wrapper{
overflow: hidden;
.wrapper{
display: flex;
flex-wrap: wrap;
padding-bottom: 20rpx;
}
.item{
display: block;
width:186rpx;
height:56rpx;
line-height: 56rpx;
text-align: center;
background:rgba(242,242,242,1);
border-radius:28rpx;
margin-top: 25rpx;
padding: 0 10rpx;
margin-right: 12rpx;
&:nth-child(3n){
margin-right: 0;
}
&.on{
background: var(--view-minorColor);
border:1px solid var(--view-theme);
color: var(--view-theme);
}
}
}
}
}
.right-bg{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,.5);
}
}
</style>

View File

@ -0,0 +1,277 @@
<template>
<view class="right-wrapper" @touchmove.stop.prevent="moveStop" :style="viewColor">
<view class="control-wrapper animated" :class="showBox?'slideInRight':''">
<view class="content-box">
<view class="title">店铺类型</view>
<view class="brand-wrapper">
<scroll-view style="max-height: 400rpx;" :scroll-y="isShow">
<view class="wrapper">
<view class="item line1" v-for="(item,index) in list" :key="index" :class="item.check?'on':''" @tap="bindChenck1(item)">
{{item.type_name}}
</view>
</view>
</scroll-view>
<view class="btns" v-if="!isShow && list.length>9" @click="isShow = true">展开全部<text class="iconfont icon-xiangxia"></text></view>
<view class="btns" v-if="isShow && list.length>9" @click="isShow = false">收起<text class="iconfont icon-xiangshang"></text></view>
</view>
<view class="title">商户分类</view>
<view class="brand-wrapper">
<scroll-view style="max-height: 400rpx;" :scroll-y="isShow">
<view class="wrapper">
<view class="item line1" v-for="(item,index) in merCate" :key="index" :class="item.check?'on':''" @tap="bindChenck2(item)">
{{item.category_name}}
</view>
</view>
</scroll-view>
<view class="btns" v-if="!isShow && merCate.length>9" @click="isShow = true">展开全部<text class="iconfont icon-xiangxia"></text></view>
</view>
<view class="foot-btn">
<view class="btn-item" @click="reset">重置</view>
<view class="btn-item confirm" @click="confirm">确定</view>
</view>
</view>
</view>
<view class="right-bg" @click="close"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { mapGetters } from "vuex";
export default{
props: {
storeTypeArr: { //
type: Array,
},
merList: { //
type: Array,
},
status:{
type:Boolean,
default:false
},
},
computed: mapGetters(['viewColor']),
data(){
return {
min: '',
max:'',
isShow:false,
list:[],
merCate: [],
activeList:[],
selectList: [],
showBox:false
}
},
mounted() {
//
this.list = this.storeTypeArr //
this.merCate = this.merList //
this.showBox = this.status
},
methods:{
bindChenck1(item){
item.check = !item.check
this.arrFilter1()
},
bindChenck2(item){
item.check = !item.check
this.arrFilter2()
},
arrFilter1(){
this.selectList = this.list.filter(item=>{
return item.check == true
})
},
arrFilter2(){
this.activeList = this.merCate.filter(item=>{
return item.check == true
})
},
reset(){
this.list.forEach((el,index)=>{
el.check = false
})
this.merCate.forEach((el,index)=>{
el.check = false
})
this.arrFilter1()
this.arrFilter2()
},
confirm(){
this.arrFilter1()
this.arrFilter2()
// console.log(this.activeList)
let obj = {
storeTypeArr:this.selectList,
merList: this.activeList,
status:false
}
this.showBox = false
this.$emit('confirm',obj)
},
close(){
this.showBox = false
this.$emit('close')
},
moveStop(){}
}
}
</script>
<style lang="scss">
.slideInRight{
animation-duration:.5s
}
.right-wrapper{
z-index: 99;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
.control-wrapper{
z-index: 90;
position: absolute;
right: 0;
top: 0;
display: flex;
flex-direction: column;
width: 635rpx;
height: 100%;
background-color: #F5F5F5;
.header{
padding: 50rpx 26rpx 40rpx;
background-color: #fff;
.title{
font-size: 26rpx;
font-weight: bold;
color: #282828;
}
.input-wrapper{
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 28rpx;
input{
width:260rpx;
height:56rpx;
padding: 0 10rpx;
background:rgba(242,242,242,1);
border-radius:28rpx;
font-size: 22rpx;
text-align: center;
}
.line{
width:15rpx;
height:2rpx;
background:#7D7D7D;
}
}
}
.content-box{
position: relative;
flex: 1;
display: flex;
flex-direction: column;
margin-top: 20rpx;
padding: 0 26rpx;
background-color: #fff;
overflow: hidden;
.title{
padding: 40rpx 0 20rpx;
font-size: 26rpx;
font-weight: bold;
color: #282828;
}
.brand-wrapper{
// flex: 1;
overflow: hidden;
.wrapper{
display: flex;
flex-wrap: wrap;
padding-bottom: 20rpx;
}
.item{
display: block;
width:186rpx;
height:56rpx;
line-height: 56rpx;
text-align: center;
background:rgba(242,242,242,1);
border-radius:28rpx;
margin-top: 25rpx;
padding: 0 10rpx;
margin-right: 12rpx;
&:nth-child(3n){
margin-right: 0;
}
&.on{
background: var(--view-minorColor);
border:1px solid var(--view-theme);
color: var(--view-theme);
}
}
.btns{
display: flex;
align-items: center;
justify-content: center;
padding-top: 10rpx;
font-size: 22rpx;
color: #999;
.iconfont{
margin-left: 10rpx;
margin-top: 5rpx;
font-size: 20rpx;
}
}
}
.foot-btn{
display: flex;
align-items: center;
justify-content: space-between;
position: absolute;
// width: 100%;
// text-align: center;
bottom: 30rpx;
.btn-item{
display: flex;
align-items: center;
justify-content: center;
width:286rpx;
height:68rpx;
background:rgba(255,255,255,1);
border:1px solid rgba(170,170,170,1);
border-radius:34rpx;
font-size: 26rpx;
color: #282828;
&.confirm{
background: var(--view-theme);
border-color: var(--view-theme);
color: #fff;
margin-left: 20rpx;
}
}
}
}
}
.right-bg{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,.5);
}
}
</style>

328
components/rightSlidera.vue Normal file
View File

@ -0,0 +1,328 @@
<template>
<view class="right-wrapper" @touchmove.stop.prevent="moveStop" :style="viewColor">
<view class="control-wrapper animated" :class="showBox?'slideInRight':''">
<view class="header">
<view class="title">价格区间</view>
<view class="input-wrapper">
<input placeholder="最低价" v-model="min" type="number"/>
<view class="line"></view>
<input placeholder="最高价" v-model="max" type="number"/>
</view>
</view>
<view class="content-box">
<view class="title">品牌</view>
<view class="brand-wrapper">
<scroll-view :style="{'height':isShow?'90%':'250rpx'}" :scroll-y="isShow">
<view class="wrapper">
<view class="item line1" v-for="(item,index) in list" :key="index" :class="item.check?'on':''" @tap="bindChenck(item)">
{{item.brand_name}}
</view>
</view>
</scroll-view>
<view class="btns" v-if="!isShow && list.length>9" @click="isShow = true">展开全部<text class="iconfont icon-xiangxia"></text></view>
<view class="btns" v-if="isShow && list.length>9" @click="isShow = false">收起<text class="iconfont icon-xiangshang"></text></view>
</view>
<view class="foot-btn">
<view class="btn-item" @click="reset">重置</view>
<view class="btn-item confirm" @click="confirm">确定</view>
</view>
</view>
</view>
<view class="right-bg" @click="close"></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import { mapGetters } from "vuex";
export default{
props: {
brandList: {
type: Array,
},
status:{
type:Boolean,
default:false
},
price_on:{
type:String,
default:''
},
price_off:{
type:String,
default:''
}
},
computed: mapGetters(['viewColor']),
data(){
return {
min: '',
max:'',
is_trader: '',
isShow:false,
list:[],
storeTypeList: [
{name: '全部', value: '',check: true},
{name: '自营', value: 'trader',check: false},
],
activeList:[],
showBox:false
}
},
mounted() {
//
this.list = this.brandList
this.showBox = this.status
this.min = this.price_on
this.max = this.price_off
},
methods:{
bindChenck(item){
item.check = !item.check
this.arrFilter()
},
bindChenckType(item,index){
this.storeTypeList = [
{name: '全部', value: '',check: false},
{name: '自营', value: 'trader',check: false},
]
this.storeTypeList[index]['check'] = true
this.is_trader = this.storeTypeList[0]['check'] ? '' : 1
},
arrFilter(){
this.activeList = this.list.filter(item=>{
return item.check == true
})
},
reset(){
this.list.forEach((el,index)=>{
el.check = false
})
this.storeTypeList = [
{name: '全部', value: '',check: true},
{name: '自营', value: 'trader',check: false}
]
this.min = this.max = ''
this.arrFilter()
},
confirm(){
this.arrFilter()
// console.log(this.activeList)
let obj = {
brandList:this.activeList,
price_on:this.min,
price_off:this.max,
status:false,
is_trader: this.is_trader
}
this.showBox = false
this.$emit('confirm',obj)
},
close(){
// this.list.forEach((el,index)=>{
// el.check = false
// })
// this.arrFilter()
this.showBox = false
this.$emit('close')
},
moveStop(){}
}
}
</script>
<style lang="scss">
.slideInRight{
animation-duration:.5s
}
.right-wrapper{
z-index: 99;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
.control-wrapper{
z-index: 90;
position: absolute;
right: 0;
top: 0;
display: flex;
flex-direction: column;
width: 635rpx;
height: 100%;
background-color: #F5F5F5;
.header{
padding: 50rpx 26rpx 40rpx;
background-color: #fff;
.title{
font-size: 26rpx;
font-weight: bold;
color: #282828;
}
.input-wrapper{
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 28rpx;
input{
width:260rpx;
height:56rpx;
padding: 0 10rpx;
background:rgba(242,242,242,1);
border-radius:28rpx;
font-size: 22rpx;
text-align: center;
}
.line{
width:15rpx;
height:2rpx;
background:#7D7D7D;
}
}
}
.content-box{
position: relative;
flex: 1;
display: flex;
flex-direction: column;
margin-top: 20rpx;
padding: 0 26rpx;
background-color: #fff;
overflow: hidden;
.title{
padding: 40rpx 0 20rpx;
font-size: 26rpx;
font-weight: bold;
color: #282828;
}
.brand-wrapper{
flex: 1;
overflow: hidden;
.wrapper{
display: flex;
flex-wrap: wrap;
padding-bottom: 20rpx;
}
.item{
display: block;
width:186rpx;
height:56rpx;
line-height: 56rpx;
text-align: center;
background:rgba(242,242,242,1);
border-radius:28rpx;
margin-top: 25rpx;
padding: 0 10rpx;
margin-right: 12rpx;
&:nth-child(3n){
margin-right: 0;
}
&.on{
background: var(--view-minorColor);
border:1px solid var(--view-theme);
color: var(--view-theme);
}
}
.btns{
display: flex;
align-items: center;
justify-content: center;
padding-top: 10rpx;
font-size: 22rpx;
color: #999;
.iconfont{
margin-left: 10rpx;
margin-top: 5rpx;
font-size: 20rpx;
}
}
}
.foot-btn{
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 30rpx;
.btn-item{
display: flex;
align-items: center;
justify-content: center;
width:286rpx;
height:68rpx;
background:rgba(255,255,255,1);
border:1px solid rgba(170,170,170,1);
border-radius:34rpx;
font-size: 26rpx;
color: #282828;
&.confirm{
background: var(--view-theme);
border-color: var(--view-theme);
color: #fff;
}
}
}
}
.store_type{
position: relative;
margin-top: 20rpx;
padding: 0 26rpx;
background-color: #fff;
overflow: hidden;
.title{
padding: 40rpx 0 20rpx;
font-size: 26rpx;
font-weight: bold;
color: #282828;
}
.brand-wrapper{
overflow: hidden;
.wrapper{
display: flex;
flex-wrap: wrap;
padding-bottom: 20rpx;
}
.item{
display: block;
width:186rpx;
height:56rpx;
line-height: 56rpx;
text-align: center;
background:rgba(242,242,242,1);
border-radius:28rpx;
margin-top: 25rpx;
padding: 0 10rpx;
margin-right: 12rpx;
&:nth-child(3n){
margin-right: 0;
}
&.on{
background: var(--view-minorColor);
border:1px solid var(--view-theme);
color: var(--view-theme);
}
}
}
}
}
.right-bg{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,.5);
}
}
</style>

View File

@ -0,0 +1,55 @@
<template>
<view v-if="shareInfoStatus" class="poster-first">
<view class="mask-share">
<image src="/static/images/share-info.png" @click="shareInfoClose" @touchmove.stop.prevent="false"></image>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
export default {
props: {
shareInfoStatus: {
type: Boolean,
default:false,
}
},
data: function() {
return {};
},
mounted: function() {},
methods: {
shareInfoClose: function() {
this.$emit("setShareInfoStatus");
}
}
};
</script>
<style scoped lang="scss">
.poster-first {
overscroll-behavior: contain;
}
.mask-share {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 99;
}
.mask-share image {
width: 100%;
height:100%;
}
</style>

View File

@ -0,0 +1,159 @@
<template>
<view class='sharing-packets' :class='isAnimate==true?"":"right"'>
<view class='sharing-con' @click='goShare'>
<image src='/static/images/red-packets.png'></image>
<view class='text font-color'>
<!-- <view class="title">分享赚佣金</view> -->
<!-- <view class='money'><text class='label'></text>{{sharePacket.priceName}}</view> -->
<view class='money'><text class='label'></text>{{parseFloat(sharePacket.max)}}</view>
<!-- <view class='tip'>下单即返佣金</view>
<view class='shareBut'>立即分享</view> -->
</view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
export default {
props: {
sharePacket: {
type: Object,
default: function() {
return {
isState: true,
priceName: ''
}
}
},
showAnimate:{
type: Boolean,
},
},
watch:{
showAnimate(nVal,oVal){
setTimeout(res=>{
this.isAnimate = nVal
},1000)
}
},
data() {
return {
scrollNum:0,
isAnimate:true
};
},
methods: {
closeShare: function() {
this.$emit('closeChange');
},
goShare: function() {
if(this.isAnimate){
this.$emit('listenerActionSheet');
}else{
this.isAnimate = true
this.$emit('boxStatus',true);
}
}
},
}
</script>
<style scoped lang="scss">
.sharing-packets {
position: fixed;
right: 30rpx;
bottom: 200rpx;
z-index: 5;
transition: all 0.3s ease-in-out 0s;
opacity: 1;
transform: scale(1);
&.right{
right: -170rpx;
}
}
.sharing-packets.on {
transform: scale(0);
opacity: 0;
}
.sharing-packets .iconfont {
width: 44rpx;
height: 44rpx;
border-radius: 50%;
text-align: center;
line-height: 44rpx;
background-color: #999;
font-size: 20rpx;
color: #fff;
margin: 0 auto;
box-sizing: border-box;
padding-left: 1px;
}
.sharing-packets .line {
width: 2rpx;
height: 40rpx;
background-color: #999;
margin: 0 auto;
}
.sharing-packets .sharing-con {
width: 197rpx;
height: 195rpx;
position: relative;
}
.sharing-packets .sharing-con image {
width: 100%;
height: 100%;
}
.sharing-packets .sharing-con .text {
position: absolute;
top: 20rpx;
font-size: 20rpx;
width: 100%;
text-align: center;
}
.sharing-packets .sharing-con .text .money {
font-size: 32rpx;
font-weight: bold;
margin-top: 24rpx;
}
.sharing-packets .sharing-con .text .money .label {
font-size: 16rpx;
}
.sharing-packets .sharing-con .text .tip {
font-size: 18rpx;
color: #AA6E56;
margin-top: 5rpx;
}
.sharing-packets .sharing-con .text .shareBut {
width: 60%;
font-size: 20rpx;
color: #F13926;
margin-top: 18rpx;
height: 30rpx;
line-height: 30rpx;
background: #FFE8BB;
border-radius: 30rpx;
margin: 26rpx auto 0;
}
</style>

View File

@ -0,0 +1,298 @@
<template>
<view>
<view class="store_content" :class="isShow?'on':''">
<view class="popup" :class="{ on: isShow }">
<scroll-view scroll-y="true">
<radio-group name="store_name" @change="changeStore">
<template v-for="item in storeList">
<div v-if="item.merchant" class="store-list">
<!-- <div class="invoice-list"> -->
<label :key="item.merchant.mer_id" class="acea-row row-middle">
<view class="text">
<view class="acea-row row-middle">
<image class="mer_logo" v-if="item.merchant.mer_avatar"
:src="item.merchant.mer_avatar" mode=""></image>
<view class="name line1">{{ item.merchant.mer_name }}</view>
</view>
</view>
<radio class="radio" :value="item.merchant.mer_id.toString()" :checked="item.merchant.mer_id == id ? true : false" />
</label>
<!-- </div> -->
</div>
</template>
</radio-group>
</scroll-view>
</view>
</view>
<view class='mask' catchtouchmove="true" :hidden='!isShow' @tap='close'></view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import {
getStoreList
} from '@/api/user.js';
export default {
props:['is_sys'],
data() {
return {
isShow: false,
id: '',
storeList: [],
}
},
watch: {
},
mounted(){
},
methods: {
isShowStore(){
this.isShow = !this.isShow;
},
close: function() {
this.$emit('changeStoreClose');
this.isShow = false;
},
changeStore(e) {
this.close()
this.getStoreName(e.detail.value)
uni.setStorageSync('serMerId',e.detail.value)
},
//
getStoreList(parmas){
getStoreList(parmas).then(res => {
this.storeList = res.data;
let serMerId = this.is_sys !== '' ? null : uni.getStorageSync('serMerId')
let storeInfo = null;
let flag = false
this.storeList.forEach(item=>{
if(flag) return;
if(!serMerId){
if(this.is_sys && !item['merchant']['mer_id']){
storeInfo = item;
flag = true;
}else if(this.is_sys == '0' && item['merchant']['mer_id']){
storeInfo = item;
flag = true;
}
}else if(serMerId == item['merchant']['mer_id']){
storeInfo = item;
flag = true;
}
})
if(!storeInfo){
storeInfo = this.storeList[0]
}
this.id = storeInfo ? storeInfo['mer_id'] : ''
this.$emit('getStoreInfo', storeInfo['merchant'])
this.$emit('getService', storeInfo);
})
},
//ID
getStoreName(id){
for (let i = 0; i < this.storeList.length; i++) {
if (this.storeList[i]['merchant']['mer_id'] == id) {
this.$emit('getStoreInfo',this.storeList[i]['merchant']);
uni.setStorageSync('storeInfo', this.storeList[i]['merchant']);
this.$emit('getService',this.storeList[i]);
}
}
},
}
}
</script>
<style lang="scss" scoped>
.store_content{
position: fixed;
bottom: 0;
width: 100%;
left: 0;
background-color: #fff;
z-index: 77;
border-radius: 16rpx 16rpx 0 0;
padding-bottom: 60rpx;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
}
.store_content.on {
transform: translate3d(0, 0, 0);
}
.store_content .title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
height: 123rpx;
line-height: 123rpx;
position: relative;
}
.store_content .title .iconfont {
position: absolute;
right: 30rpx;
color: #8a8a8a;
font-size: 35rpx;
}
.store_content .store-list{
height: 120rpx;
line-height: 120rpx;
}
.store_content .store-list .mer_logo{
width: 60rpx;
height: 60rpx;
margin-right: 20rpx;
}
form {
font-size: 28rpx;
color: #282828;
}
form input,
form radio-group {
flex: 1;
text-align: right;
}
form input {
font-size: 26rpx;
}
form label {
margin-right: 50rpx;
}
form radio {
margin-right: 8rpx;
}
form checkbox-group {
height: 90rpx;
}
form checkbox {
margin-right: 20rpx;
}
form button {
height: 76rpx;
border-radius: 38rpx;
margin: 16rpx 30rpx;
background-color: #E93323;
font-size: 30rpx;
line-height: 76rpx;
color: #FFFFFF;
}
.panel {
padding-right: 30rpx;
padding-left: 30rpx;
background-color: #FFFFFF;
}
.panel~.panel {
margin-top: 14rpx;
}
.panel .acea-row {
height: 90rpx;
}
.panel .acea-row~.acea-row {
border-top: 1px solid #EEEEEE;
}
.input-placeholder {
font-size: 26rpx;
color: #BBBBBB;
}
.icon-xiangyou {
margin-left: 25rpx;
font-size: 18rpx;
color: #BFBFBF;
}
.btn-wrap {
width: 100%;
padding: 8px 16px;
border-top: 1px solid #F5F5F5;
}
.btn-wrap .back {
border: 1px solid #E93323;
background: none;
color: #E93323;
}
.popup {
width: 100%;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
background-color: #FFFFFF;
overflow: hidden;
}
.popup scroll-view {
height: 466rpx;
padding-right: 30rpx;
padding-left: 30rpx;
box-sizing: border-box;
}
.popup .text {
flex: 1;
min-width: 0;
font-size: 28rpx;
color: #282828;
}
.popup .info {
margin-top: 10rpx;
font-size: 22rpx;
color: #909090;
}
.popup .icon-guanbi {
position: absolute;
top: 50%;
right: 30rpx;
z-index: 2;
transform: translateY(-50%);
font-size: 30rpx;
color: #707070;
cursor: pointer;
}
.popup button {
height: 86rpx;
border-radius: 43rpx;
margin-right: 30rpx;
margin-left: 30rpx;
background-color: #E93323;
font-size: 30rpx;
line-height: 86rpx;
color: #FFFFFF;
}
.popup .text .acea-row {
display: inline-flex;
max-width: 100%;
}
.popup .name {
flex: 1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 30rpx;
}
.popup .label {
width: 56rpx;
height: 28rpx;
border: 1px solid #E93323;
margin-left: 18rpx;
font-size: 20rpx;
line-height: 26rpx;
text-align: center;
color: #E93323;
}
.popup .type {
width: 124rpx;
height: 42rpx;
margin-top: 14rpx;
background-color: #FCF0E0;
font-size: 24rpx;
line-height: 42rpx;
text-align: center;
color: #D67300;
}
.popup .type.special {
background-color: #FDE9E7;
color: #E93323;
}
</style>

View File

@ -0,0 +1,607 @@
<template>
<view class="containers" :style="viewColor">
<view class="header">
<view class="search">
<text class="iconfont icon-xiazai5"></text>
<input type="text" placeholder="请输入商品名称" v-model="searchVal" @input="setValue" confirm-type="search"
@confirm="searchBut()" placeholder-class='placeholder'>
</view>
<view class="iconclose" @click="close">
<image src="@/static/images/wt_close.png" mode="aspectFit"></image>
</view>
</view>
<view class="main">
<scroll-view scroll-y="true" @touchmove.stop>
<block>
<view v-if="bought.length" @touchmove="onTouchmove" id="goods" class="goods">
<view class="picTxt acea-row" v-for="(item, i) in bought" :key="i">
<view class="checkbox">
<text @click.stop="goodsCheck(item)" v-if="item.check"
class="iconfont icon-xuanzhong1"></text>
<text @click.stop="goodsCheck(item)" v-else
:class="checkedArr.length >=5 ? 'disabled': ''"
class="iconfont icon-weixuanzhong"></text>
</view>
<view class='pictrue'>
<image :src='item.image'></image>
</view>
<view class='text'>
<view class='line2 name'>{{item.store_name}}</view>
<view class="picTxt_one" v-if="item.attrValue.length>0">
<picker class="slecte" v-if="item.attrValue.length>1"
@change="bindPickerChange($event,item.attrValue,i)" :value="index"
:range="item.attrValue" :range-key="'sku'">
<view class="uni-input">{{item.attrValue[index].sku}}</view>
</picker>
<view class="" style="margin-top: 10rpx;">
库存:{{item.attrValue[index].stock}}
</view>
</view>
</view>
<view class="picTxt_price">
<view class="price">
<span>出售价格</span>
<input type="text" :value="item.price" placeholder="输入出售价格"
@input="producrprice($event,i,item)" adjust-position=""
placeholder-style="color: #CCCCCC;" />
</view>
<view class="price_num">
<span>出售数量</span>
<subtractive v-if='item.number==0' style="margin-top: 10rpx;margin-left: 20rpx;"
class="step" :min="0" :max="item.attrValue[index].stock" :value="peicenumber"
:isMax="true" :isMin="true" index="11" @eventChange="numberChange($event,i)">
</subtractive>
<subtractive v-else style="margin-top: 10rpx;margin-left: 20rpx;" class="step"
:min="0" :max="item.attrValue[index].stock" :value="item.number" :isMax="true"
:isMin="true" index="11" @increment="incrementTotal($event,i,item)"
@eventChange="numberChange($event,i)"></subtractive>
</view>
</view>
</view>
</view>
<view v-else class="empty">
<image src="/static/images/no_thing.png"></image>
<text>暂无内容哦~</text>
</view>
</block>
</scroll-view>
<view class="foot_bar">
<button class="confirm_btn" @click="submit">确定({{checkedArr.length}})</button>
</view>
</view>
</view>
</template>
<script>
import Loading from '@/components/Loading/index.vue';
import subtractive from '@/components/subtractive/subtractive.vue';
import {
getCommunitygetOrderList
} from "@/api/trading-floor";
import {
mapGetters
} from "vuex";
export default {
props: {
checkedObj: {
type: Array,
default: []
}
},
computed: mapGetters(['viewColor']),
components: {
Loading,
subtractive
},
data() {
return {
isActive: 0,
loadedb: false,
loadingb: false,
loadedc: false,
loadingc: false,
loadeds: false,
loadings: false,
whereb: {
page: 1,
limit: 10,
keyword: '',
},
peicenumber: 0,
searchVal: "",
checked: [],
list: [],
bought: [],
checkedArr: [],
aryys: [],
// picker
storageCustomList: [{
CustGoodsCode: "TEST001",
CustGoodsName: "测试货主001",
IfBoxId: 0,
IfProductId: 0,
}, {
CustGoodsCode: "TEST002",
CustGoodsName: "测试货主002",
IfBoxId: 0,
IfProductId: 0,
}, {
CustGoodsCode: "TEST003",
CustGoodsName: "测试货主003",
IfBoxId: 0,
IfProductId: 0,
}],
index: 0,
pickerData: '请选择',
itstock: '',
};
},
watch: {
checkedObj: {
handler(n) {
this.checkedArr = n
},
deep: true
}
},
mounted() {
this.checkedArr = this.checkedObj
this.aryys = this.checkedObj
this.getBounht();
},
methods: {
//
producrprice(e, i, item) {
this.bought[i].price = e.detail.value
this.$set(item, 'check', false);
for (let i in this.checkedArr) {
if (this.checkedArr[i].product_id == item.product_id) {
this.checkedArr.splice(i, 1)
}
}
},
incrementTotal(e, i, item) {
// console.log(e, i, item)
this.$set(item, 'check', false);
for (let i in this.checkedArr) {
if (this.checkedArr[i].product_id == item.product_id) {
this.checkedArr.splice(i, 1)
}
}
},
// picker
bindPickerChange: function(e, storage, num) {
this.bought[num].attrValue[this.index].sku = storage[e.detail.value].sku
this.bought[num].attrValue[this.index].stock = storage[e.detail.value].stock
this.bought[num].product_attr_unique = storage[e.detail.value].unique
this.pickerData = storage[this.index] //
if (this.bought[num].attrValue[this.index].stock == 0) {
this.$util.Tips({
title: '库存不足'
});
}
},
//
close() {
this.$emit('close');
},
numberChange(data, i) {
this.peicenumber = data.number;
this.bought[i].number = data.number
},
tabs(index) {
this.isActive = index
this.$set(this.whereb, 'keyword', '');
this.searchVal = ''
this.searchBut()
},
onTouchmove(e) {
if (this.loadendb) return;
if (this.loadingb) return;
const query = uni.createSelectorQuery().in(this);
query.select('#goods').boundingClientRect(data => {
if (data.bottom < 1500 && data.top < 0) {
this.getBounht();
}
}).exec();
//
},
setValue: function(event) {
this.$set(this.whereb, 'keyword', event.detail.value);
if (!event.detail.value) {
this.whereb.page = 1
this.loadedb = false
this.getBounht()
}
},
searchBut() {
this.bought = []
this.whereb.page = 1
this.loadedb = false
this.getBounht()
},
getBounht() {
var that = this;
// console.log('1111111', that.loadingb, that.loadedb)
if (that.loadingb || that.loadedb) return;
that.loadingb = true;
getCommunitygetOrderList(that.whereb).then(
res => {
that.loadingb = false;
that.loadedb = res.data.list.length < that.whereb.limit;
that.bought.push.apply(that.bought, res.data.list);
that.whereb.page = that.whereb.page + 1;
that.getInitchecked(that.bought);
},
error => {
that.$util.Tips({
title: error.msg
})
}
);
},
/*获取初始化选中的数据*/
getInitchecked(arr) {
let that = this;
arr.forEach((item, index) => {
that.$set(item, 'check', false);
that.checkedArr.forEach((val, i) => {
if (item.product_id == val.product_id) {
that.$set(item, 'check', true);
that.$set(item, 'number', val.number);
that.$set(item, 'price', val.price);
that.peicenumber=val.number
}
})
})
},
/*已选中的商品打钩*/
getCheckedGoods() {
this.checked = []
this.checkedArr.forEach((item, index) => {
this.checkedArr.push(item)
})
},
/*点击选中与否*/
goodsCheck(item) {
this.$set(item, 'check', !item.check);
if (item.check) {
if (this.peicenumber == 0) {
item.number = 1
}
if (!item.product_attr_unique) {
item.product_attr_unique = item.attrValue[0].unique
}
this.checkedArr.push(item)
} else {
this.checkedArr.splice(this.checkedArr.findIndex(itemn => ((itemn.product_id == item.product_id))), 1)
}
},
/*确定提交*/
submit() {
this.$emit('getProduct', this.checkedArr);
},
}
}
</script>
<style lang="scss" scoped>
.containers {
background: #ffffff;
border-radius: 16rpx 16rpx 0 0;
padding: 40rpx 0;
position: relative;
.header {
position: relative;
padding: 0 30rpx;
.title {
width: 100%;
text-align: center;
text {
position: relative;
margin: 0 50rpx;
color: #999999;
font-size: 30rpx;
&.on {
color: #333333;
font-weight: bold;
font-size: 34rpx;
&::after {
content: "";
display: inline-block;
width: 40rpx;
height: 5rpx;
background: var(--view-theme);
position: absolute;
bottom: -10rpx;
left: 10rpx;
}
}
}
}
.iconclose {
width: 44rpx;
height: 44rpx;
line-height: 44rpx;
border-radius: 50%;
text-align: center;
position: absolute;
top: -150rpx;
right: 30rpx;
image {
width: 100%;
height: 100%;
}
}
.search {
margin-top: 44rpx;
background: #F5F5F5;
border-radius: 30rpx;
padding: 12rpx 30rpx 12rpx 66rpx;
position: relative;
.iconfont {
font-size: 24rpx;
color: #939393;
position: absolute;
top: 20rpx;
left: 30rpx;
}
.placeholder {
color: #999999;
font-size: 26rpx;
}
}
.sub_title {
color: #282828;
font-size: 26rpx;
margin-top: 30rpx;
}
.iconfont {
color: #8A8A8A;
font-size: 28rpx;
position: absolute;
top: 0;
right: 30rpx;
}
}
scroll-view {
height: 650rpx;
}
.main {
height: 650rpx;
margin: 40rpx 0 80rpx;
padding: 0 30rpx;
}
}
.picTxt {
width: 100%;
padding: 25rpx 0;
position: relative;
align-items: center;
justify-content: space-between;
border-top: 2rpx solid #E7E6E4;
.picTxt_one {
white-space: nowrap;
overflow: hidden;
}
.picTxt_one {
display: flex;
margin-top: 20rpx;
.slecte {
margin-right: 30rpx;
width: 280rpx;
height: 60rpx;
line-height: 60rpx;
text-align: center;
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #959595;
background-color: #E7E6E4;
border-radius: 10rpx 10rpx 10rpx 10rpx;
white-space: nowrap;
overflow: hidden;
}
}
.picTxt_price {
display: flex;
margin-top: 37rpx;
height: 70rpx;
line-height: 70rpx;
.price {
display: flex;
margin-right: 15rpx;
input {
width: 210rpx;
text-align: center;
height: 70rpx;
background: #F5F5F5;
border-radius: 7rpx 7rpx 7rpx 7rpx;
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
margin-left: 20rpx;
}
}
.price_num {
display: flex;
}
}
.checkbox {
margin-right: 30rpx;
.iconfont {
font-size: 38rpx;
color: #CCCCCC;
}
.icon-xuanzhong1 {
color: var(--view-theme);
}
.disabled {
pointer-events: none;
cursor: default;
opacity: 0.3;
}
}
.pictrue {
width: 160rpx;
height: 160rpx;
image {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
}
.text {
width: 430rpx;
margin-left: 30rpx;
font-size: 28rpx;
color: #282828;
position: relative;
height: 160rpx;
.name {
color: #282828;
font-size: 28rpx;
}
.money {
position: absolute;
bottom: 0;
left: 0;
color: var(--view-priceColor);
font-size: 22rpx;
font-weight: bold;
text {
font-size: 26rpx;
}
}
}
}
.foot_bar {
width: 100%;
position: fixed;
// bottom: 54px;
left: 0;
padding: 20rpx 0;
z-index: 5;
.confirm_btn {
width: 710rpx;
height: 86rpx;
line-height: 86rpx;
color: #ffffff;
text-align: center;
font-size: 32rpx;
background: var(--view-theme);
border-radius: 43rpx;
margin: 0 auto;
}
}
.empty {
margin: 130rpx 0 150rpx;
text-align: center;
image,
uni-image {
display: inline-block;
width: 414rpx;
height: 305rpx;
}
text {
display: block;
color: #999999;
font-size: 26rpx;
}
}
</style>

View File

@ -0,0 +1,190 @@
<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="rect_idx + '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="circle_idx + '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.getSystemInfoSync();
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) {
that.skeletonRectLists = res[0];
});
},
radiusHandle() {
const that = this;
uni.createSelectorQuery().selectAll(`.${this.selector}-radius`).boundingClientRect().exec(function(res) {
that.skeletonCircleLists = res[0];
});
}
}
}
</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>

105
components/specs/index.vue Normal file
View File

@ -0,0 +1,105 @@
<template>
<!-- 产品参数 -->
<view>
<view class="specs" :class="specsInfo.show === true ? 'on' : ''">
<view class="title">商品参数<text class="iconfont icon-guanbi5" @click="closeSpecs"></text></view>
<view class="list">
<view class="item acea-row" v-for="(item,index) in specsInfo.params" :key="index">
<view class="name">{{item.name}}</view>
<view class="val">{{item.value}}</view>
</view>
</view>
<view class="bnt" @click="closeSpecs">完成</view>
<slot name="bottom"></slot>
</view>
<view class="mask" @touchmove.prevent :hidden="specsInfo.show === false" @click="closeSpecs"></view>
</view>
</template>
<script>
export default {
props: {
specsInfo: {
type: Object,
default: () => {}
},
},
data() {
return {};
},
mounted() {},
methods: {
closeSpecs(){
this.$emit('myevent');
}
}
}
</script>
<style scoped lang="scss">
.specs{
position: fixed;
bottom: 0;
width: 100%;
left: 0;
background-color: #fff;
z-index: 280;
border-radius: 16rpx 16rpx 0 0;
transform: translate3d(0, 100%, 0);
transition: all .3s cubic-bezier(.25, .5, .5, .9);
padding-bottom: 22rpx;
padding-bottom: calc(22rpx+ constant(safe-area-inset-bottom)); /// IOS<11.2/
padding-bottom: calc(22rpx + env(safe-area-inset-bottom)); /// IOS>11.2/
.title{
font-size: 32rpx;
color: #282828;
text-align: center;
margin: 38rpx 0 36rpx 0;
position: relative;
font-weight: bold;
.iconfont{
position: absolute;
right: 30rpx;
top:0;
font-size: 36rpx;
font-weight: normal;
color: #999999;
}
}
.list{
height: 750rpx;
margin: 0 30rpx;
color: #999999;
overflow-x: hidden;
overflow-y: auto;
.item{
padding: 30rpx 0;
border-bottom: 1rpx solid #eee;
.name{
width: 160rpx;
margin-right: 10rpx;
word-break: break-all;
}
.val{
width: 510rpx;
word-break: break-all;
color: #282828;
}
}
}
.bnt{
width: 690rpx;
height: 86rpx;
text-align: center;
line-height: 86rpx;
border-radius: 43rpx;
background-color: var(--view-theme);
font-size: 30rpx;
color: #fff;
margin: 0 auto;
}
}
.specs.on{
transform: translate3d(0, 0, 0);
}
</style>

View File

@ -0,0 +1,217 @@
<template>
<view class="uni-numbox">
<!-- -部分 -->
<view class="uni-numbox-minus" @click="_calcValue('subtract')">
<text :class="minDisabled?'uni-numbox-disabled': ''">-</text>
</view>
<!-- 中间输入数值部分 -->
<input class="uni-numbox-value" type="number" :disabled="disabled" :value="inputValue" @blur="_onBlur">
<!-- + 部分 -->
<view class="uni-numbox-plus" @click="_calcValue('add')">
<text :class="maxDisabled?'uni-numbox-disabled': ''">+</text>
</view>
</view>
</template>
<script>
export default {
name: 'uni-number-box',
props: {
// isMax
isMax: {
type: Boolean,
default: false
},
// isMin
isMin: {
type: Boolean,
default: false
},
// index
index: {
type: String,
default: 0
},
// value
value: {
type: Number,
default: 0
},
// min
min: {
type: Number,
default: -Infinity
},
// max
max: {
type: Number,
default: Infinity
},
// step
step: {
type: Number,
default: 1
},
// disabled
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
inputValue: this.value,
minDisabled: false,
maxDisabled: false
}
},
created() {
this.maxDisabled = this.isMax;
this.minDisabled = this.isMin;
},
computed: {
},
watch: {
inputValue(number) {
const data = {
number: number,
index: this.index
}
this.$emit('eventChange', data);
}
},
methods: {
_calcValue(type) {
const scale = this._getDecimalScale();
let value = this.inputValue * scale;
let newValue = 0;
let step = this.step * scale;
if (type === 'subtract') {
newValue = value - step;
if (newValue <= this.min) {
this.minDisabled = true;
}
if (newValue < this.min) {
newValue = this.min
this.$util.Tips({
title: '达到最小值了',
icon: 'error'
})
}
if (newValue < this.max && this.maxDisabled === true) {
this.maxDisabled = false;
}
} else if (type === 'add') {
newValue = value + step;
if (newValue >= this.max) {
this.maxDisabled = true;
}
if (newValue > this.max) {
this.$util.Tips({
title: '达到最大值了',
icon: 'error'
})
newValue = this.max
}
if (newValue > this.min && this.minDisabled === true) {
this.minDisabled = false;
}
}
if (newValue === value) {
return;
}
this.inputValue = newValue / scale;
this.$emit('increment', this.inputValue)
},
_getDecimalScale() {
let scale = 1;
//
if (~~this.step !== this.step) {
scale = Math.pow(10, (this.step + '').split('.')[1].length);
}
return scale;
},
_onBlur(event) {
let value = event.detail.value;
if (!value) {
this.inputValue = 0;
return
}
value = +value;
if (value > this.max) {
value = this.max;
} else if (value < this.min) {
value = this.min
}
this.inputValue = value
}
}
}
</script>
<style>
.uni-numbox {
/* position:absolute; */
/* left: 30upx;
bottom: 0; */
display: flex;
justify-content: flex-start;
align-items: center;
width: 200upx;
height: 50upx;
/* background:#f5f5f5; */
}
.uni-numbox-minus {
background: #EEEEEE !important;
color: #909399 !important;
}
.uni-numbox-minus,
.uni-numbox-plus {
margin: 0;
width: 53rpx;
height: 53rpx;
background-color: #F84221;
opacity: 1;
line-height: 53rpx;
text-align: center;
position: relative;
color: #fff;
font-size: 40upx;
}
.uni-numbox-minus .yticon,
.uni-numbox-plus .yticon {
font-size: 36upx;
color: #555;
}
.uni-numbox-minus {
/* border-right: none;
border-top-left-radius: 6upx;
border-bottom-left-radius: 6upx; */
}
.uni-numbox-plus {
/* border-left: none;
border-top-right-radius: 6upx;
border-bottom-right-radius: 6upx; */
}
.uni-numbox-value {
position: relative;
/* background-color: #f5f5f5; */
width: 90upx;
height: 50upx;
text-align: center;
padding: 0;
font-size: 30upx;
}
.uni-numbox-disabled.yticon {
color: #d6d6d6;
}
</style>

View File

@ -0,0 +1,60 @@
<template>
<view class='swiper'>
<swiper :autoplay="autoplay" :circular="circular" :interval="interval" :duration="duration" @change="swiperChange">
<block v-for="(item,index) in imgUrls" :key="index">
<swiper-item>
<navigator :url="item.link" style='width:100%;height:100%;' hover-class='none'><image :src="item.img" class="slide-image"/></navigator>
</swiper-item>
</block>
</swiper>
<view class="dots acea-row">
<view class="dot" :class="index == currentSwiper ? 'active' : ''" v-for="(item,index) in imgUrls" :key="index"></view>
</view>
</view>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
export default {
props: {
imgUrls: {
type: Array,
default: function(){
return [];
}
}
},
data() {
return {
circular: true,
autoplay: true,
interval: 3000,
duration: 500,
currentSwiper: 0
};
},
methods: {
swiperChange: function (e) {
this.currentSwiper = e.detail.current
}
}
}
</script>
<style scoped lang="scss">
.swiper{width:100%;height:282rpx;position:relative;}
.swiper swiper{width:100%;height:100%;position:relative;}
.swiper swiper .slide-image{width:100%;height:100%;}
.swiper .dots{position:absolute;right:40rpx;bottom:20rpx;}
.swiper .dots .dot{width:12rpx;height:12rpx;border:2rpx solid #fff;border-radius:50%;margin-right:15rpx;}
.swiper .dots .dot.active{border-color:#e93323;background-color:#e93323;}
</style>

View File

@ -0,0 +1,171 @@
<template>
<canvas v-if="canvasId" :id="canvasId" :canvasId="canvasId" :style="{'width':cWidth*pixelRatio+'px','height':cHeight*pixelRatio+'px', 'transform': 'scale('+(1/pixelRatio)+')','margin-left':-cWidth*(pixelRatio-1)/2+'px','margin-top':-cHeight*(pixelRatio-1)/2+'px'}"
@touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" @error="error">
</canvas>
</template>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import uCharts from './u-charts.js';
var canvases = {};
export default {
props: {
chartType: {
required: true,
type: String,
default: 'column'
},
opts: {
required: true,
type: Object,
default () {
return null;
},
},
canvasId: {
type: String,
default: 'u-canvas',
},
cWidth: {
default: 375,
},
cHeight: {
default: 250,
},
pixelRatio: {
type: Number,
default: 1,
},
},
mounted() {
this.init();
},
methods: {
init() {
switch (this.chartType) {
case 'column':
this.initColumnChart();
break;
case 'line':
this.initLineChart();
break;
default:
break;
}
},
initColumnChart() {
canvases[this.canvasId] = new uCharts({
$this: this,
canvasId: this.canvasId,
type: 'column',
legend: true,
fontSize: 11,
background: '#FFFFFF',
pixelRatio: this.pixelRatio,
animation: true,
categories: this.opts.categories,
series: this.opts.series,
enableScroll: true,
xAxis: {
disableGrid: true,
itemCount: 4,
scrollShow: true
},
yAxis: {
//disabled:true
},
dataLabel: true,
width: this.cWidth * this.pixelRatio,
height: this.cHeight * this.pixelRatio,
extra: {
column: {
type: 'group',
}
}
});
},
initLineChart() {
canvases[this.canvasId] = new uCharts({
$this: this,
canvasId: this.canvasId,
type: 'line',
fontSize: 11,
legend: true,
dataLabel: false,
dataPointShape: true,
background: '#FFFFFF',
pixelRatio: this.pixelRatio,
categories: this.opts.categories,
series: this.opts.series,
animation: true,
enableScroll: true,
xAxis: {
type: 'grid',
gridColor: '#CCCCCC',
gridType: 'dash',
dashLength: 8,
itemCount: 4,
scrollShow: true
},
yAxis: {
gridType: 'dash',
gridColor: '#CCCCCC',
dashLength: 8,
splitNumber: 5,
min: 10,
max: 180,
format: (val) => {
return val.toFixed(0) + '元'
}
},
width: this.cWidth * this.pixelRatio,
height: this.cHeight * this.pixelRatio,
extra: {
line: {
type: 'straight'
}
}
});
},
// cidcanvas-id,newdata
changeData(cid,newdata) {
canvases[cid].updateData({
series: newdata.series,
categories: newdata.categories
});
},
touchStart(e) {
canvases[this.canvasId].showToolTip(e, {
format: function(item, category) {
return category + ' ' + item.name + ':' + item.data
}
});
canvases[this.canvasId].scrollStart(e);
},
touchMove(e) {
canvases[this.canvasId].scroll(e);
},
touchEnd(e) {
canvases[this.canvasId].scrollEnd(e);
},
error(e) {}
},
};
</script>
<style scoped>
.charts {
width: 100%;
height: 100%;
flex: 1;
background-color: #FFFFFF;
}
</style>

File diff suppressed because it is too large Load Diff

1
components/ucharts/ucharts.min.js vendored Normal file

File diff suppressed because one or more lines are too long

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