import fetch from 'dva/fetch';
import {
? notification
} from 'antd';
import qs from 'querystring';
const codeMessage = {
? 200: '請求成功',
? 201: '新建或修改數(shù)據(jù)成功',
? 202: '一個請求已經(jīng)進入后臺隊列',
? 204: '刪除數(shù)據(jù)成功',
? 400: '請求失敗',
? 401: 'token失效',
? 403: '禁止訪問',
? 404: '請求失敗',
? 406: '請求方式錯誤',
? 500: '服務(wù)器錯誤',
? 502: '網(wǎng)關(guān)錯誤',
? 503: '服務(wù)不可用',
? 504: '網(wǎng)關(guān)超時',
};
// 檢查ajax返回的狀態(tài)
function checkStatus(response) {
? if (response.status >= 200 && response.status < 300) {
? ? return response;
? }
? /**
? * 暫時沒用,服務(wù)端返回的 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) { // 沒有權(quán)限
? ? ? ? notification.error({
? ? ? ? ? message: '沒有權(quán)限',
? ? ? ? ? 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: '服務(wù)器錯誤',
? ? ? ? ? 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
? ? ? });
? ? });
}
調(diào)用:
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,
? });
}
/************************************************************************
* 接口相關(guān)
************************************************************************/
// 接口列表
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相關(guān)
************************************************************************/
// 獲取 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相關(guān)
************************************************************************/
// 獲取系統(tǒng)名
export function appNameApi({ apiId }) {
? return request(`${apiPrefix}/menu_manager/menu/api/getAppNameForApi?apiId=${apiId}`, {
? ? method: 'POST',
? ? hideTime: true,
? });
}
// 獲取指標(biāo)列表
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模型調(diào)用:?
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 彈窗相關(guān)
? ? ************************************************************************/
// 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 入?yún)⒆侄?/p>
* procedureParams({ payload }, { call }) {
const { success, data } = yield call(procedureParams, payload);
if (success) return data;
},
? ? /************************************************************************
? ? * auth 彈窗相關(guān)
? ? ************************************************************************/
// 獲取系統(tǒng)名
* appNameApi({ payload }, { call }) {
const { success, data } = yield call(appNameApi, payload);
if (success) return data;
},
// 獲取指標(biāo)
* 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, // 模態(tài)框狀態(tài)
modalType: '', // 模態(tài)框類型
record: {},? // 編輯時原始數(shù)據(jù)
};
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 });
};
// 模態(tài)框狀態(tài)處理
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 })}>授權(quán)</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 })}>授權(quán)</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="入?yún)? key="1">
<CommonTable
rowKey="apiId"
bordered={false}
selectType={false}
ref={this.tableRef}
columns={paramsColumns}
fetchList={apiList}
searchParams={{ upperId: selectedNode.id, ...searchParams }}
/>
</Panel>
</Collapse>
{/* 系統(tǒng) */}
<Row gutter={24}>
{[{ appName: 'UCM', appComment: '系統(tǒng)內(nèi)容' }, { appName: 'ACP', appComment: '系統(tǒng)內(nèi)容' },] > 0 && [{ appName: 'UCM', appComment: '系統(tǒng)內(nèi)容' }, { appName: 'ACP', appComment: '系統(tǒng)內(nèi)容' },].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: '系統(tǒng)內(nèi)容' }, { appName: 'ACP', appComment: '系統(tǒng)內(nèi)容' },].length > 0 && [{ appName: 'UCM', appComment: '系統(tǒng)內(nèi)容' }, { appName: 'ACP', appComment: '系統(tǒng)內(nèi)容' },].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>
)}
/>
)
}
{/* 授權(quán)、SQL彈窗 */}
<ModalView visible={visible} modalType={modalType} record={record} onCancel={this.closeModal} />
</Page>
);
}
}
export default Form.create()(ModelInterface);