使用dva实现的request.js请求工具函数utils封装 并且发送请求

request.js: 

import fetch from 'dva/fetch';
import {
  notification
} from 'antd';
import qs from 'querystring';

const codeMessage = {
  200: '请求成功',
  201: '新建或修改数据成功',
  202: '一个请求已经进入后台队列',
  204: '删除数据成功',
  400: '请求失败',
  401: 'token失效',
  403: '禁止访问',
  404: '请求失败',
  406: '请求方式错误',
  500: '服务器错误',
  502: '网关错误',
  503: '服务不可用',
  504: '网关超时',
};

// 检查ajax返回的状态
function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response;
  }

  /**
   * 暂时没用,服务端返回的 status 始终为200
   *
   * @type {*|string|string}
   */
  const errorText = codeMessage[response.status] || response.statusText;
  notification.error({
    message: `请求错误 ${response.status}: ${response.url}`,
    description: errorText,
  });

  const error = new Error(response.statusText);
  error.name = response.status;
  error.response = response;
  throw error;
}

// fetch超时处理
const TIMEOUT = 100000;
const timeoutFetch = (url, options) => {
  let fetchPromise = fetch(url, options);
  let timeoutPromise = new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error('请求超时')), TIMEOUT);
  });
  return Promise.race([fetchPromise, timeoutPromise]);
};

/**
 * 请求url,返回promise 对象
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
export default function request(url, options) {
  const defaultOptions = {
    credentials: 'include',
    method: 'GET',
    mode: 'cors',
  };
  const mergeOptions = {
    ...defaultOptions,
    ...options
  };
  const userInfo = JSON.parse(window.sessionStorage.getItem('userInfo'));
  const appKey = window.sessionStorage.getItem('appKey');

  mergeOptions.headers = {
    accept: 'application/json',
    'content-type': 'application/json; charset=utf-8',
    ...mergeOptions.headers,
  };
  if (appKey) mergeOptions.headers.uuuappkey = appKey;
  if (userInfo) mergeOptions.headers.uuutoken = userInfo.sessionId;

  if (mergeOptions.method !== 'GET') {
    mergeOptions.body = JSON.stringify(mergeOptions.body);
  }

  if (mergeOptions.method !== 'POST' && mergeOptions.params) {
    url = `${url}${url.indexOf('?') !== -1 ? '&' : '?'}${qs.stringify(mergeOptions.params)}`;
  }

  if (!mergeOptions.hideTime && !mergeOptions.params) {
    url = `${url}?timeStamp=${new Date().getTime()}`;
  }

  return timeoutFetch(url, mergeOptions)
    .then(checkStatus)
    .then((response) => {
      return response.json();
    })
    .then((data) => {
      if (data.code === 200 || data.success === true) {
        return data;
      }
      if (data.code === 300) { // 接口出错
        return data;
      }
      if (data.code === 401) { // token失效
        notification.error({
          message: 'token失效',
          description: data.msg,
          key: 'error'
        });
        window.g_app._store.dispatch({
          type: 'app/logout'
        });
        return data;
      }
      if (data.code === 403) { // 没有权限
        notification.error({
          message: '没有权限',
          description: data.msg,
          key: 'error'
        });
        return data;
      }
      if (data.code >= 404 && data.code < 422) {
        notification.error({
          message: '请求失败',
          description: data.msg,
          key: 'error'
        });
        return data;
      }
      if (data.code <= 504 && data.code >= 500) {
        notification.error({
          message: '服务器错误',
          description: data.msg,
          key: 'error'
        });
        return data;
      }
    })
    .catch((error) => {
      const {
        response
      } = error;

      let msg;
      let statusCode;
      if (response && response instanceof Object) {
        const {
          status,
          statusText
        } = response;
        statusCode = status;
        msg = statusText;
      } else {
        statusCode = 600;
        msg = 'Network Error';
      }

      return Promise.reject({
        success: false,
        code: statusCode,
        msg
      });
    });
}

调用:

import request from '../utils/request';
import { apiPrefix } from '../config/projectConfig';

// 获取 scheme 列表
export function oracleSchema() {
  return request(`${apiPrefix}/api_manager/interface/api/fetchOracleSchemas`);
}

// 接口菜单层级树
export function interfaceLevel(pid) {
  return request(
    `${apiPrefix}/api_manager/interface/api/getAPILevelTree?pid=${pid}`,{
      hideTime: true,
    });
}

// 获取目录树
export function catalogTree() {
  return request(`${apiPrefix}/api_manager/interface/api/getAPICatalogTree`);
}

// 搜索菜单树
export function searchLevelTree(search) {
  return request(
    `${apiPrefix}/api_manager/interface/api/searchAPILevelTree?search=${search}`, {
      hideTime: true,
    });
}

// 查询接口上级分类树
export function apiDirectory(apiId) {
  return request(`${apiPrefix}/api_manager/interface/api/getAPIDirectory?apiId=${apiId}`, {
    hideTime: true,
  });
}

// 新增 API 树目录
export function addApiTree(params) {
  return request(`${apiPrefix}/api_manager/interface/api/addApiTree`, {
    method: 'POST',
    body: params,
  });
}

// 删除 API 树目录
export function delApiTree(params) {
  return request(`${apiPrefix}/api_manager/interface/api/deleteApiTree?apiTreeId=${params.apiTreeId}`, {
    method: 'DELETE',
    hideTime: true,
  });
}

/************************************************************************
 * 接口相关
 ************************************************************************/

// 接口列表
export function apiList(params, pageNum, pageSize) {
  return request(`${apiPrefix}/api_manager/interface/api/getApiList`, {
    method: 'POST',
    body: { ...params, pageNum, pageSize },
  });
}

// 新增接口
export function addApi(params) {
  return request(`${apiPrefix}/api_manager/interface/api/addApi`, {
    method: 'POST',
    body: params,
  });
}

// 修改接口
export function updateApi(params) {
  return request(`${apiPrefix}/api_manager/interface/api/updateApi`, {
    method: 'PUT',
    body: params,
  });
}

// 删除接口
export function delApi(params) {
  return request(`${apiPrefix}/api_manager/interface/api/deleteApi?apiId=${params.apiId}`, {
    method: 'DELETE',
    hideTime: true,
  });
}

/************************************************************************
 * sql相关
 ************************************************************************/

// 获取 sql
export function getApiSqlInfo(params) {
  return request(`${apiPrefix}/api_manager/interface/api/getApiSqlInfo?apiId=${params.apiId}`, {
    hideTime: true,
  });
}

// 保存
export function interfaceDefSave(params) {
  return request(`${apiPrefix}/api_manager/interface/api/interfaceDefSave`, {
    method: 'POST',
    body: params,
  });
}

// 获取模型列表 - 表名
export function getBizList(params, pageNum, pageSize) {
  return request(`${apiPrefix}/api_manager/interface/api/getBizList`, {
    method: 'POST',
    body: { ...params, pageNum, pageSize },
  });
}

// 获取模型列表 - 列名
export function getBizColList(bizId) {
  return request(`${apiPrefix}/api_manager/interface/api/getBizColList?bizId=${bizId}`, {
    hideTime: true,
  });
}

// 解析 sql 获得 select item 列表(出参)
export function selectItemsForSql(params) {
  return request(`${apiPrefix}/api_manager/interface/api/getSelectItemsForSql`, {
    method: 'POST',
    body: params,
  });
}

// 获取 procedure info
export function procedureInfo(params) {
  return request(`${apiPrefix}/api_manager/interface/api/fetchOracleProcedureInfo`, {
    method: 'POST',
    body: params,
  });
}

// 获取 procedure params
export function procedureParams({ owner, procedureName }) {
  return request(`${apiPrefix}/api_manager/interface/api/fetchOracleAllProcedureParams`, {
    params: {
      owner,
      procedureName,
    },
  });
}

/************************************************************************
 * auth相关
 ************************************************************************/

// 获取系统名
export function appNameApi({ apiId }) {
  return request(`${apiPrefix}/menu_manager/menu/api/getAppNameForApi?apiId=${apiId}`, {
    method: 'POST',
    hideTime: true,
  });
}

// 获取指标列表
export function indexAppName(params) {
  return request(`${apiPrefix}/menu_manager/menu/api/getIndexForAppName`, {
    method: 'POST',
    body: params,
  });
}

// 保存 auth
export function addIndexAppName(params) {
  return request(`${apiPrefix}/menu_manager/menu/api/addIndexForAppName`, {
    method: 'POST',
    body: [...params],
  });
}

dva模型调用: 

import { message } from 'antd';
import modelExtend from 'dva-model-extend';

import { pageModel } from '../../../utils/util';
import {
	addApiTree,
	addApi,

	getApiSqlInfo,
	interfaceDefSave,

	selectItemsForSql,
	procedureInfo,
	procedureParams,

	appNameApi,
	indexAppName,
	addIndexAppName,
} from '../../../services/modelInterface';

export default modelExtend(pageModel, {
	namespace: 'interfaceModal',

	state: {
		interfaceDef: {},
	},

	effects: {
		// 获取 接口定义
		* getApiSqlInfo({ payload }, { call, put }) {
			const { success, data } = yield call(getApiSqlInfo, payload);

			if (success) {
				if (data.apiType === 0) data.apiType = 1;
				yield put({
					type: 'updateState',
					payload: {
						interfaceDef: data,
					},
				});

				return true;
			} else {
				message.error('初始化失败');
			}
		},

    /************************************************************************
     * sql 弹窗相关
     ************************************************************************/
		// sql弹窗保存
		* interfaceDefSave({ payload }, { call }) {
			const { success } = yield call(interfaceDefSave, payload);
			if (success) return true;
		},

		// 解析 sql 获得 select item 列表(出参)
		* getSelectItemsForSql({ payload }, { call }) {
			const { success, data } = yield call(selectItemsForSql, payload);
			if (success) return data;
		},

		// 获取 oracleChildSchema
		* procedureInfo({ payload }, { call }) {
			const { success, data } = yield call(procedureInfo, payload);
			if (success) return data.list;
		},

		// 获取 SP 入参字段
		* procedureParams({ payload }, { call }) {
			const { success, data } = yield call(procedureParams, payload);
			if (success) return data;
		},

    /************************************************************************
     * auth 弹窗相关
     ************************************************************************/

		// 获取系统名
		* appNameApi({ payload }, { call }) {
			const { success, data } = yield call(appNameApi, payload);
			if (success) return data;
		},

		// 获取指标
		* indexAppName({ payload }, { call }) {
			const { success, data } = yield call(indexAppName, payload);
			if (success) return data;
		},

		// 保存auth
		* addIndexAppName({ payload }, { call }) {
			const { success } = yield call(addIndexAppName, payload);
			if (success) return true;
		},
	},
});

模块组成:

组件具体使用:

import React, { Component, Fragment } from 'react';
import { connect } from 'dva';
import PropTypes from 'prop-types';
import { Col, Row, Button, Modal, Collapse, Card, Icon, Tooltip, Form, Input } from 'antd';
import { ContextMenu, MenuItem } from 'react-contextmenu';
import { Page, SearchTree, CommonTable, CustomModal, CustomForm, CommonSearch, Breadcrumb } from '@/components';
import { apiList } from '../../services/modelInterface';

import { modelInterfaceColumns, participationColumns } from './config/columns';
import { sqlForm, folderForm, interfaceForm } from './config/form';
import { modelInterfaceSearch } from './config/search';
import { getCrumb } from '../../utils/util';
import ModalView from './components';
import style from './index.less';

const { Panel } = Collapse;
const { TextArea } = Input;

@connect(({ modelInterface, loading }) => ({
	...modelInterface,
	loading,
}))

class ModelInterface extends Component {
	tableRef = React.createRef();
	state = {
		editable: false,
		searchParams: {},
		selectedNode: {},

		visible: false, // 模态框状态
		modalType: '', // 模态框类型
		record: {},   // 编辑时原始数据
	};

	static getDerivedStateFromProps(props, state) {
		const { dispatch, selectedNode } = props;
		if (props.selectedNode !== state.selectedNode && props.selectedNode) {
			const { id, isDirectory } = props.selectedNode;

			if (id) {
				dispatch({ type: 'modelInterface/getBizDirectory', id });
				if (!isDirectory) {
					// dispatch({ type: 'bizFormTable/bizInfo', payload: { id } });
				}

				return { selectedNode };
			}
		}

		return null;
	}

	// 处理搜索
	handleSearch = (values) => {
		this.setState({ searchParams: values });
	};

	// 模态框状态处理
	showModal = async ({ record, modalType }) => {
		const { dispatch } = this.props;
		if (modalType === 'sql') {
			const data = await dispatch({ type: 'interfaceModal/getApiSqlInfo', payload: { apiId: record.apiId } });
			if (!data) return;
		}

		this.setState({ visible: true, modalType, record });
	};
	closeModal = () => this.setState({ visible: false, modalType: '', record: {} });

	// 选择接口
	handleSelect = async (keys, { node }) => {
		const { dispatch, selectedNode } = this.props;
		const dataRef = node.props['dataRef'];
		const flag = selectedNode.id !== dataRef.id;

		if (flag) {
			this.setState({ editable: false });
			if (dataRef['subNodeNum']) {
				await dispatch({ type: 'modelInterface/levelTreeList', pid: dataRef.id });
			}
			dispatch({ type: 'modelInterface/updateState', payload: { selectedNode: dataRef } });
		}
	};

	// 新增目录
	handleAddFolder = (e, data, target) => {
		const nodeItem = JSON.parse(target.getAttribute('data-item'));
		this.setState({ visible: true, modalType: 'folder', record: { upperApiTreeId: nodeItem.id } });
	};

	// 删除目录
	handleDelFolder = (e, data, target) => {
		const nodeItem = JSON.parse(target.getAttribute('data-item'));

		Modal.confirm({
			title: '提示',
			content: '你确定删除该目录嘛?',
			onOk: async () => {
				const { dispatch } = this.props;
				await dispatch({ type: 'modelInterface/delApiTree', payload: { apiTreeId: nodeItem.id } });
				dispatch({ type: 'modelInterface/interfaceTree' });
			},
			onCancel() { },
		});
	};

	// 删除接口
	handleDelInterface = (e, data, target) => {
		const nodeItem = JSON.parse(target.getAttribute('data-item'));
		Modal.confirm({
			title: '提示',
			content: '你确定删除该接口嘛?',
			onOk: async () => {
				const { dispatch } = this.props;
				await dispatch({ type: 'modelInterface/delApi', payload: { apiId: nodeItem.id } });
				this.tableRef.current.handleFirstPage();
			},
			onCancel() { },
		});
	};

	// 保存
	handleSubmit = async (values) => {
		const { modalType, record } = this.state;
		const { dispatch } = this.props;

		if (modalType === 'folder') {
			await dispatch({
				type: 'modelInterface/addApiTree',
				payload: { ...record, ...values },
			});
			dispatch({ type: 'modelInterface/interfaceTree' });
		}

		// 新增或编辑接口
		if (modalType === 'updateApi' || modalType === 'addApi') {
			const params = record && record.apiId ? { ...values, apiId: record.apiId } : values;
			await dispatch({
				type: `modelInterface/${modalType}`,
				payload: params,
			});
			this.tableRef.current.handleFirstPage();
		}
	};

	// 面包屑点击
	handleCrumbClick = async (item) => {
		const { dispatch } = this.props;
		dispatch({ type: 'modelInterface/levelTreeList', pid: item.id });
	};

	render() {
		const { visible, modalType, record, searchParams } = this.state;
		const { selectedNode, interfaceTree, expandedKeys, directoryInfo, catalogTree, dispatch, loading, form } = this.props;
		console.log('interfaceTree>>>>>', interfaceTree)

		const columns = [
			...modelInterfaceColumns,
			{
				title: '操作',
				dataIndex: 'operator',
				render: (text, record) => (
					<div className="btn-group">
						<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'sql', record })}>SQL</Button>
						<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'updateApi', record })}>修改</Button>
						<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'auth', record })}>授权</Button>
					</div>
				),
			},
		];
		const paramsColumns = [
			...participationColumns,
			{
				title: '操作',
				dataIndex: 'operator',
				render: (text, record) => (
					<div className="btn-group">
						<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'sql', record })}>SQL</Button>
						<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'updateApi', record })}>修改</Button>
						<Button type="primary" size="small" onClick={() => this.showModal({ modalType: 'auth', record })}>授权</Button>
					</div>
				),
			},
		];

		return (
			<Page className="pageContainer" loading={loading.effects['modelInterface/interfaceTree']}>
				<Row gutter={12}>
					{/* 树列表 */}
					<Col xs={{ span: 24 }} lg={{ span: 6 }} className="treeNav">
						<SearchTree
							dispatch={dispatch}
							placeholder='请输入表名称'
							config={{ key: 'id', title: 'name' }}
							showRightMenu={true}
							showRemoteSearch={true}
							treeData={interfaceTree}
							defaultExpandedKeys={expandedKeys}
							iconFlagOptions={{ icon: 'api' }}
							handleSelect={this.handleSelect}
							modelFunc="modelInterface/searchTreeWithColCount"
						/>

						<ContextMenu id="parent_unique_identifier">
							<MenuItem key="addInterface" onClick={() => this.showModal({ modalType: 'addApi' })}>新增接口</MenuItem>
							<MenuItem divider />
							<MenuItem key="addFolder" onClick={this.handleAddFolder}>新增目录</MenuItem>
							<MenuItem divider />
							<MenuItem key="delFolder" onClick={this.handleDelFolder}>删除目录</MenuItem>
						</ContextMenu>

						<ContextMenu id="child_unique_identifier">
							<MenuItem key="delInterface" onClick={this.handleDelInterface}>删除接口</MenuItem>
						</ContextMenu>
					</Col>

					{/* 表格列表 */}
					<Col xs={{ span: 24 }} lg={{ span: 18 }} className="tableContainer">
						<div className="gutter-box">
							<Breadcrumb breadcrumbList={getCrumb(directoryInfo, { title: 'name', click: this.handleCrumbClick })} />

							{/* <CommonSearch
								style={{ marginTop: 12 }}
								columnNumber={2}
								showResetBtn={false}
								formList={modelInterfaceSearch}
								handleSearch={this.handleSearch}
							/> */}

							<Collapse defaultActiveKey={['1']} style={{ marginBottom: 20 }} >
								<Panel header="sql信息" key="1">
									<div>1111</div>
								</Panel>
							</Collapse>

							<Collapse defaultActiveKey={['1']} style={{ marginBottom: 20 }} >
								<Panel header="入参" key="1">
									<CommonTable
										rowKey="apiId"
										bordered={false}
										selectType={false}
										ref={this.tableRef}
										columns={paramsColumns}
										fetchList={apiList}
										searchParams={{ upperId: selectedNode.id, ...searchParams }}
									/>
								</Panel>
							</Collapse>

							{/* 系统 */}
							<Row gutter={24}>
								{[{ appName: 'UCM', appComment: '系统内容' }, { appName: 'ACP', appComment: '系统内容' },] > 0 && [{ appName: 'UCM', appComment: '系统内容' }, { appName: 'ACP', appComment: '系统内容' },].map((sys, index) => (
									<Col span={6} key={sys.appKey} style={{ marginBottom: 24 }}>
										<Card
											className={style.sysBox}
											bodyStyle={{ padding: '24px', height: 150 }}
										>
											<Row>
												<Col span={20} className='name'>{sys.appName}</Col>
												<Col span={4} className='operate-box'>
													<Tooltip placement='top' title='编辑'>
														<Icon type='edit' style={{ fontSize: '22px', paddingTop: '6px' }} onClick={() => { this.onShowEditModel(sys); }} />
													</Tooltip>
												</Col>
											</Row>
											<Row>
												<Col span={24} className='desc'>{sys.appComment}</Col>
											</Row>
										</Card>
									</Col>
								))}
							</Row>

							{/* 菜单 */}
							<Row gutter={24}>
								{[{ appName: 'UCM', appComment: '系统内容' }, { appName: 'ACP', appComment: '系统内容' },].length > 0 && [{ appName: 'UCM', appComment: '系统内容' }, { appName: 'ACP', appComment: '系统内容' },].map((sys, index) => (
									<Col span={6} key={sys.appKey} style={{ marginBottom: 24 }}>
										<Card
											className={style.sysBox}
											bodyStyle={{ padding: '24px', height: 150 }}
										>
											<Row>
												<Col span={20} className='name'>{sys.appName}</Col>
												<Col span={4} className='operate-box'>
													<Tooltip placement='top' title='编辑'>
														<Icon type='edit' style={{ fontSize: '22px', paddingTop: '6px' }} onClick={() => { this.onShowEditModel(sys); }} />
													</Tooltip>
												</Col>
											</Row>
											<Row>
												<Col span={24} className='desc'>{sys.appComment}</Col>
											</Row>
										</Card>
									</Col>
								))}
							</Row>

							<Collapse defaultActiveKey={['1']} >
								<Panel header="出参" key="1">
									<CommonTable
										rowKey="apiId"
										bordered={false}
										selectType={false}
										ref={this.tableRef}
										columns={paramsColumns}
										fetchList={apiList}
										searchParams={{ upperId: selectedNode.id, ...searchParams }}
									/>
								</Panel>
							</Collapse>

						</div>
					</Col>
				</Row>

				{/* 目录、接口弹窗 */}
				{
					['auth', 'sql'].indexOf(modalType) === -1 && (
						<CustomModal
							visible={visible}
							record={record}
							onCancel={this.closeModal}
							onSubmit={this.handleSubmit}
							renderTitle={() => {
								if (modalType === 'folder') {
									return (record && !record.id) ? '新增目录' : '编辑目录';
								}

								if (modalType === 'addApi') {
									return '新增接口';
								}

								if (modalType === 'updateApi') {
									return '编辑接口';
								}
							}}
							renderContent={(formOpts) => (
								<Fragment>
									{modalType === 'folder' && <CustomForm formList={folderForm} {...formOpts} />}
									{(modalType === 'addApi' || modalType === 'updateApi') && <CustomForm formList={interfaceForm(catalogTree)} {...formOpts} />}
								</Fragment>
							)}
						/>
					)
				}

				{/* 授权、SQL弹窗 */}
				<ModalView visible={visible} modalType={modalType} record={record} onCancel={this.closeModal} />
			</Page>
		);
	}
}

export default Form.create()(ModelInterface);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hzxOnlineOk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值