初始化项目

This commit is contained in:
2026-09-01 22:15:50 +08:00
commit b5a26a8848
11217 changed files with 1710987 additions and 0 deletions
+210
View File
@@ -0,0 +1,210 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<a-spin :spinning="isLoading">
<a-form :form="form" @submit="handleSubmit">
<a-form-item label="是否开启满额包邮" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['is_open', { rules: [{ required: true }] }]">
<a-radio :value="1">开启</a-radio>
<a-radio :value="0">关闭</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="单笔订单满" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input-number
:min="0"
:precision="2"
v-decorator="['money', { rules: [{ required: true, message: '请输入包邮的订单额度' }] }]"
/>
<span class="ml-10">元包邮</span>
<div class="form-item-help">
<small>如设置0为全场包邮</small>
</div>
</a-form-item>
<a-form-item label="不参与包邮的商品" :labelCol="labelCol" :wrapperCol="wrapperCol">
<SelectGoods :defaultList="excludedGoodsList" v-decorator="['excludedGoodsIds']" />
</a-form-item>
<a-form-item label="不参与包邮的地区" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-button @click="handleAreasModal">选择地区</a-button>
<p class="content">
<span v-for="(province, pidx) in excludedRegions.selectedText" :key="pidx">
<span>{{ province.name }}</span>
<template v-if="province.citys.length">
<span>[</span>
<span
class="city-name"
v-for="(city, cidx) in province.citys"
:key="cidx"
>{{ city.name }}{{ province.citys.length > cidx + 1 ? '、': '' }}</span>
<span>]</span>
</template>
<span class="mr-5"></span>
</span>
</p>
</a-form-item>
<a-form-item label="满额包邮说明" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-textarea
:autoSize="{ minRows: 4 }"
v-decorator="['describe', { rules: [{ required: true, message: '请输入满额包邮说明' }] }]"
/>
</a-form-item>
<a-form-item :wrapper-col="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" html-type="submit">提交</a-button>
</a-form-item>
</a-form>
<AreasModal ref="AreasModal" @handleSubmit="handleAreaSubmit" />
</a-spin>
</a-card>
</template>
<script>
import pick from 'lodash.pick'
import * as Api from '@/api/setting/store'
import * as GoodsApi from '@/api/goods'
import { SelectGoods } from '@/components'
import { AreasModal } from '@/components/Modal'
export default {
components: {
SelectGoods,
AreasModal
},
data () {
return {
// 当前设置项的key
key: 'full_free',
// 标签布局属性
labelCol: { span: 4 },
// 输入框布局属性
wrapperCol: { span: 12 },
// loading状态
isLoading: false,
// 当前表单元素
form: this.$form.createForm(this),
// 当前记录详情
record: {},
// 不参与包邮的地区
excludedRegions: {
cityIds: [],
selectedText: []
},
// 不参与包邮的商品列表
excludedGoodsList: []
}
},
// 初始化数据
async created () {
// 获取当前详情记录
await this.getDetail()
// 获取不参与包邮的商品列表
await this.getExcludedGoodsList()
},
methods: {
// 获取当前详情记录
async getDetail () {
this.isLoading = true
await Api.detail(this.key)
.then(result => {
// 当前记录
this.record = result.data.values
// 设置默认值
this.setFieldsValue()
})
.finally(result => {
this.isLoading = false
})
},
// 获取不参与包邮的商品列表
async getExcludedGoodsList () {
const { record: { excludedGoodsIds } } = this
if (excludedGoodsIds.length > 0) {
this.isLoading = true
await GoodsApi.listByIds(excludedGoodsIds)
.then(result => {
this.excludedGoodsList = result.data.list
})
.finally(result => {
this.isLoading = false
})
}
},
/**
* 设置默认值
*/
setFieldsValue () {
const { record, $nextTick, form: { setFieldsValue } } = this
$nextTick(() => {
this.excludedRegions = record.excludedRegions
setFieldsValue(pick(record, ['is_open', 'money', 'describe']))
})
},
// 显示选择地区对话框
handleAreasModal () {
this.$refs.AreasModal.handle({}, this.excludedRegions.cityIds)
},
// 选择地区后的回调
handleAreaSubmit (result) {
this.excludedRegions = {
cityIds: result.selectedCityIds,
selectedText: result.selectedText
}
},
/**
* 确认按钮
*/
handleSubmit (e) {
e.preventDefault()
// 表单验证
const { form: { validateFields }, excludedRegions } = this
validateFields((errors, values) => {
// 提交到后端api
if (!errors) {
values.excludedRegions = excludedRegions
this.onFormSubmit(values)
}
})
},
// 提交到后端api
onFormSubmit (values) {
this.isLoading = true
Api.update(this.key, { form: values })
.then((result) => {
// 显示提示信息
this.$message.success(result.message, 1.5)
})
.finally((result) => {
this.isLoading = false
})
}
}
}
</script>
<style lang="less" scoped>
.ant-form-item {
.ant-form-item {
margin-bottom: 0;
}
}
/deep/.ant-form-item-control {
padding-left: 10px;
.ant-form-item-control {
padding-left: 0;
}
}
.content {
color: #505050;
line-height: 1.6;
.city-name {
font-size: 12.5px;
color: #7b7b7b;
}
}
</style>
@@ -0,0 +1,210 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<a-spin :spinning="isLoading">
<a-form :form="form" @submit="handleSubmit">
<a-form-item label="优惠券名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
placeholder="请输入优惠券名称"
v-decorator="['name', { rules: [{ required: true, min: 2, message: '请输入至少2个字符' }] }]"
/>
</a-form-item>
<a-form-item label="优惠券类型" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-decorator="['coupon_type', { initialValue: 10, rules: [{ required: true }] }]"
>
<a-radio :value="10">满减券</a-radio>
<a-radio :value="20">折扣券</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item
v-if="form.getFieldValue('coupon_type') == 10"
label="减免金额"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input-number
:min="0.01"
:precision="2"
v-decorator="['reduce_price', { rules: [{ required: true, message: '请输入减免金额' }] }]"
/>
<span class="ml-5">元</span>
</a-form-item>
<a-form-item
v-if="form.getFieldValue('coupon_type') == 20"
label="折扣率"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input-number
:min="0"
:max="9.9"
:precision="1"
v-decorator="['discount', { initialValue: 9.9, rules: [{ required: true, message: '请输入折扣率' }] }]"
/>
<span class="ml-5">%</span>
<p class="form-item-help">
<small>折扣率范围 0-9.9,8代表打8折,0代表不折扣</small>
</p>
</a-form-item>
<a-form-item label="最低消费金额" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input-number
:min="1"
:precision="2"
v-decorator="['min_price', { rules: [{ required: true, message: '请输入最低消费金额' }] }]"
/>
<span class="ml-5">元</span>
</a-form-item>
<a-form-item label="到期类型" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-decorator="['expire_type', { initialValue: 10, rules: [{ required: true }] }]"
>
<a-radio :value="10">领取后生效</a-radio>
<a-radio :value="20">固定时间</a-radio>
</a-radio-group>
<a-form-item v-show="form.getFieldValue('expire_type') == 10" class="expire_type-10">
<InputNumberGroup
addonBefore="有效期"
addonAfter="天"
:inputProps="{ min: 1, precision: 0 }"
v-decorator="['expire_day', { initialValue: 7, rules: [{ required: true, message: '请输入有效期天数' }] }]"
/>
</a-form-item>
<a-form-item v-show="form.getFieldValue('expire_type') == 20" class="expire_type-20">
<a-range-picker
format="YYYY-MM-DD"
v-decorator="['betweenTime', { initialValue: defaultDate, rules: [{ required: true, message: '请选择有效期范围' }] }]"
/>
</a-form-item>
</a-form-item>
<a-form-item label="券适用范围" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-decorator="['apply_range', { initialValue: 10, rules: [{ required: true }] }]"
>
<a-radio :value="10">全场通用</a-radio>
<a-radio :value="20">指定商品</a-radio>
</a-radio-group>
<a-form-item v-if="form.getFieldValue('apply_range') == 20">
<SelectGoods
:defaultList="containGoodsList"
v-decorator="['apply_range_config.applyGoodsIds', { initialValue: [], rules: [{ required: true, message: '请选择指定的商品' }] }]"
/>
</a-form-item>
</a-form-item>
<a-form-item label="发放总数量" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input-number
:min="-1"
:precision="0"
v-decorator="['total_num', { initialValue: -1, rules: [{ required: true, message: '请输入发放总数量' }] }]"
/>
<span class="ml-5">张</span>
<p class="form-item-help">
<small>发放的优惠券总数量,-1为不限制</small>
</p>
</a-form-item>
<a-form-item label="显示状态" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['status', { initialValue: 1, rules: [{ required: true }] }]">
<a-radio :value="1">显示</a-radio>
<a-radio :value="0">隐藏</a-radio>
</a-radio-group>
<p class="form-item-help">
<small>如果设为隐藏将不会展示在用户端页面</small>
</p>
</a-form-item>
<a-form-item label="优惠券描述" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-textarea :autoSize="{ minRows: 4 }" v-decorator="['describe']" />
</a-form-item>
<a-form-item label="排序" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="数字越小越靠前">
<a-input-number
:min="0"
v-decorator="['sort', {initialValue: 100, rules:[{required: true, message: '请输入排序值'}]}]"
/>
</a-form-item>
<a-form-item class="mt-20" :wrapper-col="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" html-type="submit" :loading="isBtnLoading">提交</a-button>
</a-form-item>
</a-form>
</a-spin>
</a-card>
</template>
<script>
import moment from 'moment'
import * as Api from '@/api/market/coupon'
import { InputNumberGroup, SelectGoods } from '@/components'
import { ApplyRangeEnum, CouponTypeEnum, ExpireTypeEnum } from '@/common/enum/coupon'
export default {
components: {
SelectGoods,
InputNumberGroup
},
data () {
return {
// 枚举类
ApplyRangeEnum,
CouponTypeEnum,
ExpireTypeEnum,
// 正在加载
isLoading: false,
isBtnLoading: false,
// 标签布局属性
labelCol: { span: 3 },
// 输入框布局属性
wrapperCol: { span: 10 },
// 当前表单元素
form: this.$form.createForm(this),
// 默认日期范围
defaultDate: [moment(), moment()],
// 适用范围:指定的商品
containGoodsList: []
}
},
created () {
this.$nextTick(() => {
this.$forceUpdate()
})
},
methods: {
// 确认按钮
handleSubmit (e) {
e.preventDefault()
// 表单验证
const { form: { validateFields }, onFormSubmit } = this
validateFields((errors, values) => {
!errors && onFormSubmit(values)
})
},
// 提交到后端api
onFormSubmit (values) {
this.isLoading = true
this.isBtnLoading = true
Api.add({ form: values })
.then(result => {
// 显示提示信息
this.$message.success(result.message, 1.5)
// 跳转到列表页
setTimeout(() => {
this.$router.push('./index')
}, 1500)
})
.catch(() => {
this.isBtnLoading = false
})
.finally(result => {
this.isLoading = false
})
}
}
}
</script>
<style lang="less" scoped>
.ant-form-item {
.ant-form-item {
margin-bottom: 0;
}
}
</style>
+215
View File
@@ -0,0 +1,215 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<a-alert message="注:优惠券只能抵扣商品金额,最多优惠到0.01元,不能抵扣运费" banner />
<div class="table-operator">
<a-row>
<a-col :span="6">
<a-button
v-if="$auth('/market/coupon/create')"
type="primary"
icon="plus"
@click="handleAdd"
>新增</a-button>
</a-col>
<a-col :span="8" :offset="10">
<a-input-search
style="max-width: 300px; min-width: 150px;float: right;"
v-model="queryParam.search"
placeholder="请输入优惠券名称"
@search="onSearch"
/>
</a-col>
</a-row>
</div>
<s-table
ref="table"
rowKey="coupon_id"
:loading="isLoading"
:columns="columns"
:data="loadData"
:pageSize="15"
>
<!-- 优惠券类型 -->
<template slot="coupon_type" slot-scope="text">
<a-tag>{{ CouponTypeEnum[text].name }}</a-tag>
</template>
<!-- 最低消费金额 -->
<template slot="min_price" slot-scope="text">
<p class="c-p">{{ text }}</p>
</template>
<!-- 优惠方式 -->
<template slot="discount" slot-scope="item">
<template v-if="item.coupon_type == 10">
<span>立减</span>
<span class="c-p mlr-2">{{ item.reduce_price }}</span>
<span>元</span>
</template>
<template v-if="item.coupon_type == 20">
<span>打</span>
<span class="c-p mlr-2">{{ item.discount }}</span>
<span>折</span>
</template>
</template>
<!-- 有效期 -->
<template slot="duetime" slot-scope="item">
<template v-if="item.expire_type == 10">
<span>领取</span>
<span class="c-p mlr-2">{{ item.expire_day }}</span>
<span>天内有效</span>
</template>
<template v-if="item.expire_type == 20">
<span>{{ item.start_time }} ~ {{ item.end_time }}</span>
</template>
</template>
<!-- 状态 -->
<template slot="status" slot-scope="text">
<a-tag :color="text ? 'green' : ''">{{ text ? '显示' : '隐藏' }}</a-tag>
</template>
<!-- 操作 -->
<span class="actions" slot="action" slot-scope="item">
<a v-if="$auth('/market/coupon/update')" @click="handleEdit(item)">编辑</a>
<a v-action:delete @click="handleDelete(item)">删除</a>
</span>
</s-table>
</a-card>
</template>
<script>
import * as Api from '@/api/market/coupon'
import { STable } from '@/components'
import { ApplyRangeEnum, CouponTypeEnum, ExpireTypeEnum } from '@/common/enum/coupon'
export default {
name: 'Index',
components: {
STable
},
data () {
return {
// 查询参数
queryParam: {},
// 枚举类
ApplyRangeEnum,
CouponTypeEnum,
ExpireTypeEnum,
// 正在加载
isLoading: false,
// 表头
columns: [
{
title: '优惠券ID',
dataIndex: 'coupon_id'
},
{
title: '优惠券名称',
dataIndex: 'name'
},
{
title: '优惠券类型',
dataIndex: 'coupon_type',
scopedSlots: { customRender: 'coupon_type' }
},
{
title: '最低消费金额 (元)',
dataIndex: 'min_price',
scopedSlots: { customRender: 'min_price' }
},
{
title: '优惠方式',
scopedSlots: { customRender: 'discount' }
},
// {
// title: '有效期',
// scopedSlots: { customRender: 'duetime' }
// },
// {
// title: '发放总数量',
// dataIndex: 'total_num'
// },
{
title: '已发放/领取数量',
dataIndex: 'receive_num'
},
{
title: '状态',
dataIndex: 'status',
scopedSlots: { customRender: 'status' }
},
{
title: '排序',
dataIndex: 'sort'
},
{
title: '添加时间',
dataIndex: 'create_time'
},
{
title: '操作',
width: '180px',
scopedSlots: { customRender: 'action' }
}
],
// 加载数据方法 必须为 Promise 对象
loadData: param => {
return Api.list({ ...param, ...this.queryParam })
.then(response => {
return response.data.list
})
}
}
},
created () {
},
methods: {
// 新增记录
handleAdd () {
this.$router.push('./create')
},
// 编辑记录
handleEdit (item) {
this.$router.push({ path: './update', query: { couponId: item.coupon_id } })
},
/**
* 删除记录
*/
handleDelete (item) {
const app = this
const modal = this.$confirm({
title: '您确定要删除该记录吗?',
content: '删除后不可恢复',
onOk () {
return Api.deleted({ couponId: item.coupon_id })
.then((result) => {
app.$message.success(result.message, 1.5)
app.handleRefresh()
})
.finally(result => {
modal.destroy()
})
}
})
},
/**
* 刷新列表
* @param Boolean bool 强制刷新到第一页
*/
handleRefresh (bool = false) {
this.$refs.table.refresh(bool)
},
/**
* 检索查询
*/
onSearch () {
this.handleRefresh(true)
}
}
}
</script>
@@ -0,0 +1,165 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<div class="table-operator">
<!-- 搜索板块 -->
<a-row class="row-item-search">
<a-form class="search-form" :form="searchForm" layout="inline" @submit="handleSearch">
<a-form-item label="优惠券名称">
<a-input v-decorator="['couponName']" placeholder="请输入优惠券名称" />
</a-form-item>
<a-form-item label="会员昵称">
<a-input v-decorator="['nickName']" placeholder="请输入会员昵称" />
</a-form-item>
<a-form-item label="领取时间">
<a-range-picker format="YYYY-MM-DD" v-decorator="['betweenTime']" />
</a-form-item>
<a-form-item class="search-btn">
<a-button type="primary" icon="search" html-type="submit">搜索</a-button>
</a-form-item>
</a-form>
</a-row>
</div>
<s-table
ref="table"
rowKey="user_coupon_id"
:loading="isLoading"
:columns="columns"
:data="loadData"
:pageSize="15"
>
<!-- 会员信息 -->
<template slot="user" slot-scope="item">
<UserItem :user="item" />
</template>
<!-- 优惠券类型 -->
<template slot="coupon_type" slot-scope="text">
<a-tag>{{ CouponTypeEnum[text].name }}</a-tag>
</template>
<!-- 最低消费金额 -->
<template slot="min_price" slot-scope="text">
<p class="c-p">{{ text }}</p>
</template>
<!-- 优惠方式 -->
<template slot="discount" slot-scope="item">
<template v-if="item.coupon_type == CouponTypeEnum.FULL_DISCOUNT.value">
<span>立减</span>
<span class="c-p mlr-2">{{ item.reduce_price }}</span>
<span>元</span>
</template>
<template v-if="item.coupon_type == CouponTypeEnum.DISCOUNT.value">
<span>打</span>
<span class="c-p mlr-2">{{ item.discount }}</span>
<span>折</span>
</template>
</template>
<!-- 有效期 -->
<template slot="duetime" slot-scope="item">
<template v-if="item.expire_type == 10">
<span>领取</span>
<span class="c-p mlr-2">{{ item.expire_day }}</span>
<span>天内有效</span>
</template>
<template v-if="item.expire_type == 20">
<span>{{ item.start_time }} ~ {{ item.end_time }}</span>
</template>
</template>
</s-table>
</a-card>
</template>
<script>
import * as Api from '@/api/market/coupon'
import { STable, UserItem } from '@/components/Table'
import { CouponTypeEnum } from '@/common/enum/coupon'
export default {
name: 'Index',
components: {
STable,
UserItem
},
data () {
return {
// 当前表单元素
searchForm: this.$form.createForm(this),
// 查询参数
queryParam: {},
// 枚举类
CouponTypeEnum,
// 正在加载
isLoading: false,
// 表头
columns: [
{
title: 'ID',
dataIndex: 'user_coupon_id'
},
{
title: '会员信息',
dataIndex: 'user',
scopedSlots: { customRender: 'user' }
},
{
title: '优惠券名称',
dataIndex: 'name'
},
{
title: '优惠券类型',
dataIndex: 'coupon_type',
scopedSlots: { customRender: 'coupon_type' }
},
{
title: '最低消费金额 (元)',
dataIndex: 'min_price',
scopedSlots: { customRender: 'min_price' }
},
{
title: '优惠方式',
scopedSlots: { customRender: 'discount' }
},
{
title: '有效期',
scopedSlots: { customRender: 'duetime' }
},
{
title: '领取时间',
dataIndex: 'create_time'
}
],
// 加载数据方法 必须为 Promise 对象
loadData: param => {
return Api.receive({ ...param, ...this.queryParam })
.then(response => {
return response.data.list
})
}
}
},
created () {
},
methods: {
/**
* 刷新列表
* @param Boolean bool 强制刷新到第一页
*/
handleRefresh (bool = false) {
this.$refs.table.refresh(bool)
},
// 确认搜索
handleSearch (e) {
e.preventDefault()
this.searchForm.validateFields((error, values) => {
if (!error) {
this.queryParam = { ...this.queryParam, ...values }
this.handleRefresh(true)
}
})
}
}
}
</script>
@@ -0,0 +1,278 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<a-spin :spinning="isLoading">
<a-form :form="form" @submit="handleSubmit">
<a-form-item label="优惠券名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
placeholder="请输入优惠券名称"
v-decorator="['name', { rules: [{ required: true, min: 2, message: '请输入至少2个字符' }] }]"
/>
</a-form-item>
<a-form-item label="优惠券类型" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-decorator="['coupon_type', { initialValue: 10, rules: [{ required: true }] }]"
>
<a-radio :value="10">满减券</a-radio>
<a-radio :value="20">折扣券</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item
v-show="form.getFieldValue('coupon_type') == CouponTypeEnum.FULL_DISCOUNT.value"
label="减免金额"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input-number
:min="0.01"
:precision="2"
v-decorator="['reduce_price', { rules: [{ required: true, message: '请输入减免金额' }] }]"
/>
<span class="ml-5">元</span>
</a-form-item>
<a-form-item
v-show="form.getFieldValue('coupon_type') == CouponTypeEnum.DISCOUNT.value"
label="折扣率"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input-number
:min="0"
:max="9.9"
:precision="1"
v-decorator="['discount', { initialValue: 9.9, rules: [{ required: true, message: '请输入折扣率' }] }]"
/>
<span class="ml-5">%</span>
<p class="form-item-help">
<small>折扣率范围 0-9.9,8代表打8折,0代表不折扣</small>
</p>
</a-form-item>
<a-form-item label="最低消费金额" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input-number
:min="1"
:precision="2"
v-decorator="['min_price', { rules: [{ required: true, message: '请输入最低消费金额' }] }]"
/>
<span class="ml-5">元</span>
</a-form-item>
<a-form-item label="到期类型" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-decorator="['expire_type', { initialValue: 10, rules: [{ required: true }] }]"
>
<a-radio :value="10">领取后生效</a-radio>
<a-radio :value="20">固定时间</a-radio>
</a-radio-group>
<a-form-item v-show="form.getFieldValue('expire_type') == 10" class="expire_type-10">
<InputNumberGroup
addonBefore="有效期"
addonAfter="天"
:inputProps="{ min: 1, precision: 0 }"
v-decorator="['expire_day', { initialValue: 7, rules: [{ required: true, message: '请输入有效期天数' }] }]"
/>
</a-form-item>
<a-form-item v-show="form.getFieldValue('expire_type') == 20" class="expire_type-20">
<a-range-picker
format="YYYY-MM-DD"
v-decorator="['betweenTime', { initialValue: defaultDate, rules: [{ required: true, message: '请选择有效期范围' }] }]"
/>
</a-form-item>
</a-form-item>
<a-form-item label="券适用范围" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-decorator="['apply_range', { initialValue: 10, rules: [{ required: true }] }]"
>
<a-radio :value="10">全场通用</a-radio>
<a-radio :value="20">指定商品</a-radio>
</a-radio-group>
<a-form-item v-if="form.getFieldValue('apply_range') == 20">
<SelectGoods
:defaultList="containGoodsList"
v-decorator="['apply_range_config.applyGoodsIds', { rules: [{ required: true, message: '请选择指定的商品' }] }]"
/>
</a-form-item>
</a-form-item>
<a-form-item label="发放总数量" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input-number
:min="-1"
:precision="0"
v-decorator="['total_num', { initialValue: -1, rules: [{ required: true, message: '请输入发放总数量' }] }]"
/>
<span class="ml-5">张</span>
<p class="form-item-help">
<small>发放的优惠券总数量,-1为不限制</small>
</p>
</a-form-item>
<a-form-item label="显示状态" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['status', { initialValue: 1, rules: [{ required: true }] }]">
<a-radio :value="1">显示</a-radio>
<a-radio :value="0">隐藏</a-radio>
</a-radio-group>
<p class="form-item-help">
<small>如果设为隐藏将不会展示在用户端页面</small>
</p>
</a-form-item>
<a-form-item label="优惠券描述" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-textarea :autoSize="{ minRows: 4 }" v-decorator="['describe']" />
</a-form-item>
<a-form-item label="排序" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="数字越小越靠前">
<a-input-number
:min="0"
v-decorator="['sort', {initialValue: 100, rules:[{required: true, message: '请输入排序值'}]}]"
/>
</a-form-item>
<a-form-item class="mt-20" :wrapper-col="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" html-type="submit" :loading="isBtnLoading">提交</a-button>
</a-form-item>
</a-form>
</a-spin>
</a-card>
</template>
<script>
import moment from 'moment'
import { pick, get } from 'lodash'
import * as Api from '@/api/market/coupon'
import * as GoodsApi from '@/api/goods'
import { isEmpty } from '@/utils/util'
import { InputNumberGroup, SelectGoods } from '@/components'
import { ApplyRangeEnum, CouponTypeEnum, ExpireTypeEnum } from '@/common/enum/coupon'
export default {
components: {
SelectGoods,
InputNumberGroup
},
data () {
return {
// 枚举类
ApplyRangeEnum,
CouponTypeEnum,
ExpireTypeEnum,
// 正在加载
isLoading: false,
isBtnLoading: false,
// 标签布局属性
labelCol: { span: 3 },
// 输入框布局属性
wrapperCol: { span: 10 },
// 当前表单元素
form: this.$form.createForm(this),
// 默认日期范围
defaultDate: [moment(), moment()],
// 优惠券ID
couponId: null,
// 当前记录
record: {},
// 适用范围:指定的商品
containGoodsList: []
}
},
async created () {
// 记录优惠券ID
this.couponId = this.$route.query.couponId
// 获取当前记录
await this.getDetail()
// 获取适用范围:指定的商品
await this.getContainGoodsList()
},
methods: {
// 获取当前记录
async getDetail () {
const { couponId } = this
this.isLoading = true
await Api.detail({ couponId })
.then(result => {
// 当前记录
this.record = result.data.detail
// 设置表单默认值
this.setFieldsValue()
})
.finally(() => {
this.isLoading = false
})
},
// 获取指定的商品列表
async getContainGoodsList () {
const { record } = this
const goodsIds = get(record, 'apply_range_config.applyGoodsIds')
if (goodsIds !== undefined && goodsIds.length) {
this.isLoading = true
await GoodsApi.listByIds(goodsIds)
.then(result => {
this.containGoodsList = result.data.list
})
.finally(result => {
this.isLoading = false
})
}
},
// 设置表单默认值
setFieldsValue () {
const { record, form, $nextTick } = this
// 设置表单内容
!isEmpty(form.getFieldsValue()) && $nextTick(() => {
// 表单数据
const data = pick(record, [
'name', 'coupon_type', 'reduce_price', 'discount', 'min_price', 'status',
'expire_type', 'expire_day', 'apply_range', 'total_num', 'describe', 'sort'
])
// 时间范围
data.betweenTime = this.getBetweenTime(record)
form.setFieldsValue(data)
})
},
// 格式化时间范围
getBetweenTime (record) {
if (record.expire_type === ExpireTypeEnum.FIXED_TIME.value) {
return [moment(new Date(record.start_time)), moment(new Date(record.end_time))]
}
return this.defaultDate
},
// 确认按钮
handleSubmit (e) {
e.preventDefault()
// 表单验证
const { form: { validateFields }, onFormSubmit } = this
validateFields((errors, values) => {
!errors && onFormSubmit(values)
})
},
/**
* 提交到后端api
*/
onFormSubmit (values) {
this.isLoading = true
this.isBtnLoading = true
Api.edit({ couponId: this.couponId, form: values })
.then(result => {
// 显示提示信息
this.$message.success(result.message, 1.5)
// 跳转到列表页
setTimeout(() => {
this.$router.push('./index')
}, 1500)
})
.catch(() => {
this.isBtnLoading = false
})
.finally(result => {
this.isLoading = false
})
}
}
}
</script>
<style lang="less" scoped>
.ant-form-item {
.ant-form-item {
margin-bottom: 0;
}
}
</style>
@@ -0,0 +1,128 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<a-spin :spinning="isLoading">
<a-form :form="form" @submit="handleSubmit">
<a-form-item label="是否开启实体卡兑换" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['is_entrance', { rules: [{ required: true }] }]">
<a-radio :value="1">开启</a-radio>
<a-radio :value="0">关闭</a-radio>
</a-radio-group>
<div class="form-item-help">
<small>如设置关闭则用户端不显示兑换按钮</small>
</div>
</a-form-item>
<a-form-item label="兑换说明" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-textarea
:autoSize="{ minRows: 4 }"
v-decorator="['describe', { rules: [{ required: true, message: '请输入兑换说明' }] }]"
/>
</a-form-item>
<a-form-item :wrapper-col="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" html-type="submit">提交</a-button>
</a-form-item>
</a-form>
</a-spin>
</a-card>
</template>
<script>
import pick from 'lodash.pick'
import * as Api from '@/api/setting/store'
export default {
components: {
},
data () {
return {
// 当前设置项的key
key: 'exchange',
// 标签布局属性
labelCol: { span: 4 },
// 输入框布局属性
wrapperCol: { span: 10 },
// loading状态
isLoading: false,
// 当前表单元素
form: this.$form.createForm(this),
// 当前记录详情
record: {}
}
},
// 初始化数据
created () {
// 获取当前详情记录
this.getDetail()
},
methods: {
// 获取当前详情记录
getDetail () {
this.isLoading = true
Api.detail(this.key)
.then(result => {
// 当前记录
this.record = result.data.values
// 设置默认值
this.setFieldsValue()
})
.finally(result => {
this.isLoading = false
})
},
/**
* 设置默认值
*/
setFieldsValue () {
const { record, $nextTick, form: { setFieldsValue } } = this
$nextTick(() => {
setFieldsValue(pick(record, ['is_entrance', 'describe']))
})
},
/**
* 确认按钮
*/
handleSubmit (e) {
e.preventDefault()
// 表单验证
const { form: { validateFields } } = this
validateFields((errors, values) => {
// 提交到后端api
!errors && this.onFormSubmit(values)
})
},
/**
* 提交到后端api
*/
onFormSubmit (values) {
this.isLoading = true
Api.update(this.key, { form: values })
.then((result) => {
// 显示提示信息
this.$message.success(result.message, 1.5)
})
.finally((result) => {
this.isLoading = false
})
}
}
}
</script>
<style lang="less" scoped>
.ant-form-item {
.ant-form-item {
margin-bottom: 0;
}
}
/deep/.ant-form-item-control {
padding-left: 10px;
.ant-form-item-control {
padding-left: 0;
}
}
</style>
+131
View File
@@ -0,0 +1,131 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<div class="table-operator">
<!-- 搜索板块 -->
<a-row class="row-item-search">
<a-form class="search-form" :form="searchForm" layout="inline" @submit="handleSearch">
<a-form-item label="会员昵称">
<a-input v-decorator="['search']" placeholder="请输入会员昵称" />
</a-form-item>
<a-form-item label="变动时间">
<a-range-picker format="YYYY-MM-DD" v-decorator="['betweenTime']" />
</a-form-item>
<a-form-item class="search-btn">
<a-button type="primary" icon="search" html-type="submit">搜索</a-button>
</a-form-item>
</a-form>
</a-row>
</div>
<s-table
ref="table"
rowKey="log_id"
:loading="isLoading"
:columns="columns"
:data="loadData"
:pageSize="15"
>
<!-- 会员信息 -->
<span slot="user" slot-scope="text">
<UserItem :user="text" />
</span>
<!-- 变动数量 -->
<span slot="value" slot-scope="text">
<p class="c-p">{{ text > 0 ? '+' : '' }}{{ text }}</p>
</span>
</s-table>
</a-card>
</template>
<script>
import * as Api from '@/api/market/points'
import { STable, UserItem } from '@/components/Table'
import SceneEnum from '@/common/enum/user/balance/log/Scene'
export default {
name: 'Index',
components: {
STable,
UserItem
},
data () {
return {
// 枚举类
SceneEnum,
// 当前表单元素
searchForm: this.$form.createForm(this),
// 查询参数
queryParam: {},
// 正在加载
isLoading: false,
// 表头
columns: [
{
title: 'ID',
dataIndex: 'log_id'
},
{
title: '会员信息',
dataIndex: 'user',
scopedSlots: { customRender: 'user' }
},
{
title: '变动数量',
dataIndex: 'value',
scopedSlots: { customRender: 'value' }
},
{
title: '描述/说明',
dataIndex: 'describe'
},
{
title: '管理员备注',
dataIndex: 'remark'
},
{
title: '变动时间',
dataIndex: 'create_time'
}
],
// 加载数据方法 必须为 Promise 对象
loadData: param => {
return Api.log({ ...param, ...this.queryParam })
.then(response => {
return response.data.list
})
}
}
},
created () {
},
methods: {
/**
* 刷新列表
* @param Boolean bool 强制刷新到第一页
*/
handleRefresh (bool = false) {
this.$refs.table.refresh(bool)
},
// 确认搜索
handleSearch (e) {
e.preventDefault()
this.searchForm.validateFields((error, values) => {
if (!error) {
this.queryParam = { ...this.queryParam, ...values }
this.handleRefresh(true)
}
})
}
}
}
</script>
<style lang="less" scoped>
.ant-card-body {
padding: 22px 29px 25px;
}
</style>
@@ -0,0 +1,209 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<a-spin :spinning="isLoading">
<a-form :form="form" @submit="handleSubmit">
<a-form-item label="积分名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input
v-decorator="['points_name', { rules: [{ required: true, message: '请输入积分名称' }] }]"
/>
<div class="form-item-help">
<small>注:商家使用自定义的积分名称来做品牌运营。如京东把积分称为“京豆”,淘宝把积分称为“淘金币”</small>
</div>
</a-form-item>
<a-form-item label="积分说明" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-textarea
:autoSize="{ minRows: 4 }"
v-decorator="['describe', { rules: [{ required: true, message: '请输入积分说明' }] }]"
/>
</a-form-item>
<a-divider orientation="left">积分赠送</a-divider>
<a-form-item label="购物送积分" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-decorator="['is_shopping_gift', { initialValue: 1, rules: [{ required: true }] }]"
>
<a-radio :value="1">开启</a-radio>
<a-radio :value="0">关闭</a-radio>
</a-radio-group>
<div class="form-item-help">
<small>积分赠送规则:1. 订单确认收货已完成; 2. 已完成订单超出后台设置的申请售后期限</small>
</div>
</a-form-item>
<div v-show="form.getFieldValue('is_shopping_gift') == 1">
<a-form-item label="积分赠送比例" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input-number
:min="0.1"
:max="100"
:precision="1"
v-decorator="['gift_ratio', { rules: [{ required: true, message: '请输入积分赠送比例' }] }]"
/>
<span class="ml-10">%</span>
<div class="form-item-help">
<p class="extra">注:赠送比例请填写数字0~100;订单的运费不参与积分赠送</p>
<p class="extra">例:订单付款金额(100.00元) * 积分赠送比例(100%) = 实际赠送的积分(100积分)</p>
</div>
</a-form-item>
</div>
<a-divider orientation="left">积分抵扣</a-divider>
<a-form-item label="下单使用积分抵扣" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group
v-decorator="['is_shopping_discount', { initialValue: 1, rules: [{ required: true }] }]"
>
<a-radio :value="1">开启</a-radio>
<a-radio :value="0">关闭</a-radio>
</a-radio-group>
<div class="form-item-help">
<small>注:如开启则用户下单时可选择使用积分抵扣订单金额</small>
</div>
</a-form-item>
<div v-show="form.getFieldValue('is_shopping_discount') == 1">
<a-form-item label="积分抵扣比例" :labelCol="labelCol" :wrapperCol="wrapperCol">
<InputNumberGroup
addonBefore="1个积分可抵扣"
addonAfter="元"
:inputProps="{ min: 0.01, precision: 2 }"
v-decorator="['discount.discount_ratio', { rules: [{ required: true, message: '积分抵扣比例不能为空' }] }]"
/>
<div class="form-item-help">
<small>例如:设置1个积分可抵扣0.1元,则10积分可抵扣1元,100积分可抵扣10元</small>
</div>
</a-form-item>
<a-form-item label="最高可抵扣金额" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-form-item>
<InputNumberGroup
addonBefore="订单满"
addonAfter="元"
:inputProps="{ min: 0.01, precision: 2 }"
v-decorator="['discount.full_order_price', { rules: [{ required: true, message: '抵扣条件不能为空' }] }]"
/>
</a-form-item>
<a-form-item>
<InputNumberGroup
addonBefore="最高可抵扣金额"
addonAfter="%"
:inputProps="{ min: 0.1, max: 90, precision: 1 }"
v-decorator="['discount.max_money_ratio', { rules: [{ required: true, message: '最高可抵扣金额不能为空' }] }]"
/>
<div class="form-item-help">
<small>例如:设置最高可抵扣10%,订单金额100元,此时用户可抵扣10元</small>
</div>
</a-form-item>
</a-form-item>
</div>
<a-form-item :wrapper-col="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" html-type="submit">提交</a-button>
</a-form-item>
</a-form>
</a-spin>
</a-card>
</template>
<script>
import pick from 'lodash.pick'
import * as Api from '@/api/setting/store'
import { InputNumberGroup } from '@/components'
export default {
components: {
InputNumberGroup
},
data () {
return {
// 当前设置项的key
key: 'points',
// 标签布局属性
labelCol: { span: 4 },
// 输入框布局属性
wrapperCol: { span: 10 },
// loading状态
isLoading: false,
// 当前表单元素
form: this.$form.createForm(this),
// 当前记录详情
record: {}
}
},
// 初始化数据
created () {
// 获取当前详情记录
this.getDetail()
},
methods: {
// 获取当前详情记录
getDetail () {
this.isLoading = true
Api.detail(this.key)
.then(result => {
// 当前记录
this.record = result.data.values
// 设置默认值
this.setFieldsValue()
})
.finally(result => {
this.isLoading = false
})
},
/**
* 设置默认值
*/
setFieldsValue () {
const { record, $nextTick, form: { setFieldsValue } } = this
$nextTick(() => {
setFieldsValue(pick(record, [
'points_name', 'describe',
'is_shopping_gift', 'gift_ratio',
'is_shopping_discount', 'discount'
]))
})
},
/**
* 确认按钮
*/
handleSubmit (e) {
e.preventDefault()
// 表单验证
const { form: { validateFields } } = this
validateFields((errors, values) => {
// 提交到后端api
!errors && this.onFormSubmit(values)
})
},
/**
* 提交到后端api
*/
onFormSubmit (values) {
this.isLoading = true
Api.update(this.key, { form: values })
.then((result) => {
// 显示提示信息
this.$message.success(result.message, 1.5)
})
.finally((result) => {
this.isLoading = false
})
}
}
}
</script>
<style lang="less" scoped>
.ant-form-item {
.ant-form-item {
margin-bottom: 0;
}
}
/deep/.ant-form-item-control {
padding-left: 10px;
.ant-form-item-control {
padding-left: 0;
}
}
</style>
@@ -0,0 +1,162 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<a-spin :spinning="isLoading">
<a-form :form="form" @submit="handleSubmit">
<a-form-item label="是否开启会员充值" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['is_entrance', { rules: [{ required: true }] }]">
<a-radio :value="1">开启</a-radio>
<a-radio :value="0">关闭</a-radio>
</a-radio-group>
<div class="form-item-help">
<small>如设置关闭则用户端不显示充值按钮</small>
</div>
</a-form-item>
<a-form-item label="充值自定义金额" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['is_custom', { rules: [{ required: true }] }]">
<a-radio :value="1">允许</a-radio>
<a-radio :value="0">不允许</a-radio>
</a-radio-group>
<div class="form-item-help">
<small>是否允许用户填写自定义的充值金额</small>
</div>
</a-form-item>
<a-form-item
v-show="form.getFieldValue('is_custom') == 1"
label="最低充值金额"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
>
<a-input-number
:min="0.01"
:precision="2"
v-decorator="['lowest_money', { rules: [{ required: true, message: '请输入最低充值金额' }] }]"
/>
<span class="ml-10">元</span>
<div class="form-item-help">
<small>低于该设定金额时不允许充值</small>
</div>
</a-form-item>
<a-form-item label="自动匹配套餐" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['is_match_plan', { rules: [{ required: true }] }]">
<a-radio :value="1">开启</a-radio>
<a-radio :value="0">关闭</a-radio>
</a-radio-group>
<div class="form-item-help">
<small>充值自定义金额时 是否自动匹配充值套餐,如不开启则不参与套餐金额赠送</small>
</div>
</a-form-item>
<a-form-item label="充值说明" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-textarea
:autoSize="{ minRows: 4 }"
v-decorator="['describe', { rules: [{ required: true, message: '请输入充值说明' }] }]"
/>
</a-form-item>
<a-form-item :wrapper-col="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" html-type="submit">提交</a-button>
</a-form-item>
</a-form>
</a-spin>
</a-card>
</template>
<script>
import pick from 'lodash.pick'
import * as Api from '@/api/setting/store'
export default {
components: {
},
data () {
return {
// 当前设置项的key
key: 'recharge',
// 标签布局属性
labelCol: { span: 4 },
// 输入框布局属性
wrapperCol: { span: 10 },
// loading状态
isLoading: false,
// 当前表单元素
form: this.$form.createForm(this),
// 当前记录详情
record: {}
}
},
// 初始化数据
created () {
// 获取当前详情记录
this.getDetail()
},
methods: {
// 获取当前详情记录
getDetail () {
this.isLoading = true
Api.detail(this.key)
.then(result => {
// 当前记录
this.record = result.data.values
// 设置默认值
this.setFieldsValue()
})
.finally(result => {
this.isLoading = false
})
},
/**
* 设置默认值
*/
setFieldsValue () {
const { record, $nextTick, form: { setFieldsValue } } = this
$nextTick(() => {
setFieldsValue(pick(record, ['is_entrance', 'is_custom', 'lowest_money', 'is_match_plan', 'describe']))
})
},
/**
* 确认按钮
*/
handleSubmit (e) {
e.preventDefault()
// 表单验证
const { form: { validateFields } } = this
validateFields((errors, values) => {
// 提交到后端api
!errors && this.onFormSubmit(values)
})
},
/**
* 提交到后端api
*/
onFormSubmit (values) {
this.isLoading = true
Api.update(this.key, { form: values })
.then((result) => {
// 显示提示信息
this.$message.success(result.message, 1.5)
})
.finally((result) => {
this.isLoading = false
})
}
}
}
</script>
<style lang="less" scoped>
.ant-form-item {
.ant-form-item {
margin-bottom: 0;
}
}
/deep/.ant-form-item-control {
padding-left: 10px;
.ant-form-item-control {
padding-left: 0;
}
}
</style>
@@ -0,0 +1,165 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<div class="table-operator">
<a-row>
<a-col :span="6">
<a-button v-action:add type="primary" icon="plus" @click="handleAdd">新增</a-button>
</a-col>
<a-col :span="8" :offset="10">
<a-input-search
style="max-width: 300px; min-width: 150px;float: right;"
v-model="queryParam.search"
placeholder="请输入套餐名称"
@search="onSearch"
/>
</a-col>
</a-row>
</div>
<s-table
ref="table"
rowKey="plan_id"
:loading="isLoading"
:columns="columns"
:data="loadData"
:pageSize="15"
>
<!-- 充值金额 -->
<span slot="money" slot-scope="text">
<p class="c-p">{{ text }}</p>
</span>
<!-- 赠送金额 -->
<span slot="gift_money" slot-scope="text">
<p class="c-p">{{ text }}</p>
</span>
<!-- 操作 -->
<span slot="action" slot-scope="text, item">
<a v-action:edit style="margin-right: 8px;" @click="handleEdit(item)">编辑</a>
<a v-action:delete @click="handleDelete(item)">删除</a>
</span>
</s-table>
<AddForm ref="AddForm" @handleSubmit="handleRefresh" />
<EditForm ref="EditForm" @handleSubmit="handleRefresh" />
</a-card>
</template>
<script>
import * as Api from '@/api/market/recharge/plan'
import { STable } from '@/components'
import { AddForm, EditForm } from './modules'
export default {
name: 'Index',
components: {
STable,
AddForm,
EditForm
},
data () {
return {
// 查询参数
queryParam: {},
// 正在加载
isLoading: false,
// 表头
columns: [
{
title: '套餐ID',
dataIndex: 'plan_id'
},
{
title: '套餐名称',
dataIndex: 'plan_name'
},
{
title: '充值金额 (元)',
dataIndex: 'money',
scopedSlots: { customRender: 'money' }
},
{
title: '赠送金额 (元)',
dataIndex: 'gift_money',
scopedSlots: { customRender: 'gift_money' }
},
{
title: '排序',
dataIndex: 'sort'
},
{
title: '添加时间',
dataIndex: 'create_time'
},
{
title: '操作',
dataIndex: 'action',
width: '180px',
scopedSlots: { customRender: 'action' }
}
],
// 加载数据方法 必须为 Promise 对象
loadData: param => {
return Api.list({ ...param, ...this.queryParam })
.then(response => {
return response.data.list
})
}
}
},
created () {
},
methods: {
/**
* 新增记录
*/
handleAdd () {
this.$refs.AddForm.add()
},
/**
* 编辑记录
*/
handleEdit (item) {
this.$refs.EditForm.edit(item)
},
/**
* 删除记录
*/
handleDelete (item) {
const app = this
const modal = this.$confirm({
title: '您确定要删除该记录吗?',
content: '删除后不可恢复',
onOk () {
return Api.deleted({ planId: item.plan_id })
.then((result) => {
app.$message.success(result.message, 1.5)
app.handleRefresh()
})
.finally(result => {
modal.destroy()
})
}
})
},
/**
* 刷新列表
* @param Boolean bool 强制刷新到第一页
*/
handleRefresh (bool = false) {
this.$refs.table.refresh(bool)
},
/**
* 检索查询
*/
onSearch () {
this.handleRefresh(true)
}
}
}
</script>
@@ -0,0 +1,125 @@
<template>
<a-modal
:title="title"
:width="720"
:visible="visible"
:confirmLoading="confirmLoading"
:maskClosable="false"
@ok="handleSubmit"
@cancel="handleCancel"
>
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<a-form-item
label="套餐名称"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="便于后台查找,例如:充100元送10元"
>
<a-input
v-decorator="['plan_name', {rules: [{required: true, min: 2, message: '请输入至少2个字符'}]}]"
/>
</a-form-item>
<a-form-item label="充值金额" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="会员充值并支付的金额">
<a-input-number
:min="0.01"
v-decorator="['money', {rules: [{required: true, message: '请输入充值的金额'}]}]"
/>
<span class="ml-10">元</span>
</a-form-item>
<a-form-item
label="赠送金额"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="充值成功后赠送的金额,不能大于充值金额"
>
<a-input-number
:min="0.01"
v-decorator="['gift_money', {rules: [{required: true, message: '请输入赠送的金额'}]}]"
/>
<span class="ml-10">元</span>
</a-form-item>
<a-form-item label="排序" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="数字越小越靠前">
<a-input-number
:min="0"
v-decorator="['sort', {initialValue: 100, rules: [{required: true, message: '请输入排序值'}]}]"
/>
</a-form-item>
</a-form>
</a-spin>
</a-modal>
</template>
<script>
import * as Api from '@/api/market/recharge/plan'
export default {
data () {
return {
// 对话框标题
title: '新增充值套餐',
// 标签布局属性
labelCol: { span: 7 },
// 输入框布局属性
wrapperCol: { span: 13 },
// modal(对话框)是否可见
visible: false,
// modal(对话框)确定按钮 loading
confirmLoading: false,
// 当前表单元素
form: this.$form.createForm(this)
}
},
methods: {
/**
* 显示对话框
*/
add () {
// 显示窗口
this.visible = true
},
/**
* 确认按钮
*/
handleSubmit (e) {
e.preventDefault()
// 表单验证
const { form: { validateFields } } = this
validateFields((errors, values) => {
// 提交到后端api
!errors && this.onFormSubmit(values)
})
},
/**
* 关闭对话框事件
*/
handleCancel () {
this.visible = false
this.form.resetFields()
},
/**
* 提交到后端api
*/
onFormSubmit (values) {
this.confirmLoading = true
Api.add({ form: values })
.then((result) => {
// 显示成功
this.$message.success(result.message, 1.5)
// 关闭对话框事件
this.handleCancel()
// 通知父端组件提交完成了
this.$emit('handleSubmit', values)
})
.finally(() => {
this.confirmLoading = false
})
}
}
}
</script>
@@ -0,0 +1,142 @@
<template>
<a-modal
:title="title"
:width="720"
:visible="visible"
:confirmLoading="confirmLoading"
:maskClosable="false"
@ok="handleSubmit"
@cancel="handleCancel"
>
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<a-form-item
label="套餐名称"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="便于后台查找,例如:充100元送10元"
>
<a-input
v-decorator="['plan_name', {rules: [{required: true, min: 2, message: '请输入至少2个字符'}]}]"
/>
</a-form-item>
<a-form-item label="充值金额" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="会员充值并支付的金额">
<a-input-number
:min="0.01"
v-decorator="['money', {rules: [{required: true, message: '请输入充值的金额'}]}]"
/>
<span class="ml-10">元</span>
</a-form-item>
<a-form-item
label="赠送金额"
:labelCol="labelCol"
:wrapperCol="wrapperCol"
extra="充值成功后赠送的金额,不能大于充值金额"
>
<a-input-number
:min="0.01"
v-decorator="['gift_money', {rules: [{required: true, message: '请输入赠送的金额'}]}]"
/>
<span class="ml-10">元</span>
</a-form-item>
<a-form-item label="排序" :labelCol="labelCol" :wrapperCol="wrapperCol" extra="数字越小越靠前">
<a-input-number
:min="0"
v-decorator="['sort', {initialValue: 100, rules: [{required: true, message: '请输入排序值'}]}]"
/>
</a-form-item>
</a-form>
</a-spin>
</a-modal>
</template>
<script>
import pick from 'lodash.pick'
import * as Api from '@/api/market/recharge/plan'
export default {
data () {
return {
// 对话框标题
title: '编辑充值套餐',
// 标签布局属性
labelCol: { span: 7 },
// 输入框布局属性
wrapperCol: { span: 13 },
// modal(对话框)是否可见
visible: false,
// modal(对话框)确定按钮 loading
confirmLoading: false,
// 当前表单元素
form: this.$form.createForm(this),
// 当前记录
record: {}
}
},
methods: {
/**
* 显示对话框
*/
edit (record) {
// 显示窗口
this.visible = true
// 当前记录
this.record = record
// 设置默认值
this.setFieldsValue()
},
/**
* 设置默认值
*/
setFieldsValue () {
const { form: { setFieldsValue } } = this
this.$nextTick(() => {
setFieldsValue(pick(this.record, ['plan_name', 'money', 'gift_money', 'sort']))
})
},
/**
* 确认按钮
*/
handleSubmit (e) {
e.preventDefault()
// 表单验证
const { form: { validateFields } } = this
validateFields((errors, values) => {
// 提交到后端api
!errors && this.onFormSubmit(values)
})
},
/**
* 关闭对话框事件
*/
handleCancel () {
this.visible = false
this.form.resetFields()
},
/**
* 提交到后端api
*/
onFormSubmit (values) {
this.confirmLoading = true
Api.edit({ planId: this.record.plan_id, form: values })
.then((result) => {
// 显示成功
this.$message.success(result.message, 1.5)
// 关闭对话框事件
this.handleCancel()
// 通知父端组件提交完成了
this.$emit('handleSubmit', values)
})
.finally(() => {
this.confirmLoading = false
})
}
}
}
</script>
@@ -0,0 +1,4 @@
import AddForm from './AddForm'
import EditForm from './EditForm'
export { AddForm, EditForm }
@@ -0,0 +1,128 @@
<template>
<a-card :bordered="false">
<div class="card-title">{{ $route.meta.title }}</div>
<a-spin :spinning="isLoading">
<a-form :form="form" @submit="handleSubmit">
<a-form-item label="是否开启余额分享" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-radio-group v-decorator="['is_entrance', { rules: [{ required: true }] }]">
<a-radio :value="1">开启</a-radio>
<a-radio :value="0">关闭</a-radio>
</a-radio-group>
<div class="form-item-help">
<small>如设置关闭则用户端不显示分享按钮</small>
</div>
</a-form-item>
<a-form-item label="分享说明" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-textarea
:autoSize="{ minRows: 4 }"
v-decorator="['describe', { rules: [{ required: true, message: '请输入分享说明' }] }]"
/>
</a-form-item>
<a-form-item :wrapper-col="{ span: wrapperCol.span, offset: labelCol.span }">
<a-button type="primary" html-type="submit">提交</a-button>
</a-form-item>
</a-form>
</a-spin>
</a-card>
</template>
<script>
import pick from 'lodash.pick'
import * as Api from '@/api/setting/store'
export default {
components: {
},
data () {
return {
// 当前设置项的key
key: 'share',
// 标签布局属性
labelCol: { span: 4 },
// 输入框布局属性
wrapperCol: { span: 10 },
// loading状态
isLoading: false,
// 当前表单元素
form: this.$form.createForm(this),
// 当前记录详情
record: {}
}
},
// 初始化数据
created () {
// 获取当前详情记录
this.getDetail()
},
methods: {
// 获取当前详情记录
getDetail () {
this.isLoading = true
Api.detail(this.key)
.then(result => {
// 当前记录
this.record = result.data.values
// 设置默认值
this.setFieldsValue()
})
.finally(result => {
this.isLoading = false
})
},
/**
* 设置默认值
*/
setFieldsValue () {
const { record, $nextTick, form: { setFieldsValue } } = this
$nextTick(() => {
setFieldsValue(pick(record, ['is_entrance', 'describe']))
})
},
/**
* 确认按钮
*/
handleSubmit (e) {
e.preventDefault()
// 表单验证
const { form: { validateFields } } = this
validateFields((errors, values) => {
// 提交到后端api
!errors && this.onFormSubmit(values)
})
},
/**
* 提交到后端api
*/
onFormSubmit (values) {
this.isLoading = true
Api.update(this.key, { form: values })
.then((result) => {
// 显示提示信息
this.$message.success(result.message, 1.5)
})
.finally((result) => {
this.isLoading = false
})
}
}
}
</script>
<style lang="less" scoped>
.ant-form-item {
.ant-form-item {
margin-bottom: 0;
}
}
/deep/.ant-form-item-control {
padding-left: 10px;
.ant-form-item-control {
padding-left: 0;
}
}
</style>