From e05f19ddc6d4cc197a73357cc7e16ac4d0e7c009 Mon Sep 17 00:00:00 2001 From: YunaiV <> Date: Thu, 2 May 2019 12:47:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=AB=AF=EF=BC=9A=E5=95=86=E5=93=81?= =?UTF-8?q?=E7=BC=96=E8=BE=91=EF=BC=8C=E9=83=A8=E5=88=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin-web/config/router.config.js | 5 + .../src/components/Image/PicturesWall.js | 3 + admin-web/src/locales/zh-CN/menu.js | 1 + .../src/models/product/productAttrList.js | 4 +- .../models/product/productSpuAddOrUpdate.js | 155 ++++++++--- .../src/models/product/productSpuList.js | 5 + .../pages/Product/ProductSpuAddOrUpdate.js | 251 +++++++----------- admin-web/src/pages/Product/ProductSpuList.js | 11 +- admin-web/src/services/product.js | 6 + 9 files changed, 243 insertions(+), 198 deletions(-) diff --git a/admin-web/config/router.config.js b/admin-web/config/router.config.js index b3e1c1e9d..0c6b6cbd2 100644 --- a/admin-web/config/router.config.js +++ b/admin-web/config/router.config.js @@ -92,6 +92,11 @@ export default [ name: 'product-spu-add', component: './Product/ProductSpuAddOrUpdate', }, + { + path: '/product/product-spu-update', + name: 'product-spu-update', + component: './Product/ProductSpuAddOrUpdate', + }, { path: '/product/product-category-list', name: 'product-category-list', diff --git a/admin-web/src/components/Image/PicturesWall.js b/admin-web/src/components/Image/PicturesWall.js index c7c93663c..3e188dfe7 100644 --- a/admin-web/src/components/Image/PicturesWall.js +++ b/admin-web/src/components/Image/PicturesWall.js @@ -6,6 +6,9 @@ import {Icon, Modal, Upload} from "antd"; import styles from './PicturesWall.less'; +/** + * 照片墙,带有上传图片到七牛。 + */ class PicturesWall extends React.Component { state = { token: undefined, // 七牛 token diff --git a/admin-web/src/locales/zh-CN/menu.js b/admin-web/src/locales/zh-CN/menu.js index a41d8e51a..339bd0ca4 100644 --- a/admin-web/src/locales/zh-CN/menu.js +++ b/admin-web/src/locales/zh-CN/menu.js @@ -48,6 +48,7 @@ export default { 'menu.product': '商品管理', 'menu.product.product-spu-list': '商品管理', 'menu.product.product-spu-add': '商品添加', + 'menu.product.product-spu-update': '商品编辑', 'menu.product.product-category-list': '商品分类', // 订单 'menu.order': '订单管理', diff --git a/admin-web/src/models/product/productAttrList.js b/admin-web/src/models/product/productAttrList.js index f4b00059e..034187b7c 100644 --- a/admin-web/src/models/product/productAttrList.js +++ b/admin-web/src/models/product/productAttrList.js @@ -1,5 +1,5 @@ import { message } from 'antd'; -import { productSpuPage, productAttrTree, productCategoryUpdate, productCategoryUpdateStatus, productCategoryDelete } from '../../services/product'; +import { productAttrTree } from '../../services/product'; export default { namespace: 'productAttrList', @@ -54,7 +54,7 @@ export default { *tree({ payload }, { call, put }) { const { queryParams } = payload; const response = yield call(productAttrTree, queryParams); - message.info('查询成功!'); + // message.info('查询成功!'); yield put({ type: 'treeSuccess', payload: { diff --git a/admin-web/src/models/product/productSpuAddOrUpdate.js b/admin-web/src/models/product/productSpuAddOrUpdate.js index 6ceaa56e7..c4aacc8de 100644 --- a/admin-web/src/models/product/productSpuAddOrUpdate.js +++ b/admin-web/src/models/product/productSpuAddOrUpdate.js @@ -1,12 +1,24 @@ import { message } from 'antd'; -import { productCategoryTree, productSpuAdd, productCategoryUpdate, productCategoryUpdateStatus, productCategoryDelete } from '../../services/product'; +import { + productCategoryTree, + productSpuAdd, + productCategoryUpdate, + productCategoryUpdateStatus, + productCategoryDelete, + productSpuInfo +} from '../../services/product'; export default { namespace: 'productSpuAddOrUpdate', state: { - list: [], - attrTree: [ + // list: [], + loading: false, + spu: { // 商品 SPU + + }, + + attrTree: [ // 商品规格 // { // id: // // name: // @@ -16,7 +28,7 @@ export default { // }] // } ], - skus: [ + skus: [ // 商品 SKU // { // attrs: [{ // id: // 规格值编号 @@ -29,17 +41,6 @@ export default { }, effects: { - // *add({ payload }, { call, put }) { - // const { callback, body } = payload; - // const response = yield call(productCategoryAdd, body); - // if (callback) { - // callback(response); - // } - // yield put({ - // type: 'tree', - // payload: {}, - // }); - // }, // *update({ payload }, { call, put }) { // const { callback, body } = payload; // const response = yield call(productCategoryUpdate, body); @@ -51,25 +52,87 @@ export default { // payload: {}, // }); // }, - // *updateStatus({ payload }, { call, put }) { - // const { callback, body } = payload; - // const response = yield call(productCategoryUpdateStatus, body); - // if (callback) { - // callback(response); - // } - // yield put({ - // type: 'tree', - // payload: {}, - // }); - // }, - // *delete({ payload }, { call, put }) { - // const response = yield call(productCategoryDelete, payload); - // message.info('删除成功!'); - // yield put({ - // type: 'tree', - // payload: {}, - // }); - // }, + *info({ payload }, { call, put }) { + // 显示加载中 + yield put({ + type: 'changeLoading', + payload: true, + }); + + // 请求 + const response = yield call(productSpuInfo, { + id: payload, + }); + // 响应 + let skus = []; + let attrTree = []; + // SKU + for (let i in response.data.skus) { + let sku = response.data.skus[i]; + // 处理 sku + { + let attrs = []; + for (let j in sku.attrs) { + let attr = sku.attrs[j]; + attrs.push({ + id: attr.attrValueId, + name: attr.attrValueName, + }); + } + let newSku = { + ...sku, + attrs, + }; + skus.push(newSku); + } + // 处理 attrTree + { + for (let j in sku.attrs) { + // debugger; + let attr = sku.attrs[j]; + let attrTreeNode = undefined; + for (let k in attrTree) { + let item = attrTree[k]; + if (item.id === attr.attrId) { + attrTreeNode = item; + break; + } + } + if (!attrTreeNode) { + attrTreeNode = { + id: attr.attrId, + name: attr.attrName, + values: [{ + id: attr.attrValueId, + name: attr.attrValueName, + }] + }; + attrTree.push(attrTreeNode); + } else { + // let values = attrTreeNode.values; + // for (let k in ) { + // + // } + } + } + } + } + // debugger; + yield put({ + type: 'setAll', + payload: { + spu: response.data, + skus: skus, + attrTree: attrTree, + }, + }); + + // 隐藏加载中 + yield put({ + type: 'changeLoading', + payload: false, + }); + }, *addAttr({ payload }, { call, put }) { // const { queryParams } = payload; // const response = yield call(productCategoryTree, queryParams); @@ -212,11 +275,31 @@ export default { ...state } }, - treeSuccess(state, { payload }) { + clear(state, {payload}) { + return { + ...state, + skus: [], + attrTree: [], + } + }, + changeLoading(state, { payload }) { + return { + ...state, + listLoading: payload, + }; + }, + // 设置所有属性 + setAll(state, { payload }) { return { ...state, ...payload, }; - }, + } + // treeSuccess(state, { payload }) { + // return { + // ...state, + // ...payload, + // }; + // }, }, }; diff --git a/admin-web/src/models/product/productSpuList.js b/admin-web/src/models/product/productSpuList.js index e816bf087..77b1c1811 100644 --- a/admin-web/src/models/product/productSpuList.js +++ b/admin-web/src/models/product/productSpuList.js @@ -55,6 +55,11 @@ export default { // const { callback, body } = payload; yield put(routerRedux.replace('/product/product-spu-add')); }, + *redirectToUpdate({ payload }, { call, put }) { + // const { callback, body } = payload; + debugger; + yield put(routerRedux.replace('/product/product-spu-update?id=' + payload)); + }, *page({ payload }, { call, put }) { // const { queryParams } = payload; const response = yield call(productSpuPage, payload); diff --git a/admin-web/src/pages/Product/ProductSpuAddOrUpdate.js b/admin-web/src/pages/Product/ProductSpuAddOrUpdate.js index 1417f79e0..699ebf7ff 100644 --- a/admin-web/src/pages/Product/ProductSpuAddOrUpdate.js +++ b/admin-web/src/pages/Product/ProductSpuAddOrUpdate.js @@ -5,7 +5,7 @@ import React, {PureComponent, Fragment, Component} from 'react'; // import fs from 'fs'; import { connect } from 'dva'; import moment from 'moment'; -import {Card, Form, Input, Radio, Button, Modal, Select, Upload, Icon} from 'antd'; +import {Card, Form, Input, Radio, Button, Modal, Select, Upload, Icon, Spin} from 'antd'; import PageHeaderWrapper from '@/components/PageHeaderWrapper'; // import * as qiniu from 'qiniu-js' @@ -14,7 +14,7 @@ import PageHeaderWrapper from '@/components/PageHeaderWrapper'; import styles from './ProductSpuAddOrUpdate.less'; import ProductAttrSelectFormItem from "../../components/Product/ProductAttrSelectFormItem"; import ProductSkuAddOrUpdateTable from "../../components/Product/ProductSkuAddOrUpdateTable"; -import {fileGetQiniuToken} from "../../services/admin"; +// import {fileGetQiniuToken} from "../../services/admin"; import PicturesWall from "../../components/Image/PicturesWall"; const FormItem = Form.Item; @@ -22,12 +22,14 @@ const RadioGroup = Radio.Group; const Option = Select.Option; // roleList -@connect(({ productSpuList, productAttrList, productSpuAddOrUpdate, loading }) => ({ +@connect(({ productAttrList, productSpuAddOrUpdate, }) => ({ // list: productSpuList.list.spus, // loading: loading.models.productSpuList, productAttrList, productSpuAddOrUpdate, allAttrTree: productAttrList.tree, + loading: productSpuAddOrUpdate.loading, + spu: productSpuAddOrUpdate.spu, attrTree: productSpuAddOrUpdate.attrTree, skus: productSpuAddOrUpdate.skus, })) @@ -35,15 +37,26 @@ const Option = Select.Option; @Form.create() class ProductSpuAddOrUpdate extends Component { state = { - modalVisible: false, + // modalVisible: false, modalType: 'add', //add update - initValues: {}, - roleAssignVisible: false, - roleAssignRecord: {}, + // initValues: {}, }; componentDidMount() { const { dispatch } = this.props; + // 判断是否是更新 + const params = new URLSearchParams(this.props.location.search); + if (params.get("id")) { + let id = params.get("id"); + this.setState({ + modalType: 'update', + }) + dispatch({ + type: 'productSpuAddOrUpdate/info', + payload: parseInt(id), + }) + } + // 获得规格列表 dispatch({ type: 'productAttrList/tree', payload: { @@ -52,6 +65,10 @@ class ProductSpuAddOrUpdate extends Component { pageSize: 10, }, }); + // 重置表单 + dispatch({ + type: 'productSpuAddOrUpdate/clear', + }) } handleAddAttr = e => { @@ -62,7 +79,7 @@ class ProductSpuAddOrUpdate extends Component { payload: { }, }); - } + }; handleSubmit = e => { e.preventDefault(); @@ -110,59 +127,11 @@ class ProductSpuAddOrUpdate extends Component { } }); // console.log(fields); - } - - // handleSelectAttr = (value, option) => { - // // console.log(value); - // // console.log(option); - // // debugger; - // const { dispatch } = this.props; - // let attrIndex = option.key.substring(option.key.indexOf('option-attr-') + 'option-attr-'.length, option.key.lastIndexOf('-')); - // // console.log('attrIndex: ' + attrIndex); - // // debugger; - // dispatch({ - // type: 'productSpuAddOrUpdate/selectAttr', - // payload: { - // attrIndex: attrIndex, - // attr: { - // id: option.props.value, - // name: option.props.children, - // values: [] - // } - // }, - // }); - // } - // - // handleSelectAttrValue = (values, options) => { - // let attrValues = []; - // const { dispatch } = this.props; - // debugger; - // // console.log('x' + this.children[0]); - // let firstOption = this.children[0]; - // // let attrIndex = firstOption.key.substring(firstOption.key.indexOf('option-attr-value-') + 'option-attr-value-'.length, firstOption.key.lastIndexOf('-')); - // let attrIndex = 0; - // for (let i in options) { - // let option = options[i]; - // attrValues.push({ - // id: parseInt(option.props.value), - // name: option.props.children, - // }); - // } - // dispatch({ - // type: 'productSpuAddOrUpdate/selectAttrValues', - // payload: { - // attrIndex: attrIndex, - // attrValues: attrValues, - // }, - // }); - // // debugger; - // - // // console.log(value); - // } + }; render() { // debugger; - const { form, skus, attrTree, allAttrTree, dispatch } = this.props; + const { form, skus, attrTree, allAttrTree, loading, spu, dispatch } = this.props; // const that = this; // 添加规格 @@ -188,47 +157,7 @@ class ProductSpuAddOrUpdate extends Component { attrTreeHTML.push(); } } - // if (attrTree && attrTree.length > 0) { - // for (let i in attrTree) { - // let attr = attrTree[i]; - // // console.log('i: ' + i); - // // 1. 规格 - // let attrOptions = []; - // for (let j in allAttrTree) { - // let attr = allAttrTree[j]; - // attrOptions.push(); - // } - // // 2. 规格值 - // let attrValueOptions = []; - // // debugger; - // if (attr.id) { - // // 2.1 先招到规格值的数组 - // let attrValues = []; - // for (let j in allAttrTree) { - // let allAttr = allAttrTree[j]; - // if (attr.id === allAttr.id) { - // attrValues = allAttr.values; - // break; - // } - // } - // // 2.2 生成规格值的 HTML - // for (let j in attrValues) { - // let attrValue = attrValues[j]; - // attrValueOptions.push(); // + '' 的原因是,多选必须是字符串 - // } - // } - // // 3. 拼装最终,添加到 attrTreeHTML 中 - // attr =
- // - // - //
; - // attrTreeHTML.push(attr); - // } - // } + // 规格明细 let productSkuProps = { attrTree: attrTree, @@ -239,66 +168,70 @@ class ProductSpuAddOrUpdate extends Component { return ( - -
- - {form.getFieldDecorator('name', { - rules: [{ required: true, message: '请输入商品名!', min: 2 }], - initialValue: '', // TODO 修改 - })()} - - - {form.getFieldDecorator('sellPoint', { - rules: [{ required: true, message: '请输入商品卖点!' }], - initialValue: '', // TODO 修改 - })()} - - - {form.getFieldDecorator('cid', { - rules: [{ required: true, message: '请输入分类编号!' }], - initialValue: '', // TODO 修改 // TODO 芋艿,和面做成下拉框 - })()} - - - {/*{form.getFieldDecorator('picUrls', {*/} - {/* initialValue: '', // TODO 修改 // TODO 芋艿,做成上传组件*/} - {/*})()}*/} - - - - {form.getFieldDecorator('visible', { - initialValue: 1, // TODO 修改 - })( - - - - - )} - - - {form.getFieldDecorator('visible', { - initialValue: 1, // TODO 修改 - })( -
- {attrTreeHTML} - -
- )} -
- - {/**/} - - - - {form.getFieldDecorator('description', { - rules: [{ required: true, message: '请输入商品描述!' }], - initialValue: '', // TODO 修改 - })()} - - - - + + +
+ + {form.getFieldDecorator('name', { + rules: [{ required: true, message: '请输入商品名!', min: 2 }], + initialValue: spu.name, + })()} + + + {form.getFieldDecorator('sellPoint', { + rules: [{ required: true, message: '请输入商品卖点!' }], + initialValue: spu.sellPoint, + })()} + + + {form.getFieldDecorator('cid', { + rules: [{ required: true, message: '请输入分类编号!' }], + initialValue: spu.cid, // TODO 芋艿,和面做成下拉框 + })()} + + + {/*{form.getFieldDecorator('picUrls', {*/} + {/* initialValue: '', // TODO 修改 // TODO 芋艿,做成上传组件*/} + {/*})()}*/} + + + + {form.getFieldDecorator('visible', { + initialValue: spu.visible, + })( + + + + + )} + + + {form.getFieldDecorator('visible', { + initialValue: 1, // TODO 修改 + })( +
+ {attrTreeHTML} + +
+ )} +
+ { + attrTree.length > 0 ? + {/*
*/} + + : '' + } + + {form.getFieldDecorator('description', { + rules: [{ required: true, message: '请输入商品描述!' }], + initialValue: spu.description, // TODO 修改 + })()} + + + + + ); } diff --git a/admin-web/src/pages/Product/ProductSpuList.js b/admin-web/src/pages/Product/ProductSpuList.js index 5dcedfcc8..c90659bd4 100644 --- a/admin-web/src/pages/Product/ProductSpuList.js +++ b/admin-web/src/pages/Product/ProductSpuList.js @@ -47,6 +47,14 @@ class ProductSpuList extends PureComponent { }); }; + redirectToUpdate = (spuId) => { + const { dispatch } = this.props; + dispatch({ + type: 'productSpuList/redirectToUpdate', + payload: spuId, + }); + }; + render() { // debugger; const { list, data } = this.props; @@ -103,7 +111,8 @@ class ProductSpuList extends PureComponent { width: 200, render: (text, record) => ( - this.handleModalVisible(true, 'update', record)}>更新 + {/* this.handleModalVisible(true, 'update', record)}>更新*/} + this.redirectToUpdate(record.id)}>更新 ), }, diff --git a/admin-web/src/services/product.js b/admin-web/src/services/product.js index 624c1b8c3..271362f63 100644 --- a/admin-web/src/services/product.js +++ b/admin-web/src/services/product.js @@ -52,6 +52,12 @@ export async function productSpuAdd(params) { }); } +export async function productSpuInfo(params) { + return request(`/product-api/admins/spu/info?${stringify(params)}`, { + method: 'GET', + }); +} + // product attr + attr value export async function productAttrTree(params) {