初始上传

This commit is contained in:
2026-04-04 17:27:12 +08:00
parent 4d80d28eb4
commit b7e11774ee
11191 changed files with 1588469 additions and 0 deletions

View 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));
}
}
};

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

View 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>