一、登录功能:antd-Form、localStorage

   1.登录界面与首页实现

     1)两个界面路由注册,通过判断本地是否有用户登录数据

        有:--->  <Route path='/' component={Admin} />  (作为的根路径)

        无:--->  <Route path='/login' component={Login} />

   2.表单数据收集

     1)输入过程数据验证是否符合要求

     2)  表单提交数据验证 --> 通过发起登录请求 --> 跳转到根路由

         在这个过程中需要往本地存储用户信息,并通过memoryUtil 将数据传给首页显示

   3. 首页排版:antd -- Layout

      1)侧边栏菜单实现:通过数据遍历展现到页面

      2)权限验证:根据用户menus数据,决定侧边栏菜单功能展示

      3)头部

        退出功能:antd --- Modal 、 退出后本地用户数据清除,跳转到登录路由

        时间、天气动态展示:时间格式化Utils,高德天气接口

        标题展示:根据当前路径匹配标题

    4)home内容区:antd组件

 

二、 商品 ---- 品类管理:品类增加、修改、获取

  1.接口准备

    包括接口请求使用axios封装为一个函数,再分别创建不同类别的接口函数(reqAdd--、reqUpdate--)

    目的:方便接口传参而避免造成代码冗余

//获取分类列表
export const reqCategoryList = (parentId)=> ajax('/manage/category/list',{parentId})
//添加分类列表
export const reqAddCategory = (parentId,categoryName)=> ajax('/manage/category/add',{parentId,categoryName},'POST')
//更新分类列表
export const reqUpdateCategory = (categoryId,categoryName)=> ajax('/manage/category/update',{categoryId,categoryName},'POST')

  2. 品类管理路由组件实现--数据初始化

    1)antd---Card模块---Table模块

    2) 组件加载完后生命周期:请求数据(这是一个通用数据更新函数)、初始化数据

componentDidMount(){
          this.inintColumns()
          this.setCategory()
      }

    3)二级页面数据初始化:根据接口参数不同,请求不同数据(利用Table性质拿到对应点击数据 ),实现需要显示或隐藏部分

  3. 品类管理路由组件实现--数据修改

    1)antd---Modal模块---Form表单提交

    2)拿到表单数据(函数传参setForm)---数据验证通过后调更新接口函数 

updateCategory = ()=>{
        const categoryId = this.category._id
        //表单验证:通过后才处理
        this.form.validateFields()
        .then(async (values) =>{
            //隐藏确认框
            this.setState({
                isModalVisible: 0,
              })
          const {categoryName} = values
          //清空输入框
          //this.form.resetFields()
          const result = await reqUpdateCategory(categoryId,categoryName)
          if(result.status === 0){
              //重新展示类别列表
              message.success('修改成功')
              this.setCategory()
          }
        })
        .catch((err)=>{
            message.info('请输入分类名称')
        })
    }

     3)注意:每次点击一项修改时,输入框都应该匹配对应修改项,这里需要:

         a. 清除前一次输入内容

         b. 传值:通过props,将放在实例的对应category :  this.category 传给form表单

         c. this.category 是在点击显示模态框的时候放在实例上的

//模态框部分  destroyOnClose={true} 清除上次表单内容
<Modal title="更新" 
                visible={isModalVisible===2? true:false} 
                onOk={this.updateCategory} 
                onCancel={this.handleCancel}
                destroyOnClose={true}
                >
                <UpdateForm categoryName={name} setForm = {(form)=>{this.form = form}}/>
            </Modal>


//表单部分 initialValue={categoryName} 初始值
<Form ref={this.formRef}>
                <Item
                     name="categoryName"
                     initialValue={categoryName}
                     rules={[
                       { required: true, message: '分类名称必须输入' },
                     ]}
                >
                    {/* ----注意 <Form.Item /> 只会对它的直接子元素绑定表单功能 */}
                    <Input placeholder="输入分类的名字" />
                </Item>
            </Form>

 

三、 商品 ---- 商品管理:商品增加、修改、详情

  1. 商品列表初始化:antd-Table 来帮忙实现后台分页获取数据

     请求获取商品接口,每次点击下一页时才发请求拿数据

     注意:1)当页面初始化时,当前请求page为1,后台会返回total总数,table根据total页面展示页数

        2)页面改变时会将当前页数作为回调传给接口继续获取下一页的数据

  

<Card title={title} extra={extra}>
                <Table 
                dataSource={products} 
                columns={columns} 
                bordered
                rowKey='_id'
                loading={loading}
                pagination= {{
                    defaultPageSize:PAGE_SIZE,
                    total,
                    onChange:(pageNum)=>{this.setProducts(pageNum)} // 页码改变的回调,参数是页码数和每页条数
                }}
                />
       </Card>

  2. 页面功能:

     1)按名称搜索、按内容搜索

       

antd做组织架构 antd管理系统_初始化

 

 

         收集select --value 和input内容:select与input绑定onChange监听回调,value改变即传入数据----this.setState

         点击搜索,拿参数发请求

         注意坑:

          搜索出的列表页面会根据当前页面下标显示,所以需要在搜索的时候传初始参pageNum=1

          这里的接口分为名称、内容两个,可合并处理,注意变量作为属性名

        

//搜索商品 (productName/productDesc)
export const reqSearchProducts = ({pageNum,pageSize,searchName,searchType})=> ajax('/manage/product/search',{
    pageNum,
    pageSize,
    [searchType]:searchName
   })

     2)商品状态(上/下架)

       得到当前点击商品数据,进行接口传参,商品status需取反

     3)展示详情页

       得到当前点击商品数据 ---- 传给详情组件(路由组件传数据 this.props.history.push('/product/detail',product)})

        ---- 所属分类需要根据parentId与categoryId获取(发请求) ----   页面渲染 

    4)修改与添加功能,同一路由组件实现

         ①  点击修改时需展现当前商品信息,点击添加不需要,根据判断上级路由传没传参来决定修改还是添加

         ②  所属分类:使用antd --- Cascader实现(组件一加载需要初始化一级分类与二级分类)

         ③  级联的二级分类是动态加载的

         注意坑:更新状态值this.setState({})到时候  解构赋值

         ④  商品图片上传:

            添加时:antd-Upload 直接请求接口

            修改时:需要初始化图片列表,将imgs数组传过来渲染到页面

 

<Upload
          action="/manage/img/upload" // 上传请求接口
          accept='image/*'//上传文件类型
          name='image' //请求参数名
          listType="picture-card"
          fileList={fileList} //上传文件数量
          onPreview={this.handlePreview} // 图片显示大图的回调
          onChange={this.handleChange}  // 图片上传过程中的回调
        >
          {fileList.length >= 2 ? null : uploadButton} 
    </Upload>

        ⑤  富文本编辑器:react-draft-wysiwyg