初始上传
This commit is contained in:
4
addon/cashier/source/os/.gitignore
vendored
Executable file
4
addon/cashier/source/os/.gitignore
vendored
Executable file
@@ -0,0 +1,4 @@
|
||||
/unpackage
|
||||
/.hbuilderx
|
||||
/node_modules
|
||||
/electron/node_modules
|
||||
255
addon/cashier/source/os/App.vue
Executable file
255
addon/cashier/source/os/App.vue
Executable file
@@ -0,0 +1,255 @@
|
||||
<script>
|
||||
import {checkPageAuth,getOrderRemind,pushBind,getPushStatus} from '@/api/config.js';
|
||||
import {mapGetters} from 'vuex';
|
||||
import config from 'common/js/config.js';
|
||||
export default {
|
||||
onLaunch: function (option) {
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
uni.getSystemInfo({
|
||||
success: res => {
|
||||
let fontsize = ((res.windowWidth * 16) / 1200) * 5.5 + 'px';
|
||||
this.$store.commit('app/setRootSize', fontsize);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
|
||||
if (uni.getStorageSync('globalStoreInfo')) {
|
||||
this.$store.commit('app/setGlobalStoreInfo', uni.getStorageSync('globalStoreInfo'));
|
||||
}
|
||||
|
||||
if (uni.getStorageSync('globalStoreId')) {
|
||||
this.$store.commit('app/setGlobalStoreId', uni.getStorageSync('globalStoreId'));
|
||||
}
|
||||
|
||||
if (uni.getStorageSync('defaultImg')) {
|
||||
this.$store.commit('app/setDefaultImg', uni.getStorageSync('defaultImg'));
|
||||
}
|
||||
|
||||
if (uni.getStorageSync('addon')) {
|
||||
this.$store.commit('app/setAddon', uni.getStorageSync('addon'));
|
||||
}
|
||||
|
||||
if (uni.getStorageSync('themeConfig')) {
|
||||
this.$store.commit('app/setThemeConfig', uni.getStorageSync('themeConfig'));
|
||||
}
|
||||
|
||||
this.$store.dispatch('app/getAddonIsExistFn');
|
||||
this.$store.dispatch('app/getDefaultImgFn');
|
||||
|
||||
this.$store.dispatch('app/getThemeConfigFn');
|
||||
this.$store.dispatch('app/getMemberSearchWayConfigFn');
|
||||
|
||||
if (uni.getStorageSync('cashierToken')) {
|
||||
this.$store.dispatch('app/getStoreInfoFn');
|
||||
this.$store.dispatch('app/getUserInfoFn');
|
||||
this.$store.dispatch('app/getUserGroupFn');
|
||||
}
|
||||
|
||||
this.$store.commit('app/setCurrRoute', '/' + option.path);
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
plus.webview.open(this.$config.baseUrl + '/cashier/pages/index/loading', 'loading');
|
||||
uni.switchTab({
|
||||
url: '/pages/reserve/index',
|
||||
success: () => {
|
||||
uni.switchTab({
|
||||
url: '/pages/recharge/index',
|
||||
success: () => {
|
||||
uni.switchTab({
|
||||
url: '/pages/verify/index',
|
||||
success: () => {
|
||||
if (!uni.getStorageSync('cashierToken')) {
|
||||
uni.navigateTo({url: '/pages/login/login'});
|
||||
} else {
|
||||
uni.switchTab({url: '/pages/billing/index'});
|
||||
}
|
||||
plus.webview.close('loading');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
this.getOrderRemindFn()
|
||||
this.getPushStatusFn()
|
||||
this.initSocket()
|
||||
},
|
||||
onShow: function () {
|
||||
if (!uni.getStorageSync('cashierToken')) {
|
||||
|
||||
// #ifdef H5
|
||||
if (location.href.indexOf('pages/index/loading') == -1) {
|
||||
this.$util.redirectTo('/pages/login/login', {}, 'redirectTo');
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
this.$util.redirectTo('/pages/login/login', {}, 'redirectTo');
|
||||
// #endif
|
||||
|
||||
}
|
||||
// this.$nextTick(()=>{
|
||||
// window.addEventListener('beforeunload', this.handleBeforeUnload);
|
||||
// })
|
||||
},
|
||||
|
||||
methods: {
|
||||
// handleBeforeUnload(e){
|
||||
// // 提示用户确认
|
||||
// e.preventDefault();
|
||||
// },
|
||||
getOrderRemindFn(){
|
||||
getOrderRemind().then(res=>{
|
||||
if(res.code>=0){
|
||||
this.$store.dispatch('app/initOverallAudio',res.data);
|
||||
}
|
||||
})
|
||||
},
|
||||
getPushStatusFn(){
|
||||
getPushStatus().then(res=>{
|
||||
if(res.code>=0){
|
||||
this.$store.dispatch('app/setIsSocketConnect',true)
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
initSocket(){
|
||||
// 心跳机制
|
||||
|
||||
// 可自定义成你的模式,这里只做基本处理
|
||||
let linkNumber = 1
|
||||
let socketInterval=setInterval(()=>{
|
||||
let token = uni.getStorageSync('cashierToken');
|
||||
try{
|
||||
if(token&&this.isSocketConnect){
|
||||
if(linkNumber>3){
|
||||
|
||||
this.$util.showToast({
|
||||
title: 'webSocket连接异常,请联系管理员'
|
||||
});
|
||||
|
||||
if(this.overallAudioIsPlay) this.$store.dispatch('app/setOverallAudioIsPlay',false);
|
||||
this.$store.dispatch('app/setIsSocketConnect',false)
|
||||
linkNumber = 1
|
||||
return false
|
||||
}
|
||||
uni.sendSocketMessage({
|
||||
data: 'ping',
|
||||
success: (res) => {
|
||||
linkNumber = 1
|
||||
},
|
||||
fail: (e) => {
|
||||
linkNumber++
|
||||
uni.connectSocket({
|
||||
url:config.webSocket,
|
||||
complete: (res) => {
|
||||
},
|
||||
fail: (connectE) => {
|
||||
// console.log(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}catch(e){
|
||||
//TODO handle the exception
|
||||
}
|
||||
|
||||
},1000)
|
||||
uni.onSocketMessage((res)=>{
|
||||
var data = JSON.parse(res.data);
|
||||
let token = uni.getStorageSync('cashierToken');
|
||||
switch(data.type){
|
||||
case 'init':
|
||||
if(token){
|
||||
this.$store.dispatch('app/setOverallAudioBindClientId',data.data.client_id)
|
||||
pushBind({client_id:data.data.client_id})
|
||||
}
|
||||
break;
|
||||
case 'ping':
|
||||
uni.sendSocketMessage({
|
||||
data: 'ping',
|
||||
});
|
||||
break;
|
||||
default:
|
||||
this.$store.dispatch('app/overallAudioPlay',data.data.audio);
|
||||
}
|
||||
});
|
||||
},
|
||||
initRoute(route) {
|
||||
const search = function (menu, route, arr = []) {
|
||||
menu.find((item, index) => {
|
||||
if (item.path == route) {
|
||||
arr.push(index);
|
||||
return true;
|
||||
} else if (item.children) {
|
||||
arr = search(item.children, route, arr);
|
||||
if (arr.length) {
|
||||
arr.push(index);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return arr;
|
||||
};
|
||||
|
||||
let menuIndex = search(this.menu, route).reverse();
|
||||
this.$store.commit('app/setMenuIndex', {level: 'firstMenuIndex', index: menuIndex[0]});
|
||||
this.$store.commit('app/setMenuIndex', {level: 'secondMenuIndex', index: menuIndex[1] ?? -1});
|
||||
this.$store.commit('app/setMenuIndex', {level: 'thirdMenuIndex', index: menuIndex[2] ?? -1});
|
||||
},
|
||||
/**
|
||||
* 检测页面是否有权限
|
||||
*/
|
||||
checkPageAuthFn() {
|
||||
checkPageAuth(this.currRoute).then(res => {
|
||||
if (res.code && res.code == -10012) {
|
||||
this.$util.redirectTo('/pages/index/no_permission', {}, 'redirectTo');
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
menu() {
|
||||
let menu = require('@/common/menu/store.js');
|
||||
return menu.default ?? [];
|
||||
},
|
||||
isSocketConnect(){
|
||||
return this.$store.state.app.isSocketConnect
|
||||
},
|
||||
overallAudioIsPlay(){
|
||||
return this.$store.state.app.overallAudioIsPlay
|
||||
},
|
||||
...mapGetters(['currRoute'])
|
||||
},
|
||||
watch: {
|
||||
currRoute: function (nVal, oVal) {
|
||||
if (nVal) {
|
||||
this.initRoute(nVal);
|
||||
this.checkPageAuthFn();
|
||||
}
|
||||
},
|
||||
menu: function (nVal) {
|
||||
if (nVal.length) {
|
||||
this.initRoute(this.currRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/*每个页面公共css */
|
||||
@import url('/common/css/iconfont.css');
|
||||
@import '/common/css/common.scss';
|
||||
@import '/common/css/form.scss';
|
||||
|
||||
uni-toast .uni-toast__content {
|
||||
font-size: 0.16rem !important;
|
||||
}
|
||||
</style>
|
||||
24
addon/cashier/source/os/api/address.js
Executable file
24
addon/cashier/source/os/api/address.js
Executable file
@@ -0,0 +1,24 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取地址数据
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getAreaList(params) {
|
||||
return request.post('/cashier/storeapi/address/arealist', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过经纬度查询地址信息(地址名称)
|
||||
*/
|
||||
export function getTranAddressInfo(position) {
|
||||
return request.post('/cashier/storeapi/address/tranaddressinfo', {data: {latlng: position}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过地址名称查询详细地址信息(经纬度)
|
||||
* @param {Object} name
|
||||
*/
|
||||
export function getAddressByName(name) {
|
||||
return request.post('/cashier/storeapi/address/getaddressbyname', {data: {address: name}})
|
||||
}
|
||||
9
addon/cashier/source/os/api/card.js
Executable file
9
addon/cashier/source/os/api/card.js
Executable file
@@ -0,0 +1,9 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取卡项列表(分页)
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getCardList(params) {
|
||||
return request.post('/cashier/storeapi/card/page', {data: params})
|
||||
}
|
||||
121
addon/cashier/source/os/api/config.js
Executable file
121
addon/cashier/source/os/api/config.js
Executable file
@@ -0,0 +1,121 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/************************************整体设置+系统权限相关*******************************/
|
||||
/**
|
||||
* 获取收款设置
|
||||
*/
|
||||
export function getCollectMoneyConfig() {
|
||||
return request.post('/cashier/storeapi/cashier/getcashiercollectmoneyconfig')
|
||||
}
|
||||
|
||||
/**
|
||||
* 收款设置
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function setCollectMoneyConfig(params) {
|
||||
return request.post('/cashier/storeapi/cashier/setcashiercollectmoneyconfig', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测页面是否有权限
|
||||
* @param {Object} page
|
||||
*/
|
||||
export function checkPageAuth(page) {
|
||||
return request.post('/cashier/storeapi/store/checkpageauth', {data: {page}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测是否有新版本
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function checkUpdate(params) {
|
||||
return request.post('/cashier/storeapi/appversion/checkupdate', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件是否存在
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getAddonIsExist(params) {
|
||||
return request.post('/storeapi/addon/addonisexit')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认图
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getDefaultImg(params) {
|
||||
return request.post('/cashier/storeapi/cashier/defaultimg')
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置收银台主题风格配置
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function setThemeConfig(params) {
|
||||
return request.post('/cashier/storeapi/cashier/setThemeConfig', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收银台主题风格配置
|
||||
*/
|
||||
export function getThemeConfig() {
|
||||
return request.post('/cashier/storeapi/config/getThemeConfig')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收银台主题风格列表
|
||||
*/
|
||||
export function getThemeList() {
|
||||
return request.post('/cashier/storeapi/cashier/getThemeList')
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置收银台会员搜索方式配置
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function setMemberSearchWayConfig(params) {
|
||||
return request.post('/cashier/storeapi/config/setMemberSearchWayConfig', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收银台会员搜索方式配置
|
||||
*/
|
||||
export function getMemberSearchWayConfig() {
|
||||
return request.post('/cashier/storeapi/config/getMemberSearchWayConfig')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收银台订单消息推送-配置
|
||||
*/
|
||||
export function getOrderRemind() {
|
||||
return request.post('/cashier/storeapi/config/orderRemind')
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台消息推送-绑定门店
|
||||
*/
|
||||
export function pushBind(params) {
|
||||
return request.post('/cashier/storeapi/push/bind',{data:params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台消息推送-更换绑定门店
|
||||
*/
|
||||
export function pushChangeBind(params) {
|
||||
return request.post('/cashier/storeapi/push/changebind',{data:params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 收银台消息推送-下线
|
||||
*/
|
||||
export function pushOffline() {
|
||||
return request.post('/cashier/storeapi/push/offline',{data:params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收银台订单消息推送-服务状态
|
||||
*/
|
||||
export function getPushStatus() {
|
||||
return request.post('/cashier/storeapi/push/status')
|
||||
}
|
||||
41
addon/cashier/source/os/api/deliver.js
Executable file
41
addon/cashier/source/os/api/deliver.js
Executable file
@@ -0,0 +1,41 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取配送员列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getDeliverList(params) {
|
||||
return request.post('/cashier/storeapi/store/deliverlists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配送员详情
|
||||
* @param {Object} deliver_id
|
||||
*/
|
||||
export function getDeliverInfo(deliver_id) {
|
||||
return request.post('/cashier/storeapi/store/deliverinfo', {data: {deliver_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加配送员
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function addDeliver(params) {
|
||||
return request.post('/cashier/storeapi/store/adddeliver', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑配送员
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editDeliver(params) {
|
||||
return request.post('/cashier/storeapi/store/editdeliver', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除配送员
|
||||
* @param {Object} deliver_id
|
||||
*/
|
||||
export function deleteDeliver(deliver_id) {
|
||||
return request.post('/cashier/storeapi/store/deletedeliver', {data: {deliver_id}})
|
||||
}
|
||||
124
addon/cashier/source/os/api/goods.js
Executable file
124
addon/cashier/source/os/api/goods.js
Executable file
@@ -0,0 +1,124 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 商品列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getGoodsList(params) {
|
||||
return request.post('/cashier/storeapi/goods/page', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品详情
|
||||
* @param {Object} goods_id
|
||||
*/
|
||||
export function getGoodsDetail(goods_id) {
|
||||
return request.post('/cashier/storeapi/goods/detail', {data: {goods_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑商品
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editGoods(params) {
|
||||
return request.post('/cashier/storeapi/goods/editgoods', {data: params})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 编辑商品
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function setGoodsLocalRestrictions(params) {
|
||||
return request.post('/cashier/storeapi/goods/setGoodsLocalRestrictions', {data: params})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过扫码事件查询会员信息
|
||||
* @param {Object} sku_no
|
||||
*/
|
||||
export function getGoodsInfoByCode(sku_no) {
|
||||
return request.post('/cashier/storeapi/goods/skuinfo', {data: {sku_no}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置商品状态
|
||||
* @param {Object} params
|
||||
*{ goods_id: arr.toString(), status: status}
|
||||
*/
|
||||
export function setGoodsStatus(params) {
|
||||
return request.post('/cashier/storeapi/goods/setstatus', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品分类
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getGoodsCategory(params) {
|
||||
return request.post('/cashier/storeapi/goods/category', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品分类[库存]
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getManageGoodsCategory(params = {}) {
|
||||
return request.post('/stock/storeapi/manage/getGoodsCategory', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目分类
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getServiceCategory(params) {
|
||||
return request.post('/cashier/storeapi/service/category', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getServiceList(params) {
|
||||
return request.post('/cashier/storeapi/service/page', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品项目多规格规格数据
|
||||
* @param {Object} goods_id
|
||||
*/
|
||||
export function getGoodsSkuList(goods_id) {
|
||||
return request.post('/cashier/storeapi/goods/skulist', {data: {goods_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取电子秤信息
|
||||
*/
|
||||
export function getElectronicScaleInformation() {
|
||||
return request.post('/scale/storeapi/scale/cashierscale')
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品搜索条件
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getGoodsSceen(params = {}) {
|
||||
return request.post('/cashier/storeapi/goods/screen', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 规格选择
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getSkuListBySelect(params = {}) {
|
||||
return request.post('/cashier/storeapi/goods/getSkuListBySelect', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出打印价格标签数据
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function exportPrintPriceTagData(params = {}) {
|
||||
return request.post('/cashier/storeapi/goods/exportPrintPriceTagData', {data: params})
|
||||
}
|
||||
|
||||
26
addon/cashier/source/os/api/login.js
Executable file
26
addon/cashier/source/os/api/login.js
Executable file
@@ -0,0 +1,26 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取验证码
|
||||
* @param captcha_id
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getCaptcha(captcha_id) {
|
||||
return request.post('/storeapi/captcha/captcha', {data: {captcha_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function login(params) {
|
||||
return request.post('/cashier/storeapi/login/login', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function modifyPassword(params) {
|
||||
return request.post('/cashier/storeapi/user/modifypassword', {data: params})
|
||||
}
|
||||
48
addon/cashier/source/os/api/marketing.js
Executable file
48
addon/cashier/source/os/api/marketing.js
Executable file
@@ -0,0 +1,48 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/************************************优惠券*******************************/
|
||||
/**
|
||||
* 优惠券详情
|
||||
* @param {Object} coupon_type_id
|
||||
*/
|
||||
export function getCouponDetail(coupon_type_id) {
|
||||
return request.post('/coupon/storeapi/coupon/detail', {data: {coupon_type_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 优惠券详情领取记录
|
||||
* @param {Object} coupon_type_id
|
||||
*/
|
||||
export function getReceiveCouponPageList(coupon_type_id) {
|
||||
return request.post('/coupon/storeapi/membercoupon/getReceiveCouponPageList', {data: {coupon_type_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增优惠券
|
||||
*/
|
||||
export function addCoupon(params) {
|
||||
return request.post('/coupon/storeapi/coupon/add', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑优惠券
|
||||
*/
|
||||
export function editCoupon(params) {
|
||||
return request.post('/coupon/storeapi/coupon/edit', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭优惠券
|
||||
* @param {Object} coupon_type_id
|
||||
*/
|
||||
export function closeCoupon(coupon_type_id) {
|
||||
return request.post('/coupon/storeapi/coupon/close', {data: {coupon_type_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除优惠券
|
||||
* @param {Object} coupon_type_id
|
||||
*/
|
||||
export function deleteCoupon(coupon_type_id) {
|
||||
return request.post('/coupon/storeapi/coupon/delete', {data: {coupon_type_id}})
|
||||
}
|
||||
138
addon/cashier/source/os/api/member.js
Executable file
138
addon/cashier/source/os/api/member.js
Executable file
@@ -0,0 +1,138 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取会员信息
|
||||
* @param {Object} member_id
|
||||
*/
|
||||
export function getMemberInfoById(member_id) {
|
||||
return request.post('/cashier/storeapi/member/info', {data: {member_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员信息(通过search_text)
|
||||
* @param params
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getMemberInfoBySearchMember(params) {
|
||||
return request.post('/cashier/storeapi/member/searchmember', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getMemberList(params) {
|
||||
return request.post('/cashier/storeapi/member/lists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员等级
|
||||
*/
|
||||
export function getMemberLevelList() {
|
||||
return request.post('/cashier/storeapi/memberlevel/lists')
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加会员
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function addMember(params) {
|
||||
return request.post('/cashier/storeapi/member/addmember', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑会员
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editMember(params) {
|
||||
return request.post('/cashier/storeapi/member/editmember', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员卡包列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getMemberCardList(params) {
|
||||
return request.post('/cardservice/storeapi/membercard/lists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员卡包详情
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getMemberCardDetail(params) {
|
||||
return request.post('/cardservice/storeapi/membercard/detail', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可发放优惠券列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getCouponTypeList(params) {
|
||||
return request.post('/coupon/storeapi/coupon/getStoreCouponTypeList', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 发放优惠券
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function sendMemberCoupon(params) {
|
||||
return request.post('/cashier/storeapi/member/sendCoupon', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整会员积分
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function modifyMemberPoint(params) {
|
||||
return request.post('/cashier/storeapi/member/modifypoint', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整会员余额
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function modifyMemberBalance(params) {
|
||||
return request.post('/cashier/storeapi/member/modifybalance', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整会员成长值
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function modifyMemberGrowth(params) {
|
||||
return request.post('/cashier/storeapi/member/modifygrowth', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 办理会员卡
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function applyingMembershipCard(params) {
|
||||
return request.post('/cashier/storeapi/member/handleMember', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
* @param {Object} member_id
|
||||
*/
|
||||
export function sendMemberVerifyCode(member_id) {
|
||||
return request.post('/cashier/storeapi/member/memberverifycode', {data: {member_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证短信验证码
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function checkMemberVerifyCode(params) {
|
||||
return request.post('/cashier/storeapi/member/checksmscode', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据手机号查询会员,支持模糊
|
||||
* @param params
|
||||
* @returns {*}
|
||||
*/
|
||||
export function searchMemberByMobile(params) {
|
||||
return request.post('/cashier/storeapi/member/searchMemberByMobile', {data: params})
|
||||
}
|
||||
55
addon/cashier/source/os/api/oder_pay.js
Executable file
55
addon/cashier/source/os/api/oder_pay.js
Executable file
@@ -0,0 +1,55 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 支付确认
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function cashierConfirm(params) {
|
||||
return request.post('/cashier/storeapi/cashierpay/confirm', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建支付单
|
||||
* @param {Object} out_trade_no
|
||||
*/
|
||||
export function addPayCashierPay(out_trade_no) {
|
||||
return request.post('/cashier/storeapi/cashierpay/createpay', {data: {out_trade_no}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付二维码
|
||||
* @param {Object} out_trade_no
|
||||
*/
|
||||
export function getPayQrcode(out_trade_no) {
|
||||
return request.post('/cashier/storeapi/cashierpay/payqrcode', {data: {out_trade_no}})
|
||||
}
|
||||
/**
|
||||
* 获取扫码枪配置
|
||||
* */
|
||||
export function getPayType() {
|
||||
return request.post('/cashier/storeapi/Cashierpay/payType')
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫码枪支付
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function authCodepay(params) {
|
||||
return request.post('/pay/pay/authCodepay', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付信息
|
||||
* @param {Object} out_trade_no
|
||||
*/
|
||||
export function getCashierPayInfo(out_trade_no) {
|
||||
return request.post('/cashier/storeapi/cashierpay/info', {data: {out_trade_no}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 账号余额支付确认
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function checkPaymentCode(params) {
|
||||
return request.post('/cashier/storeapi/member/checkpaymentcode', {data: params})
|
||||
}
|
||||
129
addon/cashier/source/os/api/order.js
Executable file
129
addon/cashier/source/os/api/order.js
Executable file
@@ -0,0 +1,129 @@
|
||||
import request from '@/common/js/http'
|
||||
import util from '@/common/js/util'
|
||||
|
||||
/**
|
||||
* 订单列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getOrderList(params) {
|
||||
return request.post('/cashier/storeapi/cashierorder/lists', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单详情
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getOrderDetail(params) {
|
||||
return request.post('/cashier/storeapi/cashierorder/detail', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支付信息
|
||||
* @param {Object} order_id
|
||||
*/
|
||||
export function getOrderInfoById(order_id) {
|
||||
return request.post('/cashier/storeapi/order/info', {
|
||||
data: {order_id}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单调价
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderAdjustPrice(params) {
|
||||
return request.post('/cashier/storeapi/cashierorder/adjustPrice', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单备注
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderRemark(params) {
|
||||
return request.post('/cashier/storeapi/cashierorder/orderRemark', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 提货
|
||||
* @param {Object} order_id
|
||||
*/
|
||||
export function orderStoreDelivery(order_id) {
|
||||
return request.post('/cashier/storeapi/order/storedelivery', {
|
||||
data: {order_id}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地配送
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderLocalDelivery(params) {
|
||||
return request.post('/cashier/storeapi/order/localdelivery', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单关闭
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderClose(params) {
|
||||
return request.post('/cashier/storeapi/order/close', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印小票
|
||||
* @param order_id
|
||||
* @returns {*}
|
||||
*/
|
||||
export function orderPrintTicket(order_id) {
|
||||
let params = {order_id:order_id};
|
||||
//追加打印机数据
|
||||
let local_config = util.getLocalConfig();
|
||||
params.printer_ids = local_config.printerSelectType == 'all' ? 'all' : local_config.printerSelectIds.toString();
|
||||
return request.post('/cashier/storeapi/cashierorder/printticket', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取物流公司
|
||||
*/
|
||||
export function getExpressCompanyList() {
|
||||
return request.post('/cashier/storeapi/order/expresscompany')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配送员列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getOrderDeliverList(params) {
|
||||
return request.post('/cashier/storeapi/order/deliverlist', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单删除
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderExpressDelivery(params) {
|
||||
return request.post('/cashier/storeapi/order/expressdelivery', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取筛选条件
|
||||
*/
|
||||
export function getorderCondition() {
|
||||
return request.post('/cashier/storeapi/order/condition')
|
||||
}
|
||||
41
addon/cashier/source/os/api/order_create.js
Executable file
41
addon/cashier/source/os/api/order_create.js
Executable file
@@ -0,0 +1,41 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 开单(计算)
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function calculate(params) {
|
||||
return request.post('/cashier/storeapi/cashierordercreate/calculate', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 开单(订单创建)
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function create(params) {
|
||||
return request.post('/cashier/storeapi/cashierordercreate/create', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 售卡(计算)
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function cardCalculate(params) {
|
||||
return request.post('/cashier/storeapi/cashierordercreate/cardcalculate', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 售卡(订单创建)
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function cardCreate(params) {
|
||||
return request.post('/cashier/storeapi/cashierordercreate/cardcreate', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付(计算)
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function payCalculate(params) {
|
||||
return request.post('/cashier/storeapi/cashierpay/paycalculate', {data: params})
|
||||
}
|
||||
89
addon/cashier/source/os/api/order_refund.js
Executable file
89
addon/cashier/source/os/api/order_refund.js
Executable file
@@ -0,0 +1,89 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 订单退款申请数据
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getRefundApplyData(params) {
|
||||
return request.post('/cashier/storeapi/cashierorderrefund/getrefundapplydata', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单退款
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderRefund(params) {
|
||||
return request.post('/cashier/storeapi/cashierorderrefund/refund', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 转账
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderRefundComplete(params) {
|
||||
return request.post('/cashier/storeapi/cashierorderrefund/complete', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getOrderRefundLists(params) {
|
||||
return request.post('/cashier/storeapi/cashierorderrefund/lists', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单详情
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getOrderRefundDetail(params) {
|
||||
return request.post('/cashier/storeapi/cashierorderrefund/detail', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意维权
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderRefundAgree(params) {
|
||||
return request.post('/cashier/storeapi/cashierorderrefund/agree', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拒绝维权
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderRefundRefuse(params) {
|
||||
return request.post('/cashier/storeapi/cashierorderrefund/refuse', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 买家退货接收,维权收货
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderRefundReceive(params) {
|
||||
return request.post('/cashier/storeapi/cashierorderrefund/receive', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭维权
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function orderRefundClose(params) {
|
||||
return request.post('/cashier/storeapi/cashierorderrefund/close', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
41
addon/cashier/source/os/api/pendorder.js
Executable file
41
addon/cashier/source/os/api/pendorder.js
Executable file
@@ -0,0 +1,41 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 挂单
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function addPendOrder(params) {
|
||||
return request.post('/cashier/storeapi/pendorder/add', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 取单
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editPendOrder(params) {
|
||||
return request.post('/cashier/storeapi/pendorder/edit', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改备注
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editPendOrderRemark(params) {
|
||||
return request.post('/cashier/storeapi/pendorder/updateremark', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取挂单
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getPendOrderList(params) {
|
||||
return request.post('/cashier/storeapi/pendorder/page', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除挂单
|
||||
* @param {Object} order_id
|
||||
*/
|
||||
export function deletePendOrder(order_id) {
|
||||
return request.post('/cashier/storeapi/pendorder/delete', {data: {order_id}})
|
||||
}
|
||||
61
addon/cashier/source/os/api/printer.js
Executable file
61
addon/cashier/source/os/api/printer.js
Executable file
@@ -0,0 +1,61 @@
|
||||
import request from '@/common/js/http'
|
||||
import util from '@/common/js/util'
|
||||
|
||||
/**
|
||||
* 获取打印机列表
|
||||
*/
|
||||
export function getPrinterList(params) {
|
||||
return request.post('/printer/storeapi/printer/lists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取打印机模板
|
||||
*/
|
||||
export function getTemplate() {
|
||||
return request.post('/printer/storeapi/printer/template')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取打印机详情
|
||||
*/
|
||||
export function getPrinterInfo(printer_id) {
|
||||
return request.post('/printer/storeapi/printer/info', {data: {printer_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除打印机
|
||||
*/
|
||||
export function deletePrinter(printer_id) {
|
||||
return request.post('/printer/storeapi/printer/deleteprinter', {data: {printer_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单类型
|
||||
*/
|
||||
export function getOrderType() {
|
||||
return request.post('/printer/storeapi/printer/getordertype')
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑打印机
|
||||
*/
|
||||
export function editPrinter(params) {
|
||||
return request.post('/printer/storeapi/printer/edit', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加打印机
|
||||
*/
|
||||
export function addPrinter(params) {
|
||||
return request.post('/printer/storeapi/printer/add', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印小票
|
||||
*/
|
||||
export function printTicket(params = {}) {
|
||||
//追加打印机数据
|
||||
let local_config = util.getLocalConfig();
|
||||
params.printer_ids = local_config.printerSelectType == 'all' ? 'all' : local_config.printerSelectIds.toString();
|
||||
return request.post('/cashier/storeapi/cashier/printticket', {data: params})
|
||||
}
|
||||
15
addon/cashier/source/os/api/promotion.js
Executable file
15
addon/cashier/source/os/api/promotion.js
Executable file
@@ -0,0 +1,15 @@
|
||||
import request from '@/common/js/http'
|
||||
/**
|
||||
* 获取推广二维码设置
|
||||
*/
|
||||
export function getAddonIsExist() {
|
||||
return request.post('/cashier/storeapi/Config/addonIsExist')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取推广二维码
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getPromotionQrcode(params) {
|
||||
return request.post('/cashier/storeapi/Promotion/getPromotionQrcode', {data: params})
|
||||
}
|
||||
35
addon/cashier/source/os/api/recharge.js
Executable file
35
addon/cashier/source/os/api/recharge.js
Executable file
@@ -0,0 +1,35 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取订单列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getOrderRechargeList(params) {
|
||||
return request.post('/cashier/storeapi/recharge/orderpage', {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单详情
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getOrderRechargeDetail(params) {
|
||||
return request.post('/cashier/storeapi/recharge/orderdetail', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取充值基本配置
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getRechargeConfig(params) {
|
||||
return request.post('/cashier/storeapi/recharge/activity', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户充值
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function addRecharge(params) {
|
||||
return request.post('/cashier/storeapi/cashierordercreate/rechargecreate', {data: params})
|
||||
}
|
||||
112
addon/cashier/source/os/api/reserve.js
Executable file
112
addon/cashier/source/os/api/reserve.js
Executable file
@@ -0,0 +1,112 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取预约配置
|
||||
*/
|
||||
export function getReserveConfig() {
|
||||
return request.post('/cardservice/storeapi/reserve/getConfig')
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存预约配置
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function setReserveConfig(params) {
|
||||
return request.post('/cardservice/storeapi/reserve/setConfig', {data: params})
|
||||
}
|
||||
|
||||
/********************** 预约 ***********************/
|
||||
|
||||
/**
|
||||
* 获取预约状态字典
|
||||
*/
|
||||
export function getReserveStatus() {
|
||||
return request.post('/cardservice/storeapi/reserve/status')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取预约记录(每周)
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getReserveWeekday(params) {
|
||||
return request.post('/cardservice/storeapi/reserve/getweekday', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取预约分页数据
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getReserveLists(params) {
|
||||
return request.post('/cardservice/storeapi/reserve/lists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取预约项目列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getAppointmentProjectList(params) {
|
||||
return request.post('/cardservice/storeapi/reserve/servicelist', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取员工列表
|
||||
*/
|
||||
export function getEmployeeList() {
|
||||
return request.post('/cardservice/storeapi/reserve/servicer')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取预约详情
|
||||
* @param reserve_id
|
||||
*/
|
||||
export function getReserveDetail(reserve_id) {
|
||||
return request.post('/cardservice/storeapi/reserve/detail', {data: {reserve_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加预约
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function addReserve(params) {
|
||||
return request.post('/cardservice/storeapi/reserve/add', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑预约
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editReserve(params) {
|
||||
return request.post('/cardservice/storeapi/reserve/update', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消预约
|
||||
* @param reserve_id
|
||||
*/
|
||||
export function cancelReserve(reserve_id) {
|
||||
return request.post('/cardservice/storeapi/reserve/cancel', {data: reserve_id})
|
||||
}
|
||||
|
||||
/**
|
||||
* 预约到店确认
|
||||
* @param reserve_id
|
||||
*/
|
||||
export function reserveToStore(reserve_id) {
|
||||
return request.post('/cardservice/storeapi/reserve/confirmToStore', {data: {reserve_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 预约确认
|
||||
* @param reserve_id
|
||||
*/
|
||||
export function reserveConfirm(reserve_id) {
|
||||
return request.post('/cardservice/storeapi/reserve/confirm', {data: {reserve_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 预约完成
|
||||
* @param reserve_id
|
||||
*/
|
||||
export function reserveComplete(reserve_id) {
|
||||
return request.post('/cardservice/storeapi/reserve/complete', {data: {reserve_id}})
|
||||
}
|
||||
43
addon/cashier/source/os/api/scale.js
Executable file
43
addon/cashier/source/os/api/scale.js
Executable file
@@ -0,0 +1,43 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取电子秤列表
|
||||
*/
|
||||
export function getScaleList(params) {
|
||||
return request.post('/scale/storeapi/scale/page', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取电子秤详情
|
||||
*/
|
||||
export function getScaleDetail(params) {
|
||||
return request.post('/scale/storeapi/scale/detail', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除电子秤
|
||||
*/
|
||||
export function deleteScale(params) {
|
||||
return request.post('/scale/storeapi/scale/delete', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取电子秤品牌
|
||||
*/
|
||||
export function getScaleBrand() {
|
||||
return request.post('/scale/storeapi/scale/scaleBrand')
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑电子秤
|
||||
*/
|
||||
export function editScale(params) {
|
||||
return request.post('/scale/storeapi/scale/edit', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加电子秤
|
||||
*/
|
||||
export function addScale(params) {
|
||||
return request.post('/scale/storeapi/scale/add', {data: params})
|
||||
}
|
||||
67
addon/cashier/source/os/api/settlement.js
Executable file
67
addon/cashier/source/os/api/settlement.js
Executable file
@@ -0,0 +1,67 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取提现设置
|
||||
*/
|
||||
export function getWithdrawConfig() {
|
||||
return request.post('/store/storeapi/store/withdrawconfig')
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请提现
|
||||
* @param {Object} money
|
||||
*/
|
||||
export function applyWithdraw(money) {
|
||||
return request.post('/store/storeapi/withdraw/apply', {data: {money}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 提现详情
|
||||
* @param {Object} withdraw_id
|
||||
*/
|
||||
export function withdrawDetail(withdraw_id) {
|
||||
return request.post('/store/storeapi/withdraw/detail', {data: {withdraw_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提现方式
|
||||
*/
|
||||
export function getWithdrawScreen() {
|
||||
return request.post('/store/storeapi/withdraw/screen')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提现列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getWithdrawPage(params) {
|
||||
return request.post('/store/storeapi/withdraw/page', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 账户筛选条件
|
||||
*/
|
||||
export function getAccountScreen() {
|
||||
return request.post('/store/storeapi/account/screen')
|
||||
}
|
||||
|
||||
/**
|
||||
* 账户导出
|
||||
*/
|
||||
export function accountExport(params) {
|
||||
return request.post('/store/storeapi/account/export', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否可以新版本提现
|
||||
*/
|
||||
export function withdrawConfig() {
|
||||
return request.post('/wechatpay/api/transfer/getWithdrawConfig')
|
||||
}
|
||||
|
||||
/**
|
||||
* 提现二维码
|
||||
*/
|
||||
export function transferCode(params) {
|
||||
return request.post('/store/storeapi/withdraw/getTransferCode', {data: params})
|
||||
}
|
||||
22
addon/cashier/source/os/api/shifts.js
Executable file
22
addon/cashier/source/os/api/shifts.js
Executable file
@@ -0,0 +1,22 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 收银交班
|
||||
*/
|
||||
export function changeShifts(params = {}) {
|
||||
return request.post('/cashier/storeapi/cashier/changeshifts', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 数量统计
|
||||
*/
|
||||
export function getShiftsData() {
|
||||
return request.post('/cashier/storeapi/cashier/shiftsdata')
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出交班记录
|
||||
*/
|
||||
export function saleGoodsExport(params) {
|
||||
return request.post('/cashier/storeapi/cashier/changeShiftsSaleGoodsExport', {data: params})
|
||||
}
|
||||
29
addon/cashier/source/os/api/stat.js
Executable file
29
addon/cashier/source/os/api/stat.js
Executable file
@@ -0,0 +1,29 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 营业数据统计相关
|
||||
*/
|
||||
|
||||
/**
|
||||
* 获取整体统计
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getStatTotal(params) {
|
||||
return request.post('/cashier/storeapi/stat/statTotal', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当日统计
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getStatDay(params) {
|
||||
return request.post('/cashier/storeapi/stat/dayStatData', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当日统计
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getStatHour(params) {
|
||||
return request.post('/cashier/storeapi/stat/hourStatData', {data: params})
|
||||
}
|
||||
292
addon/cashier/source/os/api/stock.js
Executable file
292
addon/cashier/source/os/api/stock.js
Executable file
@@ -0,0 +1,292 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取库存商品列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getStockGoodsList(params) {
|
||||
return request.post('/stock/storeapi/manage/lists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品的库存流水
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getStockGoodsRecords(params) {
|
||||
return request.post('/stock/storeapi/manage/records', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单据类型
|
||||
*/
|
||||
export function getDocumentType() {
|
||||
return request.post('/stock/storeapi/manage/getDocumentType')
|
||||
}
|
||||
|
||||
/************************** 库存通用接口 ********************************/
|
||||
|
||||
/**
|
||||
* 出入库单据审核通过
|
||||
* @param document_id
|
||||
*/
|
||||
export function storageAgree(document_id) {
|
||||
return request.post('/stock/storeapi/storage/agree', {data: {document_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库单据审核拒绝
|
||||
* @param {Object} params 需要包括拒绝理由
|
||||
*/
|
||||
export function storageRefuse(params) {
|
||||
return request.post('/stock/storeapi/storage/refuse', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 出入库单据删除
|
||||
* @param {Object} document_id
|
||||
*/
|
||||
export function storageDelete(document_id) {
|
||||
return request.post('/stock/storeapi/storage/delete', {data: {document_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 库存回车查询单条商品
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getSkuListForStock(params) {
|
||||
return request.post('/stock/storeapi/manage/getskulist', {data: params})
|
||||
}
|
||||
|
||||
/************************** 入库接口 ********************************/
|
||||
/**
|
||||
* 获取入库单列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getStorageLists(params) {
|
||||
return request.post('/stock/storeapi/storage/lists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取入库单详情
|
||||
* @param document_id
|
||||
*/
|
||||
export function getStorageDetail(document_id) {
|
||||
return request.post('/stock/storeapi/storage/detail', {data: {document_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取入库单号
|
||||
*/
|
||||
export function getStorageDocumentNo() {
|
||||
return request.post('/stock/storeapi/storage/getDocumentNo')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取入库单编辑时详情
|
||||
* @param document_id
|
||||
*/
|
||||
export function getStorageDetailInEdit(document_id) {
|
||||
return request.post('/stock/storeapi/storage/editData', {data: {document_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库单编辑新增
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editStorage(params) {
|
||||
return request.post('/stock/storeapi/storage/stockin', {data: params})
|
||||
}
|
||||
|
||||
/************************** 出库接口 ********************************/
|
||||
|
||||
/**
|
||||
* 获取出库单列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getWastageLists(params) {
|
||||
return request.post('/stock/storeapi/wastage/lists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取出库单详情
|
||||
* @param document_id
|
||||
*/
|
||||
export function getWastageDetail(document_id) {
|
||||
return request.post('/stock/storeapi/wastage/detail', {data: {document_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取出库单号
|
||||
*/
|
||||
export function getWastageDocumentNo() {
|
||||
return request.post('/stock/storeapi/wastage/getDocumentNo')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取出库单编辑时详情
|
||||
* @param document_id
|
||||
*/
|
||||
export function getWastageDetailInEdit(document_id) {
|
||||
return request.post('/stock/storeapi/wastage/editData', {data: {document_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 出库单编辑新增
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editWastage(params) {
|
||||
return request.post('/stock/storeapi/wastage/stockout', {data: params})
|
||||
}
|
||||
|
||||
/************************** 调拨接口 ********************************/
|
||||
|
||||
/**
|
||||
* 获取调拨单列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getAllocateList(params) {
|
||||
return request.post('/stock/storeapi/allocate/lists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取调拨单详情
|
||||
* @param {Object} allot_id
|
||||
*/
|
||||
export function getAllocateDetail(allot_id) {
|
||||
return request.post('/stock/storeapi/allocate/detail', {data: {allot_id: allot_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取调拨单号
|
||||
*/
|
||||
export function getAllotNo() {
|
||||
return request.post('/stock/storeapi/allocate/getAllotNo')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取调拨单编辑时详情
|
||||
* @param allot_id
|
||||
*/
|
||||
export function getAllocateDetailInEdit(allot_id) {
|
||||
return request.post('/stock/storeapi/allocate/editData', {data: {allot_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取调拨门店列表(库存查询门店)
|
||||
*/
|
||||
export function getStoreLists() {
|
||||
return request.post('/stock/storeapi/store/lists')
|
||||
}
|
||||
|
||||
/**
|
||||
* 调拨单新增
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function addAllocate(params) {
|
||||
return request.post('/stock/storeapi/allocate/addallocate', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调拨单编辑
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editAllocate(params) {
|
||||
return request.post('/stock/storeapi/allocate/editAllocate', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调拨单据删除
|
||||
* @param {Object} allot_id
|
||||
*/
|
||||
export function allocateDelete(allot_id) {
|
||||
return request.post('/stock/storeapi/allocate/delete', {data: {allot_id: allot_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调拨单据审核通过
|
||||
* @param {Object} allot_id
|
||||
*/
|
||||
export function allocateAgree(allot_id) {
|
||||
return request.post('/stock/storeapi/allocate/agree', {data: {allot_id: allot_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 调拨单据审核拒绝
|
||||
* @param {Object} params 需要包括拒绝理由
|
||||
*/
|
||||
export function allocateRefuse(params) {
|
||||
return request.post('/stock/storeapi/allocate/refuse', {data: params})
|
||||
}
|
||||
|
||||
/************************** 库存盘点接口 ********************************/
|
||||
|
||||
/**
|
||||
* 获取盘点单列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getInventoryList(params) {
|
||||
return request.post('/stock/storeapi/check/lists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取盘点单详情
|
||||
* @param {Object} inventory_id
|
||||
*/
|
||||
export function getInventoryDetail(inventory_id) {
|
||||
return request.post('/stock/storeapi/check/detail', {data: {inventory_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取盘点单号
|
||||
*/
|
||||
export function getInventoryNo() {
|
||||
return request.post('/stock/storeapi/Check/getInventoryNo')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取盘点单编辑时详情
|
||||
* @param inventory_id
|
||||
*/
|
||||
export function getInventoryDetailInEdit(inventory_id) {
|
||||
return request.post('/stock/storeapi/check/editData', {data: {inventory_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 盘点单新增
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function addInventory(params) {
|
||||
return request.post('/stock/storeapi/check/add', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 盘点单编辑
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editInventory(params) {
|
||||
return request.post('/stock/storeapi/check/edit', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 盘点单据删除
|
||||
* @param {Object} inventory_id
|
||||
*/
|
||||
export function inventoryDelete(inventory_id) {
|
||||
return request.post('stock/storeapi/check/delete', {data: {inventory_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 盘点单据审核通过
|
||||
* @param {Object} inventory_id
|
||||
*/
|
||||
export function inventoryAgree(inventory_id) {
|
||||
return request.post('/stock/storeapi/check/agree', {data: {inventory_id}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 盘点单据审核拒绝
|
||||
* @param {Object} params 需要包括拒绝理由
|
||||
*/
|
||||
export function inventoryRefuse(params) {
|
||||
return request.post('/stock/storeapi/check/refuse', {data: params})
|
||||
}
|
||||
37
addon/cashier/source/os/api/store.js
Executable file
37
addon/cashier/source/os/api/store.js
Executable file
@@ -0,0 +1,37 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取门店信息(当前)
|
||||
*/
|
||||
export function getStoreInfo() {
|
||||
return request.post('/cashier/storeapi/store/info')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取门店列表(当前用户有权限的)
|
||||
*/
|
||||
export function getStoreList() {
|
||||
return request.post('/cashier/storeapi/store/lists')
|
||||
}
|
||||
|
||||
/**
|
||||
* 门店编辑
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editStore(params) {
|
||||
return request.post('/store/storeapi/store/edit', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有门店标签
|
||||
*/
|
||||
export function getAllStoreLabel() {
|
||||
return request.post('/store/storeapi/store/label')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有的门店分类
|
||||
*/
|
||||
export function getAllStoreCategory() {
|
||||
return request.post('/store/storeapi/store/category')
|
||||
}
|
||||
57
addon/cashier/source/os/api/user.js
Executable file
57
addon/cashier/source/os/api/user.js
Executable file
@@ -0,0 +1,57 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取员工列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getUserList(params) {
|
||||
return request.post('/cashier/storeapi/user/lists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取员工详情
|
||||
* @param {Object} uid
|
||||
*/
|
||||
export function getUserDetail(uid) {
|
||||
var params = {};
|
||||
if (uid) params.uid = uid;
|
||||
return request.post('/cashier/storeapi/user/userinfo', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有用户组(角色)
|
||||
*/
|
||||
export function getAllGroups() {
|
||||
return request.post('/cashier/storeapi/user/group')
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加员工
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function addUser(params) {
|
||||
return request.post('/cashier/storeapi/user/adduser', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑员工
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function editUser(params) {
|
||||
return request.post('/cashier/storeapi/user/edituser', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除员工
|
||||
* @param {Object} uid
|
||||
*/
|
||||
export function deleteUser(uid) {
|
||||
return request.post('/cashier/storeapi/user/deleteuser', {data: {uid}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取门店用户权限
|
||||
*/
|
||||
export function getUserGroupAuth() {
|
||||
return request.post('/cashier/storeapi/user/usergroupauth')
|
||||
}
|
||||
33
addon/cashier/source/os/api/verify.js
Executable file
33
addon/cashier/source/os/api/verify.js
Executable file
@@ -0,0 +1,33 @@
|
||||
import request from '@/common/js/http'
|
||||
|
||||
/**
|
||||
* 获取核销码信息
|
||||
* @param {Object} code
|
||||
*/
|
||||
export function getVerifyInfo(code) {
|
||||
return request.post('/cashier/storeapi/verify/info', {data: {code: code}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销操作
|
||||
* @param {Object} code
|
||||
*/
|
||||
export function verifyCode(code) {
|
||||
return request.post('/cashier/storeapi/verify/verify', {data: {verify_code: code}})
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销记录列表
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function getVerifyRecordList(params) {
|
||||
return request.post('/cashier/storeapi/verify/recordlists', {data: params})
|
||||
}
|
||||
|
||||
/**
|
||||
* 核销记录列表
|
||||
* @param {Object} id
|
||||
*/
|
||||
export function getVerifyRecordDetail(id) {
|
||||
return request.post('/cashier/storeapi/verify/recordsdetail', {data: {id: id}})
|
||||
}
|
||||
751
addon/cashier/source/os/common/css/common.scss
Executable file
751
addon/cashier/source/os/common/css/common.scss
Executable file
@@ -0,0 +1,751 @@
|
||||
// 基础flex布局
|
||||
.uni-flex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.uni-flex-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.uni-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.uni-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
.justify-start {
|
||||
-webkit-box-pack: start;
|
||||
-ms-flex-pack: start;
|
||||
-webkit-justify-content: flex-start;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.justify-center{
|
||||
justify-content: center;
|
||||
}
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.text-color {
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
.items-end {
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.items-baseline {
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.items-flex-end {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.flex-shrink-0 {
|
||||
-ms-flex-negative: 0;
|
||||
-webkit-flex-shrink: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.flex-grow-0 {
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex-positive: 0;
|
||||
-webkit-flex-grow: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.self-end {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.justify-self-auto {
|
||||
-ms-grid-column-align: auto;
|
||||
justify-self: auto;
|
||||
}
|
||||
|
||||
.flex-col {
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.content-start {
|
||||
-ms-flex-line-pack: start;
|
||||
-webkit-align-content: flex-start;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.justify-end {
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
-webkit-justify-content: flex-end;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
// 高度填充
|
||||
.height-all {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
// 公共区块样式
|
||||
.common-wrap {
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
// margin: .15rem .2rem;
|
||||
|
||||
// &:first-child {
|
||||
// margin-right: 0;
|
||||
// }
|
||||
|
||||
// &:last-child {
|
||||
// margin-right: .14rem;
|
||||
// }
|
||||
}
|
||||
|
||||
// 公共滚动条样式
|
||||
.common-scrollbar,
|
||||
.common-scrollbar .uni-scroll-view {
|
||||
&::-webkit-scrollbar {
|
||||
width: 0.06rem;
|
||||
height: 0.06rem;
|
||||
background-color: rgba($color: #000000, $alpha: 0);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 0.06rem;
|
||||
box-shadow: inset 0 0 0.06rem rgba(45, 43, 43, 0.45);
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
// 公共头像样式
|
||||
.common-headimg {
|
||||
overflow: hidden;
|
||||
border-radius: 50%;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// 公共tab切换
|
||||
.common-tab-wrap {
|
||||
height: 0.53rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
display: flex;
|
||||
padding: 0 0.2rem;
|
||||
position: relative;
|
||||
|
||||
.tab-item {
|
||||
height: 0.53rem;
|
||||
line-height: 0.53rem;
|
||||
padding: 0 0.2rem;
|
||||
cursor: pointer;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
&.active-bar {
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0.03rem;
|
||||
border-radius: 0.02rem;
|
||||
background: $primary-color;
|
||||
bottom: -0.01rem;
|
||||
left: 0;
|
||||
transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 公共表格操作样式
|
||||
.common-table-action {
|
||||
text {
|
||||
margin-left: 0.1rem;
|
||||
color: $primary-color;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-color-light-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 公共表格批量操作样式
|
||||
.common-table-batch {
|
||||
display: flex;
|
||||
|
||||
button {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0.02rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::after {
|
||||
border-radius: 0.02rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
// 主要按钮
|
||||
.primary-btn {
|
||||
background: $primary-color !important;
|
||||
color: #fff !important;
|
||||
font-size: 0.14rem;
|
||||
|
||||
&::after {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--primary-color-light-2) !important;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
background: var(--primary-color-light-6) !important;
|
||||
border-color: var(--primary-color-light-6) !important;
|
||||
color: #fff !important;
|
||||
|
||||
&:hover {
|
||||
background: var(--primary-color-light-6) !important;
|
||||
border-color: var(--primary-color-light-6) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 默认按钮
|
||||
.default-btn {
|
||||
font-size: 0.14rem;
|
||||
background: #fff !important;
|
||||
color: #606266 !important;
|
||||
border-color: #606266 !important;
|
||||
|
||||
&:hover {
|
||||
color: $primary-color !important;
|
||||
border-color: $primary-color !important;
|
||||
}
|
||||
|
||||
&:hover:after {
|
||||
border-color: $primary-color !important;
|
||||
}
|
||||
|
||||
&[plain] {
|
||||
color: $primary-color !important;
|
||||
border-color: $primary-color !important;
|
||||
background-color: var(--primary-color-light-9) !important;
|
||||
|
||||
&:after {
|
||||
border-color: $primary-color !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $primary-color !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
color: #ddd !important;
|
||||
border-color: #e6e6e6 !important;
|
||||
background: #f5f5f5 !important;
|
||||
|
||||
&:after {
|
||||
border-color: #e6e6e6 !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #ddd !important;
|
||||
border-color: #e6e6e6 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
color: #ddd !important;
|
||||
border-color: #e6e6e6 !important;
|
||||
background: #f5f5f5 !important;
|
||||
|
||||
&:after {
|
||||
border-color: #e6e6e6 !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: #ddd !important;
|
||||
border-color: #e6e6e6 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 公共数字键盘 */
|
||||
.keyboard-wrap {
|
||||
width: 5rem;
|
||||
margin-top: 0.2rem;
|
||||
display: flex;
|
||||
|
||||
.num-wrap {
|
||||
flex: 1;
|
||||
width: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
|
||||
.key-item {
|
||||
margin: 0.1rem 0.1rem 0 0;
|
||||
background: #f5f5f5;
|
||||
min-width: calc((100% - 0.3rem) / 3);
|
||||
text-align: center;
|
||||
padding: 0.15rem 0;
|
||||
border-radius: 0.05rem;
|
||||
font-size: 0.16rem;
|
||||
font-weight: bold;
|
||||
transition: all 0.3s;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
&.empty:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 1rem;
|
||||
|
||||
.delete,
|
||||
.confirm {
|
||||
background: #f5f5f5;
|
||||
min-width: calc((100% - 0.3rem) / 3);
|
||||
text-align: center;
|
||||
padding: 0.15rem 0;
|
||||
margin-top: 0.1rem;
|
||||
border-radius: 0.05rem;
|
||||
font-size: 0.16rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.confirm {
|
||||
flex: 1;
|
||||
background: $primary-color;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
background: var(--primary-color-light-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
/* 单行超出隐藏 */
|
||||
.using-hidden {
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
white-space: break-spaces;
|
||||
}
|
||||
|
||||
/* 多行超出隐藏 */
|
||||
.multi-hidden {
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.h-full {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.overflow-ellipsis {
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.truncate {
|
||||
overflow: hidden;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
button::after {
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button[type=default] {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.border-0 {
|
||||
border-width: 0 !important;
|
||||
}
|
||||
|
||||
uni-switch .uni-switch-input.uni-switch-input-checked {
|
||||
background-color: $primary-color;
|
||||
border-color: $primary-color;
|
||||
}
|
||||
|
||||
//二次确认弹框
|
||||
.confirm-pop {
|
||||
width: 3rem;
|
||||
// min-height: 1.5rem;
|
||||
border-radius: 0.06rem;
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
padding: 0.2rem;
|
||||
|
||||
.title {
|
||||
font-size: 0.16rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 0.3rem;
|
||||
|
||||
.btn {
|
||||
width: auto;
|
||||
padding: 0 0.15rem;
|
||||
margin: 0;
|
||||
height: 0.35rem;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.btn:last-child {
|
||||
margin-left: 0.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.message {
|
||||
width: 5.2rem;
|
||||
min-height: 3.2rem;
|
||||
background: #ffffff;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0.15rem;
|
||||
|
||||
&:after {
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
content: '';
|
||||
height: 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
height: 0.5rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
text-align: center;
|
||||
line-height: 0.5rem;
|
||||
font-size: 0.16rem;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
|
||||
.iconguanbi1 {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
right: 0.15rem;
|
||||
font-size: 0.18rem;
|
||||
}
|
||||
}
|
||||
|
||||
.textarea-box {
|
||||
margin: 0.15rem;
|
||||
height: 2.2rem;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
border-radius: 0.06rem;
|
||||
padding: 0.15rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
.textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.save {
|
||||
width: calc(100% - 0.3rem);
|
||||
float: right;
|
||||
margin: 0.15rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//开单左侧主体头部会员信息展示样式
|
||||
.cashregister-header-box {
|
||||
padding: 0.20rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
padding-bottom: 0.1rem;
|
||||
|
||||
.search-box {
|
||||
.head-search {
|
||||
display: flex;
|
||||
|
||||
.search-switch {
|
||||
width: 0.7rem;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
margin-left: 0.1rem;
|
||||
display: flex;
|
||||
border-width: 0.01rem;
|
||||
border-style: solid;
|
||||
border-color: #e6e6e6;
|
||||
height: 0.3rem;
|
||||
align-items: center;
|
||||
padding-left: 0.05rem;
|
||||
width: calc(100% - 1.3rem);
|
||||
|
||||
.iconfont {
|
||||
}
|
||||
|
||||
input {
|
||||
margin-left: 0.05rem;
|
||||
}
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
width: 0.55rem;
|
||||
margin-left: 0.1rem;
|
||||
padding: 0 0.1rem;
|
||||
height: 0.32rem;
|
||||
font-size: 0.12rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.order-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
user-select: none;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
height: 0.3rem;
|
||||
padding: 0 0.1rem 0 0.1rem;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0.02rem;
|
||||
border: 0.01rem solid #e5e5e5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 0.14rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.uni-date {
|
||||
flex: 1;
|
||||
margin-left: 0.1rem;
|
||||
}
|
||||
.uni-date-x {
|
||||
height: 0.28rem;
|
||||
}
|
||||
}
|
||||
.header {
|
||||
margin-top: 0.14rem;
|
||||
// height: 0.86rem;
|
||||
font-size: 0.2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.14rem;
|
||||
padding-right: 0.12rem;
|
||||
background: linear-gradient(270deg, #515A6E 0%, #19233E 100%);
|
||||
border-radius: 0.04rem;
|
||||
|
||||
.header-image {
|
||||
width: 0.48rem;
|
||||
height: 0.48rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.headimg{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.member-nameplate{
|
||||
width: 0.52rem;
|
||||
height: 0.18rem;
|
||||
background-size: 100% 100%;
|
||||
font-size: 0.1rem;
|
||||
font-weight: 600;
|
||||
color: #793913;
|
||||
line-height: 0.16rem;
|
||||
text-align: center;
|
||||
margin-top: -0.09rem;
|
||||
z-index: 2;
|
||||
background-image: url('@/static/member/info_bg.png');
|
||||
}
|
||||
}
|
||||
.head-info {
|
||||
flex: 1;
|
||||
margin-left: 0.1rem;
|
||||
|
||||
.name {
|
||||
font-size: 0.16rem;
|
||||
color: #F4C89A;
|
||||
display: flex;
|
||||
margin-bottom: 0.04rem;
|
||||
max-width: 1.6rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
.mobile {
|
||||
width: 0.88rem;
|
||||
height: 0.2rem;
|
||||
font-size: 0.14rem;
|
||||
font-weight: 800;
|
||||
line-height: 0.2rem;
|
||||
}
|
||||
|
||||
.text {
|
||||
// max-width: 0.8rem;
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.nickname{
|
||||
max-width: 0.44rem;
|
||||
font-size: 0.12rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
line-height: 0.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.head-info-bottom {
|
||||
font-size: 0.12rem;
|
||||
font-weight: 500;
|
||||
color: #F0F0F0;
|
||||
line-height: 0.17rem;
|
||||
&.point{
|
||||
margin-bottom: 0.02rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.switch {
|
||||
text-align: center;
|
||||
line-height: 0.3rem;
|
||||
padding: 0 0.05rem;
|
||||
overflow: hidden;
|
||||
font-size: $uni-font-size-sm;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
-ms-flex-negative: 0;
|
||||
-webkit-flex-shrink: 0;
|
||||
flex-shrink: 0;
|
||||
border-radius: 0.04rem;
|
||||
&::after{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.menber-open{
|
||||
width: 0.68rem;
|
||||
}
|
||||
.replace-member{
|
||||
margin-left: 0.06rem;
|
||||
width: 0.36rem;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//返回上一级
|
||||
.title-back{
|
||||
margin-bottom: 0.2rem;
|
||||
.left{
|
||||
margin-left: 0.05rem;
|
||||
}
|
||||
.iconqianhou1{
|
||||
font-size: 0.17rem;
|
||||
}
|
||||
text{
|
||||
font-size: 0.18rem !important;
|
||||
line-height: 1;
|
||||
}
|
||||
.content{
|
||||
margin: -0.02rem 0.05rem 0 0.05rem;
|
||||
}
|
||||
}
|
||||
|
||||
.bg-primary-color-9{
|
||||
background-color: var(--primary-color-light-9) !important;
|
||||
}
|
||||
140
addon/cashier/source/os/common/css/form.scss
Executable file
140
addon/cashier/source/os/common/css/form.scss
Executable file
@@ -0,0 +1,140 @@
|
||||
$label-width: 1.1rem;
|
||||
|
||||
.common-form{
|
||||
&.fixd{
|
||||
padding-bottom: .88rem !important;
|
||||
.common-btn-wrap{
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
background-color: #fff;
|
||||
bottom: 0;
|
||||
left: .9rem;
|
||||
right: .07rem;
|
||||
padding-bottom: .05rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 0;
|
||||
button{
|
||||
flex: 1;
|
||||
height: .4rem;
|
||||
line-height: .4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.common-form-item{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
margin-bottom: .15rem;
|
||||
.form-label{
|
||||
padding: .09rem .15rem;
|
||||
text-align: right;
|
||||
width: $label-width;
|
||||
box-sizing: border-box;
|
||||
.required{
|
||||
color: red;
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
}
|
||||
.form-input{
|
||||
height: .35rem;
|
||||
line-height: .35rem;
|
||||
width: 100%;
|
||||
padding-left: .1rem;
|
||||
box-sizing: border-box;
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
.form-inline{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.form-input-inline{
|
||||
width: 1.9rem;
|
||||
border: .01rem solid #e6e6e6;
|
||||
margin-right: 10px;
|
||||
background-color: #fff;
|
||||
font-size: 0.14rem;
|
||||
&.short{
|
||||
width: .5rem;
|
||||
}
|
||||
&.long{
|
||||
width: 4rem;
|
||||
}
|
||||
}
|
||||
.form-input-block{
|
||||
flex: 1;
|
||||
border: .01rem solid #e6e6e6;
|
||||
background-color: #fff;
|
||||
}
|
||||
.form-mid{
|
||||
margin-right: .1rem;
|
||||
}
|
||||
.form-word-aux{
|
||||
margin-right: .1rem;
|
||||
color: #999;
|
||||
font-size: $uni-font-size-base;
|
||||
}
|
||||
.form-word-aux-line{
|
||||
flex-basis: 100%;
|
||||
color: #999;
|
||||
margin-left: $label-width;
|
||||
margin-top: .1rem;
|
||||
}
|
||||
/deep/ .input-placeholder{
|
||||
font-size: $uni-font-size-base;
|
||||
}
|
||||
.form-checkbox-group, .form-radio-group{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.form-checkbox-item, .form-radio-item{
|
||||
margin-right: 26rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
/deep/ .uni-radio-input, .uni-checkbox-input{
|
||||
width: .18rem;
|
||||
height: .18rem;
|
||||
}
|
||||
}
|
||||
.common-btn-wrap{
|
||||
margin-left: $label-width;
|
||||
button{
|
||||
display: inline-block;
|
||||
padding: 0 .2rem;
|
||||
|
||||
height: .36rem;
|
||||
line-height: .36rem;
|
||||
font-size: $uni-font-size-base;
|
||||
}
|
||||
.screen-btn{
|
||||
background-color: $primary-color;
|
||||
color: #fff;
|
||||
margin-right: .1rem;
|
||||
&::after{
|
||||
border-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.uni-radio-wrapper{
|
||||
.uni-radio-input-checked{
|
||||
background-color: $primary-color!important;
|
||||
border-color: $primary-color!important;
|
||||
}
|
||||
.uni-radio-input:hover{
|
||||
border-color: $primary-color!important;
|
||||
}
|
||||
}
|
||||
.uni-checkbox-wrapper{
|
||||
.uni-checkbox-input-checked{
|
||||
color: $primary-color!important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (any-hover: hover) {
|
||||
uni-radio:not([disabled]) .uni-radio-input:hover {
|
||||
border-color: $primary-color !important;
|
||||
}
|
||||
}
|
||||
474
addon/cashier/source/os/common/css/iconfont.css
Executable file
474
addon/cashier/source/os/common/css/iconfont.css
Executable file
@@ -0,0 +1,474 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 3668609 */
|
||||
src: url('//at.alicdn.com/t/c/font_3668609_3k15vrcn5ip.woff2?t=1731148726122') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_3668609_3k15vrcn5ip.woff?t=1731148726122') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_3668609_3k15vrcn5ip.ttf?t=1731148726122') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconshoukuan-:before {
|
||||
content: "\e645";
|
||||
}
|
||||
|
||||
.icondianzicheng:before {
|
||||
content: "\edaf";
|
||||
}
|
||||
|
||||
.iconbenji:before {
|
||||
content: "\e77a";
|
||||
}
|
||||
|
||||
.iconshengyinV6xx1:before {
|
||||
content: "\e70a";
|
||||
}
|
||||
|
||||
.iconshengyin-jingyinV6xx:before {
|
||||
content: "\e6ff";
|
||||
}
|
||||
|
||||
.iconwenhao:before {
|
||||
content: "\e72d";
|
||||
}
|
||||
|
||||
.iconhuaxiangfenxi:before {
|
||||
content: "\ec14";
|
||||
}
|
||||
|
||||
.iconmenpos:before {
|
||||
content: "\e652";
|
||||
}
|
||||
|
||||
.iconhuiyuanzhucedengluguanli:before {
|
||||
content: "\e609";
|
||||
}
|
||||
|
||||
.iconsaomiaoerweima:before {
|
||||
content: "\e663";
|
||||
}
|
||||
|
||||
.icon31hongbao:before {
|
||||
content: "\e605";
|
||||
}
|
||||
|
||||
.iconshanchu:before {
|
||||
content: "\e718";
|
||||
}
|
||||
|
||||
.icontuodong:before {
|
||||
content: "\e884";
|
||||
}
|
||||
|
||||
.iconhuiyuanma:before {
|
||||
content: "\e68d";
|
||||
}
|
||||
|
||||
.icona-xingzhuang2:before {
|
||||
content: "\e679";
|
||||
}
|
||||
|
||||
.iconmima:before {
|
||||
content: "\e67a";
|
||||
}
|
||||
|
||||
.iconyanzhengma:before {
|
||||
content: "\e67b";
|
||||
}
|
||||
|
||||
.icondelete:before {
|
||||
content: "\e615";
|
||||
}
|
||||
|
||||
.iconzhanghuyue:before {
|
||||
content: "\e60e";
|
||||
}
|
||||
|
||||
.iconshourujiesuan:before {
|
||||
content: "\e655";
|
||||
}
|
||||
|
||||
.iconqingchushujuku:before {
|
||||
content: "\e632";
|
||||
}
|
||||
|
||||
.iconpeisong:before {
|
||||
content: "\e626";
|
||||
}
|
||||
|
||||
.iconyunshangchuan:before {
|
||||
content: "\e604";
|
||||
}
|
||||
|
||||
.iconnavicon-chps:before {
|
||||
content: "\e64d";
|
||||
}
|
||||
|
||||
.iconyuyue:before {
|
||||
content: "\e65f";
|
||||
}
|
||||
|
||||
.icontianmaopeisonganzhuang:before {
|
||||
content: "\e603";
|
||||
}
|
||||
|
||||
.iconyunshupeisong:before {
|
||||
content: "\e621";
|
||||
}
|
||||
|
||||
.icontiaobodan:before {
|
||||
content: "\e670";
|
||||
}
|
||||
|
||||
.iconchukudan:before {
|
||||
content: "\e671";
|
||||
}
|
||||
|
||||
.iconrukudan:before {
|
||||
content: "\e674";
|
||||
}
|
||||
|
||||
.iconyuyuedingdan:before {
|
||||
content: "\e8a2";
|
||||
}
|
||||
|
||||
.iconkucunguanli:before {
|
||||
content: "\e613";
|
||||
}
|
||||
|
||||
.iconkucunpandian:before {
|
||||
content: "\e675";
|
||||
}
|
||||
|
||||
.icondayin:before {
|
||||
content: "\e61d";
|
||||
}
|
||||
|
||||
.icongongyingshang:before {
|
||||
content: "\e61f";
|
||||
}
|
||||
|
||||
.icondingdandingdanchaxun:before {
|
||||
content: "\e791";
|
||||
}
|
||||
|
||||
.icondingdan:before {
|
||||
content: "\e62f";
|
||||
}
|
||||
|
||||
.icon12jiaobanbiao:before {
|
||||
content: "\e6b1";
|
||||
}
|
||||
|
||||
.iconhexiao:before {
|
||||
content: "\e606";
|
||||
}
|
||||
|
||||
.iconqia:before {
|
||||
content: "\e782";
|
||||
}
|
||||
|
||||
.iconicon_yingyongguanli:before {
|
||||
content: "\eb8f";
|
||||
}
|
||||
|
||||
.iconyuyueguanli:before {
|
||||
content: "\e62c";
|
||||
}
|
||||
|
||||
.iconkaidan:before {
|
||||
content: "\e61b";
|
||||
}
|
||||
|
||||
.iconinvisible:before {
|
||||
content: "\e9af";
|
||||
}
|
||||
|
||||
.iconyanjing5:before {
|
||||
content: "\e728";
|
||||
}
|
||||
|
||||
.icondianpu:before {
|
||||
content: "\e66e";
|
||||
}
|
||||
|
||||
.iconxiala:before {
|
||||
content: "\e6b9";
|
||||
}
|
||||
|
||||
.iconfanhui:before {
|
||||
content: "\e64a";
|
||||
}
|
||||
|
||||
.iconfuxuankuang1:before {
|
||||
content: "\e68e";
|
||||
}
|
||||
|
||||
.iconfuxuankuang2:before {
|
||||
content: "\e68f";
|
||||
}
|
||||
|
||||
.iconcheckbox_weiquanxuan:before {
|
||||
content: "\e650";
|
||||
}
|
||||
|
||||
.iconwushuju:before {
|
||||
content: "\e642";
|
||||
}
|
||||
|
||||
.iconqianhou1:before {
|
||||
content: "\e640";
|
||||
}
|
||||
|
||||
.iconqianhou2:before {
|
||||
content: "\e641";
|
||||
}
|
||||
|
||||
.iconguanbi:before {
|
||||
content: "\e600";
|
||||
}
|
||||
|
||||
.iconright-s:before {
|
||||
content: "\e627";
|
||||
}
|
||||
|
||||
.iconleft-s:before {
|
||||
content: "\e628";
|
||||
}
|
||||
|
||||
.icongengduo:before {
|
||||
content: "\e63c";
|
||||
}
|
||||
|
||||
.icon31sousuo:before {
|
||||
content: "\e601";
|
||||
}
|
||||
|
||||
.iconguanbi1:before {
|
||||
content: "\e723";
|
||||
}
|
||||
|
||||
.iconsanjiao_xia:before {
|
||||
content: "\e63d";
|
||||
}
|
||||
|
||||
.iconjifen:before {
|
||||
content: "\e659";
|
||||
}
|
||||
|
||||
.iconxianjin:before {
|
||||
content: "\e637";
|
||||
}
|
||||
|
||||
.iconhongbao:before {
|
||||
content: "\e672";
|
||||
}
|
||||
|
||||
.iconchengchangzhi:before {
|
||||
content: "\e633";
|
||||
}
|
||||
|
||||
.iconyouhuiquan1:before {
|
||||
content: "\e6f1";
|
||||
}
|
||||
|
||||
.iconyinhangqia:before {
|
||||
content: "\e936";
|
||||
}
|
||||
|
||||
.iconwxpay:before {
|
||||
content: "\e611";
|
||||
}
|
||||
|
||||
.icontubiao_zhifu_zhifubaozhifu:before {
|
||||
content: "\e690";
|
||||
}
|
||||
|
||||
.iconduigou1:before {
|
||||
content: "\e64f";
|
||||
}
|
||||
|
||||
.iconchenggong:before {
|
||||
content: "\e644";
|
||||
}
|
||||
|
||||
.iconfuwuguanli:before {
|
||||
content: "\e625";
|
||||
}
|
||||
|
||||
.iconliuliangshuju:before {
|
||||
content: "\e62d";
|
||||
}
|
||||
|
||||
.iconkehuguanli:before {
|
||||
content: "\e697";
|
||||
}
|
||||
|
||||
.iconqitajilu:before {
|
||||
content: "\e622";
|
||||
}
|
||||
|
||||
.icondingdanguanli:before {
|
||||
content: "\e634";
|
||||
}
|
||||
|
||||
.iconcaiwubaobiao:before {
|
||||
content: "\e6e7";
|
||||
}
|
||||
|
||||
.iconyingyeshujuguanliputong:before {
|
||||
content: "\e62e";
|
||||
}
|
||||
|
||||
.iconjichuban-sanjidaohang-kehushuju:before {
|
||||
content: "\e649";
|
||||
}
|
||||
|
||||
.icontubiaozhizuomoban-:before {
|
||||
content: "\e60c";
|
||||
}
|
||||
|
||||
.iconbangzhu:before {
|
||||
content: "\e61c";
|
||||
}
|
||||
|
||||
.iconweb-icon-:before {
|
||||
content: "\e6d6";
|
||||
}
|
||||
|
||||
.icon065chakandingdan:before {
|
||||
content: "\e643";
|
||||
}
|
||||
|
||||
.icongengduo1:before {
|
||||
content: "\e73a";
|
||||
}
|
||||
|
||||
.iconsaoyisaosaoma:before {
|
||||
content: "\e751";
|
||||
}
|
||||
|
||||
.iconjia:before {
|
||||
content: "\e8e1";
|
||||
}
|
||||
|
||||
.iconfuwudingdan:before {
|
||||
content: "\e616";
|
||||
}
|
||||
|
||||
.iconchongzhidingdan:before {
|
||||
content: "\e64b";
|
||||
}
|
||||
|
||||
.iconhuiyuandingdan:before {
|
||||
content: "\e602";
|
||||
}
|
||||
|
||||
.iconshangpinguanli:before {
|
||||
content: "\e619";
|
||||
}
|
||||
|
||||
.iconshoukadingdan:before {
|
||||
content: "\e623";
|
||||
}
|
||||
|
||||
.iconshouyindingdanjine:before {
|
||||
content: "\e739";
|
||||
}
|
||||
|
||||
.iconyundanguanli:before {
|
||||
content: "\e6cc";
|
||||
}
|
||||
|
||||
.icongoumaicika:before {
|
||||
content: "\e673";
|
||||
}
|
||||
|
||||
.iconjishi:before {
|
||||
content: "\e935";
|
||||
}
|
||||
|
||||
.icontuichu:before {
|
||||
content: "\e66f";
|
||||
}
|
||||
|
||||
.icondizhi:before {
|
||||
content: "\e614";
|
||||
}
|
||||
|
||||
.iconshijian:before {
|
||||
content: "\e629";
|
||||
}
|
||||
|
||||
.iconjian:before {
|
||||
content: "\e620";
|
||||
}
|
||||
|
||||
.iconweixinzhifu:before {
|
||||
content: "\e635";
|
||||
}
|
||||
|
||||
.iconjifen1:before {
|
||||
content: "\e65e";
|
||||
}
|
||||
|
||||
.iconzhifubaozhifu:before {
|
||||
content: "\e651";
|
||||
}
|
||||
|
||||
.iconyouhui-:before {
|
||||
content: "\e607";
|
||||
}
|
||||
|
||||
.iconyouhuiquan:before {
|
||||
content: "\e7d8";
|
||||
}
|
||||
|
||||
.iconhongbao1:before {
|
||||
content: "\e662";
|
||||
}
|
||||
|
||||
.iconyue:before {
|
||||
content: "\e6b7";
|
||||
}
|
||||
|
||||
.iconduihao:before {
|
||||
content: "\e654";
|
||||
}
|
||||
|
||||
.iconsaomaqiang:before {
|
||||
content: "\e631";
|
||||
}
|
||||
|
||||
.iconjianmianjine:before {
|
||||
content: "\e6ab";
|
||||
}
|
||||
|
||||
.iconxuanzhong:before {
|
||||
content: "\e7df";
|
||||
}
|
||||
|
||||
.iconxianjin1:before {
|
||||
content: "\e62a";
|
||||
}
|
||||
|
||||
.iconyuan_checkbox:before {
|
||||
content: "\e72f";
|
||||
}
|
||||
|
||||
.iconyuan_checked:before {
|
||||
content: "\e733";
|
||||
}
|
||||
|
||||
.iconzengpin:before {
|
||||
content: "\e693";
|
||||
}
|
||||
|
||||
.icontuikuanjilu:before {
|
||||
content: "\e73b";
|
||||
}
|
||||
20
addon/cashier/source/os/common/js/config.js
Executable file
20
addon/cashier/source/os/common/js/config.js
Executable file
@@ -0,0 +1,20 @@
|
||||
var app = {
|
||||
appkey: 'cashier',
|
||||
version: '5.5.3',
|
||||
version_no: '553250709001',
|
||||
}
|
||||
|
||||
var config = {
|
||||
// 站点ID
|
||||
siteId: 0,
|
||||
// api请求地址 https://abc.com
|
||||
baseUrl: '{{$baseUrl}}',
|
||||
// 图片域名 https://abc.com
|
||||
imgDomain: '{{$imgDomain}}',
|
||||
//长链接 wss://abc.com/wss
|
||||
webSocket: '{{$webSocket}}',
|
||||
// app版本信息
|
||||
app: app,
|
||||
}
|
||||
|
||||
export default config;
|
||||
110
addon/cashier/source/os/common/js/http.js
Executable file
110
addon/cashier/source/os/common/js/http.js
Executable file
@@ -0,0 +1,110 @@
|
||||
import Config from './config.js'
|
||||
import Util from './util.js'
|
||||
|
||||
const app_type = 'pc';
|
||||
const app_type_name = 'PC';
|
||||
|
||||
export default {
|
||||
sendRequest(params) {
|
||||
var method = params.method ?? 'POST', // 请求方式
|
||||
url = Config.baseUrl + params.url, // 请求路径
|
||||
data = {
|
||||
app_type,
|
||||
app_type_name
|
||||
};
|
||||
|
||||
if (uni.getStorageSync('cashierToken')) data.token = uni.getStorageSync('cashierToken');
|
||||
|
||||
if (uni.getStorageSync('siteId')) data.site_id = uni.getStorageSync('siteId');
|
||||
|
||||
if (uni.getStorageSync('globalStoreId')) data.store_id = uni.getStorageSync('globalStoreId');
|
||||
|
||||
if (params.data != undefined) Object.assign(data, params.data);
|
||||
|
||||
if (params.async === false) {
|
||||
//同步
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: url,
|
||||
method: method,
|
||||
data: data,
|
||||
header: params.header || {
|
||||
'content-type': 'application/x-www-form-urlencoded;application/json'
|
||||
},
|
||||
dataType: params.dataType || 'json',
|
||||
responseType: params.responseType || 'json',
|
||||
success: (res) => {
|
||||
if (res.data.code == -10009 || res.data.code == -10010) {
|
||||
uni.removeStorage({
|
||||
key: 'cashierToken'
|
||||
});
|
||||
if (Util.getCurrRoute() != 'pages/login/login') {
|
||||
Util.redirectTo('/pages/login/login', {}, 'reLaunch');
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolve(res.data);
|
||||
},
|
||||
fail: (res) => {
|
||||
reject(res);
|
||||
},
|
||||
complete: (res) => {
|
||||
// reject(res);
|
||||
}
|
||||
});
|
||||
})
|
||||
} else {
|
||||
//异步
|
||||
uni.request({
|
||||
url: url,
|
||||
method: method,
|
||||
data: data,
|
||||
header: params.header || {
|
||||
'content-type': 'application/x-www-form-urlencoded;application/json'
|
||||
},
|
||||
dataType: params.dataType || 'json',
|
||||
responseType: params.responseType || 'text',
|
||||
success: (res) => {
|
||||
if (res.data.code == -10009 || res.data.code == -10010) {
|
||||
uni.removeStorage({
|
||||
key: 'cashierToken'
|
||||
});
|
||||
if (Util.getCurrRoute() != 'pages/login/login') {
|
||||
Util.redirectTo('/pages/login/login', {}, 'reLaunch');
|
||||
return;
|
||||
}
|
||||
}
|
||||
typeof params.success == 'function' && params.success(res.data);
|
||||
},
|
||||
fail: (res) => {
|
||||
typeof params.fail == 'function' && params.fail(res);
|
||||
},
|
||||
complete: (res) => {
|
||||
typeof params.complete == 'function' && params.complete(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
post(url, params) {
|
||||
const option = {
|
||||
url,
|
||||
method: 'post',
|
||||
async: false
|
||||
};
|
||||
return this.sendRequest({
|
||||
...params,
|
||||
...option
|
||||
});
|
||||
},
|
||||
get(url, params) {
|
||||
const option = {
|
||||
url,
|
||||
method: 'get',
|
||||
async: false
|
||||
};
|
||||
return this.sendRequest({
|
||||
...params,
|
||||
...option
|
||||
});
|
||||
}
|
||||
}
|
||||
150
addon/cashier/source/os/common/js/mixin.js
Executable file
150
addon/cashier/source/os/common/js/mixin.js
Executable file
@@ -0,0 +1,150 @@
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 左侧菜单,支持触发的按键集合
|
||||
menuKeyCode: ['F6', 'F7', 'F8', 'F9', 'F10', 'F11'],
|
||||
themeColor: ''
|
||||
};
|
||||
},
|
||||
onShow() {
|
||||
|
||||
this.setNavigationBarTitleText();
|
||||
|
||||
// 监听键盘回调
|
||||
window.POS_HOTKEY_CALLBACK = (control, code) => {
|
||||
this.$store.commit('billing/setIsShowCashBox',true);
|
||||
// 触发左侧菜单按键回调
|
||||
this.menuTriggerKeyCodeCallBack(code);
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
cashierToken() {
|
||||
return uni.getStorageSync('cashierToken');
|
||||
},
|
||||
...mapGetters([
|
||||
'rootSize', 'defaultImg', 'addon', 'menu', 'userInfo', 'themeConfig',
|
||||
'globalStoreId', 'globalStoreInfo', 'globalMemberId', 'globalMemberInfo'
|
||||
])
|
||||
},
|
||||
watch: {
|
||||
'globalStoreInfo.store_id': {
|
||||
handler(nval, oval) {
|
||||
if (oval && typeof this.switchStoreAfter == 'function') {
|
||||
this.switchStoreAfter();
|
||||
this.setNavigationBarTitleText();
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
themeConfig:{
|
||||
handler(nval,oval){
|
||||
if(nval && oval && oval.color && nval.color != oval.color) {
|
||||
this.loadThemeColor();
|
||||
}
|
||||
},
|
||||
deep:true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 设置页面标题
|
||||
*/
|
||||
setNavigationBarTitleText() {
|
||||
let pages = getCurrentPages();
|
||||
let currentPage = pages[pages.length - 1];
|
||||
if (currentPage && currentPage.$holder && currentPage.$holder.navigationBarTitleText) {
|
||||
let title = currentPage.$holder.navigationBarTitleText;
|
||||
if (this.globalStoreInfo) title += '-' + this.globalStoreInfo.store_name;
|
||||
if (title != currentPage.$holder.navigationBarTitleText) uni.setNavigationBarTitle({
|
||||
title: title
|
||||
})
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.setNavigationBarTitleText();
|
||||
}, 800)
|
||||
}
|
||||
},
|
||||
// 触发左侧菜单按键回调
|
||||
menuTriggerKeyCodeCallBack(code) {
|
||||
if (this.menuKeyCode.indexOf(code) != -1) {
|
||||
let data = null;
|
||||
for (let i = 0; i < this.menu.length; i++) {
|
||||
let item = this.menu[i];
|
||||
if (item.keyCode == code) {
|
||||
data = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
|
||||
// #ifdef H5
|
||||
if (data.path == this.$route.path) return;
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
if (data.path == '/' + this.$mp.page.route) return;
|
||||
// #endif
|
||||
|
||||
this.$util.redirectTo(data.path, data.query ?? {});
|
||||
}
|
||||
}
|
||||
},
|
||||
themeColorSet() {
|
||||
let theme = this.themeConfig;
|
||||
this.themeColor = `--primary-color:${theme.color};`;
|
||||
for (let i = 9; i >= 1; i--) {
|
||||
let color = this.$util.colourBlend(theme.color, '#ffffff', (i / 10));
|
||||
this.themeColor += `--primary-color-light-${i}:${color};`;
|
||||
}
|
||||
},
|
||||
loadThemeColor(){
|
||||
let time = setInterval(() => {
|
||||
let theme = this.themeConfig;
|
||||
if (theme && theme.color) {
|
||||
this.themeColorSet();
|
||||
clearInterval(time);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
/**
|
||||
* 金额格式化
|
||||
* @param {Object} money
|
||||
*/
|
||||
moneyFormat(money) {
|
||||
if (isNaN(money)) return money;
|
||||
return parseFloat(money).toFixed(2);
|
||||
},
|
||||
/**
|
||||
* 时间格式化
|
||||
* @param {Object} time 时间戳
|
||||
* @param {Object} format 输出格式
|
||||
*/
|
||||
timeFormat(time, format = 'Y-m-d H:i:s') {
|
||||
var date = new Date();
|
||||
date.setTime(time * 1000);
|
||||
|
||||
var y = date.getFullYear();
|
||||
var m = date.getMonth() + 1;
|
||||
var d = date.getDate();
|
||||
var h = date.getHours();
|
||||
var i = date.getMinutes();
|
||||
var s = date.getSeconds();
|
||||
|
||||
format = format.replace('Y', y);
|
||||
format = format.replace('m', (m < 10 ? '0' + m : m));
|
||||
format = format.replace('d', (d < 10 ? '0' + d : d));
|
||||
format = format.replace('H', (h < 10 ? '0' + h : h));
|
||||
format = format.replace('i', (i < 10 ? '0' + i : i));
|
||||
format = format.replace('s', (s < 10 ? '0' + s : s));
|
||||
|
||||
return format;
|
||||
},
|
||||
mobileFormat(mobile) {
|
||||
return mobile.substring(0, 4 - 1) + '****' + mobile.substring(6 + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
addon/cashier/source/os/common/js/pos.js
Executable file
14
addon/cashier/source/os/common/js/pos.js
Executable file
@@ -0,0 +1,14 @@
|
||||
// import { ipcRenderer } from 'electron';
|
||||
export default {
|
||||
send(call, param) {
|
||||
if (window.ipcRenderer != undefined) {
|
||||
window.ipcRenderer.send(call, param);
|
||||
}
|
||||
if (window.POS_ != undefined) {
|
||||
window.POS_.send(call, param);
|
||||
}
|
||||
//window.ipcRenderer.send('Print', '渲染进程')
|
||||
//window.ipcRenderer.invoke('Print', '渲染进程')
|
||||
},
|
||||
|
||||
}
|
||||
51
addon/cashier/source/os/common/js/storage.js
Executable file
51
addon/cashier/source/os/common/js/storage.js
Executable file
@@ -0,0 +1,51 @@
|
||||
import Config from './config.js'
|
||||
|
||||
const prefix = Config.baseUrl.replace(/(http:\/\/)|(https:\/\/)/g, '');
|
||||
var oldPrefix = uni.getStorageSync('prefix');
|
||||
|
||||
// 域名不一致,清空
|
||||
if (oldPrefix != prefix) {
|
||||
uni.clearStorageSync();
|
||||
}
|
||||
uni.setStorageSync('prefix', prefix);
|
||||
|
||||
const handleKey = (key) => {
|
||||
const storageKey = (prefix ? `${prefix}_` : '') + key;
|
||||
return storageKey;
|
||||
};
|
||||
|
||||
export function uniStorage() {
|
||||
const setStorageSync = uni.setStorageSync;
|
||||
const setStorage = uni.setStorage;
|
||||
const getStorage = uni.getStorage;
|
||||
const getStorageSync = uni.getStorageSync;
|
||||
const removeStorage = uni.removeStorage;
|
||||
const removeStorageSync = uni.removeStorageSync;
|
||||
|
||||
uni.setStorage = (options) => {
|
||||
options.key = handleKey(options.key);
|
||||
setStorage(options)
|
||||
};
|
||||
|
||||
uni.setStorageSync = (key, data) => {
|
||||
setStorageSync(handleKey(key), data)
|
||||
};
|
||||
|
||||
uni.getStorage = (options) => {
|
||||
options.key = handleKey(options.key);
|
||||
getStorage(options)
|
||||
};
|
||||
|
||||
uni.getStorageSync = (key) => {
|
||||
return getStorageSync(handleKey(key))
|
||||
};
|
||||
|
||||
uni.removeStorage = (options) => {
|
||||
options.key = handleKey(options.key);
|
||||
removeStorage(options)
|
||||
};
|
||||
|
||||
uni.removeStorageSync = (key) => {
|
||||
return removeStorageSync(handleKey(key))
|
||||
}
|
||||
}
|
||||
340
addon/cashier/source/os/common/js/util.js
Executable file
340
addon/cashier/source/os/common/js/util.js
Executable file
@@ -0,0 +1,340 @@
|
||||
import Config from './config.js'
|
||||
import Store from '@/store/index.js'
|
||||
|
||||
export default {
|
||||
/**
|
||||
* 页面跳转
|
||||
* @param {string} to 跳转链接 /pages/idnex/index
|
||||
* @param {Object} param 参数 {key : value, ...}
|
||||
* @param {string} mode 模式
|
||||
*/
|
||||
redirectTo(to, param, mode) {
|
||||
let tabbar = [
|
||||
"/pages/billing/index", // 开单
|
||||
"/pages/reserve/index", // 预约
|
||||
"/pages/buycard/index", // 售卡
|
||||
"/pages/recharge/index", // 充值
|
||||
"/pages/verify/index" // 核销
|
||||
];
|
||||
if (tabbar.indexOf(to) != -1) mode = 'tabbar';
|
||||
|
||||
Store.commit('app/setCurrRoute', to);
|
||||
let url = to;
|
||||
if (param != undefined) {
|
||||
Object.keys(param).forEach(function (key) {
|
||||
if (url.indexOf('?') != -1) {
|
||||
url += "&" + key + "=" + param[key];
|
||||
} else {
|
||||
url += "?" + key + "=" + param[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
switch (mode) {
|
||||
case 'tabbar':
|
||||
// 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。
|
||||
uni.switchTab({
|
||||
url
|
||||
});
|
||||
break;
|
||||
case 'redirectTo':
|
||||
// 关闭当前页面,跳转到应用内的某个页面。
|
||||
uni.redirectTo({
|
||||
url
|
||||
});
|
||||
break;
|
||||
case 'reLaunch':
|
||||
// 关闭所有页面,打开到应用内的某个页面。
|
||||
uni.reLaunch({
|
||||
url
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// 保留当前页面,跳转到应用内的某个页面
|
||||
uni.navigateTo({
|
||||
url
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 图片路径转换
|
||||
* @param {String} img_path 图片地址
|
||||
* @param {Object} params 参数,针对商品、相册里面的图片区分大中小,size: big、mid、small
|
||||
*/
|
||||
img(img_path, params) {
|
||||
var path = "";
|
||||
if (img_path != undefined && img_path != "") {
|
||||
if (img_path.split(',').length > 1) {
|
||||
img_path = img_path.split(',')[0];
|
||||
}
|
||||
if (params && img_path) {
|
||||
// 过滤默认图
|
||||
let arr = img_path.split(".");
|
||||
let suffix = arr[arr.length - 1];
|
||||
arr.pop();
|
||||
arr[arr.length - 1] = arr[arr.length - 1] + "_" + params.size.toUpperCase();
|
||||
arr.push(suffix);
|
||||
img_path = arr.join(".");
|
||||
}
|
||||
if (img_path.indexOf("http://") == -1 && img_path.indexOf("https://") == -1) {
|
||||
path = Config.imgDomain + "/" + img_path;
|
||||
} else {
|
||||
path = img_path;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
},
|
||||
/**
|
||||
* 验证当前数组或对象是否为空
|
||||
* @param param 校验对象
|
||||
*/
|
||||
checkIsNotNull(param) {
|
||||
if (param) {
|
||||
if (typeof (param) == 'object') {
|
||||
if (Array.isArray(param)) {
|
||||
if (param.length > 0) return true
|
||||
} else {
|
||||
if (JSON.stringify(param) != '{}') return true
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
/**
|
||||
* 金额格式化
|
||||
* @param {Object} money
|
||||
*/
|
||||
moneyFormat(money) {
|
||||
if (isNaN(parseFloat(money))) return money;
|
||||
return parseFloat(money).toFixed(2);
|
||||
},
|
||||
/**
|
||||
* 时间格式化
|
||||
* @param {Object} time 时间戳
|
||||
* @param {Object} format 输出格式
|
||||
*/
|
||||
timeFormat(time, format = 'y-m-d h:i:s') {
|
||||
//一律用小写转换
|
||||
format = format.toLowerCase();
|
||||
if(time == 0) return '--';
|
||||
var date = new Date();
|
||||
date.setTime(time * 1000);
|
||||
|
||||
var y = date.getFullYear();
|
||||
var m = date.getMonth() + 1;
|
||||
var d = date.getDate();
|
||||
var h = date.getHours();
|
||||
var i = date.getMinutes();
|
||||
var s = date.getSeconds();
|
||||
|
||||
format = format.replace('y', y);
|
||||
format = format.replace('m', (m < 10 ? '0' + m : m));
|
||||
format = format.replace('d', (d < 10 ? '0' + d : d));
|
||||
format = format.replace('h', (h < 10 ? '0' + h : h));
|
||||
format = format.replace('i', (i < 10 ? '0' + i : i));
|
||||
format = format.replace('s', (s < 10 ? '0' + s : s));
|
||||
|
||||
return format;
|
||||
},
|
||||
/**
|
||||
* 日期格式转时间戳
|
||||
* @param {Object} string
|
||||
*/
|
||||
timeTurnTimeStamp(string) {
|
||||
var f = string.split(' ', 2);
|
||||
var d = (f[0] ? f[0] : '').split('-', 3);
|
||||
var t = (f[1] ? f[1] : '').split(':', 3);
|
||||
return (new Date(
|
||||
parseInt(d[0], 10) || null,
|
||||
(parseInt(d[1], 10) || 1) - 1,
|
||||
parseInt(d[2], 10) || null,
|
||||
parseInt(t[0], 10) || null,
|
||||
parseInt(t[1], 10) || null,
|
||||
parseInt(t[2], 10) || null
|
||||
)).getTime() / 1000;
|
||||
},
|
||||
/**
|
||||
* 获取当前页面路由
|
||||
*/
|
||||
getCurrRoute() {
|
||||
let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
|
||||
return routes.length ? routes[routes.length - 1].route : '';
|
||||
},
|
||||
/**
|
||||
* 显示消息提示框
|
||||
* @param {Object} params 参数
|
||||
*/
|
||||
showToast(params = {}) {
|
||||
params.title = params.title || "";
|
||||
params.icon = params.icon || "none";
|
||||
// params.position = params.position || 'bottom';
|
||||
params.duration = params.duration || 1500;
|
||||
uni.showToast(params);
|
||||
if (params.success) params.success();
|
||||
},
|
||||
/*
|
||||
* 深度拷贝对象
|
||||
* @param {Object} obj
|
||||
*/
|
||||
deepClone(obj) {
|
||||
const isObject = function (obj) {
|
||||
return typeof obj == 'object';
|
||||
}
|
||||
|
||||
if (!isObject(obj)) {
|
||||
throw new Error('obj 不是一个对象!')
|
||||
}
|
||||
//判断传进来的是对象还是数组
|
||||
let isArray = Array.isArray(obj)
|
||||
let cloneObj = isArray ? [] : {}
|
||||
//通过for...in来拷贝
|
||||
for (let key in obj) {
|
||||
cloneObj[key] = isObject(obj[key]) ? this.deepClone(obj[key]) : obj[key]
|
||||
}
|
||||
return cloneObj
|
||||
},
|
||||
/**
|
||||
* 图片选择加上传
|
||||
* @param num
|
||||
* @param params
|
||||
* @param callback
|
||||
* @param url
|
||||
*/
|
||||
upload: function (num, params, callback, url) {
|
||||
const app_type = 'pc';
|
||||
const app_type_name = 'PC';
|
||||
|
||||
var data = {
|
||||
token: uni.getStorageSync('cashierToken'),
|
||||
app_type: app_type,
|
||||
app_type_name: app_type_name
|
||||
}
|
||||
data = Object.assign(data, params);
|
||||
|
||||
var imgs_num = num;
|
||||
var _self = this;
|
||||
|
||||
uni.chooseImage({
|
||||
count: imgs_num,
|
||||
sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有
|
||||
sourceType: ['album', 'camera'], //从相册或者拍照
|
||||
success: async function (res) {
|
||||
const tempFilePaths = res.tempFilePaths;
|
||||
var _data = data;
|
||||
var imgs = [];
|
||||
for (var i = 0; i < tempFilePaths.length; i++) {
|
||||
var path = await _self.upload_file_server(tempFilePaths[i], _data, params.path, url);
|
||||
imgs.push(path);
|
||||
}
|
||||
|
||||
typeof callback == 'function' && callback(imgs);
|
||||
},
|
||||
fail: err => {
|
||||
console.log('图片上传错误', err)
|
||||
}
|
||||
});
|
||||
},
|
||||
//上传
|
||||
upload_file_server(tempFilePath, data, path, url = "") {
|
||||
if (url) {
|
||||
var uploadUrl = Config.baseUrl + url
|
||||
} else {
|
||||
var uploadUrl = Config.baseUrl + '/cashier/storeapi/upload/' + path
|
||||
}
|
||||
data.site_id = uni.getStorageSync('siteId');
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: uploadUrl,
|
||||
filePath: tempFilePath,
|
||||
name: 'file',
|
||||
formData: data,
|
||||
success: function (res) {
|
||||
var path_str = JSON.parse(res.data);
|
||||
if (path_str.code >= 0) {
|
||||
resolve(path_str.data.pic_path);
|
||||
} else {
|
||||
reject("error");
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 验证手机号
|
||||
* @param {string} mobile 被验证的mobile
|
||||
* @return {object} 验证后的结果
|
||||
**/
|
||||
verifyMobile(mobile) {
|
||||
var parse =/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(mobile);
|
||||
return parse;
|
||||
},
|
||||
clearStoreData() {
|
||||
Store.commit('app/setGlobalStoreInfo', null);
|
||||
Store.commit('app/setGlobalStoreId', 0);
|
||||
Store.commit('app/setGlobalMemberInfo', null);
|
||||
Store.commit('app/setUserInfo', null);
|
||||
Store.commit('app/setMenu', []);
|
||||
|
||||
// 开单
|
||||
Store.commit('billing/setGoodsData', {});
|
||||
Store.commit('billing/setPendOrderId',0);
|
||||
Store.commit('billing/setGoodsIds', []);
|
||||
Store.commit('billing/setOrderData', {});
|
||||
Store.commit('billing/setActive', '');
|
||||
Store.commit('billing/setIsScanTrigger', false);
|
||||
|
||||
// 售卡
|
||||
Store.commit('buycard/setGoodsData', {});
|
||||
Store.commit('buycard/setOrderData', {});
|
||||
Store.commit('buycard/setActive', '');
|
||||
|
||||
// 充值
|
||||
Store.commit('recharge/setActive', '');
|
||||
},
|
||||
/**
|
||||
* 颜色减值
|
||||
* @param {Object} c1
|
||||
* @param {Object} c2
|
||||
* @param {Object} ratio
|
||||
*/
|
||||
colourBlend(c1, c2, ratio) {
|
||||
ratio = Math.max(Math.min(Number(ratio), 1), 0)
|
||||
let r1 = parseInt(c1.substring(1, 3), 16)
|
||||
let g1 = parseInt(c1.substring(3, 5), 16)
|
||||
let b1 = parseInt(c1.substring(5, 7), 16)
|
||||
let r2 = parseInt(c2.substring(1, 3), 16)
|
||||
let g2 = parseInt(c2.substring(3, 5), 16)
|
||||
let b2 = parseInt(c2.substring(5, 7), 16)
|
||||
let r = Math.round(r1 * (1 - ratio) + r2 * ratio)
|
||||
let g = Math.round(g1 * (1 - ratio) + g2 * ratio)
|
||||
let b = Math.round(b1 * (1 - ratio) + b2 * ratio)
|
||||
r = ('0' + (r || 0).toString(16)).slice(-2)
|
||||
g = ('0' + (g || 0).toString(16)).slice(-2)
|
||||
b = ('0' + (b || 0).toString(16)).slice(-2)
|
||||
return '#' + r + g + b
|
||||
},
|
||||
//商品类型字典
|
||||
goodsClassDict:{
|
||||
real:1,
|
||||
virtual:2,
|
||||
virtualcard:3,
|
||||
service:4,
|
||||
card:5,
|
||||
weigh:6,
|
||||
},
|
||||
setLocalConfig(obj){
|
||||
var local_config = this.getLocalConfig();
|
||||
local_config = Object.assign(local_config, obj);
|
||||
uni.setStorageSync('local_config', local_config);
|
||||
},
|
||||
getLocalConfig(){
|
||||
var local_config = uni.getStorageSync('local_config');
|
||||
if(!local_config) local_config = {};
|
||||
local_config = Object.assign({
|
||||
printerSelectType:'all',
|
||||
printerSelectIds:[],
|
||||
}, local_config);
|
||||
return local_config;
|
||||
},
|
||||
}
|
||||
173
addon/cashier/source/os/common/js/validate.js
Executable file
173
addon/cashier/source/os/common/js/validate.js
Executable file
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* 数据验证(表单验证)
|
||||
*/
|
||||
module.exports = {
|
||||
error: '',
|
||||
check: function(data, rule) {
|
||||
for (var i = 0; i < rule.length; i++) {
|
||||
if (!rule[i].checkType) {
|
||||
return true;
|
||||
}
|
||||
if (!rule[i].name) {
|
||||
return true;
|
||||
}
|
||||
if (!rule[i].errorMsg) {
|
||||
return true;
|
||||
}
|
||||
if (!data[rule[i].name]) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
switch (rule[i].checkType) {
|
||||
case 'custom':
|
||||
if (typeof rule[i].validate == 'function') {
|
||||
if (!rule[i].validate(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'required':
|
||||
var reg = new RegExp('/[\S]+/');
|
||||
if (reg.test(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
var reg = new RegExp('^.{' + rule[i].checkRule + '}$');
|
||||
if (!reg.test(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'int':
|
||||
var reg = new RegExp('^(-[1-9]|[1-9])[0-9]{' + rule[i].checkRule + '}$');
|
||||
if (!reg.test(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'between':
|
||||
if (!this.isNumber(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
var minMax = rule[i].checkRule.split(',');
|
||||
minMax[0] = Number(minMax[0]);
|
||||
minMax[1] = Number(minMax[1]);
|
||||
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'betweenD':
|
||||
var reg = /^-?[1-9][0-9]?$/;
|
||||
if (!reg.test(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
var minMax = rule[i].checkRule.split(',');
|
||||
minMax[0] = Number(minMax[0]);
|
||||
minMax[1] = Number(minMax[1]);
|
||||
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'betweenF':
|
||||
var reg = /^-?[0-9][0-9]?.+[0-9]+$/;
|
||||
if (!reg.test(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
var minMax = rule[i].checkRule.split(',');
|
||||
minMax[0] = Number(minMax[0]);
|
||||
minMax[1] = Number(minMax[1]);
|
||||
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'same':
|
||||
if (data[rule[i].name] != rule[i].checkRule) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'notsame':
|
||||
if (data[rule[i].name] == rule[i].checkRule) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'email':
|
||||
var reg = /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
|
||||
if (!reg.test(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'phoneno':
|
||||
var reg = /^\d{11}$/;
|
||||
if (!reg.test(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'zipcode':
|
||||
var reg = /^[0-9]{6}$/;
|
||||
if (!reg.test(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'reg':
|
||||
var reg = new RegExp(rule[i].checkRule);
|
||||
if (!reg.test(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'in':
|
||||
if (rule[i].checkRule.indexOf(data[rule[i].name]) == -1) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'notnull':
|
||||
if (data[rule[i].name] == 0 || data[rule[i].name] == undefined || data[rule[i].name] ==
|
||||
null || data[rule[i].name]
|
||||
.length < 1) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'lengthMin':
|
||||
if (data[rule[i].name].length < rule[i].checkRule) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'lengthMax':
|
||||
if (data[rule[i].name].length > rule[i].checkRule) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'numberId':
|
||||
var pattern = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
|
||||
if (!pattern.test(data[rule[i].name])) {
|
||||
this.error = rule[i].errorMsg;
|
||||
return false
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
isNumber: function(checkVal) {
|
||||
var reg = /^-?[1-9][0-9]?.?[0-9]*$/;
|
||||
return reg.test(checkVal);
|
||||
}
|
||||
}
|
||||
243
addon/cashier/source/os/common/menu/store.js
Executable file
243
addon/cashier/source/os/common/menu/store.js
Executable file
@@ -0,0 +1,243 @@
|
||||
export default [{
|
||||
title: '开单',
|
||||
icon: 'iconkaidan',
|
||||
path: '/pages/billing/index',
|
||||
name: 'billing',
|
||||
keyCode: 'F6' // 触发按键
|
||||
},
|
||||
{
|
||||
title: '售卡',
|
||||
icon: 'iconqia',
|
||||
path: '/pages/buycard/index',
|
||||
name: 'buycard',
|
||||
keyCode: 'F7' // 触发按键
|
||||
},
|
||||
{
|
||||
title: '充值',
|
||||
icon: 'iconchongzhidingdan',
|
||||
path: '/pages/recharge/index',
|
||||
name: 'recharge',
|
||||
keyCode: 'F8' // 触发按键
|
||||
},
|
||||
{
|
||||
title: '订单',
|
||||
icon: 'icondingdan',
|
||||
path: '/pages/order/orderlist',
|
||||
name: 'order_list',
|
||||
keyCode: 'F9' // 触发按键
|
||||
},
|
||||
{
|
||||
title: '会员',
|
||||
icon: 'iconkehuguanli',
|
||||
path: '/pages/member/list',
|
||||
name: 'member_list',
|
||||
keyCode: 'F10' // 触发按键
|
||||
},
|
||||
{
|
||||
title: '核销',
|
||||
icon: 'iconhexiao',
|
||||
path: '/pages/verify/index',
|
||||
name: 'verify_index',
|
||||
keyCode: 'F11' // 触发按键
|
||||
},
|
||||
{
|
||||
title: '更多',
|
||||
icon: 'iconicon_yingyongguanli',
|
||||
childshow: true,
|
||||
children: [{
|
||||
title: '收银',
|
||||
children: [{
|
||||
title: '开单',
|
||||
icon: 'iconkaidan',
|
||||
path: '/pages/billing/index',
|
||||
name: 'billing'
|
||||
},
|
||||
{
|
||||
title: '售卡',
|
||||
icon: 'iconqia',
|
||||
path: '/pages/buycard/index',
|
||||
name: 'buycard'
|
||||
},
|
||||
{
|
||||
title: '核销',
|
||||
icon: 'iconhexiao',
|
||||
path: '/pages/verify/index',
|
||||
name: 'verify_index'
|
||||
},
|
||||
{
|
||||
title: '预约',
|
||||
icon: 'iconyuyueguanli',
|
||||
path: '/pages/reserve/index',
|
||||
name: 'reserve_index',
|
||||
addon: 'cardservice'
|
||||
},
|
||||
{
|
||||
title: '充值',
|
||||
icon: 'iconchongzhidingdan',
|
||||
path: '/pages/recharge/index',
|
||||
name: 'recharge'
|
||||
},
|
||||
{
|
||||
title: '交班',
|
||||
icon: 'icon12jiaobanbiao',
|
||||
path: '/pages/index/change_shifts',
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '管理',
|
||||
children: [{
|
||||
title: '商品管理',
|
||||
icon: 'iconshangpinguanli',
|
||||
path: '/pages/goods/goodslist',
|
||||
name: 'goods_list'
|
||||
},
|
||||
{
|
||||
title: '会员管理',
|
||||
icon: 'iconkehuguanli',
|
||||
path: '/pages/member/list',
|
||||
name: 'member_list'
|
||||
},
|
||||
{
|
||||
title: '员工管理',
|
||||
icon: 'iconjishi',
|
||||
path: '/pages/user/list',
|
||||
name: 'user_list'
|
||||
},
|
||||
{
|
||||
title: '订单管理',
|
||||
icon: 'icondingdan',
|
||||
path: '/pages/order/orderlist',
|
||||
name: 'order_list'
|
||||
},
|
||||
{
|
||||
title: '退款维权',
|
||||
icon: 'iconjishi',
|
||||
path: '/pages/order/orderrefund',
|
||||
name: 'order_refund_list'
|
||||
},
|
||||
{
|
||||
title: '交班记录',
|
||||
icon: 'icon12jiaobanbiao',
|
||||
path: '/pages/index/change_shiftsrecord',
|
||||
name: 'change_shifts_record_list'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '营销',
|
||||
name : 'promotion',
|
||||
children:[{
|
||||
title:'优惠券',
|
||||
icon:'icon31hongbao',
|
||||
path:'/pages/marketing/coupon_list',
|
||||
name:'coupon_list'
|
||||
}]
|
||||
},
|
||||
{
|
||||
title: '库存',
|
||||
name: 'stock',
|
||||
children: [{
|
||||
title: '出库单',
|
||||
icon: 'iconchukudan',
|
||||
path: '/pages/stock/wastage',
|
||||
name: 'stock_wastage',
|
||||
addon: 'stock'
|
||||
},
|
||||
{
|
||||
title: '入库单',
|
||||
icon: 'iconrukudan',
|
||||
path: '/pages/stock/storage',
|
||||
name: 'stock_storage',
|
||||
addon: 'stock'
|
||||
},
|
||||
{
|
||||
title: '调拨单',
|
||||
icon: 'icontiaobodan',
|
||||
path: '/pages/stock/allocate',
|
||||
name: 'stock_allocate',
|
||||
addon: 'stock'
|
||||
},
|
||||
{
|
||||
title: '库存盘点',
|
||||
icon: 'iconkucunpandian',
|
||||
path: '/pages/stock/check',
|
||||
name: 'stock_check',
|
||||
addon: 'stock'
|
||||
},
|
||||
{
|
||||
title: '库存管理',
|
||||
icon: 'iconkucunguanli',
|
||||
path: '/pages/stock/manage',
|
||||
name: 'stock_manage',
|
||||
addon: 'stock'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '数据',
|
||||
children: [{
|
||||
title: '门店结算',
|
||||
icon: 'iconshourujiesuan',
|
||||
path: '/pages/store/settlement',
|
||||
addon: 'store',
|
||||
name: 'store_settlement'
|
||||
},
|
||||
{
|
||||
title: '营业数据',
|
||||
icon: 'iconyingyeshujuguanliputong',
|
||||
path: '/pages/stat/index',
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '设置',
|
||||
children: [{
|
||||
title: '门店设置',
|
||||
icon: 'icongongyingshang',
|
||||
path: '/pages/store/index',
|
||||
name: 'store_config_root',
|
||||
},
|
||||
{
|
||||
title: '收款设置',
|
||||
icon: 'iconshoukuan-',
|
||||
path: '/pages/collectmoney/config',
|
||||
// name: 'collectmoney_config',
|
||||
},
|
||||
{
|
||||
title: '预约设置',
|
||||
icon: 'iconyuyue',
|
||||
path: '/pages/reserve/config',
|
||||
name: 'reserve_config',
|
||||
addon: 'cardservice'
|
||||
},
|
||||
{
|
||||
title: '小票打印',
|
||||
icon: 'icondayin',
|
||||
name: 'printer_config',
|
||||
path: '/pages/printer/list',
|
||||
},
|
||||
{
|
||||
title: '配送员',
|
||||
icon: 'iconpeisong',
|
||||
path: '/pages/store/deliver',
|
||||
name: 'store_deliver_config'
|
||||
},
|
||||
{
|
||||
title: '电子秤管理',
|
||||
icon: 'icondianzicheng',
|
||||
name: 'heavt_config',
|
||||
path: '/pages/scale/list',
|
||||
addon: 'scale'
|
||||
},
|
||||
{
|
||||
title: '本机设置',
|
||||
icon: 'iconbenji',
|
||||
path: '/pages/local/config',
|
||||
name: 'local_config',
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<unipopup ref="couponCategoryPop" type="center">
|
||||
<view class="coupon-category-pop">
|
||||
<view class="header flex justify-between">
|
||||
<view class="title">选择分类</view>
|
||||
<!-- <view class="pop-header-close" @click="$refs.couponCategoryPop.close()">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view> -->
|
||||
</view>
|
||||
<!-- :checkStrictly="true" -->
|
||||
<view :overflow-y="true" class="body">
|
||||
<scroll-view class="tree" :overflow-y="true">
|
||||
<DaTreeVue2
|
||||
ref="DaTreeRef"
|
||||
:data="treeData"
|
||||
labelField="category_name"
|
||||
valueField="category_id"
|
||||
childrenField="child_list"
|
||||
:themeColors="'var(--primary-color)'"
|
||||
expandChecked
|
||||
showCheckbox
|
||||
:defaultCheckedKeys="defaultCheckedKeysValue"
|
||||
@change="handleTreeChange"></DaTreeVue2>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="footer flex justify-end">
|
||||
<button type="default" class="confirm btn" @click="confirm">确认</button>
|
||||
<button type="default" class="btn" @click="$refs.couponCategoryPop.close()">取消</button>
|
||||
</view>
|
||||
</view>
|
||||
</unipopup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DaTreeVue2 from '@/components/da-tree-vue2/index.vue'
|
||||
import unipopup from '@/components/uni-popup/uni-popup.vue';
|
||||
import index from './index.js';
|
||||
export default {
|
||||
components: {
|
||||
DaTreeVue2,
|
||||
unipopup,
|
||||
},
|
||||
mixins: [index]
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
87
addon/cashier/source/os/components/coupon-category-popup/index.js
Executable file
87
addon/cashier/source/os/components/coupon-category-popup/index.js
Executable file
@@ -0,0 +1,87 @@
|
||||
import {
|
||||
getGoodsCategory
|
||||
} from '@/api/goods.js'
|
||||
export default {
|
||||
name: 'couponCategoryPopup',
|
||||
data() {
|
||||
return {
|
||||
treeData: [],
|
||||
defaultCheckedKeysValue: [],
|
||||
checkList: [], //选中以及半选中数据
|
||||
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getGoodsCategoryFn()
|
||||
},
|
||||
methods: {
|
||||
getGoodsCategoryFn() {
|
||||
getGoodsCategory({
|
||||
level: 3
|
||||
}).then(res => {
|
||||
this.treeData = res.data
|
||||
})
|
||||
},
|
||||
open(value) {
|
||||
this.defaultCheckedKeysValue = this.$util.deepClone(value)
|
||||
this.$refs.couponCategoryPop.open()
|
||||
},
|
||||
handleTreeChange(val) {
|
||||
this.defaultCheckedKeysValue = this.$util.deepClone(val)
|
||||
let halfCheckList = this.$refs.DaTreeRef.getHalfCheckedKeys()||[]
|
||||
this.checkList = this.$util.deepClone(val.concat(halfCheckList))
|
||||
},
|
||||
//处理数据
|
||||
getSelectedIdsAndNames(tree_selected, tree_all) {
|
||||
let name_arr = [];
|
||||
let id_arr = [];
|
||||
let selected_num = 0;
|
||||
for (let i in tree_selected) {
|
||||
let item_selected = tree_selected[i];
|
||||
let item_all = null;
|
||||
tree_all.forEach((item) => {
|
||||
if (item.category_id === item_selected.category_id) {
|
||||
item_all = item;
|
||||
return;
|
||||
}
|
||||
})
|
||||
if (!item_all) throw '对比数据有误';
|
||||
let title = item_selected.category_name;
|
||||
id_arr.push(item_selected.category_id);
|
||||
if (item_selected.child_num > 0) {
|
||||
let res = this.getSelectedIdsAndNames(item_selected.child_list, item_all.child_list);
|
||||
if (res.selected_num == item_all.child_num) {
|
||||
selected_num++;
|
||||
} else {
|
||||
title += '(' + res.name_arr.join('、') + ')';
|
||||
}
|
||||
id_arr = id_arr.concat(res.id_arr);
|
||||
} else {
|
||||
selected_num++;
|
||||
}
|
||||
name_arr.push(title);
|
||||
}
|
||||
return {
|
||||
selected_num: selected_num,
|
||||
name_arr: name_arr,
|
||||
id_arr: id_arr,
|
||||
};
|
||||
},
|
||||
confirm() {
|
||||
if(!this.checkList.length){
|
||||
this.$util.showToast({
|
||||
title: "请选择商品分类"
|
||||
});
|
||||
return false
|
||||
}
|
||||
getGoodsCategory({
|
||||
level: 3,
|
||||
category_ids:this.checkList.join(',')
|
||||
}).then(res => {
|
||||
let selectedData = this.getSelectedIdsAndNames(res.data, this.treeData);
|
||||
this.$emit('confirm',selectedData)
|
||||
this.$refs.couponCategoryPop.close()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
42
addon/cashier/source/os/components/coupon-category-popup/index.scss
Executable file
42
addon/cashier/source/os/components/coupon-category-popup/index.scss
Executable file
@@ -0,0 +1,42 @@
|
||||
.coupon-category-pop{
|
||||
width: 7rem;
|
||||
background-color: #fff;
|
||||
border-radius: 0.06rem;
|
||||
.header{
|
||||
padding: 0.15rem 0.2rem;
|
||||
font-size: 0.14rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
|
||||
}
|
||||
.body{
|
||||
padding: 0.2rem 0.3rem;
|
||||
padding-bottom: 0.15rem;
|
||||
box-sizing: border-box;
|
||||
height: 4rem;
|
||||
.tree{
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.footer{
|
||||
padding: 0 0.3rem;
|
||||
padding-bottom: 0.15rem;
|
||||
.btn {
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
padding: 0 0.2rem;
|
||||
height: 0.36rem;
|
||||
line-height: .36rem;
|
||||
font-size: 0.14rem;
|
||||
border-radius: 3px;
|
||||
|
||||
&.confirm{
|
||||
background-color: var(--primary-color);
|
||||
color: #fff;
|
||||
margin-right: 0.15rem;
|
||||
&::after{
|
||||
border-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
110
addon/cashier/source/os/components/da-tree-vue2/changelog.md
Executable file
110
addon/cashier/source/os/components/da-tree-vue2/changelog.md
Executable file
@@ -0,0 +1,110 @@
|
||||
# 1.4.1
|
||||
|
||||
## 版本调整
|
||||
|
||||
建议更新,但需要注意,异步数据的时候,后台需返回 leaf 字段来判断是否末项数据
|
||||
|
||||
1. **调整数据项格式,新增 `leaf` 字段,来判断是否为末节点**
|
||||
2. **调整数据项格式,新增 `sort` 字段,来排序节点位置**
|
||||
3. **注意:异步加载数据,当为末项的时候,需要服务端数据返回 `leaf` 字段**
|
||||
4. 新增 `alwaysFirstLoad` ,即异步数据总会在第一次展开节点时,拉取一次后台数据,来比对是否一致
|
||||
5. 拆分 `field` 属性,**注意: 1.5.0 版本后将移除 `field` 属性**
|
||||
6. 新增 `labelField` 同 `field.label`,指定节点对象中某个属性为**标签**字段,默认`label`
|
||||
7. 新增 `valueField` 同 `field.key`,指定节点对象中某个属性为**值**字段,默认`value`
|
||||
8. 新增 `childrenField` 同 `field.children`,指定节点对象中某个属性为**子树节点**字段,默认`children`
|
||||
9. 新增 `disabledField` 同 `field.disabled`,指定节点对象中某个属性为**禁用**字段,默认`disabled`
|
||||
10. 新增 `appendField` 同 `field.append`,指定节点对象中某个属性为**副标签**字段,默认`append`
|
||||
11. 新增 `leafField` 同 `field.label`,指定节点对象中某个属性为**末级节点**字段,默认`leaf`
|
||||
12. 新增 `sortField` 同 `field.label`,指定节点对象中某个属性为**排序**字段,默认`sort`
|
||||
13. 新增 `isLeafFn` ,用来自定义控制数据项的末项
|
||||
14. 更多的项目示例
|
||||
15. 支持单选取消选中
|
||||
16. 修复节点展开时可能存在的 bug
|
||||
17. 修复节点选择可能存在的 bug
|
||||
18. 调整为子节点默认继承父节点禁用属性
|
||||
19. `setExpandedKeys` 添加参数一为 `all` 即可支持一键展开/收起全部节点
|
||||
20. 其它更多优化
|
||||
|
||||
# 1.3.4
|
||||
|
||||
优化
|
||||
|
||||
1. 优化图标字体命名
|
||||
|
||||
# 1.3.3
|
||||
|
||||
版本同步于 Vue3 版,[查看 Vue3 版更新日志](https://ext.dcloud.net.cn/plugin?id=12384&update_log)
|
||||
|
||||
# 1.3.2
|
||||
|
||||
版本同步于 Vue3 版,[查看 Vue3 版更新日志](https://ext.dcloud.net.cn/plugin?id=12384&update_log)
|
||||
|
||||
# 1.3.1.1
|
||||
|
||||
修复
|
||||
|
||||
1. 修复 APP 兼容性引起的报错
|
||||
|
||||
# 1.3.1
|
||||
|
||||
## 建议更新
|
||||
|
||||
### 1.2.2~1.3.1 更新预览
|
||||
|
||||
1. 新增支持主题换色
|
||||
2. 新增支持点击标签也能选中节点
|
||||
3. 新增`field`字段 `append` 用于在标签后面显示小提示
|
||||
4. 方法`setExpandedKeys`支持加载动态数据
|
||||
5. 支持单选的`onlyRadioLeaf`为`true`时可点父节点展开/收起
|
||||
6. 新增 `expandChecked`,控制选择时是否展开当前已选的所有下级节点
|
||||
7. 新增 `checkedDisabled`,支持渲染禁用值
|
||||
8. 新增 `packDisabledkey`,支持返回已选中的禁用的 key
|
||||
9. 更多细节修复、优化请移步 Vue3 版的更新日志
|
||||
|
||||
后续版本仍不会实时同步 Vue3 版本,如急需新功能,请移步 Vue3 版
|
||||
|
||||
版本同步于 Vue3 版,[查看 Vue3 版更新日志](https://ext.dcloud.net.cn/plugin?id=12384&update_log)
|
||||
|
||||
# 1.2.2
|
||||
|
||||
## 建议更新,优化诸多问题
|
||||
|
||||
版本同步于 Vue3 版,[查看 Vue3 版更新日志](https://ext.dcloud.net.cn/plugin?id=12384&update_log)
|
||||
|
||||
# 1.2.1
|
||||
|
||||
版本同步于 Vue3 版,[查看 Vue3 版更新日志](https://ext.dcloud.net.cn/plugin?id=12384&update_log)
|
||||
|
||||
# 1.2.0.1
|
||||
|
||||
优化
|
||||
|
||||
1. 优化小程序兼容
|
||||
|
||||
# 1.2.0
|
||||
|
||||
版本同步于 Vue3 版,[查看 Vue3 版更新日志](https://ext.dcloud.net.cn/plugin?id=12384&update_log)
|
||||
|
||||
# 1.1.1.1
|
||||
|
||||
修复
|
||||
|
||||
1. 修复同步版本的错误写法引起的报错
|
||||
|
||||
# 1.1.1
|
||||
|
||||
版本同步于 Vue3 版,[查看 Vue3 版更新日志](https://ext.dcloud.net.cn/plugin?id=12384&update_log)
|
||||
|
||||
# 1.1.0
|
||||
|
||||
版本同步于 Vue3 版,[查看 Vue3 版更新日志](https://ext.dcloud.net.cn/plugin?id=12384&update_log)
|
||||
|
||||
# 1.0.6
|
||||
|
||||
新增
|
||||
|
||||
版本同步于 Vue3 版,[查看 Vue3 版更新日志](https://ext.dcloud.net.cn/plugin?id=12384&update_log)
|
||||
|
||||
# 1.0.5
|
||||
|
||||
版本同步于 Vue3 版,[查看 Vue3 版更新日志](https://ext.dcloud.net.cn/plugin?id=12384),基于 Vue2 进行开发,支持单选、多选,全平台兼容。
|
||||
1105
addon/cashier/source/os/components/da-tree-vue2/index.vue
Executable file
1105
addon/cashier/source/os/components/da-tree-vue2/index.vue
Executable file
File diff suppressed because it is too large
Load Diff
183
addon/cashier/source/os/components/da-tree-vue2/props.js
Executable file
183
addon/cashier/source/os/components/da-tree-vue2/props.js
Executable file
@@ -0,0 +1,183 @@
|
||||
// @ts-nocheck
|
||||
export default {
|
||||
/**
|
||||
* 树的数据
|
||||
*/
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
/**
|
||||
* 主题色
|
||||
*/
|
||||
themeColors: {
|
||||
type: String,
|
||||
default: '#007aff',
|
||||
},
|
||||
/**
|
||||
* 是否开启多选,默认单选
|
||||
*/
|
||||
showCheckbox: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 默认选中的节点,注意单选时为单个key,多选时为key的数组
|
||||
*/
|
||||
defaultCheckedKeys: {
|
||||
type: [Array, String, Number],
|
||||
default: null,
|
||||
},
|
||||
/**
|
||||
* 选择框的位置,可选 left/right
|
||||
*/
|
||||
checkboxPlacement: {
|
||||
type: String,
|
||||
default: 'left',
|
||||
},
|
||||
/**
|
||||
* 是否默认展开全部
|
||||
*/
|
||||
defaultExpandAll: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 默认展开的节点
|
||||
*/
|
||||
defaultExpandedKeys: {
|
||||
type: Array,
|
||||
default: null,
|
||||
},
|
||||
/**
|
||||
* 是否自动展开到选中的节点,默认不展开
|
||||
*/
|
||||
expandChecked: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 子项缩进距离,默认40,单位rpx
|
||||
*/
|
||||
indent: {
|
||||
type: Number,
|
||||
default: 0.4,
|
||||
},
|
||||
/**
|
||||
* (旧)字段对应内容,默认为 {label: 'label',key: 'key', children: 'children', disabled: 'disabled', append: 'append'}
|
||||
* 注意:1.5.0版本后不再兼容
|
||||
*/
|
||||
field: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
/**
|
||||
* 标签字段(新,拆分了)
|
||||
*/
|
||||
labelField: {
|
||||
type: String,
|
||||
default: 'label',
|
||||
},
|
||||
/**
|
||||
* 值字段(新,拆分了)
|
||||
*/
|
||||
valueField: {
|
||||
type: String,
|
||||
default: 'value',
|
||||
},
|
||||
/**
|
||||
* 下级字段(新,拆分了)
|
||||
*/
|
||||
childrenField: {
|
||||
type: String,
|
||||
default: 'children',
|
||||
},
|
||||
/**
|
||||
* 禁用字段(新,拆分了)
|
||||
*/
|
||||
disabledField: {
|
||||
type: String,
|
||||
default: 'disabled',
|
||||
},
|
||||
/**
|
||||
* 末级节点字段(新,拆分了)
|
||||
*/
|
||||
leafField: {
|
||||
type: String,
|
||||
default: 'leaf',
|
||||
},
|
||||
/**
|
||||
* 副标签字段(新,拆分了)
|
||||
*/
|
||||
appendField: {
|
||||
type: String,
|
||||
default: 'append',
|
||||
},
|
||||
/**
|
||||
* 排序字段(新,拆分了)
|
||||
*/
|
||||
sortField: {
|
||||
type: String,
|
||||
default: 'sort',
|
||||
},
|
||||
isLeafFn: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
/**
|
||||
* 是否显示单选图标,默认显示
|
||||
*/
|
||||
showRadioIcon: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
/**
|
||||
* 单选时只允许选中末级,默认可随意选中
|
||||
*/
|
||||
onlyRadioLeaf: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 多选时,是否执行父子不关联的任意勾选,默认父子关联
|
||||
*/
|
||||
checkStrictly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 为 true 时,空的 children 数组会显示展开图标
|
||||
*/
|
||||
loadMode: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 异步加载接口
|
||||
*/
|
||||
loadApi: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
/**
|
||||
* 是否总在首次的时候加载一下内容,来比对是否一致
|
||||
*/
|
||||
alwaysFirstLoad: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 是否渲染(操作)禁用值
|
||||
*/
|
||||
checkedDisabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 是否返回已禁用的但已选中的key
|
||||
*/
|
||||
packDisabledkey: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
}
|
||||
303
addon/cashier/source/os/components/da-tree-vue2/readme.md
Executable file
303
addon/cashier/source/os/components/da-tree-vue2/readme.md
Executable file
@@ -0,0 +1,303 @@
|
||||
# da-tree-vue2
|
||||
|
||||
一个基于 Vue2 的 tree(树)组件,同时支持主题换色,可能是最适合你的 tree(树)组件
|
||||
|
||||
`内容同步于 Vue3 版本,在此查看 ===>` **[Vue3 版](https://ext.dcloud.net.cn/plugin?id=12384)**
|
||||
|
||||
_与 Vue3 版本版本不同的是,此版本兼容更全面,比如 360 小程序、快应用等均支持_
|
||||
|
||||
### 关于使用
|
||||
|
||||
可在右侧的`使用 HBuilderX 导入插件`或`下载示例项目ZIP`,方便快速上手。
|
||||
|
||||
可通过下方的示例及文档说明,进一步了解使用组件相关细节参数。
|
||||
|
||||
插件地址:https://ext.dcloud.net.cn/plugin?id=12692
|
||||
|
||||
### 组件示例
|
||||
|
||||
```jsx
|
||||
<template>
|
||||
<view>
|
||||
<view>多选</view>
|
||||
<view><button @click="doCheckedTree(['2'],true)">全选</button></view>
|
||||
<view><button @click="doCheckedTree(['2'],false)">取消全选</button></view>
|
||||
<view><button @click="doCheckedTree(['211','222'],true)">选中指定节点</button></view>
|
||||
<view><button @click="doCheckedTree(['211','222'],false)">取消选中指定节点</button></view>
|
||||
<view><button @click="doExpandTree('all',true)">展开全部节点</button></view>
|
||||
<view><button @click="doExpandTree('all',false)">收起全部节点</button></view>
|
||||
<view><button @click="doExpandTree(['22','23'],true)">展开节点</button></view>
|
||||
<view><button @click="doExpandTree(['22','23'],false)">收起节点</button></view>
|
||||
<DaTreeVue2
|
||||
ref="DaTreeRef"
|
||||
:data="roomTreeData"
|
||||
labelField="name"
|
||||
valueField="id"
|
||||
defaultExpandAll
|
||||
showCheckbox
|
||||
:defaultCheckedKeys="defaultCheckedKeysValue"
|
||||
@change="handleTreeChange"
|
||||
@expand="handleExpandChange" />
|
||||
|
||||
<view>单选</view>
|
||||
<DaTreeVue2
|
||||
:data="roomTreeData"
|
||||
labelField="name"
|
||||
valueField="id"
|
||||
defaultExpandAll
|
||||
:defaultCheckedKeys="defaultCheckedKeysValue2"
|
||||
@change="handleTreeChange"
|
||||
@expand="handleExpandChange" />
|
||||
<view>默认展开指定节点</view>
|
||||
<DaTreeVue2
|
||||
:data="roomTreeData"
|
||||
labelField="name"
|
||||
valueField="id"
|
||||
showCheckbox
|
||||
:defaultExpandedKeys="defaultExpandKeysValue3"
|
||||
@change="handleTreeChange"
|
||||
@expand="handleExpandChange" />
|
||||
<view>异步加载数据</view>
|
||||
<DaTreeVue2
|
||||
:data="roomTreeData"
|
||||
labelField="name"
|
||||
valueField="id"
|
||||
showCheckbox
|
||||
loadMode
|
||||
:loadApi="GetApiData"
|
||||
defaultExpandAll
|
||||
@change="handleTreeChange"
|
||||
@expand="handleExpandChange" />
|
||||
</view>
|
||||
</template>
|
||||
```
|
||||
|
||||
```js
|
||||
/**
|
||||
* 模拟创建一个接口数据
|
||||
*/
|
||||
function GetApiData(currentNode) {
|
||||
const { key } = currentNode
|
||||
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
// 模拟返回空数据
|
||||
if (key.indexOf('-') > -1) {
|
||||
return resolve(null)
|
||||
// return resolve([])
|
||||
}
|
||||
|
||||
return resolve([
|
||||
{
|
||||
id: `${key}-1`,
|
||||
name: `行政部X${key}-1`,
|
||||
},
|
||||
{
|
||||
id: `${key}-2`,
|
||||
name: `财务部X${key}-2`,
|
||||
append: '定义了末项数据',
|
||||
leaf: true,
|
||||
},
|
||||
{
|
||||
id: `${key}-3`,
|
||||
name: `资源部X${key}-3`,
|
||||
},
|
||||
{
|
||||
id: `${key}-4`,
|
||||
name: `资源部X${key}-3`,
|
||||
append: '被禁用,无展开图标',
|
||||
disabled: true,
|
||||
},
|
||||
])
|
||||
}, 2000)
|
||||
})
|
||||
}
|
||||
|
||||
import DaTreeVue2 from '@/components/da-tree-vue2/index.vue'
|
||||
export default {
|
||||
components: { DaTreeVue2 },
|
||||
data() {
|
||||
return {
|
||||
GetApiData,
|
||||
// key的类型必须对应树数据key的类型
|
||||
defaultCheckedKeysValue: ['211', '222'],
|
||||
defaultCheckedKeysValue2: '222',
|
||||
defaultExpandKeysValue3: ['212', '231'],
|
||||
roomTreeData: [
|
||||
{
|
||||
id: '2',
|
||||
name: '行政中心',
|
||||
children: [
|
||||
{
|
||||
id: '21',
|
||||
name: '行政部',
|
||||
children: [
|
||||
{
|
||||
id: '211',
|
||||
name: '行政一部',
|
||||
children: null,
|
||||
},
|
||||
{
|
||||
id: '212',
|
||||
name: '行政二部',
|
||||
children: [],
|
||||
disabled: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
name: '财务部',
|
||||
children: [
|
||||
{
|
||||
id: '221',
|
||||
name: '财务一部',
|
||||
children: [],
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
id: '222',
|
||||
name: '财务二部',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '23',
|
||||
name: '人力资源部',
|
||||
children: [
|
||||
{
|
||||
id: '231',
|
||||
name: '人力一部',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: '232',
|
||||
name: '人力二部',
|
||||
append: '更多示例,请下载示例项目查看',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
doExpandTree(keys, expand) {
|
||||
this.$refs.DaTreeRef?.setExpandedKeys(keys, expand)
|
||||
|
||||
const gek = this.$refs.DaTreeRef?.getExpandedKeys()
|
||||
console.log('当前已展开的KEY ==>', gek)
|
||||
},
|
||||
doCheckedTree(keys, checked) {
|
||||
this.$refs.DaTreeRef?.setCheckedKeys(keys, checked)
|
||||
|
||||
const gek = this.$refs.DaTreeRef?.getCheckedKeys()
|
||||
console.log('当前已选中的KEY ==>', gek)
|
||||
},
|
||||
handleTreeChange(allSelectedKeys, currentItem) {
|
||||
console.log('handleTreeChange ==>', allSelectedKeys, currentItem)
|
||||
},
|
||||
handleExpandChange(expand, currentItem) {
|
||||
console.log('handleExpandChange ==>', expand, currentItem)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
** 更多示例请下载/导入示例项目 ZIP 查看 **
|
||||
|
||||
### 组件参数
|
||||
|
||||
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|
||||
| :------------------ | :------------------------------ | :--------- | :--- | :--------------------------------------------------------------------------- |
|
||||
| data | `Array` | - | 是 | 树的数据 |
|
||||
| themeColor | `String` | `#007aff` | 否 | 主题色,十六进制 |
|
||||
| defaultCheckedKeys | `Array` \| `Number` \| `String` | - | 否 | 默认选中的节点,单选为单个 key,多选为 key 的数组 |
|
||||
| showCheckbox | `Boolean` | `false` | 否 | 是否开启多选,默认单选 |
|
||||
| checkStrictly | `Boolean` | `false` | 否 | 多选时,是否执行父子不关联的任意勾选,默认父子关联 |
|
||||
| showRadioIcon | `Boolean` | `true` | 否 | 是否显示单选图标,默认显示 |
|
||||
| onlyRadioLeaf | `Boolean` | `true` | 否 | 单选时只允许选中末级,默认可随意选中 |
|
||||
| defaultExpandAll | `Boolean` | `false` | 否 | 是否默认展开全部 |
|
||||
| defaultExpandedKeys | `Array` | - | 否 | 默认展开的节点 |
|
||||
| indent | `Number` | `40` | 否 | 子项缩进距离,单位 rpx |
|
||||
| checkboxPlacement | `String` | `left` | 否 | 选择框的位置,可选 left/right |
|
||||
| loadMode | `Boolean` | `false` | 否 | 为 true 时,空的 children 数组会显示展开图标 |
|
||||
| loadApi | `Function` | - | 否 | 选择框的位置,可选 left/right |
|
||||
| checkedDisabled | `Boolean` | `false` | 否 | 是否渲染禁用值,默认不渲染 |
|
||||
| packDisabledkey | `Boolean` | `true` | 否 | 是否返回已禁用的但已选中的 key,默认返回禁用已选值 |
|
||||
| expandChecked | `Boolean` | `false` | 否 | 是否自动展开到选中的节点,默认不展开 |
|
||||
| alwaysFirstLoad | `Boolean` | `false` | 否 | 是否总在首次的时候加载一下内容,默认不加载,否则只有展开末级节点才会加载数据 |
|
||||
| isLeafFn | `Function` | - | 否 | 自定义函数返回来控制数据项的末项 |
|
||||
| field | `Object` | - | 否 | 字段对应内容,格式参考下方(1.5.0 后移除,请用单独的字段匹配) |
|
||||
| labelField | `String` | `label` | 否 | 指定节点对象中某个属性为标签字段,默认`label` |
|
||||
| valueField | `String` | `value` | 否 | 指定节点对象中某个属性为值字段,默认`value` |
|
||||
| childrenField | `String` | `children` | 否 | 指定节点对象中某个属性为子树节点字段,默认`children` |
|
||||
| disabledField | `String` | `disabled` | 否 | 指定节点对象中某个属性为禁用字段,默认`disabled` |
|
||||
| appendField | `String` | `append` | 否 | 指定节点对象中某个属性为副标签字段,默认`append` |
|
||||
| leafField | `String` | `leaf` | 否 | 指定节点对象中某个属性为末级节点字段,默认`leaf` |
|
||||
| sortField | `String` | `sort` | 否 | 指定节点对象中某个属性为排序字段,默认`sort` |
|
||||
|
||||
**field 格式(1.5.0 后移除,请用单独的字段匹配)**
|
||||
|
||||
```js
|
||||
{
|
||||
label: 'label',
|
||||
key: 'key',
|
||||
children: 'children',
|
||||
disabled: 'disabled',
|
||||
append: 'append'
|
||||
}
|
||||
```
|
||||
|
||||
### 组件事件
|
||||
|
||||
| 事件名称 | 回调参数 | 说明 |
|
||||
| :------- | :-------------------------------------- | :-------------- |
|
||||
| change | `(allCheckedKeys, currentItem) => void` | 选中时回调 |
|
||||
| expand | `(expandState, currentItem) => void` | 展开/收起时回调 |
|
||||
|
||||
### 组件方法
|
||||
|
||||
| 方法名称 | 参数 | 说明 |
|
||||
| :------------------ | :--------------- | :------------------------------------------------------------------------------------------------ |
|
||||
| setCheckedKeys | `(keys,checked)` | 设置指定 key 的节点选中/取消选中的状态。注: keys 单选时为 key,多选时为 key 的数组 |
|
||||
| setExpandedKeys | `(keys,expand)` | 设置指定 key 的节点展开/收起的状态,当 keys 为 all 时即代表展开/收起全部。注:keys 为数组或 `all` |
|
||||
| getCheckedKeys | - | 返回已选的 key |
|
||||
| getHalfCheckedKeys | - | 返回半选的 key |
|
||||
| getUncheckedKeys | - | 返回未选的 key |
|
||||
| getCheckedNodes | - | 返回已选的节点 |
|
||||
| getUncheckedNodes | - | 返回未选的节点 |
|
||||
| getHalfCheckedNodes | - | 返回半选的节点 |
|
||||
| getExpandedKeys | - | 返回已展开的 key |
|
||||
| getUnexpandedKeys | - | 返回未展开的 key |
|
||||
| getExpandedNodes | - | 返回已展开的节点 |
|
||||
| getUnexpandedNodes | - | 返回未展开的节点 |
|
||||
|
||||
### 组件版本
|
||||
|
||||
v1.4.1
|
||||
|
||||
### 差异化
|
||||
|
||||
已通过测试
|
||||
|
||||
> - H5 页面
|
||||
> - 微信小程序
|
||||
> - 支付宝、钉钉小程序
|
||||
> - 字节跳动、抖音、今日头条小程序
|
||||
> - 百度小程序
|
||||
> - 飞书小程序
|
||||
> - QQ 小程序
|
||||
> - 京东小程序
|
||||
> - 快应用
|
||||
> - 360 小程序
|
||||
|
||||
未测试
|
||||
|
||||
> - 快手小程序由于非企业用户暂无演示
|
||||
|
||||
### 开发组
|
||||
|
||||
[@CRLANG](https://crlang.com)
|
||||
151
addon/cashier/source/os/components/da-tree-vue2/utils.js
Executable file
151
addon/cashier/source/os/components/da-tree-vue2/utils.js
Executable file
@@ -0,0 +1,151 @@
|
||||
// @ts-nocheck
|
||||
/** 未选 */
|
||||
export const unCheckedStatus = 0
|
||||
/** 半选 */
|
||||
export const halfCheckedStatus = 1
|
||||
/** 选中 */
|
||||
export const isCheckedStatus = 2
|
||||
|
||||
/**
|
||||
* 深拷贝内容
|
||||
* @param originData 拷贝对象
|
||||
* @author crlang(https://crlang.com)
|
||||
*/
|
||||
export function deepClone(originData) {
|
||||
const type = Object.prototype.toString.call(originData)
|
||||
let data
|
||||
if (type === '[object Array]') {
|
||||
data = []
|
||||
for (let i = 0; i < originData.length; i++) {
|
||||
data.push(deepClone(originData[i]))
|
||||
}
|
||||
} else if (type === '[object Object]') {
|
||||
data = {}
|
||||
for (const prop in originData) {
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (originData.hasOwnProperty(prop)) { // 非继承属性
|
||||
data[prop] = deepClone(originData[prop])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data = originData
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有指定的节点
|
||||
* @param type
|
||||
* @param value
|
||||
* @author crlang(https://crlang.com)
|
||||
*/
|
||||
export function getAllNodes(list, type, value, packDisabledkey = true) {
|
||||
if (!list || list.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const res = []
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const item = list[i]
|
||||
if (item[type] === value) {
|
||||
if ((packDisabledkey && item.disabled) || !item.disabled) {
|
||||
res.push(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有指定的key值
|
||||
* @param type
|
||||
* @param value
|
||||
* @author crlang(https://crlang.com)
|
||||
*/
|
||||
export function getAllNodeKeys(list, type, value, packDisabledkey = true) {
|
||||
if (!list || list.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
const res = []
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const item = list[i]
|
||||
if (item[type] === value) {
|
||||
if ((packDisabledkey && item.disabled) || !item.disabled) {
|
||||
res.push(item.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res.length ? res : null
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误输出
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
export function logError(msg, ...args) {
|
||||
console.error(`DaTree: ${msg}`, ...args)
|
||||
}
|
||||
|
||||
const toString = Object.prototype.toString
|
||||
|
||||
export function is(val, type) {
|
||||
return toString.call(val) === `[object ${type}]`
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否对象(Object)
|
||||
* @param val
|
||||
|
||||
*/
|
||||
export function isObject(val) {
|
||||
return val !== null && is(val, 'Object')
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否数字(Number)
|
||||
* @param val
|
||||
|
||||
*/
|
||||
export function isNumber(val) {
|
||||
return is(val, 'Number')
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否字符串(String)
|
||||
* @param val
|
||||
|
||||
*/
|
||||
export function isString(val) {
|
||||
return is(val, 'String')
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否函数方法(Function)
|
||||
* @param val
|
||||
|
||||
*/
|
||||
export function isFunction(val) {
|
||||
return typeof val === 'function'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否布尔(Boolean)
|
||||
* @param val
|
||||
|
||||
*/
|
||||
export function isBoolean(val) {
|
||||
return is(val, 'Boolean')
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否数组(Array)
|
||||
* @param val
|
||||
|
||||
*/
|
||||
export function isArray(val) {
|
||||
return val && Array.isArray(val)
|
||||
}
|
||||
159
addon/cashier/source/os/components/ns-card/index.js
Executable file
159
addon/cashier/source/os/components/ns-card/index.js
Executable file
@@ -0,0 +1,159 @@
|
||||
import {getCardList} from '@/api/card.js';
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'nsCard',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: 'oncecard'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
goodsType: '',
|
||||
pageSize: 35,
|
||||
onceCardData: {
|
||||
page: 0,
|
||||
total: 1,
|
||||
list: []
|
||||
},
|
||||
timeCardData: {
|
||||
page: 0,
|
||||
total: 1,
|
||||
list: []
|
||||
},
|
||||
commonCardData: {
|
||||
page: 0,
|
||||
total: 1,
|
||||
list: []
|
||||
},
|
||||
itemNum: 3,
|
||||
mediaQueryOb: null,
|
||||
selectCardSkuId: [],
|
||||
isLoad: false
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.goodsType = this.type;
|
||||
this.init();
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['buyCardGoodsData'])
|
||||
},
|
||||
watch: {
|
||||
buyCardGoodsData: {
|
||||
// 每个属性值发生变化就会调用这个函数
|
||||
handler(newVal, oldVal) {
|
||||
this.selectCardSkuId = [];
|
||||
if(!Object.values(this.buyCardGoodsData).length) return false;
|
||||
Object.values(this.buyCardGoodsData).forEach((item,index)=>{
|
||||
this.selectCardSkuId.push(item.sku_id);
|
||||
});
|
||||
},
|
||||
// 深度监听 属性的变化
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.mediaQueryOb = uni.createMediaQueryObserver(this);
|
||||
|
||||
this.mediaQueryOb.observe({maxWidth: 1500}, matches => {
|
||||
if (matches) this.itemNum = 2;
|
||||
});
|
||||
|
||||
this.mediaQueryOb.observe({minWidth: 1501, maxWidth: 1700}, matches => {
|
||||
if (matches) this.itemNum = 3;
|
||||
});
|
||||
|
||||
this.mediaQueryOb.observe({minWidth: 1701}, matches => {
|
||||
if (matches) this.itemNum = 4;
|
||||
});
|
||||
},
|
||||
destroyed() {
|
||||
this.mediaQueryOb.disconnect();
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.isLoad = false;
|
||||
this.onceCardData.page = 0;
|
||||
this.timeCardData.page = 0;
|
||||
this.commonCardData.page = 0;
|
||||
this.getOnceCard();
|
||||
this.getTimeCard();
|
||||
this.getCommonCard();
|
||||
},
|
||||
switchGoodsType(type) {
|
||||
this.goodsType = type;
|
||||
},
|
||||
//卡项相关
|
||||
goodsSelect(data) {
|
||||
if (data.stock <= 0) return;
|
||||
|
||||
let _buyCardGoodsData = this.$util.deepClone(this.buyCardGoodsData);
|
||||
|
||||
if (_buyCardGoodsData['sku_' + data.sku_id]) {
|
||||
_buyCardGoodsData['sku_' + data.sku_id].num += 1;
|
||||
} else {
|
||||
_buyCardGoodsData['sku_' + data.sku_id] = data;
|
||||
_buyCardGoodsData['sku_' + data.sku_id].num = 1;
|
||||
}
|
||||
this.$store.commit('buycard/setGoodsData', _buyCardGoodsData);
|
||||
this.$store.commit('buycard/setActive', 'SelectGoodsAfter');
|
||||
},
|
||||
getOnceCard() {
|
||||
this.isLoad = false;
|
||||
if (this.onceCardData.page + 1 > this.onceCardData.total) return;
|
||||
this.onceCardData.page += 1;
|
||||
getCardList({
|
||||
page: this.onceCardData.page,
|
||||
page_size: this.pageSize,
|
||||
card_type: 'oncecard',
|
||||
goods_state: 1,
|
||||
status: 1,
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.isLoad = true;
|
||||
this.onceCardData.total = res.data.page_count || 1;
|
||||
if (this.onceCardData.page == 1) this.onceCardData.list = [];
|
||||
if (res.data.list.length) this.onceCardData.list = this.onceCardData.list.concat(res.data.list);
|
||||
}
|
||||
});
|
||||
},
|
||||
getTimeCard() {
|
||||
if (this.timeCardData.page + 1 > this.timeCardData.total) return;
|
||||
this.timeCardData.page += 1;
|
||||
getCardList({
|
||||
page: this.timeCardData.page,
|
||||
card_type: 'timecard',
|
||||
goods_state: 1,
|
||||
page_size: this.pageSize,
|
||||
status: 1,
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.timeCardData.total = res.data.page_count || 1;
|
||||
if (this.timeCardData.page == 1) this.timeCardData.list = [];
|
||||
if (res.data.list.length) this.timeCardData.list = this.timeCardData.list.concat(
|
||||
res.data.list);
|
||||
}
|
||||
});
|
||||
},
|
||||
getCommonCard() {
|
||||
if (this.commonCardData.page + 1 > this.commonCardData.total) return;
|
||||
this.commonCardData.page += 1;
|
||||
getCardList({
|
||||
page: this.commonCardData.page,
|
||||
card_type: 'commoncard',
|
||||
goods_state: 1,
|
||||
page_size: this.pageSize,
|
||||
status: 1,
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.commonCardData.total = res.data.page_count || 1;
|
||||
if (this.commonCardData.page == 1) this.commonCardData.list = [];
|
||||
if (res.data.list.length) this.commonCardData.list = this.commonCardData.list.concat(res.data.list);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
228
addon/cashier/source/os/components/ns-card/index.scss
Executable file
228
addon/cashier/source/os/components/ns-card/index.scss
Executable file
@@ -0,0 +1,228 @@
|
||||
.container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.header-action {
|
||||
padding: 0.22rem 0.24rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #fff;
|
||||
border-radius: 0.04rem;
|
||||
|
||||
.header-action-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 0.44rem;
|
||||
background-color: var(--primary-color-light-9);
|
||||
border-radius: 0.22rem;
|
||||
|
||||
view {
|
||||
min-width: 1.02rem;
|
||||
height: 0.44rem;
|
||||
line-height: 0.44rem;
|
||||
text-align: center;
|
||||
font-size: 0.14rem;
|
||||
border-left-width: 0;
|
||||
transition: all 0.3s;
|
||||
cursor: pointer;
|
||||
border-radius: 0.22rem;
|
||||
color: $primary-color;
|
||||
|
||||
&.active {
|
||||
color: #fff;
|
||||
background-color: $primary-color;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-left-width: 0.01rem;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: .2rem;
|
||||
box-sizing: border-box;
|
||||
height: calc(100% - 1.08rem);
|
||||
transform: rotate(0);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.list-wrap {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.table-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.table-item {
|
||||
border: 0.01rem solid #fff;
|
||||
box-sizing: border-box;
|
||||
padding: 0.1rem 0.18rem 0.1rem 0.1rem;
|
||||
background-color: #fff;
|
||||
margin-bottom: 0.12rem;
|
||||
margin-right: 0.12rem;
|
||||
cursor: pointer;
|
||||
transition: border-color, background-color 0.3s;
|
||||
position: relative;
|
||||
border-radius: 0.04rem;
|
||||
&.item-mum-2{
|
||||
width: calc((100% - 0.25rem) / 2);
|
||||
}
|
||||
&.item-mum-3{
|
||||
width: calc((100% - 0.37rem) / 3);
|
||||
}
|
||||
&.item-mum-4{
|
||||
width: calc((100% - 0.49rem) / 4);
|
||||
}
|
||||
.item-other {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-left: 0.1rem;
|
||||
}
|
||||
|
||||
.item-img {
|
||||
width: 0.9rem;
|
||||
height: 0.9rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
-ms-flex-negative: 0;
|
||||
-webkit-flex-shrink: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
border-radius: 0.03rem;
|
||||
}
|
||||
}
|
||||
|
||||
.item-name {
|
||||
height: 0.4rem;
|
||||
line-height: 0.2rem;
|
||||
max-width: 1.58rem;
|
||||
margin-bottom: 0.05rem;
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
.no-stock {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
cursor: not-allowed;
|
||||
image{
|
||||
height: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
.item-info {
|
||||
cursor: pointer;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
||||
.item-time {
|
||||
font-size: 0.12rem;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.item-money {
|
||||
font-size: 0.14rem;
|
||||
color: $primary-color;
|
||||
height: 0.19rem;
|
||||
line-height: 0.19rem;
|
||||
}
|
||||
|
||||
.item-stock {
|
||||
height: 0.17rem;
|
||||
font-size: 0.12rem;
|
||||
color: #808695;
|
||||
line-height: 0.17rem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.table-item.yes-stock {
|
||||
&:hover {
|
||||
background-color: var(--primary-color-light-9);
|
||||
border-color: $primary-color;
|
||||
}
|
||||
|
||||
&.focus,
|
||||
&:focus {
|
||||
background-color: var(--primary-color-light-9);
|
||||
border-color: $primary-color;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: $primary-color;
|
||||
background-color: $primary-color;
|
||||
color: #fff;
|
||||
|
||||
.item-time,
|
||||
.item-money,
|
||||
.item-stock {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding-top: 1.2rem;
|
||||
|
||||
image {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.tips {
|
||||
color: #999;
|
||||
margin-top: 0.15rem;
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .uni-scroll-view {
|
||||
&::-webkit-scrollbar {
|
||||
width: 0.06rem;
|
||||
height: 0.06rem;
|
||||
background-color: rgba($color: #000000, $alpha: 0);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 0.06rem;
|
||||
box-shadow: inset 0 0 0.06rem rgba(45, 43, 43, 0.45);
|
||||
background-color: #ddd;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover::-webkit-scrollbar-thumb {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
111
addon/cashier/source/os/components/ns-card/ns-card.vue
Executable file
111
addon/cashier/source/os/components/ns-card/ns-card.vue
Executable file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="header-action common-wrap">
|
||||
<view class="header-action-left">
|
||||
<view :class="{ active: goodsType == 'oncecard' }" @click="switchGoodsType('oncecard')">限次卡</view>
|
||||
<view :class="{ active: goodsType == 'timecard' }" @click="switchGoodsType('timecard')">限时卡</view>
|
||||
<view :class="{ active: goodsType == 'commoncard' }" @click="switchGoodsType('commoncard')">通用卡</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
<scroll-view scroll-y="true" class="list-wrap" @scrolltolower="getOncecard()" v-show="goodsType == 'oncecard'">
|
||||
<view class="table-list" v-show="onceCardData.list.length > 0">
|
||||
<view class="table-item" :class="{'yes-stock': item.stock>0, 'item-mum-2': itemNum == 2, 'item-mum-3': itemNum == 3, 'item-mum-4': itemNum == 4, 'active': selectCardSkuId.indexOf(item.sku_id) > -1 }" v-for="(item, index) in onceCardData.list" :key="index" @click="goodsSelect(item)">
|
||||
<view class="item-info">
|
||||
<view class="item-img">
|
||||
<image v-if="item.goods_image == '@/static/goods/goods.png'" src="@/static/goods/goods.png" mode="widthFix"/>
|
||||
<image v-else :src="$util.img(item.goods_image.split(',')[0], { size: 'small' })" @error="item.goods_image = '@/static/goods/goods.png'" mode="widthFix"/>
|
||||
</view>
|
||||
<view class="item-other flex-1">
|
||||
<view class="item-name">{{ item.goods_name }}</view>
|
||||
<view class="w-full self-end">
|
||||
<view class="item-money">
|
||||
<text class="util">¥</text>
|
||||
{{ item.discount_price | moneyFormat }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="no-stock" v-if="item.stock <= 0">
|
||||
<image src="@/static/stock/stock_empty.png" mode="heightFix"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty" v-if="isLoad && !onceCardData.list.length">
|
||||
<image src="@/static/goods/goods_empty.png" mode="widthFix"/>
|
||||
<view class="tips">暂无卡项</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<scroll-view scroll-y="true" class="list-wrap" @scrolltolower="getTimecard()" v-show="goodsType == 'timecard'">
|
||||
<view class="table-list" v-show="timeCardData.list.length > 0">
|
||||
<view class="table-item" :class="{'yes-stock': item.stock>0, 'item-mum-2': itemNum == 2, 'item-mum-3': itemNum == 3, 'item-mum-4': itemNum == 4,}" v-for="(item, index) in timeCardData.list" :key="index" @click="goodsSelect(item)">
|
||||
<view class="item-info">
|
||||
<view class="item-img">
|
||||
<image v-if="item.goods_image == '@/static/goods/goods.png'" src="@/static/goods/goods.png" mode="widthFix"/>
|
||||
<image v-else :src="$util.img(item.goods_image.split(',')[0], { size: 'small' })" @error="item.goods_image = '@/static/goods/goods.png'" mode="widthFix"/>
|
||||
</view>
|
||||
<view class="item-other flex-1">
|
||||
<view class="item-name">{{ item.goods_name }}</view>
|
||||
<view class="w-full self-end">
|
||||
<view class="item-money">
|
||||
<text class="util">¥</text>
|
||||
{{ item.discount_price | moneyFormat }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="no-stock" v-if="item.stock <= 0">
|
||||
<image src="@/static/stock/stock_empty.png" mode="heightFix"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty" v-if="!timeCardData.list.length">
|
||||
<image src="@/static/goods/goods_empty.png" mode="widthFix"/>
|
||||
<view class="tips">暂无卡项</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<scroll-view scroll-y="true" class="list-wrap" @scrolltolower="getCommoncard()" v-show="goodsType == 'commoncard'">
|
||||
<view class="table-list" v-show="commonCardData.list.length > 0">
|
||||
<view class="table-item" :class="{'yes-stock': item.stock>0, 'item-mum-2': itemNum == 2, 'item-mum-3': itemNum == 3, 'item-mum-4': itemNum == 4,}" v-for="(item, index) in commonCardData.list" :key="index" @click="goodsSelect(item)">
|
||||
<view class="item-info">
|
||||
<view class="item-img">
|
||||
<image v-if="item.goods_image == '@/static/goods/goods.png'" src="@/static/goods/goods.png" mode="widthFix"/>
|
||||
<image v-else :src="$util.img(item.goods_image.split(',')[0], { size: 'small' })" @error="item.goods_image = '@/static/goods/goods.png'" mode="widthFix"/>
|
||||
</view>
|
||||
<view class="item-other flex-1">
|
||||
<view class="item-name">{{ item.goods_name }}</view>
|
||||
<view class="w-full self-end">
|
||||
<view class="item-money">
|
||||
<text class="util">¥</text>
|
||||
{{ item.discount_price | moneyFormat }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="no-stock" v-if="item.stock <= 0">
|
||||
<image src="@/static/stock/stock_empty.png" mode="heightFix"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty" v-if="!commonCardData.list.length">
|
||||
<image src="@/static/goods/goods_empty.png" mode="widthFix"/>
|
||||
<view class="tips">暂无卡项</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import index from './index.js';
|
||||
export default {
|
||||
mixins: [index]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
520
addon/cashier/source/os/components/ns-goods-sku-select/ns-goods-sku-select.vue
Executable file
520
addon/cashier/source/os/components/ns-goods-sku-select/ns-goods-sku-select.vue
Executable file
@@ -0,0 +1,520 @@
|
||||
<template>
|
||||
<unipopup ref="dialogRef" type="center" :maskClick="false">
|
||||
<view class="stock-dialog-wrap">
|
||||
<view class="stock-dialog-head">
|
||||
<text>商品选择</text>
|
||||
<text class="iconfont iconguanbi1" @click="$emit('change', false)"></text>
|
||||
</view>
|
||||
<view class="stock-dialog-body">
|
||||
<view class="tree">
|
||||
<scroll-view scroll-y="true" class="list-wrap">
|
||||
<view class="item" :class="{ 'active': option.category_id === '' }" @click="itemClick({ category_id: '', child_num: 0 })">
|
||||
<view class="icon"></view>
|
||||
<view>全部分类</view>
|
||||
</view>
|
||||
<view v-for="(item, key) in goodsCategoryList" :key="key">
|
||||
<view class="item" :class="{ 'active': option.category_id === item.category_id }" @click="itemClick(item)">
|
||||
<view class="icon" :class="{ 'active': activeList.indexOf(item.category_id) != -1 }">
|
||||
<text v-if="item.child_num" class="iconfont iconsanjiao_xia"></text>
|
||||
</view>
|
||||
<view>{{ item.title }}</view>
|
||||
</view>
|
||||
<template v-if="item.child_num">
|
||||
<view v-show="activeList.indexOf(item.category_id) != -1" v-for="(item2, key2) in item.children" :key="key2" class="level">
|
||||
<view class="item" :class="{ 'active': option.category_id === item2.category_id }" @click="itemClick(item2)">
|
||||
<view class="icon" :class="{ 'active': activeList.indexOf(item2.category_id) != -1 }">
|
||||
<text v-if="item2.child_num" class="iconfont iconsanjiao_xia"></text>
|
||||
</view>
|
||||
<view>{{ item2.title }}</view>
|
||||
</view>
|
||||
<template>
|
||||
<view v-show="activeList.indexOf(item2.category_id) != -1" v-for="(item3, key3) in item2.children" :key="key3" class="level">
|
||||
<view class="item item2" @click="itemClick(item3)">
|
||||
<view class="icon"></view>
|
||||
<view>{{ item3.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="stock-dialog-table">
|
||||
<view class="search common-form">
|
||||
<view class="common-form-item">
|
||||
<view class="form-input-inline" v-if="isInstallSupply == 1">
|
||||
<select-lay :zindex="10" :value="option.supplier_id" name="supplier_id" placeholder="请选择供应商" :options="supplierList" @selectitem="selectSupplier"/>
|
||||
</view>
|
||||
<view class="form-input-inline">
|
||||
<select-lay :zindex="10" :value="option.brand_id" name="brand_id" placeholder="请选择品牌" :options="brandList" @selectitem="selectBrand"/>
|
||||
</view>
|
||||
<view class="form-input-inline">
|
||||
<select-lay :zindex="10" :value="option.goods_class" name="goods_class" placeholder="请选择类型" :options="goodsClassList" @selectitem="selectGoodsClass"/>
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<view class="form-input-inline">
|
||||
<input type="text" v-model="option.search_text" @confirm="getStoreGoods" placeholder="请输入名称/编码" class="form-input" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-inline common-btn-wrap">
|
||||
<button type="default" class="screen-btn" @click="getStoreGoods">筛选</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uniDataTable class="goods-table" pk="sku_id" :url="url" :option="option" :cols="cols" :pagesize="8" ref="goodsListTable"></uniDataTable>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="btn">
|
||||
<button type="primary" class="primary-btn submit" @click="submit('close')">选中</button>
|
||||
<button type="primary" class="default-btn" @click="$emit('change', false)">取消</button>
|
||||
</view>
|
||||
</view>
|
||||
</unipopup>
|
||||
</template>
|
||||
<script>
|
||||
import unipopup from '@/components/uni-popup/uni-popup.vue';
|
||||
import uniDataTable from '@/components/uni-data-table/uni-data-table-new.vue';
|
||||
import {getManageGoodsCategory,getGoodsSceen,getSkuListBySelect} from '@/api/goods.js';
|
||||
|
||||
export default {
|
||||
name: 'stockDialog',
|
||||
components: {
|
||||
unipopup,
|
||||
uniDataTable
|
||||
},
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change'
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
default: ()=>{
|
||||
return {}
|
||||
}
|
||||
},
|
||||
goodsClass:{
|
||||
type: Array,
|
||||
default: ()=>{
|
||||
return [1,4,5,6];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
goodsCategoryList: {},
|
||||
activeList: [],//下拉激活
|
||||
option: {
|
||||
category_id: '',
|
||||
search_text: '',
|
||||
is_weigh: 0,
|
||||
page_size: 8,
|
||||
goods_class_all:'',
|
||||
goods_class:'',
|
||||
supplier_id:'',
|
||||
brand_id:'',
|
||||
},
|
||||
checkList: {},
|
||||
cols: [],
|
||||
url: '',
|
||||
goodsClassList: [],
|
||||
isInstallSupply:0,
|
||||
supplierList:[],
|
||||
brandList:[],
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler: function (val) {
|
||||
if (val) {
|
||||
this.$nextTick(() => {
|
||||
this.option = Object.assign(this.option, this.params);
|
||||
if (this.params.temp_store_id && this.params.temp_store_id == '') {
|
||||
delete this.option.temp_store_id
|
||||
}
|
||||
this.$refs.dialogRef.open()
|
||||
})
|
||||
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.option = Object(this.option, {
|
||||
category_id: '',
|
||||
search_text: '',
|
||||
is_weigh: 0,
|
||||
page: 1,
|
||||
page_size: 8,
|
||||
});
|
||||
this.checkList = {};
|
||||
this.$refs.dialogRef.close()
|
||||
})
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.skuConfig();
|
||||
this.getGoodsCategory();
|
||||
this.getScreen();
|
||||
this.getGoodsClassList();
|
||||
},
|
||||
methods: {
|
||||
skuConfig(){
|
||||
this.cols = [{
|
||||
width: 20,
|
||||
align: 'center',
|
||||
checkbox: true,
|
||||
}, {
|
||||
field: 'account_data',
|
||||
width: 50,
|
||||
title: '商品信息',
|
||||
align: 'left',
|
||||
templet: data => {
|
||||
let img = this.$util.img(data.sku_image);
|
||||
let html = `
|
||||
<view class="goods-content">
|
||||
<image class="goods-img" src="${img}" mode="aspectFit"/>
|
||||
<text class="goods-name multi-hidden" title="${data.sku_name}">${data.sku_name}</text>
|
||||
</view>
|
||||
`;
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
field: 'stock',
|
||||
width: 22,
|
||||
title: '库存',
|
||||
align: 'center',
|
||||
templet: data => {
|
||||
return (data.stock || 0);
|
||||
}
|
||||
}, {
|
||||
width: 22,
|
||||
title: '单位',
|
||||
templet: data => {
|
||||
return (data.unit || '件');
|
||||
}
|
||||
}];
|
||||
this.url = '/cashier/storeapi/goods/getSkuListBySelect';
|
||||
},
|
||||
selectGoodsClass(index) {
|
||||
this.option.goods_class = index == -1 ? '' : this.goodsClassList[index].value.toString();
|
||||
this.getStoreGoods();
|
||||
},
|
||||
selectBrand(index){
|
||||
this.option.brand_id = index == -1 ? '' : this.brandList[index].value.toString();
|
||||
this.getStoreGoods();
|
||||
},
|
||||
selectSupplier(index){
|
||||
this.option.supplier_id = index == -1 ? '' : this.supplierList[index].value.toString();
|
||||
this.getStoreGoods();
|
||||
},
|
||||
getGoodsCategory() {
|
||||
getManageGoodsCategory().then(res=>{
|
||||
uni.hideLoading();
|
||||
if (res.data && Object.keys(res.data)) {
|
||||
this.goodsCategoryList = res.data
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
getScreen(){
|
||||
getGoodsSceen().then(res=>{
|
||||
this.isInstallSupply = res.data.is_install_supply;
|
||||
(res.data.supplier_list || []).forEach((item) => {
|
||||
this.supplierList.push({
|
||||
value : item.supplier_id,
|
||||
label : item.title,
|
||||
})
|
||||
})
|
||||
res.data.brand_list.forEach((item) => {
|
||||
this.brandList.push({
|
||||
value : item.brand_id,
|
||||
label : item.brand_name,
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
getGoodsClassList(){
|
||||
let goodsClassList = [
|
||||
{
|
||||
value: this.$util.goodsClassDict.real,
|
||||
label: '实物商品'
|
||||
}, {
|
||||
value: this.$util.goodsClassDict.service,
|
||||
label: '服务项目'
|
||||
}, {
|
||||
value: this.$util.goodsClassDict.card,
|
||||
label: '卡项套餐'
|
||||
}, {
|
||||
value: this.$util.goodsClassDict.weigh,
|
||||
label: '称重商品'
|
||||
}
|
||||
];
|
||||
let goods_class_all = [];
|
||||
goodsClassList.forEach((item)=>{
|
||||
if(this.goodsClass.indexOf(item.value) > -1){
|
||||
this.goodsClassList.push(item);
|
||||
goods_class_all.push(item.value);
|
||||
}
|
||||
})
|
||||
this.option.goods_class_all = goods_class_all.toString();
|
||||
},
|
||||
itemClick(item) {//tree点击
|
||||
this.option.category_id = item.category_id;
|
||||
var index = this.activeList.indexOf(item.category_id);
|
||||
if (item.child_num && index === -1) {
|
||||
this.activeList.push(item.category_id);
|
||||
} else if (item.child_num && index != -1) {
|
||||
this.activeList.splice(index, 1);
|
||||
}
|
||||
this.$forceUpdate();
|
||||
this.getStoreGoods();
|
||||
},
|
||||
getStoreGoods() {//表格查询
|
||||
this.$refs.goodsListTable.load({
|
||||
page: 1
|
||||
});
|
||||
},
|
||||
submit(action) {
|
||||
let res = this.$refs.goodsListTable.getSelectData();
|
||||
if(res.selectedNum == 0){
|
||||
this.$util.showToast({
|
||||
title: '请选择商品'
|
||||
});
|
||||
return false
|
||||
}
|
||||
|
||||
if(res.allSelected){
|
||||
let option = this.$util.deepClone(this.option);
|
||||
option.unselected_sku_ids = Object.keys(res.unselectedData).toString();
|
||||
option.page_size = 0;
|
||||
uni.showLoading({
|
||||
title: '数据获取中'
|
||||
});
|
||||
getSkuListBySelect(option).then(res=>{
|
||||
uni.hideLoading();
|
||||
this.$emit('selectGoods', res.data.list);
|
||||
this.$refs.goodsListTable.clearCheck();
|
||||
if(action == 'close'){
|
||||
this.$emit('change', false);
|
||||
}
|
||||
})
|
||||
}else{
|
||||
this.$emit('selectGoods', Object.values(res.selectedData));
|
||||
this.$refs.goodsListTable.clearCheck();
|
||||
if(action == 'close'){
|
||||
this.$emit('change', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.stock-dialog-wrap {
|
||||
background-color: #fff;
|
||||
border-radius: 0.05rem;
|
||||
width: 100%;
|
||||
height: 75vh;
|
||||
|
||||
|
||||
.stock-dialog-head {
|
||||
padding: 0 0.15rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 0.15rem;
|
||||
height: 0.45rem;
|
||||
border-bottom: 0.01rem solid #e8eaec;
|
||||
|
||||
.iconguanbi1 {
|
||||
font-size: $uni-font-size-lg;
|
||||
}
|
||||
}
|
||||
|
||||
.stock-dialog-body {
|
||||
width: 100%;
|
||||
// height: 7.3rem;
|
||||
height: calc(100% - 0.45rem - 0.58rem);
|
||||
padding: 0.1rem 0.2rem 0 0.2rem;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
|
||||
.tree {
|
||||
width: 1.8rem;
|
||||
// height: 7.1rem;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
border-right: 0.01rem solid #e8eaec;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
flex-grow: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
.list-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
>view {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
view.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
line-height: 0.3rem;
|
||||
min-height: 0.3rem;
|
||||
font-weight: 500;
|
||||
|
||||
&.active {
|
||||
|
||||
.icon,
|
||||
view {
|
||||
color: $primary-color !important;
|
||||
}
|
||||
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 0.2rem;
|
||||
height: 0.3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transform: rotate(-90deg);
|
||||
transition: all ease 0.5s;
|
||||
|
||||
&.active {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.level {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.item {
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
|
||||
.item2 {
|
||||
padding-left: 0.4rem;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.stock-dialog-table {
|
||||
width: 6.6rem;
|
||||
margin-left: 0.2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
.search {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.goods-table /deep/{
|
||||
flex: 1;
|
||||
height: 0;
|
||||
.tbody{
|
||||
height: calc( 100% - 0.5rem - 0.5rem );
|
||||
overflow-y: auto;
|
||||
&::-webkit-scrollbar{
|
||||
width: 0.06rem;
|
||||
height: 0.06rem;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
&::-webkit-scrollbar-button{
|
||||
display: none;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb{
|
||||
border-radius: 0.06rem;
|
||||
box-shadow: inset 0 0 0.06rem rgba(45, 43, 43, 0.45);
|
||||
background-color: #ddd;
|
||||
}
|
||||
&::-webkit-scrollbar-track{
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
border-top: 0.01rem solid #e8eaec;
|
||||
padding: 0.1rem 0.2rem 0.1rem 0.2rem;
|
||||
box-sizing: border-box;
|
||||
height: 0.58rem;
|
||||
|
||||
.default-btn,
|
||||
.primary-btn {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.default-btn {
|
||||
border: 0.01rem solid #e8eaec !important;
|
||||
}
|
||||
.submit{
|
||||
margin-right: 0.15rem;
|
||||
}
|
||||
.default-btn::after {
|
||||
display: none;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.common-form{
|
||||
.common-btn-wrap {
|
||||
margin-left: 0;
|
||||
.screen-btn {
|
||||
margin-right: 0;
|
||||
padding-left:14px;
|
||||
padding-right:14px;
|
||||
}
|
||||
}
|
||||
.common-form-item {
|
||||
margin-bottom: 0.1rem;
|
||||
.form-input-inline {
|
||||
width: 1.3rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .goods-content {
|
||||
display: flex;
|
||||
|
||||
.goods-img {
|
||||
margin-right: 0.1rem;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<view class="ns-record">
|
||||
<view class="title">
|
||||
库存记录
|
||||
<text class="iconfont iconguanbi1" @click="close"></text>
|
||||
</view>
|
||||
<view class="table">
|
||||
<view class="table-th">
|
||||
<view class="table-td" style="width: 15%;">规格名称</view>
|
||||
<view class="table-td" style="width: 12%;">业务类型</view>
|
||||
<view class="table-td" style="width: 14%;">原始数量</view>
|
||||
<view class="table-td" style="width: 14%;">变动数量</view>
|
||||
<view class="table-td" style="width: 14%;">剩余数量</view>
|
||||
<view class="table-td" style="width: 14%;">入库单价</view>
|
||||
<view class="table-td" style="width: 17%;">创建时间</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="table-tb">
|
||||
<view class="table-tr" v-for="(item, index) in list" :key="index">
|
||||
<view class="table-td" style="width: 15%;">{{ item.spec_name ? item.spec_name : item.goods_name }}</view>
|
||||
<view class="table-td" style="width: 12%;">{{ item.name }}</view>
|
||||
<view class="table-td" style="width: 14%;">{{ item.before_store_stock }}</view>
|
||||
<view class="table-td" style="width: 14%;">{{ item.goods_num }}</view>
|
||||
<view class="table-td" style="width: 14%;">{{ item.after_store_stock }}</view>
|
||||
<view class="table-td" style="width: 14%;">{{ item.goods_price }}</view>
|
||||
<view class="table-td" style="width: 17%;">{{ $util.timeFormat(item.create_time) }}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- 分页 -->
|
||||
<view class="pagination">
|
||||
<uni-pagination @change="changePage" :pageSize="page_size" show-icon="true" :total="total" :current="page"/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getStockGoodsRecords} from '@/api/stock.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
page: 1,
|
||||
page_size: 8,
|
||||
list: [],
|
||||
total: 0
|
||||
};
|
||||
},
|
||||
props: {
|
||||
goodsId: {
|
||||
type: Number,
|
||||
default: () => {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getData();
|
||||
},
|
||||
methods: {
|
||||
// 分页发生变化
|
||||
changePage(e) {
|
||||
this.page = e.current;
|
||||
this.getData();
|
||||
},
|
||||
// 获取数据
|
||||
getData() {
|
||||
getStockGoodsRecords({
|
||||
page: this.page,
|
||||
page_size: this.page_size,
|
||||
goods_id: this.goodsId,
|
||||
}).then(res => {
|
||||
if (res.code >= 0) {
|
||||
this.total = res.data.count;
|
||||
this.list = res.data.list.map((item, index) => {
|
||||
let unit = '';
|
||||
if (item.type == 'input') {
|
||||
unit = '+';
|
||||
} else {
|
||||
unit = '-';
|
||||
}
|
||||
item.goods_num = unit + item.goods_num;
|
||||
return item;
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
// 弹窗关闭
|
||||
close() {
|
||||
this.$emit('close');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ns-record {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #ffffff;
|
||||
border-radius: 0.04rem;
|
||||
min-height: 2rem;
|
||||
padding-bottom: 0.4rem;
|
||||
.title {
|
||||
width: 100%;
|
||||
height: 0.5rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
font-size: 0.16rem;
|
||||
line-height: 0.5rem;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
font-weight: bold;
|
||||
.iconguanbi1 {
|
||||
font-size: 0.2rem;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0.15rem;
|
||||
transform: translateY(-50%);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
.table {
|
||||
width: 100%;
|
||||
height: 4rem;
|
||||
padding: 0 0.15rem;
|
||||
box-sizing: border-box;
|
||||
.table-th {
|
||||
width: 100%;
|
||||
height: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: #f7f8fa;
|
||||
padding: 0 0.15rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.table-tb {
|
||||
width: 100%;
|
||||
height: calc(100% - 0.5rem);
|
||||
.table-tr {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
height: 0.5rem;
|
||||
padding: 0 0.15rem;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .uni-date-single {
|
||||
height: 0.3rem;
|
||||
}
|
||||
.table-td {
|
||||
height: 100%;
|
||||
line-height: 0.5rem;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
.pagination {
|
||||
width: 100%;
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
</style>
|
||||
268
addon/cashier/source/os/components/ns-goods-sku/ns-goods-sku.vue
Executable file
268
addon/cashier/source/os/components/ns-goods-sku/ns-goods-sku.vue
Executable file
@@ -0,0 +1,268 @@
|
||||
<template>
|
||||
<view class="ns-record">
|
||||
<view class="title">
|
||||
价格库存
|
||||
<text class="iconfont iconguanbi1" @click="close"></text>
|
||||
</view>
|
||||
<view class="table">
|
||||
<view class="table-th">
|
||||
<view class="table-td" style="min-width: 35%;max-width: 35%;">规格名称</view>
|
||||
<view class="table-td">统一售价</view>
|
||||
<view class="table-td" v-if="isUnifyPrice == 0">独立售价</view>
|
||||
<view class="table-td">库存</view>
|
||||
<view class="table-td" v-if="disabled">限制起送</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="table-tb">
|
||||
<view class="table-tr" v-for="(item, index) in skuList" :key="index">
|
||||
<view class="table-td" style="min-width: 35%;max-width: 35%;">
|
||||
{{ item.spec_name ? item.spec_name : item.goods_name }}</view>
|
||||
<view class="table-td">{{ item.discount_price }}</view>
|
||||
<view class="table-td input-wrap" v-if="isUnifyPrice == 0">
|
||||
<input class="input" v-model="item.store_price" type="digit" />
|
||||
<view class="unit">元</view>
|
||||
</view>
|
||||
<view class="table-td input-wrap" v-if="!disabled">
|
||||
<block v-if="globalStoreInfo.stock_type == 'store'">
|
||||
<input class="input" v-model="item.stock" type="digit" :disabled="disabled" />
|
||||
<view class="unit">{{ item.unit ? item.unit : '件' }}</view>
|
||||
</block>
|
||||
<view v-else>{{ item.stock }}</view>
|
||||
</view>
|
||||
<view class="table-td input-wrap" v-else>
|
||||
<view>{{ item.stock }}</view>
|
||||
</view>
|
||||
<view class="table-td input-wrap" v-if="disabled">
|
||||
<switch @change="changeswitch($event,index)" color="#FA6400" style="transform:scale(0.7)"
|
||||
:checked="item.is_delivery_restrictions == 1" />
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
</view>
|
||||
<view class="pop-bottom"><button class="primary-btn" @click="save()">确定</button></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
editGoods,
|
||||
setGoodsLocalRestrictions
|
||||
} from '@/api/goods.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
goodsSkuList: [],
|
||||
flag: true
|
||||
};
|
||||
},
|
||||
props: {
|
||||
skuList: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
isUnifyPrice: {
|
||||
type: Number,
|
||||
default: () => {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: () => {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
changeswitch(e, index) {
|
||||
this.skuList[index].is_delivery_restrictions = e.detail.value ? 1 : 0
|
||||
},
|
||||
getGoodsSku() {
|
||||
this.goodsSkuList = [];
|
||||
Object.keys(this.skuList).forEach(key => {
|
||||
let data = this.skuList[key];
|
||||
let obj = {}
|
||||
if (this.disabled) {
|
||||
obj.sku_id = data.sku_id
|
||||
obj.is_delivery_restrictions = data.is_delivery_restrictions
|
||||
} else {
|
||||
obj.sku_id = data.sku_id
|
||||
obj.price = data.store_price ? data.store_price : data.discount_price
|
||||
}
|
||||
if (this.globalStoreInfo.stock_type == 'store') {
|
||||
obj.stock = data.stock;
|
||||
}
|
||||
this.goodsSkuList.push(obj);
|
||||
});
|
||||
},
|
||||
save() {
|
||||
this.getGoodsSku();
|
||||
if (!this.flag) return false;
|
||||
this.flag = false;
|
||||
uni.showLoading({
|
||||
title: '请求处理中'
|
||||
});
|
||||
if (this.disabled) {
|
||||
setGoodsLocalRestrictions({
|
||||
goods_sku_list: JSON.stringify(this.goodsSkuList)
|
||||
}).then(res => {
|
||||
uni.hideLoading();
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
this.$root.$refs.goodsListTable.load();
|
||||
this.close();
|
||||
} else {
|
||||
this.flag = true;
|
||||
}
|
||||
})
|
||||
} else {
|
||||
editGoods({
|
||||
goods_sku_list: JSON.stringify(this.goodsSkuList)
|
||||
}).then(res => {
|
||||
uni.hideLoading();
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
this.$root.$refs.goodsListTable.load();
|
||||
this.close();
|
||||
} else {
|
||||
this.flag = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
// 弹窗关闭
|
||||
close() {
|
||||
this.$emit('close');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ns-record {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #ffffff;
|
||||
border-radius: 0.04rem;
|
||||
min-height: 2rem;
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
height: 0.5rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
font-size: 0.16rem;
|
||||
line-height: 0.5rem;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
font-weight: bold;
|
||||
|
||||
.iconguanbi1 {
|
||||
font-size: 0.2rem;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0.15rem;
|
||||
transform: translateY(-50%);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
width: 100%;
|
||||
height: 4rem;
|
||||
padding: 0.15rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
.table-th {
|
||||
width: 100%;
|
||||
height: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: #f7f8fa;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.table-td {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
padding: 0 0.15rem;
|
||||
}
|
||||
|
||||
.table-tb {
|
||||
width: 100%;
|
||||
height: calc(100% - 0.5rem);
|
||||
|
||||
.table-tr {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
height: 0.5rem;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .uni-date-single {
|
||||
height: 0.3rem;
|
||||
}
|
||||
|
||||
.input-wrap {
|
||||
height: 100%;
|
||||
line-height: 0.5rem;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 0.14rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.input {
|
||||
width: 0.7rem;
|
||||
height: 0.35rem;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
padding: 0 0.1rem;
|
||||
border-top-left-radius: 0.03rem;
|
||||
border-bottom-left-radius: 0.03rem;
|
||||
}
|
||||
|
||||
.unit {
|
||||
background-color: #eee;
|
||||
height: 0.35rem;
|
||||
width: 0.35rem;
|
||||
text-align: center;
|
||||
line-height: 0.35rem;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
border-left: 0;
|
||||
border-top-right-radius: 0.03rem;
|
||||
border-bottom-right-radius: 0.03rem;
|
||||
}
|
||||
}
|
||||
|
||||
.save {
|
||||
height: 0.3rem;
|
||||
line-height: 0.3rem;
|
||||
}
|
||||
|
||||
.pop-bottom {
|
||||
padding: 0.1rem 0.2rem;
|
||||
border-top: 0.01rem solid #eee;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
line-height: 0.35rem;
|
||||
height: 0.35rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
828
addon/cashier/source/os/components/ns-goods/index.js
Executable file
828
addon/cashier/source/os/components/ns-goods/index.js
Executable file
@@ -0,0 +1,828 @@
|
||||
var self;
|
||||
|
||||
import {
|
||||
getGoodsList,
|
||||
getGoodsCategory,
|
||||
getServiceCategory,
|
||||
getServiceList,
|
||||
getGoodsSkuList,
|
||||
getElectronicScaleInformation,
|
||||
getGoodsInfoByCode
|
||||
} from '@/api/goods'
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'nsGoods',
|
||||
props: {
|
||||
indexFocus: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: 'goods',
|
||||
serviceCategory: [],
|
||||
serviceCategoryId: 'all',
|
||||
serviceData: {
|
||||
size: 12,
|
||||
index: 1,
|
||||
total: 0,
|
||||
list: []
|
||||
},
|
||||
goodsCategoryId: 'all',
|
||||
goodsCategory: [],
|
||||
goodsData: {
|
||||
size: 30,
|
||||
index: 1,
|
||||
total: 0,
|
||||
list: []
|
||||
},
|
||||
skuInfo: null,
|
||||
allSku: null,
|
||||
searchText: '',
|
||||
itemNum: 3,
|
||||
mediaQueryOb: null,
|
||||
paymentMoney: '',
|
||||
cashierScale: null,
|
||||
actionIndex: 0,
|
||||
inputFocus: false,
|
||||
goodsCategoryShow: false,
|
||||
goodsCategoryIndex: 0,
|
||||
serviceCategoryShow: false,
|
||||
serviceCategoryIndex: 0,
|
||||
scanCode: {
|
||||
code: '',
|
||||
lastTime: 0
|
||||
},
|
||||
isGoodsLoad: false,
|
||||
goodsItems:{},//点击商品后如果是可转换库存商品存储商品数据
|
||||
scanCodeSearch:false,
|
||||
goodsNextPage: true,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
serviceCategoryId: function (nval) {
|
||||
this.serviceData.page = 0;
|
||||
this.serviceData.index = 1;
|
||||
this.$refs.loading.show();
|
||||
this.getService();
|
||||
},
|
||||
goodsCategoryId: function (nval) {
|
||||
this.goodsData.page = 0;
|
||||
this.goodsData.index = 1;
|
||||
this.$refs.goodsLoading.show();
|
||||
this.getGoods();
|
||||
},
|
||||
type: function () {
|
||||
this.searchText = '';
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
goodsSpec() {
|
||||
if (this.allSku && this.skuInfo) {
|
||||
let data = [];
|
||||
if (this.skuInfo.goods_class != 6 || (this.skuInfo.goods_class == 6 && this.skuInfo.goods_spec_format)) {
|
||||
data = this.allSku['sku_id_' + this.skuInfo.sku_id].goods_spec_format;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
...mapGetters(['billingGoodsIds', 'billingGoodsData', 'billingActive', 'billingIsScanTrigger','billingIsShowCashBox'])
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
this.addScanCodeEvent();
|
||||
this.addKeyDownEvent();
|
||||
},
|
||||
mounted() {
|
||||
this.mediaQueryOb = uni.createMediaQueryObserver(this);
|
||||
|
||||
this.mediaQueryOb.observe({maxWidth: 1500}, matches => {
|
||||
if (matches) this.itemNum = 2;
|
||||
});
|
||||
|
||||
this.mediaQueryOb.observe({minWidth: 1501, maxWidth: 1700}, matches => {
|
||||
if (matches) this.itemNum = 3;
|
||||
});
|
||||
|
||||
this.mediaQueryOb.observe({minWidth: 1701}, matches => {
|
||||
if (matches) this.itemNum = 4;
|
||||
});
|
||||
|
||||
document.addEventListener('click', this.isListShow)
|
||||
},
|
||||
beforeDestroy() {
|
||||
document.removeEventListener("click", this.isListShow);
|
||||
},
|
||||
methods: {
|
||||
nextGoodsLiist(){
|
||||
if(!this.goodsNextPage) return;
|
||||
this.goodsData.index ++;
|
||||
this.getGoods();
|
||||
},
|
||||
init() {
|
||||
self = this;
|
||||
this.getServiceCategoryFn();
|
||||
this.getGoodsCategoryFn();
|
||||
this.getService();
|
||||
this.getGoods();
|
||||
},
|
||||
getServiceCategoryFn() {
|
||||
getServiceCategory().then(res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.serviceCategory = res.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
getGoodsCategoryFn() {
|
||||
getGoodsCategory().then(res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.goodsCategory = res.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
getService() {
|
||||
getServiceList({
|
||||
page: this.serviceData.index,
|
||||
page_size: this.serviceData.size,
|
||||
category: this.serviceCategoryId,
|
||||
search_text: this.searchText,
|
||||
status: 1
|
||||
}).then(res => {
|
||||
if (this.$refs.loading) this.$refs.loading.hide();
|
||||
if (res.code == 0) {
|
||||
this.serviceData.total = res.data.count;
|
||||
this.serviceData.list = res.data.list || [];
|
||||
this.searchText = '';
|
||||
}
|
||||
});
|
||||
},
|
||||
getGoods() {
|
||||
this.isGoodsLoad = false;
|
||||
getGoodsList({
|
||||
page: this.goodsData.index,
|
||||
page_size: this.goodsData.size,
|
||||
category: this.goodsCategoryId,
|
||||
search_text: this.searchText,
|
||||
goods_class: '1,6',
|
||||
status: 1,
|
||||
scene:'billing',
|
||||
}).then((res) => {
|
||||
if (this.$refs.goodsLoading) this.$refs.goodsLoading.hide();
|
||||
if (res.code == 0) {
|
||||
this.goodsData.total = res.data.count;
|
||||
// this.goodsData.list = res.data.list || [];
|
||||
res.data.list.forEach(item => {
|
||||
item.adjust = {}; // 存储规格调价
|
||||
});
|
||||
if (this.goodsData.index == 1) this.goodsData.list = []; //如果是第一页需手动制空列表
|
||||
this.goodsData.list.push(...res.data.list);
|
||||
if(res.data.list.length) this.goodsNextPage = true;
|
||||
else this.goodsNextPage = false;
|
||||
if(this.scanCodeSearch) this.searchText = '';
|
||||
this.scanCodeSearch = false;
|
||||
}
|
||||
this.isGoodsLoad = true;
|
||||
})
|
||||
},
|
||||
goodsSelect(data, index) {
|
||||
if (this.type == 'goods' && !data.stock) return;
|
||||
if (index != undefined) this.actionIndex = index;
|
||||
|
||||
if (data.goods_class != 6 && data.adjust && data.adjust['sku_id_' + data.sku_id]) {
|
||||
data.adjust_price = data.adjust['sku_id_' + data.sku_id].adjust_price;
|
||||
data.is_adjust = data.adjust['sku_id_' + data.sku_id].is_adjust;
|
||||
}
|
||||
|
||||
// 满足条件:多规格,称重商品计重模式,编辑数量
|
||||
if (data.goods_spec_format || (data.goods_class == 6 && data.pricing_type == 'weight') || (data.status && data.status == 'edit')) {
|
||||
this.setActive('SelectGoodsSku');
|
||||
getGoodsSkuList(data.goods_id).then(res => {
|
||||
if (res.code == 0) {
|
||||
let obj = {};
|
||||
res.data.forEach(item => {
|
||||
try{
|
||||
item.goods_spec_format = JSON.parse(item.goods_spec_format);
|
||||
}catch(e){
|
||||
item.goods_spec_format = [];
|
||||
}
|
||||
obj['sku_id_' + item.sku_id] = item;
|
||||
});
|
||||
this.allSku = obj;
|
||||
this.skuInfo = obj['sku_id_' + data.sku_id];
|
||||
// 调整价格,称重商品不参与永久调价,每次都是初始原价
|
||||
if (data.goods_class != 6 && data.adjust_price) {
|
||||
this.skuInfo.adjust_price = data.adjust_price; // 使用调价
|
||||
} else {
|
||||
this.skuInfo.adjust_price = data.price; // 未调价,使用原价
|
||||
}
|
||||
|
||||
this.skuInfo.adjust_price = parseFloat(this.skuInfo.adjust_price).toFixed(2);
|
||||
|
||||
this.$set(this.skuInfo, 'status', data.status || '');
|
||||
this.$set(this.skuInfo, 'editKey', data.editKey || '');
|
||||
|
||||
if (data.goods_class != 6) {
|
||||
this.skuInfo.num = data.num || 1; // 默认购买数量为1
|
||||
}
|
||||
|
||||
// 称重商品,计重模式
|
||||
if (data.goods_class == 6 && data.pricing_type == 'weight') {
|
||||
let num = data.num || '';
|
||||
|
||||
if (num) {
|
||||
this.$set(this.skuInfo, 'weigh', num);
|
||||
Object.values(this.allSku).forEach((item, index) => {
|
||||
this.$set(item, 'weigh', num);
|
||||
});
|
||||
}
|
||||
|
||||
// 打开收银秤
|
||||
this.openCashierScale()
|
||||
}
|
||||
|
||||
this.$refs.skuPopup.open();
|
||||
|
||||
setTimeout(() => {
|
||||
this.inputFocus = true;
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.handleSelectGoods(data);
|
||||
this.scanCode = {
|
||||
lastTime: 0,
|
||||
code: ''
|
||||
};
|
||||
this.$store.commit('billing/setActive', 'SelectGoodsAfter'); // 记录页面当前活跃值:选择完商品
|
||||
}
|
||||
},
|
||||
skuSelect(sku_id) {
|
||||
if (!this.skuInfo.status) {
|
||||
this.skuInfo = this.allSku['sku_id_' + sku_id];
|
||||
this.goodsItems.sku_id = sku_id
|
||||
let skuData = this.goodsData.list[this.actionIndex];
|
||||
|
||||
// 调整价格
|
||||
if (skuData.adjust && skuData.adjust['sku_id_' + sku_id]) {
|
||||
this.skuInfo.adjust_price = skuData.adjust['sku_id_' + sku_id].adjust_price;
|
||||
this.skuInfo.is_adjust = skuData.adjust['sku_id_' + sku_id].is_adjust;
|
||||
} else {
|
||||
// 使用原价
|
||||
this.skuInfo.adjust_price = this.skuInfo.price;
|
||||
}
|
||||
this.skuInfo.adjust_price = parseFloat(this.skuInfo.adjust_price).toFixed(2);
|
||||
|
||||
if (this.skuInfo.goods_class != 6) {
|
||||
this.skuInfo.num = this.skuInfo.num || 1; // 默认购买数量为1
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
skuConfirm() {
|
||||
if (!this.skuInfo) return;
|
||||
if (this.skuInfo.stock <= 0) {
|
||||
this.$util.showToast({
|
||||
title: '商品库存不足'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.skuInfo.price.length == 0 || this.skuInfo.adjust_price.length == 0) {
|
||||
this.$util.showToast({
|
||||
title: '请输入单价'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.skuInfo.price < 0 || this.skuInfo.adjust_price < 0) {
|
||||
this.$util.showToast({
|
||||
title: '单价不能小于0'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.skuInfo.goods_class != 6) {
|
||||
if (Number.parseInt(this.skuInfo.num) <= 0 || !/^\d{0,10}$/.test(Number.parseInt(this.skuInfo.num))) {
|
||||
this.$util.showToast({
|
||||
title: '请输入合法的数值,数值要大于零'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.skuInfo.stock < this.skuInfo.num) {
|
||||
this.$util.showToast({
|
||||
title: '商品库存不足'
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.skuInfo.goods_class == 6 && this.skuInfo.pricing_type == 'weight') {
|
||||
if (Number.parseFloat(this.skuInfo.weigh) <= 0 || !/^\d{0,10}(.?\d{0,3})$/.test(Number.parseFloat(this.skuInfo.weigh))) {
|
||||
this.$util.showToast({
|
||||
title: '请输入合法的数值,数值要大于零且小数位不能超过三位'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.skuInfo.stock < this.skuInfo.weigh) {
|
||||
this.$util.showToast({
|
||||
title: '商品库存不足'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.$pos.send('CloseWeigher');
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
this.skuInfo.is_adjust = this.skuInfo.adjust_price != this.skuInfo.price;
|
||||
|
||||
// 设置右侧商品的调价
|
||||
if (!this.goodsData.list[this.actionIndex].adjust['sku_id_' + this.skuInfo.sku_id]) {
|
||||
this.goodsData.list[this.actionIndex].adjust['sku_id_' + this.skuInfo.sku_id] = {};
|
||||
}
|
||||
this.goodsData.list[this.actionIndex].adjust['sku_id_' + this.skuInfo.sku_id].adjust_price = this.skuInfo.adjust_price;
|
||||
this.goodsData.list[this.actionIndex].adjust['sku_id_' + this.skuInfo.sku_id].is_adjust = this.skuInfo.is_adjust;
|
||||
|
||||
this.handleSelectGoods(this.skuInfo);
|
||||
this.scanCode = {
|
||||
lastTime: 0,
|
||||
code: ''
|
||||
};
|
||||
this.$store.commit('billing/setActive', 'SelectGoodsAfter'); // 记录页面当前活跃值:选择完商品
|
||||
this.$refs.skuPopup.close();
|
||||
},
|
||||
search() {
|
||||
switch (this.type) {
|
||||
case 'service':
|
||||
this.serviceData.page = 0;
|
||||
this.serviceData.index = 1;
|
||||
this.$refs.loading.show();
|
||||
this.getService();
|
||||
break;
|
||||
case 'goods':
|
||||
this.goodsData.page = 0;
|
||||
this.goodsData.index = 1;
|
||||
this.$refs.goodsLoading.show();
|
||||
this.getGoods();
|
||||
break;
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
this.mediaQueryOb.disconnect();
|
||||
},
|
||||
switchStoreAfter() {
|
||||
this.serviceCategory = [];
|
||||
this.serviceCategoryId = 'all';
|
||||
this.serviceData = {
|
||||
size: 12,
|
||||
index: 1,
|
||||
page: 0,
|
||||
total: 1,
|
||||
list: []
|
||||
};
|
||||
this.goodsCategoryId = 'all';
|
||||
this.goodsCategory = [];
|
||||
this.goodsData = {
|
||||
size: 30,
|
||||
index: 1,
|
||||
page: 0,
|
||||
total: 1,
|
||||
list: []
|
||||
};
|
||||
this.getServiceCategoryFn();
|
||||
this.getGoodsCategoryFn();
|
||||
this.getService();
|
||||
this.getGoods();
|
||||
},
|
||||
pageChange(e) {
|
||||
if (this.type == 'goods') {
|
||||
this.goodsData.index = e.current;
|
||||
this.getGoods();
|
||||
} else if (this.type == 'service') {
|
||||
this.serviceData.index = e.current;
|
||||
this.getService();
|
||||
}
|
||||
},
|
||||
switchItem(type) {
|
||||
this.type = type;
|
||||
if (this.type == 'goods') {
|
||||
this.goodsData.index = 1;
|
||||
this.getGoods();
|
||||
} else if (this.type == 'service') {
|
||||
this.serviceData.index = 1;
|
||||
this.getService();
|
||||
} else if (this.type == 'money') {
|
||||
// 无码商品
|
||||
this.setActive('UnnumberedGoods');
|
||||
}
|
||||
},
|
||||
keydown(value) {
|
||||
let arr = this.paymentMoney.split('.');
|
||||
if (arr[1]) {
|
||||
if (value == '.' || arr[1].length == 2) return;
|
||||
if (value == '00' && arr[1].length == 1) value = '0';
|
||||
}
|
||||
if (parseFloat(this.paymentMoney + value) > 1000000) {
|
||||
this.$util.showToast({
|
||||
title: '最大不能超过1000000'
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.paymentMoney += value;
|
||||
},
|
||||
deleteCode() {
|
||||
this.paymentMoney = this.paymentMoney.substr(0, this.paymentMoney.length - 1);
|
||||
},
|
||||
paymentMoneyConfirm() {
|
||||
if (!this.paymentMoney.length) {
|
||||
this.$util.showToast({
|
||||
title: '请输入收款金额'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (isNaN(parseFloat(this.paymentMoney)) || !/^(([0-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/.test(parseFloat(this.paymentMoney))) {
|
||||
this.$util.showToast({
|
||||
title: '收款金额格式错误'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.paymentMoney <= 0) {
|
||||
this.$util.showToast({
|
||||
title: '收款金额不能小于等于0'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (parseFloat(this.paymentMoney) > 1000000) {
|
||||
this.$util.showToast({
|
||||
title: '最大不能超过1000000'
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.handleSelectGoods({
|
||||
goods_id: parseInt(new Date().getTime() / 1000),
|
||||
sku_id: parseInt(new Date().getTime() / 1000),
|
||||
num: 1,
|
||||
money: parseFloat(this.paymentMoney)
|
||||
});
|
||||
this.scanCode = {
|
||||
lastTime: 0,
|
||||
code: ''
|
||||
};
|
||||
this.$store.commit('billing/setActive', 'SelectGoodsAfter'); // 记录页面当前活跃值:选择完商品
|
||||
this.paymentMoney = '';
|
||||
},
|
||||
/**
|
||||
* 打开收银秤
|
||||
*/
|
||||
openCashierScale() {
|
||||
if (this.addon.includes('scale')) {
|
||||
if (!this.cashierScale) {
|
||||
getElectronicScaleInformation().then(res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.cashierScale = res.data.config;
|
||||
try {
|
||||
this.$pos.send('OpenWeigher', `OS2X:${this.cashierScale.serialport}:${this.cashierScale.baudrate}`);
|
||||
} catch (e) {
|
||||
this.cashierScale = null
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
try {
|
||||
this.$pos.send('OpenWeigher', `OS2X:${this.cashierScale.serialport}:${this.cashierScale.baudrate}`);
|
||||
} catch (e) {
|
||||
this.cashierScale = null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 去皮
|
||||
*/
|
||||
tare() {
|
||||
this.$pos.send('Tare')
|
||||
},
|
||||
/**
|
||||
* 清零
|
||||
*/
|
||||
zero() {
|
||||
this.$pos.send('Zero');
|
||||
},
|
||||
setActive(key) {
|
||||
this.$store.commit('billing/setActive', key);
|
||||
},
|
||||
paymentMoneyChange(event) {
|
||||
if (this.paymentMoney.length == 0) {
|
||||
// 如果没有输入则结账
|
||||
this.setActive('SelectGoodsAfter')
|
||||
} else {
|
||||
this.setActive('UnnumberedGoods')
|
||||
}
|
||||
},
|
||||
// 商品数量减少
|
||||
dec(data) {
|
||||
if (this.skuInfo) {
|
||||
if (this.skuInfo.num <= 1 && this.skuInfo.stock > 0) {
|
||||
this.skuInfo.num = 1;
|
||||
} else if(this.skuInfo.stock > 0) {
|
||||
this.skuInfo.num--;
|
||||
}
|
||||
this.$forceUpdate();
|
||||
}
|
||||
},
|
||||
// 商品数量增加
|
||||
inc(data) {
|
||||
if (this.skuInfo) {
|
||||
if (this.skuInfo.num >= this.skuInfo.stock && this.skuInfo.stock > 0) {
|
||||
this.skuInfo.num = this.skuInfo.stock;
|
||||
} else if(this.skuInfo.stock > 0){
|
||||
this.skuInfo.num++;
|
||||
}
|
||||
this.$forceUpdate();
|
||||
}
|
||||
},
|
||||
// 打开钱箱
|
||||
openCashBox() {
|
||||
this.$emit('openCashBox')
|
||||
},
|
||||
setGoodsCategoryShow(id, index) {
|
||||
if (!this.goodsCategoryShow) {
|
||||
if (id === 'all') {
|
||||
if (this.goodsCategory.length > 13) {
|
||||
this.goodsCategoryShow = !this.goodsCategoryShow
|
||||
} else {
|
||||
this.goodsCategoryId = id
|
||||
}
|
||||
} else {
|
||||
this.goodsCategoryId = id
|
||||
}
|
||||
} else {
|
||||
this.goodsCategoryId = id;
|
||||
this.goodsCategoryIndex = index;
|
||||
this.goodsCategoryShow = false
|
||||
}
|
||||
},
|
||||
setServiceCategoryShow(id, index) {
|
||||
if (!this.serviceCategoryShow) {
|
||||
if (id === 'all') {
|
||||
if (this.serviceCategory.length > 13) {
|
||||
this.serviceCategoryShow = !this.serviceCategoryShow
|
||||
} else {
|
||||
this.serviceCategoryId = id
|
||||
}
|
||||
|
||||
} else {
|
||||
this.serviceCategoryId = id
|
||||
}
|
||||
} else {
|
||||
this.serviceCategoryId = id;
|
||||
this.serviceCategoryIndex = index;
|
||||
this.serviceCategoryShow = false
|
||||
}
|
||||
},
|
||||
isListShow() {
|
||||
this.goodsCategoryShow = false;
|
||||
this.serviceCategoryShow = false;
|
||||
},
|
||||
// 获取商品信息通过条形码
|
||||
getSkuByCode(code) {
|
||||
if (this.type != 'goods' || this.billingActive == 'ShowMember' || this.billingActive == 'OrderCreate') return;
|
||||
|
||||
code = code.toString().trim();
|
||||
getGoodsInfoByCode(code).then(res => {
|
||||
if (res.code == 0) {
|
||||
if (res.data) {
|
||||
if (res.data.goods_state == 0) {
|
||||
this.$util.showToast({
|
||||
title: '该商品已下架'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (res.data.stock == 0) {
|
||||
this.$util.showToast({
|
||||
title: '该商品库存不足!'
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.handleSelectGoods(res.data);
|
||||
this.scanCode = {
|
||||
lastTime: 0,
|
||||
code: ''
|
||||
};
|
||||
this.$store.commit('billing/setActive', 'SelectGoodsAfter'); // 记录页面当前活跃值:选择完商品
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: '未找到该商品!'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: res.message,
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 处理选中商品数据
|
||||
handleSelectGoods(data) {
|
||||
let key = 'sku_' + data.sku_id;
|
||||
let num = data.num || 1;
|
||||
num = parseInt(num);
|
||||
|
||||
// 项目服务和称重商品每次都是新增,重新定义key
|
||||
if (data.goods_class == 4 || data.goods_class == 6) {
|
||||
if (data.status == 'edit') {
|
||||
// 编辑
|
||||
key = data.editKey;
|
||||
} else {
|
||||
//新增
|
||||
var index = 0;
|
||||
Object.keys(this.billingGoodsData).forEach(k => {
|
||||
if (k.indexOf(key) != -1) {
|
||||
index++;
|
||||
}
|
||||
});
|
||||
key += '_' + index;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 称重商品,计价方式:计重
|
||||
if (data.goods_class == 6 && data.pricing_type == 'weight') num = Number.parseFloat(data.weigh);
|
||||
|
||||
let _billingGoodsData = this.$util.deepClone(this.billingGoodsData);
|
||||
|
||||
// 已加入清单,追加数量
|
||||
if (_billingGoodsData[key]) {
|
||||
_billingGoodsData[key].num += num;
|
||||
} else {
|
||||
// 第一次加入清单,设置数据
|
||||
_billingGoodsData[key] = this.$util.deepClone(data);
|
||||
_billingGoodsData[key].num = num;
|
||||
}
|
||||
|
||||
// 编辑商品数量
|
||||
if (data.status && data.status == 'edit') {
|
||||
_billingGoodsData[key].num = num;
|
||||
}
|
||||
|
||||
// 称重商品每次覆盖数量
|
||||
if (data.goods_class == 6 && data.pricing_type == 'weight') {
|
||||
_billingGoodsData[key].num = parseFloat(_billingGoodsData[key].num.toFixed(3))
|
||||
}
|
||||
|
||||
// 调整单价
|
||||
if (data.adjust_price) {
|
||||
_billingGoodsData[key].price = parseFloat(data.adjust_price);
|
||||
_billingGoodsData[key].adjust_price = parseFloat(data.adjust_price);
|
||||
}
|
||||
|
||||
_billingGoodsData[key].is_adjust = data.is_adjust || false;
|
||||
|
||||
this.$store.commit('billing/setGoodsData', _billingGoodsData);
|
||||
|
||||
},
|
||||
/**
|
||||
* 添加扫码监听事件
|
||||
*/
|
||||
addScanCodeEvent() {
|
||||
// #ifdef APP-PLUS
|
||||
plus.key.addEventListener('keyup', this.listenerScanCode, true);
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
window.addEventListener('keypress', this.listenerScanCode, true);
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 移除扫码监听事件
|
||||
*/
|
||||
removeScanCodeEvent() {
|
||||
// #ifdef APP-PLUS
|
||||
plus.key.removeEventListener('keyup', this.listenerScanCode, true);
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
window.removeEventListener('keypress', this.listenerScanCode, true);
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 监听扫码事件
|
||||
* @param {Object} e
|
||||
*/
|
||||
listenerScanCode(e) {
|
||||
const clearBarCode = () => {
|
||||
this.scanCode = {
|
||||
lastTime: 0,
|
||||
code: ''
|
||||
};
|
||||
this.$store.commit('billing/setIsScanTrigger', false);
|
||||
};
|
||||
|
||||
// #ifdef H5
|
||||
var currCode = e.keyCode || e.which || e.charCode;
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
const keyArr = {
|
||||
'keycode_7': 0,
|
||||
'keycode_8': 1,
|
||||
'keycode_9': 2,
|
||||
'keycode_10': 3,
|
||||
'keycode_11': 4,
|
||||
'keycode_12': 5,
|
||||
'keycode_13': 6,
|
||||
'keycode_14': 7,
|
||||
'keycode_15': 8,
|
||||
'keycode_16': 9
|
||||
};
|
||||
var currCode = keyArr['keycode_' + e.keyCode] || '';
|
||||
// #endif
|
||||
|
||||
var currTime = new Date().getTime();
|
||||
if (this.scanCode.lastTime > 0) {
|
||||
if (currTime - this.scanCode.lastTime <= 100) {
|
||||
this.scanCode.code += String.fromCharCode(currCode);
|
||||
this.$store.commit('billing/setIsScanTrigger', true);
|
||||
} else if (currTime - this.scanCode.lastTime > 500) {
|
||||
// 输入间隔500毫秒清空
|
||||
clearBarCode();
|
||||
}
|
||||
} else {
|
||||
this.scanCode.code = String.fromCharCode(currCode);
|
||||
}
|
||||
this.scanCode.lastTime = currTime;
|
||||
|
||||
// #ifdef H5
|
||||
var code = 13;
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
var code = 66;
|
||||
// #endif
|
||||
|
||||
if (currCode == code) {
|
||||
|
||||
// 扫码枪
|
||||
if (this.scanCode.code && this.scanCode.code.length >= 8) {
|
||||
this.scanCodeSearch = true;
|
||||
this.getSkuByCode(this.scanCode.code);
|
||||
this.$store.commit('billing/setIsScanTrigger', true);
|
||||
}
|
||||
|
||||
// 回车输入后清空
|
||||
clearBarCode();
|
||||
}
|
||||
|
||||
},
|
||||
/**
|
||||
* 添加键盘监听事件
|
||||
*/
|
||||
addKeyDownEvent() {
|
||||
// #ifdef H5
|
||||
window.addEventListener("keydown", this.listenerKeyDown, true);
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 移除键盘监听事件
|
||||
*/
|
||||
removeKeyDownEvent() {
|
||||
// #ifdef H5
|
||||
window.removeEventListener("keydown", this.listenerKeyDown, true);
|
||||
// #endif
|
||||
},
|
||||
// 监听键盘按下事件
|
||||
listenerKeyDown(e) {
|
||||
var code = e.code;
|
||||
|
||||
if (this.billingActive == 'SelectGoodsSku') {
|
||||
|
||||
// 打开商品规格项弹出框
|
||||
if (code == 'Enter' || code == 'NumpadEnter') {
|
||||
this.skuConfirm();
|
||||
}
|
||||
|
||||
} else if (this.billingActive == 'UnnumberedGoods') {
|
||||
// 无码商品
|
||||
|
||||
if (code == 'Enter' || code == 'NumpadEnter') {
|
||||
|
||||
if (!this.billingIsScanTrigger) this.paymentMoneyConfirm();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
/**
|
||||
* 监听重量变化
|
||||
* @param {Object} text
|
||||
*/
|
||||
window.WEIGHER_DATA_CALLBACK = function (text) {
|
||||
let data = text.split(':');
|
||||
self.$set(self.skuInfo, 'weigh', data[0] != '-' ? data[0] : '')
|
||||
};
|
||||
628
addon/cashier/source/os/components/ns-goods/index.scss
Executable file
628
addon/cashier/source/os/components/ns-goods/index.scss
Executable file
@@ -0,0 +1,628 @@
|
||||
.container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.header-action {
|
||||
padding: 0.22rem 0.24rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-radius: 0.04rem;
|
||||
margin-bottom: 0.2rem;
|
||||
height: 0.88rem;
|
||||
|
||||
.header-action-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 0.44rem;
|
||||
background-color: var(--primary-color-light-9);
|
||||
border-radius: 0.22rem;
|
||||
|
||||
view {
|
||||
min-width: 1.02rem;
|
||||
height: 0.44rem;
|
||||
line-height: 0.44rem;
|
||||
text-align: center;
|
||||
font-size: 0.14rem;
|
||||
border-left-width: 0;
|
||||
transition: all 0.3s;
|
||||
cursor: pointer;
|
||||
border-radius: 0.22rem;
|
||||
color: $primary-color;
|
||||
|
||||
&.active {
|
||||
color: #fff;
|
||||
background-color: $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-action-center {
|
||||
margin-left: 0.29rem;
|
||||
|
||||
.left {
|
||||
margin-right: 0.24rem;
|
||||
}
|
||||
|
||||
view {
|
||||
min-width: 1.02rem;
|
||||
height: 0.44rem;
|
||||
line-height: 0.44rem;
|
||||
text-align: center;
|
||||
font-size: 0.14rem;
|
||||
border-left-width: 0;
|
||||
transition: all 0.3s;
|
||||
cursor: pointer;
|
||||
border-radius: 0.22rem;
|
||||
color: #fff;
|
||||
background-color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.header-action-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 0.4rem;
|
||||
border-radius: 0.2rem;
|
||||
border: 0.01rem solid #CCCCCC;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
|
||||
input {
|
||||
background: #ffffff;
|
||||
border-radius: 0.02rem;
|
||||
height: 0.36rem;
|
||||
padding-left: 0.24rem;
|
||||
font-size: 0.14rem;
|
||||
width: 2.80rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
width: 0.36rem;
|
||||
height: 0.36rem;
|
||||
background: #ffffff;
|
||||
border-radius: 0.02rem;
|
||||
border-left: 0;
|
||||
text-align: center;
|
||||
line-height: 0.36rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
height: calc(100% - 1.08rem);
|
||||
transform: rotate(0);
|
||||
display: flex;
|
||||
|
||||
.table-pages {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 1.72rem;
|
||||
right: 0;
|
||||
background-color: #fff;
|
||||
padding: 0.24rem 0.20rem;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.type-switch {
|
||||
width: 1.52rem;
|
||||
margin-right: 0.2rem;
|
||||
padding: 0.24rem 0;
|
||||
font-size: 0.14rem;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0.04rem;
|
||||
position: relative;
|
||||
|
||||
.list {
|
||||
height: calc(100% - 0.6rem) !important;
|
||||
}
|
||||
|
||||
.list-all {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 99;
|
||||
box-shadow: 0.04rem 0 0.12rem 0 rgba(0, 0, 0, 0.04);
|
||||
transition: width 0.3s;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
border-radius: 0.04rem;
|
||||
|
||||
&.show {
|
||||
width: 4.08rem;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.center {
|
||||
width: 4.08rem;
|
||||
height: 100%;
|
||||
padding: 0.24rem;
|
||||
overflow-y: auto;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.switch-item {
|
||||
margin-right: 0.24rem;
|
||||
width: 1.04rem;
|
||||
&:nth-child(2n+2){
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/deep/ .uni-scroll-view-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// align-items: center;
|
||||
}
|
||||
|
||||
// /deep/ .uni-scroll-view {
|
||||
// width: 1.1rem !important;
|
||||
// }
|
||||
|
||||
.switch-item {
|
||||
width: 1.04rem;
|
||||
border-radius: 0.04rem;
|
||||
padding: 0.1rem 0.1rem;
|
||||
font-size: 0.14rem;
|
||||
text-align: center;
|
||||
margin-left: 0.24rem;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
border: 0.01rem solid #DCDEE2;
|
||||
.item-title{
|
||||
white-space: normal;
|
||||
max-height: 0.4rem;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
.all-category{
|
||||
.switch-item {
|
||||
height: 0.4rem;
|
||||
width: 1.04rem;
|
||||
border-radius: 0.04rem;
|
||||
padding: 0 0.1rem;
|
||||
font-size: 0.14rem;
|
||||
text-align: center;
|
||||
line-height: 0.4rem;
|
||||
margin-left: 0.24rem;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border: 0.01rem solid #DCDEE2;
|
||||
}
|
||||
}
|
||||
.switch-item.active {
|
||||
background-color: $primary-color;
|
||||
border-color: $primary-color;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.switch-item:not(:last-child) {
|
||||
margin-bottom: 0.20rem;
|
||||
}
|
||||
}
|
||||
|
||||
.list-wrap {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
padding-bottom: 0.78rem;
|
||||
}
|
||||
|
||||
.money-pages {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.money-wrap {
|
||||
background: #fff;
|
||||
border-radius: 0.05rem;
|
||||
padding-top: 0.3rem;
|
||||
|
||||
.head {
|
||||
height: 0.6rem;
|
||||
line-height: 0.6rem;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
|
||||
text {
|
||||
font-size: 0.16rem;
|
||||
}
|
||||
|
||||
.iconguanbi1 {
|
||||
position: absolute;
|
||||
right: 0.15rem;
|
||||
font-size: 0.22rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
display: flex;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
height: 0.6rem;
|
||||
align-items: center;
|
||||
margin: 0 0.2rem;
|
||||
padding: 0 0.15rem;
|
||||
|
||||
.unit {
|
||||
font-size: 0.25rem;
|
||||
}
|
||||
|
||||
.money {
|
||||
margin-left: 0.05rem;
|
||||
font-size: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.keyboard-wrap {
|
||||
width: 4rem;
|
||||
padding: 0 0.2rem 0.3rem 0.2rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
width: calc(100% + 0.12rem);
|
||||
|
||||
.table-item {
|
||||
border: 0.01rem solid #fff;
|
||||
box-sizing: border-box;
|
||||
padding: 0.1rem 0.18rem 0.1rem 0.1rem;
|
||||
background-color: #fff;
|
||||
margin-bottom: 0.12rem;
|
||||
margin-right: 0.12rem;
|
||||
cursor: pointer;
|
||||
transition: border-color, background-color 0.3s;
|
||||
position: relative;
|
||||
border-radius: 0.04rem;
|
||||
&.item-mum-2{
|
||||
width: calc((100% - 0.25rem) / 2);
|
||||
}
|
||||
&.item-mum-3{
|
||||
width: calc((100% - 0.37rem) / 3);
|
||||
}
|
||||
&.item-mum-4{
|
||||
width: calc((100% - 0.49rem) / 4);
|
||||
}
|
||||
&:focus{
|
||||
outline: none;
|
||||
}
|
||||
.item-other {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-left: 0.1rem;
|
||||
|
||||
}
|
||||
|
||||
.item-img {
|
||||
width: 0.9rem;
|
||||
height: 0.9rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
-ms-flex-negative: 0;
|
||||
-webkit-flex-shrink: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
border-radius: 0.03rem;
|
||||
}
|
||||
}
|
||||
|
||||
.item-name {
|
||||
height: 0.4rem;
|
||||
line-height: 0.2rem;
|
||||
max-width: 1.58rem;
|
||||
margin-bottom: 0.05rem;
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.item-info {
|
||||
cursor: pointer;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
||||
.item-time {
|
||||
font-size: 0.12rem;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.item-money {
|
||||
font-size: 0.14rem;
|
||||
color: $primary-color;
|
||||
height: 0.19rem;
|
||||
line-height: 0.19rem;
|
||||
}
|
||||
|
||||
.item-stock {
|
||||
height: 0.17rem;
|
||||
font-size: 0.12rem;
|
||||
color: #808695;
|
||||
line-height: 0.17rem;
|
||||
}
|
||||
}
|
||||
|
||||
.no-stock {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
cursor: not-allowed;
|
||||
|
||||
image {
|
||||
height: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.table-item.yes-stock {
|
||||
&:hover {
|
||||
background-color: var(--primary-color-light-9);
|
||||
border-color: $primary-color;
|
||||
}
|
||||
|
||||
&.focus,
|
||||
&:focus {
|
||||
background-color: var(--primary-color-light-9);
|
||||
border-color: $primary-color;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: $primary-color;
|
||||
background-color: $primary-color;
|
||||
color: #fff;
|
||||
|
||||
.item-time,
|
||||
.item-money,
|
||||
.item-stock {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sku-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 7rem;
|
||||
height: 4rem;
|
||||
background-color: #fff;
|
||||
border-radius: 0.04rem;
|
||||
box-shadow: 0 0.01rem 0.12rem 0 rgba(0, 0, 0, 0.1);
|
||||
|
||||
.header,
|
||||
.footer {
|
||||
height: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
position: relative;
|
||||
|
||||
.title {
|
||||
font-size: 0.16rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
right: 0.15rem;
|
||||
font-size: 0.2rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
flex: 1;
|
||||
padding: 0.15rem;
|
||||
|
||||
scroll-view {
|
||||
height: 2.55rem;
|
||||
}
|
||||
}
|
||||
|
||||
.spec {
|
||||
line-height: 0.35rem;
|
||||
font-weight: bold;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
.spec-value {
|
||||
.value-item {
|
||||
display: inline-block;
|
||||
height: 0.3rem;
|
||||
line-height: 0.3rem;
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
margin: 0.05rem 0.1rem 0 0;
|
||||
padding: 0 0.1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
border-radius: 0.04rem;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
background: var(--primary-color-light-9);
|
||||
border-color: $primary-color;
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
color: #999;
|
||||
cursor: not-allowed;
|
||||
background: #f7f7f7;
|
||||
border-color: #f7f7f7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.spec-value-form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.spec-value-input {
|
||||
margin-right: 0.05rem;
|
||||
border-width: 0.01rem;
|
||||
border-style: solid;
|
||||
background-color: #fff;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
padding-left: 0.1rem;
|
||||
height: 0.38rem;
|
||||
line-height: 0.38rem;
|
||||
font-size: 0.14rem;
|
||||
border-color: #e6e6e6;
|
||||
border-radius: 0.02rem;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.num-dec {
|
||||
width: 0.25rem;
|
||||
height: 0.25rem;
|
||||
background: #e6e6e6;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
border-radius: 30%;
|
||||
text-align: center;
|
||||
line-height: 0.23rem;
|
||||
font-size: 0.25rem;
|
||||
margin-right: 0.1rem;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.num-inc {
|
||||
width: 0.25rem;
|
||||
height: 0.25rem;
|
||||
background: $primary-color;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
border-radius: 30%;
|
||||
text-align: center;
|
||||
line-height: 0.23rem;
|
||||
font-size: 0.25rem;
|
||||
margin-left: 0.1rem;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.scale-action {
|
||||
button {
|
||||
width: .8rem;
|
||||
margin: .15rem .15rem 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-info {
|
||||
display: flex;
|
||||
|
||||
.image {
|
||||
width: 0.7rem;
|
||||
height: 0.7rem;
|
||||
margin-right: 0.1rem;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.price {
|
||||
line-height: 1;
|
||||
margin-top: 0.05rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
border: 0;
|
||||
height: 0.6rem;
|
||||
|
||||
button {
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding-top: 1.2rem;
|
||||
|
||||
image {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.tips {
|
||||
color: #999;
|
||||
margin-top: 0.15rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 450px) and (max-width: 950px) {
|
||||
.type-switch .list-all.show {
|
||||
width: 2.78rem;
|
||||
.center{
|
||||
width: 2.78rem;
|
||||
.switch-item:nth-child(2n+2) {
|
||||
margin-right: 0;
|
||||
}
|
||||
.switch-item:nth-child(3n+3) {
|
||||
margin-right: 0.24rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1201px) and (max-width: 1900px) {
|
||||
.type-switch .list-all.show {
|
||||
width: 6.6rem;
|
||||
.center{
|
||||
width: 6.6rem;
|
||||
.switch-item:nth-child(5n+5) {
|
||||
margin-right: 0;
|
||||
}
|
||||
.switch-item:nth-child(3n+3) {
|
||||
margin-right: 0.24rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
239
addon/cashier/source/os/components/ns-goods/ns-goods.vue
Executable file
239
addon/cashier/source/os/components/ns-goods/ns-goods.vue
Executable file
@@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<view class="container goods-container">
|
||||
<view class="header-action common-wrap">
|
||||
<view class="flex items-center">
|
||||
<view class="header-action-left">
|
||||
<view class="flex-1" :class="{ active: type == 'goods' }" @click="switchItem('goods')">商品</view>
|
||||
<view class="flex-1" :class="{ active: type == 'service' }" @click="switchItem('service')">项目</view>
|
||||
<view class="flex-1" :class="{ active: type == 'money' }" @click="switchItem('money')">无码商品</view>
|
||||
</view>
|
||||
<view class="header-action-center flex" v-if="billingIsShowCashBox">
|
||||
<view class="flex-1" @click="openCashBox()">打开钱箱</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="header-action-right">
|
||||
<input placeholder="请输入商品/项目名称/编码" placeholder-style="font-size:0.14rem;color:#ACACAC;" v-model="searchText" @focus="setActive('inputSearchText')" @blur="setActive('')" @confirm="search" />
|
||||
<view class="search-btn" @click="search">
|
||||
<text class="iconfont icon31sousuo"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
<view class="type-switch common-wrap flex-shrink-0 flex uni-column" v-if="serviceCategory.length && type == 'service'">
|
||||
<view class="switch-item flex-shrink-0" :class="{ active: serviceCategoryId == 'all' }" @click.stop="setServiceCategoryShow('all',0)">所有分类</view>
|
||||
<scroll-view scroll-y="true" :show-scrollbar="false" :scroll-into-view="'serviceCategory-' + serviceCategoryIndex" class="list flex-shrink-0 common-scrollbar">
|
||||
<view :id="'serviceCategory-' + index" class="switch-item flex-shrink-0" :class="{ active: serviceCategoryId == item.category_id }" v-for="(item, index) in serviceCategory" :key="index" @click.stop="setServiceCategoryShow(item.category_id,index)">
|
||||
<view class="item-title">{{ item.category_name }}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view v-if="serviceCategory.length > 13" class="list-all common-wrap" :class="{ 'show': serviceCategoryShow }" @click.stop="() => { return false }">
|
||||
<view class="all-category center flex content-start">
|
||||
<view class="switch-item flex-shrink-0" :class="{ active: serviceCategoryId == 'all' }" @click="setServiceCategoryShow('all', 0)">所有分类</view>
|
||||
<view class="switch-item flex-shrink-0" :class="{ active: serviceCategoryId == item.category_id }" v-for="(item, index) in serviceCategory" :key="index" @click="setServiceCategoryShow(item.category_id, index)">
|
||||
<view class="item-title">{{ item.category_name }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="type-switch common-wrap flex-shrink-0 flex uni-column" v-if="goodsCategory.length && type == 'goods'">
|
||||
<view class="switch-item flex-shrink-0" :class="{ active: goodsCategoryId == 'all' }" @click.stop.prevent="setGoodsCategoryShow('all',0)">所有分类</view>
|
||||
<scroll-view scroll-y="true" :show-scrollbar="false" :scroll-into-view="'goodsCategory-' + goodsCategoryIndex" class="list flex-shrink-0 common-scrollbar" v-show="goodsCategory.length && type == 'goods'">
|
||||
<view :id="'goodsCategory-' + index" class="switch-item flex-shrink-0" :class="{ active: goodsCategoryId == item.category_id }" v-for="(item, index) in goodsCategory" :key="index" @click.stop="setGoodsCategoryShow(item.category_id,index)">
|
||||
<view class="item-title">{{ item.category_name }}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view v-if="goodsCategory.length > 13" class="list-all common-wrap" :class="{ 'show': goodsCategoryShow }" @click.stop="() => { return false }">
|
||||
<view class="all-category center flex content-start">
|
||||
<view class="switch-item flex-shrink-0" :class="{ active: goodsCategoryId == 'all' }" @click="setGoodsCategoryShow('all')">所有分类</view>
|
||||
<view class="switch-item flex-shrink-0" :class="{ active: goodsCategoryId == item.category_id }" v-for="(item, index) in goodsCategory" :key="index" @click="setGoodsCategoryShow(item.category_id, index)">
|
||||
<view class="item-title">{{ item.category_name }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="list-wrap goods" v-show="type == 'goods'" @scrolltolower="nextGoodsLiist">
|
||||
<view class="table-list" v-show="goodsData.list.length" data-focus="true">
|
||||
<view class="table-item goods-select-focus goods-focus"
|
||||
:class="{ 'yes-stock': item.stock>0, 'item-mum-2': itemNum == 2, 'item-mum-3': itemNum == 3, 'item-mum-4': itemNum == 4, active: billingGoodsIds.indexOf(item.goods_id) != -1, focus: indexFocus == index }"
|
||||
v-for="(item, index) in goodsData.list" :key="index" @click="goodsSelect(item, index)" tabindex="0" :data-tab-index="index">
|
||||
|
||||
<view class="item-info">
|
||||
<view class="item-img">
|
||||
<image v-if="item.goods_image == '@/static/goods/goods.png'" src="@/static/goods/goods.png" mode="widthFix"/>
|
||||
<image v-else :src="$util.img(item.goods_image.split(',')[0], { size: 'small' })" @error="item.goods_image = '@/static/goods/goods.png'" mode="widthFix"/>
|
||||
</view>
|
||||
<view class="item-other flex-1">
|
||||
<view class="item-name multi-hidden">{{ item.goods_name }}</view>
|
||||
<view class="w-full flex justify-between items-center self-end">
|
||||
<view class="item-money">¥{{ item.price | moneyFormat }}</view>
|
||||
<view class="item-stock">库存:{{ item.stock }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="no-stock" v-if="item.stock <= 0">
|
||||
<image src="@/static/stock/stock_empty.png" mode="heightFix"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty" v-show="isGoodsLoad && !goodsData.list.length">
|
||||
<image src="@/static/goods/goods_empty.png" mode="widthFix"/>
|
||||
<view class="tips">暂无商品</view>
|
||||
</view>
|
||||
<ns-loading :layer-background="{ background: 'rgba(255,255,255,.6)' }" :default-show="false" ref="goodsLoading"></ns-loading>
|
||||
</scroll-view>
|
||||
|
||||
<scroll-view scroll-y="true" class="list-wrap service" v-show="type == 'service'">
|
||||
<view class="table-list" v-show="serviceData.list.length">
|
||||
|
||||
<view class="table-item goods-select-focus service-focus"
|
||||
:class="{ 'yes-stock': item.stock > 0, 'item-mum-2': itemNum == 2, 'item-mum-3': itemNum == 3, 'item-mum-4': itemNum == 4, active: billingGoodsIds.indexOf(item.goods_id) != -1, focus: indexFocus == index }"
|
||||
v-for="(item, index) in serviceData.list" :key="index" @click="goodsSelect(item, index)" tabindex="0" :data-tab-index="index">
|
||||
|
||||
<view class="item-info">
|
||||
<view class="item-img">
|
||||
<image v-if="item.goods_image == '@/static/goods/goods.png'" src="@/static/goods/goods.png" mode="widthFix"/>
|
||||
<image v-else :src="$util.img(item.goods_image.split(',')[0], { size: 'small' })" @error="item.goods_image = '@/static/goods/goods.png'" mode="widthFix"/>
|
||||
</view>
|
||||
<view class="item-other">
|
||||
<view class="item-name multi-hidden">{{ item.goods_name }}</view>
|
||||
<view class="w-full flex justify-between items-center self-end">
|
||||
<view class="item-money">¥{{ item.price | moneyFormat }}</view>
|
||||
<view class="item-time" v-if="item.service_length">时长:{{ item.service_length }}分钟</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="no-stock" v-if="item.stock <= 0">
|
||||
<image src="@/static/stock/stock_empty.png" mode="heightFix"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty" v-show="!serviceData.list.length">
|
||||
<image src="@/static/goods/goods_empty.png" mode="widthFix"/>
|
||||
<view class="tips">暂无商品</view>
|
||||
</view>
|
||||
<ns-loading :layer-background="{ background: 'rgba(255,255,255,.6)' }" :default-show="false" ref="loading"></ns-loading>
|
||||
</scroll-view>
|
||||
|
||||
<view class="table-pages" v-show="type == 'service' && serviceData.list.length">
|
||||
<uni-pagination :total="serviceData.total" :showIcon="true" @change="pageChange" :pageSize="serviceData.size" :value="serviceData.index" />
|
||||
</view>
|
||||
<!-- <view class="table-pages" v-show="type == 'goods' && goodsData.list.length">
|
||||
<uni-pagination :total="goodsData.total" :showIcon="true" @change="pageChange" :pageSize="goodsData.size" :value="goodsData.index" />
|
||||
</view> -->
|
||||
|
||||
<view class="money-pages" v-show="type == 'money'">
|
||||
<view class="money-wrap">
|
||||
<view class="content-wrap">
|
||||
<view class="unit">¥</view>
|
||||
<input type="text" class="money" v-model="paymentMoney" @input="paymentMoneyChange" />
|
||||
</view>
|
||||
<view class="keyboard-wrap">
|
||||
<view class="num-wrap">
|
||||
<view class="key-item" @click="keydown('1')">1</view>
|
||||
<view class="key-item" @click="keydown('2')">2</view>
|
||||
<view class="key-item" @click="keydown('3')">3</view>
|
||||
<view class="key-item" @click="keydown('4')">4</view>
|
||||
<view class="key-item" @click="keydown('5')">5</view>
|
||||
<view class="key-item" @click="keydown('6')">6</view>
|
||||
<view class="key-item" @click="keydown('7')">7</view>
|
||||
<view class="key-item" @click="keydown('8')">8</view>
|
||||
<view class="key-item" @click="keydown('9')">9</view>
|
||||
<view class="key-item" @click="keydown('00')">00</view>
|
||||
<view class="key-item" @click="keydown('0')">0</view>
|
||||
<view class="key-item" @click="keydown('.')">.</view>
|
||||
</view>
|
||||
<view class="action-wrap">
|
||||
<view class="delete" @click="deleteCode">删除</view>
|
||||
<view class="delete" @click="paymentMoney = ''">清空</view>
|
||||
<view class="confirm" @click="paymentMoneyConfirm">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<uni-popup ref="skuPopup" type="center">
|
||||
<view class="sku-wrap">
|
||||
<view class="header">
|
||||
<text class="title">{{ skuInfo && skuInfo.status == 'edit' ? '调整' : '选择' }}</text>
|
||||
<text class="iconfont iconguanbi1" @click="$refs.skuPopup.close()"></text>
|
||||
</view>
|
||||
<view class="body">
|
||||
<scroll-view scroll-y="true">
|
||||
<view class="goods-info" v-if="skuInfo">
|
||||
<view class="image">
|
||||
<image v-if="skuInfo.sku_image == '@/static/goods/goods.png'" src="@/static/goods/goods.png" mode="widthFix"/>
|
||||
<image v-else :src="$util.img(skuInfo.sku_image, { size: 'small' })" @error="skuInfo.sku_image = '@/static/goods/goods.png'" mode="widthFix"/>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="multi-hidden">{{ skuInfo.goods_name }}</view>
|
||||
<view class="price">¥{{ skuInfo.adjust_price }} / {{ skuInfo.unit ? skuInfo.unit : '件' }}</view>
|
||||
<view>库存:{{ skuInfo.stock }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-for="(item, index) in goodsSpec" :key="index">
|
||||
<view class="spec">{{ item.spec_name }}</view>
|
||||
<view class="spec-value">
|
||||
<view class="value-item" :class="{ active: spec.selected, disabled: (!spec.selected && skuInfo.status == 'edit') }" v-for="(spec, sindex) in item.value" :key="sindex" @click="skuSelect(spec.sku_id)">
|
||||
{{ spec.spec_value_name }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<block v-if="skuInfo">
|
||||
<view class="spec">单价</view>
|
||||
<view class="spec-value spec-value-form">
|
||||
<input type="text" class="spec-value-input" v-model="skuInfo.adjust_price" placeholder="请输入单价" />
|
||||
<text>元</text>
|
||||
</view>
|
||||
<block v-if="skuInfo.goods_class != 6">
|
||||
<view class="spec">数量</view>
|
||||
<view class="spec-value spec-value-form">
|
||||
<view class="num-dec" @click.stop="dec">-</view>
|
||||
<input type="text" class="spec-value-input" v-model="skuInfo.num" placeholder="请输入数量" :focus="inputFocus" @focus="inputFocus = true" @blur="inputFocus = false" />
|
||||
<view class="num-inc" @click.stop="inc">+</view>
|
||||
<text>{{ skuInfo.unit }}</text>
|
||||
</view>
|
||||
</block>
|
||||
<block v-if="skuInfo.goods_class == 6 && skuInfo.pricing_type == 'weight'">
|
||||
<view class="info">
|
||||
<view class="spec">剩余库存</view>
|
||||
<view>{{ skuInfo.stock }}<text>{{ skuInfo.unit }}</text></view>
|
||||
</view>
|
||||
<view>
|
||||
<view class="spec">称重</view>
|
||||
<view class="spec-value spec-value-form">
|
||||
<input type="text" class="spec-value-input" v-model="skuInfo.weigh" placeholder="请输入重量" :focus="inputFocus" @focus="inputFocus = true" @blur="inputFocus = false" />
|
||||
<text>{{ skuInfo.unit }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex scale-action" v-if="addon.includes('scale') && cashierScale">
|
||||
<button type="primary" class="default-btn" plain @click="zero">归零</button>
|
||||
<button type="primary" class="default-btn" plain @click="tare">去皮</button>
|
||||
</view>
|
||||
</block>
|
||||
</block>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="footer">
|
||||
<button type="default" class="primary-btn" @click="skuConfirm" :disabled="skuInfo && skuInfo.stock <= 0">确认</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import index from './index.js';
|
||||
export default {
|
||||
mixins: [index],
|
||||
components:{
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
116
addon/cashier/source/os/components/ns-loading/ns-loading.vue
Executable file
116
addon/cashier/source/os/components/ns-loading/ns-loading.vue
Executable file
@@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<view class="loading-layer" v-if="isShow" :style="layerBackground">
|
||||
<view class="loading-anim">
|
||||
<view class="box item"><view class="border out item color-base-border-top color-base-border-left"></view></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'nsLoading',
|
||||
props: {
|
||||
layerBackground: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
defaultShow: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShow: true
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.isShow = this.defaultShow;
|
||||
},
|
||||
methods: {
|
||||
show() {
|
||||
this.isShow = true;
|
||||
},
|
||||
hide() {
|
||||
this.isShow = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.loading-layer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 997;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.loading-anim {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 40%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.loading-anim > .item {
|
||||
position: relative;
|
||||
width: 0.3rem;
|
||||
height: 0.3rem;
|
||||
perspective: 8rem;
|
||||
transform-style: preserve-3d;
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
.loading-anim .border {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
border: 0.03rem solid $primary-color;
|
||||
}
|
||||
|
||||
.loading-anim .out {
|
||||
top: 15%;
|
||||
left: 15%;
|
||||
width: 70%;
|
||||
height: 70%;
|
||||
// border-left-color: red !important;
|
||||
border-right-color: rgba($color: #000000, $alpha: 0) !important;
|
||||
// border-top-color: rgba($color: #000000, $alpha: 0) !important;
|
||||
border-bottom-color: rgba($color: #000000, $alpha: 0) !important;
|
||||
animation: spin 0.6s linear normal infinite;
|
||||
}
|
||||
|
||||
.loading-anim .in {
|
||||
top: 25%;
|
||||
left: 25%;
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
border-top-color: transparent !important;
|
||||
border-bottom-color: transparent !important;
|
||||
animation: spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
.loading-anim .mid {
|
||||
top: 40%;
|
||||
left: 40%;
|
||||
width: 20%;
|
||||
height: 20%;
|
||||
border-left-color: transparent;
|
||||
border-right-color: transparent;
|
||||
animation: spin 0.6s linear infinite;
|
||||
}
|
||||
</style>
|
||||
195
addon/cashier/source/os/components/ns-member-card-popup/index.js
Executable file
195
addon/cashier/source/os/components/ns-member-card-popup/index.js
Executable file
@@ -0,0 +1,195 @@
|
||||
import {
|
||||
getMemberCardList
|
||||
} from '@/api/member'
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
memberCardData: {
|
||||
page: 0,
|
||||
total: 1,
|
||||
list: [],
|
||||
index: 0,
|
||||
currData: {},
|
||||
selected: {}
|
||||
},
|
||||
itemNum: 1
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['billingGoodsData'])
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.memberCardPopup.open();
|
||||
this.memberCardData.page = 0;
|
||||
this.memberCardData.index = 0;
|
||||
this.memberCardData.list = [];
|
||||
this.memberCardData.currData = {};
|
||||
this.memberCardData.selected = {};
|
||||
this.getMemberCard()
|
||||
},
|
||||
// 获取会员项目
|
||||
getMemberCard() {
|
||||
if (this.memberCardData.page + 1 > this.memberCardData.total) return;
|
||||
this.memberCardData.page += 1;
|
||||
getMemberCardList({
|
||||
status: 1,
|
||||
page: this.memberCardData.page,
|
||||
member_id: this.globalMemberInfo.member_id
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.memberCardData.total = res.data.page_count || 1;
|
||||
Object.values(this.billingGoodsData).forEach(data => {
|
||||
if (data.card_id) {
|
||||
res.data.list.forEach((card)=>{
|
||||
if(card.card_id == data.card_id){
|
||||
// 通用卡:选择商品,总数量发生变化
|
||||
if (data.card_type == 'commoncard') {
|
||||
card.total_use_num += data.num;
|
||||
} else if (data.card_type == 'oncecard') {
|
||||
// 限次卡:选择商品后,商品和总数量都要发生变化
|
||||
card.total_use_num += data.num;
|
||||
card.item_list.forEach((card_item)=>{
|
||||
if(card_item.item_id == data.item_id){
|
||||
card_item.use_num += data.num;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
if (res.data.list.length) this.memberCardData.list = this.memberCardData.list.concat(res.data.list);
|
||||
if (this.memberCardData.page == 1) {
|
||||
// 默认展示第一个卡项信息
|
||||
if (res.data.count) this.selectMemberCard(this.memberCardData.list[0], 0);
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 选择会员套餐
|
||||
* @param {Object} data
|
||||
* @param {Object} index
|
||||
*/
|
||||
selectMemberCard(data, index) {
|
||||
this.memberCardData.index = index;
|
||||
this.memberCardData.currData = this.$util.deepClone(data);
|
||||
this.memberCardData.selected = {};
|
||||
},
|
||||
/**
|
||||
* 选择会员套餐商品项
|
||||
* @param {Object} data
|
||||
* @param {Object} index
|
||||
*/
|
||||
selectMemberCardItem(data, index) {
|
||||
if (this.memberCardData.selected['item_' + data.item_id]) {
|
||||
if (data.card_type == 'commoncard') {
|
||||
this.memberCardData.currData.total_use_num -= this.memberCardData.selected['item_' + data.item_id].input_num;
|
||||
}
|
||||
delete this.memberCardData.selected['item_' + data.item_id];
|
||||
} else {
|
||||
if (!this.checkStatus(data)) return;
|
||||
this.memberCardData.selected['item_' + data.item_id] = this.$util.deepClone(data);
|
||||
this.memberCardData.selected['item_' + data.item_id].input_num = 1;
|
||||
this.memberCardData.selected['item_' + data.item_id].index = index;
|
||||
this.memberCardData.selected['item_' + data.item_id].card_name = this.memberCardData.currData.goods_name;
|
||||
if (data.card_type == 'commoncard') {
|
||||
this.memberCardData.currData.total_use_num += 1;
|
||||
}
|
||||
}
|
||||
|
||||
this.$forceUpdate();
|
||||
},
|
||||
/**
|
||||
* 加入购物车
|
||||
*/
|
||||
selectGoods() {
|
||||
if (!Object.keys(this.memberCardData.selected).length) {
|
||||
this.$util.showToast({
|
||||
title: '请选择服务/商品',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let billingGoodsData = this.$util.deepClone(this.billingGoodsData);
|
||||
let billingGoodsKeys = Object.keys(billingGoodsData);
|
||||
Object.keys(this.memberCardData.selected).forEach((key) => {
|
||||
|
||||
let data = this.memberCardData.selected[key];
|
||||
data.card_index = this.memberCardData.index;
|
||||
this.memberCardData.list[this.memberCardData.index].total_use_num += data.input_num;
|
||||
this.memberCardData.list[this.memberCardData.index].item_list[data.index].use_num += data.input_num;
|
||||
this.memberCardData.currData.item_list[data.index].use_num += data.input_num;
|
||||
//服务商品每个都是一个订单项,需要循环处理
|
||||
if(data.goods_class == this.$util.goodsClassDict.service){
|
||||
let addNum = 0;
|
||||
Object.values(billingGoodsData).forEach((item)=>{
|
||||
if(item.sku_id == data.sku_id){
|
||||
addNum ++;
|
||||
}
|
||||
})
|
||||
data.num = 1;
|
||||
for(let num = 1;num <= data.input_num;num ++){
|
||||
let skuKey = 'sku_' + data.sku_id + '_item_' + data.item_id + '_' + addNum;
|
||||
billingGoodsData[skuKey] = this.$util.deepClone(data);
|
||||
addNum ++;
|
||||
}
|
||||
}else{
|
||||
data.num = data.input_num;
|
||||
let skuKey = 'sku_' + data.sku_id + '_item_' + data.item_id;
|
||||
if(billingGoodsData.hasOwnProperty(skuKey)){
|
||||
data.num += billingGoodsData[skuKey].num;
|
||||
}
|
||||
billingGoodsData[skuKey] = this.$util.deepClone(data);
|
||||
}
|
||||
});
|
||||
|
||||
this.$store.commit('billing/setGoodsData', billingGoodsData);
|
||||
|
||||
this.memberCardData.selected = {};
|
||||
},
|
||||
/**
|
||||
* 数量减
|
||||
* @param {Object} data
|
||||
*/
|
||||
itemDec(data) {
|
||||
let currData = this.memberCardData.currData;
|
||||
if (this.memberCardData.selected['item_' + data.item_id].input_num > 1) {
|
||||
this.memberCardData.selected['item_' + data.item_id].input_num -= 1;
|
||||
if (data.card_type == 'commoncard') {
|
||||
currData.total_use_num -= 1;
|
||||
}
|
||||
this.$forceUpdate();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 数量加
|
||||
* @param {Object} data
|
||||
*/
|
||||
itemInc(data) {
|
||||
let currData = this.memberCardData.currData;
|
||||
if (data.card_type == 'commoncard') {
|
||||
if ((currData.total_num - currData.total_use_num - 1) < 0) return;
|
||||
} else if (data.card_type == 'oncecard') {
|
||||
if ((data.num - data.use_num - this.memberCardData.selected['item_' + data.item_id].input_num - 1) < 0) return;
|
||||
}
|
||||
if (data.card_type == 'commoncard') {
|
||||
currData.total_use_num += 1;
|
||||
}
|
||||
this.memberCardData.selected['item_' + data.item_id].input_num += 1;
|
||||
this.$forceUpdate();
|
||||
},
|
||||
checkStatus(data) {
|
||||
let currData = this.memberCardData.currData;
|
||||
if (data.card_type == 'commoncard') {
|
||||
return currData.total_num > currData.total_use_num;
|
||||
} else if (data.card_type == 'oncecard') {
|
||||
return data.num > data.use_num;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
376
addon/cashier/source/os/components/ns-member-card-popup/index.scss
Executable file
376
addon/cashier/source/os/components/ns-member-card-popup/index.scss
Executable file
@@ -0,0 +1,376 @@
|
||||
.container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
height: 0.66rem;
|
||||
line-height: 0.66rem;
|
||||
text-align: left;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
color: #303133;
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
|
||||
.info-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 6.5rem;
|
||||
padding: 0 0.2rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
.headimg-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 0.2rem;
|
||||
|
||||
.headimg {
|
||||
width: 0.7rem;
|
||||
height: 0.7rem;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.header-info {
|
||||
margin-left: 0.15rem;
|
||||
width: calc(100% - 0.85rem);
|
||||
|
||||
.name {
|
||||
font-size: 0.16rem;
|
||||
color: #303133;
|
||||
|
||||
text {
|
||||
background: #ffffff;
|
||||
border: 0.01rem solid $primary-color;
|
||||
border-radius: 0.02rem;
|
||||
font-size: 0.12rem;
|
||||
color: $primary-color;
|
||||
margin-left: 0.15rem;
|
||||
padding: 0.01rem 0.04rem;
|
||||
}
|
||||
}
|
||||
|
||||
.header-info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 0.1rem;
|
||||
justify-content: space-between;
|
||||
|
||||
view {
|
||||
text-align: left;
|
||||
font-size: 0.14rem;
|
||||
color: #303133;
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding-top: 1.2rem;
|
||||
margin: 0 auto;
|
||||
|
||||
image {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.tips {
|
||||
color: #999;
|
||||
margin-top: 0.15rem;
|
||||
}
|
||||
}
|
||||
|
||||
.member-card-wrap {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.card-wrap {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
display: flex;
|
||||
padding-top: 0.2rem;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.card-list {
|
||||
width: 2rem;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
margin-right: 0.1rem;
|
||||
padding: 0.1rem 0;
|
||||
|
||||
.card-item {
|
||||
width: calc(100% - 0.2rem);
|
||||
height: 1rem;
|
||||
border: 0.01rem solid $primary-color;
|
||||
margin: 0 0.1rem 0.1rem 0.1rem;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0.05rem;
|
||||
cursor: pointer;
|
||||
padding: 0.15rem 0.1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background-color: var(--primary-color-light-8);
|
||||
|
||||
&.active {
|
||||
background-color: $primary-color;
|
||||
color: #fff;
|
||||
|
||||
.card-name {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.info {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.card-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: #999;
|
||||
|
||||
& > view {
|
||||
font-size: 0.12rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-list {
|
||||
flex: 1;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 0;
|
||||
|
||||
.content {
|
||||
padding: 0 0.1rem;
|
||||
}
|
||||
|
||||
.empty {
|
||||
padding-top: 0.8rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
line-height: 0.3rem;
|
||||
padding: 0.1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.num {
|
||||
color: $primary-color;
|
||||
margin: 0 0.02rem;
|
||||
}
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
height: 0.5rem;
|
||||
line-height: 0.5rem;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
box-shadow: 0 0.04rem 0.12rem 0 rgba(0, 0, 0, 0.1);
|
||||
padding: 0.1rem 0;
|
||||
|
||||
button {
|
||||
height: 0.4rem;
|
||||
line-height: 0.4rem;
|
||||
margin: 0 0.1rem 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.item-wrap {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
display: flex;
|
||||
|
||||
.uni-flex {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.card-item {
|
||||
display: flex;
|
||||
width: calc(50% - 0.05rem);
|
||||
padding: 0.1rem;
|
||||
border: 0.01rem solid #eee;
|
||||
border-radius: 0.03rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 0.1rem;
|
||||
|
||||
.image {
|
||||
width: 0.7rem;
|
||||
height: 0.7rem;
|
||||
margin-right: 0.1rem;
|
||||
overflow: hidden;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
width: 0;
|
||||
|
||||
.num {
|
||||
margin-top: 0.05rem;
|
||||
color: #999;
|
||||
font-size: 0.12rem;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 0.14rem;
|
||||
color: #fe2278;
|
||||
line-height: 1;
|
||||
|
||||
.util {
|
||||
font-size: 0.12rem;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
line-height: 1.5;
|
||||
|
||||
.tag {
|
||||
border-radius: 0.02rem;
|
||||
padding: 0.01rem 0.05rem;
|
||||
background-color: var(--primary-color-light-8);
|
||||
color: $primary-color;
|
||||
font-size: 0.12rem;
|
||||
margin-right: 0.05rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 0.12rem;
|
||||
margin-top: 0.05rem;
|
||||
height: 0.25rem;
|
||||
}
|
||||
|
||||
.number-wrap {
|
||||
display: none;
|
||||
height: 0.25rem;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
border-radius: 0.02rem;
|
||||
overflow: hidden;
|
||||
|
||||
input {
|
||||
height: 0.25rem;
|
||||
line-height: 0.25rem;
|
||||
width: 0.25rem;
|
||||
border: 1px solid #e6e6e6;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
font-size: 0.12rem;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
height: 0.25rem;
|
||||
width: 0.25rem;
|
||||
text-align: center;
|
||||
line-height: 0.25rem;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
.card-item.active {
|
||||
background-color: var(--primary-color-light-2);
|
||||
|
||||
.num {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.price {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.name {
|
||||
color: #fff;
|
||||
|
||||
.tag {
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.number-wrap {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.not-select {
|
||||
background: #eee;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pop弹框
|
||||
.pop-box {
|
||||
background: #ffffff;
|
||||
width: 8rem;
|
||||
height: 7rem;
|
||||
|
||||
.pop-header {
|
||||
padding: 0 0.15rem 0 0.2rem;
|
||||
height: 0.5rem;
|
||||
line-height: 0.5rem;
|
||||
border-bottom: 0.01rem solid #f0f0f0;
|
||||
font-size: 0.14rem;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
border-radius: 0.02rem 0.2rem 0 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.pop-header-text {
|
||||
}
|
||||
|
||||
.pop-header-close {
|
||||
cursor: pointer;
|
||||
|
||||
text {
|
||||
font-size: 0.18rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pop-content {
|
||||
height: calc(100% - 1rem);
|
||||
overflow-y: scroll;
|
||||
padding: 0.1rem 0.2rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
129
addon/cashier/source/os/components/ns-member-card-popup/ns-member-card-popup.vue
Executable file
129
addon/cashier/source/os/components/ns-member-card-popup/ns-member-card-popup.vue
Executable file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<uni-popup ref="memberCardPopup">
|
||||
|
||||
<view class="pop-box member-info-wrap">
|
||||
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">会员卡项</view>
|
||||
<view class="pop-header-close" @click="$refs.memberCardPopup.close()">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-wrap" v-if="globalMemberInfo">
|
||||
<view class="headimg-content">
|
||||
<view class="headimg">
|
||||
<image :src="globalMemberInfo.headimg ? $util.img(globalMemberInfo.headimg) : $util.img(defaultImg.head)" @error="globalMemberInfo.headimg = defaultImg.head"/>
|
||||
</view>
|
||||
<view class="header-info">
|
||||
<view class="name">
|
||||
{{ globalMemberInfo.nickname }}
|
||||
<text v-if="globalMemberInfo.member_level">{{ globalMemberInfo.member_level_name }}</text>
|
||||
</view>
|
||||
<view class="header-info-item">
|
||||
<view>电话:{{ globalMemberInfo.mobile }}</view>
|
||||
<view>性别:{{ globalMemberInfo.sex == 0 ? '未知' : globalMemberInfo.sex == 1 ? '男' : '女' }}</view>
|
||||
<view>生日:{{ globalMemberInfo.birthday }}</view>
|
||||
<view>注册时间:{{ globalMemberInfo.reg_time | timeFormat }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="member-card-wrap">
|
||||
<view class="card-wrap">
|
||||
<scroll-view scroll-y="true" class="card-list" @scrolltolower="getMemberCard()">
|
||||
<block v-if="memberCardData.list.length">
|
||||
<view class="card-item" :class="{ active: memberCardData.index == index }" v-for="(item, index) in memberCardData.list" :key="index" @click="selectMemberCard(item, index)">
|
||||
<view class="card-name">{{ item.goods_name }}</view>
|
||||
<view class="info">
|
||||
<view v-if="item.total_num > 0">可用{{ item.total_num - item.total_use_num }}次</view>
|
||||
<view v-else>不限次</view>
|
||||
<view v-if="item.end_time > 0">至{{ $util.timeFormat(item.end_time, 'Y/m/d') }}</view>
|
||||
<view v-else>长期有效</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<view v-else class="empty">
|
||||
<image src="@/static/card/card_empty.png" mode="widthFix"/>
|
||||
<view class="tips">暂无可用卡项</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="item-list">
|
||||
<view class="title">
|
||||
<view>可用服务/商品</view>
|
||||
<view v-if="memberCardData.currData.card_type == 'commoncard'">
|
||||
<text>以下服务/商品剩余可用</text>
|
||||
<text class="num">{{ memberCardData.currData.total_num - memberCardData.currData.total_use_num }}</text>
|
||||
<text>次</text>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="item-wrap">
|
||||
<view class="uni-flex justify-between content" v-if="memberCardData.currData.item_list">
|
||||
<view class="card-item" :class="{
|
||||
active: memberCardData.selected['item_' + item.item_id],
|
||||
'not-select': !checkStatus(item) && !memberCardData.selected['item_' + item.item_id]
|
||||
}" @click="selectMemberCardItem(item, index)" v-for="(item, index) in memberCardData.currData.item_list">
|
||||
<view class="image">
|
||||
<image v-if="item.sku_image == '@/static/goods/goods.png'" src="@/static/goods/goods.png" mode="widthFix"/>
|
||||
<image v-else :src="$util.img(item.sku_image.split(',')[0], { size: 'small' })" @error="item.sku_image = '@/static/goods/goods.png'" mode="widthFix"/>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view>
|
||||
<view class="name">
|
||||
<text class="tag">{{ item.is_virtual ? '服务' : '商品' }}</text>
|
||||
<text>{{ item.sku_name }}</text>
|
||||
</view>
|
||||
<block v-if="memberCardData.currData.card_type != 'commoncard'">
|
||||
<view class="num" v-if="item.num > 0">剩余可用{{ item.num - item.use_num }}次</view>
|
||||
<view class="num" v-else>不限次</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="action-wrap">
|
||||
<view class="price">
|
||||
<text class="util">¥</text>
|
||||
{{ item.price }}
|
||||
</view>
|
||||
<view class="number-wrap" v-if="memberCardData.selected['item_' + item.item_id]">
|
||||
<text class="iconfont iconjian" @click.stop="itemDec(memberCardData.selected['item_' + item.item_id])"></text>
|
||||
<input type="number" v-model="memberCardData.selected['item_' + item.item_id].input_num" />
|
||||
<text class="iconfont iconjia" @click.stop="itemInc(memberCardData.selected['item_' + item.item_id])"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty" v-else>
|
||||
<image src="@/static/goods/goods_empty.png" mode="widthFix"/>
|
||||
<view class="tips">暂无相关数据</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="button-wrap">
|
||||
<button type="default" class="primary-btn" :disabled="memberCardData.itemIndex == -1" @click="selectGoods()">加入购物车</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniDataCheckbox from '@/components/uni-data-checkbox/uni-data-checkbox.vue';
|
||||
import UniPopup from "../uni-popup/uni-popup";
|
||||
import index from './index.js';
|
||||
|
||||
export default {
|
||||
name: 'nsMember',
|
||||
components: {
|
||||
UniPopup,
|
||||
uniDataCheckbox
|
||||
},
|
||||
mixins: [index]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
@@ -0,0 +1,398 @@
|
||||
<template>
|
||||
<view class="member-detail-wrap">
|
||||
<!-- 卡包 -->
|
||||
<uni-popup ref="cardListPop">
|
||||
<view class="pop-box card-list-pop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">卡包</view>
|
||||
<view class="pop-header-close" @click="close('cardlist')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="common-scrollbar pop-content">
|
||||
<dataTable url="/cardservice/storeapi/membercard/lists" :cols="card" ref="table" :option="option" :pagesize="pageSize">
|
||||
<template v-slot:action="dataTable">
|
||||
<text class="view-detail" @click="viewDetails(dataTable.value.card_id)">查看详情</text>
|
||||
</template>
|
||||
</dataTable>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<uni-popup ref="cardDetailPop">
|
||||
<view class="pop-box cardDetailPop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">详情</view>
|
||||
<view class="pop-header-close" @click="$refs.cardDetailPop.close()">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pop-content">
|
||||
<view class="tab-head">
|
||||
<text v-for="(item, index) in tabObj.list" :key="index" :class="{ active: tabObj.index == item.value }" v-if="(item.value == 3 && card_detail.card_log && card_detail.card_log.length > 0) || item.value != 3" @click="tabObj.index = item.value">
|
||||
{{ item.name }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="tab-content">
|
||||
<view class="basic-info" v-if="tabObj.index == 0">
|
||||
<view class="basic-item using-hidden">卡项名称:{{ basicInfo.goods_name }}</view>
|
||||
<view class="basic-item">价格:{{ basicInfo.price }}</view>
|
||||
<view class="basic-item">
|
||||
卡类型:{{ (basicInfo.card_type == 'oncecard' && '限次卡') || (basicInfo.card_type == 'timecard' && '限时卡') || (basicInfo.card_type == 'commoncard' && '通用卡') }}
|
||||
</view>
|
||||
<view class="basic-item">总次数/已使用:{{ basicInfo.card_type == 'timecard' ? '不限' : basicInfo.total_num }}/{{ basicInfo.total_use_num }}</view>
|
||||
<view class="basic-item">获取时间:{{ $util.timeFormat(basicInfo.create_time) }}</view>
|
||||
<view class="basic-item">到期时间:{{ basicInfo.end_time > 0 ? $util.timeFormat(basicInfo.end_time) : '永久有效' }}</view>
|
||||
</view>
|
||||
<view class="other-information" v-if="tabObj.index == 1 && basicInfo && basicInfo.card_item">
|
||||
<view class="information-head">
|
||||
<text>商品名称</text>
|
||||
<text>总次数/已使用</text>
|
||||
<text>有效期</text>
|
||||
</view>
|
||||
<view class="information-body">
|
||||
<view class="information-tr" v-for="(item, index) in basicInfo.card_item" :key="index">
|
||||
<text class="using-hidden">{{ item.sku_name }}</text>
|
||||
<text>{{ item.card_type == 'timecard' ? '不限' : item.num }} /{{ item.use_num }}</text>
|
||||
<text>{{ item.end_time > 0 ? $util.timeFormat(item.end_time) : '永久有效' }}</text>
|
||||
</view>
|
||||
<view class="information-tr empty" v-if="!basicInfo.card_item.length">
|
||||
<view class="iconfont iconwushuju"></view>
|
||||
<view>暂无数据</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card-info" v-if="tabObj.index == 2">
|
||||
<dataTable url="/cardservice/storeapi/membercard/records" :cols="cardInfo.card" ref="table" :option="cardInfo.option" :pagesize="cardInfo.pageSize"></dataTable>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getMemberCardDetail } from '@/api/member'
|
||||
import dataTable from '@/components/uni-data-table/uni-data-table.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
dataTable
|
||||
},
|
||||
props: {
|
||||
option: {}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageSize: 8,
|
||||
card: [{
|
||||
width: 20,
|
||||
title: '名称',
|
||||
align: 'left',
|
||||
field: 'goods_name'
|
||||
}, {
|
||||
width: 18,
|
||||
title: '卡号',
|
||||
align: 'center',
|
||||
field: 'card_code'
|
||||
}, {
|
||||
width: 8,
|
||||
title: '卡类型',
|
||||
align: 'left',
|
||||
templet: function (data) {
|
||||
if (data.card_type == 'oncecard') return '限次卡';
|
||||
if (data.card_type == 'timecard') return '限时卡';
|
||||
if (data.card_type == 'commoncard') return '通用卡';
|
||||
}
|
||||
}, {
|
||||
width: 12,
|
||||
title: '总次数/已使用',
|
||||
align: 'center',
|
||||
templet: data => {
|
||||
var totalNum = data.card_type == 'timecard' ? '不限' : data.total_num;
|
||||
return totalNum + '/' + data.total_use_num;
|
||||
}
|
||||
}, {
|
||||
width: 17,
|
||||
title: '创建时间',
|
||||
align: 'center',
|
||||
templet: data => {
|
||||
return this.$util.timeFormat(data.create_time);
|
||||
}
|
||||
}, {
|
||||
width: 17,
|
||||
title: '到期时间',
|
||||
align: 'center',
|
||||
templet: data => {
|
||||
if (data.end_time) return this.$util.timeFormat(data.end_time);
|
||||
else return '长期有效';
|
||||
}
|
||||
}, {
|
||||
width: 8,
|
||||
title: '操作',
|
||||
align: 'right',
|
||||
action: true
|
||||
}],
|
||||
tabObj: {
|
||||
list: [{
|
||||
value: 0,
|
||||
name: '基础信息'
|
||||
}, {
|
||||
value: 1,
|
||||
name: '商品/项目'
|
||||
}, {
|
||||
value: 2,
|
||||
name: '使用记录'
|
||||
}],
|
||||
index: 1
|
||||
},
|
||||
currCardId: 0,
|
||||
basicInfo: {},
|
||||
cardInfo: {
|
||||
card: [{
|
||||
width: 40,
|
||||
title: '卡项名称',
|
||||
align: 'left',
|
||||
field: 'sku_name'
|
||||
}, {
|
||||
width: 20,
|
||||
title: '使用次数',
|
||||
align: 'center',
|
||||
field: 'num'
|
||||
}, {
|
||||
width: 25,
|
||||
title: '使用时间',
|
||||
align: 'right',
|
||||
templet: data => {
|
||||
return this.$util.timeFormat(data.create_time);
|
||||
}
|
||||
}, {
|
||||
width: 15,
|
||||
title: '操作',
|
||||
align: 'right',
|
||||
action: true
|
||||
}],
|
||||
option: {},
|
||||
pageSize: 6
|
||||
}
|
||||
};
|
||||
},
|
||||
created() { },
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.cardListPop.open();
|
||||
},
|
||||
close() {
|
||||
this.$refs.cardListPop.close();
|
||||
},
|
||||
viewDetails(card_id) {
|
||||
this.currCardId = card_id;
|
||||
this.$refs.cardDetailPop.open();
|
||||
this.getCardDetail();
|
||||
|
||||
this.cardInfo.option.member_id = this.globalMemberInfo.member_id;
|
||||
this.cardInfo.option.card_id = this.currCardId;
|
||||
},
|
||||
getCardDetail() {
|
||||
let data = {};
|
||||
data.member_id = this.globalMemberInfo.member_id;
|
||||
data.card_id = this.currCardId;
|
||||
getMemberCardDetail(data).then(res => {
|
||||
this.basicInfo = {};
|
||||
if (res.code >= 0) {
|
||||
this.basicInfo = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pop-box {
|
||||
background: #ffffff;
|
||||
width: 8rem;
|
||||
height: 7rem;
|
||||
|
||||
.pop-header {
|
||||
padding: 0 0.15rem 0 0.2rem;
|
||||
height: 0.5rem;
|
||||
line-height: 0.5rem;
|
||||
border-bottom: 0.01rem solid #f0f0f0;
|
||||
font-size: 0.14rem;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
border-radius: 0.02rem 0.2rem 0 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.pop-header-close {
|
||||
cursor: pointer;
|
||||
|
||||
text {
|
||||
font-size: 0.18rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pop-content {
|
||||
height: calc(100% - 1rem);
|
||||
overflow-y: scroll;
|
||||
padding: 0.1rem 0.2rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pop-bottom {
|
||||
button {
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-list-pop-box {
|
||||
width: 10rem;
|
||||
height: 5.7rem;
|
||||
|
||||
.pop-content {
|
||||
height: calc(100% - 0.5rem);
|
||||
}
|
||||
|
||||
/deep/ .tpage {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.basic-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0.2rem;
|
||||
padding: 0.2rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.basic {
|
||||
padding: 0.1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.cardDetailPop-box {
|
||||
width: 10rem;
|
||||
height: 5.7rem;
|
||||
|
||||
.tab-head {
|
||||
display: flex;
|
||||
background-color: #f7f8fa;
|
||||
|
||||
text {
|
||||
height: 0.5rem;
|
||||
line-height: 0.5rem;
|
||||
text-align: center;
|
||||
padding: 0 0.35rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.active {
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pop-content {
|
||||
overflow-y: inherit;
|
||||
|
||||
.basic-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
padding: 0.2rem;
|
||||
|
||||
.basic-item {
|
||||
flex-basis: 33%;
|
||||
height: 0.4rem;
|
||||
line-height: 0.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.other-information {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
padding-top: 0.2rem;
|
||||
|
||||
.information-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: #f7f8fa;
|
||||
|
||||
text {
|
||||
padding: 0 0.2rem;
|
||||
height: 0.5rem;
|
||||
line-height: 0.5rem;
|
||||
|
||||
&:nth-child(1) {
|
||||
flex-basis: 35%;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
flex-basis: 35%;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
flex-basis: 30%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.information-tr {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
|
||||
text {
|
||||
padding: 0 0.2rem;
|
||||
height: 0.5rem;
|
||||
line-height: 0.5rem;
|
||||
|
||||
&:nth-child(1) {
|
||||
flex-basis: 35%;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
flex-basis: 35%;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
flex-basis: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
&.empty {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 0.5rem;
|
||||
color: #909399;
|
||||
|
||||
.iconfont {
|
||||
font-size: 0.25rem;
|
||||
margin: 0.05rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-top: 0.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.view-detail {
|
||||
color: $primary-color;
|
||||
}</style>
|
||||
183
addon/cashier/source/os/components/ns-member-detail-popup/index.js
Executable file
183
addon/cashier/source/os/components/ns-member-detail-popup/index.js
Executable file
@@ -0,0 +1,183 @@
|
||||
import {
|
||||
getMemberInfoById,
|
||||
getMemberLevelList,
|
||||
getCouponTypeList,
|
||||
sendMemberCoupon,
|
||||
applyingMembershipCard
|
||||
} from '@/api/member'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pageSize: 8,
|
||||
sex: [{
|
||||
text: '未知',
|
||||
value: 0
|
||||
}, {
|
||||
text: '男',
|
||||
value: 1
|
||||
}, {
|
||||
text: '女',
|
||||
value: 2
|
||||
}],
|
||||
sendCoupon: {
|
||||
list: [],
|
||||
page: 1
|
||||
},
|
||||
memberLevelList: [],
|
||||
applyMember: {
|
||||
level_id: '',
|
||||
member_level: '',
|
||||
member_level_name: '',
|
||||
member_code: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getMemberLevel();
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.getMemberInfo(); // 保证数据实时性
|
||||
this.$refs.memberPop.open();
|
||||
},
|
||||
getMemberInfo() {
|
||||
getMemberInfoById(this.globalMemberInfo.member_id).then(res => {
|
||||
if (res.code >= 0) {
|
||||
res.data.birthday = res.data.birthday > 0 ? this.$util.timeFormat(res.data.birthday, 'Y-m-d') : '--';
|
||||
this.$store.commit('app/setGlobalMemberInfo', res.data);
|
||||
}
|
||||
});
|
||||
},
|
||||
getMemberLevel() {
|
||||
this.memberLevelList = [];
|
||||
getMemberLevelList().then(res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
for (let i in res.data) {
|
||||
this.memberLevelList.push({
|
||||
label: res.data[i]['level_name'],
|
||||
value: res.data[i]['level_id'].toString(),
|
||||
disabled: false
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
selectMemberLevel(index, item) {
|
||||
if (index >= 0) {
|
||||
this.applyMember.level_id = item.value;
|
||||
this.applyMember.member_level = item.value;
|
||||
this.applyMember.member_level_name = item.label;
|
||||
} else {
|
||||
this.applyMember.level_id = '';
|
||||
this.applyMember.member_level = item.value;
|
||||
this.applyMember.member_level_name = item.label;
|
||||
}
|
||||
},
|
||||
// 客户操作
|
||||
memberAction(type) {
|
||||
switch (type) {
|
||||
case 'sendCoupon':
|
||||
this.getCouponList();
|
||||
this.$refs.sendCouponPop.open('center');
|
||||
break;
|
||||
case 'applyMember':
|
||||
this.$refs.applyMemberPop.open();
|
||||
break;
|
||||
}
|
||||
},
|
||||
popClose(type) {
|
||||
this.$refs[type + 'Pop'].close();
|
||||
},
|
||||
//获取发放优惠券列表
|
||||
getCouponList() {
|
||||
let data = {
|
||||
page: this.sendCoupon.page,
|
||||
page_size: 7
|
||||
};
|
||||
getCouponTypeList(data).then(res => {
|
||||
if (res.code >= 0) {
|
||||
if (this.sendCoupon.page == 1) this.sendCoupon.list = [];
|
||||
if (res.data.list && res.data.list.length) {
|
||||
res.data.list.forEach((item, index) => {
|
||||
if (item.validity_type == 0) item.validity_name = '失效日期:' + this.$util.timeFormat(item.end_time);
|
||||
else if (item.validity_type == 1) item.validity_name = '领取后,' + item.fixed_term + '天有效';
|
||||
else item.validity_name = '长期有效';
|
||||
item.num = 0;
|
||||
});
|
||||
}
|
||||
this.sendCoupon.list = this.sendCoupon.list.concat(res.data.list);
|
||||
if (res.data.page_count >= this.sendCoupon.page) this.sendCoupon.page++;
|
||||
}
|
||||
});
|
||||
},
|
||||
// 发放数量
|
||||
dec: function (item) {
|
||||
if (item.num > 0) {
|
||||
item.num = item.num - 1;
|
||||
}
|
||||
},
|
||||
inc: function (item) {
|
||||
item.num = item.num + 1;
|
||||
},
|
||||
// 发放优惠券
|
||||
sendCouponFn() {
|
||||
if (!this.sendCoupon.list || !this.sendCoupon.list.length) return false;
|
||||
let data = {};
|
||||
data.member_id = this.globalMemberInfo.member_id;
|
||||
data.coupon_data = '';
|
||||
let couponDataArr = [];
|
||||
|
||||
this.sendCoupon.list.forEach((item, index) => {
|
||||
if (item.num > 0) {
|
||||
let obj = {};
|
||||
obj.coupon_type_id = item.coupon_type_id;
|
||||
obj.num = item.num;
|
||||
couponDataArr.push(obj);
|
||||
}
|
||||
});
|
||||
if (couponDataArr.length <= 0) return false;
|
||||
data.coupon_data = JSON.stringify(couponDataArr);
|
||||
sendMemberCoupon(data).then(res => {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
this.sendCoupon.page = 1;
|
||||
this.sendCoupon.list = [];
|
||||
this.getMemberInfo();
|
||||
this.$refs.sendCouponPop.close();
|
||||
}
|
||||
});
|
||||
},
|
||||
//打开会员卡项
|
||||
showMemberCard() {
|
||||
this.$refs.memberCardPopup.open();
|
||||
},
|
||||
// 办理会员卡
|
||||
saveApplyMember() {
|
||||
if (!this.applyMember.level_id) {
|
||||
this.$util.showToast({
|
||||
title: '请选择会员卡等级'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
applyingMembershipCard({
|
||||
member_id: this.globalMemberInfo.member_id,
|
||||
level_id: this.applyMember.level_id,
|
||||
member_code: this.applyMember.member_code
|
||||
}).then(res => {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
this.getMemberInfo();
|
||||
this.popClose('applyMember');
|
||||
}
|
||||
});
|
||||
},
|
||||
headError(item) {
|
||||
item.headimg = this.defaultImg.head;
|
||||
}
|
||||
}
|
||||
}
|
||||
412
addon/cashier/source/os/components/ns-member-detail-popup/index.scss
Executable file
412
addon/cashier/source/os/components/ns-member-detail-popup/index.scss
Executable file
@@ -0,0 +1,412 @@
|
||||
.member-detail-wrap {
|
||||
width: 100%;
|
||||
border-left: 0;
|
||||
|
||||
.member-head {
|
||||
height: 0.66rem;
|
||||
line-height: 0.66rem;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
|
||||
.member-content {
|
||||
padding: 0.15rem;
|
||||
width: 100%;
|
||||
height: calc(100vh - 0.8rem);
|
||||
box-sizing: border-box;
|
||||
|
||||
.content-block {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.item-img {
|
||||
width: 0.7rem;
|
||||
height: 0.7rem;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.item-content {
|
||||
padding-left: 0.15rem;
|
||||
width: calc(100% - 0.7rem);
|
||||
box-sizing: border-box;
|
||||
|
||||
.item-title {
|
||||
width: 100%;
|
||||
font-size: 0.16rem;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
||||
.item-label {
|
||||
border: 0.01rem solid $primary-color;
|
||||
color: $primary-color;
|
||||
background-color: #fff;
|
||||
border-radius: 0.02rem;
|
||||
width: fit-content;
|
||||
padding: 0.01rem 0.05rem;
|
||||
margin-left: 0.15rem;
|
||||
}
|
||||
|
||||
.item-title-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 50%;
|
||||
font-size: 0.16rem;
|
||||
}
|
||||
}
|
||||
|
||||
.info-list {
|
||||
margin-top: 0.1rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
.info-item {
|
||||
font-size: .14rem;
|
||||
padding-right: .2rem;
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
height: .25rem;
|
||||
line-height: .25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-block.account {
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 0.2rem;
|
||||
border-radius: 0.03rem;
|
||||
align-items: baseline;
|
||||
padding: .1rem 0;
|
||||
|
||||
.content-data-item {
|
||||
padding: .1rem 0;
|
||||
width: 33%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.data-item-title {
|
||||
}
|
||||
|
||||
.data-item-value {
|
||||
font-size: 0.26rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.content-block.assets {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 0.2rem;
|
||||
|
||||
.content-data-left {
|
||||
background-color: #ffffff;
|
||||
padding: 0.25rem 0;
|
||||
border-radius: 0.03rem;
|
||||
width: calc(50% - 0.075rem);
|
||||
margin-right: 0.15rem;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
height: 1rem;
|
||||
|
||||
.content-data-item {
|
||||
.data-item-title {
|
||||
}
|
||||
|
||||
.data-item-value {
|
||||
font-size: 0.26rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-block.action {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-top: 0.2rem;
|
||||
|
||||
.content-data-item {
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
width: calc(100% / 3);
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
padding: 0.15rem 0;
|
||||
border-radius: 0.03rem;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
margin-right: 0.15rem;
|
||||
cursor: pointer;
|
||||
|
||||
.data-item-icon {
|
||||
width: 0.55rem;
|
||||
height: 0.55rem;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.data-item-value {
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pop弹框
|
||||
.pop-box {
|
||||
background: #ffffff;
|
||||
width: 8rem;
|
||||
height: 7rem;
|
||||
|
||||
.pop-header {
|
||||
padding: 0 0.15rem 0 0.2rem;
|
||||
height: 0.5rem;
|
||||
line-height: 0.5rem;
|
||||
border-bottom: 0.01rem solid #f0f0f0;
|
||||
font-size: 0.14rem;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
border-radius: 0.02rem 0.2rem 0 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.pop-header-text {
|
||||
}
|
||||
|
||||
.pop-header-close {
|
||||
cursor: pointer;
|
||||
|
||||
text {
|
||||
font-size: 0.18rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pop-content {
|
||||
height: calc(100% - 1rem);
|
||||
overflow-y: scroll;
|
||||
padding: 0.1rem 0.2rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pop-bottom {
|
||||
button {
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//表单
|
||||
.form-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 0.1rem;
|
||||
display: flex;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
width: 1.2rem;
|
||||
text-align: right;
|
||||
padding-right: 0.1rem;
|
||||
box-sizing: border-box;
|
||||
height: 0.32rem;
|
||||
line-height: 0.32rem;
|
||||
|
||||
.required {
|
||||
color: red;
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
}
|
||||
|
||||
.form-inline {
|
||||
width: 2.4rem;
|
||||
line-height: 0.32rem;
|
||||
margin-right: 0.1rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
.form-input {
|
||||
border-width: 0.01rem;
|
||||
border-style: solid;
|
||||
background-color: #fff;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
border-radius: 0.02rem;
|
||||
padding-left: 0.1rem;
|
||||
height: 0.32rem;
|
||||
line-height: 0.32rem;
|
||||
font-size: 0.14rem;
|
||||
border-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.word-aux {
|
||||
color: #999;
|
||||
font-size: 0.12rem;
|
||||
line-height: 1.5;
|
||||
margin-top: 0.05rem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.member-info-wrap {
|
||||
width: 5.5rem;
|
||||
height: 5.2rem;
|
||||
}
|
||||
|
||||
.applyMemberPop-box {
|
||||
width: 6rem;
|
||||
height: 3.38rem;
|
||||
|
||||
.pop-content {
|
||||
overflow: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.sendCoupon-box {
|
||||
width: 9rem;
|
||||
height: 5.06rem;
|
||||
|
||||
.sendCoupon-content {
|
||||
padding: 0.1rem 0.2rem;
|
||||
|
||||
.coupon-table-head {
|
||||
display: flex;
|
||||
background: #f7f8fa;
|
||||
}
|
||||
|
||||
.coupon-table-body {
|
||||
height: 3.2rem;
|
||||
|
||||
.coupon-table-tr {
|
||||
display: flex;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
}
|
||||
|
||||
.table-input {
|
||||
height: 0.3rem;
|
||||
line-height: 0.3rem;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
padding: 0 0.1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.item-num {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 0.1rem;
|
||||
|
||||
.num-dec {
|
||||
width: 0.6rem;
|
||||
height: 0.25rem;
|
||||
background: #e6e6e6;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
border-radius: 30%;
|
||||
text-align: center;
|
||||
line-height: 0.23rem;
|
||||
font-size: 0.25rem;
|
||||
margin-right: 0.1rem;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.num-inc {
|
||||
width: 0.6rem;
|
||||
height: 0.25rem;
|
||||
background: $primary-color;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
border-radius: 30%;
|
||||
text-align: center;
|
||||
line-height: 0.23rem;
|
||||
font-size: 0.25rem;
|
||||
margin-left: 0.1rem;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-table-td:nth-child(4) {
|
||||
padding: 0 0.05rem;
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-table-td,
|
||||
.coupon-table-th {
|
||||
padding: 0 0.1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 0.5rem;
|
||||
|
||||
&:nth-child(1) {
|
||||
flex-basis: 30%;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
flex-basis: 20%;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
flex-basis: 30%;
|
||||
}
|
||||
|
||||
&:nth-child(4) {
|
||||
justify-content: flex-end;
|
||||
flex-basis: 20%;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pop-bottom {
|
||||
margin-top: 0.12rem;
|
||||
}
|
||||
|
||||
.empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 0.5rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
color: #909399;
|
||||
|
||||
.iconfont {
|
||||
font-size: 0.25rem;
|
||||
margin: 0.05rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
<template>
|
||||
<view class="member-detail-wrap">
|
||||
|
||||
<uni-popup ref="memberPop">
|
||||
<view class="pop-box member-info-wrap" v-if="globalMemberInfo">
|
||||
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">会员详情</view>
|
||||
<view class="pop-header-close" @click="popClose('member')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="member-content">
|
||||
<view class="content-block">
|
||||
<view class="item-img">
|
||||
<image mode="aspectFill" v-if="globalMemberInfo.headimg" :src="$util.img(globalMemberInfo.headimg)" @error="headError(globalMemberInfo)"/>
|
||||
<image mode="aspectFill" v-else :src="$util.img(defaultImg.head)"/>
|
||||
</view>
|
||||
<view class="item-content">
|
||||
<view class="item-title">
|
||||
<view class="item-title-text">{{ globalMemberInfo.nickname ? globalMemberInfo.nickname : '' }}</view>
|
||||
<view class="item-label" v-if="globalMemberInfo.member_level && globalMemberInfo.member_level_name">{{ globalMemberInfo.member_level_name }}</view>
|
||||
</view>
|
||||
<view class="info-list">
|
||||
<view class="info-item">手机:{{ globalMemberInfo.mobile ? globalMemberInfo.mobile : '' }}</view>
|
||||
<view class="info-item" v-if="globalMemberInfo.sex == 0">性别:未知</view>
|
||||
<view class="info-item" v-if="globalMemberInfo.sex == 1">性别:男</view>
|
||||
<view class="info-item" v-if="globalMemberInfo.sex == 2">性别:女</view>
|
||||
<view class="info-item">生日:{{ globalMemberInfo.birthday }}</view>
|
||||
<view class="info-item" v-if="globalMemberInfo.member_time">成为会员:{{ $util.timeFormat(globalMemberInfo.member_time,'Y-m-d') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content-block account">
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">积分</view>
|
||||
<view class="data-item-value">{{ globalMemberInfo.point ? parseInt(globalMemberInfo.point) : '0' }}</view>
|
||||
</view>
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">储值余额(元)</view>
|
||||
<view class="data-item-value">{{ globalMemberInfo.balance ? globalMemberInfo.balance : '0.00' }}</view>
|
||||
</view>
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">现金余额(元)</view>
|
||||
<view class="data-item-value">{{ globalMemberInfo.balance_money ? globalMemberInfo.balance_money : '0.00' }}</view>
|
||||
</view>
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">成长值</view>
|
||||
<view class="data-item-value">{{ globalMemberInfo.growth ? globalMemberInfo.growth : '0' }}</view>
|
||||
</view>
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">优惠券(张)</view>
|
||||
<view class="data-item-value">{{ globalMemberInfo.coupon_num ? globalMemberInfo.coupon_num : '0' }}</view>
|
||||
</view>
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">卡包</view>
|
||||
<view class="data-item-value">{{ globalMemberInfo.card_num ? globalMemberInfo.card_num : '0' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-block action">
|
||||
<view class="content-data-item" @click="memberAction('sendCoupon')">
|
||||
<view class="data-item-icon">
|
||||
<image mode="aspectFit" src="@/static/member/icon-member-coupon.png" />
|
||||
</view>
|
||||
<view class="data-item-value">送优惠券</view>
|
||||
</view>
|
||||
<view class="content-data-item" v-if="isShowMemberCard" @click="showMemberCard">
|
||||
<view class="data-item-icon">
|
||||
<image mode="aspectFit" src="@/static/member/icon-member-balance.png" />
|
||||
</view>
|
||||
<view class="data-item-value">会员卡项</view>
|
||||
</view>
|
||||
<view class="content-data-item" @click="memberAction('applyMember')" v-if="!globalMemberInfo.is_member">
|
||||
<view class="data-item-icon">
|
||||
<image mode="aspectFit" src="@/static/member/icon-member-apply.png" />
|
||||
</view>
|
||||
<view class="data-item-value">办理会员</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 发放优惠券 -->
|
||||
<uni-popup ref="sendCouponPop">
|
||||
<view class="pop-box sendCoupon-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">送优惠券</view>
|
||||
<view class="pop-header-close" @click="popClose('sendCoupon')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="common-scrollbar sendCoupon-content">
|
||||
<view class="coupon-table-head">
|
||||
<view class="coupon-table-th">优惠券名称</view>
|
||||
<view class="coupon-table-th">金额</view>
|
||||
<view class="coupon-table-th">有效期</view>
|
||||
<view class="coupon-table-th">发放数量</view>
|
||||
</view>
|
||||
<scroll-view class="coupon-table-body" @scrolltolower="getCouponList()" scroll-y="true">
|
||||
<view class="coupon-table-tr" v-for="(item, index) in sendCoupon.list" :key="index">
|
||||
<view class="coupon-table-td">{{ item.coupon_name }}</view>
|
||||
<view class="coupon-table-td">{{ item.money }}</view>
|
||||
<view class="coupon-table-td">{{ item.validity_name }}</view>
|
||||
<view class="coupon-table-td">
|
||||
<view class="item-num">
|
||||
<view class="num-dec" v-on:click="dec(item)">-</view>
|
||||
<input class="table-input" type="text" v-model="item.num" />
|
||||
<view class="num-inc" v-on:click="inc(item)">+</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty" v-if="!sendCoupon.list.length">
|
||||
<view class="iconfont iconwushuju"></view>
|
||||
<view>暂无数据</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="pop-bottom">
|
||||
<button v-if="sendCoupon.list.length" class="primary-btn" @click="sendCouponFn">发放优惠券</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 办理会员 -->
|
||||
<uni-popup ref="applyMemberPop">
|
||||
<view class="pop-box applyMemberPop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">办理会员</view>
|
||||
<view class="pop-header-close" @click="popClose('applyMember')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="common-scrollbar pop-content">
|
||||
<view class="form-content">
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
会员等级:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<select-lay :zindex="10" :value="applyMember.level_id" name="names" placeholder="请选择会员等级" :options="memberLevelList" @selectitem="selectMemberLevel"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
会员卡号:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<input class="form-input" type="text" placeholder="请输入会员卡号" v-model="applyMember.member_code" />
|
||||
<view class="word-aux">会员卡号为会员唯一编号,若不设置将会自动生成</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pop-bottom">
|
||||
<button class="primary-btn" @click="saveApplyMember">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 会员卡项弹出框 -->
|
||||
<ns-member-card-popup v-if="isShowMemberCard" ref="memberCardPopup"/>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dataTable from '@/components/uni-data-table/uni-data-table.vue';
|
||||
import index from './index.js';
|
||||
import UniPopup from "../uni-popup/uni-popup";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
UniPopup,
|
||||
dataTable
|
||||
},
|
||||
props:{
|
||||
// 是否展示会员卡项
|
||||
isShowMemberCard:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
mixins: [index],
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
<style>
|
||||
.member-info-pop >>> .pop-content, .member-info-pop >>> .uni-scroll-view{
|
||||
overflow: inherit !important;
|
||||
}
|
||||
</style>
|
||||
502
addon/cashier/source/os/components/ns-member-detail/index.js
Executable file
502
addon/cashier/source/os/components/ns-member-detail/index.js
Executable file
@@ -0,0 +1,502 @@
|
||||
import {
|
||||
getMemberInfoById,
|
||||
getMemberLevelList,
|
||||
getCouponTypeList,
|
||||
sendMemberCoupon,
|
||||
editMember,
|
||||
modifyMemberPoint,
|
||||
modifyMemberBalance,
|
||||
modifyMemberGrowth,
|
||||
applyingMembershipCard
|
||||
} from '@/api/member'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
memberId: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageSize: 8,
|
||||
endTime: '',
|
||||
memberInfo: null,
|
||||
sex: [{
|
||||
text: '未知',
|
||||
value: 0
|
||||
}, {
|
||||
text: '男',
|
||||
value: 1
|
||||
}, {
|
||||
text: '女',
|
||||
value: 2
|
||||
}],
|
||||
pointData: {
|
||||
num: 0,
|
||||
desc: ''
|
||||
},
|
||||
growthData: {
|
||||
num: 0,
|
||||
desc: ''
|
||||
},
|
||||
balanceData: {
|
||||
num: 0,
|
||||
desc: ''
|
||||
},
|
||||
option: {},
|
||||
sendCoupon: {
|
||||
list: [],
|
||||
page: 1
|
||||
},
|
||||
memberLevelList: [],
|
||||
applyMember: {
|
||||
level_id: '',
|
||||
member_level_name: '',
|
||||
member_code: ''
|
||||
},
|
||||
couponCols: [{
|
||||
width: 15,
|
||||
title: '优惠券名称',
|
||||
align: 'left',
|
||||
field: 'coupon_name'
|
||||
}, {
|
||||
width: 7,
|
||||
title: '类型',
|
||||
align: 'left',
|
||||
templet: function (data) {
|
||||
if (data.type == 'reward') return '满减';
|
||||
if (data.type == 'discount') return '折扣';
|
||||
}
|
||||
}, {
|
||||
width: 18,
|
||||
title: '优惠金额',
|
||||
align: 'left',
|
||||
templet: function (data) {
|
||||
if (data.type == 'reward') {
|
||||
var html = `满${data.at_least}元减${data.money}`;
|
||||
return `<view title="${html}">${html}</view>`;
|
||||
}
|
||||
if (data.type == 'discount') {
|
||||
var text = '满' + data.at_least + '元打' + data.discount + '折';
|
||||
if (data.discount_limit) text += '(最多抵扣' + data.discount_limit + '元)';
|
||||
return '<view title="' + text + '">' + text + '</view>';
|
||||
}
|
||||
}
|
||||
}, {
|
||||
width: 17,
|
||||
title: '有效期',
|
||||
align: 'center',
|
||||
templet: data => {
|
||||
if (data.end_time) return this.$util.timeFormat(data.end_time);
|
||||
else return '长期有效';
|
||||
}
|
||||
}, {
|
||||
width: 10,
|
||||
title: '状态',
|
||||
align: 'center',
|
||||
return: data => {
|
||||
if (data.state == 1) return '未使用';
|
||||
if (data.state == 2) return '已使用';
|
||||
if (data.state == 3) return '已过期';
|
||||
}
|
||||
},{
|
||||
title: '适用场景',
|
||||
field: 'use_channel_name',
|
||||
width: 15,
|
||||
align: 'left',
|
||||
}, {
|
||||
width: 18,
|
||||
title: '领取时间',
|
||||
align: 'right',
|
||||
templet: data => {
|
||||
return this.$util.timeFormat(data.fetch_time);
|
||||
}
|
||||
}],
|
||||
pointCols: [{
|
||||
width: 20,
|
||||
title: '积分',
|
||||
align: 'left',
|
||||
field: 'account_data'
|
||||
}, {
|
||||
width: 25,
|
||||
title: '发生方式',
|
||||
align: 'left',
|
||||
field: 'type_name'
|
||||
}, {
|
||||
width: 25,
|
||||
title: '发生时间',
|
||||
align: 'left',
|
||||
templet: data => {
|
||||
var html = this.$util.timeFormat(data.create_time);
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
width: 30,
|
||||
title: '备注',
|
||||
align: 'left',
|
||||
field: 'remark'
|
||||
}],
|
||||
balanceCols: [{
|
||||
width: 10,
|
||||
title: '账户类型',
|
||||
align: 'left',
|
||||
field: 'account_type_name'
|
||||
}, {
|
||||
width: 15,
|
||||
title: '余额',
|
||||
align: 'left',
|
||||
field: 'account_data'
|
||||
}, {
|
||||
width: 20,
|
||||
title: '发生方式',
|
||||
align: 'left',
|
||||
field: 'type_name'
|
||||
}, {
|
||||
width: 25,
|
||||
title: '发生时间',
|
||||
align: 'left',
|
||||
templet: data => {
|
||||
var html = this.$util.timeFormat(data.create_time);
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
width: 30,
|
||||
title: '备注',
|
||||
align: 'left',
|
||||
field: 'remark'
|
||||
}],
|
||||
growthCols: [{
|
||||
width: 20,
|
||||
title: '成长值',
|
||||
align: 'left',
|
||||
field: 'account_data'
|
||||
}, {
|
||||
width: 25,
|
||||
title: '发生方式',
|
||||
align: 'left',
|
||||
field: 'type_name'
|
||||
}, {
|
||||
width: 25,
|
||||
title: '发生时间',
|
||||
align: 'left',
|
||||
templet: data => {
|
||||
var html = this.$util.timeFormat(data.create_time);
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
width: 30,
|
||||
title: '备注',
|
||||
align: 'left',
|
||||
field: 'remark'
|
||||
}],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getMemberInfo();
|
||||
this.getMemberLevel();
|
||||
let date = new Date();
|
||||
var y = date.getFullYear();
|
||||
var m = date.getMonth() + 1;
|
||||
var d = date.getDate();
|
||||
this.endTime = y + '-' + m + '-' + d;
|
||||
},
|
||||
watch: {
|
||||
memberId: function () {
|
||||
this.getMemberInfo();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkAdmin() {
|
||||
if (this.userInfo && this.userInfo.is_admin == 0) {
|
||||
// 检查当前账号是否有修改手机号的权限
|
||||
var isAgree = false;
|
||||
this.userInfo.user_group_list.forEach((item) => {
|
||||
if (item.store_id == this.globalStoreInfo.store_id) {
|
||||
if (item.menu_array.indexOf('member_edit') != -1) {
|
||||
isAgree = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (isAgree) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
getMemberInfo() {
|
||||
getMemberInfoById(this.memberId).then(res => {
|
||||
if (res.code >= 0) {
|
||||
res.data.birthday = res.data.birthday > 0 ? this.$util.timeFormat(res.data.birthday, 'Y-m-d') : '';
|
||||
this.memberInfo = res.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
getMemberLevel() {
|
||||
this.memberLevelList = [];
|
||||
getMemberLevelList().then(res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
for (let i in res.data) {
|
||||
this.memberLevelList.push({
|
||||
label: res.data[i]['level_name'],
|
||||
value: res.data[i]['level_id'].toString(),
|
||||
disabled: false
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
selectMemberLevel(index, item) {
|
||||
if (index >= 0) {
|
||||
this.applyMember.level_id = item.value;
|
||||
this.applyMember.member_level_name = item.label;
|
||||
this.memberInfo.member_level = item.value;
|
||||
} else {
|
||||
this.applyMember.level_id = '';
|
||||
this.applyMember.member_level_name = '';
|
||||
this.memberInfo.member_level = '';
|
||||
}
|
||||
},
|
||||
// 客户操作
|
||||
memberAction(type) {
|
||||
switch (type) {
|
||||
case 'memberInfo':
|
||||
this.$refs.memberInfoPop.open('center');
|
||||
break;
|
||||
case 'point':
|
||||
this.$refs.pointPop.open('center');
|
||||
break;
|
||||
case 'balance':
|
||||
this.$store.commit('app/setGlobalMemberInfo', this.memberInfo);
|
||||
this.$util.redirectTo('/pages/recharge/index');
|
||||
break;
|
||||
case 'sendCoupon':
|
||||
this.getCouponList();
|
||||
this.$refs.sendCouponPop.open('center');
|
||||
break;
|
||||
case 'growth':
|
||||
this.$refs.growthPop.open('center');
|
||||
break;
|
||||
case 'couponList':
|
||||
this.option = {
|
||||
member_id: this.memberId
|
||||
};
|
||||
this.$refs.couponListPop.open('center');
|
||||
break;
|
||||
case 'cardList':
|
||||
this.option = {
|
||||
member_id: this.memberId,
|
||||
status:1,
|
||||
};
|
||||
this.$refs.memberCardRecord.open('center');
|
||||
break;
|
||||
case 'pointList':
|
||||
// 积分列表
|
||||
this.option = {
|
||||
member_id: this.memberId,
|
||||
account_type: 'point'
|
||||
};
|
||||
this.$refs.pointListPop.open();
|
||||
break;
|
||||
case 'balanceList':
|
||||
// 余额列表
|
||||
this.option = {
|
||||
member_id: this.memberId,
|
||||
account_type: 'balance'
|
||||
};
|
||||
this.$refs.balanceListPop.open();
|
||||
break;
|
||||
case 'growthList':
|
||||
// 成长值列表
|
||||
this.option = {
|
||||
member_id: this.memberId,
|
||||
account_type: 'growth'
|
||||
};
|
||||
this.$refs.growthListPop.open();
|
||||
break;
|
||||
case 'applyMember':
|
||||
this.$refs.applyMemberPop.open();
|
||||
break;
|
||||
}
|
||||
},
|
||||
popClose(type) {
|
||||
this.$refs[type + 'Pop'].close();
|
||||
},
|
||||
//获取发放优惠券列表
|
||||
getCouponList() {
|
||||
let data = {
|
||||
page: this.sendCoupon.page,
|
||||
page_size: 7
|
||||
};
|
||||
getCouponTypeList(data).then(res => {
|
||||
if (res.code >= 0) {
|
||||
if (this.sendCoupon.page == 1) this.sendCoupon.list = [];
|
||||
if (res.data.list && res.data.list.length) {
|
||||
res.data.list.forEach((item, index) => {
|
||||
if (item.validity_type == 0) item.validity_name = '失效日期:' + this.$util.timeFormat(item.end_time);
|
||||
else if (item.validity_type == 1) item.validity_name = '领取后,' + item.fixed_term + '天有效';
|
||||
else item.validity_name = '长期有效';
|
||||
item.num = 0;
|
||||
});
|
||||
}
|
||||
this.sendCoupon.list = this.sendCoupon.list.concat(res.data.list);
|
||||
if (res.data.page_count >= this.sendCoupon.page) this.sendCoupon.page++;
|
||||
}
|
||||
});
|
||||
},
|
||||
// 发放数量
|
||||
dec: function (item) {
|
||||
if (item.num > 0) {
|
||||
item.num = item.num - 1;
|
||||
}
|
||||
},
|
||||
inc: function (item) {
|
||||
item.num = item.num + 1;
|
||||
},
|
||||
// 发放优惠券
|
||||
sendCouponFn() {
|
||||
if (!this.sendCoupon.list || !this.sendCoupon.list.length) return false;
|
||||
let data = {};
|
||||
data.member_id = this.memberInfo.member_id;
|
||||
data.coupon_data = '';
|
||||
let couponDataArr = [];
|
||||
|
||||
this.sendCoupon.list.forEach((item, index) => {
|
||||
if (item.num > 0) {
|
||||
let obj = {};
|
||||
obj.coupon_type_id = item.coupon_type_id;
|
||||
obj.num = item.num;
|
||||
couponDataArr.push(obj);
|
||||
}
|
||||
});
|
||||
if (couponDataArr.length <= 0) return false;
|
||||
data.coupon_data = JSON.stringify(couponDataArr);
|
||||
sendMemberCoupon(data).then(res => {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
this.sendCoupon.page = 1;
|
||||
this.sendCoupon.list = [];
|
||||
this.getMemberInfo();
|
||||
this.$refs.sendCouponPop.close();
|
||||
}
|
||||
});
|
||||
},
|
||||
//修改客户信息
|
||||
saveMemberInfo() {
|
||||
let data = {
|
||||
nickname: this.memberInfo.nickname,
|
||||
sex: this.memberInfo.sex,
|
||||
birthday: this.memberInfo.birthday,
|
||||
member_id: this.memberInfo.member_id,
|
||||
level_id: this.memberInfo.member_level
|
||||
};
|
||||
if (this.checkAdmin()) {
|
||||
data.mobile = this.memberInfo.mobile;
|
||||
}
|
||||
editMember(data).then(res => {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
this.getMemberInfo();
|
||||
this.popClose('memberInfo');
|
||||
}
|
||||
});
|
||||
},
|
||||
// 调整积分
|
||||
savePoint() {
|
||||
if (parseInt(this.pointData.num) < 0 && parseInt(this.memberInfo.point) < parseInt(this.pointData.num * -1)) {
|
||||
this.$util.showToast({
|
||||
title: '调整数额与当前积分之和不能小于0'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
modifyMemberPoint({
|
||||
member_id: this.memberInfo.member_id,
|
||||
adjust_num: this.pointData.num,
|
||||
remark: this.pointData.desc
|
||||
}).then(res => {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
this.pointData.num = 0;
|
||||
this.pointData.desc = '';
|
||||
this.getMemberInfo();
|
||||
this.popClose('point');
|
||||
}
|
||||
});
|
||||
},
|
||||
// 调整余额
|
||||
saveBalance() {
|
||||
modifyMemberBalance({
|
||||
member_id: this.memberInfo.member_id,
|
||||
adjust_num: this.balanceData.num,
|
||||
remark: this.balanceData.desc
|
||||
}).then(res => {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
this.balanceData.num = 0;
|
||||
this.balanceData.desc = '';
|
||||
this.getMemberInfo();
|
||||
this.popClose('balance');
|
||||
}
|
||||
});
|
||||
},
|
||||
// 调整成长值
|
||||
saveGrowth() {
|
||||
if (parseInt(this.growthData.num) < 0 && parseInt(this.memberInfo.growth) < parseInt(this.growthData.num * -1)) {
|
||||
this.$util.showToast({
|
||||
title: '调整数额与当前成长值之和不能小于0'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
modifyMemberGrowth({
|
||||
member_id: this.memberInfo.member_id,
|
||||
adjust_num: this.growthData.num,
|
||||
remark: this.growthData.desc
|
||||
}).then(res => {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
this.growthData.num = 0;
|
||||
this.growthData.desc = '';
|
||||
this.getMemberInfo();
|
||||
this.popClose('growth');
|
||||
}
|
||||
});
|
||||
},
|
||||
// 办理会员卡
|
||||
saveApplyMember() {
|
||||
if (!this.applyMember.level_id) {
|
||||
this.$util.showToast({
|
||||
title: '请选择会员卡等级'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
applyingMembershipCard({
|
||||
member_id: this.memberInfo.member_id,
|
||||
level_id: this.applyMember.level_id,
|
||||
member_code: this.applyMember.member_code
|
||||
}).then(res => {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
this.$root.page = 1;
|
||||
this.$root.search_text = 1;
|
||||
this.$root.getMemberListFn();
|
||||
this.popClose('applyMember');
|
||||
}
|
||||
});
|
||||
},
|
||||
headError(item) {
|
||||
item.headimg = this.defaultImg.head;
|
||||
}
|
||||
}
|
||||
}
|
||||
453
addon/cashier/source/os/components/ns-member-detail/index.scss
Executable file
453
addon/cashier/source/os/components/ns-member-detail/index.scss
Executable file
@@ -0,0 +1,453 @@
|
||||
.member-detail-wrap {
|
||||
width: 100%;
|
||||
border-left: 0;
|
||||
|
||||
.member-head {
|
||||
height: 0.66rem;
|
||||
line-height: 0.66rem;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
|
||||
.member-content {
|
||||
padding: 0.15rem;
|
||||
width: 100%;
|
||||
height: calc(100vh - 0.8rem);
|
||||
box-sizing: border-box;
|
||||
|
||||
.content-block {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.item-img {
|
||||
width: 0.7rem;
|
||||
height: 0.7rem;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.item-content {
|
||||
padding-left: 0.15rem;
|
||||
width: calc(100% - 0.7rem);
|
||||
box-sizing: border-box;
|
||||
|
||||
.item-title {
|
||||
width: 100%;
|
||||
font-size: 0.16rem;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
||||
.item-label {
|
||||
border: 0.01rem solid $primary-color;
|
||||
color: $primary-color;
|
||||
background-color: #fff;
|
||||
border-radius: 0.02rem;
|
||||
width: fit-content;
|
||||
padding: 0.01rem 0.05rem;
|
||||
margin-left: 0.15rem;
|
||||
}
|
||||
|
||||
.item-title-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 50%;
|
||||
font-size: 0.16rem;
|
||||
}
|
||||
}
|
||||
|
||||
.info-list {
|
||||
margin-top: 0.15rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.info-item {
|
||||
font-size: 0.14rem;
|
||||
margin-right: 0.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-block.account {
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
background-color: #ffffff;
|
||||
padding: 0.25rem 0;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 0.2rem;
|
||||
border-radius: 0.03rem;
|
||||
align-items: baseline;
|
||||
|
||||
.content-data-item {
|
||||
.data-item-title {}
|
||||
|
||||
.data-item-value {
|
||||
font-size: 0.26rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
.data-item-action {
|
||||
margin-top: 0.1rem;
|
||||
color: $primary-color;
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
|
||||
&:nth-child(2n) {
|
||||
margin-left: 0.1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-block.assets {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 0.2rem;
|
||||
|
||||
.content-data-left {
|
||||
background-color: #ffffff;
|
||||
padding: 0.25rem 0;
|
||||
border-radius: 0.03rem;
|
||||
width: calc(50% - 0.075rem);
|
||||
margin-right: 0.15rem;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
height: 1rem;
|
||||
|
||||
.content-data-item {
|
||||
.data-item-title {}
|
||||
|
||||
.data-item-value {
|
||||
font-size: 0.26rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
.data-item-action {
|
||||
margin-top: 0.15rem;
|
||||
color: $primary-color;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.content-block.action {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-top: 0.2rem;
|
||||
|
||||
.content-data-item {
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
width: calc(100% / 6);
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
padding: 0.15rem 0;
|
||||
border-radius: 0.03rem;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
margin-right: 0.15rem;
|
||||
cursor: pointer;
|
||||
|
||||
.data-item-icon {
|
||||
width: 0.55rem;
|
||||
height: 0.55rem;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.data-item-value {
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pop弹框
|
||||
.pop-box {
|
||||
background: #ffffff;
|
||||
width: 8rem;
|
||||
height: 7rem;
|
||||
|
||||
.pop-header {
|
||||
padding: 0 0.15rem 0 0.2rem;
|
||||
height: 0.5rem;
|
||||
line-height: 0.5rem;
|
||||
border-bottom: 0.01rem solid #f0f0f0;
|
||||
font-size: 0.14rem;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
border-radius: 0.02rem 0.2rem 0 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.pop-header-close {
|
||||
cursor: pointer;
|
||||
|
||||
text {
|
||||
font-size: 0.18rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pop-content {
|
||||
height: calc(100% - 1.05rem);
|
||||
overflow-y: auto;
|
||||
padding: 0.1rem 0.2rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pop-bottom {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0.1rem 0.2rem;
|
||||
button {
|
||||
width: 100%;
|
||||
line-height: 0.35rem;
|
||||
height: 0.35rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//表单
|
||||
.form-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 0.1rem;
|
||||
display: flex;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
width: 1.2rem;
|
||||
text-align: right;
|
||||
padding-right: 0.1rem;
|
||||
box-sizing: border-box;
|
||||
height: 0.32rem;
|
||||
line-height: 0.32rem;
|
||||
|
||||
.required {
|
||||
color: red;
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
}
|
||||
|
||||
.form-inline {
|
||||
width: 2.5rem;
|
||||
line-height: 0.32rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
.form-input {
|
||||
border-width: 0.01rem;
|
||||
border-style: solid;
|
||||
background-color: #fff;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
border-radius: 0.02rem;
|
||||
padding-left: 0.1rem;
|
||||
height: 0.32rem;
|
||||
line-height: 0.32rem;
|
||||
font-size: 0.14rem;
|
||||
border-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
border-width: 0.01rem;
|
||||
border-style: solid;
|
||||
background-color: #fff;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
border-radius: 0.02rem;
|
||||
padding-left: 0.1rem;
|
||||
line-height: 0.32rem;
|
||||
font-size: 0.14rem;
|
||||
border-color: #e6e6e6;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.word-aux {
|
||||
color: #999;
|
||||
font-size: 0.12rem;
|
||||
line-height: 1.5;
|
||||
margin-top: 0.05rem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.memberInfo-box {
|
||||
width: 5.2rem;
|
||||
height: 4.31rem;
|
||||
}
|
||||
|
||||
.pointPop-box {
|
||||
width: 4.2rem;
|
||||
height: 3.94rem;
|
||||
}
|
||||
|
||||
.balancePop-box {
|
||||
width: 4.2rem;
|
||||
height: 4.2rem;
|
||||
}
|
||||
|
||||
.coupon-list-pop-box {
|
||||
width: 10rem;
|
||||
height: 5.7rem;
|
||||
|
||||
.pop-content {
|
||||
height: calc(100% - 0.5rem);
|
||||
}
|
||||
|
||||
/deep/ .tpage {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.applyMemberPop-box {
|
||||
width: 4.2rem;
|
||||
height: 3.38rem;
|
||||
|
||||
.pop-content {
|
||||
overflow: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.sendCoupon-box {
|
||||
width: 9rem;
|
||||
height: 5.06rem;
|
||||
|
||||
.sendCoupon-content {
|
||||
padding: 0.1rem 0.2rem;
|
||||
|
||||
.coupon-table-head {
|
||||
display: flex;
|
||||
background: #f7f8fa;
|
||||
}
|
||||
|
||||
.coupon-table-body {
|
||||
height: 3.2rem;
|
||||
|
||||
.coupon-table-tr {
|
||||
display: flex;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
}
|
||||
|
||||
.table-input {
|
||||
height: 0.3rem;
|
||||
line-height: 0.3rem;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
padding: 0 0.1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.item-num {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 0.1rem;
|
||||
|
||||
.num-dec {
|
||||
width: 0.6rem;
|
||||
height: 0.25rem;
|
||||
background: #e6e6e6;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
border-radius: 30%;
|
||||
text-align: center;
|
||||
line-height: 0.23rem;
|
||||
font-size: 0.25rem;
|
||||
margin-right: 0.1rem;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.num-inc {
|
||||
width: 0.6rem;
|
||||
height: 0.25rem;
|
||||
background: $primary-color;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
border-radius: 30%;
|
||||
text-align: center;
|
||||
line-height: 0.23rem;
|
||||
font-size: 0.25rem;
|
||||
margin-left: 0.1rem;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-table-td:nth-child(4) {
|
||||
padding: 0 0.05rem;
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-table-td,
|
||||
.coupon-table-th {
|
||||
padding: 0 0.1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 0.5rem;
|
||||
|
||||
&:nth-child(1) {
|
||||
flex-basis: 30%;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
flex-basis: 20%;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
flex-basis: 30%;
|
||||
}
|
||||
|
||||
&:nth-child(4) {
|
||||
justify-content: flex-end;
|
||||
flex-basis: 20%;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pop-bottom {
|
||||
margin-top: 0.12rem;
|
||||
}
|
||||
|
||||
.empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 0.5rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
color: #909399;
|
||||
|
||||
.iconfont {
|
||||
font-size: 0.25rem;
|
||||
margin: 0.05rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
500
addon/cashier/source/os/components/ns-member-detail/ns-member-detail.vue
Executable file
500
addon/cashier/source/os/components/ns-member-detail/ns-member-detail.vue
Executable file
@@ -0,0 +1,500 @@
|
||||
<template>
|
||||
<view class="member-detail-wrap">
|
||||
<view class="member-head flex items-center justify-between">
|
||||
<text>会员详情</text>
|
||||
<text class="iconfont iconguanbi1 cursor-pointer" @click="$emit('close')"></text>
|
||||
</view>
|
||||
<view class="member-content">
|
||||
<view class="content-block">
|
||||
<view class="item-img">
|
||||
<image mode="aspectFill" v-if="memberInfo && memberInfo.headimg" :src="$util.img(memberInfo.headimg)" @error="headError(memberInfo)"/>
|
||||
<image mode="aspectFill" v-else :src="$util.img(defaultImg.head)"/>
|
||||
</view>
|
||||
<view class="item-content">
|
||||
<view class="item-title">
|
||||
<view class="item-title-text">{{ memberInfo && memberInfo.nickname ? memberInfo.nickname : '' }}</view>
|
||||
<view class="item-label" v-if="memberInfo && memberInfo.member_level && memberInfo.member_level_name">{{ memberInfo.member_level_name }}</view>
|
||||
</view>
|
||||
<view class="info-list">
|
||||
<view class="info-item">手机:{{ memberInfo && memberInfo.mobile ? memberInfo.mobile : '' }}</view>
|
||||
<view class="info-item" v-if="memberInfo && memberInfo.sex == 0">性别:未知</view>
|
||||
<view class="info-item" v-if="memberInfo && memberInfo.sex == 1">性别:男</view>
|
||||
<view class="info-item" v-if="memberInfo && memberInfo.sex == 2">性别:女</view>
|
||||
<view class="info-item">生日:{{ memberInfo && memberInfo.birthday ? memberInfo.birthday : '' }}</view>
|
||||
<view class="info-item" v-if="memberInfo && memberInfo.member_time">成为会员:{{ $util.timeFormat(memberInfo.member_time) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content-block account">
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">积分</view>
|
||||
<view class="data-item-value">{{ memberInfo && memberInfo.point ? parseInt(memberInfo.point) : '0' }}</view>
|
||||
<view class="data-item-action" @click="memberAction('pointList')">查看</view>
|
||||
</view>
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">储值余额(元)</view>
|
||||
<view class="data-item-value">{{ memberInfo && memberInfo.balance ? memberInfo.balance : '0.00' }}</view>
|
||||
<view class="data-item-action" @click="memberAction('balanceList')">查看</view>
|
||||
</view>
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">现金余额(元)</view>
|
||||
<view class="data-item-value">{{ memberInfo && memberInfo.balance_money ? memberInfo.balance_money : '0.00' }}</view>
|
||||
</view>
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">成长值</view>
|
||||
<view class="data-item-value">{{ memberInfo && memberInfo.growth ? memberInfo.growth : '0' }}</view>
|
||||
<view class="data-item-action" @click="memberAction('growthList')">查看</view>
|
||||
</view>
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">优惠券(张)</view>
|
||||
<view class="data-item-value">{{ memberInfo && memberInfo.coupon_num ? memberInfo.coupon_num : '0' }}</view>
|
||||
<view class="data-item-action" @click="memberAction('couponList')">查看</view>
|
||||
</view>
|
||||
<view class="content-data-item">
|
||||
<view class="data-item-title">卡包</view>
|
||||
<view class="data-item-value">{{ memberInfo && memberInfo.card_num ? memberInfo.card_num : '0' }}
|
||||
</view>
|
||||
<view class="data-item-action" @click="memberAction('cardList')">查看</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-block action">
|
||||
<view class="content-data-item" @click="memberAction('memberInfo')">
|
||||
<view class="data-item-icon">
|
||||
<image mode="aspectFit" src="@/static/member/icon-member-info.png" />
|
||||
</view>
|
||||
<view class="data-item-value">会员信息</view>
|
||||
</view>
|
||||
<view class="content-data-item" @click="memberAction('point')">
|
||||
<view class="data-item-icon">
|
||||
<image mode="aspectFit" src="@/static/member/icon-member-point.png" />
|
||||
</view>
|
||||
<view class="data-item-value">积分调整</view>
|
||||
</view>
|
||||
<view class="content-data-item" @click="memberAction('balance')">
|
||||
<view class="data-item-icon">
|
||||
<image mode="aspectFit" src="@/static/member/icon-member-balance.png" />
|
||||
</view>
|
||||
<view class="data-item-value">余额充值</view>
|
||||
</view>
|
||||
<view class="content-data-item" @click="memberAction('sendCoupon')">
|
||||
<view class="data-item-icon">
|
||||
<image mode="aspectFit" src="@/static/member/icon-member-coupon.png" />
|
||||
</view>
|
||||
<view class="data-item-value">送优惠券</view>
|
||||
</view>
|
||||
<view class="content-data-item" @click="memberAction('growth')">
|
||||
<view class="data-item-icon">
|
||||
<image mode="aspectFit" src="@/static/member/icon-member-growth.png" />
|
||||
</view>
|
||||
<view class="data-item-value">成长值调整</view>
|
||||
</view>
|
||||
<view class="content-data-item" @click="memberAction('applyMember')" v-if="memberInfo && !memberInfo.is_member">
|
||||
<view class="data-item-icon">
|
||||
<image mode="aspectFit" src="@/static/member/icon-member-apply.png" />
|
||||
</view>
|
||||
<view class="data-item-value">办理会员</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 会员详情 -->
|
||||
<uni-popup ref="memberInfoPop">
|
||||
<view class="pop-box memberInfo-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">会员详情</view>
|
||||
<view class="pop-header-close" @click="popClose('memberInfo')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y="true" class="common-scrollbar pop-content">
|
||||
<view class="form-content" v-if="memberInfo">
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
昵称:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<input class="form-input" placeholder="请输入会员昵称" v-model="memberInfo.nickname" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
手机号:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<input class="form-input" placeholder="请输入手机号" v-model="memberInfo.mobile" maxlength="11" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
会员等级:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<select-lay :zindex="10" :value="memberInfo.member_level" name="names" placeholder="请选择会员等级" :options="memberLevelList" @selectitem="selectMemberLevel"/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
性别:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<uni-data-checkbox v-model="memberInfo.sex" :localdata="sex"></uni-data-checkbox>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
生日:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<uni-datetime-picker :end="endTime" v-model="memberInfo.birthday" type="date" :clearIcon="false" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
注册时间:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
{{ memberInfo && memberInfo.reg_time ? $util.timeFormat(memberInfo.reg_time) : '--' }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
最后访问时间:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
{{ memberInfo && memberInfo.last_login_time ? $util.timeFormat(memberInfo.last_login_time) : '--' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="pop-bottom">
|
||||
<button class="primary-btn" @click="saveMemberInfo">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 积分调整 -->
|
||||
<uni-popup ref="pointPop">
|
||||
<view class="pop-box pointPop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">调整积分</view>
|
||||
<view class="pop-header-close" @click="popClose('point')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y="true" class="common-scrollbar pop-content">
|
||||
<view class="form-content">
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
当前积分:
|
||||
</view>
|
||||
<view class="form-inline">{{ memberInfo && memberInfo.point ? memberInfo.point : '0' }}</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
调整数额:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<input class="form-input" type="number" placeholder="请输入调整数额" v-model="pointData.num" />
|
||||
<view class="word-aux">调整数额与当前积分数相加不能小于0</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
备注:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<textarea class="form-textarea" v-model="pointData.desc"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="pop-bottom">
|
||||
<button class="primary-btn" @click="savePoint">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 发放优惠券 -->
|
||||
<uni-popup ref="sendCouponPop">
|
||||
<view class="pop-box sendCoupon-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">送优惠券</view>
|
||||
<view class="pop-header-close" @click="popClose('sendCoupon')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="common-scrollbar sendCoupon-content">
|
||||
<view class="coupon-table-head">
|
||||
<view class="coupon-table-th">优惠券名称</view>
|
||||
<view class="coupon-table-th">金额</view>
|
||||
<view class="coupon-table-th">有效期</view>
|
||||
<view class="coupon-table-th">发放数量</view>
|
||||
</view>
|
||||
<scroll-view class="coupon-table-body" @scrolltolower="getCouponList()" scroll-y="true">
|
||||
<view class="coupon-table-tr" v-for="(item, index) in sendCoupon.list" :key="index">
|
||||
<view class="coupon-table-td">{{ item.coupon_name }}</view>
|
||||
<view class="coupon-table-td">{{ item.money }}</view>
|
||||
<view class="coupon-table-td">{{ item.validity_name }}</view>
|
||||
<view class="coupon-table-td">
|
||||
<view class="item-num">
|
||||
<view class="num-dec" v-on:click="dec(item)">-</view>
|
||||
<input class="table-input" type="text" v-model="item.num" />
|
||||
<view class="num-inc" v-on:click="inc(item)">+</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty" v-if="!sendCoupon.list.length">
|
||||
<view class="iconfont iconwushuju"></view>
|
||||
<view>暂无数据</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="pop-bottom">
|
||||
<button v-if="sendCoupon.list.length" class="primary-btn" @click="sendCouponFn">发放优惠券</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 余额调整 -->
|
||||
<uni-popup ref="balancePop">
|
||||
<view class="pop-box pointPop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">调整余额</view>
|
||||
<view class="pop-header-close" @click="popClose('balance')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y="true" class="common-scrollbar pop-content">
|
||||
<view class="form-content">
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
当前余额:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
{{ memberInfo && memberInfo.balance ? memberInfo.balance : '0.00' }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
调整数额:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<input class="form-input" type="number" placeholder="请输入调整数额" v-model="balanceData.num" />
|
||||
<view class="word-aux">调整数额与当前储值余额相加不能小于0</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
备注:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<textarea class="form-textarea" v-model="balanceData.desc"></textarea>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="pop-bottom">
|
||||
<button class="primary-btn" @click="saveBalance">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 成长值调整 -->
|
||||
<uni-popup ref="growthPop">
|
||||
<view class="pop-box pointPop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">调整成长值</view>
|
||||
<view class="pop-header-close" @click="popClose('growth')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y="true" class="common-scrollbar pop-content">
|
||||
<view class="form-content">
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
当前成长值:
|
||||
</view>
|
||||
<view class="form-inline">{{ memberInfo && memberInfo.growth ? memberInfo.growth : '0' }}</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
调整数额:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<input class="form-input" type="number" placeholder="请输入调整数额" v-model="growthData.num" />
|
||||
<view class="word-aux">调整数额与当前成长值相加不能小于0</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
备注:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<textarea class="form-textarea" v-model="growthData.desc"></textarea>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="pop-bottom">
|
||||
<button class="primary-btn" @click="saveGrowth">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 办理会员 -->
|
||||
<uni-popup ref="applyMemberPop">
|
||||
<view class="pop-box applyMemberPop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">办理会员</view>
|
||||
<view class="pop-header-close" @click="popClose('applyMember')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="common-scrollbar pop-content">
|
||||
<view class="form-content">
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
会员等级:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<select-lay :zindex="10" :value="applyMember.level_id" name="names" placeholder="请选择会员等级" :options="memberLevelList" @selectitem="selectMemberLevel"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
会员卡号:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<input class="form-input" type="text" placeholder="请输入会员卡号" v-model="applyMember.member_code" />
|
||||
<view class="word-aux">会员卡号为会员唯一编号,若不设置将会自动生成</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pop-bottom">
|
||||
<button class="primary-btn" @click="saveApplyMember">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 优惠券列表 -->
|
||||
<uni-popup ref="couponListPop">
|
||||
<view class="pop-box coupon-list-pop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">优惠券</view>
|
||||
<view class="pop-header-close" @click="popClose('couponList')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="common-scrollbar pop-content">
|
||||
<dataTable url="/cashier/storeapi/member/coupon" :cols="couponCols" ref="table" :option="option" :pagesize="pageSize"></dataTable>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 积分列表 -->
|
||||
<uni-popup ref="pointListPop">
|
||||
<view class="pop-box coupon-list-pop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">积分</view>
|
||||
<view class="pop-header-close" @click="popClose('pointList')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y="true" class="common-scrollbar pop-content">
|
||||
<dataTable url="/cashier/storeapi/member/memberaccountlist" :cols="pointCols" ref="table" :option="option" :pagesize="pageSize"></dataTable>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 余额列表 -->
|
||||
<uni-popup ref="balanceListPop">
|
||||
<view class="pop-box coupon-list-pop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">余额</view>
|
||||
<view class="pop-header-close" @click="popClose('balanceList')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y="true" class="common-scrollbar pop-content">
|
||||
<dataTable url="/cashier/storeapi/member/memberaccountlist" :cols="balanceCols" ref="table" :option="option" :pagesize="pageSize"></dataTable>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 成长值列表 -->
|
||||
<uni-popup ref="growthListPop">
|
||||
<view class="pop-box coupon-list-pop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">成长值</view>
|
||||
<view class="pop-header-close" @click="popClose('growthList')">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y="true" class="common-scrollbar pop-content">
|
||||
<dataTable url="/cashier/storeapi/member/memberaccountlist" :cols="growthCols" ref="table" :option="option" :pagesize="pageSize"></dataTable>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 卡项 -->
|
||||
<ns-member-card-record ref="memberCardRecord" :option="option"/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dataTable from '@/components/uni-data-table/uni-data-table.vue';
|
||||
import nsMemberCardRecord from '@/components/ns-member-card-record/ns-member-card-record.vue';
|
||||
import index from './index.js';
|
||||
export default {
|
||||
components: {
|
||||
dataTable,
|
||||
nsMemberCardRecord
|
||||
},
|
||||
mixins: [index]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
106
addon/cashier/source/os/components/ns-order-log/ns-order-log.vue
Executable file
106
addon/cashier/source/os/components/ns-order-log/ns-order-log.vue
Executable file
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<view class="journal">
|
||||
<view class="item" v-for="(item, index) in list" :key="index">
|
||||
<view class="time">
|
||||
<view>{{ $util.timeFormat(item.action_time).split(' ')[0] }}</view>
|
||||
<view>{{ $util.timeFormat(item.action_time).split(' ')[1] }}</view>
|
||||
</view>
|
||||
<view class="unit">
|
||||
<view class="top">
|
||||
<view class="core"></view>
|
||||
<view class="unit-separate"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="message">{{ item.action }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
mounted() {},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.journal {
|
||||
padding-left: 0.1rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
height: 0.7rem;
|
||||
display: flex;
|
||||
|
||||
.time {
|
||||
margin-right: 0.1rem;
|
||||
min-width: 1rem;
|
||||
|
||||
view:nth-child(1) {
|
||||
font-size: 0.16rem;
|
||||
margin-bottom: 0.1rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
view:nth-child(2) {
|
||||
font-size: 0.14rem;
|
||||
color: #999999;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.unit {
|
||||
width: 0.18rem;
|
||||
height: 100%;
|
||||
margin-right: 0.1rem;
|
||||
|
||||
.top {
|
||||
width: 0.18rem;
|
||||
height: 0.18rem;
|
||||
border-radius: 50%;
|
||||
background: $primary-color;
|
||||
position: relative;
|
||||
|
||||
.core {
|
||||
background: #ffffff;
|
||||
width: 0.08rem;
|
||||
height: 0.08rem;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.unit-separate {
|
||||
position: absolute;
|
||||
width: 0.01rem;
|
||||
height: 0.7rem;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: $primary-color;
|
||||
z-index: 555;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
1023
addon/cashier/source/os/components/ns-payment/index.js
Executable file
1023
addon/cashier/source/os/components/ns-payment/index.js
Executable file
File diff suppressed because it is too large
Load Diff
786
addon/cashier/source/os/components/ns-payment/index.scss
Executable file
786
addon/cashier/source/os/components/ns-payment/index.scss
Executable file
@@ -0,0 +1,786 @@
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
& > view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.payment-wrap {
|
||||
.header {
|
||||
height: 0.66rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
}
|
||||
|
||||
.body {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
padding: 0.15rem 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.info-wrap {
|
||||
flex: 1;
|
||||
width: 0;
|
||||
margin-right: 0.15rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
background-color: #f7f8fa;
|
||||
padding-bottom: 0.15rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
/deep/ .uni-scroll-view-content {
|
||||
margin: 0 0.15rem;
|
||||
width: calc(100% - 0.3rem);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.payment-money {
|
||||
text-align: right;
|
||||
font-size: 0.2rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
line-height: 0.6rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
line-height: 0.6rem;
|
||||
font-size: 0.16rem;
|
||||
}
|
||||
|
||||
.uni-flex {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.type-item {
|
||||
padding: 0.2rem 0.1rem;
|
||||
background: #fff;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 0.16rem;
|
||||
margin: 0 0.1rem 0.1rem 0;
|
||||
width: calc((100% - 0.86rem) / 3);
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
border-radius: 0.02rem;
|
||||
|
||||
&.account {
|
||||
width: calc((100% - 0.86rem) / 2);
|
||||
}
|
||||
|
||||
.name {
|
||||
flex: 1;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&:nth-child(3n + 3) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
color: $primary-color;
|
||||
font-size: 0.3rem;
|
||||
margin-right: 0.1rem;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: #fe2278;
|
||||
margin-left: 0.05rem;
|
||||
}
|
||||
|
||||
.iconxuanzhong {
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: $primary-color;
|
||||
|
||||
.iconxuanzhong {
|
||||
display: block;
|
||||
right: -0.11rem;
|
||||
bottom: -0.01rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
background: #f5f5f5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.pay-type {
|
||||
.type-item {
|
||||
padding: 0.15rem 0.1rem;
|
||||
}
|
||||
|
||||
.pay-icon {
|
||||
color: #fff;
|
||||
background: #f0f0f0;
|
||||
width: 0.3rem;
|
||||
height: 0.3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.16rem;
|
||||
border-radius: 0.05rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
padding-top: 0.15rem;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
.scancode {
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0 0 0 0.1rem;
|
||||
min-width: 1rem;
|
||||
}
|
||||
|
||||
.print-ticket {
|
||||
flex: 1;
|
||||
width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bill-wrap {
|
||||
width: 3rem;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
font-size: 0.2rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
line-height: 0.6rem;
|
||||
}
|
||||
|
||||
.body {
|
||||
padding: 0;
|
||||
margin: 0 0.15rem;
|
||||
display: block;
|
||||
height: auto;
|
||||
|
||||
.block-title {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
height: 0.35rem;
|
||||
margin-top: 0.2rem;
|
||||
|
||||
text {
|
||||
padding: 0 0.2rem;
|
||||
background: #fff;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
z-index: 1;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 0.16rem;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
border-top: 0.01rem dashed #e6e6e6;
|
||||
}
|
||||
}
|
||||
|
||||
.bill-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
line-height: 1;
|
||||
align-items: center;
|
||||
margin-top: 0.2rem;
|
||||
|
||||
.text {
|
||||
color: #fe2278;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.remark-info {
|
||||
padding: 0.1rem;
|
||||
background-color: var(--primary-color-light-9);
|
||||
color: $primary-color;
|
||||
margin-top: 0.1rem;
|
||||
font-size: 0.12rem;
|
||||
}
|
||||
}
|
||||
|
||||
.pay-result {
|
||||
.body {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
text-align: center;
|
||||
|
||||
&.status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
|
||||
.iconfont {
|
||||
font-size: 1rem;
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
.msg {
|
||||
margin-top: 0.1rem;
|
||||
font-size: 0.16rem;
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
height: 0.66rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-top: 0.01rem solid #e6e6e6;
|
||||
justify-content: center;
|
||||
|
||||
button {
|
||||
margin: 0 0 0 0.15rem;
|
||||
width: auto;
|
||||
min-width: 1.6rem;
|
||||
height: 0.45rem;
|
||||
line-height: 0.45rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.money-wrap {
|
||||
background: #fff;
|
||||
border-radius: 0.05rem;
|
||||
|
||||
.head {
|
||||
height: 0.6rem;
|
||||
line-height: 0.6rem;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
|
||||
text {
|
||||
font-size: 0.16rem;
|
||||
}
|
||||
|
||||
.iconguanbi1 {
|
||||
position: absolute;
|
||||
right: 0.15rem;
|
||||
font-size: 0.22rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
display: flex;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
height: 0.6rem;
|
||||
align-items: center;
|
||||
margin: 0 0.2rem;
|
||||
padding: 0 0.15rem;
|
||||
|
||||
.unit {
|
||||
font-size: 0.25rem;
|
||||
}
|
||||
|
||||
.money {
|
||||
margin-left: 0.05rem;
|
||||
font-size: 0.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.keyboard-wrap {
|
||||
width: 4rem;
|
||||
padding: 0 0.2rem 0.3rem 0.2rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-wrap {
|
||||
background: #fff;
|
||||
width: 6rem;
|
||||
border-radius: 0.05rem;
|
||||
|
||||
.head {
|
||||
height: 0.6rem;
|
||||
line-height: 0.6rem;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
|
||||
text {
|
||||
font-size: 0.16rem;
|
||||
}
|
||||
|
||||
.iconguanbi1 {
|
||||
position: absolute;
|
||||
right: 0.15rem;
|
||||
font-size: 0.22rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
padding: 0.1rem 0.15rem;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.item {
|
||||
margin: 0 0.1rem 0.1rem 0;
|
||||
padding: 0.1rem 0;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
width: calc((100% - 0.14rem) / 2);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
.iconxuanzhong {
|
||||
position: absolute;
|
||||
display: none;
|
||||
right: -0.01rem;
|
||||
bottom: -0.01rem;
|
||||
font-size: 0.3rem;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: $primary-color;
|
||||
|
||||
.iconxuanzhong {
|
||||
display: block;
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2n + 2) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.money {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 0.6rem;
|
||||
min-width: 1rem;
|
||||
font-size: 0.2rem;
|
||||
line-height: 1;
|
||||
|
||||
.unit {
|
||||
font-size: 0.16rem;
|
||||
margin-top: 0.05rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
padding: 0 0.1rem;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.time,
|
||||
.limit {
|
||||
font-size: 0.12rem;
|
||||
color: #999;
|
||||
line-height: 1;
|
||||
margin-top: 0.05rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.safe-verify-popup {
|
||||
width: 4.4rem;
|
||||
height: 3.1rem;
|
||||
background-color: #fff;
|
||||
border-radius: 0.1rem;
|
||||
|
||||
.header {
|
||||
height: 0.6rem;
|
||||
line-height: 0.6rem;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
.type-wrap {
|
||||
display: flex;
|
||||
|
||||
.item {
|
||||
margin-left: 0.15rem;
|
||||
font-size: 0.16rem;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
font-size: 0.18rem;
|
||||
color: $primary-color;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.iconguanbi1 {
|
||||
position: absolute;
|
||||
right: 0.15rem;
|
||||
top: 0;
|
||||
font-size: 0.22rem;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 0.3rem;
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
|
||||
.member-code-hint{
|
||||
margin-top: .3rem;
|
||||
font-size: .16rem;
|
||||
}
|
||||
|
||||
.tips {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.mobile {
|
||||
font-size: 0.25rem;
|
||||
font-weight: bold;
|
||||
margin-top: 0.05rem;
|
||||
}
|
||||
|
||||
.sms-code {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 0.15rem;
|
||||
border-bottom: 0.01rem solid #eee;
|
||||
padding: 0.15rem 0;
|
||||
|
||||
view {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
margin: 0 0.1rem 0 0;
|
||||
padding: 0;
|
||||
border-bottom: none;
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
|
||||
text {
|
||||
position: absolute;
|
||||
right: 0.1rem;
|
||||
font-size: 0.2rem;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.send-tip {
|
||||
color: $primary-color;
|
||||
font-size: 0.13rem;
|
||||
cursor: pointer;
|
||||
|
||||
&.disabled {
|
||||
color: #999;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
|
||||
.primary-btn {
|
||||
margin-top: 0.3rem;
|
||||
line-height: 0.4rem;
|
||||
}
|
||||
|
||||
.scancode-wrap {
|
||||
text-align: center;
|
||||
|
||||
.input-wrap {
|
||||
display: flex;
|
||||
|
||||
view {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
|
||||
input {
|
||||
width: 0;
|
||||
flex: 1;
|
||||
height: 0.5rem;
|
||||
border: 0.01rem solid #cccccc;
|
||||
text-align: center;
|
||||
padding: 0 0.1rem;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s;
|
||||
|
||||
&.focus {
|
||||
border-color: $primary-color;
|
||||
box-shadow: 0 0 0.02rem 0.02rem var(--primary-color-light-7);
|
||||
}
|
||||
}
|
||||
|
||||
text {
|
||||
position: absolute;
|
||||
right: 0.1rem;
|
||||
font-size: 0.2rem;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.primary-btn {
|
||||
margin: 0 0 0 0.1rem;
|
||||
line-height: 0.5rem;
|
||||
width: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
image {
|
||||
width: 3rem;
|
||||
padding: 0.2rem 0.4rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.third-popup {
|
||||
width: 4rem;
|
||||
height: 5rem;
|
||||
background-color: #fff;
|
||||
border-radius: 0.1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.head {
|
||||
height: 0.8rem;
|
||||
line-height: 0.8rem;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
text {
|
||||
font-size: 0.25rem;
|
||||
}
|
||||
|
||||
.iconguanbi1 {
|
||||
position: absolute;
|
||||
right: 0.15rem;
|
||||
font-size: 0.22rem;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.money {
|
||||
text-align: center;
|
||||
font-size: 0.18rem;
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
.scan-code-type {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin-top: 0.2rem;
|
||||
background-color: #f5f5f5;
|
||||
|
||||
.type-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
line-height: 0.5rem;
|
||||
font-size: 0.16rem;
|
||||
cursor: pointer;
|
||||
border-bottom: 0.03rem solid #f5f5f5;
|
||||
position: relative;
|
||||
|
||||
&.active {
|
||||
border-bottom: 0.03rem solid $primary-color;
|
||||
}
|
||||
|
||||
&:last-child::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 20%;
|
||||
width: 0.01rem;
|
||||
height: 60%;
|
||||
background: #ddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.qrcode-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.empty {
|
||||
padding: 1rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qrcode-item {
|
||||
height: 1.3rem;
|
||||
width: 1.3rem;
|
||||
padding: 0.1rem;
|
||||
box-shadow: 0 0.02rem 0.1rem 0 rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.qrcode {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 0.25rem;
|
||||
position: absolute !important;
|
||||
z-index: 5;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
margin-left: 0.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scancode-wrap {
|
||||
view {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
width: 3.3rem;
|
||||
height: 0.5rem;
|
||||
border: 0.01rem solid #cccccc;
|
||||
text-align: center;
|
||||
padding: 0 0.1rem;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s;
|
||||
|
||||
&.focus {
|
||||
border-color: $primary-color;
|
||||
box-shadow: 0 0 0.02rem 0.02rem var(--primary-color-light-7);
|
||||
}
|
||||
}
|
||||
|
||||
text {
|
||||
position: absolute;
|
||||
right: 0.1rem;
|
||||
font-size: 0.2rem;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
image {
|
||||
width: 3.3rem;
|
||||
padding: 0.2rem 0.4rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.remark-wrap {
|
||||
width: 6rem;
|
||||
background-color: #fff;
|
||||
border-radius: 0.04rem;
|
||||
box-shadow: 0 0.01rem 0.12rem 0 rgba(0, 0, 0, 0.1);
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 0.15rem;
|
||||
height: 0.45rem;
|
||||
line-height: 0.45rem;
|
||||
border-bottom: 0.01rem solid #e8eaec;
|
||||
|
||||
.iconfont {
|
||||
font-size: $uni-font-size-lg;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
padding: 0.15rem 0.15rem 0.1rem;
|
||||
|
||||
textarea {
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
width: 100%;
|
||||
padding: 0.1rem;
|
||||
box-sizing: border-box;
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
|
||||
.placeholder-class {
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
height: 0.5rem;
|
||||
padding-bottom: 0.05rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
button {
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
}
|
||||
366
addon/cashier/source/os/components/ns-payment/ns-payment.vue
Executable file
366
addon/cashier/source/os/components/ns-payment/ns-payment.vue
Executable file
@@ -0,0 +1,366 @@
|
||||
<template>
|
||||
<view class="container" v-if="payInfo">
|
||||
<view class="uni-flex uni-column payment-wrap" v-show="payStatus == 'pay'">
|
||||
<view class="header">结算</view>
|
||||
<view class="body">
|
||||
<view class="info-wrap">
|
||||
<scroll-view scroll-y="true" class="info">
|
||||
<view class="payment-money">费用总额:¥{{ payInfo.original_money | moneyFormat }}</view>
|
||||
<block v-if="promotionShow">
|
||||
<view class="title">营销优惠</view>
|
||||
<view class="uni-flex">
|
||||
<view class="type-item" :class="{ disabled: payInfo.offset.coupon_array.member_coupon_list.length == 0, active: discount.coupon_id }" @click="selectCoupon" v-if="payInfo.offset.coupon_array">
|
||||
<view class="iconfont iconyouhuiquan"></view>
|
||||
<view class="name" v-show="!discount.coupon_id">
|
||||
优惠券
|
||||
<text class="text" v-if="payInfo.offset.coupon_array.member_coupon_list.length">
|
||||
({{ payInfo.offset.coupon_array.member_coupon_list.length }}张可用)
|
||||
</text>
|
||||
</view>
|
||||
<view class="name" v-show="discount.coupon_id">
|
||||
优惠券抵扣
|
||||
<text class="text">{{ payInfo.coupon_money }}元</text>
|
||||
</view>
|
||||
<view class="iconfont iconxuanzhong"></view>
|
||||
</view>
|
||||
<view class="type-item" :class="{ active: discount.reduction }" @click="reduction" v-if="payInfo.collectmoney_config.reduction == 1">
|
||||
<view class="iconfont iconjianmianjine"></view>
|
||||
<view class="name" v-if="discount.reduction" @click.stop="openMoneyPopup({ title: '减免金额', money: $util.moneyFormat(discount.reduction), type: 'reduction' })">
|
||||
减免
|
||||
<text class="text">{{ discount.reduction }}元</text>
|
||||
</view>
|
||||
<view v-else class="name">减免金额</view>
|
||||
<view class="iconfont iconxuanzhong"></view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<block v-if="payInfo.offset.point_array || payInfo.offset.balance">
|
||||
<view class="title">账户余额</view>
|
||||
<view class="uni-flex">
|
||||
<view class="type-item account" :class="{ active: discount.is_use_balance, disabled: balance == 0 }" @click="useBalance" v-if="payInfo.offset.balance">
|
||||
<view class="iconfont iconyue"></view>
|
||||
<view class="name" v-if="discount.is_use_balance">
|
||||
余额支付
|
||||
<text class="text">{{ payInfo.total_balance | moneyFormat }}元</text>
|
||||
</view>
|
||||
<view class="name" v-else>
|
||||
账户余额
|
||||
<text class="text" v-if="balance > 0">{{ balance | moneyFormat }}元</text>
|
||||
</view>
|
||||
<view class="iconfont iconxuanzhong"></view>
|
||||
</view>
|
||||
<view class="type-item account" :class="{ active: discount.is_use_point, disabled: payInfo.offset.point_array.point == 0 }" @click="usePoint" v-if="payInfo.offset.point_array">
|
||||
<view class="iconfont iconjifen1"></view>
|
||||
<view class="name" v-if="discount.is_use_point">
|
||||
积分抵扣
|
||||
<text class="text">{{ payInfo.point_money | moneyFormat }}元({{ parseInt(payInfo.offset.point_array.point) }}积分)</text>
|
||||
</view>
|
||||
<view class="name" v-else>
|
||||
账户积分
|
||||
<text class="text" v-if="globalMemberInfo.point">{{ globalMemberInfo.point }}积分</text>
|
||||
</view>
|
||||
<view class="iconfont iconxuanzhong"></view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<view class="title">支付方式</view>
|
||||
<view class="uni-flex pay-type">
|
||||
<block v-for="(item, key,index) in payType" :key="key">
|
||||
<view class="type-item" @click="switchPayType(item.type)" :class="{ active: item.type == type }">
|
||||
<view class="pay-icon iconfont" :style="{ background: item.background }" :class="item.icon"></view>
|
||||
<view class="name">{{ item.name }} [{{ item.hotKey }}]</view>
|
||||
<view class="iconfont iconxuanzhong"></view>
|
||||
</view>
|
||||
</block>
|
||||
<view class="type-item" @click="switchMemberCode()" :class="{ active: discount.is_use_balance}">
|
||||
<view class="pay-icon iconfont iconhuiyuanma" :style="{ background: '#F7861E' }"></view>
|
||||
<view class="name">
|
||||
<text>会员码 [M]</text>
|
||||
<template v-if="discount.is_use_balance">
|
||||
<text style="margin-left: 0.05rem;">(</text>
|
||||
<text style="margin-left: 0.05rem;">使用余额</text>
|
||||
<text class="text">{{ payInfo.total_balance | moneyFormat }}元</text>
|
||||
<text style="margin-left: 0.05rem;">)</text>
|
||||
</template>
|
||||
</view>
|
||||
<!-- <view class="iconfont iconxuanzhong"></view> -->
|
||||
</view>
|
||||
</view>
|
||||
<view class="remark-info" v-if="payInfo.remark">备注:{{ payInfo.remark }}</view>
|
||||
</scroll-view>
|
||||
<view class="button-wrap">
|
||||
<view class="print-ticket">
|
||||
<checkbox-group @change="autoPrintTicket = !autoPrintTicket">
|
||||
<label>
|
||||
<checkbox :checked="autoPrintTicket" style="transform:scale(0.7)" />
|
||||
<text>打印小票</text>
|
||||
</label>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
<button class="default-btn" @click="openRemark">备注</button>
|
||||
<button class="default-btn cancel-btn" plain @click="cancelPayment">取消 [Esc]</button>
|
||||
<button class="primary-btn" @click="confirm()" v-if="type != 'third' || payInfo.pay_money == 0">收款 [Enter]</button>
|
||||
<button class="primary-btn" @click="thirdConfirm()" v-else>收款 [Enter]</button>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="bill-wrap">
|
||||
<view class="title">支付明细</view>
|
||||
<view class="body">
|
||||
<view class="bill-info">
|
||||
<view>费用总额</view>
|
||||
<view>¥{{ payInfo.original_money | moneyFormat }}</view>
|
||||
</view>
|
||||
<view class="block-title"><text>营销优惠</text></view>
|
||||
<view class="bill-info">
|
||||
<view>减免金额</view>
|
||||
<view class="text">
|
||||
-¥{{ payInfo.offset.reduction ? $util.moneyFormat(payInfo.offset.reduction) : '0.00' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="bill-info" v-if="payInfo.offset.coupon_array">
|
||||
<view>优惠券</view>
|
||||
<view class="text">-¥{{ $util.moneyFormat(payInfo.coupon_money) }}</view>
|
||||
</view>
|
||||
<view class="bill-info" v-if="payInfo.offset.hongbao_array">
|
||||
<view>红包</view>
|
||||
<view class="text">-¥{{ $util.moneyFormat(payInfo.hongbao_money) }}</view>
|
||||
</view>
|
||||
<view class="bill-info" v-if="payInfo.offset.point_array">
|
||||
<view>积分抵扣</view>
|
||||
<view class="text">-¥{{ $util.moneyFormat(payInfo.point_money) }}</view>
|
||||
</view>
|
||||
<block v-if="payInfo.offset.balance">
|
||||
<view class="block-title"><text>余额抵扣</text></view>
|
||||
<view class="bill-info">
|
||||
<view>余额支付</view>
|
||||
<view>-¥{{ $util.moneyFormat(payInfo.total_balance) }}</view>
|
||||
</view>
|
||||
</block>
|
||||
<view class="block-title"><text>支付方式</text></view>
|
||||
<view class="bill-info">
|
||||
<view>{{ payType[type].name }}</view>
|
||||
<view v-show="type == 'cash'">
|
||||
¥{{ payInfo.cash > 0 ? $util.moneyFormat(payInfo.cash) : $util.moneyFormat(payInfo.pay_money) }}
|
||||
</view>
|
||||
<view v-show="type != 'cash'">¥{{ payInfo.pay_money | moneyFormat }}</view>
|
||||
</view>
|
||||
<view class="block-title"></view>
|
||||
<view class="bill-info">
|
||||
<view>需支付</view>
|
||||
<view>¥{{ payInfo.pay_money | moneyFormat }}</view>
|
||||
</view>
|
||||
<view class="bill-info">
|
||||
<view>实付</view>
|
||||
<view v-show="type == 'cash'">
|
||||
¥{{ payInfo.cash > 0 ? $util.moneyFormat(payInfo.cash) : $util.moneyFormat(payInfo.pay_money) }}
|
||||
</view>
|
||||
<view v-show="type != 'cash'">¥{{ payInfo.pay_money | moneyFormat }}</view>
|
||||
</view>
|
||||
<view class="bill-info" v-if="payInfo.cash_change > 0">
|
||||
<view>找零</view>
|
||||
<view>¥{{ payInfo.cash_change | moneyFormat }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 支付结果 -->
|
||||
<view class="uni-flex uni-column pay-result" v-show="payStatus == 'success'">
|
||||
<view class="body status">
|
||||
<view class="iconfont iconchenggong"></view>
|
||||
<view class="msg">收款成功</view>
|
||||
</view>
|
||||
<view class="footer">
|
||||
<button class="primary-btn" @click="paySuccess">继续收款 [Enter]({{ autoComplete.time }}s)</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<uni-popup ref="moneyPopup" type="center">
|
||||
<view class="money-wrap">
|
||||
<view class="head">
|
||||
<text>{{ moneyPopup.title }}</text>
|
||||
<text class="iconfont iconguanbi1" @click="$refs.moneyPopup.close()"></text>
|
||||
</view>
|
||||
<view class="content-wrap">
|
||||
<view class="unit">¥</view>
|
||||
<view class="money">{{ moneyPopup.money }}</view>
|
||||
</view>
|
||||
<view class="keyboard-wrap">
|
||||
<view class="num-wrap">
|
||||
<view class="key-item" @click="keydown('1')">1</view>
|
||||
<view class="key-item" @click="keydown('2')">2</view>
|
||||
<view class="key-item" @click="keydown('3')">3</view>
|
||||
<view class="key-item" @click="keydown('4')">4</view>
|
||||
<view class="key-item" @click="keydown('5')">5</view>
|
||||
<view class="key-item" @click="keydown('6')">6</view>
|
||||
<view class="key-item" @click="keydown('7')">7</view>
|
||||
<view class="key-item" @click="keydown('8')">8</view>
|
||||
<view class="key-item" @click="keydown('9')">9</view>
|
||||
<view class="key-item" @click="keydown('00')">00</view>
|
||||
<view class="key-item" @click="keydown('0')">0</view>
|
||||
<view class="key-item" @click="keydown('.')">.</view>
|
||||
</view>
|
||||
<view class="action-wrap">
|
||||
<view class="delete" @click="deleteCode">删除</view>
|
||||
<view class="delete" @click="moneyPopup.money = ''">清空</view>
|
||||
<view class="confirm" @click="moneyPopupConfirm()">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<uni-popup ref="couponPopup" type="center" v-if="payInfo.offset.coupon_array && payInfo.offset.coupon_array.member_coupon_list.length">
|
||||
<view class="coupon-wrap">
|
||||
<view class="head">
|
||||
<text>选择优惠券</text>
|
||||
<text class="iconfont iconguanbi1" @click="$refs.couponPopup.close()"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="body">
|
||||
<view class="list">
|
||||
<view class="item" :class="{ active: discount.coupon_id && discount.coupon_id == item.coupon_id }" v-for="(item, index) in payInfo.offset.coupon_array.member_coupon_list" :key="index" @click="selectCouponItem(item)">
|
||||
<view class="money" v-show="item.type == 'discount'">
|
||||
{{ item.discount }}
|
||||
<text class="unit">折</text>
|
||||
</view>
|
||||
<view class="money" v-show="item.type != 'discount'">
|
||||
<text class="unit">¥</text>
|
||||
{{ item.money }}
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="title">{{ item.coupon_name }}</view>
|
||||
<view class="limit">
|
||||
{{ item.at_least == 0 ? '无门槛券' : '满' + item.at_least + '可用' }}
|
||||
{{ item.type == 'discount' && item.discount_limit > 0 ? ',最多优惠' + item.discount_limit : '' }}
|
||||
</view>
|
||||
<view class="time" v-if="item.end_time">{{ $util.timeFormat(item.end_time, 'y-m-d') }}前可用
|
||||
</view>
|
||||
<view class="time" v-else>长期有效</view>
|
||||
</view>
|
||||
<view class="iconfont iconxuanzhong"></view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 扫码枪支付弹窗 -->
|
||||
<uni-popup ref="thirdPopup" type="center" @change="popupChange">
|
||||
<view class="third-popup">
|
||||
<view class="head">
|
||||
<text>请选择扫码方式</text>
|
||||
<text class="iconfont iconguanbi1" @click="$refs.thirdPopup.close();thirdPopupOpen = false;"></text>
|
||||
</view>
|
||||
<view class="money">扫码收款¥{{ payInfo.pay_money | moneyFormat }}</view>
|
||||
<view class="scan-code-type" v-if="type == 'third'">
|
||||
<view class="type-item" :class="{ active: scanCodeType == 'scancode' }" @click="scanCodeType = 'scancode'">扫码枪</view>
|
||||
<view class="type-item" :class="{ active: scanCodeType == 'qrcode' }" @click="scanCodeType = 'qrcode'">二维码</view>
|
||||
</view>
|
||||
<view class="content-wrap">
|
||||
<view class="qrcode-wrap" v-show="scanCodeType == 'qrcode'">
|
||||
<block v-if="payQrcode.length">
|
||||
<view class="qrcode-item" v-for="(item, index) in payQrcode" :key="index">
|
||||
<image :src="item.qrcode.replace(/[\r\n]/g, '')" mode="widthFix" class="qrcode" v-if="item.qrcode.indexOf('data:image') != -1" />
|
||||
<image :src="$util.img(item.qrcode)" mode="widthFix" class="qrcode" v-else />
|
||||
<image :src="$util.img(item.logo)" mode="widthFix" class="logo" />
|
||||
</view>
|
||||
</block>
|
||||
<view class="empty" v-else>没有可用的收款二维码</view>
|
||||
</view>
|
||||
<view class="scancode-wrap" v-show="scanCodeType == 'scancode'">
|
||||
<block v-if="scancodeList.length">
|
||||
<view>
|
||||
<input type="number" v-model="authCode" :class="{ focus: scanCodeFocus }"
|
||||
:focus="scanCodeFocus" placeholder="请点击输入框聚焦扫码或输入付款码" @confirm="scanCode"
|
||||
@focus="scanCodeFocus = true" @blur="scanCodeInputBlur()" />
|
||||
<text class="iconfont icondelete" v-show="authCode.length > 0" @click="clearAuthCode"></text>
|
||||
</view>
|
||||
<image src="@/static/cashier/scan_code_tip.png" mode="widthFix" />
|
||||
</block>
|
||||
<view class="empty" v-else>没有可用的支付方式</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 使用账号余额,验证会员码/手机号 -->
|
||||
<uni-popup ref="safeVerifyPopup" type="center">
|
||||
<view class="safe-verify-popup">
|
||||
<view class="header">
|
||||
<view class="type-wrap" v-if="active == 'memberCodePopup'">
|
||||
<view class="item">会员码</view>
|
||||
</view>
|
||||
<view class="type-wrap" v-else-if="active == 'safeVerifyPopup' && payInfo.collectmoney_config.sms_verify == 1">
|
||||
<view class="item" :class="{ active: safeVerifyType == 'payment_code' }" @click="changeSafeVerifyType('payment_code')">会员码</view>
|
||||
<view class="item" :class="{ active: safeVerifyType == 'sms_code' }" @click="changeSafeVerifyType('sms_code')">短信验证码</view>
|
||||
</view>
|
||||
<text class="iconfont iconguanbi1" @click="$refs.safeVerifyPopup.close()"></text>
|
||||
</view>
|
||||
<view class="content" v-show="safeVerifyType == 'payment_code'">
|
||||
<view class="scancode-wrap">
|
||||
<view class="input-wrap">
|
||||
<view>
|
||||
<input type="number" v-model="paymentCode" :class="{ focus: scanCodeFocus }"
|
||||
:focus="scanCodeFocus" placeholder="请点击输入框聚焦扫码或输入会员码" @confirm="verifyPaymentCode"
|
||||
@focus="scanCodeFocus = true" @blur="scanCodeInputBlur()"
|
||||
placeholder-class="placeholder" />
|
||||
<text class="iconfont icondelete" v-show="paymentCode.length > 0" @click="clearPaymentCode"></text>
|
||||
</view>
|
||||
<button class="primary-btn" @click="verifyPaymentCode">确认</button>
|
||||
</view>
|
||||
<image src="@/static/cashier/scan_code_tip.png" mode="widthFix" />
|
||||
<!-- <view class="member-code-hint">打开手机端 --》个人中心 --》 会员码</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<view class="content" v-show="safeVerifyType == 'sms_code' && active == 'safeVerifyPopup'">
|
||||
<block v-if="payInfo.member_account">
|
||||
<view class="tip">将发送验证码到该手机</view>
|
||||
<view class="mobile">
|
||||
{{ payInfo.member_account.mobile.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2') }}
|
||||
</view>
|
||||
<view class="sms-code">
|
||||
<view>
|
||||
<input type="number" v-model="smsCode" class="sms-code" placeholder="请输入验证码"
|
||||
:focus="scanCodeFocus" placeholder-class="placeholder" @focus="scanCodeFocus = true"
|
||||
@blur="scanCodeFocus = false" />
|
||||
<text class="iconfont icondelete" v-show="smsCode.length > 0" @click="clearSmsCode"></text>
|
||||
</view>
|
||||
<text class="send-tip" @click="sendMobileCode" :class="{ disabled: dynacodeData.isSend }">{{ dynacodeData.codeText }}</text>
|
||||
</view>
|
||||
<button class="primary-btn" @click="verifySmsCode">确认</button>
|
||||
</block>
|
||||
<view v-else>该会员尚未绑定手机号,无法使用该验证方式</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<uni-popup ref="remarkPopup" type="center">
|
||||
<view class="remark-wrap">
|
||||
<view class="header">
|
||||
<text class="title">备注</text>
|
||||
<text class="iconfont iconguanbi1" @click="$refs.remarkPopup.close()"></text>
|
||||
</view>
|
||||
<view class="body">
|
||||
<textarea v-model="remark" placeholder="填写备注信息" placeholder-class="placeholder-class" @keydown.enter="remarkConfirm" />
|
||||
</view>
|
||||
<view class="footer">
|
||||
<button type="default" class="primary-btn" @click="remarkConfirm">确认</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import index from './index.js';
|
||||
export default {
|
||||
name: 'nsPayment',
|
||||
mixins: [index]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
146
addon/cashier/source/os/components/ns-pend-order-popup/index.js
Executable file
146
addon/cashier/source/os/components/ns-pend-order-popup/index.js
Executable file
@@ -0,0 +1,146 @@
|
||||
import { editPendOrderRemark, deletePendOrder, getPendOrderList } from '@/api/pendorder.js';
|
||||
import { getMemberInfoById } from '@/api/member.js'
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'nsPendOrder',
|
||||
data() {
|
||||
return {
|
||||
orderData: {
|
||||
page: 0,
|
||||
total: 1,
|
||||
list: []
|
||||
},
|
||||
remark: '',
|
||||
index: -1,
|
||||
orderId: 0,
|
||||
isRepeat: false,
|
||||
height: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['pendOrderNum'])
|
||||
},
|
||||
created() {
|
||||
this.getOrder();
|
||||
},
|
||||
mounted() {
|
||||
this.setHeight();
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.pendOrderPop.open();
|
||||
},
|
||||
getOrder(page = null) {
|
||||
if (page === 0) this.orderData.page = page;
|
||||
this.orderId = 0;
|
||||
|
||||
if (this.orderData.page + 1 > this.orderData.total) return;
|
||||
|
||||
this.orderData.page++;
|
||||
|
||||
getPendOrderList({ page: this.orderData.page }).then(res => {
|
||||
if (res.code == 0) {
|
||||
if (this.orderData.page == 1) this.orderData.list = [];
|
||||
this.$store.commit('billing/setPendOrderNum', res.data.count);
|
||||
if (res.data.list.length) {
|
||||
this.orderData.total = res.data.page_count;
|
||||
this.orderData.list = this.orderData.list.concat(res.data.list);
|
||||
} else {
|
||||
this.orderData.total = 1;
|
||||
}
|
||||
this.setHeight();
|
||||
}
|
||||
});
|
||||
},
|
||||
deleteOrder(order_id) {
|
||||
if (this.isRepeat) return;
|
||||
this.isRepeat = true;
|
||||
deletePendOrder(order_id).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.isRepeat = false;
|
||||
this.getOrder(0);
|
||||
}
|
||||
});
|
||||
},
|
||||
remarkConfirm() {
|
||||
let data = this.orderData.list[this.index];
|
||||
editPendOrderRemark({
|
||||
order_id: data.order_id,
|
||||
remark: this.remark
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.orderData.list[this.index].remark = this.remark;
|
||||
this.$refs.remarkPopup.close();
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: '操作失败'
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
remarkSetting(data, index) {
|
||||
this.index = index;
|
||||
this.remark = data.remark;
|
||||
this.$refs.remarkPopup.open();
|
||||
},
|
||||
async takeOrder(data) {
|
||||
this.orderId = data.order_id;
|
||||
//获取挂单数据的会员信息
|
||||
if (data.member_id) {
|
||||
let res = await getMemberInfoById(data.member_id);
|
||||
if (res.code == 0 && res.data) {
|
||||
this.$store.commit('app/setGlobalMemberInfo', res.data);
|
||||
} else {
|
||||
this.$store.commit('app/setGlobalMemberInfo', null);
|
||||
}
|
||||
}
|
||||
//取出挂单数据设置到展示列表
|
||||
let goodsData = {};
|
||||
data.order_goods.forEach(item => {
|
||||
if (item.goods_class == 'money') item.money = item.price;
|
||||
//item.is_adjust = true;
|
||||
var key = 'sku_' + item.sku_id;
|
||||
if (item.goods_class == 4 || item.goods_class == 6) {
|
||||
var index = 0;
|
||||
Object.keys(goodsData).forEach(k => {
|
||||
if (k.indexOf(key) != -1) {
|
||||
index++;
|
||||
}
|
||||
});
|
||||
key += '_' + index;
|
||||
}
|
||||
goodsData[key] = item;
|
||||
});
|
||||
this.$store.commit('billing/setPendOrderId', data.order_id);
|
||||
this.$store.commit('billing/setPendOrderNum', this.pendOrderNum - 1);
|
||||
this.$store.commit('billing/setGoodsData', goodsData);
|
||||
this.$store.commit('billing/setOrderData', {
|
||||
goods_list: [],
|
||||
remark: data.remark
|
||||
});
|
||||
|
||||
this.$store.commit('billing/setActive', 'SelectGoodsAfter');
|
||||
this.$refs.pendOrderPop.close();
|
||||
},
|
||||
switchStoreAfter() {
|
||||
this.orderData = {
|
||||
page: 0,
|
||||
total: 1,
|
||||
list: []
|
||||
};
|
||||
this.getOrder();
|
||||
},
|
||||
setHeight() {
|
||||
this.$nextTick(() => {
|
||||
const query = uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
query.selectViewport().scrollOffset(data => {
|
||||
this.height = (data.scrollHeight - 51 - 67 - 15) / 100 + 'rem';
|
||||
}).exec();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
269
addon/cashier/source/os/components/ns-pend-order-popup/index.scss
Executable file
269
addon/cashier/source/os/components/ns-pend-order-popup/index.scss
Executable file
@@ -0,0 +1,269 @@
|
||||
.container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.pend-order-scroll-view-wrap {
|
||||
height: calc(100% - 0.67rem) !important;
|
||||
box-sizing: border-box;
|
||||
padding-top: 0.15rem;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
height: 0.66rem;
|
||||
line-height: 0.66rem;
|
||||
text-align: left;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
color: #303133;
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
|
||||
.table-list {
|
||||
.table-item {
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
padding: 0.15rem;
|
||||
position: relative;
|
||||
margin-bottom: 0.2rem;
|
||||
|
||||
.table-header-info {
|
||||
text {
|
||||
font-size: 0.16rem;
|
||||
}
|
||||
|
||||
.color {
|
||||
font-size: 0.18rem;
|
||||
color: #fe2278;
|
||||
}
|
||||
}
|
||||
|
||||
.table-header-time {
|
||||
color: #909399;
|
||||
font-size: 0.14rem;
|
||||
margin-top: 0.1rem;
|
||||
|
||||
.line {
|
||||
margin: 0 0.15rem;
|
||||
}
|
||||
}
|
||||
|
||||
.table-header-btn {
|
||||
position: absolute;
|
||||
right: 0.3rem;
|
||||
top: 0.3rem;
|
||||
color: $primary-color;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.table-content {
|
||||
margin-top: 0.1rem;
|
||||
|
||||
.table-content-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
padding: 0.1rem 0;
|
||||
|
||||
.content-item-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
width: 0;
|
||||
|
||||
.content-item-info {
|
||||
padding-right: 0.15rem;
|
||||
flex: 1;
|
||||
width: 0;
|
||||
|
||||
view {
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
|
||||
.content-item-name {
|
||||
margin-bottom: 0.05rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-item-img {
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
margin-right: 0.1rem;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.content-item-number {
|
||||
font-size: 0.16rem;
|
||||
}
|
||||
|
||||
.content-item-price {
|
||||
font-size: 0.14rem;
|
||||
width: 40%;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.remark-info {
|
||||
padding: 0.1rem;
|
||||
background-color: var(--primary-color-light-9);
|
||||
color: $primary-color;
|
||||
margin-top: 0.1rem;
|
||||
font-size: 0.12rem;
|
||||
}
|
||||
|
||||
.table-bottom {
|
||||
margin-top: 0.2rem;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
|
||||
button {
|
||||
width: 1rem;
|
||||
margin: 0;
|
||||
margin-right: 0.1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .uni-scroll-view {
|
||||
&::-webkit-scrollbar {
|
||||
width: 0.06rem;
|
||||
height: 0.06rem;
|
||||
background-color: rgba($color: #000000, $alpha: 0);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 0.06rem;
|
||||
box-shadow: inset 0 0 0.06rem rgba(45, 43, 43, 0.45);
|
||||
background-color: #ddd;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover::-webkit-scrollbar-thumb {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.remark-wrap {
|
||||
width: 6rem;
|
||||
background-color: #fff;
|
||||
border-radius: 0.04rem;
|
||||
box-shadow: 0 0.01rem 0.12rem 0 rgba(0, 0, 0, 0.1);
|
||||
|
||||
.header,
|
||||
.footer {
|
||||
height: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
position: relative;
|
||||
|
||||
.title {
|
||||
font-size: 0.16rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
right: 0.15rem;
|
||||
font-size: 0.2rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
padding: 0.15rem;
|
||||
|
||||
textarea {
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
width: 100%;
|
||||
padding: 0.1rem;
|
||||
box-sizing: border-box;
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
|
||||
.placeholder-class {
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
border-top: 0.01rem solid #e6e6e6;
|
||||
border-bottom: unset;
|
||||
|
||||
button {
|
||||
width: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding-top: 1.2rem;
|
||||
|
||||
image {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.tips {
|
||||
color: #999;
|
||||
margin-top: 0.15rem;
|
||||
}
|
||||
}
|
||||
|
||||
// pop弹框
|
||||
.pop-box {
|
||||
background: #ffffff;
|
||||
width: 8rem;
|
||||
height: 7rem;
|
||||
|
||||
.pop-header {
|
||||
padding: 0 0.15rem 0 0.2rem;
|
||||
height: 0.5rem;
|
||||
line-height: 0.5rem;
|
||||
border-bottom: 0.01rem solid #f0f0f0;
|
||||
font-size: 0.14rem;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
border-radius: 0.02rem 0.2rem 0 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.pop-header-text {}
|
||||
|
||||
.pop-header-close {
|
||||
cursor: pointer;
|
||||
|
||||
text {
|
||||
font-size: 0.18rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<view class="container pend-order">
|
||||
|
||||
<uni-popup ref="pendOrderPop">
|
||||
<view class="pop-box">
|
||||
<view class="pop-header">
|
||||
<view class="pop-header-text">挂/取单</view>
|
||||
<view class="pop-header-close" @click="$refs.pendOrderPop.close()">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" @scrolltolower="getOrder" class="pend-order-scroll-view-wrap" :style="{height : height}">
|
||||
<view class="table-list" v-if="orderData.list.length">
|
||||
<block v-for="(item, index) in orderData.list" :key="index">
|
||||
<view class="table-item" v-show="item.order_id != orderId">
|
||||
<view class="table-header">
|
||||
<view class="table-header-info">
|
||||
<text>订单总价:</text>
|
||||
<text class="color">¥{{ item.order_money | moneyFormat }}</text>
|
||||
</view>
|
||||
<view class="table-header-time">
|
||||
<text>挂单时间:{{ item.create_time | timeFormat }}</text>
|
||||
<block v-if="item.member_id">
|
||||
<text class="line">|</text>
|
||||
<text>会员:{{ item.nickname }}</text>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="table-content">
|
||||
<view class="table-content-item" v-for="(goods, gindex) in item.order_goods" :key="gindex">
|
||||
<view class="content-item-left">
|
||||
<view class="content-item-img">
|
||||
<image v-if="goods.goods_class == 'money'" src="@/static/goods/goods.png"/>
|
||||
<image v-else-if="goods.goods_image == '@/static/goods/goods.png'" src="@/static/goods/goods.png"/>
|
||||
<image v-else :src="$util.img(goods.goods_image, { size: 'small' })" @error="goods.goods_image = '@/static/goods/goods.png'"/>
|
||||
</view>
|
||||
<view class="content-item-info">
|
||||
<view class="content-item-name" v-if="goods.goods_class == 'money'">无码商品</view>
|
||||
<view class="content-item-name" v-else>
|
||||
<text>{{ goods.goods_name }}</text>
|
||||
<text>{{ goods.spec_name }}</text>
|
||||
</view>
|
||||
<view>¥{{ goods.price | moneyFormat }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-item-number">x {{ goods.num }}</view>
|
||||
<view class="content-item-price">¥{{ (goods.num * goods.price) | moneyFormat }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="remark-info" v-if="item.remark">备注:{{ item.remark }}</view>
|
||||
<view class="table-bottom">
|
||||
<button class="default-btn btn-left" @click="deleteOrder(item.order_id)">删除</button>
|
||||
<button class="default-btn btn-left" @click="remarkSetting(item, index)">备注</button>
|
||||
<button class="primary-btn btn-right" @click="takeOrder(item)">取单</button>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="empty" v-if="!orderData.list.length || (orderData.list.length == 1 && orderId)">
|
||||
<image src="@/static/goods/goods_empty.png" mode="widthFix"/>
|
||||
<view class="tips">暂无挂单记录</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
</view>
|
||||
</uni-popup>
|
||||
<uni-popup ref="remarkPopup" type="center">
|
||||
<view class="remark-wrap">
|
||||
<view class="header">
|
||||
<text class="title">备注</text>
|
||||
<text class="iconfont iconguanbi1" @click="$refs.remarkPopup.close()"></text>
|
||||
</view>
|
||||
<view class="body">
|
||||
<textarea v-model="remark" placeholder="填写备注信息" placeholder-class="placeholder-class" />
|
||||
</view>
|
||||
<view class="footer">
|
||||
<button type="default" class="primary-btn" @click="remarkConfirm">确认</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import index from './index.js';
|
||||
|
||||
export default {
|
||||
mixins: [index]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
127
addon/cashier/source/os/components/ns-promotion-popup/index.js
Executable file
127
addon/cashier/source/os/components/ns-promotion-popup/index.js
Executable file
@@ -0,0 +1,127 @@
|
||||
import {getAddonIsExist,getPromotionQrcode} from '@/api/promotion.js';
|
||||
export default {
|
||||
name: 'nsPromotionPopup',
|
||||
props: {
|
||||
pageName: {
|
||||
type: String,
|
||||
default: 'COUPON_DETAIL'
|
||||
},
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
qrParams:{
|
||||
page_name:'',
|
||||
option:'',
|
||||
app_type:'h5'
|
||||
},
|
||||
APPType:'h5',
|
||||
appTypeArray: [{
|
||||
text: 'H5',
|
||||
value: 'h5'
|
||||
}],
|
||||
qrData:{}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.qrParams.page_name = this.pageName
|
||||
this.getAddonIsExistFn()
|
||||
},
|
||||
methods:{
|
||||
getAddonIsExistFn(){
|
||||
getAddonIsExist().then(res=>{
|
||||
if(res.data.weapp){
|
||||
this.appTypeArray.push({text:'微信小程序',value:'weapp'})
|
||||
}
|
||||
if(res.data.aliapp){
|
||||
this.appTypeArray.push({text:'支付宝小程序',value:'aliapp'})
|
||||
}
|
||||
})
|
||||
},
|
||||
getPromotionQrcodeFn(){
|
||||
getPromotionQrcode(this.qrParams).then(res=>{
|
||||
this.qrData = Object.assign(this.qrData,res.data)
|
||||
this.$forceUpdate();
|
||||
})
|
||||
},
|
||||
open(option){
|
||||
this.qrParams.option = JSON.stringify(option)
|
||||
this.$refs.promotionPop.open()
|
||||
this.qrData={}
|
||||
this.appTypeArray.forEach((el)=>{
|
||||
this.qrParams.app_type = el.value
|
||||
this.getPromotionQrcodeFn()
|
||||
})
|
||||
|
||||
},
|
||||
//复制链接
|
||||
copyTextToClipboard(text) {
|
||||
uni.setClipboardData({
|
||||
data: text,
|
||||
success: function () {
|
||||
// 可以添加用户友好的提示,例如使用uni.showToast提示复制成功
|
||||
uni.showToast({
|
||||
title: '复制成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
},
|
||||
fail: function () {
|
||||
console.log('复制失败');
|
||||
// 可以添加错误处理或用户友好的提示
|
||||
}
|
||||
});
|
||||
},
|
||||
//下载二维码
|
||||
download(url){
|
||||
var oA = document.createElement("a");
|
||||
oA.innerHTML = '123'
|
||||
oA.download = ''; // 设置下载的文件名,默认是'下载'
|
||||
oA.target = "_blank"
|
||||
oA.href = url; //临时路径再保存到本地
|
||||
document.body.appendChild(oA);
|
||||
oA.click();
|
||||
oA.remove(); // 下载之后把创建的元素删除
|
||||
|
||||
}
|
||||
// download(url){
|
||||
// //下载文档
|
||||
// uni.downloadFile({
|
||||
// url: url,//下载地址接口返回
|
||||
// success: (data) => {
|
||||
// if (data.statusCode === 200) {
|
||||
// //文件保存到本地
|
||||
// uni.saveFile({
|
||||
// tempFilePath: data.tempFilePath, //临时路径
|
||||
// success: function(res) {
|
||||
// uni.showToast({
|
||||
// icon: 'none',
|
||||
// mask: true,
|
||||
// title: '文件已保存:' + res.savedFilePath, //保存路径
|
||||
// duration: 3000,
|
||||
// });
|
||||
// setTimeout(() => {
|
||||
// //打开文档查看
|
||||
// uni.openDocument({
|
||||
// filePath: res.savedFilePath,
|
||||
// success: function(res) {
|
||||
// // console.log('打开文档成功');
|
||||
// }
|
||||
// });
|
||||
// }, 3000)
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// },
|
||||
// fail: (err) => {
|
||||
// console.log(err);
|
||||
// uni.showToast({
|
||||
// icon: 'none',
|
||||
// mask: true,
|
||||
// title: '失败请重新下载',
|
||||
// });
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
}
|
||||
}
|
||||
76
addon/cashier/source/os/components/ns-promotion-popup/index.scss
Executable file
76
addon/cashier/source/os/components/ns-promotion-popup/index.scss
Executable file
@@ -0,0 +1,76 @@
|
||||
.promotion-pop{
|
||||
width: 7rem;
|
||||
background-color: #fff;
|
||||
border-radius: 0.06rem;
|
||||
.header{
|
||||
padding: 0.15rem 0.2rem;
|
||||
font-size: 0.14rem;
|
||||
border-bottom: 0.01rem solid #e6e6e6;
|
||||
|
||||
}
|
||||
.body{
|
||||
width: 100%;
|
||||
padding: 0.2rem 0.3rem;
|
||||
box-sizing: border-box;
|
||||
.alter{
|
||||
height: 0.48rem;
|
||||
line-height: 0.48rem;
|
||||
font-size: 0.14rem;
|
||||
padding: 0 0.2rem;
|
||||
color: #666;
|
||||
background-color: var(--primary-color-light-9);
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
.content{
|
||||
.qrCode{
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
background-color: #f8f8f8;
|
||||
color: #333;
|
||||
font-size: 0.14rem;
|
||||
image{
|
||||
width:1.6rem;
|
||||
height:1.6rem;
|
||||
}
|
||||
}
|
||||
.right{
|
||||
margin-left: 0.2rem;
|
||||
.form-item{
|
||||
margin-bottom: 0.1rem;
|
||||
}
|
||||
.link {
|
||||
|
||||
.form-inline{
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
}
|
||||
input{
|
||||
width: 2rem;
|
||||
height: 0.3rem;
|
||||
border: 0.01rem solid #e6e6e6;
|
||||
padding: 0 0.12rem;
|
||||
font-size: 0.14rem;
|
||||
border-radius: 0.02rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.btn{
|
||||
background-color: var(--primary-color);
|
||||
color: #fff;
|
||||
margin-left: .1rem;
|
||||
font-size: 0.14rem;
|
||||
height: 0.3rem;
|
||||
line-height: 0.3rem;
|
||||
&::after{
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
.download{
|
||||
color: var(--primary-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
60
addon/cashier/source/os/components/ns-promotion-popup/ns-promotion-popup.vue
Executable file
60
addon/cashier/source/os/components/ns-promotion-popup/ns-promotion-popup.vue
Executable file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<unipopup ref="promotionPop" type="center">
|
||||
<view class="promotion-pop">
|
||||
<view class="header flex justify-between">
|
||||
<view class="title">推广</view>
|
||||
<view class="pop-header-close" @click="$refs.promotionPop.close()">
|
||||
<text class="iconguanbi1 iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="body">
|
||||
<view class="alter">活动可分享至多个渠道推广,增加曝光率,提升分享打开率。</view>
|
||||
<view class="flex content">
|
||||
<view class="qrCode flex items-center justify-center">
|
||||
<image v-if="qrData[APPType]&&qrData[APPType].path" :src="$util.img(qrData[APPType].path)"/>
|
||||
<text v-else>小程序配置错误</text>
|
||||
</view>
|
||||
<view class="flex-1 right">
|
||||
<view class="form-box">
|
||||
<view class="form-content">
|
||||
<view class="form-item flex">
|
||||
<view class="form-label">充值方式:</view>
|
||||
<view class="form-inline">
|
||||
<uni-data-checkbox v-model="APPType" :localdata="appTypeArray" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item link" v-if="APPType == 'h5'&&qrData[APPType]&&qrData[APPType].url">
|
||||
<view class="form-label">
|
||||
推广链接:
|
||||
</view>
|
||||
<view class="form-inline flex items-center">
|
||||
<input type="text" disabled v-model="qrData[APPType].url" @keydown.enter="search('enter')" />
|
||||
<button type="default" class="btn" @click="copyTextToClipboard(qrData[APPType].url)">复制</button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item" v-if="qrData[APPType]&&qrData[APPType].path">
|
||||
<text class="download" @click="download($util.img(qrData[APPType].path))">下载二维码</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</unipopup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import unipopup from '@/components/uni-popup/uni-popup.vue';
|
||||
import index from './index.js';
|
||||
export default {
|
||||
components: {
|
||||
unipopup,
|
||||
},
|
||||
mixins: [index]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
185
addon/cashier/source/os/components/ns-scale-goods/command.js
Executable file
185
addon/cashier/source/os/components/ns-scale-goods/command.js
Executable file
File diff suppressed because one or more lines are too long
384
addon/cashier/source/os/components/ns-scale-goods/ns-scale-goods.vue
Executable file
384
addon/cashier/source/os/components/ns-scale-goods/ns-scale-goods.vue
Executable file
@@ -0,0 +1,384 @@
|
||||
<template>
|
||||
<view>
|
||||
<uni-popup ref="memberInquirePopup" type="center" @change="popupChange" :mask-click="false">
|
||||
<view class="popup-inquire-wrap">
|
||||
<view class="popup-header">
|
||||
<text class="title">称重商品同步到电子秤</text>
|
||||
<text class="iconfont iconguanbi1" @click="$refs.memberInquirePopup.close()"></text>
|
||||
</view>
|
||||
|
||||
<view class="popup-content">
|
||||
<view v-show="step == 1">
|
||||
<view class="content-title">选择商品</view>
|
||||
<uniDataTable url="/weighgoods/storeapi/goods/skuall" :cols="cols" :classType="true" @checkBox="checkBox" ref="goodsListTable" />
|
||||
</view>
|
||||
<view v-show="step == 2">
|
||||
<view class="content-title">选择需同步的电子秤</view>
|
||||
<uniDataTable url="/scale/storeapi/scale/page" :pagesize="0" :cols="scaleCols" :classType="true" ref="scaleListTable" @tableData="onloadScale" />
|
||||
</view>
|
||||
<view v-show="step == 3">
|
||||
<view class="content-title">同步商品到电子秤</view>
|
||||
<uniDataTable :cols="syncTaskCols" :classType="true" ref="syncTaskTable" :data="syncTask" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="popup-footer" v-show="step == 1">
|
||||
<button type="default" class="default-btn" @click="next">下一步</button>
|
||||
</view>
|
||||
<view class="popup-footer" v-show="step == 2">
|
||||
<button type="default" class="default-btn" @click="step = 1">上一步</button>
|
||||
<button type="primary" class="primary-btn" @click="syncGoods">同步</button>
|
||||
</view>
|
||||
<view class="popup-footer" v-show="step == 3">
|
||||
<button type="default" class="primary-btn" :loading="synching" v-if="synching">同步中</button>
|
||||
<button type="default" class="primary-btn" :loading="synching" @click="$refs.memberInquirePopup.close()" v-else>完成</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniDataTable from '@/components/uni-data-table/uni-data-table.vue';
|
||||
import { getScaleList } from '@/api/scale.js';
|
||||
import {
|
||||
createCommand
|
||||
} from './command.js'
|
||||
|
||||
var self;
|
||||
|
||||
export default {
|
||||
components: {
|
||||
uniDataTable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
step: 1,
|
||||
cols: [{
|
||||
width: 6,
|
||||
align: 'center',
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'account_data',
|
||||
width: 50,
|
||||
title: '商品信息',
|
||||
align: 'left',
|
||||
templet: data => {
|
||||
let img = this.$util.img(data.sku_image);
|
||||
let html = `
|
||||
<view class="goods-content">
|
||||
<image class="goods-img" src="${img}" mode="aspectFit"/>
|
||||
<text class="goods-name multi-hidden">${data.sku_name}</text>
|
||||
</view>
|
||||
`;
|
||||
return html;
|
||||
}
|
||||
},
|
||||
{
|
||||
width: 10,
|
||||
title: '价格',
|
||||
align: 'center',
|
||||
templet: function(data) {
|
||||
return '¥' + data.price;
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'plu',
|
||||
width: 10,
|
||||
title: 'PLU码',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
width: 10,
|
||||
title: '计价方式',
|
||||
align: 'center',
|
||||
templet: function(data) {
|
||||
if (data.pricing_type == 'num') {
|
||||
return '计数';
|
||||
} else {
|
||||
return '计重';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
width: 10,
|
||||
title: '状态',
|
||||
align: 'center',
|
||||
templet: function(data) {
|
||||
var str = '';
|
||||
if (data.store_status == 1) {
|
||||
str = '销售中';
|
||||
} else if (data.store_status == 0) {
|
||||
str = '仓库中';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
],
|
||||
scaleCols: [{
|
||||
width: 6,
|
||||
align: 'center',
|
||||
checkbox: true,
|
||||
disabled: (data) => {
|
||||
return !data.connect_status
|
||||
}
|
||||
},
|
||||
{
|
||||
width: 24,
|
||||
title: '设备名称',
|
||||
align: 'left',
|
||||
field: 'name',
|
||||
},
|
||||
{
|
||||
width: 20,
|
||||
title: '设备品牌',
|
||||
align: 'center',
|
||||
field: 'brand_name',
|
||||
},
|
||||
{
|
||||
width: 20,
|
||||
title: '设备型号',
|
||||
align: 'center',
|
||||
field: 'model_name',
|
||||
},
|
||||
{
|
||||
width: 20,
|
||||
title: '状态',
|
||||
align: 'center',
|
||||
templet: (data) => {
|
||||
return data.connect_status ? '已连接' : '未连接'
|
||||
}
|
||||
}
|
||||
],
|
||||
syncTaskCols: [{
|
||||
width: 70,
|
||||
title: '设备名称',
|
||||
align: 'left',
|
||||
templet: (data) => {
|
||||
return data.name
|
||||
}
|
||||
},
|
||||
{
|
||||
width: 30,
|
||||
title: '同步状态',
|
||||
align: 'left',
|
||||
templet: (data) => {
|
||||
var str = '';
|
||||
switch (data.syncStatus) {
|
||||
case '1':
|
||||
str = `<view>同步成功</view>`;
|
||||
break;
|
||||
case '0':
|
||||
str = `<view>同步失败</view><view style="color: red;display:block;white-space: normal;">失败原因:${data.msg}</view>`;
|
||||
break;
|
||||
default:
|
||||
str = `<view>同步中</view>`;
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
],
|
||||
syncTask: {},
|
||||
synching: false
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getScaleListFn();
|
||||
self = this;
|
||||
},
|
||||
methods: {
|
||||
popupChange(e) {
|
||||
if (!e.show) {
|
||||
this.syncTask = {};
|
||||
this.synching = false;
|
||||
this.step = 1
|
||||
}
|
||||
},
|
||||
open() {
|
||||
this.$refs.memberInquirePopup.open();
|
||||
},
|
||||
selectScale(e) {
|
||||
this.scale = this.scaleList[e].name;
|
||||
this.scaleId = this.scaleList[e].scale_id
|
||||
},
|
||||
checkBox(e) {
|
||||
this.goodsList = e;
|
||||
},
|
||||
getScaleListFn() {
|
||||
if (!this.addon.includes('scale')) {
|
||||
return;
|
||||
}
|
||||
getScaleList({
|
||||
page: 1,
|
||||
page_size: 100
|
||||
}).then(res=>{
|
||||
if (res.data.list.length > 0) this.scaleList = res.data.list;
|
||||
});
|
||||
},
|
||||
next() {
|
||||
const selected = this.$refs.goodsListTable.selected;
|
||||
if (!selected.length) {
|
||||
this.$util.showToast({
|
||||
'title': '请选择要同步的商品'
|
||||
});
|
||||
return
|
||||
}
|
||||
this.step += 1;
|
||||
},
|
||||
onloadScale(list) {
|
||||
if (typeof window.POS_DATA_CALLBACK == 'function') delete window.POS_DATA_CALLBACK;
|
||||
|
||||
/**
|
||||
* 商品同步数据回调
|
||||
* @param {Object} text
|
||||
*/
|
||||
window.POS_DATA_CALLBACK = function(text) {
|
||||
let data = text.split(':');
|
||||
let index = parseInt(data[0]);
|
||||
|
||||
switch (data[1]) {
|
||||
case 'SyncGoodsPlu':
|
||||
self.$set(self.syncTask[index], 'syncStatus', data[2]);
|
||||
self.$set(self.syncTask[index], 'msg', data[4]);
|
||||
|
||||
if (index == self.syncTask.length - 1) {
|
||||
self.synching = false
|
||||
}
|
||||
break;
|
||||
case 'PingWeigher':
|
||||
self.$set(self.$refs.scaleListTable.list[index], 'connect_status', parseInt(data[3]));
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
let weigher = list.map(item => {
|
||||
item.config = JSON.parse(item.config);
|
||||
return item;
|
||||
});
|
||||
|
||||
try {
|
||||
this.$pos.send('PingWeigher', JSON.stringify({
|
||||
weigher
|
||||
}));
|
||||
} catch (e) {}
|
||||
},
|
||||
async syncGoods() {
|
||||
const selected = this.$refs.scaleListTable.selected;
|
||||
if (!selected.length) {
|
||||
this.$util.showToast({
|
||||
'title': '请选择要同步的设备'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.synching) return;
|
||||
this.synching = true;
|
||||
|
||||
this.syncTask = this.$refs.scaleListTable.selected
|
||||
this.step += 1;
|
||||
|
||||
setTimeout(() => {
|
||||
this.createSyncData()
|
||||
}, 100)
|
||||
},
|
||||
createSyncData() {
|
||||
let task = {};
|
||||
task.weigher = this.$refs.scaleListTable.selected.map(scale => {
|
||||
scale.config = typeof scale.config == 'string' ? JSON.parse(scale.config) : scale.config;
|
||||
scale.goodsList = this.$refs.goodsListTable.selected.map(sku => {
|
||||
return {
|
||||
sku_no: sku.sku_no,
|
||||
plu: sku.plu,
|
||||
price: sku.price,
|
||||
sku_name: sku.sku_name,
|
||||
pricing_type: sku.pricing_type,
|
||||
command: ''
|
||||
}
|
||||
});
|
||||
return scale;
|
||||
});
|
||||
|
||||
this.syncTask = task.weigher;
|
||||
|
||||
try {
|
||||
console.log(JSON.stringify(task));
|
||||
this.$pos.send('SyncGoodsPlu', JSON.stringify(task));
|
||||
} catch (e) {
|
||||
this.synching = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.popup-inquire-wrap {
|
||||
overflow: hidden;
|
||||
width: 9.55rem;
|
||||
height: 5.37rem;
|
||||
background-color: #fff;
|
||||
border-radius: 0.05rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 0.15rem;
|
||||
height: 0.45rem;
|
||||
line-height: 0.45rem;
|
||||
border-bottom: 0.01rem solid #e8eaec;
|
||||
|
||||
.iconfont {
|
||||
font-size: $uni-font-size-lg;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
overflow-y: auto;
|
||||
padding: 0.1rem;
|
||||
|
||||
/deep/ .content {}
|
||||
|
||||
.content-title {
|
||||
margin-bottom: .1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
padding: 0.1rem;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
|
||||
button {
|
||||
width: 1rem;
|
||||
margin: 0 0 0 .15rem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/deep/.goods-content {
|
||||
display: flex;
|
||||
|
||||
.goods-img {
|
||||
margin-right: 0.1rem;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
white-space: pre-wrap;
|
||||
align-self: baseline;
|
||||
}
|
||||
}
|
||||
|
||||
/deep/.uni-select-lay-select {
|
||||
width: 2rem !important;
|
||||
height: 0.42rem !important;
|
||||
}
|
||||
</style>
|
||||
242
addon/cashier/source/os/components/ns-select-member/index.js
Executable file
242
addon/cashier/source/os/components/ns-select-member/index.js
Executable file
@@ -0,0 +1,242 @@
|
||||
import {getMemberList,getMemberInfoById, getMemberLevelList, addMember, searchMemberByMobile} from '@/api/member.js';
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
searchText: '',
|
||||
page: 1,
|
||||
memberList: [],
|
||||
memberId: '',
|
||||
memberData: {
|
||||
sex: 0,
|
||||
mobile: '',
|
||||
nickname: '',
|
||||
birthday: '',
|
||||
member_level: '',
|
||||
member_level_name: ''
|
||||
},
|
||||
memberLevelList: [], // 会员等级
|
||||
sex: [{
|
||||
text: '未知',
|
||||
value: 0
|
||||
}, {
|
||||
text: '男',
|
||||
value: 1
|
||||
}, {
|
||||
text: '女',
|
||||
value: 2
|
||||
}],
|
||||
memberType: 'login',
|
||||
flag: false,
|
||||
inputFocus: false,
|
||||
isPhone: false,
|
||||
searchFinish: false // 搜索是否完成
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getMemberLevel();
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['memberSearchWayConfig'])
|
||||
},
|
||||
watch: {
|
||||
memberSearchWayConfig: {
|
||||
immediate: true,
|
||||
handler(newVal, oldVal) {
|
||||
if(newVal) {
|
||||
if(newVal.way == 'list'){
|
||||
this.getMemberListFn();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
searchMemberInputBlur(){
|
||||
this.inputFocus = false;
|
||||
//强制聚焦处理
|
||||
if(this.memberType = 'login'){
|
||||
this.$nextTick(() => {
|
||||
this.inputFocus = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
open(callback) {
|
||||
this.memberId = this.globalMemberInfo ? this.globalMemberInfo.member_id + '' : '';
|
||||
this.$refs.memberPopup.open('', callback);
|
||||
this.inputFocus = true;
|
||||
this.searchFinish = false;
|
||||
},
|
||||
// 查询会员列表
|
||||
searchMemberByMobileFn() {
|
||||
setTimeout(() => {
|
||||
if (!this.searchText) return false;
|
||||
searchMemberByMobile({
|
||||
mobile: this.searchText
|
||||
}).then((res) => {
|
||||
if (res.code >= 0) {
|
||||
this.$store.commit('app/setGlobalMemberInfo', res.data);
|
||||
this.initData();
|
||||
this.$refs.memberPopup.close();
|
||||
} else {
|
||||
if (res.data > 1) {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
return false;
|
||||
}
|
||||
var regex = /^1[3-9]\d{9}$/;
|
||||
if (res.data == 0 && regex.test(this.searchText)) {
|
||||
this.isPhone = true;
|
||||
this.$refs.emptyPopup.open();
|
||||
return false;
|
||||
}
|
||||
if (res.data == 0) {
|
||||
this.isPhone = false;
|
||||
this.$refs.emptyPopup.open();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 200)
|
||||
},
|
||||
getMemberInfo(memberId, callback) {
|
||||
this.memberId = memberId;
|
||||
getMemberInfoById(memberId).then(res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.$store.commit('app/setGlobalMemberInfo', res.data);
|
||||
if (callback) callback();
|
||||
this.initData();
|
||||
this.$refs.memberPopup.close();
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: '未获取到会员信息'
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
/******************************** 录入会员 ********************************/
|
||||
getMemberLevel() {
|
||||
this.memberLevelList = [];
|
||||
getMemberLevelList().then(res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
for (let i in res.data) {
|
||||
this.memberLevelList.push({
|
||||
label: res.data[i]['level_name'],
|
||||
value: res.data[i]['level_id'].toString(),
|
||||
disabled: false
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 选择会员等级
|
||||
selectMemberLevel(index, item) {
|
||||
if (index >= 0) {
|
||||
this.memberData.member_level = item.value;
|
||||
this.memberData.member_level_name = item.label;
|
||||
} else {
|
||||
this.memberData.member_level = '';
|
||||
this.memberData.member_level_name = '';
|
||||
}
|
||||
this.$forceUpdate();
|
||||
},
|
||||
// 选择时间
|
||||
changeTime(e) {
|
||||
this.memberData.birthday = e;
|
||||
},
|
||||
verify() {
|
||||
if (!this.memberData.mobile) {
|
||||
this.$util.showToast({
|
||||
title: '请输入会员手机号'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!this.$util.verifyMobile(this.memberData.mobile)) {
|
||||
this.$util.showToast({
|
||||
title: '请输入正确的手机号码'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// 确定录入
|
||||
addMemberFn() {
|
||||
if (this.verify()) {
|
||||
if (this.flag) return;
|
||||
this.flag = true;
|
||||
addMember(this.memberData).then(res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.memberType = 'login';
|
||||
this.getMemberInfo(res.data)
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
}
|
||||
this.flag = false;
|
||||
})
|
||||
}
|
||||
},
|
||||
closedFn() {
|
||||
this.memberType = "login";
|
||||
this.$refs.memberPopup.close();
|
||||
},
|
||||
memberEmptyRegister() {
|
||||
this.memberType = "register";
|
||||
this.memberData.mobile = this.searchText;
|
||||
this.$refs.emptyPopup.close();
|
||||
},
|
||||
initData() {
|
||||
this.searchText = '';
|
||||
this.memberData.sex = 0;
|
||||
this.memberData.mobile = '';
|
||||
this.memberData.nickname = '';
|
||||
this.memberData.birthday = '';
|
||||
this.memberData.member_level = '';
|
||||
this.memberData.member_level_name = '';
|
||||
},
|
||||
stayTuned() {
|
||||
this.$util.showToast({
|
||||
title: '敬请期待'
|
||||
});
|
||||
},
|
||||
getMemberListFn(isSearch){
|
||||
getMemberList({
|
||||
page: this.page,
|
||||
page_size: 12,
|
||||
search_text: this.searchText
|
||||
}).then((res)=>{
|
||||
if (res.code >= 0) {
|
||||
if (this.page == 1) this.memberList = [];
|
||||
this.memberList = this.memberList.concat(res.data.list);
|
||||
this.memberList.forEach((item) => {
|
||||
if (item.mobile) {
|
||||
if (this.userInfo && this.userInfo.is_admin == 0) {
|
||||
// 非管理员,不能查看会员手机号
|
||||
item.mobile = item.mobile.substring(0, 4 - 1) + '****' + item.mobile.substring(6 + 1);
|
||||
}
|
||||
} else {
|
||||
item.mobile = '--';
|
||||
}
|
||||
});
|
||||
|
||||
if (isSearch) {
|
||||
// 默认选中第一个搜索结果
|
||||
this.memberId = 0;
|
||||
if (this.memberList.length) {
|
||||
this.memberId = this.memberList[0].member_id;
|
||||
}
|
||||
}
|
||||
this.searchFinish = true;
|
||||
if (res.data.page_count >= this.page) this.page++;
|
||||
}
|
||||
})
|
||||
},
|
||||
searchMemberByList(){
|
||||
this.page = 1;
|
||||
this.getMemberListFn(Boolean(this.searchText));
|
||||
}
|
||||
}
|
||||
};
|
||||
333
addon/cashier/source/os/components/ns-select-member/index.scss
Executable file
333
addon/cashier/source/os/components/ns-select-member/index.scss
Executable file
@@ -0,0 +1,333 @@
|
||||
.member-inquire-wrap {
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
border-radius: 0.05rem;
|
||||
|
||||
.member-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 0.15rem;
|
||||
height: 0.45rem;
|
||||
line-height: 0.45rem;
|
||||
border-bottom: 0.01rem solid #e8eaec;
|
||||
|
||||
.iconfont {
|
||||
font-size: $uni-font-size-lg;
|
||||
}
|
||||
}
|
||||
|
||||
&.exact{
|
||||
width: 4rem;
|
||||
|
||||
.member-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.3rem 0.3rem;
|
||||
|
||||
.member-img{
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
}
|
||||
.member-input{
|
||||
margin-top: .25rem;
|
||||
width: 100%;
|
||||
height: .4rem;
|
||||
line-height: .4rem;
|
||||
// border-radius: 0.02rem;
|
||||
padding: 0 0.1rem;
|
||||
border: 0.01rem solid $primary-color;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
button{
|
||||
// border-radius: 0.05rem;
|
||||
height: .4rem;
|
||||
line-height: .4rem;
|
||||
margin-top: 0.15rem;
|
||||
width: 100%;
|
||||
}
|
||||
.function-list{
|
||||
margin-top: .25rem;
|
||||
padding-top: .15rem;
|
||||
border-top: 0.01rem dashed #ccc;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.item-wrap{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
.item-icon{
|
||||
font-size: .25rem;
|
||||
color: #333;
|
||||
margin-bottom: 0.05rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.list{
|
||||
width: 9.55rem;
|
||||
height: 5.37rem;
|
||||
|
||||
.member-content {
|
||||
padding: 0.1rem;
|
||||
|
||||
.search-warp {
|
||||
margin-left: 0.1rem;
|
||||
|
||||
.search-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 0.05rem;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
padding-left: 0.1rem;
|
||||
width: 2.5rem;
|
||||
height: 0.4rem;
|
||||
line-height: 0.4rem;
|
||||
border: 0.01rem solid #dcdee2;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 2rem;
|
||||
height: 0.42rem;
|
||||
line-height: 0.42rem;
|
||||
color: #fff;
|
||||
font-size: $uni-font-size-base;
|
||||
margin: 0;
|
||||
|
||||
&:last-of-type {
|
||||
margin-left: 0.15rem;
|
||||
margin-right: 0.1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .uni-scroll-view-content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: baseline;
|
||||
height: 430px;
|
||||
}
|
||||
|
||||
.member-list {
|
||||
.member-item {
|
||||
display: flex;
|
||||
padding: 0.13rem 0.15rem;
|
||||
margin: 0.1rem;
|
||||
width: 2.9rem;
|
||||
height: 1rem;
|
||||
background-color: #f5f5f5;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0.05rem;
|
||||
&.active {
|
||||
background-color: $primary-color;
|
||||
.name,
|
||||
.phone,
|
||||
.other>view {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(3n + 3) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 0.45rem;
|
||||
height: 0.45rem;
|
||||
border-radius: 50%;
|
||||
margin-right: 0.1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
width: calc( 100% - 0.55rem );
|
||||
.name{
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
text:nth-child(1) {
|
||||
font-size: $uni-font-size-lg;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.phone {
|
||||
font-size: $uni-font-size-sm;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.other {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: $uni-font-size-sm;
|
||||
|
||||
view {
|
||||
font-size: $uni-font-size-sm;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 录入会员
|
||||
.member-entering-wrap {
|
||||
width: 3.8rem;
|
||||
background-color: #fff;
|
||||
border-radius: 0.05rem;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 0.15rem;
|
||||
height: 0.45rem;
|
||||
line-height: 0.45rem;
|
||||
border-bottom: 0.01rem solid #e8eaec;
|
||||
|
||||
.iconfont {
|
||||
font-size: $uni-font-size-lg;
|
||||
}
|
||||
}
|
||||
|
||||
.form-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 0.2rem;
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 0.1rem;
|
||||
display: flex;
|
||||
|
||||
.form-label {
|
||||
width: 0.9rem;
|
||||
text-align: right;
|
||||
padding-right: 0.1rem;
|
||||
box-sizing: border-box;
|
||||
height: 0.32rem;
|
||||
line-height: 0.32rem;
|
||||
|
||||
.required {
|
||||
color: red;
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
}
|
||||
|
||||
.form-inline {
|
||||
width: 2.5rem;
|
||||
line-height: 0.32rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
.form-input {
|
||||
border-width: 0.01rem;
|
||||
border-style: solid;
|
||||
background-color: #fff;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
border-radius: 0.02rem;
|
||||
padding-left: 0.1rem;
|
||||
height: 0.32rem;
|
||||
line-height: 0.32rem;
|
||||
font-size: 0.14rem;
|
||||
border-color: #e6e6e6;
|
||||
}
|
||||
|
||||
button {
|
||||
width: calc(50% - 0.05rem);
|
||||
display: inline-block;
|
||||
margin-right: 0.1rem;
|
||||
|
||||
&:nth-child(2) {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.btn-wrap {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0.1rem 0;
|
||||
.primary-btn {
|
||||
height: 0.4rem;
|
||||
line-height: 0.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding-top: 0.8rem;
|
||||
width: 100%;
|
||||
|
||||
image {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.tips {
|
||||
color: #999;
|
||||
margin-top: 0.15rem;
|
||||
}
|
||||
}
|
||||
|
||||
.member-empty{
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
border-radius: 0.02rem;
|
||||
width: 3rem;
|
||||
.head{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: .2rem;
|
||||
height: .42rem;
|
||||
background-color: #f8f8f8;
|
||||
border-bottom: .01rem solid #eee;
|
||||
}
|
||||
.content{
|
||||
padding: .06rem .2rem 0;
|
||||
height: .6rem;
|
||||
line-height: .6rem;
|
||||
}
|
||||
.btn-wrap{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-right: .2rem;
|
||||
padding-bottom: .2rem;
|
||||
button{
|
||||
margin: 0;
|
||||
margin-left: .1rem;
|
||||
border-radius: .02rem;
|
||||
}
|
||||
.close-btn{
|
||||
font-size: 0.14rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
154
addon/cashier/source/os/components/ns-select-member/ns-select-member.vue
Executable file
154
addon/cashier/source/os/components/ns-select-member/ns-select-member.vue
Executable file
@@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<view>
|
||||
<uni-popup ref="memberPopup" type="center" @maskClick="closedFn">
|
||||
<view class="member-inquire-wrap" :class="{ 'exact' : memberSearchWayConfig.way == 'exact','list' : memberSearchWayConfig.way == 'list' }" v-if="memberType == 'login'">
|
||||
<view class="member-header">
|
||||
<text class="title">{{ memberSearchWayConfig.way == 'exact' ? '会员查询' : '会员列表' }}</text>
|
||||
<text class="iconfont iconguanbi1" @click="closedFn"></text>
|
||||
</view>
|
||||
|
||||
<view class="member-content" v-if="memberSearchWayConfig.way == 'exact'">
|
||||
<image class="member-img" mode="aspectFill" src="@/static/member/head.png" />
|
||||
<input type="number" class="member-input" focus placeholder="请输入手机号或手机号后四位" placeholder-style="font-size:0.14rem" v-model="searchText" @confirm="searchMemberByMobileFn()" :focus="inputFocus" @focus="inputFocus = true" @blur="searchMemberInputBlur" />
|
||||
<button class="switch primary-btn" @click="searchMemberByMobileFn()">查询</button>
|
||||
<view class="function-list">
|
||||
<view class="item-wrap" @click="stayTuned">
|
||||
<text class="item-icon iconfont iconmenpos"></text>
|
||||
<text>刷卡登录</text>
|
||||
</view>
|
||||
<view class="item-wrap" @click="stayTuned">
|
||||
<!-- <image class="item-img" mode="aspectFill" src="@/static/member/head.png" /> -->
|
||||
<text class="item-icon iconfont iconsaomiaoerweima"></text>
|
||||
<text>扫码登录</text>
|
||||
</view>
|
||||
<view class="item-wrap" @click="stayTuned">
|
||||
<text class="item-icon iconfont iconhuaxiangfenxi"></text>
|
||||
<text>人脸登录</text>
|
||||
</view>
|
||||
<view class="item-wrap" @click="memberType = 'register'">
|
||||
<text class="item-icon iconfont iconhuiyuanzhucedengluguanli"></text>
|
||||
<text>会员注册</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="member-content" v-if="memberSearchWayConfig.way == 'list'">
|
||||
<view class="search-warp">
|
||||
<view class="search-input">
|
||||
<input focus placeholder="可查询会员账号、手机号、昵称" placeholder-style="font-size:0.14rem" v-model="searchText" @confirm="searchMemberByList()" :focus="inputFocus" @focus="inputFocus = true" @blur="searchMemberInputBlur" />
|
||||
<button class="switch primary-btn" @click="searchMemberByList()">查询 [Enter]</button>
|
||||
<button class="default-btn" plain="true" @click="memberType = 'register'">添加会员</button>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view @scrolltolower="getMemberListFn()" scroll-y="true" class="member-list">
|
||||
<view :class="['member-item', { active: item.member_id == memberId }]" v-for="(item, index) in memberList" :key="index" @click="getMemberInfo(item.member_id)">
|
||||
<image class="item-img" mode="aspectFill" v-if="item.headimg" :src="$util.img(item.headimg)" @error="item.headimg = defaultImg.head"/>
|
||||
<image class="item-img" mode="aspectFill" v-else :src="$util.img(defaultImg.head)"/>
|
||||
<view class="item-content">
|
||||
<view class="name">
|
||||
<text :title="item.nickname">{{ item.nickname }}</text>
|
||||
</view>
|
||||
<view class="phone">手机号:{{ item.mobile }}</view>
|
||||
<view class="other">
|
||||
<view>余额:{{ parseFloat(parseFloat(item.balance) + parseFloat(item.balance_money)).toFixed(2) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-show="memberList.length == 0" class="empty">
|
||||
<image :src="$util.img('public/uniapp/cashier/member-empty.png')" mode="widthFix"/>
|
||||
<view class="tips">暂无会员</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<view class="member-entering-wrap" v-if="memberType == 'register'">
|
||||
<view class="header">
|
||||
<text class="iconfont iconqianhou1" @click="memberType = 'login'"></text>
|
||||
<text class="title">录入会员</text>
|
||||
<text class="iconfont iconguanbi1" @click="closedFn"></text>
|
||||
</view>
|
||||
<view class="form-content">
|
||||
<view>
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required">*</text>
|
||||
手机号:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<input type="number" class="form-input" v-model="memberData.mobile" placeholder="请输入会员手机号" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
会员名称:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<input type="text" class="form-input" v-model="memberData.nickname" placeholder="请输入会员昵称" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
性别:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<uni-data-checkbox v-model="memberData.sex" :localdata="sex"/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
生日:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<uni-datetime-picker v-model="memberData.birthday" type="date" :clearIcon="false" @change="changeTime" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item" v-if="memberLevelList.length">
|
||||
<view class="form-label">
|
||||
<text class="required"></text>
|
||||
会员等级:
|
||||
</view>
|
||||
<view class="form-inline">
|
||||
<select-lay :zindex="10" :value="memberData.member_level" name="names" placeholder="请选择会员等级" :options="memberLevelList" @selectitem="selectMemberLevel"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn-wrap">
|
||||
<button type="primary" class="primary-btn" @click="addMemberFn">确定录入</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<uni-popup ref="emptyPopup" type="center">
|
||||
<view class="member-empty">
|
||||
<view class="head">提示</view>
|
||||
<view class="content">未找到顾客{{searchText}}</view>
|
||||
<view class="btn-wrap">
|
||||
<button class="close-btn" @click="$refs.emptyPopup.close()">关闭</button>
|
||||
<button class="primary-btn" v-if="isPhone" @click="memberEmptyRegister()">注册</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import index from './index.js';
|
||||
export default {
|
||||
mixins: [index]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
146
addon/cashier/source/os/components/ns-update/ns-update.vue
Executable file
146
addon/cashier/source/os/components/ns-update/ns-update.vue
Executable file
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<view>
|
||||
<uni-popup ref="updatePopup" type="center" :maskClick="false" v-if="versionInfo">
|
||||
<view class="update-wrap">
|
||||
<view class="head"><image src="@/static/cashier/update_header.png" /></view>
|
||||
<view class="body">
|
||||
<view class="version-no">版本号:{{ versionInfo.version }}</view>
|
||||
<view class="title">更新内容</view>
|
||||
<view class="desc common-scrollbar">{{ versionInfo.update_desc }}</view>
|
||||
<button type="default" class="primary-btn" @click="update">立即更新</button>
|
||||
<view class="giveup-update" @click="giveupUpdate" v-if="!versionInfo.is_force_upgrade">以后再说</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* app版本更新
|
||||
*/
|
||||
import {checkUpdate} from '@/api/config.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
versionInfo: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// wifi模式下才检测升级
|
||||
if (plus.networkinfo.getCurrentType() == plus.networkinfo.CONNECTION_WIFI) {
|
||||
this.checkUpdateFn();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 检测是否有新版本
|
||||
*/
|
||||
checkUpdateFn() {
|
||||
checkUpdate({
|
||||
app_key: this.$config.app.app_key,
|
||||
version: this.$config.app.version_no,
|
||||
platform: uni.getSystemInfoSync().platform
|
||||
}).then(res=>{
|
||||
if (res.code == 0 && res.data) {
|
||||
this.versionInfo = res.data;
|
||||
if (!uni.getStorageSync('version_' + this.versionInfo.version_no)) {
|
||||
this.$refs.updatePopup.open();
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 确认更新
|
||||
*/
|
||||
update() {
|
||||
let systemInfo = uni.getSystemInfoSync();
|
||||
if (systemInfo.platform == 'android') {
|
||||
uni.showLoading({});
|
||||
uni.downloadFile({
|
||||
url: this.$util.img(this.versionInfo.package_path),
|
||||
success: data => {
|
||||
uni.hideLoading();
|
||||
if (data.statusCode === 200) {
|
||||
plus.runtime.install(
|
||||
data.tempFilePath,
|
||||
{
|
||||
force: false
|
||||
},
|
||||
function() {
|
||||
plus.runtime.restart();
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
fail: res => {
|
||||
this.$util.showToast({ title: '安装包下载失败' });
|
||||
uni.hideLoading();
|
||||
}
|
||||
});
|
||||
} else if (systemInfo.platform == 'ios') {
|
||||
plus.runtime.launchApplication({ action: this.versionInfo.package_path }, e => {
|
||||
this.$util.showToast({ title: e.message });
|
||||
this.$refs.updatePopup.close();
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 放弃本次更新
|
||||
*/
|
||||
giveupUpdate() {
|
||||
uni.setStorageSync('version_' + this.versionInfo.version_no, 1);
|
||||
this.$refs.updatePopup.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.update-wrap {
|
||||
width: 3rem;
|
||||
|
||||
.head {
|
||||
height: 0.98rem;
|
||||
|
||||
image {
|
||||
width: 3rem;
|
||||
height: 0.98rem;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
padding: 0.2rem 0.3rem;
|
||||
background: #fff;
|
||||
|
||||
.version-no {
|
||||
margin-bottom: 0.15rem;
|
||||
}
|
||||
|
||||
.desc {
|
||||
max-height: 1rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 0.16rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.15rem;
|
||||
}
|
||||
|
||||
.primary-btn {
|
||||
margin-top: 0.15rem;
|
||||
}
|
||||
|
||||
.giveup-update {
|
||||
margin-top: 0.15rem;
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .uni-popup {
|
||||
z-index: 1010;
|
||||
}
|
||||
</style>
|
||||
220
addon/cashier/source/os/components/pick-regions/pick-regions.vue
Executable file
220
addon/cashier/source/os/components/pick-regions/pick-regions.vue
Executable file
@@ -0,0 +1,220 @@
|
||||
<template>
|
||||
<view class="pick-regions">
|
||||
<picker mode="multiSelector" :value="multiIndex" :range="multiArray" @change="handleValueChange" @columnchange="handleColumnChange">
|
||||
<slot></slot>
|
||||
</picker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getAreaList} from '@/api/address.js'
|
||||
export default {
|
||||
props: {
|
||||
defaultRegions: {
|
||||
type: Array
|
||||
},
|
||||
selectArr: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pickerValueArray: [],
|
||||
cityArr: [],
|
||||
districtArr: [],
|
||||
multiIndex: [0, 0, 0],
|
||||
isInitMultiArray: false,
|
||||
// 是否加载完默认地区
|
||||
isLoadDefaultAreas: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
defaultRegions: {
|
||||
handler(arr, oldArr = []) {
|
||||
// 避免传的是字面量的时候重复触发
|
||||
if (arr.length != this.selectArr || arr.join('') === oldArr.join('')) return;
|
||||
|
||||
this.handleDefaultRegions();
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
multiArray() {
|
||||
if (!this.isLoadDefaultAreas) return;
|
||||
var arr = this.pickedArr.map(arr => arr.map(item => item.label));
|
||||
return arr;
|
||||
},
|
||||
pickedArr() {
|
||||
// 进行初始化
|
||||
if (this.isInitMultiArray) {
|
||||
if (this.selectArr == '2') {
|
||||
return [this.pickerValueArray[0], this.pickerValueArray[1]];
|
||||
} else {
|
||||
return [this.pickerValueArray[0], this.pickerValueArray[1], this.pickerValueArray[2]];
|
||||
}
|
||||
}
|
||||
|
||||
if (this.selectArr == '2') {
|
||||
return [this.pickerValueArray[0], this.cityArr];
|
||||
} else {
|
||||
return [this.pickerValueArray[0], this.cityArr, this.districtArr];
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getDefaultAreas(0, { level: 0 });
|
||||
},
|
||||
methods: {
|
||||
async handleColumnChange(e) {
|
||||
this.isInitMultiArray = false;
|
||||
let col = e.detail.column;
|
||||
let row = e.detail.value;
|
||||
this.multiIndex[col] = row;
|
||||
switch (col) {
|
||||
case 0:
|
||||
//选择省,加载市、区县
|
||||
this.cityArr = await this.getAreasAsync(this.pickerValueArray[0][this.multiIndex[col]].value);
|
||||
this.districtArr = await this.getAreasAsync(this.cityArr[0].value);
|
||||
break;
|
||||
case 1:
|
||||
//选择市,加载区县
|
||||
this.districtArr = await this.getAreasAsync(this.cityArr[this.multiIndex[col]].value);
|
||||
break;
|
||||
case 2:
|
||||
if (!this.cityArr.length) this.cityArr = await this.getAreasAsync(this.pickerValueArray[0][0].value)
|
||||
if (!this.districtArr.length) this.districtArr = await this.getAreasAsync(this.cityArr[0].value);
|
||||
break;
|
||||
}
|
||||
},
|
||||
handleValueChange(e) {
|
||||
// 结构赋值
|
||||
let [index0, index1, index2] = e.detail.value;
|
||||
let [arr0, arr1, arr2] = this.pickedArr;
|
||||
let address = '';
|
||||
if (this.selectArr == '2') {
|
||||
address = [arr0[index0], arr1[index1]];
|
||||
} else {
|
||||
address = [arr0[index0], arr1[index1], arr2[index2]];
|
||||
}
|
||||
this.$emit('getRegions', address);
|
||||
},
|
||||
handleDefaultRegions() {
|
||||
var time = setInterval(() => {
|
||||
if (!this.isLoadDefaultAreas) return;
|
||||
this.isInitMultiArray = false;
|
||||
for (let i = 0; i < this.defaultRegions.length; i++) {
|
||||
for (let j = 0; j < this.pickerValueArray[i].length; j++) {
|
||||
// 匹配省
|
||||
if ( (this.defaultRegions[i] == this.pickerValueArray[i][j].value || this.defaultRegions[i] == this.pickerValueArray[i][j].label) && this.pickerValueArray[i][j].level == 1) {
|
||||
// 设置选中省
|
||||
this.$set(this.multiIndex, i, j);
|
||||
|
||||
// 查询市
|
||||
this.getAreas(this.pickerValueArray[i][j].value, data => {
|
||||
this.cityArr = data;
|
||||
|
||||
for (let k = 0; k < this.cityArr.length; k++) {
|
||||
if (this.defaultRegions[1] == this.cityArr[k].value || this.defaultRegions[1] == this.cityArr[k].label) {
|
||||
// 设置选中市
|
||||
this.$set(this.multiIndex, 1, k);
|
||||
|
||||
// 查询区县
|
||||
this.getAreas(this.cityArr[k].value, data => {
|
||||
this.districtArr = data;
|
||||
|
||||
// 设置选中区县
|
||||
for (let u = 0; u < this.districtArr.length; u++) {
|
||||
if (this.defaultRegions[2] == this.districtArr[u].value || this.defaultRegions[2] == this.districtArr[u].label) {
|
||||
this.$set(this.multiIndex, 2, u);
|
||||
this.handleValueChange({
|
||||
detail: {
|
||||
value: [j, k, u]
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.isLoadDefaultAreas) clearInterval(time);
|
||||
}, 100);
|
||||
},
|
||||
getDefaultAreas(pid, obj) {
|
||||
getAreaList({ pid: pid }).then(res=>{
|
||||
if (res.code == 0) {
|
||||
var data = [];
|
||||
var selected = undefined;
|
||||
res.data.forEach((item, index) => {
|
||||
if (obj != undefined) {
|
||||
if (obj.level == 0 && obj.province_id != undefined) {
|
||||
selected = obj.province_id;
|
||||
} else if (obj.level == 1 && obj.city_id != undefined) {
|
||||
selected = obj.city_id;
|
||||
} else if (obj.level == 2 && obj.district_id != undefined) {
|
||||
selected = obj.district_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (selected == undefined && index == 0) {
|
||||
selected = item.id;
|
||||
}
|
||||
data.push({
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
level: item.level
|
||||
});
|
||||
});
|
||||
|
||||
this.pickerValueArray[obj.level] = data;
|
||||
if (obj.level + 1 < 3) {
|
||||
obj.level++;
|
||||
this.getDefaultAreas(selected, obj);
|
||||
} else {
|
||||
this.isInitMultiArray = true;
|
||||
this.isLoadDefaultAreas = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 同步获取地区
|
||||
async getAreasAsync(pid) {
|
||||
let res = await getAreaList({ pid: pid });
|
||||
if (res.code == 0) {
|
||||
var data = [];
|
||||
res.data.forEach((item, index) => {
|
||||
data.push({
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
level: item.level
|
||||
});
|
||||
});
|
||||
return data;
|
||||
}
|
||||
},
|
||||
// 异步获取地区
|
||||
getAreas(pid, callback) {
|
||||
getAreaList({ pid: pid }).then(res=>{
|
||||
if (res.code == 0) {
|
||||
var data = [];
|
||||
res.data.forEach((item, index) => {
|
||||
data.push({
|
||||
value: item.id,
|
||||
label: item.name,
|
||||
level: item.level
|
||||
});
|
||||
});
|
||||
if (callback) callback(data);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
201
addon/cashier/source/os/components/qiun-data-charts/license.md
Executable file
201
addon/cashier/source/os/components/qiun-data-charts/license.md
Executable file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
1598
addon/cashier/source/os/components/qiun-data-charts/qiun-data-charts.vue
Executable file
1598
addon/cashier/source/os/components/qiun-data-charts/qiun-data-charts.vue
Executable file
File diff suppressed because it is too large
Load Diff
44
addon/cashier/source/os/components/qiun-error/qiun-error.vue
Executable file
44
addon/cashier/source/os/components/qiun-error/qiun-error.vue
Executable file
File diff suppressed because one or more lines are too long
166
addon/cashier/source/os/components/qiun-loading/loading1.vue
Executable file
166
addon/cashier/source/os/components/qiun-loading/loading1.vue
Executable file
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<view class="container loading1">
|
||||
<view class="shape shape1"></view>
|
||||
<view class="shape shape2"></view>
|
||||
<view class="shape shape3"></view>
|
||||
<view class="shape shape4"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading1',
|
||||
data() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped="true">
|
||||
.container {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container.loading1 {
|
||||
-webkit-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.container .shape {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.container .shape.shape1 {
|
||||
left: 0;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
|
||||
.container .shape.shape2 {
|
||||
right: 0;
|
||||
background-color: #91CB74;
|
||||
}
|
||||
|
||||
.container .shape.shape3 {
|
||||
bottom: 0;
|
||||
background-color: #FAC858;
|
||||
}
|
||||
|
||||
.container .shape.shape4 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #EE6666;
|
||||
}
|
||||
|
||||
.loading1 .shape1 {
|
||||
-webkit-animation: animation1shape1 0.5s ease 0s infinite alternate;
|
||||
animation: animation1shape1 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation1shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(16px, 16px);
|
||||
transform: translate(16px, 16px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation1shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(16px, 16px);
|
||||
transform: translate(16px, 16px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading1 .shape2 {
|
||||
-webkit-animation: animation1shape2 0.5s ease 0s infinite alternate;
|
||||
animation: animation1shape2 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation1shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-16px, 16px);
|
||||
transform: translate(-16px, 16px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation1shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-16px, 16px);
|
||||
transform: translate(-16px, 16px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading1 .shape3 {
|
||||
-webkit-animation: animation1shape3 0.5s ease 0s infinite alternate;
|
||||
animation: animation1shape3 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation1shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(16px, -16px);
|
||||
transform: translate(16px, -16px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation1shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(16px, -16px);
|
||||
transform: translate(16px, -16px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading1 .shape4 {
|
||||
-webkit-animation: animation1shape4 0.5s ease 0s infinite alternate;
|
||||
animation: animation1shape4 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation1shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-16px, -16px);
|
||||
transform: translate(-16px, -16px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation1shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-16px, -16px);
|
||||
transform: translate(-16px, -16px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
176
addon/cashier/source/os/components/qiun-loading/loading2.vue
Executable file
176
addon/cashier/source/os/components/qiun-loading/loading2.vue
Executable file
@@ -0,0 +1,176 @@
|
||||
<template>
|
||||
<view class="container loading2">
|
||||
<view class="shape shape1"></view>
|
||||
<view class="shape shape2"></view>
|
||||
<view class="shape shape3"></view>
|
||||
<view class="shape shape4"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading2',
|
||||
data() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped="true">
|
||||
.container {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container.loading2 {
|
||||
-webkit-transform: rotate(10deg);
|
||||
transform: rotate(10deg);
|
||||
}
|
||||
|
||||
.container.loading2 .shape {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.container.loading2 {
|
||||
-webkit-animation: rotation 1s infinite;
|
||||
animation: rotation 1s infinite;
|
||||
}
|
||||
|
||||
.container .shape {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.container .shape.shape1 {
|
||||
left: 0;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
|
||||
.container .shape.shape2 {
|
||||
right: 0;
|
||||
background-color: #91CB74;
|
||||
}
|
||||
|
||||
.container .shape.shape3 {
|
||||
bottom: 0;
|
||||
background-color: #FAC858;
|
||||
}
|
||||
|
||||
.container .shape.shape4 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #EE6666;
|
||||
}
|
||||
|
||||
|
||||
.loading2 .shape1 {
|
||||
-webkit-animation: animation2shape1 0.5s ease 0s infinite alternate;
|
||||
animation: animation2shape1 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation2shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(20px, 20px);
|
||||
transform: translate(20px, 20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation2shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(20px, 20px);
|
||||
transform: translate(20px, 20px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading2 .shape2 {
|
||||
-webkit-animation: animation2shape2 0.5s ease 0s infinite alternate;
|
||||
animation: animation2shape2 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation2shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-20px, 20px);
|
||||
transform: translate(-20px, 20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation2shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-20px, 20px);
|
||||
transform: translate(-20px, 20px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading2 .shape3 {
|
||||
-webkit-animation: animation2shape3 0.5s ease 0s infinite alternate;
|
||||
animation: animation2shape3 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation2shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(20px, -20px);
|
||||
transform: translate(20px, -20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation2shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(20px, -20px);
|
||||
transform: translate(20px, -20px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading2 .shape4 {
|
||||
-webkit-animation: animation2shape4 0.5s ease 0s infinite alternate;
|
||||
animation: animation2shape4 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation2shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-20px, -20px);
|
||||
transform: translate(-20px, -20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation2shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-20px, -20px);
|
||||
transform: translate(-20px, -20px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
182
addon/cashier/source/os/components/qiun-loading/loading3.vue
Executable file
182
addon/cashier/source/os/components/qiun-loading/loading3.vue
Executable file
@@ -0,0 +1,182 @@
|
||||
<template>
|
||||
<view class="container loading3">
|
||||
<view class="shape shape1"></view>
|
||||
<view class="shape shape2"></view>
|
||||
<view class="shape shape3"></view>
|
||||
<view class="shape shape4"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading3',
|
||||
data() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped="true">
|
||||
.container {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container.loading3 {
|
||||
-webkit-animation: rotation 1s infinite;
|
||||
animation: rotation 1s infinite;
|
||||
}
|
||||
|
||||
.container.loading3 .shape1 {
|
||||
border-top-left-radius: 10px;
|
||||
}
|
||||
|
||||
.container.loading3 .shape2 {
|
||||
border-top-right-radius: 10px;
|
||||
}
|
||||
|
||||
.container.loading3 .shape3 {
|
||||
border-bottom-left-radius: 10px;
|
||||
}
|
||||
|
||||
.container.loading3 .shape4 {
|
||||
border-bottom-right-radius: 10px;
|
||||
}
|
||||
|
||||
.container .shape {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.container .shape.shape1 {
|
||||
left: 0;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
|
||||
.container .shape.shape2 {
|
||||
right: 0;
|
||||
background-color: #91CB74;
|
||||
}
|
||||
|
||||
.container .shape.shape3 {
|
||||
bottom: 0;
|
||||
background-color: #FAC858;
|
||||
}
|
||||
|
||||
.container .shape.shape4 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #EE6666;
|
||||
}
|
||||
|
||||
.loading3 .shape1 {
|
||||
-webkit-animation: animation3shape1 0.5s ease 0s infinite alternate;
|
||||
animation: animation3shape1 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation3shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(5px, 5px);
|
||||
transform: translate(5px, 5px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation3shape1 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(5px, 5px);
|
||||
transform: translate(5px, 5px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading3 .shape2 {
|
||||
-webkit-animation: animation3shape2 0.5s ease 0s infinite alternate;
|
||||
animation: animation3shape2 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation3shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-5px, 5px);
|
||||
transform: translate(-5px, 5px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation3shape2 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-5px, 5px);
|
||||
transform: translate(-5px, 5px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading3 .shape3 {
|
||||
-webkit-animation: animation3shape3 0.5s ease 0s infinite alternate;
|
||||
animation: animation3shape3 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation3shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(5px, -5px);
|
||||
transform: translate(5px, -5px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation3shape3 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(5px, -5px);
|
||||
transform: translate(5px, -5px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading3 .shape4 {
|
||||
-webkit-animation: animation3shape4 0.5s ease 0s infinite alternate;
|
||||
animation: animation3shape4 0.5s ease 0s infinite alternate;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation3shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-5px, -5px);
|
||||
transform: translate(-5px, -5px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation3shape4 {
|
||||
from {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translate(-5px, -5px);
|
||||
transform: translate(-5px, -5px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
227
addon/cashier/source/os/components/qiun-loading/loading4.vue
Executable file
227
addon/cashier/source/os/components/qiun-loading/loading4.vue
Executable file
@@ -0,0 +1,227 @@
|
||||
<template>
|
||||
<view class="container loading5">
|
||||
<view class="shape shape1"></view>
|
||||
<view class="shape shape2"></view>
|
||||
<view class="shape shape3"></view>
|
||||
<view class="shape shape4"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading5',
|
||||
data() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped="true">
|
||||
.container {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container.loading5 .shape {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.container .shape {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.container .shape.shape1 {
|
||||
left: 0;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
|
||||
.container .shape.shape2 {
|
||||
right: 0;
|
||||
background-color: #91CB74;
|
||||
}
|
||||
|
||||
.container .shape.shape3 {
|
||||
bottom: 0;
|
||||
background-color: #FAC858;
|
||||
}
|
||||
|
||||
.container .shape.shape4 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #EE6666;
|
||||
}
|
||||
|
||||
.loading5 .shape1 {
|
||||
animation: animation5shape1 2s ease 0s infinite reverse;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation5shape1 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, 15px);
|
||||
transform: translate(0, 15px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(15px, 15px);
|
||||
transform: translate(15px, 15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(15px, 0);
|
||||
transform: translate(15px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation5shape1 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, 15px);
|
||||
transform: translate(0, 15px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(15px, 15px);
|
||||
transform: translate(15px, 15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(15px, 0);
|
||||
transform: translate(15px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.loading5 .shape2 {
|
||||
animation: animation5shape2 2s ease 0s infinite reverse;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation5shape2 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(-15px, 0);
|
||||
transform: translate(-15px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-15px, 15px);
|
||||
transform: translate(-15px, 15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, 15px);
|
||||
transform: translate(0, 15px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation5shape2 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(-15px, 0);
|
||||
transform: translate(-15px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-15px, 15px);
|
||||
transform: translate(-15px, 15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, 15px);
|
||||
transform: translate(0, 15px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading5 .shape3 {
|
||||
animation: animation5shape3 2s ease 0s infinite reverse;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation5shape3 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(15px, 0);
|
||||
transform: translate(15px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(15px, -15px);
|
||||
transform: translate(15px, -15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, -15px);
|
||||
transform: translate(0, -15px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation5shape3 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(15px, 0);
|
||||
transform: translate(15px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(15px, -15px);
|
||||
transform: translate(15px, -15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, -15px);
|
||||
transform: translate(0, -15px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading5 .shape4 {
|
||||
animation: animation5shape4 2s ease 0s infinite reverse;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation5shape4 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, -15px);
|
||||
transform: translate(0, -15px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-15px, -15px);
|
||||
transform: translate(-15px, -15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(-15px, 0);
|
||||
transform: translate(-15px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation5shape4 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, -15px);
|
||||
transform: translate(0, -15px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-15px, -15px);
|
||||
transform: translate(-15px, -15px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(-15px, 0);
|
||||
transform: translate(-15px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
235
addon/cashier/source/os/components/qiun-loading/loading5.vue
Executable file
235
addon/cashier/source/os/components/qiun-loading/loading5.vue
Executable file
@@ -0,0 +1,235 @@
|
||||
<template>
|
||||
<view class="container loading6">
|
||||
<view class="shape shape1"></view>
|
||||
<view class="shape shape2"></view>
|
||||
<view class="shape shape3"></view>
|
||||
<view class="shape shape4"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'loading6',
|
||||
data() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped="true">
|
||||
.container {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container.loading6 {
|
||||
-webkit-animation: rotation 1s infinite;
|
||||
animation: rotation 1s infinite;
|
||||
}
|
||||
|
||||
.container.loading6 .shape {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.container .shape {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.container .shape.shape1 {
|
||||
left: 0;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
|
||||
.container .shape.shape2 {
|
||||
right: 0;
|
||||
background-color: #91CB74;
|
||||
}
|
||||
|
||||
.container .shape.shape3 {
|
||||
bottom: 0;
|
||||
background-color: #FAC858;
|
||||
}
|
||||
|
||||
.container .shape.shape4 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: #EE6666;
|
||||
}
|
||||
|
||||
.loading6 .shape1 {
|
||||
-webkit-animation: animation6shape1 2s linear 0s infinite normal;
|
||||
animation: animation6shape1 2s linear 0s infinite normal;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation6shape1 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, 18px);
|
||||
transform: translate(0, 18px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(18px, 18px);
|
||||
transform: translate(18px, 18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(18px, 0);
|
||||
transform: translate(18px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation6shape1 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, 18px);
|
||||
transform: translate(0, 18px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(18px, 18px);
|
||||
transform: translate(18px, 18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(18px, 0);
|
||||
transform: translate(18px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.loading6 .shape2 {
|
||||
-webkit-animation: animation6shape2 2s linear 0s infinite normal;
|
||||
animation: animation6shape2 2s linear 0s infinite normal;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation6shape2 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(-18px, 0);
|
||||
transform: translate(-18px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-18px, 18px);
|
||||
transform: translate(-18px, 18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, 18px);
|
||||
transform: translate(0, 18px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation6shape2 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(-18px, 0);
|
||||
transform: translate(-18px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-18px, 18px);
|
||||
transform: translate(-18px, 18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, 18px);
|
||||
transform: translate(0, 18px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading6 .shape3 {
|
||||
-webkit-animation: animation6shape3 2s linear 0s infinite normal;
|
||||
animation: animation6shape3 2s linear 0s infinite normal;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation6shape3 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(18px, 0);
|
||||
transform: translate(18px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(18px, -18px);
|
||||
transform: translate(18px, -18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, -18px);
|
||||
transform: translate(0, -18px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation6shape3 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(18px, 0);
|
||||
transform: translate(18px, 0);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(18px, -18px);
|
||||
transform: translate(18px, -18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(0, -18px);
|
||||
transform: translate(0, -18px);
|
||||
}
|
||||
}
|
||||
|
||||
.loading6 .shape4 {
|
||||
-webkit-animation: animation6shape4 2s linear 0s infinite normal;
|
||||
animation: animation6shape4 2s linear 0s infinite normal;
|
||||
}
|
||||
|
||||
@-webkit-keyframes animation6shape4 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, -18px);
|
||||
transform: translate(0, -18px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-18px, -18px);
|
||||
transform: translate(-18px, -18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(-18px, 0);
|
||||
transform: translate(-18px, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animation6shape4 {
|
||||
0% {
|
||||
-webkit-transform: translate(0, 0);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
25% {
|
||||
-webkit-transform: translate(0, -18px);
|
||||
transform: translate(0, -18px);
|
||||
}
|
||||
50% {
|
||||
-webkit-transform: translate(-18px, -18px);
|
||||
transform: translate(-18px, -18px);
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translate(-18px, 0);
|
||||
transform: translate(-18px, 0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
34
addon/cashier/source/os/components/qiun-loading/qiun-loading.vue
Executable file
34
addon/cashier/source/os/components/qiun-loading/qiun-loading.vue
Executable file
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<view>
|
||||
<Loading1 v-if="loadingType==1" />
|
||||
<Loading2 v-if="loadingType==2" />
|
||||
<Loading3 v-if="loadingType==3" />
|
||||
<Loading4 v-if="loadingType==4" />
|
||||
<Loading5 v-if="loadingType==5" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Loading1 from "./loading1.vue";
|
||||
import Loading2 from "./loading2.vue";
|
||||
import Loading3 from "./loading3.vue";
|
||||
import Loading4 from "./loading4.vue";
|
||||
import Loading5 from "./loading5.vue";
|
||||
|
||||
export default {
|
||||
components: {Loading1, Loading2, Loading3, Loading4, Loading5},
|
||||
name: 'qiun-loading',
|
||||
props: {
|
||||
loadingType: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
455
addon/cashier/source/os/components/select-lay/select-lay.vue
Executable file
455
addon/cashier/source/os/components/select-lay/select-lay.vue
Executable file
@@ -0,0 +1,455 @@
|
||||
<template>
|
||||
<view class="uni-select-lay" :style="{ 'z-index': zindex }">
|
||||
<input type="text" :name="name" v-model="value" class="uni-select-input" readonly />
|
||||
<view class="uni-select-lay-select" :class="{ active: active }">
|
||||
<!-- 禁用mask -->
|
||||
<view class="uni-disabled" v-if="disabled"></view>
|
||||
<!-- 禁用mask -->
|
||||
<!-- 清空 -->
|
||||
<view class="uni-select-lay-input-close" v-if="changevalue != '' && this.active"><text @click.stop="removevalue"></text></view>
|
||||
<!-- 清空 -->
|
||||
<input
|
||||
type="text"
|
||||
readonly
|
||||
disabled="true"
|
||||
class="uni-select-lay-input"
|
||||
:class="{ active: changevalue != '' && changevalue != placeholder }"
|
||||
v-model="changevalue"
|
||||
:placeholder="placeholder"
|
||||
@focus="unifocus"
|
||||
@input="intchange"
|
||||
@blur="uniblur"
|
||||
@click.stop="select"
|
||||
/>
|
||||
<view class="uni-select-lay-icon" :class="{ disabled: disabled }" @click.stop="select"><text></text></view>
|
||||
</view>
|
||||
<view class="uni-date-mask" v-show="active" @click.stop="select"></view>
|
||||
<scroll-view class="uni-select-lay-options" :scroll-y="true" v-show="active" @scroll="selectmove" @touchstart="movetouch">
|
||||
<template v-if="!changes">
|
||||
<view class="uni-select-lay-item" v-if="showplaceholder" :class="{ active: value == '' }" @click.stop="selectitem(-1, null)">{{ placeholder }}</view>
|
||||
<view class="uni-select-lay-item" :class="{ active: value == item[svalue], disabled: item.disabled }" v-for="(item, index) in options" :key="index" @click.stop="selectitem(index, item)">
|
||||
{{ item[slabel] }}
|
||||
</view>
|
||||
</template>
|
||||
<!-- 搜索 -->
|
||||
<template v-else>
|
||||
<template v-if="vlist.length > 0">
|
||||
<view class="uni-select-lay-item" :class="{ active: value == item[svalue] }" v-for="(item, index) in vlist" :key="index" @click.stop="selectitem(index, item)">
|
||||
{{ item[slabel] }}
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="nosearch">{{ changesValue }}</view>
|
||||
</template>
|
||||
</template>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'select-lay',
|
||||
props: {
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
zindex: {
|
||||
type: Number,
|
||||
default: 999
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
value: {
|
||||
type: [String,Number],
|
||||
default: ''
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
showplaceholder: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
slabel: {
|
||||
type: String,
|
||||
default: 'label'
|
||||
},
|
||||
svalue: {
|
||||
type: String,
|
||||
default: 'value'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
active: false, //组件是否激活,
|
||||
isfocus: false, //是否有焦点
|
||||
isremove: false, //是否是因为点击清空才导致的失去焦点
|
||||
ismove: false, //是否是因为移动才失去焦点
|
||||
changevalue: '', //搜索框同步
|
||||
oldvalue: '', //数据回滚
|
||||
changes: false, //正在搜索
|
||||
changesValue: '',
|
||||
vlist: [], //搜索框查询的列表
|
||||
settimer: null //value改变定时器
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.itemcheck();
|
||||
},
|
||||
watch: {
|
||||
//value改变
|
||||
value() {
|
||||
this.itemcheck();
|
||||
},
|
||||
//初始化数组
|
||||
options() {
|
||||
// 此处判断是否有初始value,存在则判断显示文字
|
||||
this.itemcheck();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//判断数组跟当前active值
|
||||
itemcheck() {
|
||||
// 此处判断是否有初始value,存在则判断显示文字
|
||||
if (this.value != '') {
|
||||
// 展示plachhoder
|
||||
//判断数组
|
||||
if (this.options.length > 0) {
|
||||
this.options.forEach(item => {
|
||||
if (this.value == item[this.svalue]) {
|
||||
this.oldvalue = this.changevalue = item[this.slabel];
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.oldvalue = this.changevalue = '';
|
||||
}
|
||||
},
|
||||
//点击组件
|
||||
select() {
|
||||
if (this.disabled) return;
|
||||
this.active = !this.active;
|
||||
if (this.active) {
|
||||
this.changes = false;
|
||||
} else {
|
||||
this.changevalue = this.oldvalue;
|
||||
}
|
||||
},
|
||||
// 获得焦点
|
||||
unifocus() {
|
||||
if (this.disabled) return;
|
||||
this.active = true;
|
||||
this.changes = false;
|
||||
this.isfocus = true;
|
||||
},
|
||||
// 失去焦点
|
||||
uniblur() {
|
||||
this.isfocus = false;
|
||||
// bug 点击组件列会先触发失去焦点,此时组件列事件不执行
|
||||
setTimeout(() => {
|
||||
if (this.isremove || this.ismove) {
|
||||
this.isremove = false;
|
||||
this.ismove = false;
|
||||
} else {
|
||||
this.changevalue = this.oldvalue;
|
||||
this.isremove = false;
|
||||
this.active = false;
|
||||
}
|
||||
}, 153);
|
||||
},
|
||||
movetouch() {
|
||||
setTimeout(() => {
|
||||
if (this.isfocus) {
|
||||
this.ismove = false;
|
||||
return;
|
||||
}
|
||||
if (!this.ismove) this.ismove = true;
|
||||
}, 100);
|
||||
// this.changes = false;
|
||||
},
|
||||
selectmove() {
|
||||
setTimeout(() => {
|
||||
if (this.isfocus) {
|
||||
this.ismove = false;
|
||||
return;
|
||||
}
|
||||
if (!this.ismove) this.ismove = true;
|
||||
}, 100);
|
||||
|
||||
// this.changes = false;
|
||||
},
|
||||
//移除数据
|
||||
removevalue() {
|
||||
this.isremove = true;
|
||||
this.changes = false;
|
||||
this.changevalue = '';
|
||||
},
|
||||
//value 改变
|
||||
intchange() {
|
||||
if (this.changevalue == '') {
|
||||
this.changes = false;
|
||||
return;
|
||||
}
|
||||
if (this.oldvalue == this.changevalue) {
|
||||
return;
|
||||
}
|
||||
this.vlist = [];
|
||||
this.changes = true;
|
||||
this.changesValue = '正在搜索...';
|
||||
if (this.settimer) {
|
||||
clearTimeout(this.settimer);
|
||||
}
|
||||
this.settimer = setTimeout(() => {
|
||||
this.vlist = this.options.filter(item => {
|
||||
return item[this.slabel].includes(this.changevalue);
|
||||
});
|
||||
if (this.vlist.length === 0) {
|
||||
this.changesValue = '暂无匹配内容!';
|
||||
}
|
||||
}, 600);
|
||||
},
|
||||
|
||||
//点击组件列
|
||||
selectitem(index, item) {
|
||||
if (item && item.disabled) {
|
||||
return false;
|
||||
}
|
||||
this.changevalue = this.oldvalue;
|
||||
this.active = false;
|
||||
this.$emit('selectitem', index, item);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uni-select-lay {
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
box-sizing: border-box;
|
||||
.uni-select-input {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
z-index: -111;
|
||||
}
|
||||
|
||||
// select部分
|
||||
.uni-select-lay-select {
|
||||
user-select: none;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
height: 0.32rem;
|
||||
padding: 0 0.3rem 0 0.1rem;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0.02rem;
|
||||
border: 0.01rem solid rgb(229, 229, 229);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 0.14rem;
|
||||
color: #999;
|
||||
|
||||
.uni-disabled {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 19;
|
||||
cursor: no-drop;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
// input 框的清除按钮
|
||||
.uni-select-lay-input-close {
|
||||
position: absolute;
|
||||
right: 0.35rem;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 0.15rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 3;
|
||||
cursor: pointer;
|
||||
|
||||
text {
|
||||
position: relative;
|
||||
background: #fff;
|
||||
width: 0.13rem;
|
||||
height: 0.13rem;
|
||||
border-radius: 50%;
|
||||
border: 0.01rem solid #bbb;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 20%;
|
||||
top: 50%;
|
||||
height: 0.01rem;
|
||||
width: 60%;
|
||||
transform: rotate(45deg);
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
&::after {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.uni-select-lay-input {
|
||||
font-size: 0.14rem;
|
||||
color: #999;
|
||||
display: block;
|
||||
width: 98%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
line-height: 0.3rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.active {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.uni-select-lay-icon {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 0.3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
width: 0.01rem;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
|
||||
text {
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-width: 0.07rem 0.07rem 0;
|
||||
border-style: solid;
|
||||
border-color: #bbb transparent transparent;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: no-drop;
|
||||
|
||||
text {
|
||||
width: 0.2rem;
|
||||
height: 0.2rem;
|
||||
border: 0.02rem solid #ff0000;
|
||||
border-radius: 50%;
|
||||
transition: 0.3s;
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 0.02rem;
|
||||
margin-top: -0.01rem;
|
||||
background-color: #ff0000;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.active .uni-select-lay-icon {
|
||||
text {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// options部分
|
||||
.uni-select-lay-options {
|
||||
user-select: none;
|
||||
position: absolute;
|
||||
top: calc(100% + 0.05rem);
|
||||
left: 0;
|
||||
width: 100%;
|
||||
// height: 500rpx;
|
||||
max-height: 2.5rem;
|
||||
// overflow-y: auto;
|
||||
border-radius: 0.02rem;
|
||||
border: 1px solid rgb(229, 229, 229);
|
||||
background: #fff;
|
||||
padding: 0.05rem 0;
|
||||
box-sizing: border-box;
|
||||
z-index: 9;
|
||||
|
||||
.uni-select-lay-item {
|
||||
padding: 0 0.1rem;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
line-height: 2.5;
|
||||
transition: 0.3s;
|
||||
font-size: 0.14rem;
|
||||
|
||||
&.active {
|
||||
background: $primary-color;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
background: $primary-color;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
color: #999;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
.nosearch {
|
||||
font-size: 0.16rem;
|
||||
line-height: 3;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
.uni-date-mask {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
transition-duration: 0.3s;
|
||||
z-index: 8;
|
||||
}
|
||||
</style>
|
||||
480
addon/cashier/source/os/components/stock-goods-dialog/stock-goods-dialog.vue
Executable file
480
addon/cashier/source/os/components/stock-goods-dialog/stock-goods-dialog.vue
Executable file
@@ -0,0 +1,480 @@
|
||||
<template>
|
||||
<unipopup ref="dialogRef" type="center" :maskClick="false">
|
||||
<view class="stock-dialog-wrap">
|
||||
<view class="stock-dialog-head">
|
||||
<text>商品选择</text>
|
||||
<text class="iconfont iconguanbi1" @click="$emit('change', false)"></text>
|
||||
</view>
|
||||
<view class="stock-dialog-body">
|
||||
<view class="tree">
|
||||
<scroll-view scroll-y="true" class="list-wrap">
|
||||
<view class="item" :class="{ 'active': option.category_id === '' }" @click="itemClick({ category_id: '', child_num: 0 })">
|
||||
<view class="icon"></view>
|
||||
<view>全部分类</view>
|
||||
</view>
|
||||
<view v-for="(item, key) in goodsCategoryList" :key="key">
|
||||
<view class="item" :class="{ 'active': option.category_id === item.category_id }" @click="itemClick(item)">
|
||||
<view class="icon" :class="{ 'active': activeList.indexOf(item.category_id) != -1 }">
|
||||
<text v-if="item.child_num" class="iconfont iconsanjiao_xia"></text>
|
||||
</view>
|
||||
<view>{{ item.title }}</view>
|
||||
</view>
|
||||
<template v-if="item.child_num">
|
||||
<view v-show="activeList.indexOf(item.category_id) != -1" v-for="(item2, key2) in item.children" :key="key2" class="level">
|
||||
<view class="item" :class="{ 'active': option.category_id === item2.category_id }" @click="itemClick(item2)">
|
||||
<view class="icon" :class="{ 'active': activeList.indexOf(item2.category_id) != -1 }">
|
||||
<text v-if="item2.child_num" class="iconfont iconsanjiao_xia"></text>
|
||||
</view>
|
||||
<view>{{ item2.title }}</view>
|
||||
</view>
|
||||
<template>
|
||||
<view v-show="activeList.indexOf(item2.category_id) != -1" v-for="(item3, key3) in item2.children" :key="key3" class="level">
|
||||
<view class="item item2" @click="itemClick(item3)">
|
||||
<view class="icon"></view>
|
||||
<view>{{ item3.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="stock-dialog-table">
|
||||
<view class="search common-form">
|
||||
<view class="common-form-item">
|
||||
<view class="form-inline">
|
||||
<view class="form-input-inline">
|
||||
<input type="text" v-model="option.search_text" @confirm="getStoreGoods" placeholder="请输入产品名称/规格/编码" class="form-input" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-inline common-btn-wrap">
|
||||
<button type="default" class="screen-btn" @click="getStoreGoods">筛选</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uniDataTable :url="url" :option="option" :cols="cols" :pagesize="8" ref="goodsListTable" @checkBox="checkBox" @tableData="tableDataChange"></uniDataTable>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="btn">
|
||||
<button type="primary" class="default-btn submit" @click="submit('close')">选中</button>
|
||||
<button type="primary" class="default-btn" @click="$emit('change', false)">取消</button>
|
||||
</view>
|
||||
</view>
|
||||
</unipopup>
|
||||
</template>
|
||||
<script>
|
||||
import unipopup from '@/components/uni-popup/uni-popup.vue';
|
||||
import uniDataTable from '@/components/uni-data-table/uni-data-table.vue';
|
||||
import {getManageGoodsCategory} from '@/api/goods.js';
|
||||
|
||||
export default {
|
||||
name: 'stockDialog',
|
||||
components: {
|
||||
unipopup,
|
||||
uniDataTable
|
||||
},
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change'
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
default: ()=>{
|
||||
return {}
|
||||
}
|
||||
},
|
||||
apiType: {
|
||||
type: String,
|
||||
default: 'sku' //选择是sku 还是 spu
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
goodsCategoryList: {},
|
||||
activeList: [],//下拉激活
|
||||
option: {
|
||||
category_id: '',
|
||||
search_text: '',
|
||||
is_weigh: 0,
|
||||
page_size: 8,
|
||||
},
|
||||
cols: [{
|
||||
width: 6,
|
||||
align: 'center',
|
||||
checkbox: true
|
||||
}, {
|
||||
field: 'account_data',
|
||||
width: 50,
|
||||
title: '商品信息',
|
||||
align: 'left',
|
||||
templet: data => {
|
||||
let img = this.$util.img(data.sku_image);
|
||||
let html = `
|
||||
<view class="goods-content">
|
||||
<image class="goods-img" src="${img}" mode="aspectFit"/>
|
||||
<text class="goods-name multi-hidden" title="${data.sku_name}">${data.sku_name}</text>
|
||||
</view>
|
||||
`;
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
field: 'real_stock',
|
||||
width: 22,
|
||||
title: '库存',
|
||||
align: 'center',
|
||||
templet: data => {
|
||||
return (data.real_stock || 0);
|
||||
}
|
||||
}, {
|
||||
width: 22,
|
||||
title: '单位',
|
||||
templet: data => {
|
||||
return (data.unit || '件');
|
||||
}
|
||||
}],
|
||||
checkList: {},
|
||||
url: '/stock/storeapi/manage/getStoreGoods'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler: function (val) {
|
||||
if (val) {
|
||||
this.$nextTick(() => {
|
||||
this.option = Object.assign(this.option, this.params);
|
||||
if (this.params.temp_store_id && this.params.temp_store_id == '') {
|
||||
delete this.option.temp_store_id
|
||||
}
|
||||
this.$refs.dialogRef.open()
|
||||
})
|
||||
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.option = Object(this.option, {
|
||||
category_id: '',
|
||||
search_text: '',
|
||||
is_weigh: 0,
|
||||
page: 1,
|
||||
page_size: 8,
|
||||
});
|
||||
this.checkList = {};
|
||||
this.$refs.dialogRef.close()
|
||||
})
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
apiType: {
|
||||
handler: function (val) {
|
||||
if(val == 'sku'){
|
||||
this.cols = [{
|
||||
width: 6,
|
||||
align: 'center',
|
||||
checkbox: true
|
||||
}, {
|
||||
field: 'account_data',
|
||||
width: 50,
|
||||
title: '商品信息',
|
||||
align: 'left',
|
||||
templet: data => {
|
||||
let img = this.$util.img(data.sku_image);
|
||||
let html = `
|
||||
<view class="goods-content">
|
||||
<image class="goods-img" src="${img}" mode="aspectFit"/>
|
||||
<text class="goods-name multi-hidden" title="${data.sku_name}">${data.sku_name}</text>
|
||||
</view>
|
||||
`;
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
field: 'real_stock',
|
||||
width: 22,
|
||||
title: '库存',
|
||||
align: 'center',
|
||||
templet: data => {
|
||||
return (data.real_stock || 0);
|
||||
}
|
||||
}, {
|
||||
width: 22,
|
||||
title: '单位',
|
||||
templet: data => {
|
||||
return (data.unit || '件');
|
||||
}
|
||||
}];
|
||||
this.url = '/stock/storeapi/manage/getStoreGoods';
|
||||
}else if(val == 'spu'){
|
||||
this.cols = [{
|
||||
width: 6,
|
||||
align: 'center',
|
||||
checkbox: true
|
||||
}, {
|
||||
field: 'account_data',
|
||||
width: 50,
|
||||
title: '商品信息',
|
||||
align: 'left',
|
||||
templet: data => {
|
||||
let img = this.$util.img(data.goods_image);
|
||||
let html = `
|
||||
<view class="goods-content">
|
||||
<image class="goods-img" src="${img}" mode="aspectFit"/>
|
||||
<text class="goods-name multi-hidden" title="${data.goods_name}">${data.goods_name}</text>
|
||||
</view>
|
||||
`;
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
field: 'goods_stock',
|
||||
width: 22,
|
||||
title: '库存',
|
||||
align: 'center',
|
||||
templet: data => {
|
||||
return (data.goods_stock || 0);
|
||||
}
|
||||
}, {
|
||||
width: 22,
|
||||
title: '商品类型',
|
||||
templet: data => {
|
||||
return (data.goods_class_name || '--');
|
||||
}
|
||||
}];
|
||||
this.url = '/cashier/storeapi/goods/getGoodsListBySelect';
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getGoodsCategory()
|
||||
},
|
||||
methods: {
|
||||
getGoodsCategory() {
|
||||
getManageGoodsCategory().then(res=>{
|
||||
uni.hideLoading();
|
||||
if (res.data && Object.keys(res.data)) {
|
||||
this.goodsCategoryList = res.data
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
itemClick(item) {//tree点击
|
||||
this.option.category_id = item.category_id;
|
||||
var index = this.activeList.indexOf(item.category_id);
|
||||
if (item.child_num && index === -1) {
|
||||
this.activeList.push(item.category_id);
|
||||
} else if (item.child_num && index != -1) {
|
||||
this.activeList.splice(index, 1);
|
||||
}
|
||||
this.$forceUpdate();
|
||||
this.getStoreGoods();
|
||||
},
|
||||
getStoreGoods() {//表格查询
|
||||
this.$refs.goodsListTable.load({
|
||||
page: 1
|
||||
});
|
||||
},
|
||||
checkBox(list, listIndex) {
|
||||
this.checkList[this.$refs.goodsListTable.page] = {};
|
||||
this.checkList[this.$refs.goodsListTable.page].data = list;
|
||||
this.checkList[this.$refs.goodsListTable.page].index = listIndex;
|
||||
},
|
||||
tableDataChange(){
|
||||
if(this.checkList[this.$refs.goodsListTable.page])
|
||||
this.$refs.goodsListTable.defaultSelectData(this.checkList[this.$refs.goodsListTable.page].data, this.checkList[this.$refs.goodsListTable.page].index);
|
||||
},
|
||||
submit(val) {
|
||||
if (!Object.values(this.checkList).length) {
|
||||
this.$util.showToast({
|
||||
title: '请选择商品'
|
||||
});
|
||||
return false
|
||||
}
|
||||
let data = [];
|
||||
Object.values(this.checkList).forEach((item,index)=>{
|
||||
data = data.concat(item.data)
|
||||
});
|
||||
this.$emit('selectGoods', data);
|
||||
if(val !='submit'){
|
||||
this.$emit('change', false);
|
||||
}else{
|
||||
this.$refs.goodsListTable.clearCheck();
|
||||
}
|
||||
this.checkList = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.stock-dialog-wrap {
|
||||
background-color: #fff;
|
||||
border-radius: 0.05rem;
|
||||
width: 9rem;
|
||||
|
||||
.stock-dialog-head {
|
||||
padding: 0 0.15rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 0.15rem;
|
||||
height: 0.45rem;
|
||||
border-bottom: 0.01rem solid #e8eaec;
|
||||
|
||||
.iconguanbi1 {
|
||||
font-size: $uni-font-size-lg;
|
||||
}
|
||||
}
|
||||
|
||||
.stock-dialog-body {
|
||||
width: 100%;
|
||||
height: 7.3rem;
|
||||
padding: 0.1rem 0.2rem 0 0.2rem;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
|
||||
.tree {
|
||||
width: 1.8rem;
|
||||
height: 7.1rem;
|
||||
overflow-y: auto;
|
||||
border-right: 0.01rem solid #e8eaec;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
flex-grow: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
.list-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
>view {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
view.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
line-height: 0.3rem;
|
||||
min-height: 0.3rem;
|
||||
font-weight: 500;
|
||||
|
||||
&.active {
|
||||
|
||||
.icon,
|
||||
view {
|
||||
color: $primary-color !important;
|
||||
}
|
||||
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 0.2rem;
|
||||
height: 0.3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transform: rotate(-90deg);
|
||||
transition: all ease 0.5s;
|
||||
|
||||
&.active {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.level {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.item {
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
|
||||
.item2 {
|
||||
padding-left: 0.4rem;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.stock-dialog-table {
|
||||
width: 6.6rem;
|
||||
margin-left: 0.2rem;
|
||||
|
||||
.search {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
border-top: 0.01rem solid #e8eaec;
|
||||
padding: 0.1rem 0.2rem 0.1rem 0.2rem;
|
||||
height: 0.38rem;
|
||||
|
||||
.default-btn,
|
||||
.primary-btn {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.default-btn {
|
||||
|
||||
border: 0.01rem solid #e8eaec !important;
|
||||
}
|
||||
.submit{
|
||||
margin-right: 0.15rem;
|
||||
}
|
||||
.default-btn::after {
|
||||
display: none;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.common-form .common-btn-wrap {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.common-form .common-btn-wrap .screen-btn {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.common-form .common-form-item {
|
||||
margin-bottom: 0.1rem;
|
||||
}
|
||||
|
||||
/deep/ .goods-content {
|
||||
display: flex;
|
||||
|
||||
.goods-img {
|
||||
margin-right: 0.1rem;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
420
addon/cashier/source/os/components/u-charts/config-echarts.js
Executable file
420
addon/cashier/source/os/components/u-charts/config-echarts.js
Executable file
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* uCharts®
|
||||
* 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台
|
||||
* Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
|
||||
* Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
* 复制使用请保留本段注释,感谢支持开源!
|
||||
*
|
||||
* uCharts®官方网站
|
||||
* https://www.uCharts.cn
|
||||
*
|
||||
* 开源地址:
|
||||
* https://gitee.com/uCharts/uCharts
|
||||
*
|
||||
* uni-app插件市场地址:
|
||||
* http://ext.dcloud.net.cn/plugin?id=271
|
||||
*
|
||||
*/
|
||||
|
||||
// 通用配置项
|
||||
|
||||
// 主题颜色配置:如每个图表类型需要不同主题,请在对应图表类型上更改color属性
|
||||
const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
|
||||
|
||||
module.exports = {
|
||||
//demotype为自定义图表类型
|
||||
"type": ["pie", "ring", "rose", "funnel", "line", "column", "area", "radar", "gauge","candle","demotype"],
|
||||
//增加自定义图表类型,如果需要categories,请在这里加入您的图表类型例如最后的"demotype"
|
||||
"categories": ["line", "column", "area", "radar", "gauge", "candle","demotype"],
|
||||
//instance为实例变量承载属性,option为eopts承载属性,不要删除
|
||||
"instance": {},
|
||||
"option": {},
|
||||
//下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换
|
||||
"formatter":{
|
||||
"tooltipDemo1":function(res){
|
||||
let result = ''
|
||||
for (let i in res) {
|
||||
if (i == 0) {
|
||||
result += res[i].axisValueLabel + '年销售额'
|
||||
}
|
||||
let value = '--'
|
||||
if (res[i].data !== null) {
|
||||
value = res[i].data
|
||||
}
|
||||
// #ifdef H5
|
||||
result += '\n' + res[i].seriesName + ':' + value + ' 万元'
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
result += '<br/>' + res[i].marker + res[i].seriesName + ':' + value + ' 万元'
|
||||
// #endif
|
||||
}
|
||||
return result;
|
||||
},
|
||||
legendFormat:function(name){
|
||||
return "自定义图例+"+name;
|
||||
},
|
||||
yAxisFormatDemo:function (value, index) {
|
||||
return value + '元';
|
||||
},
|
||||
seriesFormatDemo:function(res){
|
||||
return res.name + '年' + res.value + '元';
|
||||
}
|
||||
},
|
||||
//这里演示了自定义您的图表类型的option,可以随意命名,之后在组件上 type="demotype" 后,组件会调用这个花括号里的option,如果组件上还存在eopts参数,会将demotype与eopts中option合并后渲染图表。
|
||||
"demotype":{
|
||||
"color": color,
|
||||
//在这里填写echarts的option即可
|
||||
|
||||
},
|
||||
//下面是自定义配置,请添加项目所需的通用配置
|
||||
"column": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'axis'
|
||||
},
|
||||
"grid": {
|
||||
"top": 30,
|
||||
"bottom": 50,
|
||||
"right": 15,
|
||||
"left": 40
|
||||
},
|
||||
"legend": {
|
||||
"bottom": 'left',
|
||||
},
|
||||
"toolbox": {
|
||||
"show": false,
|
||||
},
|
||||
"xAxis": {
|
||||
"type": 'category',
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
"boundaryGap": true,
|
||||
"data": []
|
||||
},
|
||||
"yAxis": {
|
||||
"type": 'value',
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'bar',
|
||||
"data": [],
|
||||
"barwidth": 20,
|
||||
"label": {
|
||||
"show": true,
|
||||
"color": "#666666",
|
||||
"position": 'top',
|
||||
},
|
||||
},
|
||||
},
|
||||
"line": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'axis'
|
||||
},
|
||||
"grid": {
|
||||
"top": 30,
|
||||
"bottom": 50,
|
||||
"right": 15,
|
||||
"left": 40
|
||||
},
|
||||
"legend": {
|
||||
"bottom": 'left',
|
||||
},
|
||||
"toolbox": {
|
||||
"show": false,
|
||||
},
|
||||
"xAxis": {
|
||||
"type": 'category',
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
"boundaryGap": true,
|
||||
"data": []
|
||||
},
|
||||
"yAxis": {
|
||||
"type": 'value',
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'line',
|
||||
"data": [],
|
||||
"barwidth": 20,
|
||||
"label": {
|
||||
"show": true,
|
||||
"color": "#666666",
|
||||
"position": 'top',
|
||||
},
|
||||
},
|
||||
},
|
||||
"area": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'axis'
|
||||
},
|
||||
"grid": {
|
||||
"top": 30,
|
||||
"bottom": 50,
|
||||
"right": 15,
|
||||
"left": 40
|
||||
},
|
||||
"legend": {
|
||||
"bottom": 'left',
|
||||
},
|
||||
"toolbox": {
|
||||
"show": false,
|
||||
},
|
||||
"xAxis": {
|
||||
"type": 'category',
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
"boundaryGap": true,
|
||||
"data": []
|
||||
},
|
||||
"yAxis": {
|
||||
"type": 'value',
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": '#666666'
|
||||
},
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": '#CCCCCC'
|
||||
}
|
||||
},
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'line',
|
||||
"data": [],
|
||||
"areaStyle": {},
|
||||
"label": {
|
||||
"show": true,
|
||||
"color": "#666666",
|
||||
"position": 'top',
|
||||
},
|
||||
},
|
||||
},
|
||||
"pie": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'item'
|
||||
},
|
||||
"grid": {
|
||||
"top": 40,
|
||||
"bottom": 30,
|
||||
"right": 15,
|
||||
"left": 15
|
||||
},
|
||||
"legend": {
|
||||
"bottom": 'left',
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'pie',
|
||||
"data": [],
|
||||
"radius": '50%',
|
||||
"label": {
|
||||
"show": true,
|
||||
"color": "#666666",
|
||||
"position": 'top',
|
||||
},
|
||||
},
|
||||
},
|
||||
"ring": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'item'
|
||||
},
|
||||
"grid": {
|
||||
"top": 40,
|
||||
"bottom": 30,
|
||||
"right": 15,
|
||||
"left": 15
|
||||
},
|
||||
"legend": {
|
||||
"bottom": 'left',
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'pie',
|
||||
"data": [],
|
||||
"radius": ['40%', '70%'],
|
||||
"avoidLabelOverlap": false,
|
||||
"label": {
|
||||
"show": true,
|
||||
"color": "#666666",
|
||||
"position": 'top',
|
||||
},
|
||||
"labelLine": {
|
||||
"show": true
|
||||
},
|
||||
},
|
||||
},
|
||||
"rose": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'item'
|
||||
},
|
||||
"legend": {
|
||||
"top": 'bottom'
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'pie',
|
||||
"data": [],
|
||||
"radius": "55%",
|
||||
"center": ['50%', '50%'],
|
||||
"rosetype": 'area',
|
||||
},
|
||||
},
|
||||
"funnel": {
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": 'item',
|
||||
"formatter": "{b} : {c}%"
|
||||
},
|
||||
"legend": {
|
||||
"top": 'bottom'
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'funnel',
|
||||
"left": '10%',
|
||||
"top": 60,
|
||||
"bottom": 60,
|
||||
"width": '80%',
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"minSize": '0%',
|
||||
"maxSize": '100%',
|
||||
"sort": 'descending',
|
||||
"gap": 2,
|
||||
"label": {
|
||||
"show": true,
|
||||
"position": 'inside'
|
||||
},
|
||||
"labelLine": {
|
||||
"length": 10,
|
||||
"lineStyle": {
|
||||
"width": 1,
|
||||
"type": 'solid'
|
||||
}
|
||||
},
|
||||
"itemStyle": {
|
||||
"bordercolor": '#fff',
|
||||
"borderwidth": 1
|
||||
},
|
||||
"emphasis": {
|
||||
"label": {
|
||||
"fontSize": 20
|
||||
}
|
||||
},
|
||||
"data": [],
|
||||
},
|
||||
},
|
||||
"gauge": {
|
||||
"color": color,
|
||||
"tooltip": {
|
||||
"formatter": '{a} <br/>{b} : {c}%'
|
||||
},
|
||||
"seriesTemplate": {
|
||||
"name": '业务指标',
|
||||
"type": 'gauge',
|
||||
"detail": {"formatter": '{value}%'},
|
||||
"data": [{"value": 50, "name": '完成率'}]
|
||||
},
|
||||
},
|
||||
"candle": {
|
||||
"xAxis": {
|
||||
"data": []
|
||||
},
|
||||
"yAxis": {},
|
||||
"color": color,
|
||||
"title": {
|
||||
"text": ''
|
||||
},
|
||||
"dataZoom": [{
|
||||
"type": 'inside',
|
||||
"xAxisIndex": [0, 1],
|
||||
"start": 10,
|
||||
"end": 100
|
||||
},
|
||||
{
|
||||
"show": true,
|
||||
"xAxisIndex": [0, 1],
|
||||
"type": 'slider',
|
||||
"bottom": 10,
|
||||
"start": 10,
|
||||
"end": 100
|
||||
}
|
||||
],
|
||||
"seriesTemplate": {
|
||||
"name": '',
|
||||
"type": 'k',
|
||||
"data": [],
|
||||
},
|
||||
}
|
||||
}
|
||||
433
addon/cashier/source/os/components/u-charts/config-ucharts.js
Executable file
433
addon/cashier/source/os/components/u-charts/config-ucharts.js
Executable file
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* uCharts®
|
||||
* 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台
|
||||
* Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
|
||||
* Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
* 复制使用请保留本段注释,感谢支持开源!
|
||||
*
|
||||
* uCharts®官方网站
|
||||
* https://www.uCharts.cn
|
||||
*
|
||||
* 开源地址:
|
||||
* https://gitee.com/uCharts/uCharts
|
||||
*
|
||||
* uni-app插件市场地址:
|
||||
* http://ext.dcloud.net.cn/plugin?id=271
|
||||
*
|
||||
*/
|
||||
|
||||
// 主题颜色配置:如每个图表类型需要不同主题,请在对应图表类型上更改color属性
|
||||
const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
|
||||
|
||||
module.exports = {
|
||||
//demotype为自定义图表类型
|
||||
"type":["pie","ring","rose","word","funnel","map","arcbar","line","column","area","radar","gauge","candle","mix","demotype"],
|
||||
"range":["饼状图","圆环图","玫瑰图","词云图","漏斗图","地图","圆弧进度条","折线图","柱状图","区域图","雷达图","仪表盘","K线图","混合图","自定义类型"],
|
||||
//增加自定义图表类型,如果需要categories,请在这里加入您的图表类型例如最后的"demotype"
|
||||
"categories":["line","column","area","radar","gauge","candle","mix","demotype"],
|
||||
//instance为实例变量承载属性,option为eopts承载属性,不要删除
|
||||
"instance":{},
|
||||
"option":{},
|
||||
//下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换
|
||||
"formatter":{
|
||||
"yAxisDemo1":function(val){return val+'元'},
|
||||
"yAxisDemo2":function(val){return val.toFixed(2)},
|
||||
"seriesDemo1":function(val){
|
||||
return val+'元'
|
||||
},
|
||||
"tooltipDemo1":function(item, category, index, opts){
|
||||
if(index==0){
|
||||
return '随便用'+item.data+'年'
|
||||
}else{
|
||||
return '其他我没改'+item.data+'天'
|
||||
}
|
||||
},
|
||||
"pieDemo":function(val, index, series){
|
||||
if(index !== undefined){
|
||||
return series[index].name+':'+series[index].data+'元'
|
||||
}
|
||||
},
|
||||
},
|
||||
//这里演示了自定义您的图表类型的option,可以随意命名,之后在组件上 type="demotype" 后,组件会调用这个花括号里的option,如果组件上还存在opts参数,会将demotype与opts中option合并后渲染图表。
|
||||
"demotype":{
|
||||
//我这里把曲线图当做了自定义图表类型,您可以根据需要随意指定类型或配置
|
||||
"type": "line",
|
||||
"color": color,
|
||||
"padding": [15,10,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
"gridType": "dash",
|
||||
"dashLength": 2,
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"line": {
|
||||
"type": "curve",
|
||||
"width": 2
|
||||
},
|
||||
}
|
||||
},
|
||||
//下面是自定义配置,请添加项目所需的通用配置
|
||||
"pie":{
|
||||
"type": "pie",
|
||||
"color": color,
|
||||
"padding": [5,5,5,5],
|
||||
"extra": {
|
||||
"pie": {
|
||||
"activeOpacity": 0.5,
|
||||
"activeRadius": 10,
|
||||
"offsetAngle": 0,
|
||||
"labelWidth": 15,
|
||||
"border": true,
|
||||
"borderWidth": 3,
|
||||
"borderColor": "#FFFFFF"
|
||||
},
|
||||
}
|
||||
},
|
||||
"ring":{
|
||||
"type": "ring",
|
||||
"color": color,
|
||||
"padding": [5,5,5,5],
|
||||
"rotate": false,
|
||||
"dataLabel": true,
|
||||
"legend": {
|
||||
"show": true,
|
||||
"position": "right",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"title": {
|
||||
"name": "收益率",
|
||||
"fontSize": 15,
|
||||
"color": "#666666"
|
||||
},
|
||||
"subtitle": {
|
||||
"name": "70%",
|
||||
"fontSize": 25,
|
||||
"color": "#7cb5ec"
|
||||
},
|
||||
"extra": {
|
||||
"ring": {
|
||||
"ringWidth":30,
|
||||
"activeOpacity": 0.5,
|
||||
"activeRadius": 10,
|
||||
"offsetAngle": 0,
|
||||
"labelWidth": 15,
|
||||
"border": true,
|
||||
"borderWidth": 3,
|
||||
"borderColor": "#FFFFFF"
|
||||
},
|
||||
},
|
||||
},
|
||||
"rose":{
|
||||
"type": "rose",
|
||||
"color": color,
|
||||
"padding": [5,5,5,5],
|
||||
"legend": {
|
||||
"show": true,
|
||||
"position": "left",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"extra": {
|
||||
"rose": {
|
||||
"type": "area",
|
||||
"minRadius": 50,
|
||||
"activeOpacity": 0.5,
|
||||
"activeRadius": 10,
|
||||
"offsetAngle": 0,
|
||||
"labelWidth": 15,
|
||||
"border": false,
|
||||
"borderWidth": 2,
|
||||
"borderColor": "#FFFFFF"
|
||||
},
|
||||
}
|
||||
},
|
||||
"word":{
|
||||
"type": "word",
|
||||
"color": color,
|
||||
"extra": {
|
||||
"word": {
|
||||
"type": "normal",
|
||||
"autoColors": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"funnel":{
|
||||
"type": "funnel",
|
||||
"color": color,
|
||||
"padding": [15,15,0,15],
|
||||
"extra": {
|
||||
"funnel": {
|
||||
"activeOpacity": 0.3,
|
||||
"activeWidth": 10,
|
||||
"border": true,
|
||||
"borderWidth": 2,
|
||||
"borderColor": "#FFFFFF",
|
||||
"fillOpacity": 1,
|
||||
"labelAlign": "right"
|
||||
},
|
||||
}
|
||||
},
|
||||
"map":{
|
||||
"type": "map",
|
||||
"color": color,
|
||||
"padding": [0,0,0,0],
|
||||
"dataLabel": true,
|
||||
"extra": {
|
||||
"map": {
|
||||
"border": true,
|
||||
"borderWidth": 1,
|
||||
"borderColor": "#666666",
|
||||
"fillOpacity": 0.6,
|
||||
"activeBorderColor": "#F04864",
|
||||
"activeFillColor": "#FACC14",
|
||||
"activeFillOpacity": 1
|
||||
},
|
||||
}
|
||||
},
|
||||
"arcbar":{
|
||||
"type": "arcbar",
|
||||
"color": color,
|
||||
"title": {
|
||||
"name": "百分比",
|
||||
"fontSize": 25,
|
||||
"color": "#00FF00"
|
||||
},
|
||||
"subtitle": {
|
||||
"name": "默认标题",
|
||||
"fontSize": 15,
|
||||
"color": "#666666"
|
||||
},
|
||||
"extra": {
|
||||
"arcbar": {
|
||||
"type": "default",
|
||||
"width": 12,
|
||||
"backgroundColor": "#E9E9E9",
|
||||
"startAngle": 0.75,
|
||||
"endAngle": 0.25,
|
||||
"gap": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"line":{
|
||||
"type": "line",
|
||||
"color": color,
|
||||
"padding": [15,10,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
"gridType": "dash",
|
||||
"dashLength": 2,
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"line": {
|
||||
"type": "straight",
|
||||
"width": 2
|
||||
},
|
||||
}
|
||||
},
|
||||
"column":{
|
||||
"type": "column",
|
||||
"color": color,
|
||||
"padding": [15,15,0,5],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"column": {
|
||||
"type": "group",
|
||||
"width": 30,
|
||||
"meterBorde": 1,
|
||||
"meterFillColor": "#FFFFFF",
|
||||
"activeBgColor": "#000000",
|
||||
"activeBgOpacity": 0.08
|
||||
},
|
||||
}
|
||||
},
|
||||
"area":{
|
||||
"type": "area",
|
||||
"color": color,
|
||||
"padding": [15,15,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
"gridType": "dash",
|
||||
"dashLength": 2,
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"area": {
|
||||
"type": "straight",
|
||||
"opacity": 0.2,
|
||||
"addLine": true,
|
||||
"width": 2,
|
||||
"gradient": false
|
||||
},
|
||||
}
|
||||
},
|
||||
"radar":{
|
||||
"type": "radar",
|
||||
"color": color,
|
||||
"padding": [5,5,5,5],
|
||||
"legend": {
|
||||
"show": true,
|
||||
"position": "right",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"extra": {
|
||||
"radar": {
|
||||
"gridType": "radar",
|
||||
"gridColor": "#CCCCCC",
|
||||
"gridCount": 3,
|
||||
"opacity": 0.2,
|
||||
"labelColor": "#666666",
|
||||
"max": 200
|
||||
},
|
||||
}
|
||||
},
|
||||
"gauge":{
|
||||
"type": "gauge",
|
||||
"color": color,
|
||||
"title": {
|
||||
"name": "66Km/H",
|
||||
"fontSize": 25,
|
||||
"color": "#2fc25b",
|
||||
"offsetY": 50
|
||||
},
|
||||
"subtitle": {
|
||||
"name": "实时速度",
|
||||
"fontSize": 15,
|
||||
"color": "#1890ff",
|
||||
"offsetY": -50
|
||||
},
|
||||
"extra": {
|
||||
"gauge": {
|
||||
"type": "default",
|
||||
"width": 30,
|
||||
"labelColor": "#666666",
|
||||
"startAngle": 0.75,
|
||||
"endAngle": 0.25,
|
||||
"startNumber": 0,
|
||||
"endNumber": 100,
|
||||
"labelFormat": "",
|
||||
"splitLine": {
|
||||
"fixRadius": 0,
|
||||
"splitNumber": 10,
|
||||
"width": 30,
|
||||
"color": "#FFFFFF",
|
||||
"childNumber": 5,
|
||||
"childWidth": 12
|
||||
},
|
||||
"pointer": {
|
||||
"width": 24,
|
||||
"color": "auto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"candle":{
|
||||
"type": "candle",
|
||||
"color": color,
|
||||
"padding": [15,15,0,15],
|
||||
"enableScroll": true,
|
||||
"enableMarkLine": true,
|
||||
"dataLabel": false,
|
||||
"xAxis": {
|
||||
"labelCount": 4,
|
||||
"itemCount": 40,
|
||||
"disableGrid": true,
|
||||
"gridColor": "#CCCCCC",
|
||||
"gridType": "solid",
|
||||
"dashLength": 4,
|
||||
"scrollShow": true,
|
||||
"scrollAlign": "left",
|
||||
"scrollColor": "#A6A6A6",
|
||||
"scrollBackgroundColor": "#EFEBEF"
|
||||
},
|
||||
"yAxis": {
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"candle": {
|
||||
"color": {
|
||||
"upLine": "#f04864",
|
||||
"upFill": "#f04864",
|
||||
"downLine": "#2fc25b",
|
||||
"downFill": "#2fc25b"
|
||||
},
|
||||
"average": {
|
||||
"show": true,
|
||||
"name": ["MA5","MA10","MA30"],
|
||||
"day": [5,10,20],
|
||||
"color": ["#1890ff","#2fc25b","#facc14"]
|
||||
}
|
||||
},
|
||||
"markLine": {
|
||||
"type": "dash",
|
||||
"dashLength": 5,
|
||||
"data": [
|
||||
{
|
||||
"value": 2150,
|
||||
"lineColor": "#f04864",
|
||||
"showLabel": true
|
||||
},
|
||||
{
|
||||
"value": 2350,
|
||||
"lineColor": "#f04864",
|
||||
"showLabel": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"mix":{
|
||||
"type": "mix",
|
||||
"color": color,
|
||||
"padding": [15,15,0,15],
|
||||
"xAxis": {
|
||||
"disableGrid": true,
|
||||
},
|
||||
"yAxis": {
|
||||
"disabled": false,
|
||||
"disableGrid": false,
|
||||
"splitNumber": 5,
|
||||
"gridType": "dash",
|
||||
"dashLength": 4,
|
||||
"gridColor": "#CCCCCC",
|
||||
"padding": 10,
|
||||
"showTitle": true,
|
||||
"data": []
|
||||
},
|
||||
"legend": {
|
||||
},
|
||||
"extra": {
|
||||
"mix": {
|
||||
"column": {
|
||||
"width": 20
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"point":{
|
||||
"type": "point",
|
||||
"color":color,
|
||||
"padding":[15,15,0,15],
|
||||
},
|
||||
"bubble":{
|
||||
"type": "bubble",
|
||||
"color":color,
|
||||
"padding":[15,15,0,15],
|
||||
}
|
||||
}
|
||||
201
addon/cashier/source/os/components/u-charts/license.md
Executable file
201
addon/cashier/source/os/components/u-charts/license.md
Executable file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
12
addon/cashier/source/os/components/u-charts/readme.md
Executable file
12
addon/cashier/source/os/components/u-charts/readme.md
Executable file
@@ -0,0 +1,12 @@
|
||||
# uCharts JSSDK说明
|
||||
1、如不使用uCharts组件,可直接引用u-charts.js,打包编译后会`自动压缩`,压缩后体积约为`98kb`。
|
||||
2、如果100kb的体积仍需压缩,请手动删除u-charts.js内您不需要的图表类型,如k线图candle。
|
||||
3、config-ucharts.js为uCharts组件的用户配置文件,升级前请`自行备份config-ucharts.js`文件,以免被强制覆盖。
|
||||
3、config-echarts.js为ECharts组件的用户配置文件,升级前请`自行备份config-echarts.js`文件,以免被强制覆盖。
|
||||
|
||||
# v1.0转v2.0注意事项
|
||||
1、opts.colors变更为opts.color
|
||||
2、ring圆环图的扩展配置由extra.pie变更为extra.ring
|
||||
3、混合图借用的扩展配置由extra.column变更为extra.mix.column
|
||||
4、全部涉及到format的格式化属性变更为formatter
|
||||
5、不需要再传canvasId及$this参数,如果通过uChats获取context,可能会导致this实例混乱,导致小程序开发者工具报错。如果不使用qiun-data-charts官方组件,需要在new uCharts()实例化之前,自行获取canvas的上下文context(ctx),并传入new中的context(opts.context)。为了能跨更多的端,给您带来的不便敬请谅解。
|
||||
5910
addon/cashier/source/os/components/u-charts/u-charts-v2.0.0.js
Executable file
5910
addon/cashier/source/os/components/u-charts/u-charts-v2.0.0.js
Executable file
File diff suppressed because it is too large
Load Diff
808
addon/cashier/source/os/components/uni-data-checkbox/uni-data-checkbox.vue
Executable file
808
addon/cashier/source/os/components/uni-data-checkbox/uni-data-checkbox.vue
Executable file
@@ -0,0 +1,808 @@
|
||||
<template>
|
||||
<view class="uni-data-checklist" :style="{'margin-top':isTop+'px'}">
|
||||
<template >
|
||||
<checkbox-group v-if="multiple" class="checklist-group" :class="{'is-list':mode==='list' || wrap}" @change="chagne">
|
||||
<label class="checklist-box" :class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']"
|
||||
:style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index">
|
||||
<checkbox class="hidden" hidden :disabled="disabled || !!item.disabled" :value="item[map.value]+''" :checked="item.selected" />
|
||||
<view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" class="checkbox__inner" :style="item.styleIcon">
|
||||
<view class="checkbox__inner-icon"></view>
|
||||
</view>
|
||||
<view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}">
|
||||
<text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text>
|
||||
<view v-if="mode === 'list' && icon === 'right'" class="checkobx__list" :style="item.styleBackgroud"></view>
|
||||
</view>
|
||||
</label>
|
||||
</checkbox-group>
|
||||
<radio-group v-else class="checklist-group" :class="{'is-list':mode==='list','is-wrap':wrap}" @change="chagne">
|
||||
<label class="checklist-box" :class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']"
|
||||
:style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index">
|
||||
<radio class="hidden" hidden :disabled="disabled || item.disabled" :value="item[map.value]+''" :checked="item.selected" />
|
||||
<view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" class="radio__inner" :style="item.styleBackgroud">
|
||||
<view class="radio__inner-icon" :style="item.styleIcon"></view>
|
||||
</view>
|
||||
<view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}">
|
||||
<text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text>
|
||||
<view v-if="mode === 'list' && icon === 'right'" :style="item.styleRightIcon" class="checkobx__list"></view>
|
||||
</view>
|
||||
</label>
|
||||
</radio-group>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* DataChecklist 数据选择器
|
||||
* @description 通过数据渲染 checkbox 和 radio
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
|
||||
* @property {String} mode = [default| list | button | tag] 显示模式
|
||||
* @value default 默认横排模式
|
||||
* @value list 列表模式
|
||||
* @value button 按钮模式
|
||||
* @value tag 标签模式
|
||||
* @property {Boolean} multiple = [true|false] 是否多选
|
||||
* @property {Array|String|Number} value 默认值
|
||||
* @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}]
|
||||
* @property {Number|String} min 最小选择个数 ,multiple为true时生效
|
||||
* @property {Number|String} max 最大选择个数 ,multiple为true时生效
|
||||
* @property {Boolean} wrap 是否换行显示
|
||||
* @property {String} icon = [left|right] list 列表模式下icon显示位置
|
||||
* @property {Boolean} selectedColor 选中颜色
|
||||
* @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效
|
||||
* @property {Boolean} selectedTextColor 选中文本颜色,如不填写则自动显示
|
||||
* @property {Object} map 字段映射, 默认 map={text:'text',value:'value'}
|
||||
* @value left 左侧显示
|
||||
* @value right 右侧显示
|
||||
* @event {Function} change 选中发生变化触发
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'uniDataChecklist',
|
||||
mixins: [uniCloud.mixinDatacom || {}],
|
||||
emits:['input','update:modelValue','change'],
|
||||
props: {
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
value: {
|
||||
type: [Array, String, Number],
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
// TODO vue3
|
||||
modelValue: {
|
||||
type: [Array, String, Number],
|
||||
default() {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
localdata: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
min: {
|
||||
type: [Number, String],
|
||||
default: ''
|
||||
},
|
||||
max: {
|
||||
type: [Number, String],
|
||||
default: ''
|
||||
},
|
||||
wrap: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'left'
|
||||
},
|
||||
selectedColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
selectedTextColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
emptyText:{
|
||||
type: String,
|
||||
default: '暂无数据'
|
||||
},
|
||||
disabled:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
map:{
|
||||
type: Object,
|
||||
default(){
|
||||
return {
|
||||
text:'text',
|
||||
value:'value'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
localdata: {
|
||||
handler(newVal) {
|
||||
this.range = newVal;
|
||||
this.dataList = this.getDataList(this.getSelectedValue(newVal));
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
mixinDatacomResData(newVal) {
|
||||
this.range = newVal;
|
||||
this.dataList = this.getDataList(this.getSelectedValue(newVal));
|
||||
},
|
||||
value(newVal) {
|
||||
this.dataList = this.getDataList(newVal);
|
||||
// fix by mehaotian is_reset 在 uni-forms 中定义
|
||||
if(!this.is_reset){
|
||||
this.is_reset = false;
|
||||
this.formItem && this.formItem.setValue(newVal);
|
||||
}
|
||||
},
|
||||
modelValue(newVal) {
|
||||
this.dataList = this.getDataList(newVal);
|
||||
if(!this.is_reset){
|
||||
this.is_reset = false;
|
||||
this.formItem && this.formItem.setValue(newVal);
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dataList: [],
|
||||
range: [],
|
||||
contentText: {
|
||||
contentdown: '查看更多',
|
||||
contentrefresh: '加载中',
|
||||
contentnomore: '没有更多'
|
||||
},
|
||||
isLocal:true,
|
||||
styles: {
|
||||
selectedColor: '$primary-color',
|
||||
selectedTextColor: '#666',
|
||||
},
|
||||
isTop:0
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
dataValue(){
|
||||
if(this.value === '')return this.modelValue;
|
||||
if(this.modelValue === '') return this.value;
|
||||
return this.value;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.form = this.getForm('uniForms');
|
||||
this.formItem = this.getForm('uniFormsItem');
|
||||
// this.formItem && this.formItem.setValue(this.value)
|
||||
|
||||
if (this.formItem) {
|
||||
this.isTop = 6;
|
||||
if (this.formItem.name) {
|
||||
// 如果存在name添加默认值,否则formData 中不存在这个字段不校验
|
||||
if(!this.is_reset){
|
||||
this.is_reset = false;
|
||||
this.formItem.setValue(this.dataValue);
|
||||
}
|
||||
this.rename = this.formItem.name;
|
||||
this.form.inputChildrens.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.localdata && this.localdata.length !== 0) {
|
||||
this.isLocal = true;
|
||||
this.range = this.localdata;
|
||||
this.dataList = this.getDataList(this.getSelectedValue(this.range));
|
||||
} else {
|
||||
if (this.collection) {
|
||||
this.isLocal = false;
|
||||
this.loadData();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
this.mixinDatacomGet().then(res=>{
|
||||
this.mixinDatacomResData = res.result.data;
|
||||
if(this.mixinDatacomResData.length === 0){
|
||||
this.isLocal = false;
|
||||
this.mixinDatacomErrorMessage = this.emptyText;
|
||||
}else{
|
||||
this.isLocal = true;
|
||||
}
|
||||
}).catch(err=>{
|
||||
this.mixinDatacomErrorMessage = err.message;
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getForm(name = 'uniForms') {
|
||||
let parent = this.$parent;
|
||||
let parentName = parent.$options.name;
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent;
|
||||
if (!parent) return false;
|
||||
parentName = parent.$options.name;
|
||||
}
|
||||
return parent;
|
||||
},
|
||||
chagne(e) {
|
||||
const values = e.detail.value;
|
||||
|
||||
let detail = {
|
||||
value: [],
|
||||
data: []
|
||||
};
|
||||
|
||||
if (this.multiple) {
|
||||
this.range.forEach(item => {
|
||||
if (values.includes(item[this.map.value] + '')) {
|
||||
detail.value.push(item[this.map.value]);
|
||||
detail.data.push(item);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const range = this.range.find(item => (item[this.map.value] + '') === values);
|
||||
if (range) {
|
||||
detail = {
|
||||
value: range[this.map.value],
|
||||
data: range
|
||||
}
|
||||
}
|
||||
}
|
||||
this.formItem && this.formItem.setValue(detail.value);
|
||||
// TODO 兼容 vue2
|
||||
this.$emit('input', detail.value);
|
||||
// // TOTO 兼容 vue3
|
||||
this.$emit('update:modelValue', detail.value);
|
||||
this.$emit('change', {
|
||||
detail
|
||||
});
|
||||
if (this.multiple) {
|
||||
// 如果 v-model 没有绑定 ,则走内部逻辑
|
||||
// if (this.value.length === 0) {
|
||||
this.dataList = this.getDataList(detail.value, true)
|
||||
// }
|
||||
} else {
|
||||
this.dataList = this.getDataList(detail.value)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取渲染的新数组
|
||||
* @param {Object} value 选中内容
|
||||
*/
|
||||
getDataList(value) {
|
||||
// 解除引用关系,破坏原引用关系,避免污染源数据
|
||||
let dataList = JSON.parse(JSON.stringify(this.range));
|
||||
let list = [];
|
||||
if (this.multiple) {
|
||||
if (!Array.isArray(value)) {
|
||||
value = []
|
||||
}
|
||||
}
|
||||
dataList.forEach((item, index) => {
|
||||
item.disabled = item.disable || item.disabled || false;
|
||||
if (this.multiple) {
|
||||
if (value.length > 0) {
|
||||
let have = value.find(val => val === item[this.map.value]);
|
||||
item.selected = have !== undefined;
|
||||
} else {
|
||||
item.selected = false;
|
||||
}
|
||||
} else {
|
||||
item.selected = value === item[this.map.value];
|
||||
}
|
||||
|
||||
list.push(item)
|
||||
});
|
||||
return this.setRange(list)
|
||||
},
|
||||
/**
|
||||
* 处理最大最小值
|
||||
* @param {Object} list
|
||||
*/
|
||||
setRange(list) {
|
||||
let selectList = list.filter(item => item.selected);
|
||||
let min = Number(this.min) || 0;
|
||||
let max = Number(this.max) || '';
|
||||
list.forEach((item, index) => {
|
||||
if (this.multiple) {
|
||||
if (selectList.length <= min) {
|
||||
let have = selectList.find(val => val[this.map.value] === item[this.map.value]);
|
||||
if (have !== undefined) {
|
||||
item.disabled = true
|
||||
}
|
||||
}
|
||||
|
||||
if (selectList.length >= max && max !== '') {
|
||||
let have = selectList.find(val => val[this.map.value] === item[this.map.value]);
|
||||
if (have === undefined) {
|
||||
item.disabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setStyles(item, index);
|
||||
list[index] = item
|
||||
});
|
||||
return list
|
||||
},
|
||||
/**
|
||||
* 设置 class
|
||||
* @param {Object} item
|
||||
* @param {Object} index
|
||||
*/
|
||||
setStyles(item, index) {
|
||||
// 设置自定义样式
|
||||
item.styleBackgroud = this.setStyleBackgroud(item);
|
||||
item.styleIcon = this.setStyleIcon(item);
|
||||
item.styleIconText = this.setStyleIconText(item);
|
||||
item.styleRightIcon = this.setStyleRightIcon(item);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取选中值
|
||||
* @param {Object} range
|
||||
*/
|
||||
getSelectedValue(range) {
|
||||
if (!this.multiple) return this.dataValue;
|
||||
let selectedArr = [];
|
||||
range.forEach((item) => {
|
||||
if (item.selected) {
|
||||
selectedArr.push(item[this.map.value])
|
||||
}
|
||||
});
|
||||
return this.dataValue && this.dataValue.length > 0 ? this.dataValue : selectedArr
|
||||
},
|
||||
|
||||
/**
|
||||
* 设置背景样式
|
||||
*/
|
||||
setStyleBackgroud(item) {
|
||||
let styles = {}
|
||||
let selectedColor = this.selectedColor?this.selectedColor:''
|
||||
if (this.mode !== 'list') {
|
||||
styles['border-color'] = item.selected?selectedColor:''
|
||||
}
|
||||
if (this.mode === 'tag') {
|
||||
styles['background-color'] = item.selected? selectedColor:''
|
||||
}
|
||||
let classles = ''
|
||||
for (let i in styles) {
|
||||
classles += `${i}:${styles[i]};`
|
||||
}
|
||||
return classles
|
||||
},
|
||||
setStyleIcon(item) {
|
||||
let styles = {}
|
||||
let classles = ''
|
||||
let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
|
||||
styles['background-color'] = item.selected?selectedColor:'#fff'
|
||||
styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
|
||||
|
||||
if(!item.selected && item.disabled){
|
||||
styles['background-color'] = '#F2F6FC'
|
||||
styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
|
||||
}
|
||||
|
||||
for (let i in styles) {
|
||||
classles += `${i}:${styles[i]};`
|
||||
}
|
||||
return classles
|
||||
},
|
||||
setStyleIconText(item) {
|
||||
let styles = {}
|
||||
let classles = ''
|
||||
let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
|
||||
if (this.mode === 'tag') {
|
||||
styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:'#fff'):'#666'
|
||||
} else {
|
||||
styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:selectedColor):'#666'
|
||||
}
|
||||
if(!item.selected && item.disabled){
|
||||
styles.color = '#999'
|
||||
}
|
||||
|
||||
for (let i in styles) {
|
||||
classles += `${i}:${styles[i]};`
|
||||
}
|
||||
return classles
|
||||
},
|
||||
setStyleRightIcon(item) {
|
||||
let styles = {}
|
||||
let classles = ''
|
||||
if (this.mode === 'list') {
|
||||
styles['border-color'] = item.selected?this.styles.selectedColor:'#DCDFE6'
|
||||
}
|
||||
for (let i in styles) {
|
||||
classles += `${i}:${styles[i]};`
|
||||
}
|
||||
|
||||
return classles
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$checked-color: $primary-color !important;
|
||||
$border-color: #DCDFE6;
|
||||
$disable:0.4;
|
||||
|
||||
@mixin flex {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-data-loading {
|
||||
@include flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 0.36rem;
|
||||
padding-left: 0.1rem;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.uni-data-checklist {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
flex: 1;
|
||||
// 多选样式
|
||||
.checklist-group {
|
||||
@include flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&.is-list {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.checklist-box {
|
||||
@include flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
margin: 0.05rem 0;
|
||||
margin-right: 0.25rem;
|
||||
|
||||
.hidden {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
// 文字样式
|
||||
.checklist-content {
|
||||
@include flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.checklist-text {
|
||||
font-size: 0.14rem;
|
||||
color: #666;
|
||||
margin-left: 0.05rem;
|
||||
line-height: 0.14rem;
|
||||
}
|
||||
|
||||
.checkobx__list {
|
||||
border-right-width: 0.01rem;
|
||||
border-right-color: $primary-color;
|
||||
border-right-style: solid;
|
||||
border-bottom-width:0.01rem;
|
||||
border-bottom-color: $primary-color;
|
||||
border-bottom-style: solid;
|
||||
height: 0.12rem;
|
||||
width: 0.06rem;
|
||||
left: -0.05rem;
|
||||
transform-origin: center;
|
||||
transform: rotate(45deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 多选样式
|
||||
.checkbox__inner {
|
||||
/* #ifndef APP-NVUE */
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
position: relative;
|
||||
width: 0.16rem;
|
||||
height: 0.16rem;
|
||||
border: 0.01rem solid $border-color;
|
||||
border-radius: 0.04rem;
|
||||
background-color: #fff;
|
||||
z-index: 1;
|
||||
.checkbox__inner-icon {
|
||||
position: absolute;
|
||||
/* #ifdef APP-NVUE */
|
||||
top: 0.02rem;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
top: 0.01rem;
|
||||
/* #endif */
|
||||
left: 0.05rem;
|
||||
height: 0.08rem;
|
||||
width: 0.04rem;
|
||||
border-right-width: 0.01rem;
|
||||
border-right-color: #fff;
|
||||
border-right-style: solid;
|
||||
border-bottom-width:0.01rem ;
|
||||
border-bottom-color: #fff;
|
||||
border-bottom-style: solid;
|
||||
opacity: 0;
|
||||
transform-origin: center;
|
||||
transform: rotate(40deg);
|
||||
}
|
||||
}
|
||||
|
||||
// 单选样式
|
||||
.radio__inner {
|
||||
@include flex;
|
||||
/* #ifndef APP-NVUE */
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
width: 0.16rem;
|
||||
height: 0.16rem;
|
||||
border: 0.01rem solid $border-color;
|
||||
border-radius: 0.16rem;
|
||||
background-color: #fff;
|
||||
z-index: 1;
|
||||
|
||||
.radio__inner-icon {
|
||||
width: 0.08rem;
|
||||
height: 0.08rem;
|
||||
border-radius: 0.1rem;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 默认样式
|
||||
&.is--default {
|
||||
|
||||
// 禁用
|
||||
&.is-disable {
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
.checkbox__inner {
|
||||
background-color: #F2F6FC;
|
||||
border-color: $border-color;
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.radio__inner {
|
||||
background-color: #F2F6FC;
|
||||
border-color: $border-color;
|
||||
}
|
||||
.checklist-text {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
// 选中
|
||||
&.is-checked {
|
||||
.checkbox__inner {
|
||||
border-color: $checked-color;
|
||||
background-color: $checked-color;
|
||||
|
||||
.checkbox__inner-icon {
|
||||
opacity: 1;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
.radio__inner {
|
||||
border-color: $checked-color;
|
||||
.radio__inner-icon {
|
||||
opacity: 1;
|
||||
background-color: $checked-color;
|
||||
}
|
||||
}
|
||||
.checklist-text {
|
||||
color: $checked-color;
|
||||
}
|
||||
// 选中禁用
|
||||
&.is-disable {
|
||||
.checkbox__inner {
|
||||
opacity: $disable;
|
||||
}
|
||||
|
||||
.checklist-text {
|
||||
opacity: $disable;
|
||||
}
|
||||
.radio__inner {
|
||||
opacity: $disable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 按钮样式
|
||||
&.is--button {
|
||||
margin-right: 0.1rem;
|
||||
padding: 0.05rem 0.1rem;
|
||||
border: 0.01rem $border-color solid;
|
||||
border-radius: 0.03rem;
|
||||
transition: border-color 0.2s;
|
||||
|
||||
// 禁用
|
||||
&.is-disable {
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
border: 0.01rem #eee solid;
|
||||
opacity: $disable;
|
||||
.checkbox__inner {
|
||||
background-color: #F2F6FC;
|
||||
border-color: $border-color;
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
}
|
||||
.radio__inner {
|
||||
background-color: #F2F6FC;
|
||||
border-color: $border-color;
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
}
|
||||
.checklist-text {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-checked {
|
||||
border-color: $checked-color;
|
||||
.checkbox__inner {
|
||||
border-color: $checked-color;
|
||||
background-color: $checked-color;
|
||||
.checkbox__inner-icon {
|
||||
opacity: 1;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
|
||||
.radio__inner {
|
||||
border-color: $checked-color;
|
||||
|
||||
.radio__inner-icon {
|
||||
opacity: 1;
|
||||
background-color: $checked-color;
|
||||
}
|
||||
}
|
||||
|
||||
.checklist-text {
|
||||
color: $checked-color;
|
||||
}
|
||||
|
||||
// 选中禁用
|
||||
&.is-disable {
|
||||
opacity: $disable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 标签样式
|
||||
&.is--tag {
|
||||
margin-right: 0.1rem;
|
||||
padding: 0.05rem 0.1rem;
|
||||
border: 0.01rem $border-color solid;
|
||||
border-radius: 0.3rem;
|
||||
background-color: #f5f5f5;
|
||||
|
||||
.checklist-text {
|
||||
margin: 0;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
// 禁用
|
||||
&.is-disable {
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
opacity: $disable;
|
||||
}
|
||||
|
||||
&.is-checked {
|
||||
background-color: $checked-color;
|
||||
border-color: $checked-color;
|
||||
|
||||
.checklist-text {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 列表样式
|
||||
&.is--list {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
padding: 0.1rem 0.15rem;
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
|
||||
&.is-list-border {
|
||||
border-top: 0.01rem #eee solid;
|
||||
}
|
||||
|
||||
// 禁用
|
||||
&.is-disable {
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
.checkbox__inner {
|
||||
background-color: #F2F6FC;
|
||||
border-color: $border-color;
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
}
|
||||
.checklist-text {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-checked {
|
||||
.checkbox__inner {
|
||||
border-color: $checked-color;
|
||||
background-color: $checked-color;
|
||||
|
||||
.checkbox__inner-icon {
|
||||
opacity: 1;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
.radio__inner {
|
||||
.radio__inner-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.checklist-text {
|
||||
color: $checked-color;
|
||||
}
|
||||
|
||||
.checklist-content {
|
||||
.checkobx__list {
|
||||
opacity: 1;
|
||||
border-color: $checked-color;
|
||||
}
|
||||
}
|
||||
|
||||
// 选中禁用
|
||||
&.is-disable {
|
||||
.checkbox__inner {
|
||||
opacity: $disable;
|
||||
}
|
||||
|
||||
.checklist-text {
|
||||
opacity: $disable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user