Commit f098606d authored by baixian's avatar baixian

积分管理

parent d2dc6b14
......@@ -148,6 +148,9 @@ export default {
goodsAdd: `${dakaapi}member/integral_goods/store`,
goodsEdit: `${dakaapi}member/integral_goods/update`,
journalList: `${dakaapi}member/integral/records`,
integralRulesAdd: `${dakaapi}member/integral_rules/store`,
integralRulesEdit: `${dakaapi}member/integral_rules/update`,
integralRulesList: `${dakaapi}member/integral_rules/show`,
},
};
......@@ -24,26 +24,70 @@ export default {
recordList: [],
recordListTotal: 0,
couponImg: '',
goodsBanner: [],
editCouponInfo: {
id: 0,
title: '',
cover: '',
price: 0,
inventory: 0,
},
editGoodsInfo: {
id: 0,
title: '',
cover: '',
price: 0,
inventory: 0,
banner: [],
},
type1: {
single: 0,
copySingle: 0,
daily_limit: 0,
checked: true,
unlimited: -1, // 0 不是无限 -1 无限
},
type2: {
single: 0,
daily_limit: 0,
checked: true,
unlimited: 0,
},
type3: {
single: 0,
daily_limit: 0,
checked: true,
unlimited: 0,
},
type4: {
single: 0,
daily_limit: 0,
checked: true,
unlimited: 0,
},
type5: {
single: 0,
daily_limit: 0,
checked: true,
unlimited: 0,
},
type6: {
single: 0,
daily_limit: 0,
checked: true,
unlimited: 0,
},
type7: {
single: 0,
daily_limit: 0,
checked: true,
unlimited: 0,
},
type8: {
single: 0,
daily_limit: 0,
checked: true,
unlimited: 0,
},
type9: {
single: 0,
daily_limit: 0,
checked: true,
unlimited: 0,
},
ruleList: [],
},
subscriptions: {
setup({ dispatch, history }) { // eslint-disable-line
......@@ -115,6 +159,11 @@ export default {
editScoreVisible: false,
},
});
yield put({
type: 'integralModeljournalList',
payload: {
},
});
} else if (scoreAdd.code == 4000) {
message.error(scoreAdd.msg, 1);
} else {
......@@ -125,9 +174,6 @@ export default {
},
});
}
yield put(routerRedux.push({
pathname: '/sjd/integralmanage',
}));
},
* integralModelStudentsList({ payload }, { call, put, select }) {
const { sid } = yield select(state => state.webapp);
......@@ -160,7 +206,7 @@ export default {
* integralModelGoodAdd({ payload }, { call, put, select }) {
const { sid } = yield select(state => state.webapp);
const {
studentSubmiting, couponImg, couponBanner, editCouponInfo,
studentSubmiting, couponImg, goodsBanner, editCouponInfo,
} = yield select(state => state.integral);
if (!sid) {
return;
......@@ -185,7 +231,6 @@ export default {
banner,
callBack,
} = payload;
console.log(payload, 'payload');
const loadmessage = message.loading('保存中...', 0);
const postFunction = editCouponInfo.id != 0 ? goodsAjax.goodsEdit : goodsAjax.goodsAdd;
const data = yield call(postFunction, Object.assign(editCouponInfo, {
......@@ -197,7 +242,7 @@ export default {
remark,
type,
status,
banner: 'banner',
banner: type == 1 ? JSON.stringify(goodsBanner) : JSON.stringify([]),
}));
yield put({
type: 'updateState',
......@@ -215,6 +260,8 @@ export default {
payload: {
editCouponModalShow: false,
editGoodsModalShow: false,
couponImg: '',
goodsBanner: [],
},
});
if (callBack && (typeof callBack == 'function')) {
......@@ -231,6 +278,7 @@ export default {
},
* integralModelGoodEdit({ payload }, { call, put, select }) {
const { record } = payload;
console.log(record, 'record');
if (record.type == 1) {
yield put({
type: 'updateState',
......@@ -327,6 +375,16 @@ export default {
},
});
},
* updateGoodBanner({ payload }, { call, put, select }) {
const { avatar } = payload;
console.log(avatar, 'avatar商品');
yield put({
type: 'updateState',
payload: {
goodsBanner: avatar,
},
});
},
* pageInit({ payload }, { call, put, select }) {
yield put({
type: 'updateState',
......@@ -334,40 +392,168 @@ export default {
sid: 0,
goodslist: [],
editCourseModalShow: false,
editGoodsModalShow: false,
editCouponInfo: {
id: 0,
title: '',
cover: '',
price: 0,
inventory: 0,
},
editGoodsInfo: {
id: 0,
title: '',
cover: '',
price: 0,
inventory: 0,
banner: [],
},
},
});
},
* handleSubmit({ payload }, { call, put, select }) {
const { type1 } = yield select(state => state.integral);
const {
type1, type2,
type3,
type4,
type5,
type6,
type7,
type8,
type9, ruleLoading, ruleList,
} = yield select(state => state.integral);
console.log(type9, 'type9');
const { sid } = yield select(state => state.webapp);
console.log(type1);
if (ruleLoading) {
return;
}
yield put({
type: 'updateState',
payload: {
ruleLoading: true,
},
});
if (!sid) {
return;
}
const loadmessage = message.loading('数据保存中...', 0);
const data = {
1: {
single: type1.single || 0,
day_limit: type1.day_limit || 0,
daily_limit: type1.daily_limit || 0,
school_id: sid,
},
2: {
single: type2.single || 0,
daily_limit: type2.daily_limit || 0,
school_id: sid,
},
3: {
single: type3.single || 0,
daily_limit: type3.daily_limit || 0,
school_id: sid,
},
4: {
single: type4.single || 0,
daily_limit: type4.daily_limit || 0,
school_id: sid,
},
5: {
single: type5.single || 0,
daily_limit: type5.daily_limit || 0,
school_id: sid,
},
6: {
single: type6.single || 0,
daily_limit: type6.daily_limit || 0,
school_id: sid,
},
7: {
single: type7.single || 0,
daily_limit: type7.daily_limit || 0,
school_id: sid,
},
8: {
single: type8.single || 0,
daily_limit: type8.daily_limit || 0,
school_id: sid,
},
9: {
single: type9.single || 0,
daily_limit: type9.daily_limit || 0,
school_id: sid,
},
// 2: type2,
};
console.log(data, 'data');
const newData = JSON.parse(JSON.stringify(data));
console.log(newData, 'newData');
const postFunction = ruleList && ruleList.length > 0 ? goodsAjax.ruleEdit : goodsAjax.ruleAdd;
const ruleData = yield call(postFunction, { data: JSON.stringify(newData) });
yield put({
type: 'updateState',
payload: {
ruleLoading: false,
},
});
setTimeout(loadmessage);
if (ruleData.code == 200) {
yield put({
type: 'updateState',
payload: {
},
});
yield put({
type: 'integralModelRuleList',
payload: {
},
});
} else {
yield put({
type: 'webapp/errorrequestresolve',
payload: {
data: ruleData,
},
});
}
// yield put(routerRedux.push({
// pathname: '/sjd/integralmanage',
// }));
},
* integralModelRuleList({ payload }, { call, put, select }) {
const { sid } = yield select(state => state.webapp);
const loadmessage = message.loading('数据加载中...', 0);
const rulelistinfo = yield call(goodsAjax.ruleSelect, {
school_id: sid,
});
setTimeout(loadmessage);
if (rulelistinfo.code == 200) {
yield put({
type: 'updateState',
payload: {
sid,
ruleList: rulelistinfo.data && rulelistinfo.data.list,
},
});
const ruleList = rulelistinfo.data.list;
for (let i = 0; i < ruleList.length; i++) {
yield put({
type: 'updateState',
payload: {
[`type${ruleList[i].type}`]: {
daily_limit: ruleList[i].daily_limit,
single: ruleList[i].single,
checked: ruleList[i].single > 0,
unlimited: ruleList[i].daily_limit > -1 ? 0 : -1,
},
},
});
}
console.log(ruleList, 'ruleList');
} else {
yield put({
type: 'webapp/errorrequestresolve',
payload: {
data: rulelistinfo,
},
});
}
},
* valueChange({ payload }, { call, put, select }) {
const state = yield select(state => state.integral);
const { value, index, key } = payload;
console.log(payload, 'payload');
// ley typevalue = state[]
// ley typevalue = state[]
// console.log({
......
......@@ -171,6 +171,9 @@ export default {
const {
bannerImg, course, orgdescs,
} = yield select(state => state.officialweb);
const {
goodsBanner,
} = yield select(state => state.integral);
const {
cropperUrl, filename, uploadtype, orgType, orgIndex, imgIndex, action,
} = yield select(state => state.uploader);
......@@ -235,6 +238,15 @@ export default {
avatar: `${filename}?x-oss-process=${cropperUrl}`,
},
});
} else if (uploadtype == 'goodBannerupload') {
const newbannerImg = JSON.parse(JSON.stringify(goodsBanner));
newbannerImg.push(`${filename}?x-oss-process=${cropperUrl}`);
yield put({
type: 'integral/updateGoodBanner',
payload: {
avatar: newbannerImg,
},
});
}
},
* unloadstates({ payload }, { call, put }) { // 释放该页面存储的所有状态
......
......@@ -525,6 +525,12 @@ export default {
payload: {
},
});
dispatch({
type: 'integral/integralModelRuleList',
payload: {
},
});
dispatch({
type: 'webapp/updateState',
payload: {
......
......@@ -44,6 +44,15 @@ class ClassMgtForm extends React.Component {
},
});
}
integralCancel=(modalVisible) => {
const { dispatch, form } = this.props;
dispatch({
type: 'integral/updateState',
payload: {
editScoreVisible: modalVisible,
},
});
}
handleScoreSubmit = (e) => {
const { dispatch, form, handleScoreCancel } = this.props;
e.preventDefault();
......@@ -106,12 +115,13 @@ class ClassMgtForm extends React.Component {
visible={editScoreVisible}
title="积分变动"
okText="保存"
onCancel={() => this.integralBtn(false)}
onCancel={() => this.integralCancel(false)}
onOk={this.handleScoreSubmit}
confirmLoading={courseSubmiting}
centered
width={586}
destroyOnClose
maskClosable={false}
>
<Form labelAlign="left">
<FormItem {...formItemModalLineLayout} label="学员">
......
......@@ -45,8 +45,56 @@
display: flex;
align-items: center;
margin-top: 15px;
.formflex {
.formflex,.formflex1 {
display: flex;
align-items: center;
.number {
border: 1px solid #D9D9D9;
width: 40px;
height: 24px;
line-height: 24px;
}
.numberActive {
border: 1px solid red;
width: 56px;
height: 32px;
line-height: 32px;
}
.switch {
width: 40px;
height: 24px;
background-color: #E5E5E5;
border-radius: 4px;
font-size: 12px;
color: #5E5E5E;
line-height: 24px;
text-align: center;
}
.switchActive {
background-color: #1890FF;
width: 56px;
height: 32px;
border-radius: 4px;
font-size: 14px;
color: #fff;
line-height: 32px;
text-align: center;
}
.sprit {
padding: 0 15px;
}
}
}
.formflex1 :global {
.ant-input-number {
width: 40px;
height: 24px;
line-height: 24px;
}
.ant-input-number-input {
width: 40px;
height: 24px;
line-height: 24px;
}
}
......@@ -12,7 +12,6 @@ class StoreMgt extends React.Component {
}
changePagination = (page, perPage) => {
console.log(page, perPage);
const { dispatch } = this.props;
dispatch({
type: 'integral/paginationchange',
......@@ -24,10 +23,23 @@ class StoreMgt extends React.Component {
},
});
}
sizeChange = (page, perPage) => {
const { dispatch } = this.props;
dispatch({
type: 'integral/paginationchange',
payload: {
params: {
page: 1,
perPage,
},
},
});
}
render() {
const {
recordList,
recordListTotal,
classListQueryParams,
} = this.props;
console.log(recordList);
const columns = [
......@@ -70,7 +82,6 @@ class StoreMgt extends React.Component {
onShowSizeChange={this.sizeChange}
total={Number(recordListTotal)}
onChange={this.changePagination}
/>
</div>
)}
......@@ -88,12 +99,14 @@ function mapStateToProps(state) {
editCouponModalShow,
classSubmitting,
recordListTotal,
classListQueryParams,
} = state.integral;
return {
recordList,
editCouponModalShow,
classSubmitting,
recordListTotal,
classListQueryParams,
};
}
export default connect(mapStateToProps)(StoreMgt);
......
.container {
background-color: #fff;
padding: 24px 0 0;
padding: 0;
position: relative;
overflow-y: hidden;
}
.tablebox {
padding: 20px 0;
background: #fff;
}
......@@ -29,7 +29,7 @@ class CouponAddModal extends React.Component {
const {
form, save, editCouponInfo, couponImg,
} = this.props;
console.log(couponImg, 'couponImg');
console.log(this.props, 'this.props');
if (editCouponInfo.id == 0 && (couponImg == '' || couponImg == undefined)) {
message.error('请上传卡券封面', 0.5);
return;
......
import { connect } from 'dva';
import React from 'react';
import PropTypes from 'prop-types';
import { message, Row, Col, Input, Select, Modal, Form, InputNumber } from 'antd';
import { message, Row, Col, Input, Select, Modal, Form, InputNumber, Carousel } from 'antd';
import { imagify, pageIn } from '../../../utils/index';
import pageStyle from './GoodsAddModal.less';
const { Option } = Select;
......@@ -25,7 +25,7 @@ class GoodsAddModal extends React.Component {
}
save = () => {
const {
form, save, editCouponInfo, couponImg,
form, save, editCouponInfo, couponImg, goodsBanner,
} = this.props;
if (editCouponInfo.id == 0 && (couponImg == '' || couponImg == undefined)) {
message.error('请上传卡券封面', 0.5);
......@@ -70,16 +70,24 @@ class GoodsAddModal extends React.Component {
uploadtype: 'goodsAvatorupload',
});
}
uploadBanner = (e) => {
const { uploadBanner, goodsBanner } = this.props;
uploadBanner({
files: e.target,
uploadtype: 'goodBannerupload',
});
};
render() {
const {
visible,
isEdit,
couponImg,
uploadAvator,
uploadBanner,
editCouponInfo,
goodsBanner,
form: { getFieldDecorator, getFieldValue },
} = this.props;
console.log(this.props);
const { classRoomId, title } = this.state;
const formItemModalLineLayout = {
labelCol: {
......@@ -91,6 +99,14 @@ class GoodsAddModal extends React.Component {
sm: { span: 18 },
},
};
const settings = {
dots: true,
infinite: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1,
arrows: true,
};
return (
<Modal
visible={visible}
......@@ -132,14 +148,42 @@ class GoodsAddModal extends React.Component {
sm: { span: 24 },
}}
>
<div className={pageStyle.banner}>
<img className={pageStyle.avatar} src={imagify(couponImg) ? imagify(couponImg) : imagify(editCouponInfo.cover)} alt="" />
<span className={pageStyle.uploadThumb}>
<input type="file" id="uploadinput" className={pageStyle.fileuploadinput} onChange={(e) => { this.uploadAvator(e); }} accept="image/*" />
{
editCouponInfo.banner.length > 0 ?
<div className={pageStyle.banner}>
<div className={pageStyle.bannerBox}>
<Carousel>
{ editCouponInfo.banner.length > 0 && (JSON.parse(editCouponInfo.banner)).map((item, index) => (
<div>
<img className={pageStyle.avatar} src={imagify(item)} alt="" />
</div>
))}
</Carousel>,
</div>
<span className={pageStyle.uploadThumb}>
<input type="file" id="uploadinput" className={pageStyle.fileuploadinput} onChange={(e) => { this.uploadBanner(e); }} accept="image/*" />
新增图片
</span>
<div className={pageStyle.thumbTip}><span>建议尺寸:750*310 最多上传4 </span></div>
</div>
</span>
<div className={pageStyle.thumbTip}><span>建议尺寸:750*310 最多上传4 </span></div>
</div> :
<div className={pageStyle.banner}>
<div className={pageStyle.bannerBox}>
<Carousel>
{ goodsBanner.map((item, index) => (
<div>
<img className={pageStyle.avatar} src={imagify(item)} alt="" />
</div>
))}
</Carousel>,
</div>
<span className={pageStyle.uploadThumb}>
<input type="file" id="uploadinput" className={pageStyle.fileuploadinput} onChange={(e) => { this.uploadBanner(e); }} accept="image/*" />
新增图片
</span>
<div className={pageStyle.thumbTip}><span>建议尺寸:750*310 最多上传4 </span></div>
</div>
}
</FormItem>
{getFieldDecorator('type', { initialValue: 1 })(<Input type="hidden" />)}
{getFieldDecorator('status', { initialValue: 1 })(<Input type="hidden" />)}
......
......@@ -18,6 +18,12 @@
margin-right: 30px;
}
}
.bannerBox {
width: 223px;
height: 92px;
background-color: #D8D8D8;
margin-right: 30px;
}
.banner {
display: flex;
position: relative;
......@@ -69,4 +75,11 @@
margin-bottom: 20px;
}
}
.ant-carousel .slick-slide {
text-align: center;
height: 92px;
overflow: hidden;
background-color: #D8D8D8;
}
}
......@@ -57,6 +57,7 @@ class StoreMgt extends React.Component {
content: '删除后不可恢复,请谨慎操作!',
okText: '确定',
cancelText: '取消',
icon: <Icon type="close-circle" style={{ color: 'red' }} />,
onOk() {
dispatch({
type: 'integral/integralModelDelete',
......@@ -72,6 +73,14 @@ class StoreMgt extends React.Component {
},
});
},
okButtonProps: {
type: 'danger',
style: {
color: '#fff',
backgroundColor: '#ff4d4f',
borderColor: '#ff4d4f',
},
},
});
};
addGoods=() => {
......@@ -89,6 +98,7 @@ class StoreMgt extends React.Component {
cover: '',
price: 0,
inventory: 0,
banner: [],
},
},
});
......@@ -108,6 +118,7 @@ class StoreMgt extends React.Component {
cover: '',
price: 0,
inventory: 0,
banner: [],
},
},
});
......@@ -136,6 +147,7 @@ class StoreMgt extends React.Component {
cover: '',
price: 0,
inventory: 0,
banner: [],
},
},
});
......@@ -152,6 +164,7 @@ class StoreMgt extends React.Component {
cover: '',
price: 0,
inventory: 0,
banner: [],
},
},
});
......@@ -167,6 +180,17 @@ class StoreMgt extends React.Component {
},
});
}
uploadBanner = ({ files, uploadtype }) => {
const { dispatch } = this.props;
dispatch({
type: 'uploader/queryimgsignature',
payload: {
files,
avatorUploader: this.state.avatorUploader,
uploadtype,
},
});
}
getCropperUrl = (url) => {
const { dispatch } = this.props;
dispatch({
......@@ -208,6 +232,7 @@ class StoreMgt extends React.Component {
couponImg,
editCouponInfo,
editGoodsModalShow,
goodsBanner,
} = this.props;
const {
previewVisible, previewImage, isEdit, type,
......@@ -267,9 +292,9 @@ class StoreMgt extends React.Component {
];
return (
<div className={pageStyle.container}>
<Row>
<Col span={2}> <Button onClick={this.addCoupon} type="primary"><Icon type="credit-card" />添加卡券</Button></Col>
<Col span={2}> <Button onClick={() => this.addGoods()} type="primary"><Icon type="shopping" />添加商品</Button></Col>
<Row gutter={16}>
<Col xs={10} sm={8} md={6} lg={4} xl={3}> <Button onClick={this.addCoupon} type="primary"><Icon type="credit-card" />添加卡券</Button></Col>
<Col xs={10} sm={8} md={6} lg={4} xl={3}> <Button onClick={() => this.addGoods()} type="primary"><Icon type="shopping" />添加商品</Button></Col>
</Row>
<div className={pageStyle.tablebox}>
<Table
......@@ -303,13 +328,17 @@ class StoreMgt extends React.Component {
close={this.closeGoodsModal}
save={this.save}
uploadAvator={this.uploadAvator}
uploadBanner={this.uploadBanner}
couponImg={couponImg}
goodsBanner={goodsBanner}
editCouponInfo={editCouponInfo}
/>
{cropperboxShow && <Cropper
avatorUploader={this.state.avatorUploader}
cancelCropper={this.cancelCropper}
getCropperUrl={this.getCropperUrl}
uploadAvator={this.uploadAvator}
uploadBanner={this.uploadBanner}
sureCropper={this.sureCropper}
uploadImgUrl={uploadImgUrl}
/>}
......@@ -332,6 +361,7 @@ function mapStateToProps(state) {
studentSubmiting,
couponImg,
editGoodsModalShow,
goodsBanner,
} = state.integral;
return {
goodsList,
......@@ -343,6 +373,7 @@ function mapStateToProps(state) {
couponImg,
editCouponInfo,
editGoodsModalShow,
goodsBanner,
};
}
export default connect(mapStateToProps)(StoreMgt);
......
......@@ -49,4 +49,28 @@ export function goodsAdd(params) {
data,
});
}
export function ruleAdd(params) {
const data = qs.stringify(params);
return request({
url: `${api.integralsetting.integralRulesAdd}`,
method: 'POST',
data,
});
}
export function ruleEdit(params) {
const data = qs.stringify(params);
return request({
url: `${api.integralsetting.integralRulesEdit}`,
method: 'POST',
data,
});
}
export function ruleSelect(parmas) {
const data = qs.stringify(parmas);
return request({
url: `${api.integralsetting.integralRulesList}?${data}`,
method: 'GET',
data,
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment