umi.js学习(九)、antd pro中使用dva数据流_umi里怎么获取其他model的数据-程序员宅基地

技术标签: js  umijs  react  React.js  andt pro  

  • 效果展示

在这里插入图片描述

  • 创建模块

在这里插入图片描述

  • 配置路由及配置代理
在config/proxy.ts中

/**
 * 在生产环境 代理是无法生效的,所以这里没有生产环境的配置
 * The agent cannot take effect in the production environment
 * so there is no configuration of the production environment
 * For details, please see
 * https://pro.ant.design/docs/deploy
 */
export default {
    
  dev: {
    
    '/api': {
    
      target: 'http://*****.cn:9036',
      changeOrigin: true,
      pathRewrite: {
     '^/api': '' },
    },
  },
};

  • 封装网络请求request.ts
/** Request 网络请求工具 更详细的 api 文档: https://github.com/umijs/umi-request */
import {
     message } from 'antd';
import {
     extend } from 'umi-request';
import {
     errorHandler, requestOpt, reLogin } from './requestopt';
import {
     setToken, getToken } from '@/utils/auth'

/** 配置request请求时的默认参数 */
const request = extend({
    
  errorHandler, // 默认错误处理
  credentials: 'include', // 默认请求是否带上cookie
});

// request拦截器, 改变url 或 options.
request.interceptors.request.use((url, options) => {
    
  return requestOpt(url, options)
});

// response拦截器, 处理response
request.interceptors.response.use(async response => {
    
  const data = await response.clone().json();
  const token = await response.headers.get('token')
  if (token && token != getToken()) {
    
    setToken(token)
  }
  if (process.env.NODE_ENV === 'development') {
    
    console.log(data)
  }
  if (data.code !== 200) {
    
    message.error(data.message);
    if (data.code === 300) {
    
      reLogin()
    }
    return data.message
  } else {
    
    return response;
  }
})
export default request

import {
     message } from 'antd';
import {
     RequestOptionsInit } from 'umi-request';
import {
     getToken } from '@/utils/auth'
import {
     getPageQuery } from '@/utils/utils';
import {
     history } from 'umi';
import {
     stringify } from 'querystring';
import {
     removeToken } from '@/utils/auth'

const codeMessage: {
     [status: string]: string } = {
    
    200: '服务器成功返回请求的数据。',
    201: '新建或修改数据成功。',
    202: '一个请求已经进入后台排队(异步任务)。',
    204: '删除数据成功。',
    400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
    401: '用户没有权限(令牌、用户名、密码错误)。',
    403: '用户得到授权,但是访问是被禁止的。',
    404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
    406: '请求的格式不可得。',
    410: '请求的资源被永久删除,且不会再得到的。',
    422: '当创建一个对象时,发生一个验证错误。',
    500: '服务器发生错误,请检查服务器。',
    502: '网关错误。',
    503: '服务不可用,服务器暂时过载或维护。',
    504: '网关超时。',
};

/** 异常处理程序 */
export const errorHandler = (error: {
     response: Response }): Response => {
    
    const {
     response } = error;
    console.log(response)
    if (response && response.status) {
    
        const errorText = codeMessage[response.status] || response.statusText;
        message.error(errorText);
    } else if (!response) {
    
        message.error('您的网络发生异常,无法连接服务器');
    }
    return response;
};


/**
 * request拦截器, 改变url 或 options.
 * @returns 
 */
export const requestOpt = (url: string, options: RequestOptionsInit): object => {
    
    if (process.env.NODE_ENV === 'development'){
    
        console.log("url==>", url)
        if (options.data) {
    
            console.log("options.data==>", JSON.stringify(options.data))
        } else if (options.params && Object.keys(options.params).length > 0) {
    
            console.log("options.params==>", options.params)
        }
    }
    if (process.env.NODE_ENV === 'development' && !options.prefix) {
    
        url = '/api' + url
    }
    const headers = {
    
        'token': getToken(),
    };
    return {
    
        url: url,
        options: {
     ...options, headers },
    };
}

export const reLogin = () => {
    
    const {
     redirect } = getPageQuery();
    // Note: There may be security issues, please note
    if (window.location.pathname !== '/user/login' && !redirect) {
    
        removeToken()
        history.replace({
    
            pathname: '/user/login',
            search: stringify({
    
                redirect: window.location.href,
            }),
        });
    }
}

  • 网络请求接口(service.ts中)
import request from '@/utils/request';
import type {
     ListParamsType } from '@/services/data'
import type {
     AccountInfoType } from './data'
/**
 * 列表数据
 * @param params 
 * @returns 
 */
export async function getUserList(params: ListParamsType): Promise<any> {
    
    return request('/Admin/UserList', {
    
        method: 'POST',
        data: {
     ...params },
        requestType: 'form'
    });
}

/**
 * 獲取账户信息
 * @param params 
 * @returns 
 */
export async function getUserInfo(params: {
     id: string }): Promise<any> {
    
    return request('/Admin/UserAdd', {
    
        method: 'GET',
        params: {
     ...params },
        requestType: 'form'
    });
}
/**
 * 用户添加
 * @param params 
 * @returns 
 */
export async function userAdd(params: AccountInfoType): Promise<any> {
    
    return request('/Admin/UserAdd', {
    
        method: 'POST',
        data: {
     ...params },
        requestType: 'form'
    });
}
/**
 * 冻结
 * @param params 
 * @returns 
 */
export async function userFrozen(params: {
     id: string }): Promise<any> {
    
    return request('/Admin/UserFroze', {
    
        method: 'POST',
        data: {
     ...params },
        requestType: 'form'
    });
}

  • 取公用数据类型(data.d.ts中)

/**
 * 封装后台返回的数据
 */
export type SingleUserListType = {
    
    id: number,
    level?: number,
    account?: string,
    password?: string,
    contact_name?: string,
    contact_mobile?: string,
    remark?: string,
    role_id?: number,
    is_enable?: number,
    ctime?: string,
    uptime?: string,
    role_name?: string,
    ctime_str: string,
}

/**
 * 添加编辑账户
 */
export type UserAddType = {
    
    user_id?: number,
    account?: string,
    account_password?: string,
    contact_name?: string,
    contact_mobile?: number,
    role_id?: number,
};


/**
 * 獲取账户信息
 */
export type AccountInfoType = {
    
    user_id?: number,
    account?: string,
    password?: string,
    contact_name?: string,
    contact_mobile?: number,
    role_id?: number,
    id?: number
};

/**
 * 獲取账户信息列表
 */
export type AccountRoleListType = {
    
    ctime?: number,
    ctime_str?: string,
    id?: number,
    is_enable?: number,
    menu_ids?: string,
    role_name?: string,
    uptime?: number,
    value?:number,
    label?:string,
    disabled?:boolean
};
  • model.ts中dva数据获取
import {
     Effect, Reducer } from 'umi';

//导入service远端数据请求
import {
     getUserList, getUserInfo, userAdd, userFrozen } from './service'

import {
     SingleUserListType, AccountInfoType, AccountRoleListType } from './data'
import {
     message } from 'antd';


export type AccountListState = {
    
    rows: SingleUserListType[];
    total: number;
    info: AccountInfoType;
    role_list: AccountRoleListType[]
}

interface AccountListModelType {
    
    namespace: string
    state: AccountListState;//封装后台返回的数据
    effects: {
    
        getRemoteUserList: Effect;
        getRemoteUserInfoData: Effect;
        postRemoteUserAdd: Effect;
        postRemoteUserFrozen: Effect;
    };
    reducers: {
    
        getUserList: Reducer<AccountListState>,
        getUserInfoData: Reducer<AccountListState>,
    };
}

const AccountListModel: AccountListModelType = {
    
    namespace: 'accountListData',
    state: {
    
        rows: [],
        total: 0,
        info: {
    },
        role_list: []
    },
    effects: {
    
        *getRemoteUserList({
     payload }, {
     call, put }) {
    
            //从service中获取数据(service主要用于接口请求)
            const response = yield call(getUserList, {
     ...payload })
            if (response && response instanceof Object) {
    
                yield put({
    
                    type: 'getUserList',//这个是将数据给reducers中哪个方法
                    payload: response.data  //注意这里传递一个数组会出问题,原因待定
                })
            }
        },
        //獲取账户信息
        *getRemoteUserInfoData({
     payload }, {
     call, put }) {
    
            const response = yield call(getUserInfo, {
     ...payload })
            if (response && response instanceof Object) {
    
                let {
     role_list } = response.data
                role_list.forEach((element: AccountRoleListType) => {
    
                    element.value = element.id,
                        element.label = element.role_name,
                        element.disabled = element.is_enable == 0
                })
                response.data.role_list = role_list
                response.data.info = {
     ...response.data.info, role_id: (response.data.info.role_id == 0 ? '' : response.data.info.role_id) }
                yield put({
    
                    type: 'getUserInfoData',
                    payload: response.data
                })
            }
        },
        //用户添加
        *postRemoteUserAdd({
     payload }, {
     call, put }) {
    
            const response = yield call(userAdd, {
     ...payload })
            if (response && response instanceof Object) {
    
                message.success(response.message)
            }
        },
        //冻结
        *postRemoteUserFrozen({
     payload }, {
     call, put }) {
    
            const response = yield call(userFrozen, {
     ...payload })
            if (response && response instanceof Object) {
    
                message.success(response.message)
            }
        }
    },
    //同步
    reducers: {
    
        getUserList(state, action) {
    
            return {
    
                ...state,
                ...action.payload,
            };
        },
        getUserInfoData(state, action) {
    
            return {
    
                ...state,
                ...action.payload,
            };
        }
    },
}

export default AccountListModel;
  • 首页index.tsx展示数据
import React, {
     useRef, FC } from 'react';
import type {
     ProColumns, ActionType } from '@ant-design/pro-table';
import {
     PageContainer, WaterMark } from '@ant-design/pro-layout';
import {
     Card, Space } from 'antd';
import {
     connect, Dispatch, AccountListState } from 'umi';
import type {
     ListParamsType } from '@/services/data'
import {
     SingleUserListType, UserAddType } from './data'
import ProTable from '@ant-design/pro-table'
import './index.less'
import AddAccountModal from './components/addaccountmodal'
/**
 * 声明下方 props 类型
 */
type accountListPageProps = {
    
  listData: AccountListState,
  dispatch: Dispatch
}

const AccountListPage: FC<accountListPageProps> = (props) => {
    

  //获取从model中来的数据    
  const {
     listData, dispatch } = props
  //配置ProTable
  const ref = useRef<ActionType>();

  /**
    * ProTable的网络请求 request
    */
  const requestHandler = async (params: ListParamsType) => {
    
    await dispatch({
    
      type: 'accountListData/getRemoteUserList',
      payload: params = {
     ...params }
    })
    return {
    }
  }

  //提交数据
  const onCreateFinish = async (values: UserAddType) => {
    
    await dispatch({
    
      type: 'accountListData/postRemoteUserAdd',
      payload: {
     ...values }
    })
    ref.current?.reload();
    return true
  }
  /**
    * 启用或停用
    * @param id 
    */
  const onAccountTypeClick = async (id: number) => {
    
    await dispatch({
    
      type: 'accountListData/postRemoteUserFrozen',
      payload: {
     id: id }
    })
    ref.current?.reload();
  }

  const columns: ProColumns<SingleUserListType>[] = [
    {
    
      title: 'ID',
      dataIndex: 'id',
      width: 128,
      search: false,
      align: 'left'
    },
    {
    
      title: '账号名称',
      dataIndex: 'account',
      align: 'left',
    },
    {
    
      title: '状态',
      dataIndex: 'is_enable',
      search: false,
      align: 'left',
      render: (text) => <span>{
    text == 1 ? `启用` : `停用`}</span>,
    },
    {
    
      title: '联系人姓名',
      dataIndex: 'contact_name',
      hideInTable: true,
    },
    {
    
      title: '创建时间',
      dataIndex: 'ctime_str',
      search: false,
      align: 'left'
    },
    {
    
      title: '操作',
      align: 'center',
      render: (text, record) => (
        <Space size="middle">
          <AddAccountModal
            userId={
    record.id}
            itemInfo={
    listData.info}
            roleList={
    listData.role_list}
            dispatch={
    dispatch}
            showType={
    1}
            onCreateFinish={
    onCreateFinish} />
          {
    
            record.is_enable == 0 ? <a className="start-using" onClick={
    () => onAccountTypeClick(record.id)}>启用</a> :
              <a className="stop-using" onClick={
    () => onAccountTypeClick(record.id)}>停用</a>
          }
        </Space>
      ),
    },
  ];
  return (
    <PageContainer title="账号列表">
      <Card>
        <WaterMark content="地环院内部管理系统">
          <ProTable
            actionRef={
    ref}
            request={
    requestHandler}
            columns={
    columns}
            dataSource={
    listData.rows}
            rowKey="id"
            search={
    {
    
              labelWidth: 'auto',
            }}
            pagination={
    {
    
              showQuickJumper: true,
              pageSize: 10,
              total: listData.total
            }}
            form={
    {
    
              span: 6
            }}
            toolBarRender={
    () => [
              <AddAccountModal
                userId={
    0}
                itemInfo={
    listData.info}
                roleList={
    listData.role_list}
                dispatch={
    dispatch}
                showType={
    0}
                onCreateFinish={
    onCreateFinish} />
            ]}
          />
        </WaterMark>
      </Card>
    </PageContainer>
  )
}

const mapStateToProps = ({
     accountListData }: {
     accountListData: AccountListState }) => {
    
  return {
    
    listData: accountListData,//这里的usersData就是model中的namespace
  }
}
export default connect(mapStateToProps)(AccountListPage)
  • 弹框 addaccountmodal.tsx
import React, {
     useEffect, FC } from 'react'
import {
     Button, Form } from 'antd';
import {
    
    ModalForm,
    ProFormText,
    ProFormSelect,
} from '@ant-design/pro-form';
import {
     PlusOutlined } from '@ant-design/icons';
import type {
     UserAddType } from '../data'
import {
     Dispatch } from 'umi';

type AddAccountModalProps = {
    
    showType: number
    onCreateFinish: (values: UserAddType) => void
    dispatch: Dispatch
    userId: number
    itemInfo: any
    roleList: any
}

const AddAccountModal: FC<AddAccountModalProps> = (props) => {
    

    const {
     showType, onCreateFinish, dispatch, userId, itemInfo, roleList } = props

    useEffect(() => {
    
        form.setFieldsValue({
    
            ...itemInfo,
        })
    }, [itemInfo])

    const [form] = Form.useForm();
    const layout = {
    
        labelCol: {
     span: 5 },
    };

    //ModalForm状态改变
    const onVisibleChange = async (value: boolean) => {
    
        if (value) {
    
            await dispatch({
    
                type: 'accountListData/getRemoteUserInfoData',
                payload: {
     id: userId }
            })
        }
    }

    return (
        <ModalForm<{
    
            account: string;
            account_password: string;
            contact_name: string;
            contact_mobile: number;
            role_id: number;
            user_id: number
        }>
            width="35%"
            {
    ...layout}
            form={
    form}
            title={
    showType === 0 ? `添加账户` : `编辑账户`}
            trigger={
    
                showType === 0 ? (
                    <Button type="primary">
                        <PlusOutlined />
                        添加账户
                    </Button>
                ) : (
                    <a>编辑</a>
                )
            }
            onFinish={
    async (values) => {
    
                return onCreateFinish(values = {
     ...values, user_id: userId });
            }}
            onVisibleChange={
    onVisibleChange}
        >
            <ProFormText name="account"
                label="账户名称:"
                placeholder="请填写账户名称"
                disabled={
    showType !== 0}
                rules={
    [{
     required: true, message: '您还没填写账户名称' }]}
            />
            <ProFormText name="account_password"
                label="账户密码:"
                placeholder={
    userId == 0 ? `请填写账户密码` : `修改则填写新密码,不修改则不填`}
                rules={
    [{
    
                    required: true, validator: (rule, value = '', callback) => {
    
                        if (Object.keys(value).length == 0) {
    
                            if (userId) {
    
                                return Promise.resolve()
                            } else {
    
                                return Promise.reject('您还没填写账户密码');
                            }
                        } else if (!new RegExp(/^(?!^(\d+|[a-zA-Z]+|[~!@#$%^&*?]+)$)^[\w~!@#$%^&*?]{
    6,20}$/).test(value)) {
    
                            return Promise.reject('必须含有数字、字母、特殊符号三项中间的两项,6到20位')
                        } else {
    
                            return Promise.resolve()
                        }
                    }
                }]}
            />
            <ProFormText name="contact_name"
                label="姓名:"
                placeholder="请填写姓名"
                rules={
    [{
     required: true, message: '您还没填写姓名' }]}
            />
            <ProFormText name="contact_mobile"
                label="手机号:"
                placeholder="请填写手机号"
                rules={
    [{
     required: true, message: '您还没填写手机号' },
                {
    
                    pattern: /^((13[0-9])|(14[5,7])|(15[0-3,5-9])|166|(17[0,3,5-8])|(18[0-9])|19[1,8,9]|(147))([0-9]{
    8})+$/,
                    message: '手机号格式不正确',
                },]}
            />
            <ProFormSelect
                options={
    roleList}
                width="md"
                name="role_id"
                label="绑定角色:"
                placeholder="请选择绑定角色"
                rules={
    [{
     required: true, message: '您还没选择绑定角色' }]}
            />
        </ModalForm>
    );
};

export default AddAccountModal;
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/huangxiaoguo1/article/details/116201356

智能推荐

从零开始搭建Hadoop_创建一个hadoop项目-程序员宅基地

文章浏览阅读331次。第一部分:准备工作1 安装虚拟机2 安装centos73 安装JDK以上三步是准备工作,至此已经完成一台已安装JDK的主机第二部分:准备3台虚拟机以下所有工作最好都在root权限下操作1 克隆上面已经有一台虚拟机了,现在对master进行克隆,克隆出另外2台子机;1.1 进行克隆21.2 下一步1.3 下一步1.4 下一步1.5 根据子机需要,命名和安装路径1.6 ..._创建一个hadoop项目

心脏滴血漏洞HeartBleed CVE-2014-0160深入代码层面的分析_heartbleed代码分析-程序员宅基地

文章浏览阅读1.7k次。心脏滴血漏洞HeartBleed CVE-2014-0160 是由heartbeat功能引入的,本文从深入码层面的分析该漏洞产生的原因_heartbleed代码分析

java读取ofd文档内容_ofd电子文档内容分析工具(分析文档、签章和证书)-程序员宅基地

文章浏览阅读1.4k次。前言ofd是国家文档标准,其对标的文档格式是pdf。ofd文档是容器格式文件,ofd其实就是压缩包。将ofd文件后缀改为.zip,解压后可看到文件包含的内容。ofd文件分析工具下载:点我下载。ofd文件解压后,可以看到如下内容: 对于xml文件,可以用文本工具查看。但是对于印章文件(Seal.esl)、签名文件(SignedValue.dat)就无法查看其内容了。本人开发一款ofd内容查看器,..._signedvalue.dat

基于FPGA的数据采集系统(一)_基于fpga的信息采集-程序员宅基地

文章浏览阅读1.8w次,点赞29次,收藏313次。整体系统设计本设计主要是对ADC和DAC的使用,主要实现功能流程为:首先通过串口向FPGA发送控制信号,控制DAC芯片tlv5618进行DA装换,转换的数据存在ROM中,转换开始时读取ROM中数据进行读取转换。其次用按键控制adc128s052进行模数转换100次,模数转换数据存储到FIFO中,再从FIFO中读取数据通过串口输出显示在pc上。其整体系统框图如下:图1:FPGA数据采集系统框图从图中可以看出,该系统主要包括9个模块:串口接收模块、按键消抖模块、按键控制模块、ROM模块、D.._基于fpga的信息采集

微服务 spring cloud zuul com.netflix.zuul.exception.ZuulException GENERAL-程序员宅基地

文章浏览阅读2.5w次。1.背景错误信息:-- [http-nio-9904-exec-5] o.s.c.n.z.filters.post.SendErrorFilter : Error during filteringcom.netflix.zuul.exception.ZuulException: Forwarding error at org.springframework.cloud..._com.netflix.zuul.exception.zuulexception

邻接矩阵-建立图-程序员宅基地

文章浏览阅读358次。1.介绍图的相关概念  图是由顶点的有穷非空集和一个描述顶点之间关系-边(或者弧)的集合组成。通常,图中的数据元素被称为顶点,顶点间的关系用边表示,图通常用字母G表示,图的顶点通常用字母V表示,所以图可以定义为:  G=(V,E)其中,V(G)是图中顶点的有穷非空集合,E(G)是V(G)中顶点的边的有穷集合1.1 无向图:图中任意两个顶点构成的边是没有方向的1.2 有向图:图中..._给定一个邻接矩阵未必能够造出一个图

随便推点

MDT2012部署系列之11 WDS安装与配置-程序员宅基地

文章浏览阅读321次。(十二)、WDS服务器安装通过前面的测试我们会发现,每次安装的时候需要加域光盘映像,这是一个比较麻烦的事情,试想一个上万个的公司,你天天带着一个光盘与光驱去给别人装系统,这将是一个多么痛苦的事情啊,有什么方法可以解决这个问题了?答案是肯定的,下面我们就来简单说一下。WDS服务器,它是Windows自带的一个免费的基于系统本身角色的一个功能,它主要提供一种简单、安全的通过网络快速、远程将Window..._doc server2012上通过wds+mdt无人值守部署win11系统.doc

python--xlrd/xlwt/xlutils_xlutils模块可以读xlsx吗-程序员宅基地

文章浏览阅读219次。python–xlrd/xlwt/xlutilsxlrd只能读取,不能改,支持 xlsx和xls 格式xlwt只能改,不能读xlwt只能保存为.xls格式xlutils能将xlrd.Book转为xlwt.Workbook,从而得以在现有xls的基础上修改数据,并创建一个新的xls,实现修改xlrd打开文件import xlrdexcel=xlrd.open_workbook('E:/test.xlsx') 返回值为xlrd.book.Book对象,不能修改获取sheett_xlutils模块可以读xlsx吗

关于新版本selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘等问题_unresolved attribute reference 'find_element_by_id-程序员宅基地

文章浏览阅读8.2w次,点赞267次,收藏656次。运行Selenium出现'WebDriver' object has no attribute 'find_element_by_id'或AttributeError: 'WebDriver' object has no attribute 'find_element_by_xpath'等定位元素代码错误,是因为selenium更新到了新的版本,以前的一些语法经过改动。..............._unresolved attribute reference 'find_element_by_id' for class 'webdriver

DOM对象转换成jQuery对象转换与子页面获取父页面DOM对象-程序员宅基地

文章浏览阅读198次。一:模态窗口//父页面JSwindow.showModalDialog(ifrmehref, window, 'dialogWidth:550px;dialogHeight:150px;help:no;resizable:no;status:no');//子页面获取父页面DOM对象//window.showModalDialog的DOM对象var v=parentWin..._jquery获取父window下的dom对象

什么是算法?-程序员宅基地

文章浏览阅读1.7w次,点赞15次,收藏129次。算法(algorithm)是解决一系列问题的清晰指令,也就是,能对一定规范的输入,在有限的时间内获得所要求的输出。 简单来说,算法就是解决一个问题的具体方法和步骤。算法是程序的灵 魂。二、算法的特征1.可行性 算法中执行的任何计算步骤都可以分解为基本可执行的操作步,即每个计算步都可以在有限时间里完成(也称之为有效性) 算法的每一步都要有确切的意义,不能有二义性。例如“增加x的值”,并没有说增加多少,计算机就无法执行明确的运算。 _算法

【网络安全】网络安全的标准和规范_网络安全标准规范-程序员宅基地

文章浏览阅读1.5k次,点赞18次,收藏26次。网络安全的标准和规范是网络安全领域的重要组成部分。它们为网络安全提供了技术依据,规定了网络安全的技术要求和操作方式,帮助我们构建安全的网络环境。下面,我们将详细介绍一些主要的网络安全标准和规范,以及它们在实际操作中的应用。_网络安全标准规范