You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1213 lines
38 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="member-card-create">
<!-- 顶部标题和统计 -->
<div class="page-header">
<h2>办理会员卡</h2>
<div class="statistics">
<el-tag type="success">今日办理{{ todayCount }} </el-tag>
</div>
</div>
<div>
</div>
<el-card shadow="never" class="main-card">
<!-- 步骤条 -->
<el-steps :active="activeStep" finish-status="success" class="steps">
<el-step title="选择会员" description="选择或创建会员"></el-step>
<el-step title="选择卡类型" description="选择会员卡类型"></el-step>
<el-step title="填写信息" description="填写办理信息"></el-step>
</el-steps>
<!-- 步骤1选择会员 -->
<div v-if="activeStep === 0" class="step-content">
<el-row :gutter="20">
<el-col :span=12>
<div class="section-title">
<h3>搜索会员</h3>
<el-button type="primary" size="small" @click="handleAddStudent">
</el-button>
</div>
<el-input
v-model="searchKeyword"
placeholder="请输入会员手机号"
clearable
@keyup.enter="searchMember"
class="search-input"
>
<el-button slot="append" icon="el-icon-search" @click="searchMember"></el-button>
</el-input>
<div v-if="memberList.length > 0" class="member-list">
<el-radio-group v-model="selectedMemberId" @change="handleMemberSelect">
<div v-for="member in memberList" :key="member.studentId" class="member-item">
<el-radio :label="member.studentId" class="member-radio">
<div class="member-info">
<div class="member-name">{{ member.studentName }}</div>
<div class="member-phone">{{ member.phone }}</div>
<div class="member-phone">{{ member.age }}岁</div>
<div class="member-tags">
{{sexFormat(member)}}
<el-tag size="mini" type="info">生日{{ member.birthDay || '未设置生日' }}</el-tag>
</div>
</div>
</el-radio>
</div>
</el-radio-group>
</div>
<div v-else-if="searched" class="empty-state">
<el-empty description="未找到相关会员"></el-empty>
</div>
</el-col>
<el-col :span=12>
<div class="selected-member" v-if="selectedMember">
<div class="section-title">
<h3>已选会员信息</h3>
</div>
<el-descriptions :column="1" border>
<el-descriptions-item label="会员编号">{{ selectedMember.studentId || '-' }}</el-descriptions-item>
<el-descriptions-item label="姓名">{{ selectedMember.studentName }}</el-descriptions-item>
<el-descriptions-item label="手机号">{{ selectedMember.phone }}</el-descriptions-item>
<el-descriptions-item label="性别">
{{sexFormat(selectedMember)}}
</el-descriptions-item>
<el-descriptions-item label="生日">{{ selectedMember.birthDay || '-' }}</el-descriptions-item>
<el-descriptions-item label="注册时间">{{ selectedMember.inTime || '-' }}</el-descriptions-item>
</el-descriptions>
<div v-if="memberCards.length > 0" class="current-cards">
<h4>名下会员卡</h4>
<el-table :data="memberCards" size="small">
<el-table-column prop="cardNo" label="卡号"></el-table-column>
<el-table-column prop="cardTypeName" label="类型"></el-table-column>
<el-table-column prop="chargeType" label="扣费方式">
<template slot-scope="scope">
{{ scope.row.chargeType=='count'?'按次数':scope.row.chargeType=='total_fee'?'按储值':'按周期' }}
{{scope.row.chargeType=='count'?'(余 '+scope.row.remainingCount+' 次)':''}}
{{scope.row.chargeType=='total_fee'?'(余 '+scope.row.remainingTotalFee+' ¥)':''}}
{{scope.row.chargeType=='days'?'(余 '+scope.row.remainingDays+' 天)':''}}
</template>
</el-table-column>
<el-table-column prop="status" label="状态">
<template slot-scope="scope">
<el-tag :type="getStatusTagType(scope.row.status)" size="mini">
{{ scope.row.statusDesc }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="expiryDate" label="到期时间"></el-table-column>
</el-table>
</div>
</div>
<div v-else class="placeholder">
<el-empty description="请选择会员"></el-empty>
</div>
</el-col>
</el-row>
<div class="step-actions">
<el-button type="primary" :disabled="!selectedMemberId" @click="nextStep">
下一步:选择卡类型
</el-button>
</div>
</div>
<!-- 步骤2选择卡类型 -->
<div v-if="activeStep === 1" class="step-content">
<member-card-Type-table ref="memberCardtype" />
<div class="step-actions">
<el-button @click="prevStep">上一步</el-button>
<el-button
type="primary"
@click="nextStepFor2"
>
下一步:填写信息
</el-button>
</div>
</div>
<!-- 步骤3填写信息 -->
<div v-if="activeStep === 2" class="step-content">
<el-form ref="form" :model="formData" :rules="formRules" label-width="120px">
<el-row :gutter="10" style="background-color: #e7e9ea;">
<el-col span="12">
<el-form-item label="会员信息">
<div class="member-info-display">
<div style="font-weight: bold;font-size: 16px">{{ selectedMember.studentName }}</div>
<div class="sub-info">{{ selectedMember.phone }}</div>
</div>
</el-form-item>
</el-col>
<el-col span="12" >
<el-form-item label="卡类名称">
<div v-if="chargeType=='days'" class="card-type-display" >
<div style="color: #00afff;font-weight: bold;font-size: 16px">{{selectedCardType.cardName }}</div>
<div class="sub-info" >会员卡扣费方式 :按周期</div>
<div class="sub-info" >总天数/有效期 {{ selectedCardType.days }}天</div>
<div class="sub-info" v-if="selectedCardType.days">
根据卡类型,默认有效期为 {{ selectedCardType.days }} 天</div>
</div>
<div v-if="chargeType=='count'" class="card-type-display">
<div style="color: #00afff;font-weight: bold;font-size: 16px">{{selectedCardType.cardName }}</div>
<div class="sub-info" >会员卡扣费方式 :按次数</div>
<div class="sub-info" >默认课程总次数 {{ selectedCardType.count }}次</div>
<div class="sub-info" v-if="selectedCardType.days">
根据卡类型,默认有效期为 {{ selectedCardType.days }} 天</div>
</div>
<div v-if="chargeType=='total_fee'" class="card-type-display">
<div style="color: #00afff;font-weight: bold;font-size: 16px">{{ selectedCardType.cardName }}</div>
<div class="sub-info" >会员卡扣费方式 :按储值</div>
<div class="sub-info" >默认储值金额:{{ selectedCardType.totalFee }} ¥</div>
<div class="sub-info" v-if="selectedCardType.days">
根据卡类型,默认有效期为 {{ selectedCardType.days }} 天</div>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top: 10px">
<el-col :span=12>
<el-form-item label="经办校区" prop="handleDepartId">
<el-select
v-model="formData.handleDepartId"
placeholder="请选择经办校区"
clearable
size="small"
filterable
default-first-option
>
<el-option
v-for="item in campusOptions"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="销售员工" prop="saleStaffId">
<user-select v-model="formData.saleStaffId" style="width: 180px" />
</el-form-item >
<el-form-item label="佣金方案" prop="commissionPlansId">
<commission-select v-model="formData.commissionPlansId" />
</el-form-item>
<el-form-item label="收款账户" prop="accountId">
<el-select
v-model="formData.accountId"
placeholder="请选择收款账户"
clearable
size="small"
filterable
default-first-option
>
<el-option
v-for="item in receiptAccountOptions"
:key="item.accountId"
:label="item.accountName"
:value="item.accountId"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span=12>
<el-form-item label="实付金额" prop="price">
<el-input-number
v-model="formData.price"
:min="0"
:step="100"
:precision="2"
placeholder="请输入购买价格"
></el-input-number>
</el-form-item>
<div v-if="chargeType=='days'">
<el-form-item label="开卡日期:" prop="haveActivationDate" class="align-left">
<el-radio-group v-model="formData.haveActivationDate" @change="changeHaveActivationDate" >
<el-radio label="1">立即开卡</el-radio>
<el-radio label="2">首次预约开卡</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="激活日期" v-if="formData.haveActivationDate=='1'" prop="activationDate">
<el-date-picker
v-model="formData.activationDate"
type="date"
placeholder="选择激活日期"
value-format="yyyy-MM-dd"
:picker-options="activationDateOptions"
@change="calculateExpiryDate"
>
</el-date-picker>
</el-form-item>
<el-form-item label="到期日期" v-if="formData.haveActivationDate=='1'" prop="expiryDate">
<el-date-picker
v-model="formData.expiryDate"
type="date"
placeholder="选择到期日期"
value-format="yyyy-MM-dd"
:picker-options="expiryDateOptions"
@change="calculateDays"
>
</el-date-picker>
<span class="form-tip" > 共{{ formData.totalDays }}天截止至当天23:59:59</span>
</el-form-item>
<el-form-item label="储值天数" v-if="formData.haveActivationDate=='2'" prop="totalDays" >
<el-input-number
v-model="formData.totalDays"
:min="0"
:step="100"
:precision="0"
placeholder="请输入储值天数"
>
</el-input-number>
<span class="form-tip" > * 该卡从会员首次约课时算第一天,再往后共{{ formData.totalDays }}天</span>
</el-form-item>
</div >
<div v-else>
<el-form-item label="卡有效期:" prop="haveExpiryDate" class="align-left">
<el-radio-group v-model="formData.haveExpiryDate" @change="changeHaveExpiryDate">
<el-radio label="1">不限期,用完失效</el-radio>
<el-radio label="2">设置有效期</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="到期日期" v-if="formData.haveExpiryDate=='2'" prop="expiryDate">
<el-date-picker
v-model="formData.expiryDate"
type="date"
placeholder="选择到期日期"
value-format="yyyy-MM-dd"
:picker-options="expiryDateOptions"
>
</el-date-picker>
<span class="form-tip" > 截止至当天23:59:59</span>
</el-form-item>
</div>
<el-form-item v-if="chargeType=='total_fee'" label="储值金额" prop="totalFee">
<el-input-number
v-model="formData.totalFee"
:min="0"
:step="100"
:precision="2"
placeholder="请输入购买价格"
>
</el-input-number>
<span class="form-tip"> * 举例若实付金额1000送200则储值金额应填写1200</span>
</el-form-item>
<el-form-item v-if="chargeType=='count'" label="充值课时" prop="totalCount">
<el-input-number
v-model="formData.totalCount"
:min="0"
:step="1"
:precision="1"
placeholder="请输入充值次数"
>
</el-input-number>
</el-form-item>
<el-form-item label="备注" prop="notes">
<el-input
v-model="formData.notes"
type="textarea"
:rows="3"
placeholder="请输入备注信息"
></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="summary-card">
<h3>办理信息汇总</h3>
<el-descriptions :column="2" border>
<el-descriptions-item label="会员">{{ selectedMember.studentName }}</el-descriptions-item>
<el-descriptions-item label="手机号">{{ selectedMember.phone }}</el-descriptions-item>
<el-descriptions-item label="卡类名称">{{ selectedCardType.cardName }}</el-descriptions-item>
<el-descriptions-item v-if="chargeType=='total_fee'" label="储值金额">{{ formData.totalFee }} &nbsp;&nbsp;¥</el-descriptions-item>
<el-descriptions-item v-if="chargeType=='count'" label="充值课时">{{ formData.totalCount }} 次</el-descriptions-item>
<el-descriptions-item v-if="chargeType=='days'" label="有效天数">{{ formData.totalDays }} 天</el-descriptions-item>
<el-descriptions-item label="实付金额">{{ formData.price }}&nbsp;&nbsp;¥</el-descriptions-item>
<el-descriptions-item label="收款账户">
{{ getPaymentMethodName(formData.accountId) }}
</el-descriptions-item>
<el-descriptions-item label="激活日期">
{{ formData.activationDate || '暂不激活' }}
</el-descriptions-item>
<el-descriptions-item label="到期日期">
{{ formData.expiryDate }}
</el-descriptions-item>
</el-descriptions>
</div>
<div class="step-actions">
<el-button @click="prevStep">上一步</el-button>
<el-button
type="primary"
@click="validateAndNext"
:loading="validating"
>
确认办理
</el-button>
</div>
</div>
</el-card>
<change-student ref="changeStudent" @success="handleMemberSelect" />
</div>
</template>
<script>
import {select as cardTypeSelect} from '@/api/school/sc/memberCardType/index'
import {listStudent} from '@/api/school/sc/student/index'
import { select as receiptSelect} from '@/api/school/system/receipt'
import {selectDictLabel} from "@/utils/commonUtils";
import { campusList } from '@/api/school/system/dept'
import memberCardTypeTable from '@/components/sc/memberCardTypes/memberCardTypeTable.vue'
import changeStudent from '@/components/sc/student/changeStudent'
import memberCardApi from '@/api/school/sc/memberCard/index'
import commissionSelect from '@/components/sc/commission/commissionSelect'
import userSelect from '@/components/system/user/userSelect'
export default {
name: 'MemberCardCreate',
components: {
memberCardTypeTable,
changeStudent,
commissionSelect,
userSelect
},
data() {
return {
activeStep: 0,
// 统计信息
todayCount: 0,
monthCount: 0,
// 会员相关
searchKeyword: '',
memberList: [],
selectedMemberId: null,
selectedMember: null,
memberCards: [],
searched: false,
sexOptions:[],
// 卡类型相关
cardTypes: [],
selectedCardTypeId: null,
selectedCardType: null,
chargeType: null,
// 经办校区
campusOptions: [],
// 表单数据
formData: {
handleDepartId:'',
saleStaffId:'',
commissionPlansId:'',
accountId: '',//收款账户
haveActivationDate:'1',//时间卡 是否激活
haveExpiryDate:'1',//储值or次数卡 是否设置有效期
activationDate: '',//激活时间
expiryDate: '',//过期时间
price: 0,
totalFee: 0,
totalCount: 0,
totalDays: 0,
notes: '',
orderId:''
},
autoGenerateCardNo: true,
// 支付相关
receiptAccountOptions:[],
paymentType: 'WECHAT',
paying: false,
saving: false,
validating: false,
// 对话框控制
showCreateMemberDialog: false,
showCardTypeDetailDialog: false,
// 表单验证规则
formRules: {
accountId: [
{ required: true, message: '请选择收款账户', trigger: 'change' }
],
handleDepartId: [
{ required: true, message: '请选择经办校区', trigger: 'change' }
],
saleStaffId: [
{ required: true, message: '请选择销售员工', trigger: 'change' }
],
commissionPlansId: [
{ required: true, message: '请选择佣金方案', trigger: 'change' }
],
price: [
{ required: true, message: '请输入购买价格', trigger: 'blur' },
{ type: 'number', min: 0, message: '价格不能小于0', trigger: 'blur' }
],
activationDate: [
{ validator: (rule, value, callback) => {
// 如果 haveActivationDate 为 1activationDate 不能为空
if (this.formData.haveActivationDate === '1' && !value) {
callback(new Error('请选择激活日期'));
} else {
callback(); // 验证通过
}
},
trigger: 'change' // 日期选择器用 change 触发
},
],
expiryDate: [
{ validator: (rule, value, callback) => {
// 条件1haveActivationDate 为 1 时,有效期不能为空
// 条件2haveExpiryDate 为 2 时,有效期不能为空
const needExpiryDate = this.formData.haveActivationDate === '1' || this.formData.haveExpiryDate === '2';
if (needExpiryDate && !value) {
callback(new Error('请选择有效期'));
} else {
callback(); // 验证通过
}
},
trigger: 'blur'// 日期选择器用 change 触发
},
],
days: [
{
validator: (rule, value, callback) => {
// 如果 haveActivationDate 为 2days 不能为空且不能为 0
if (this.formData.haveActivationDate === '2') {
if (!value || value === 0) {
callback(new Error('请输入有效天数'));
} else if (value < 0) {
callback(new Error('有效天数不能小于0'));
} else {
callback();
}
} else {
callback(); // 其他情况不验证
}
},
trigger: ['blur', 'change']// 输入框用 blur 触发
},
],
},
// 日期选择器选项
activationDateOptions: {
disabledDate(time) {
return time.getTime() < Date.now() - 8.64e7 // 不能选择过去的时间
}
},
expiryDateOptions: {
disabledDate(time) {
return time.getTime() < Date.now() - 8.64e7 // 不能选择过去的时间
}
}
}
},
created() {
this.loadCardTypes()
this.loadStatistics()
this.loadReceiptAccount()
this.getDictListByDictType('sys_user_sex').then(response => {
this.sexOptions = response.data
})
campusList().then(response => {
this.campusOptions = response.data
if (this.campusOptions.length === 1) {
this.formData.handleDepartId = this.campusOptions[0].id
}
})
},
methods: {
loadReceiptAccount(){
receiptSelect().then(response => {
this.receiptAccountOptions = response.data
})
},
// 加载统计信息
async loadStatistics() {
try {
memberCardApi.getTodayCardCount().then(response => {
this.todayCount = response.data || 0
})
} catch (error) {
console.error('加载统计信息失败:', error)
}
},
// 加载卡类型
async loadCardTypes() {
try {
cardTypeSelect({}).then(response => {
this.cardTypes = response.data || []
})
} catch (error) {
this.$message.error('加载卡类型失败')
console.error('加载卡类型失败:', error)
}
},
// 搜索会员
async searchMember() {
if (!this.searchKeyword.trim()) {
this.$message.warning('请输入搜索关键词')
return
}
try {
listStudent({phone:this.searchKeyword}).then(response => {
this.memberList = response.data.rows || []
this.searched = true
if (this.memberList.length === 0) {
this.$message.info('未找到相关会员')
}
})
} catch (error) {
this.$message.error('搜索会员失败')
console.error('搜索会员失败:', error)
}
},
// 性别字典翻译
sexFormat(row, column) {
return selectDictLabel(this.sexOptions, row.sex)
},
// 选择会员
async handleMemberSelect(studentId) {
const member = this.memberList.find(m => m.studentId === studentId)
if (member) {
this.selectedMember = member
await this.loadMemberCards(studentId)
}
},
// 加载会员的会员卡
async loadMemberCards(memberId) {
try {
const response = await memberCardApi.getMemberCards(memberId)
this.memberCards = response.data || []
} catch (error) {
console.error('加载会员卡失败:', error)
}
},
// 新建学员信息
handleAddStudent() {
this.$refs.changeStudent.handleAdd()
},
// 获取收款账户名称
getPaymentMethodName(method) {
let item=this.receiptAccountOptions.find(item => item.accountId == method);
let methodName=item==null?'':item.accountName;
return methodName;
},
// 获取状态标签类型
getStatusTagType(status) {
const typeMap = {
'ACTIVE': 'success',
'INACTIVE': 'info',
'EXPIRED': 'warning',
'SUSPENDED': 'danger',
'DEPLETED': 'danger'
}
return typeMap[status] || 'info'
},
changeHaveActivationDate(){
this.formData.activationDate=''
this.formData.expiryDate=''
this.formData.totalDays=0
},
changeHaveExpiryDate(){
if (this.formData.haveExpiryDate=='2'){
this.calculateExpiryDate()
return;
}
this.formData.expiryDate='' ;
},
// 计算到期日期
calculateExpiryDate( ) {
if (!this.selectedCardType || !this.selectedCardType.days) {
return '未设置'
}
const activationDate = this.formData.activationDate
? new Date(this.formData.activationDate)
: new Date()
const expiryDate = new Date(activationDate)
expiryDate.setDate(expiryDate.getDate() + this.selectedCardType.days)
this.formData.expiryDate=expiryDate.toISOString().split('T')[0];
this.calculateDays()
},
calculateDays(){
if (!this.formData.activationDate || !this.formData.expiryDate){
return;
}
const activationDate =new Date(this.formData.activationDate);
const expiryDate =new Date(this.formData.expiryDate);
const timeDiff = Math.abs(activationDate.getTime() - expiryDate.getTime());
const dayDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24));
this.formData.totalDays=dayDiff;
},
// 验证并进入下一步
async validateAndNext() {
this.$refs.form.validate(async (valid) => {
if (valid) {
this.validating = true
try {
// 这里可以添加一些业务验证
await this.handlePayment()
} catch (error) {
console.error('验证失败:', error)
} finally {
this.validating = false
}
} else {
this.$message.warning('请填写完整信息')
}
})
},
// 下一步
nextStep() {
if (this.activeStep < 2) {
this.activeStep++
}
},
// 上一步
prevStep() {
if (this.activeStep > 0) {
this.activeStep--
}
},
cleanForm(){
this.formData.haveActivationDate='1';
this.formData.haveExpiryDate='1';
this.formData.activationDate='';
this.formData.expiryDate='';
this.formData.price=0;
this.formData.totalFee=0;
this.formData.totalCount=0;
this.formData.totalDays=0;
},
nextStepFor2(){
if (this.$refs.memberCardtype.queryParams.cardType==undefined || this.$refs.memberCardtype.queryParams.cardType==''){
this.msgError('请选择收费模式!')
return ;
}
this.cleanForm()
this.formData.activationDate=new Date().toISOString().split('T')[0]
// if (this.$refs.memberCardtype.queryParams.cardType=='total_fee'){
// this.chargeType=this.$refs.memberCardtype.queryParams.cardType;
// this.selectedCardTypeId=this.$refs.memberCardtype.chooseCardTypeId[0];
// this.selectedCardType=this.$refs.memberCardtype.chooseCardTypes[0];
//
// if (this.selectedCardType ==null){
// this.selectedCardType={
// cardName:'储值卡',
// totalFee:0
// }
// }
// this.activeStep++
// return ;
// }
if (this.$refs.memberCardtype.chooseCardTypeId.length>1 || this.$refs.memberCardtype.chooseCardTypeId.length==0){
this.msgError('请选择1项确认选择数量')
return ;
}
this.chargeType=this.$refs.memberCardtype.queryParams.cardType;
this.selectedCardTypeId=this.$refs.memberCardtype.chooseCardTypeId[0];
this.selectedCardType=this.$refs.memberCardtype.chooseCardTypes[0];
this.calculateExpiryDate()
this.activeStep++
},
// 处理订单信息
async handlePayment() {
if (!this.selectedMemberId ) {
this.$message.error('请完成前面的步骤')
return
}
// if ( !this.selectedCardTypeId && this.chargeType!='total_fee') {
if ( !this.selectedCardTypeId) {
this.$message.error('请完成前面的步骤')
return
}
this.paying = true
try {
// 构建办理会员卡的请求数据
const requestData = {
memberId: this.selectedMemberId,
cardTypeId: this.selectedCardTypeId,
handleDepartId:this.formData.handleDepartId,
saleStaffId:this.formData.saleStaffId,
commissionPlansId:this.formData.commissionPlansId,
haveActivationDate:this.formData.haveActivationDate,//时间卡 是否激活
haveExpiryDate:this.formData.haveExpiryDate,//储值or次数卡 是否设置有效期
activationDate: this.formData.activationDate || null,
expiryDate: this.formData.expiryDate || null,
price: this.formData.price,
accountId: this.formData.accountId,
orderNo: this.formData.orderNo,
totalFee: this.formData.totalFee || 0,
totalCount: this.formData.totalCount || 0,
totalDays: this.formData.totalDays || 0,
notes: this.formData.notes,
chargeType:this.chargeType
}
const response = await memberCardApi.createMemberCard(requestData)
if (response.respCode === '0000') {
this.$message.success('会员卡办理成功!')
// 重置表单
this.resetForm()
// 跳转到会员卡详情页
const cardId = response.data.id
// this.$router.push({
// name: 'MemberCardDetail',
// params: { id: cardId }
// })
} else {
this.$message.error(response.respMsg || '办理失败')
}
} catch (error) {
console.error('办理会员卡失败:', error)
this.$message.error('办理失败:' + (error.message || '网络错误'))
} finally {
this.paying = false
}
},
// 保存为草稿
async saveAsDraft() {
this.saving = true
try {
// TODO: 实现保存草稿功能
this.$message.success('已保存为草稿')
} catch (error) {
console.error('保存草稿失败:', error)
this.$message.error('保存草稿失败')
} finally {
this.saving = false
}
},
// 查看卡类型详情
showCardTypeDetail(cardType) {
this.selectedCardType = cardType
this.showCardTypeDetailDialog = true
},
// 处理会员创建成功
handleMemberCreateSuccess(newMember) {
this.showCreateMemberDialog = false
this.memberList.unshift(newMember)
this.selectedMemberId = newMember.id
this.selectedMember = newMember
this.searchKeyword = ''
this.$message.success('会员创建成功')
},
// 处理创建会员对话框关闭
handleCreateMemberClose() {
if (this.$refs.memberCreateForm) {
this.$refs.memberCreateForm.resetForm()
}
},
// 重置表单
resetForm() {
this.activeStep = 0
this.selectedMemberId = null
this.selectedMember = null
this.memberCards = []
this.selectedCardTypeId = null
this.selectedCardType = null
this.formData = {
handleDepartId:'',
saleStaffId:'',
commissionPlansId:'',
accountId: '',//收款账户
haveActivationDate:'1',//时间卡 是否激活
haveExpiryDate:'1',//储值or次数卡 是否设置有效期
activationDate: '',//激活时间
expiryDate: '',//过期时间
price: 0,
totalFee: 0,
totalCount: 0,
totalDays: 0,
notes: '',
orderNo: ''
}
this.autoGenerateCardNo = true
this.paymentType = 'WECHAT'
if (this.$refs.form) {
this.$refs.form.resetFields()
}
// 重新加载卡类型
this.loadCardTypes()
this.loadStatistics()
}
}
}
</script>
<style scoped lang="scss">
.member-card-create {
padding: 20px;
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
h2 {
margin: 0;
color: #333;
}
.statistics {
display: flex;
gap: 10px;
}
}
.main-card {
margin-top: 20px;
.steps {
margin-bottom: 40px;
}
.step-content {
padding: 20px;
.section-title {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
h3 {
margin: 0;
color: #333;
}
}
.search-input {
margin-bottom: 20px;
}
.member-list {
max-height: 400px;
overflow-y: auto;
.member-item {
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ebeef5;
border-radius: 4px;
transition: all 0.3s;
&:hover {
border-color: #409eff;
background-color: #f5f7fa;
}
.member-radio {
width: 100%;
}
.member-info {
display: flex;
flex-direction: column;
margin-left: 10px;
.member-name {
font-weight: bold;
font-size: 14px;
color: #333;
}
.member-phone {
font-size: 12px;
color: #666;
margin: 4px 0;
}
.member-tags {
display: flex;
gap: 5px;
}
}
}
}
.empty-state {
text-align: center;
padding: 40px 0;
}
.selected-member {
.current-cards {
margin-top: 20px;
h4 {
margin: 20px 0 10px;
color: #333;
}
}
}
.placeholder {
text-align: center;
padding: 40px 0;
color: #999;
}
.card-type-list {
.card-type-item {
border: 2px solid #ebeef5;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
cursor: pointer;
transition: all 0.3s;
height: 100%;
&:hover {
border-color: #409eff;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
&.selected {
border-color: #67c23a;
background-color: #f0f9eb;
}
.card-type-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
h3 {
margin: 0;
color: #333;
}
}
.card-type-price {
margin-bottom: 15px;
.price {
font-size: 24px;
font-weight: bold;
color: #f56c6c;
}
.original-price {
font-size: 14px;
color: #999;
text-decoration: line-through;
margin-left: 10px;
}
}
.card-type-details {
margin-bottom: 15px;
.detail-item {
display: flex;
align-items: center;
margin-bottom: 8px;
font-size: 13px;
color: #666;
i {
margin-right: 8px;
color: #409eff;
}
}
}
.card-type-benefits {
h4 {
margin: 0 0 8px;
font-size: 14px;
color: #333;
}
p {
margin: 0;
font-size: 13px;
color: #666;
line-height: 1.5;
}
}
.card-type-footer {
margin-top: 15px;
text-align: center;
}
}
}
.selected-card-type {
margin: 20px 0;
.selected-alert {
.selected-info {
display: flex;
align-items: center;
justify-content: space-between;
.price {
font-weight: bold;
color: #f56c6c;
}
}
}
}
.member-info-display,
.card-type-display {
padding: 8px 0;
.sub-info {
font-size: 12px;
color: #666;
margin-top: 4px;
}
}
.form-tip {
font-size: 12px;
color: #999;
margin-top: 4px;
}
.summary-card {
margin-top: 30px;
padding: 20px;
background-color: #f5f7fa;
border-radius: 4px;
h3 {
margin: 0 0 15px;
color: #333;
}
}
.payment-options {
margin: 30px 0;
h3 {
margin: 0 0 15px;
color: #333;
}
.payment-buttons {
display: flex;
gap: 10px;
.icon-wechat,
.icon-alipay {
margin-right: 5px;
font-size: 16px;
}
}
}
.step-actions {
margin-top: 30px;
text-align: center;
}
.final-actions {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 30px;
}
}
}
}
//
@media (max-width: 1200px) {
.member-card-create {
.card-type-list {
.card-type-item {
.card-type-details {
.detail-item {
flex-direction: column;
align-items: flex-start;
}
}
}
}
}
}
@media (max-width: 768px) {
.member-card-create {
.page-header {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.step-content {
.section-title {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
}
}
}
</style>