diff --git a/admin-web/config/router.config.js b/admin-web/config/router.config.js index a058ce557..3bf367c03 100644 --- a/admin-web/config/router.config.js +++ b/admin-web/config/router.config.js @@ -125,6 +125,11 @@ export default [ name: 'product-brand-list', component: './Product/ProductBrandList', }, + { + path: '/product/product-attr-list', + name: 'product-attr-list', + component: './Product/ProductAttrList', + }, ], }, // promotion diff --git a/admin-web/src/locales/zh-CN/menu.js b/admin-web/src/locales/zh-CN/menu.js index 2dcf49161..0e9ef9d14 100644 --- a/admin-web/src/locales/zh-CN/menu.js +++ b/admin-web/src/locales/zh-CN/menu.js @@ -52,6 +52,8 @@ export default { 'menu.product.product-spu-update': '商品编辑', 'menu.product.product-category-list': '商品分类', 'menu.product.product-brand-list': '商品品牌', + 'menu.product.product-attr-list': '规格管理', + // 订单 'menu.order': '订单管理', 'menu.order.order-list': '订单管理', diff --git a/admin-web/src/models/admin/adminList.js b/admin-web/src/models/admin/adminList.js index c9c433ec7..95025b69f 100644 --- a/admin-web/src/models/admin/adminList.js +++ b/admin-web/src/models/admin/adminList.js @@ -1,5 +1,5 @@ -import {message} from 'antd'; -import {buildTreeNode, findCheckedKeys} from '../../utils/tree.utils'; +import { message } from 'antd'; +import { buildTreeNode, findCheckedKeys } from '../../utils/tree.utils'; import { addAdmin, adminRoleAssign, @@ -8,14 +8,30 @@ import { queryAdminRoleList, updateAdmin, updateAdminStatus, + deptTreeAll, } from '../../services/admin'; -import {arrayToStringParams} from '../../utils/request.qs'; +import { arrayToStringParams } from '../../utils/request.qs'; import PaginationHelper from '../../../helpers/PaginationHelper'; const SEARCH_PARAMS_DEFAULT = { nickname: '', }; +const buildSelectTree = list => { + return list.map(item => { + let children = []; + if (item.children) { + children = buildSelectTree(item.children); + } + return { + title: item.name, + value: `${item.name}-${item.id}`, + key: item.id, + children, + }; + }); +}; + export default { namespace: 'adminList', @@ -37,11 +53,22 @@ export default { roleModalVisible: false, roleCheckedKeys: [], // 此处的 Key ,就是角色编号 roleAssignLoading: false, + + //部门相关 + deptSelectTree: [], }, effects: { + *getDeptmentTree({ payload }, { call, put }) { + const result = yield call(deptTreeAll, payload); + yield put({ + type: 'treeSuccess', + payload: result.data, + }); + }, + // 查询列表 - * query({ payload }, { call, put }) { + *query({ payload }, { call, put }) { // 显示加载中 yield put({ type: 'changeListLoading', @@ -57,8 +84,8 @@ export default { list: response.data.list, pagination: PaginationHelper.formatPagination(response.data, payload), searchParams: { - nickname: payload.nickname || '' - } + nickname: payload.nickname || '', + }, }, }); @@ -68,7 +95,7 @@ export default { payload: false, }); }, - * add({ payload }, { call, put }) { + *add({ payload }, { call, put }) { // 显示加载中 yield put({ type: 'changeModalLoading', @@ -87,7 +114,7 @@ export default { yield put({ type: 'query', payload: { - ...PaginationHelper.defaultPayload + ...PaginationHelper.defaultPayload, }, }); } @@ -98,7 +125,7 @@ export default { payload: false, }); }, - * update({ payload }, { call, put }) { + *update({ payload }, { call, put }) { const { callback, body } = payload; // 显示加载中 yield put({ @@ -117,7 +144,7 @@ export default { yield put({ type: 'query', payload: { - ...PaginationHelper.defaultPayload + ...PaginationHelper.defaultPayload, }, }); } @@ -129,7 +156,7 @@ export default { }); }, - * updateStatus({ payload }, { call, put }) { + *updateStatus({ payload }, { call, put }) { // 请求 const response = yield call(updateAdminStatus, payload); // 响应 @@ -139,13 +166,13 @@ export default { yield put({ type: 'query', payload: { - ...PaginationHelper.defaultPayload + ...PaginationHelper.defaultPayload, }, }); } }, - * delete({ payload }, { call, put }) { + *delete({ payload }, { call, put }) { // 请求 const response = yield call(deleteAdmin, payload); // 响应 @@ -155,13 +182,13 @@ export default { yield put({ type: 'query', payload: { - ...PaginationHelper.defaultPayload + ...PaginationHelper.defaultPayload, }, }); } }, - * queryRoleList({ payload }, { call, put }) { + *queryRoleList({ payload }, { call, put }) { // 显示加载中 yield put({ type: 'changeRoleAssignLoading', @@ -191,7 +218,7 @@ export default { }); }, - * roleAssign({ payload }, { call, put }) { + *roleAssign({ payload }, { call, put }) { const { callback, body } = payload; // 显示加载中 yield put({ @@ -220,6 +247,27 @@ export default { }, reducers: { + treeSuccess(state, { payload }) { + const resultData = payload; + const treeData = buildSelectTree(resultData); + + // // value 要保护 displayName 不然,搜索会失效 + // const rootNode = [ + // { + // title: '根节点', + // value: `根节点-0`, + // key: 0, + // children: [], + // }, + // ]; + + // const deptSelectTree = rootNode.concat(treeData); + return { + ...state, + // list: resultData, + deptSelectTree: treeData, + }; + }, changeRoleCheckedKeys(state, { payload }) { return { ...state, @@ -251,6 +299,6 @@ export default { ...state, ...payload, }; - } + }, }, }; diff --git a/admin-web/src/models/admin/deptmentList.js b/admin-web/src/models/admin/deptmentList.js index ab44614ea..b659beca0 100644 --- a/admin-web/src/models/admin/deptmentList.js +++ b/admin-web/src/models/admin/deptmentList.js @@ -1,5 +1,11 @@ import { message } from 'antd'; -import { deptTreePage, deptTreeAll, addDeptment, updateDeptment } from '../../services/admin'; +import { + deptTreePage, + deptTreeAll, + addDeptment, + updateDeptment, + deleteDeptment, +} from '../../services/admin'; const buildSelectTree = list => { return list.map(item => { @@ -35,6 +41,13 @@ export default { onSuccess && onSuccess(); } }, + *delete({ payload }, { call, put }) { + const { onSuccess, body } = payload; + const response = yield call(deleteDeptment, body); + if (response && response.code === 0) { + onSuccess && onSuccess(); + } + }, *update({ payload }, { call, put }) { const { onSuccess, body } = payload; const response = yield call(updateDeptment, body); diff --git a/admin-web/src/models/product/productAttrList.js b/admin-web/src/models/product/productAttrList.js index 54ffaf64c..80405882d 100644 --- a/admin-web/src/models/product/productAttrList.js +++ b/admin-web/src/models/product/productAttrList.js @@ -1,36 +1,76 @@ import { message } from 'antd'; -import { productAttrTree, productAttrValueAdd } from '../../services/product'; +import { + productAttrTree, + productAttrValueAdd, + productAttrPage, + productAttrAdd, + productAttrUpdate, + productAttrUpdateStatus, + productAttrValueUpdate, + productAttrValueUpdateStatus, +} from '../../services/product'; +import PaginationHelper from '../../../helpers/PaginationHelper'; export default { namespace: 'productAttrList', state: { list: [], + // tree: [], + attrData: [], + pagination: PaginationHelper.defaultPaginationConfig, }, 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); - // if (callback) { - // callback(response); - // } - // yield put({ - // type: 'tree', - // payload: {}, - // }); - // }, + *add({ payload }, { call, put }) { + const { onSuccess, onFail, body } = payload; + const response = yield call(productAttrAdd, body); + if (response && response.code === 0) { + onSuccess && onSuccess(); + } else { + onFail && onFail(response); + } + }, + + *update({ payload }, { call, put }) { + const { onSuccess, onFail, body } = payload; + const response = yield call(productAttrUpdate, body); + if (response && response.code === 0) { + onSuccess && onSuccess(); + } else { + onFail && onFail(response); + } + }, + + *value_update({ payload }, { call, put }) { + const { onSuccess, onFail, body } = payload; + const response = yield call(productAttrValueUpdate, body); + if (response && response.code === 0) { + onSuccess && onSuccess(); + } else { + onFail && onFail(response); + } + }, + + *update_status({ payload }, { call, put }) { + const { onSuccess, onFail, body } = payload; + const response = yield call(productAttrUpdateStatus, body); + if (response && response.code === 0) { + onSuccess && onSuccess(); + } else { + onFail && onFail(response); + } + }, + + *value_update_status({ payload }, { call, put }) { + const { onSuccess, onFail, body } = payload; + const response = yield call(productAttrValueUpdateStatus, body); + if (response && response.code === 0) { + onSuccess && onSuccess(); + } else { + onFail && onFail(response); + } + }, // *updateStatus({ payload }, { call, put }) { // const { callback, body } = payload; // const response = yield call(productCategoryUpdateStatus, body); @@ -51,6 +91,21 @@ export default { // }); // }, + *page({ payload }, { call, put }) { + const result = yield call(productAttrPage, payload); + let attrData = {}; + if (result.code === 0) { + attrData = result.data; + } + yield put({ + type: 'save', + payload: { + attrData, + pagination: PaginationHelper.formatPagination(attrData, payload), + }, + }); + }, + *tree({ payload }, { call, put }) { const { queryParams } = payload; const response = yield call(productAttrTree, queryParams); @@ -62,6 +117,17 @@ export default { }, }); }, + + *value_add({ payload }, { call, put }) { + const { onSuccess, onFail, body } = payload; + const response = yield call(productAttrValueAdd, body); + if (response && response.code === 0) { + onSuccess && onSuccess(); + } else { + onFail && onFail(response); + } + }, + *addValue({ payload, callback }, { call, put }) { // debugger; // const {queryParams} = payload; @@ -84,10 +150,16 @@ export default { callback(response.data); } } - } + }, }, reducers: { + save(state, action) { + return { + ...state, + ...action.payload, + }; + }, treeSuccess(state, { payload }) { return { ...state, diff --git a/admin-web/src/pages/Admin/AdminList.js b/admin-web/src/pages/Admin/AdminList.js index 8e4e77ca5..1866cfad8 100644 --- a/admin-web/src/pages/Admin/AdminList.js +++ b/admin-web/src/pages/Admin/AdminList.js @@ -2,22 +2,44 @@ import React, { PureComponent, Fragment } from 'react'; import { connect } from 'dva'; -import {Card, Form, Input, Button, Modal, message, Table, Divider, Tree, Spin, Row, Col, Select, Icon} from 'antd'; -import { checkTypeWithEnglishAndNumbers } from '../../../helpers/validator' +import { + Card, + Form, + Input, + Button, + Modal, + message, + Table, + Divider, + Tree, + Spin, + Row, + Col, + Select, + Icon, + TreeSelect, +} from 'antd'; +import { checkTypeWithEnglishAndNumbers } from '../../../helpers/validator'; import PageHeaderWrapper from '@/components/PageHeaderWrapper'; import styles from './AdminList.less'; -import moment from "moment"; -import PaginationHelper from "../../../helpers/PaginationHelper"; +import moment from 'moment'; +import PaginationHelper from '../../../helpers/PaginationHelper'; const FormItem = Form.Item; const { TreeNode } = Tree; const status = ['未知', '正常', '禁用']; // 列表 -function List ({ dataSource, loading, pagination, searchParams, dispatch, - handleModalVisible, handleRoleAssignModalVisible}) { - +function List({ + dataSource, + loading, + pagination, + searchParams, + dispatch, + handleModalVisible, + handleRoleAssignModalVisible, +}) { function handleRoleAssign(record) { // 显示 Modal handleRoleAssignModalVisible(true, record); @@ -66,12 +88,16 @@ function List ({ dataSource, loading, pagination, searchParams, dispatch, const columns = [ { title: '账号', - dataIndex: 'username' + dataIndex: 'username', }, { title: '员工姓名', dataIndex: 'nickname', }, + { + title: '部门', + dataIndex: 'deptment.name', + }, { title: '角色', dataIndex: 'roles', @@ -85,8 +111,8 @@ function List ({ dataSource, loading, pagination, searchParams, dispatch, text += roles[i].name; } } - return ({text}); - } + return {text}; + }, }, { title: '状态', @@ -114,30 +140,30 @@ function List ({ dataSource, loading, pagination, searchParams, dispatch, handleStatus(record)}> {statusText} - { - record.status === 2 ? - - - handleDelete(record)}> - 删除 - - : null - } + {record.status === 2 ? ( + + + handleDelete(record)}> + 删除 + + + ) : null} ); }, }, ]; - function onPageChange(page) { // 翻页 + function onPageChange(page) { + // 翻页 dispatch({ type: 'adminList/query', payload: { pageNo: page.current, pageSize: page.pageSize, - ...searchParams - } - }) + ...searchParams, + }, + }); } return ( @@ -149,7 +175,7 @@ function List ({ dataSource, loading, pagination, searchParams, dispatch, pagination={pagination} onChange={onPageChange} /> - ) + ); } // 搜索表单 @@ -157,17 +183,23 @@ const SearchForm = Form.create()(props => { const { form, form: { getFieldDecorator }, - dispatch + dispatch, + deptSelectTree, } = props; function search() { + const fields = form.getFieldsValue(); + if (fields.deptmentId) { + const deptmentId = fields.deptmentId.split('-')[1]; + fields.deptmentId = deptmentId; + } dispatch({ type: 'adminList/query', payload: { ...PaginationHelper.defaultPayload, - ...form.getFieldsValue() - } - }) + ...fields, + }, + }); } // 提交搜索 @@ -189,20 +221,36 @@ const SearchForm = Form.create()(props => { return (
- + - {getFieldDecorator('nickname')()} + {getFieldDecorator('nickname')()} - - - - - + + + {getFieldDecorator('deptmentId', { + rules: [{ required: true, message: '请选择部门' }], + })( + + )} + + + + + + + +
@@ -211,12 +259,24 @@ const SearchForm = Form.create()(props => { // 添加 or 修改 Form 表单 const AddOrUpdateForm = Form.create()(props => { - const { dispatch, modalVisible, form, handleModalVisible, modalType, formVals } = props; + const { + dispatch, + modalVisible, + form, + handleModalVisible, + modalType, + formVals, + deptSelectTree, + } = props; const okHandle = () => { form.validateFields((err, fields) => { if (err) return; // 添加表单 + if (fields.deptmentId) { + const deptmentId = fields.deptmentId.split('-')[1]; + fields.deptmentId = deptmentId; + } if (modalType === 'add') { dispatch({ type: 'adminList/add', @@ -264,29 +324,52 @@ const AddOrUpdateForm = Form.create()(props => { title={title} visible={modalVisible} onOk={okHandle} - okText='保存' + okText="保存" onCancel={() => handleModalVisible()} > {form.getFieldDecorator('username', { - rules: [{ required: true, message: '请输入账号!'}, - {max: 16, min:6, message: '长度为 6-16 位'}, - { validator: (rule, value, callback) => checkTypeWithEnglishAndNumbers(rule, value, callback, '数字以及字母')} + rules: [ + { required: true, message: '请输入账号!' }, + { max: 16, min: 6, message: '长度为 6-16 位' }, + { + validator: (rule, value, callback) => + checkTypeWithEnglishAndNumbers(rule, value, callback, '数字以及字母'), + }, ], initialValue: formVals.username, })()} {form.getFieldDecorator('nickname', { - rules: [{ required: true, message: '请输入员工姓名!'}, - {max: 10, message: '姓名最大长度为 10'}], + rules: [ + { required: true, message: '请输入员工姓名!' }, + { max: 10, message: '姓名最大长度为 10' }, + ], initialValue: formVals.nickname, })()} + + {form.getFieldDecorator('deptmentId', { + rules: [{ required: true, message: '请选择部门' }], + initialValue: + formVals.deptmentId && formVals.deptmentId !== 0 ? formVals.deptmentId : null, + })( + + )} + {form.getFieldDecorator('password', { - rules: [{ required: modalType === 'add', message: '请填写密码'}, // 添加时,必须输入密码 - {max: 16, min: 6, message: '长度为 6-18 位'}], + rules: [ + { required: modalType === 'add', message: '请填写密码' }, // 添加时,必须输入密码 + { max: 16, min: 6, message: '长度为 6-18 位' }, + ], initialValue: formVals.password, })()} @@ -321,7 +404,8 @@ const RoleAssignModal = Form.create()(props => { const renderTreeNodes = data => { return data.map(item => { - if (item.children) { // 递归拼接节点 + if (item.children) { + // 递归拼接节点 return ( {renderTreeNodes(item.children)} @@ -387,32 +471,31 @@ const RoleAssignModal = Form.create()(props => { onOk={okHandle} onCancel={() => handleModalVisible()} > - - {renderModalContent(treeData)} - + {renderModalContent(treeData)} ); }); - @connect(({ adminList }) => ({ // list: adminList.list, // pagination: adminList.pagination, ...adminList, })) - // 主界面 @Form.create() class AdminList extends PureComponent { - componentDidMount() { const { dispatch } = this.props; dispatch({ type: 'adminList/query', payload: { - ...PaginationHelper.defaultPayload + ...PaginationHelper.defaultPayload, }, }); + dispatch({ + type: 'adminList/getDeptmentTree', + payload: {}, + }); } handleModalVisible = (modalVisible, modalType, record) => { @@ -422,7 +505,7 @@ class AdminList extends PureComponent { payload: { modalVisible, modalType, - formVals: record || {} + formVals: record || {}, }, }); }; @@ -433,18 +516,29 @@ class AdminList extends PureComponent { type: 'adminList/setAll', payload: { roleModalVisible: roleModalVisible, - formVals: record || {} + formVals: record || {}, }, }); }; render() { // let that = this; - const { dispatch, - list, listLoading, searchParams, pagination, - modalVisible, modalType, formVals, + const { + dispatch, + list, + listLoading, + searchParams, + pagination, + modalVisible, + modalType, + formVals, confirmLoading, - roleList, roleModalVisible, roleAssignLoading, roleCheckedKeys } = this.props; + roleList, + roleModalVisible, + roleAssignLoading, + roleCheckedKeys, + deptSelectTree, + } = this.props; // 列表属性 const listProps = { @@ -461,6 +555,7 @@ class AdminList extends PureComponent { // 搜索表单属性 const searchFormProps = { dispatch, + deptSelectTree, }; // 添加 or 更新表单属性 @@ -469,6 +564,7 @@ class AdminList extends PureComponent { modalType, formVals, dispatch, + deptSelectTree, handleModalVisible: this.handleModalVisible, // Function }; diff --git a/admin-web/src/pages/Admin/DeptmentList.js b/admin-web/src/pages/Admin/DeptmentList.js index a741a72c8..621d86539 100644 --- a/admin-web/src/pages/Admin/DeptmentList.js +++ b/admin-web/src/pages/Admin/DeptmentList.js @@ -107,13 +107,23 @@ export default class DepetmentList extends PureComponent { componentDidMount() { const { dispatch } = this.props; dispatch({ - type: 'deptmentList/getDeptmentList', + type: 'deptmentList/getDeptmentAll', payload: { ...PaginationHelper.defaultPayload, }, }); } + initFetch = () => { + const { dispatch } = this.props; + dispatch({ + type: 'deptmentList/getDeptmentAll', + payload: { + ...PaginationHelper.defaultPayload, + }, + }); + }; + handleModalVisible = (flag, modalType, initValues) => { this.setState({ modalVisible: !!flag, @@ -130,6 +140,33 @@ export default class DepetmentList extends PureComponent { } }; + handleDelete(row) { + const { dispatch } = this.props; + const _this = this; + Modal.confirm({ + title: `确认删除?`, + content: `${row.name}`, + onOk() { + dispatch({ + type: 'deptmentList/delete', + payload: { + body: { + id: row.id, + }, + onSuccess: () => { + message.success('删除成功'); + _this.initFetch(); + }, + onFail: response => { + message.warn('删除失败' + response.message); + }, + }, + }); + }, + onCancel() {}, + }); + } + handleAdd = ({ fields, modalType, initValues }) => { const { dispatch } = this.props; if (modalType === 'add') { @@ -142,6 +179,7 @@ export default class DepetmentList extends PureComponent { onSuccess: () => { message.success('添加成功'); this.handleModalVisible(); + this.initFetch(); }, onFail: response => { message.warn('添加失败' + response.message); @@ -159,6 +197,7 @@ export default class DepetmentList extends PureComponent { onSuccess: () => { message.success('更新成功成功'); this.handleModalVisible(); + this.initFetch(); }, onFail: response => { message.warn('更新失败' + response.message); @@ -169,7 +208,7 @@ export default class DepetmentList extends PureComponent { }; render() { - const { deptmentData, deptmentList } = this.props; + const { deptmentData, deptmentList, loading } = this.props; const { selectTree } = deptmentList; const { modalVisible, modalType, initValues } = this.state; const parentMethods = { @@ -229,8 +268,9 @@ export default class DepetmentList extends PureComponent { diff --git a/admin-web/src/pages/Product/ProductAttrList.js b/admin-web/src/pages/Product/ProductAttrList.js new file mode 100644 index 000000000..fad82cb73 --- /dev/null +++ b/admin-web/src/pages/Product/ProductAttrList.js @@ -0,0 +1,550 @@ +import React, { PureComponent, Fragment, Component } from 'react'; +import { + Row, + Col, + Form, + Card, + Table, + Button, + Divider, + Modal, + Input, + message, + Switch, + Select, +} from 'antd'; +import moment from 'moment'; +import { connect } from 'dva'; +import PageHeaderWrapper from '@/components/PageHeaderWrapper'; +import PaginationHelper from '../../../helpers/PaginationHelper'; +import styles from './ProductAttrList.less'; + +const FormItem = Form.Item; +const Option = Select.Option; + +const ValueCreateForm = Form.create()(props => { + const { + valueModalVisible, + form, + handleValueAdd, + handleValueModalVisible, + modalType, + initValues, + tree, + } = props; + + const okHandle = () => { + form.validateFields((err, fieldsValue) => { + if (err) return; + let pid = fieldsValue.pid; + if (fieldsValue.pid) { + pid = pid.split('-')[1]; + fieldsValue.pid = pid; + } + form.resetFields(); + handleValueAdd({ + fields: fieldsValue, + modalType, + initValues, + }); + }); + }; + + const selectStyle = { + width: 200, + }; + + function onTypeChange(event) { + initValues.type = parseInt(event.target.value); + } + + const title = modalType === 'add' ? '添加规格值' : '编辑规格值'; + const okText = modalType === 'add' ? '添加' : '编辑'; + return ( + handleValueModalVisible()} + > + {modalType === 'add' ? ( + + {form.getFieldDecorator('attrId', { + // initialValue: template.durationHour ? template.durationHour : '3', + rules: [ + { + required: true, + message: '请选择规格', + }, + ], + })( + + )} + + ) : null} + + {form.getFieldDecorator('name', { + initialValue: initValues ? initValues.name : null, + rules: [{ required: true, message: '请输入规格值!', min: 2 }], + })()} + + + ); +}); + +const CreateForm = Form.create()(props => { + const { modalVisible, form, handleAdd, handleModalVisible, modalType, initValues } = props; + + const okHandle = () => { + form.validateFields((err, fieldsValue) => { + if (err) return; + let pid = fieldsValue.pid; + if (fieldsValue.pid) { + pid = pid.split('-')[1]; + fieldsValue.pid = pid; + } + form.resetFields(); + handleAdd({ + fields: fieldsValue, + modalType, + initValues, + }); + }); + }; + + const selectStyle = { + width: 200, + }; + + function onTypeChange(event) { + initValues.type = parseInt(event.target.value); + } + + const title = modalType === 'add' ? '添加规格' : '编辑规格'; + const okText = modalType === 'add' ? '添加' : '编辑'; + return ( + handleModalVisible()} + > + + {form.getFieldDecorator('name', { + initialValue: initValues ? initValues.name : null, + rules: [{ required: true, message: '请输入规格名称!', min: 2 }], + })()} + + + ); +}); + +@connect(({ productAttrList, loading }) => ({ + productAttrList, + attrData: productAttrList.attrData, + tree: productAttrList.tree, + loading: loading.models.productAttrList, +})) +@Form.create() +export default class ProductAttrList extends PureComponent { + state = { + modalVisible: false, + valueModalVisible: false, + modalType: 'add', //add or update + initValues: {}, + current: 1, + pageSize: 10, + name: null, + }; + + componentDidMount() { + this.initFetch(); + } + + initFetch = () => { + const { dispatch } = this.props; + const { current, pageSize, name } = this.state; + dispatch({ + type: 'productAttrList/page', + payload: { + pageNo: current, + pageSize, + name, + }, + }); + // const { dispatch } = this.props; + dispatch({ + type: 'productAttrList/tree', + payload: { + ...PaginationHelper.defaultPayload, + }, + }); + }; + + expandedRowRender = record => { + const columns = [ + { + title: '规格值', + dataIndex: 'name', + }, + { + title: '状态', + // dataIndex: 'status', + render: (text, record) => ( + this.switchValueChange(checked, record)} + /> + ), + }, + { + title: '创建时间', + dataIndex: 'createTime', + sorter: true, + render: val => {moment(val).format('YYYY-MM-DD')}, + }, + { + title: '操作', + render: (text, record) => ( + + this.handleValueModalVisible(true, 'update', record)}>编辑 + + {/* this.handleDelete(record)}> + 删除 + */} + + ), + }, + ]; + + return
; + }; + + handleAdd = ({ fields, modalType, initValues }) => { + const { dispatch } = this.props; + if (modalType === 'add') { + dispatch({ + type: 'productAttrList/add', + payload: { + body: { + ...fields, + }, + onSuccess: () => { + message.success('添加成功'); + this.handleModalVisible(); + this.initFetch(); + }, + onFail: response => { + message.warn('添加失败' + response.message); + }, + }, + }); + } else { + dispatch({ + type: 'productAttrList/update', + payload: { + body: { + ...initValues, + ...fields, + }, + onSuccess: () => { + message.success('更新成功'); + this.handleModalVisible(); + this.initFetch(); + }, + onFail: response => { + message.warn('更新失败' + response.message); + }, + }, + }); + } + }; + + handleValueAdd = ({ fields, modalType, initValues }) => { + const { dispatch } = this.props; + if (modalType === 'add') { + dispatch({ + type: 'productAttrList/value_add', + payload: { + body: { + ...fields, + }, + onSuccess: () => { + message.success('添加成功'); + this.handleValueModalVisible(); + this.initFetch(); + }, + onFail: response => { + message.warn('添加失败' + response.message); + }, + }, + }); + } else { + dispatch({ + type: 'productAttrList/value_update', + payload: { + body: { + ...initValues, + ...fields, + }, + onSuccess: () => { + message.success('更新成功'); + this.handleValueModalVisible(); + this.initFetch(); + }, + onFail: response => { + message.warn('更新失败' + response.message); + }, + }, + }); + } + }; + + handleModalVisible = (flag, modalType, initValues) => { + this.setState({ + modalVisible: !!flag, + initValues: initValues || {}, + modalType: modalType || 'add', + }); + }; + + handleValueModalVisible = (flag, modalType, initValues) => { + this.setState({ + valueModalVisible: !!flag, + initValues: initValues || {}, + modalType: modalType || 'add', + }); + }; + + handleTableChange = pagination => { + const { pageSize, current, index } = pagination; + this.setState( + { + current, + pageSize, + }, + function() { + this.initFetch(); + } + ); + }; + + switchValueChange = (checked, record) => { + const { dispatch } = this.props; + dispatch({ + type: 'productAttrList/value_update_status', + payload: { + body: { + id: record.id, + status: checked ? 1 : 2, + }, + onSuccess: () => { + message.success('修改状态成功'); + this.initFetch(); + }, + }, + }); + }; + + switchChange = (checked, record) => { + const { dispatch } = this.props; + dispatch({ + type: 'productAttrList/update_status', + payload: { + body: { + id: record.id, + status: checked ? 1 : 2, + }, + onSuccess: () => { + message.success('修改状态成功'); + this.initFetch(); + }, + }, + }); + }; + + handleFormReset = () => { + const { form, dispatch } = this.props; + form.resetFields(); + this.setState( + { + name: null, + }, + function() { + this.initFetch(); + } + ); + }; + + handleCondition = e => { + e.preventDefault(); + + const { dispatch, form } = this.props; + + form.validateFields((err, fieldsValue) => { + if (err) return; + const values = { + ...fieldsValue, + }; + + if (values.name) { + this.setState( + { + searched: true, + name: values.name, + }, + function() { + this.initFetch(); + } + ); + } else { + this.initFetch(); + } + + // dispatch({ + // type: 'fenfa/getCategoryList', + // payload: { + // key: values.name + // }, + // }); + }); + }; + + renderSimpleForm() { + const { form } = this.props; + const { getFieldDecorator } = form; + return ( + + + + + {getFieldDecorator('name')()} + + + + + + + + + + + + ); + } + + render() { + const { attrData, productAttrList, loading, tree } = this.props; + const columns = [ + { + title: '规格名称', + dataIndex: 'name', + }, + { + title: '状态', + // dataIndex: 'status', + render: (text, record) => ( + this.switchChange(checked, record)} + /> + ), + }, + { + title: '创建时间', + dataIndex: 'createTime', + sorter: true, + render: val => {moment(val).format('YYYY-MM-DD')}, + }, + { + title: '操作', + render: (text, record) => ( + + this.handleModalVisible(true, 'update', record)}>编辑 + + this.handleValueModalVisible(true, 'add', {})}>新建规格值 + {/* this.handleDelete(record)}> + 删除 + */} + + ), + }, + ]; + + const { modalVisible, modalType, initValues, valueModalVisible } = this.state; + + const parentMethods = { + handleAdd: this.handleAdd, + handleModalVisible: this.handleModalVisible, + modalType, + initValues, + }; + + const valueFormParentMethods = { + handleValueAdd: this.handleValueAdd, + handleValueModalVisible: this.handleValueModalVisible, + modalType, + initValues, + tree: tree, + }; + + const pagination = { + total: attrData.count, + index: this.state.current, + pageSize: this.state.pageSize, + }; + + return ( + + +
+
+ +
+ + + +
{this.renderSimpleForm()}
+ + + + +
this.handleTableChange(pagination)} + /> + + {modalVisible ? : null} + {valueModalVisible ? ( + + ) : null} + + ); + } +} diff --git a/admin-web/src/pages/Product/ProductAttrList.less b/admin-web/src/pages/Product/ProductAttrList.less new file mode 100644 index 000000000..22e257421 --- /dev/null +++ b/admin-web/src/pages/Product/ProductAttrList.less @@ -0,0 +1,11 @@ +@import '~antd/lib/style/themes/default.less'; +@import '~@/utils/utils.less'; + +.tableList { + .tableListOperator { + margin-bottom: 16px; + button { + margin-right: 8px; + } + } +} diff --git a/admin-web/src/services/admin.js b/admin-web/src/services/admin.js index d39953d0e..b3dca958e 100644 --- a/admin-web/src/services/admin.js +++ b/admin-web/src/services/admin.js @@ -74,6 +74,12 @@ export async function updateDeptment(params) { }); } +export async function deleteDeptment(params) { + return request(`/admin-api/admins/dept/delete?${stringify(params)}`, { + method: 'POST', + }); +} + export async function deptTreePage(params) { return request(`/admin-api/admins/dept/tree/page?${stringify(params)}`, { method: 'GET', diff --git a/admin-web/src/services/product.js b/admin-web/src/services/product.js index a8929dd4e..2236d74fc 100644 --- a/admin-web/src/services/product.js +++ b/admin-web/src/services/product.js @@ -4,23 +4,23 @@ import request from '@/utils/request'; // product category export async function productCategoryTree(params) { - return request(`/product-api/admins/category/tree?${stringify(params)}`, { - method: 'GET', - }); + return request(`/product-api/admins/category/tree?${stringify(params)}`, { + method: 'GET', + }); } export async function productCategoryAdd(params) { - return request(`/product-api/admins/category/add?${stringify(params)}`, { - method: 'POST', - body: {}, - }); + return request(`/product-api/admins/category/add?${stringify(params)}`, { + method: 'POST', + body: {}, + }); } export async function productCategoryUpdate(params) { - return request(`/product-api/admins/category/update?${stringify(params)}`, { - method: 'POST', - body: {}, - }); + return request(`/product-api/admins/category/update?${stringify(params)}`, { + method: 'POST', + body: {}, + }); } export async function productCategoryUpdateStatus(params) { @@ -31,9 +31,9 @@ export async function productCategoryUpdateStatus(params) { } export async function productCategoryDelete(params) { - return request(`/product-api/admins/category/delete?${stringify(params)}`, { - method: 'POST', - }); + return request(`/product-api/admins/category/delete?${stringify(params)}`, { + method: 'POST', + }); } // product spu + sku @@ -85,12 +85,53 @@ export async function productSpuInfo(params) { // product attr + attr value +export async function productAttrPage(params) { + return request(`/product-api/admins/attr/page?${stringify(params)}`, { + method: 'GET', + }); +} + +export async function productAttrAdd(params) { + return request(`/product-api/admins/attr/add?${stringify(params)}`, { + method: 'POST', + body: {}, + }); +} + +export async function productAttrUpdate(params) { + return request(`/product-api/admins/attr/update?${stringify(params)}`, { + method: 'POST', + body: {}, + }); +} + +export async function productAttrUpdateStatus(params) { + return request(`/product-api/admins/attr/update_status?${stringify(params)}`, { + method: 'POST', + body: {}, + }); +} + export async function productAttrTree(params) { return request(`/product-api/admins/attr/tree?${stringify(params)}`, { method: 'GET', }); } +export async function productAttrValueUpdate(params) { + return request(`/product-api/admins/attr_value/update?${stringify(params)}`, { + method: 'POST', + body: {}, + }); +} + +export async function productAttrValueUpdateStatus(params) { + return request(`/product-api/admins/attr_value/update_status?${stringify(params)}`, { + method: 'POST', + body: {}, + }); +} + export async function productAttrValueAdd(params) { return request(`/product-api/admins/attr_value/add?${stringify(params)}`, { method: 'POST', @@ -98,30 +139,30 @@ export async function productAttrValueAdd(params) { }); } - // product brand 2019-05-31 +// product brand 2019-05-31 export async function productBrandAdd(params) { - return request(`/product-api/admins/brand/add?${stringify(params)}`, { - method: 'POST', - body: {}, - }); + return request(`/product-api/admins/brand/add?${stringify(params)}`, { + method: 'POST', + body: {}, + }); } export async function productBrandUpdate(params) { - return request(`/product-api/admins/brand/update?${stringify(params)}`, { - method: 'POST', - body: {}, - }); + return request(`/product-api/admins/brand/update?${stringify(params)}`, { + method: 'POST', + body: {}, + }); } export async function productBrandGet(params) { return request(`/product-api/admins/brand/get?${stringify(params)}`, { - method: 'GET' + method: 'GET', }); } export async function productBrandPage(params) { return request(`/product-api/admins/brand/page?${stringify(params)}`, { - method: 'GET' + method: 'GET', }); } diff --git a/docs/guides/功能列表/功能列表-管理后台.md b/docs/guides/功能列表/功能列表-管理后台.md index 12477a334..9585d6e62 100644 --- a/docs/guides/功能列表/功能列表-管理后台.md +++ b/docs/guides/功能列表/功能列表-管理后台.md @@ -20,6 +20,7 @@ - [x] 展示类目 - [ ] 品牌管理【开发中 @黑子】 - [ ] 商品标签 + - [ ] 商品规格页面【开发中 @Tprotect曦】 - [ ] 订单管理 - [x] 销售单 - [x] 售后单 @@ -49,7 +50,7 @@ - [x] 员工管理 - [x] 角色管理 - [x] 权限管理 - - [ ] 部门管理【开发中 @Tprotect曦】 + - [x] 部门管理 - [x] 数据字典 - [x] 短信管理 - [X] 短信模板 diff --git a/docs/sql/mall_admin.sql b/docs/sql/mall_admin.sql index abf6cf7ae..c9a8230fd 100644 --- a/docs/sql/mall_admin.sql +++ b/docs/sql/mall_admin.sql @@ -50,6 +50,7 @@ CREATE TABLE `admin` ( `nickname` varchar(10) NOT NULL COMMENT '昵称', `password` varchar(32) NOT NULL COMMENT '密码\n *\n * TODO 芋艿 暂时最简单的 MD5', `status` tinyint(11) NOT NULL COMMENT '账号状态', + `deptment_id` int(11) DEFAULT 0 NOT NULL COMMENT '部门id', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `deleted` bit(1) DEFAULT NULL, @@ -313,6 +314,8 @@ INSERT INTO `resource` VALUES (50, 2, 3, '删除字典', 19, '', NULL, 'system.d INSERT INTO `resource` VALUES (51, 1, -1, '短信ss', 0, '', 'user', '', '2019-05-26 12:00:31', '2019-06-03 13:54:54', b'0'); INSERT INTO `resource` VALUES (52, 1, 1, '短信签名', 51, '/sms/sign-list', 'user', '', '2019-05-26 12:01:56', '2019-05-26 12:01:56', b'0'); INSERT INTO `resource` VALUES (53, 1, 2, '短信模板', 51, '/sms/template-list', 'user', '', '2019-05-26 12:02:19', '2019-05-26 12:02:18', b'0'); +INSERT INTO `resource` VALUES (54, 1, 3, '部门管理', 13, '/admin/dept-list', 'user', '', '2019-06-27 23:41:19', '2019-06-27 23:41:51', b'0'); +INSERT INTO `resource` VALUES (55, 1, 4, '规格管理', 20, '/product/product-attr-list', null, null, '2019-08-14 23:59:38', '2019-08-14 23:59:38', b'0'); COMMIT; -- ---------------------------- diff --git a/docs/sql/mall_user.sql b/docs/sql/mall_user.sql index 7500b7410..5be346735 100644 --- a/docs/sql/mall_user.sql +++ b/docs/sql/mall_user.sql @@ -139,6 +139,8 @@ CREATE TABLE `user_spu_collections` ( `spu_id` int(11) NOT NULL COMMENT '商品id', `spu_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '商品名字', `spu_image` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '图片名字', + `sell_point` varchar(50) NOT NULL DEFAULT '' COMMENT '卖点', + `price` int(11) DEFAULT NULL COMMENT '价格', `create_time` datetime(0) NOT NULL COMMENT '创建时间', `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', `deleted` smallint(2) NOT NULL COMMENT '删除状态', diff --git a/mobile-web/src/page/product/detail.vue b/mobile-web/src/page/product/detail.vue index f2184ee14..1a50657b2 100644 --- a/mobile-web/src/page/product/detail.vue +++ b/mobile-web/src/page/product/detail.vue @@ -98,7 +98,7 @@ - + 收藏 @@ -208,6 +208,7 @@ calSkuPriceResult: { }, + hasCollectionType:0 }; }, @@ -291,6 +292,20 @@ } }); }, + initHasUserSpuFavorite(spuId){ + if (!checkLogin()) { + this.hasCollectionType = 0; + return; + } + //初始化验证商品收藏 + hasUserSpuFavorite(spuId).then(data => { + let hasCollection = data; + // alert("是否收藏==" + hasCollection); + if (hasCollection) { + this.hasCollectionType = 1; + } + }); + }, onClickCart() { this.$router.push('/cart'); @@ -327,11 +342,14 @@ // alert("hasCollectionType==" + hasCollectionType); collectionSpu(id,hasCollectionType).then(data =>{ let v = data; - if (hasCollectionType == 1 && v){ - alert("商品已收藏"); - }else if (hasCollectionType == 2 && v){ - alert("商品已取消"); - } + this.hasCollectionType = hasCollectionType; + // if (hasCollectionType == 1 && v){ + // // alert("商品已收藏"); + // this.hasCollectionType = hasCollectionType; + // }else if (hasCollectionType == 2 && v){ + // // alert("商品已取消"); + // this.hasCollectionType = hasCollectionType; + // } }) }); @@ -426,6 +444,7 @@ // 初始化 attrValueMap this.attrValueMap.set(attr.attrValueId, attr.attrValueName); } + } // debugger; this.vanSku = vanSku; @@ -435,6 +454,9 @@ this.initialSku.quantity = 1; // 执行 sku 价格计算 this.doCalcSkuPrice(this.initialSku.id); + + this.initHasUserSpuFavorite(id); + }); // 获得购物车数量 if (checkLogin()) { @@ -448,6 +470,9 @@ diff --git a/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/message/ProductSpuCollectionMessage.java b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/message/ProductSpuCollectionMessage.java index 685a2cc45..b957218e0 100644 --- a/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/message/ProductSpuCollectionMessage.java +++ b/product/product-service-api/src/main/java/cn/iocoder/mall/product/api/message/ProductSpuCollectionMessage.java @@ -37,6 +37,16 @@ public class ProductSpuCollectionMessage { */ private String spuImage; + /** + * 卖点 + */ + private String sellPoint; + + /** + * 价格,单位:分 + */ + private Integer price; + /** * 1 收藏 2 取消 */ diff --git a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductAttrServiceImpl.java b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductAttrServiceImpl.java index a48375409..7ccdfb8ce 100644 --- a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductAttrServiceImpl.java +++ b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductAttrServiceImpl.java @@ -72,7 +72,7 @@ public class ProductAttrServiceImpl implements ProductAttrService { public ProductAttrPageBO getProductAttrPage(ProductAttrPageDTO productAttrPageDTO) { ProductAttrPageBO productAttrPageBO = new ProductAttrPageBO(); // 查询分页数据 - int offset = productAttrPageDTO.getPageNo() * productAttrPageDTO.getPageSize(); + int offset = (productAttrPageDTO.getPageNo()-1) * productAttrPageDTO.getPageSize(); productAttrPageBO.setAttrs(ProductAttrConvert.INSTANCE.convert(productAttrMapper.selectListByNameLike(productAttrPageDTO.getName(), offset, productAttrPageDTO.getPageSize()))); // 查询分页总数 diff --git a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductSpuCollectionServiceImpl.java b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductSpuCollectionServiceImpl.java index dae127325..874cc4412 100644 --- a/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductSpuCollectionServiceImpl.java +++ b/product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductSpuCollectionServiceImpl.java @@ -6,11 +6,14 @@ import cn.iocoder.mall.product.api.constant.ProductErrorCodeEnum; import cn.iocoder.mall.product.api.message.ProductSpuCollectionMessage; import cn.iocoder.mall.product.dao.ProductSpuMapper; import cn.iocoder.mall.product.dataobject.ProductSpuDO; +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.util.List; /** * ProductSpuCollectionServiceImpl @@ -47,9 +50,14 @@ public class ProductSpuCollectionServiceImpl implements ProductSpuCollectionServ */ private void sendProductSpuCollectionMessage(final ProductSpuDO productSpuDO, final Integer hasCollectionType, final Integer userId) { + List result = Lists.newArrayList(Splitter.on(",").omitEmptyStrings().trimResults().split(productSpuDO.getPicUrls())); ProductSpuCollectionMessage productSpuCollectionMessage = new ProductSpuCollectionMessage() - .setSpuId(productSpuDO.getId()).setSpuName(productSpuDO.getName()) - .setSpuImage(productSpuDO.getPicUrls()).setHasCollectionType(hasCollectionType) + .setSpuId(productSpuDO.getId()) + .setSpuName(productSpuDO.getName()) + .setSpuImage(result.size() > 0 ? result.get(0) : "") + .setSellPoint(productSpuDO.getSellPoint()) + .setPrice(productSpuDO.getPrice()) + .setHasCollectionType(hasCollectionType) .setUserId(userId); rocketMQTemplate.convertAndSend(ProductSpuCollectionMessage.TOPIC, productSpuCollectionMessage); } diff --git a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/AdminController.java b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/AdminController.java index 8b874d5ac..9a72166f7 100644 --- a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/AdminController.java +++ b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/AdminController.java @@ -5,8 +5,10 @@ import cn.iocoder.common.framework.util.CollectionUtil; import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.common.framework.vo.PageResult; import cn.iocoder.mall.admin.api.AdminService; +import cn.iocoder.mall.admin.api.DeptmentService; import cn.iocoder.mall.admin.api.ResourceService; import cn.iocoder.mall.admin.api.RoleService; +import cn.iocoder.mall.admin.api.bo.deptment.DeptmentBO; import cn.iocoder.mall.admin.api.bo.resource.ResourceBO; import cn.iocoder.mall.admin.api.bo.role.RoleBO; import cn.iocoder.mall.admin.api.bo.admin.AdminBO; @@ -23,6 +25,7 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; import org.apache.dubbo.config.annotation.Reference; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.*; @@ -44,6 +47,9 @@ public class AdminController { @Reference(validation = "true", version = "${dubbo.provider.RoleService.version}") private RoleService roleService; + @Autowired + private DeptmentService deptmentService; + // =========== 当前管理员相关的资源 API =========== // TODO 功能:当前管理员 @@ -85,7 +91,7 @@ public class AdminController { } // =========== 管理员管理 API =========== - + //TODO 目前需要增加搜索所有子部门的用户 @GetMapping("/page") @RequiresPermissions("system.admin.page") @ApiOperation(value = "管理员分页") @@ -97,7 +103,17 @@ public class AdminController { // 查询角色数组 Map> roleMap = adminService.getAdminRolesMap(CollectionUtil.convertList(resultPage.getList(), AdminBO::getId)); resultPage.getList().forEach(admin -> admin.setRoles(AdminConvert.INSTANCE.convertAdminVORoleList(roleMap.get(admin.getId())))); + + // 查询对应部门 + List deptmentBOS = deptmentService.getAllDeptments(); + Map deptNameMap = deptmentBOS.stream().collect(Collectors.toMap(d->d.getId(), d->d.getName())); + //管理员所在部门被删后,变成未分配状态 + deptNameMap.put(0, "未分配"); + resultPage.getList().forEach(admin->{ + admin.setDeptment(new AdminVO.Deptment(admin.getDeptmentId(), deptNameMap.get(admin.getDeptmentId()))); + }); } + return success(resultPage); } diff --git a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/DeptmentController.java b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/DeptmentController.java index 132f520dc..1a74a8572 100644 --- a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/DeptmentController.java +++ b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/DeptmentController.java @@ -49,7 +49,7 @@ public class DeptmentController { public CommonResult> treeAll(){ List list = deptmentService.getAllDeptments(); List voList = DeptmentConvert.INSTANCE.convert(list); - Map nodeMap = calaNodeMap(voList); + Map nodeMap = calcNodeMap(voList); // 获得到所有的根节点 List rootNodes = nodeMap.values().stream() .filter(node -> node.getPid().equals(ResourceConstants.PID_ROOT)) @@ -64,7 +64,7 @@ public class DeptmentController { PageResult voPageResult = DeptmentConvert.INSTANCE.convert(pageResult); List list = deptmentService.getAllDeptments(); List voList = DeptmentConvert.INSTANCE.convert(list); - Map nodeMap = calaNodeMap(voList); + Map nodeMap = calcNodeMap(voList); voPageResult.getList().forEach(d->{ d.setChildren(nodeMap.get(d.getId()).getChildren()); }); @@ -97,7 +97,7 @@ public class DeptmentController { )); } - private Map calaNodeMap(List voList){ + private Map calcNodeMap(List voList){ Map nodeMap = voList.stream().collect(Collectors.toMap(e->e.getId(), e->e)); nodeMap.values().stream() diff --git a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/vo/admin/AdminVO.java b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/vo/admin/AdminVO.java index 086e4266e..6847d1829 100644 --- a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/vo/admin/AdminVO.java +++ b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/vo/admin/AdminVO.java @@ -3,6 +3,7 @@ package cn.iocoder.mall.admin.application.vo.admin; import cn.iocoder.mall.admin.api.bo.admin.AdminBO; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.experimental.Accessors; @@ -15,6 +16,8 @@ public class AdminVO extends AdminBO { private List roles; + private Deptment deptment; + @ApiModel("管理员 VO - 角色") @Data @Accessors(chain = true) @@ -28,4 +31,19 @@ public class AdminVO extends AdminBO { } + @ApiModel("管理员 VO - 部门") + @Data + @Accessors(chain = true) + @AllArgsConstructor + public static class Deptment { + + @ApiModelProperty(value = "部门编号", required = true, example = "1") + private Integer id; + + @ApiModelProperty(value = "部门名称", required = true, example = "研发部") + private String name; + + + } + } diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/admin/AdminBO.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/admin/AdminBO.java index 88dbb3428..b348f2c3d 100644 --- a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/admin/AdminBO.java +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/bo/admin/AdminBO.java @@ -28,4 +28,7 @@ public class AdminBO implements Serializable { @ApiModelProperty(value = "创建时间", required = true, example = "时间戳格式") private Date createTime; + @ApiModelProperty(value = "部门ID", required = true, example = "1") + private Integer deptmentId; + } diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminAddDTO.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminAddDTO.java index 79ed25335..748b77399 100644 --- a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminAddDTO.java +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminAddDTO.java @@ -7,6 +7,7 @@ import lombok.experimental.Accessors; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import java.io.Serializable; @@ -31,4 +32,8 @@ public class AdminAddDTO implements Serializable { @Length(min = 4, max = 16, message = "密码长度为 4-16 位") private String password; + @ApiModelProperty(value = "部门ID", required = true, example = "1") + @NotNull(message = "部门不能为空") + private Integer deptmentId; + } diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminPageDTO.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminPageDTO.java index 26f508123..f1e8a1ee7 100644 --- a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminPageDTO.java +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminPageDTO.java @@ -14,4 +14,8 @@ public class AdminPageDTO extends PageParam { @ApiModelProperty(value = "昵称,模糊匹配", example = "小王") private String nickname; + + @ApiModelProperty(value = "所在部门ID") + private Integer deptmentId; + } diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminUpdateDTO.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminUpdateDTO.java index 5fac82467..c88c6e05b 100644 --- a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminUpdateDTO.java +++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/admin/AdminUpdateDTO.java @@ -35,4 +35,8 @@ public class AdminUpdateDTO implements Serializable { @Length(min = 4, max = 16, message = "密码长度为 4-16 位") private String password; + @ApiModelProperty(value = "部门ID", required = true, example = "1") + @NotNull(message = "部门不能为空") + private Integer deptmentId; + } diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AdminMapper.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AdminMapper.java index 49e049537..a15c940cd 100644 --- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AdminMapper.java +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AdminMapper.java @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Param; +import org.omg.PortableInterceptor.INACTIVE; import org.springframework.stereotype.Repository; @Repository @@ -19,7 +20,14 @@ public interface AdminMapper extends BaseMapper { default IPage selectPage(AdminPageDTO adminPageDTO) { return selectPage(new Page<>(adminPageDTO.getPageNo(), adminPageDTO.getPageSize()), - new QueryWrapperX().likeIfPresent("nickname", adminPageDTO.getNickname())); + new QueryWrapperX().likeIfPresent("nickname", adminPageDTO.getNickname()) + .eqIfPresent("deptment_id", adminPageDTO.getDeptmentId())); + } + + default int updateDeptByDeptId(@Param("fromDeptId")Integer fromDeptId, @Param("toDeptId")Integer toDeptId){ + QueryWrapper query = new QueryWrapper() + .eq("deptment_id", fromDeptId); + return update(new AdminDO().setDeptmentId(toDeptId), query); } } diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminDO.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminDO.java index 08b030628..88f7643d6 100644 --- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminDO.java +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminDO.java @@ -36,6 +36,12 @@ public class AdminDO extends DeletableDO { */ private Integer status; + /** + * 管理员部门id + */ + private Integer deptmentId; + + // TODO 芋艿,最后登陆时间、最后登陆 IP // TODO 芋艿,登陆日志 diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/DeptmentServiceImpl.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/DeptmentServiceImpl.java index d7ec20235..2a02040cb 100644 --- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/DeptmentServiceImpl.java +++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/DeptmentServiceImpl.java @@ -11,6 +11,7 @@ import cn.iocoder.mall.admin.api.dto.depetment.DeptmentAddDTO; import cn.iocoder.mall.admin.api.dto.depetment.DeptmentPageDTO; import cn.iocoder.mall.admin.api.dto.depetment.DeptmentUpdateDTO; import cn.iocoder.mall.admin.convert.DeptmentConvert; +import cn.iocoder.mall.admin.dao.AdminMapper; import cn.iocoder.mall.admin.dao.DeptmentMapper; import cn.iocoder.mall.admin.dao.DeptmentRoleMapper; import cn.iocoder.mall.admin.dataobject.DeptmentDO; @@ -39,6 +40,9 @@ public class DeptmentServiceImpl implements DeptmentService { @Autowired private DeptmentRoleMapper deptmentRoleMapper; + @Autowired + private AdminMapper adminMapper; + @Override public DeptmentBO addDeptment(Integer adminId, DeptmentAddDTO deptmentAddDTO) { if (deptmentAddDTO.getPid() != 0 && @@ -69,6 +73,8 @@ public class DeptmentServiceImpl implements DeptmentService { deptmentRoleMapper.deleteByDeptmentId(deptmentId); + //将改部门下所有员工的DeptmentID设置为0 + adminMapper.updateDeptByDeptId(deptmentId, 0); return true; } diff --git a/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/bo/UserProductSpuCollectionsBO.java b/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/bo/UserProductSpuCollectionsBO.java index 694cd73a0..d427a7fc6 100644 --- a/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/bo/UserProductSpuCollectionsBO.java +++ b/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/bo/UserProductSpuCollectionsBO.java @@ -45,6 +45,16 @@ public class UserProductSpuCollectionsBO implements Serializable { */ private String spuImage; + /** + * 卖点 + */ + private String sellPoint; + + /** + * 价格,单位:分 + */ + private Integer price; + /** * 创建时间 */ diff --git a/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/dto/UserProductSpuCollectionsAddDTO.java b/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/dto/UserProductSpuCollectionsAddDTO.java index e949c3d1b..d2e86ae4f 100644 --- a/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/dto/UserProductSpuCollectionsAddDTO.java +++ b/user/user-service-api/src/main/java/cn/iocoder/mall/user/api/dto/UserProductSpuCollectionsAddDTO.java @@ -46,6 +46,16 @@ public class UserProductSpuCollectionsAddDTO implements Serializable { */ private String spuImage; + /** + * 卖点 + */ + private String sellPoint; + + /** + * 价格,单位:分 + */ + private Integer price; + /** * 创建时间 */ diff --git a/user/user-service-impl/src/main/java/cn/iocoder/mall/user/biz/dataobject/UserProductSpuCollectionsDO.java b/user/user-service-impl/src/main/java/cn/iocoder/mall/user/biz/dataobject/UserProductSpuCollectionsDO.java index bda45a973..9d532b9d5 100644 --- a/user/user-service-impl/src/main/java/cn/iocoder/mall/user/biz/dataobject/UserProductSpuCollectionsDO.java +++ b/user/user-service-impl/src/main/java/cn/iocoder/mall/user/biz/dataobject/UserProductSpuCollectionsDO.java @@ -50,6 +50,16 @@ public class UserProductSpuCollectionsDO implements Serializable { */ private String spuImage; + /** + * 卖点 + */ + private String sellPoint; + + /** + * 价格,单位:分 + */ + private Integer price; + /** * 创建时间 */ diff --git a/user/user-service-impl/src/main/java/cn/iocoder/mall/user/biz/service/UserProductSpuCollectionsServiceImpl.java b/user/user-service-impl/src/main/java/cn/iocoder/mall/user/biz/service/UserProductSpuCollectionsServiceImpl.java index 2c4a6a20b..55e1858a6 100644 --- a/user/user-service-impl/src/main/java/cn/iocoder/mall/user/biz/service/UserProductSpuCollectionsServiceImpl.java +++ b/user/user-service-impl/src/main/java/cn/iocoder/mall/user/biz/service/UserProductSpuCollectionsServiceImpl.java @@ -11,6 +11,8 @@ import cn.iocoder.mall.user.api.dto.UserProductSpuCollectionsUpdateDTO; import cn.iocoder.mall.user.biz.convert.UserProductSpuCollectionsConvert; import cn.iocoder.mall.user.biz.dao.UserProductSpuCollectionsMapper; import cn.iocoder.mall.user.biz.dataobject.UserProductSpuCollectionsDO; +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -33,6 +35,10 @@ public class UserProductSpuCollectionsServiceImpl implements UserProductSpuColle @Autowired private UserProductSpuCollectionsMapper userProductSpuCollectionsMapper; + // TODO 暂时先使用冗余字段,有需要在对接实时数据查询 +// @Reference(validation = "true", version = "${dubbo.consumer.PromotionActivityService.version}") +// private ProductSpuService productSpuService; + @Override public int addUserSkuCollections(UserProductSpuCollectionsAddDTO userProductSpuCollectionsAddDTO) { @@ -72,6 +78,11 @@ public class UserProductSpuCollectionsServiceImpl implements UserProductSpuColle return CommonResult.success( new UserProductSpuCollectionsPageBO().setList(Collections.emptyList()).setTotal(totalCount)); } + for (UserProductSpuCollectionsDO userProductSpuCollectionsDO : list + ) { + List result = Lists.newArrayList(Splitter.on(",").omitEmptyStrings().trimResults().split(userProductSpuCollectionsDO.getSpuImage())); + userProductSpuCollectionsDO.setSpuImage(result.size() > 0 ? result.get(0) : ""); + } UserProductSpuCollectionsPageBO userProductSpuCollectionsPageBO = new UserProductSpuCollectionsPageBO(); userProductSpuCollectionsPageBO.setList(UserProductSpuCollectionsConvert.INSTANCE.convert(list)); diff --git a/user/user-service-impl/src/main/resources/mapper/UserProductSpuCollectionsMapper.xml b/user/user-service-impl/src/main/resources/mapper/UserProductSpuCollectionsMapper.xml index d4d3b3daa..ec77f1fe0 100644 --- a/user/user-service-impl/src/main/resources/mapper/UserProductSpuCollectionsMapper.xml +++ b/user/user-service-impl/src/main/resources/mapper/UserProductSpuCollectionsMapper.xml @@ -4,7 +4,7 @@ id, user_id, nickname, spu_id, spu_name, - spu_image, create_time, update_time, + spu_image,sell_point,price, create_time, update_time, deleted