Browse Source

feat: 项目管理列表增删减

lanjianrong 3 years atrás
parent
commit
f1dc78e0f4

+ 1 - 1
config/defaultSettings.ts

@@ -15,7 +15,7 @@ const Settings: LayoutSettings & {
   title: '财审管理系统',
   pwa: false,
   logo: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
-  iconfontUrl: '//at.alicdn.com/t/font_2906856_nyfthtvyads.js'
+  iconfontUrl: '//at.alicdn.com/t/font_2906856_nbx546tuh5.js'
 }
 
 export default Settings

+ 9 - 9
config/proxy.ts

@@ -9,23 +9,23 @@
 export default {
   dev: {
     '/api/': {
-      target: 'https://preview.pro.ant.design',
+      target: 'http://fabqa.com',
       changeOrigin: true,
-      pathRewrite: { '^': '' },
-    },
+      pathRewrite: { '^': '' }
+    }
   },
   test: {
     '/api/': {
       target: 'https://preview.pro.ant.design',
       changeOrigin: true,
-      pathRewrite: { '^': '' },
-    },
+      pathRewrite: { '^': '' }
+    }
   },
   pre: {
     '/api/': {
       target: 'your pre url',
       changeOrigin: true,
-      pathRewrite: { '^': '' },
-    },
-  },
-};
+      pathRewrite: { '^': '' }
+    }
+  }
+}

+ 40 - 3
config/routes.ts

@@ -19,14 +19,51 @@
     ]
   },
   {
+    path: '/',
+    redirect: '/dashboard'
+  },
+  {
     path: '/dashboard',
     name: 'dashboard',
-    icon: 'rich-shouye',
+    icon: 'icon-shouye',
     component: './Dashboard'
   },
   {
-    path: '/',
-    redirect: '/dashboard'
+    path: '/project',
+    name: 'project',
+    icon: 'icon-city-one-add',
+    routes: [
+      {
+        path: '/project',
+        redirect: '/project/management'
+      },
+      {
+        path: 'management',
+        name: 'management',
+        component: './Project/Management'
+      }
+    ]
+  },
+  {
+    path: 'institutions',
+    name: 'institutions',
+    icon: 'icon-every-user',
+    routes: [
+      {
+        path: '/institutions',
+        redirect: '/institutions/company'
+      },
+      {
+        path: 'company',
+        name: 'company',
+        component: './Institutions/Company'
+      },
+      {
+        path: 'staff',
+        name: 'staff',
+        component: './Institutions/Staff'
+      }
+    ]
   },
   {
     component: './404'

+ 128 - 9
src/app.tsx

@@ -1,9 +1,11 @@
 import type { Settings as LayoutSettings } from '@ant-design/pro-layout'
 import { PageLoading } from '@ant-design/pro-layout'
-import type { RunTimeLayoutConfig } from 'umi'
-import { history } from 'umi'
+import type { RequestConfig, RunTimeLayoutConfig } from 'umi'
+import { getIntl, getLocale, history } from 'umi'
+import type { RequestOptionsInit, ResponseError } from 'umi-request'
 import RightContent from '@/components/RightContent'
-import { currentUser as queryCurrentUser } from './services/ant-design-pro/api'
+// import { currentUser as queryCurrentUser } from './services/ant-design-pro/api'
+import consts from './utils/consts'
 
 const loginPath = '/user/login'
 
@@ -25,7 +27,7 @@ export async function getInitialState(): Promise<{
       const msg = await queryCurrentUser()
       return msg.data
     } catch (error) {
-      history.push(loginPath)
+      // history.push(loginPath)
     }
     return undefined
   }
@@ -44,6 +46,123 @@ export async function getInitialState(): Promise<{
   }
 }
 
+const authHeaderInterceptor = (url: string, options: RequestOptionsInit) => {
+  const token = window.localStorage.getItem('TOKEN_ID')
+  // 如果是登录页面,不执行
+  if (!token && history.location.pathname !== loginPath) {
+    return history.push(loginPath)
+  }
+  const authHeader = { Authorization: `Bearer ${JSON.parse(token)}` }
+  return {
+    url: `${url}`,
+    options: { ...options, interceptors: true, headers: authHeader }
+  }
+}
+
+/**
+ * 异常处理程序
+ const codeMessage = {
+    200: '服务器成功返回请求的数据。',
+    201: '新建或修改数据成功。',
+    202: '一个请求已经进入后台排队(异步任务)。',
+    204: '删除数据成功。',
+    400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
+    401: '用户没有权限(令牌、用户名、密码错误)。',
+    403: '用户得到授权,但是访问是被禁止的。',
+    404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
+    405: '请求方法不被允许。',
+    406: '请求的格式不可得。',
+    410: '请求的资源被永久删除,且不会再得到的。',
+    422: '当创建一个对象时,发生一个验证错误。',
+    500: '服务器发生错误,请检查服务器。',
+    502: '网关错误。',
+    503: '服务不可用,服务器暂时过载或维护。',
+    504: '网关超时。',
+ };
+ * @see https://beta-pro.ant.design/docs/request-cn
+ */
+export const request: RequestConfig = {
+  errorHandler: (error: ResponseError) => {
+    const { messages } = getIntl(getLocale())
+    const { response } = error
+
+    if (response && response.status) {
+      const { status, statusText, url } = response
+      const requestErrorMessage = messages['app.request.error']
+      const errorMessage = `${requestErrorMessage} ${status}: ${url}`
+      const errorDescription = messages[`app.request.${status}`] || statusText
+      notification.error({
+        message: errorMessage,
+        description: errorDescription
+      })
+    }
+
+    if (!response) {
+      notification.error({
+        description: '您的网络发生异常,无法连接服务器',
+        message: '网络异常'
+      })
+    }
+    throw error
+  },
+  middlewares: [
+    async (ctx, next) => {
+      await next()
+      const { req, res } = ctx
+      // @ts-ignore
+      if (req.options?.skipErrorHandler) {
+        return
+      }
+      const errorAdaptor = req.options?.errorConfig.adaptor || (resData => resData)
+      const { options } = req
+      const { getResponse } = options
+      const resData = getResponse ? res.data : res
+      const errorInfo = errorAdaptor(resData, ctx)
+      if (resData.code !== consts.RET_CODE.SUCCESS) {
+        // 抛出错误到 errorHandler 中处理
+        const error = new Error(errorInfo.errorMessage)
+        error.name = 'BizError'
+        error.data = resData
+        error.info = errorInfo
+        error.response = res
+        throw error
+      }
+    }
+  ],
+  prefix: '/api',
+  errorConfig: {
+    adaptor: resData => {
+      return {
+        // success: resData.code === consts.RET_CODE.SUCCESS,
+        data: resData.data,
+        errorCode: resData.code,
+        errorMessage: resData.msg
+      }
+    }
+  },
+  responseInterceptors: [
+    async (response, options) => {
+      const errorAdaptor = options?.errorConfig.adaptor || (resData => resData)
+      const res = await response.clone().json()
+      const { getResponse } = options
+      const resData = getResponse ? res.data : res
+      const errorInfo = errorAdaptor(resData, { res: response, req: options })
+
+      if (res?.code !== consts.RET_CODE.SUCCESS) {
+        // 抛出错误到 errorHandler 中处理
+        const error = new Error(errorInfo.errorMessage)
+        error.name = 'BizError'
+        error.data = resData
+        error.info = errorInfo
+        error.response = res
+        throw error
+      }
+      return response
+    }
+  ],
+  requestInterceptors: [authHeaderInterceptor]
+}
+
 // ProLayout 支持的api https://procomponents.ant.design/components/layout
 export const layout: RunTimeLayoutConfig = ({ initialState }) => {
   return {
@@ -53,11 +172,11 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
       content: initialState?.currentUser?.name
     },
     onPageChange: () => {
-      const { location } = history
-      // 如果没有登录,重定向到 login
-      if (!initialState?.currentUser && location.pathname !== loginPath) {
-        history.push(loginPath)
-      }
+      // const { location } = history
+      // // 如果没有登录,重定向到 login
+      // if (!initialState?.currentUser && location.pathname !== loginPath) {
+      //   history.push(loginPath)
+      // }
     },
     menuHeaderRender: undefined,
     // 自定义 403 页面

+ 35 - 35
src/components/RightContent/AvatarDropdown.tsx

@@ -1,50 +1,50 @@
-import React, { useCallback } from 'react';
-import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
-import { Avatar, Menu, Spin } from 'antd';
-import { history, useModel } from 'umi';
-import { stringify } from 'querystring';
-import HeaderDropdown from '../HeaderDropdown';
-import styles from './index.less';
-import { outLogin } from '@/services/ant-design-pro/api';
-import type { MenuInfo } from 'rc-menu/lib/interface';
+import React, { useCallback } from 'react'
+import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons'
+import { Avatar, Menu, Spin } from 'antd'
+import { history, useModel } from 'umi'
+import { stringify } from 'querystring'
+import HeaderDropdown from '../HeaderDropdown'
+import styles from './index.less'
+// import { outLogin } from '@/services/ant-design-pro/api';
+import type { MenuInfo } from 'rc-menu/lib/interface'
 
 export type GlobalHeaderRightProps = {
-  menu?: boolean;
-};
+  menu?: boolean
+}
 
 /**
  * 退出登录,并且将当前的 url 保存
  */
 const loginOut = async () => {
-  await outLogin();
-  const { query = {}, pathname } = history.location;
-  const { redirect } = query;
+  await outLogin()
+  const { query = {}, pathname } = history.location
+  const { redirect } = query
   // Note: There may be security issues, please note
   if (window.location.pathname !== '/user/login' && !redirect) {
     history.replace({
       pathname: '/user/login',
       search: stringify({
-        redirect: pathname,
-      }),
-    });
+        redirect: pathname
+      })
+    })
   }
-};
+}
 
 const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
-  const { initialState, setInitialState } = useModel('@@initialState');
+  const { initialState, setInitialState } = useModel('@@initialState')
 
   const onMenuClick = useCallback(
     (event: MenuInfo) => {
-      const { key } = event;
+      const { key } = event
       if (key === 'logout') {
-        setInitialState((s) => ({ ...s, currentUser: undefined }));
-        loginOut();
-        return;
+        setInitialState(s => ({ ...s, currentUser: undefined }))
+        loginOut()
+        return
       }
-      history.push(`/account/${key}`);
+      history.push(`/account/${key}`)
     },
-    [setInitialState],
-  );
+    [setInitialState]
+  )
 
   const loading = (
     <span className={`${styles.action} ${styles.account}`}>
@@ -52,20 +52,20 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
         size="small"
         style={{
           marginLeft: 8,
-          marginRight: 8,
+          marginRight: 8
         }}
       />
     </span>
-  );
+  )
 
   if (!initialState) {
-    return loading;
+    return loading
   }
 
-  const { currentUser } = initialState;
+  const { currentUser } = initialState
 
   if (!currentUser || !currentUser.name) {
-    return loading;
+    return loading
   }
 
   const menuHeaderDropdown = (
@@ -89,7 +89,7 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
         退出登录
       </Menu.Item>
     </Menu>
-  );
+  )
   return (
     <HeaderDropdown overlay={menuHeaderDropdown}>
       <span className={`${styles.action} ${styles.account}`}>
@@ -97,7 +97,7 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
         <span className={`${styles.name} anticon`}>{currentUser.name}</span>
       </span>
     </HeaderDropdown>
-  );
-};
+  )
+}
 
-export default AvatarDropdown;
+export default AvatarDropdown

+ 6 - 1
src/locales/zh-CN/menu.ts

@@ -14,5 +14,10 @@ export default {
   'menu.account.center': '个人中心',
   'menu.account.settings': '个人设置',
   'menu.account.trigger': '触发报错',
-  'menu.account.logout': '退出登录'
+  'menu.account.logout': '退出登录',
+  'menu.project': '项目',
+  'menu.project.management': '项目管理',
+  'menu.institutions': '企事业单位',
+  'menu.institutions.company': '单位管理',
+  'menu.institutions.staff': '人员管理'
 }

+ 19 - 0
src/locales/zh-CN/request.ts

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

+ 5 - 0
src/pages/Institutions/Company/index.tsx

@@ -0,0 +1,5 @@
+const Company = () => {
+  return <div>这是单位管理</div>
+}
+
+export default Company

+ 5 - 0
src/pages/Institutions/Staff/index.tsx

@@ -0,0 +1,5 @@
+const Staff = () => {
+  return <div>员工管理</div>
+}
+
+export default Staff

+ 88 - 0
src/pages/Project/Management/components/AddProject.tsx

@@ -0,0 +1,88 @@
+import { useRequest } from 'umi'
+import { useRef, useEffect } from 'react'
+import { ModalForm, ProFormSelect, ProFormText } from '@ant-design/pro-form'
+import { Button, message } from 'antd'
+import { addProject, updateProject } from '@/services/api/project'
+import type { FormInstance } from 'antd'
+
+export enum ModalType {
+  ADD = 0,
+  UPDATE = 1
+}
+
+type AddProjectProps = {
+  visible: boolean
+  onVisibleChange: (visible: boolean) => void
+  type: ModalType
+  defaultFormData?: {
+    id: string
+    name: string
+    project_type_id: string
+  }
+  pTypeList: API.ProjectTypeList
+}
+const AddProject: React.FC<AddProjectProps> = ({
+  visible,
+  onVisibleChange,
+  type,
+  defaultFormData,
+  pTypeList
+}) => {
+  const ref = useRef<FormInstance>(null)
+  useEffect(() => {
+    console.log('defaultFormData', defaultFormData)
+
+    defaultFormData && ref.current?.setFieldsValue({ ...defaultFormData })
+  }, [defaultFormData])
+  const { run: tryUpdateProject } = useRequest(updateProject, {
+    manual: true,
+    onSuccess: () => {
+      message.success('更新成功')
+    }
+  })
+  const { run: tryAddProject } = useRequest(addProject, {
+    manual: true,
+    onSuccess: () => {
+      message.success('创建成功')
+    }
+  })
+  return (
+    <div>
+      <ModalForm
+        visible={visible}
+        onVisibleChange={onVisibleChange}
+        title={type === ModalType.ADD ? '新增项目' : '编辑项目'}
+        formRef={ref}
+        trigger={<Button>新增项目</Button>}
+        onFinish={async values => {
+          try {
+            // 执行表单提交
+            if (type === ModalType.ADD) {
+              await tryAddProject(values)
+            } else {
+              await tryUpdateProject(values)
+            }
+            return true
+          } catch (error) {
+            return false
+          }
+        }}
+      >
+        {type === ModalType.UPDATE ? <ProFormText name="id" hidden /> : null}
+        <ProFormText
+          name="name"
+          label="项目名称"
+          rules={[{ required: true, message: '请输入项目名称' }]}
+        />
+        <ProFormSelect
+          name="project_type_id"
+          label="项目类型"
+          rules={[{ required: true, message: '请选择项目类型' }]}
+          options={pTypeList}
+        />
+      </ModalForm>
+    </div>
+  )
+}
+
+export default AddProject

+ 140 - 0
src/pages/Project/Management/index.tsx

@@ -0,0 +1,140 @@
+import { delProject, getProjectList } from '@/services/api/project'
+import ProTable from '@ant-design/pro-table'
+import type { ProColumnType, ActionType } from '@ant-design/pro-table'
+import { Popconfirm } from 'antd'
+import consts from '@/utils/consts'
+import { useRef, useState, useEffect } from 'react'
+import { connect, useRequest } from 'umi'
+import type { ConnectProps } from 'umi'
+import type { ProjectModelState } from '../model'
+import { DeleteOutlined } from '@ant-design/icons'
+import AddProject, { ModalType } from './components/AddProject'
+
+type ListProps = ConnectProps & {
+  pTypeList: { label: string; value: string }[]
+}
+
+const List: React.FC<ListProps> = ({ dispatch, pTypeList }) => {
+  const tRef = useRef<ActionType>(null)
+  useEffect(() => {
+    if (!pTypeList.length) {
+      dispatch({
+        type: 'project/queryProjectTypeList'
+      })
+    }
+  }, [])
+  const [state, setState] = useState({
+    params: {
+      search: null
+    },
+    visible: false,
+    currentModalType: ModalType.ADD,
+    defaultFormData: null
+  })
+  const { run: tryDelProject } = useRequest(delProject, {
+    manual: true,
+    onSuccess: () => tRef.current?.reload()
+  })
+  const columns: ProColumnType<API.ProjectListItem>[] = [
+    {
+      dataIndex: 'name',
+      title: '项目名称'
+    },
+    {
+      dataIndex: 'create_time',
+      title: '创建时间'
+    },
+    {
+      dataIndex: 'project_type_id',
+      title: '项目类型',
+      filters: true,
+      filterMultiple: false,
+      render: (_, record) => <div>{record.name}</div>,
+      valueEnum: pTypeList.reduce((prev, curr) => {
+        const items = { ...prev }
+        items[curr.value] = {
+          text: curr.label
+        }
+        return items
+      }, {})
+    },
+    {
+      dataIndex: 'created',
+      title: '创建人'
+    },
+    {
+      title: '操作',
+      dataIndex: 'operation',
+      render: (_, record) => (
+        <div className="divide-x divide-bg-gray-400 flex flex-row">
+          <div
+            className="pr-2 text-primary cursor-pointer hover:text-hex-967bbd"
+            onClick={() => {
+              setState({
+                ...state,
+                visible: true,
+                currentModalType: ModalType.UPDATE,
+                defaultFormData: {
+                  id: record.id,
+                  name: record.name,
+                  project_type_id: record.project_type?.id
+                }
+              })
+            }}
+          >
+            编辑
+          </div>
+          <Popconfirm
+            title="确认删除吗?"
+            okText="确认"
+            cancelText="取消"
+            onConfirm={() => tryDelProject({ id: record.id })}
+          >
+            <div className="pl-2 text-hex-fd3995 cursor-pointer hover:text-hex-e7026e">
+              <DeleteOutlined />
+            </div>
+          </Popconfirm>
+        </div>
+      )
+    }
+  ]
+  return (
+    <ProTable<API.ProjectListItem>
+      rowKey="id"
+      params={state.params}
+      actionRef={tRef}
+      columns={columns}
+      request={async (params, filter, sorter) => {
+        const { code = -1, data: { items = [], totle = 0 } = {} } = await getProjectList({
+          ...params,
+          ...filter,
+          ...sorter
+        })
+        return {
+          data: items,
+          success: code === consts.RET_CODE.SUCCESS,
+          totle
+        }
+      }}
+      toolbar={{
+        search: {
+          onSearch: val => setState({ ...state, params: { ...state.params, search: val } })
+        },
+        actions: [
+          <AddProject
+            type={state.currentModalType}
+            defaultFormData={state.defaultFormData}
+            pTypeList={pTypeList}
+            visible={state.visible}
+            onVisibleChange={(visible: boolean) => setState({ ...state, visible })}
+          />
+        ]
+      }}
+      search={false}
+    />
+  )
+}
+
+export default connect(({ project }: { project: ProjectModelState }) => ({
+  pTypeList: project.projectTypeList.map(item => ({ label: item.name, value: item.id }))
+}))(List)

+ 56 - 0
src/pages/Project/model.ts

@@ -0,0 +1,56 @@
+import { getProjectTypeList } from '@/services/api/project'
+import consts from '@/utils/consts'
+import type { Effect, Reducer } from 'umi'
+
+export interface ProjectModelState {
+  projectTypeList: API.ProjectTypeList
+}
+
+export interface ProjectModelType {
+  namespace: 'project'
+  state: ProjectModelState
+  effects: {
+    query: Effect
+  }
+  reducers: {
+    save: Reducer<ProjectModelState>
+    // 启用 immer 之后
+    // save: ImmerReducer<ProjectModelState>;
+  }
+}
+
+const ProjectModel: ProjectModelType = {
+  namespace: 'project',
+
+  state: {
+    projectTypeList: []
+  },
+
+  effects: {
+    *queryProjectTypeList({ payload }, { call, put }) {
+      const response = yield call(getProjectTypeList, payload)
+      if (response?.code === consts.RET_CODE.SUCCESS) {
+        yield put({
+          type: 'save',
+          payload: {
+            projectTypeList: response.data
+          }
+        })
+      }
+    }
+  },
+  reducers: {
+    save(state, action) {
+      return {
+        ...state,
+        ...action.payload
+      }
+    }
+    // 启用 immer 之后
+    // save(state, action) {
+    //   state.name = action.payload;
+    // },
+  }
+}
+
+export default ProjectModel

+ 7 - 4
src/pages/user/Login/index.tsx

@@ -3,7 +3,7 @@ import { Alert, message, Tabs } from 'antd'
 import React, { useState } from 'react'
 import { ProFormCheckbox, ProFormText, LoginForm } from '@ant-design/pro-form'
 import { useIntl, history, FormattedMessage, SelectLang, useModel } from 'umi'
-import { login } from '@/services/ant-design-pro/api'
+// import { login } from '@/services/ant-design-pro/api'
 
 import styles from './index.less'
 
@@ -84,7 +84,8 @@ const Login: React.FC = () => {
           actions={[]}
           onFinish={async values => {
             await handleSubmit(values as API.LoginParams)
-          }}>
+          }}
+        >
           <Tabs activeKey={type} onChange={setType}>
             <Tabs.TabPane
               key="account"
@@ -156,14 +157,16 @@ const Login: React.FC = () => {
           <div
             style={{
               marginBottom: 24
-            }}>
+            }}
+          >
             <ProFormCheckbox noStyle name="autoLogin">
               <FormattedMessage id="pages.login.rememberMe" defaultMessage="自动登录" />
             </ProFormCheckbox>
             <a
               style={{
                 float: 'right'
-              }}>
+              }}
+            >
               <FormattedMessage id="pages.login.forgotPassword" defaultMessage="忘记密码" />
             </a>
           </div>

+ 0 - 85
src/services/ant-design-pro/api.ts

@@ -1,85 +0,0 @@
-// @ts-ignore
-/* eslint-disable */
-import { request } from 'umi';
-
-/** 获取当前的用户 GET /api/currentUser */
-export async function currentUser(options?: { [key: string]: any }) {
-  return request<{
-    data: API.CurrentUser;
-  }>('/api/currentUser', {
-    method: 'GET',
-    ...(options || {}),
-  });
-}
-
-/** 退出登录接口 POST /api/login/outLogin */
-export async function outLogin(options?: { [key: string]: any }) {
-  return request<Record<string, any>>('/api/login/outLogin', {
-    method: 'POST',
-    ...(options || {}),
-  });
-}
-
-/** 登录接口 POST /api/login/account */
-export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
-  return request<API.LoginResult>('/api/login/account', {
-    method: 'POST',
-    headers: {
-      'Content-Type': 'application/json',
-    },
-    data: body,
-    ...(options || {}),
-  });
-}
-
-/** 此处后端没有提供注释 GET /api/notices */
-export async function getNotices(options?: { [key: string]: any }) {
-  return request<API.NoticeIconList>('/api/notices', {
-    method: 'GET',
-    ...(options || {}),
-  });
-}
-
-/** 获取规则列表 GET /api/rule */
-export async function rule(
-  params: {
-    // query
-    /** 当前的页码 */
-    current?: number;
-    /** 页面的容量 */
-    pageSize?: number;
-  },
-  options?: { [key: string]: any },
-) {
-  return request<API.RuleList>('/api/rule', {
-    method: 'GET',
-    params: {
-      ...params,
-    },
-    ...(options || {}),
-  });
-}
-
-/** 新建规则 PUT /api/rule */
-export async function updateRule(options?: { [key: string]: any }) {
-  return request<API.RuleListItem>('/api/rule', {
-    method: 'PUT',
-    ...(options || {}),
-  });
-}
-
-/** 新建规则 POST /api/rule */
-export async function addRule(options?: { [key: string]: any }) {
-  return request<API.RuleListItem>('/api/rule', {
-    method: 'POST',
-    ...(options || {}),
-  });
-}
-
-/** 删除规则 DELETE /api/rule */
-export async function removeRule(options?: { [key: string]: any }) {
-  return request<Record<string, any>>('/api/rule', {
-    method: 'DELETE',
-    ...(options || {}),
-  });
-}

+ 0 - 21
src/services/ant-design-pro/login.ts

@@ -1,21 +0,0 @@
-// @ts-ignore
-/* eslint-disable */
-import { request } from 'umi';
-
-/** 发送验证码 POST /api/login/captcha */
-export async function getFakeCaptcha(
-  params: {
-    // query
-    /** 手机号 */
-    phone?: string;
-  },
-  options?: { [key: string]: any },
-) {
-  return request<API.FakeCaptcha>('/api/login/captcha', {
-    method: 'GET',
-    params: {
-      ...params,
-    },
-    ...(options || {}),
-  });
-}

+ 0 - 101
src/services/ant-design-pro/typings.d.ts

@@ -1,101 +0,0 @@
-// @ts-ignore
-/* eslint-disable */
-
-declare namespace API {
-  type CurrentUser = {
-    name?: string;
-    avatar?: string;
-    userid?: string;
-    email?: string;
-    signature?: string;
-    title?: string;
-    group?: string;
-    tags?: { key?: string; label?: string }[];
-    notifyCount?: number;
-    unreadCount?: number;
-    country?: string;
-    access?: string;
-    geographic?: {
-      province?: { label?: string; key?: string };
-      city?: { label?: string; key?: string };
-    };
-    address?: string;
-    phone?: string;
-  };
-
-  type LoginResult = {
-    status?: string;
-    type?: string;
-    currentAuthority?: string;
-  };
-
-  type PageParams = {
-    current?: number;
-    pageSize?: number;
-  };
-
-  type RuleListItem = {
-    key?: number;
-    disabled?: boolean;
-    href?: string;
-    avatar?: string;
-    name?: string;
-    owner?: string;
-    desc?: string;
-    callNo?: number;
-    status?: number;
-    updatedAt?: string;
-    createdAt?: string;
-    progress?: number;
-  };
-
-  type RuleList = {
-    data?: RuleListItem[];
-    /** 列表的内容总数 */
-    total?: number;
-    success?: boolean;
-  };
-
-  type FakeCaptcha = {
-    code?: number;
-    status?: string;
-  };
-
-  type LoginParams = {
-    username?: string;
-    password?: string;
-    autoLogin?: boolean;
-    type?: string;
-  };
-
-  type ErrorResponse = {
-    /** 业务约定的错误码 */
-    errorCode: string;
-    /** 业务上的错误信息 */
-    errorMessage?: string;
-    /** 业务上的请求是否成功 */
-    success?: boolean;
-  };
-
-  type NoticeIconList = {
-    data?: NoticeIconItem[];
-    /** 列表的内容总数 */
-    total?: number;
-    success?: boolean;
-  };
-
-  type NoticeIconItemType = 'notification' | 'message' | 'event';
-
-  type NoticeIconItem = {
-    id?: string;
-    extra?: string;
-    key?: string;
-    read?: boolean;
-    avatar?: string;
-    title?: string;
-    status?: string;
-    datetime?: string;
-    description?: string;
-    type?: NoticeIconItemType;
-  };
-}

+ 3 - 5
src/services/ant-design-pro/index.ts

@@ -2,9 +2,7 @@
 /* eslint-disable */
 // API 更新时间:
 // API 唯一标识:
-import * as api from './api';
-import * as login from './login';
+import * as project from './project'
 export default {
-  api,
-  login,
-};
+  project
+}

+ 50 - 50
src/services/swagger/pet.ts

@@ -1,17 +1,17 @@
 // @ts-ignore
 /* eslint-disable */
-import { request } from 'umi';
+import { request } from 'umi'
 
 /** Update an existing pet PUT /pet */
 export async function updatePet(body: API.Pet, options?: { [key: string]: any }) {
   return request<any>('/pet', {
     method: 'PUT',
     headers: {
-      'Content-Type': 'application/json',
+      'Content-Type': 'application/json'
     },
     data: body,
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Add a new pet to the store POST /pet */
@@ -19,11 +19,11 @@ export async function addPet(body: API.Pet, options?: { [key: string]: any }) {
   return request<any>('/pet', {
     method: 'POST',
     headers: {
-      'Content-Type': 'application/json',
+      'Content-Type': 'application/json'
     },
     data: body,
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Finds Pets by status Multiple status values can be provided with comma separated strings GET /pet/findByStatus */
@@ -31,18 +31,18 @@ export async function findPetsByStatus(
   params: {
     // query
     /** Status values that need to be considered for filter */
-    status: 'available' | 'pending' | 'sold'[];
+    status: 'available' | 'pending' | 'sold'[]
   },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
   return request<API.Pet[]>('/pet/findByStatus', {
     method: 'GET',
     params: {
-      ...params,
+      ...params
     },
 
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Finds Pets by tags Muliple tags can be provided with comma separated strings. Use         tag1, tag2, tag3 for testing. GET /pet/findByTags */
@@ -50,18 +50,18 @@ export async function findPetsByTags(
   params: {
     // query
     /** Tags to filter by */
-    tags: string[];
+    tags: string[]
   },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
   return request<API.Pet[]>('/pet/findByTags', {
     method: 'GET',
     params: {
-      ...params,
+      ...params
     },
 
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Find pet by ID Returns a single pet GET /pet/${param0} */
@@ -69,17 +69,17 @@ export async function getPetById(
   params: {
     // path
     /** ID of pet to return */
-    petId: number;
+    petId: number
   },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
-  const { petId: param0 } = params;
+  const { petId: param0 } = params
   return request<API.Pet>(`/pet/${param0}`, {
     method: 'GET',
     params: { ...params },
 
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Updates a pet in the store with form data POST /pet/${param0} */
@@ -87,50 +87,50 @@ export async function updatePetWithForm(
   params: {
     // path
     /** ID of pet that needs to be updated */
-    petId: number;
+    petId: number
   },
   body: { name?: string; status?: string },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
-  const { petId: param0 } = params;
-  const formData = new FormData();
+  const { petId: param0 } = params
+  const formData = new FormData()
 
-  Object.keys(body).forEach((ele) => {
-    const item = (body as any)[ele];
+  Object.keys(body).forEach(ele => {
+    const item = (body as any)[ele]
 
     if (item !== undefined && item !== null) {
-      formData.append(ele, typeof item === 'object' ? JSON.stringify(item) : item);
+      formData.append(ele, typeof item === 'object' ? JSON.stringify(item) : item)
     }
-  });
+  })
 
   return request<any>(`/pet/${param0}`, {
     method: 'POST',
     headers: {
-      'Content-Type': 'application/x-www-form-urlencoded',
+      'Content-Type': 'application/x-www-form-urlencoded'
     },
     params: { ...params },
     data: formData,
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Deletes a pet DELETE /pet/${param0} */
 export async function deletePet(
   params: {
     // header
-    api_key?: string;
+    api_key?: string
     // path
     /** Pet id to delete */
-    petId: number;
+    petId: number
   },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
-  const { petId: param0 } = params;
+  const { petId: param0 } = params
   return request<any>(`/pet/${param0}`, {
     method: 'DELETE',
     params: { ...params },
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** uploads an image POST /pet/${param0}/uploadImage */
@@ -138,29 +138,29 @@ export async function uploadFile(
   params: {
     // path
     /** ID of pet to update */
-    petId: number;
+    petId: number
   },
   body: { additionalMetadata?: string; file?: string },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
-  const { petId: param0 } = params;
-  const formData = new FormData();
+  const { petId: param0 } = params
+  const formData = new FormData()
 
-  Object.keys(body).forEach((ele) => {
-    const item = (body as any)[ele];
+  Object.keys(body).forEach(ele => {
+    const item = (body as any)[ele]
 
     if (item !== undefined && item !== null) {
-      formData.append(ele, typeof item === 'object' ? JSON.stringify(item) : item);
+      formData.append(ele, typeof item === 'object' ? JSON.stringify(item) : item)
     }
-  });
+  })
 
   return request<API.ApiResponse>(`/pet/${param0}/uploadImage`, {
     method: 'POST',
     headers: {
-      'Content-Type': 'multipart/form-data',
+      'Content-Type': 'multipart/form-data'
     },
     params: { ...params },
     data: formData,
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }

+ 41 - 0
src/services/api/project.ts

@@ -0,0 +1,41 @@
+import { request } from 'umi'
+
+/** 获取项目列表 POST /api/project/list */
+export async function getProjectList(params: API.ProjectListParams) {
+  return request<API.ProjectList>('/project/list', {
+    method: 'POST',
+    data: {
+      ...params
+    }
+  })
+}
+
+/** 获取项目类型列表 POST /api/projectType/list */
+export async function getProjectTypeList() {
+  return request<API.ProjectTypeList>('/projectType/list', {
+    method: 'POST'
+  })
+}
+
+/** 删除项目 POST /api/project/delete */
+export async function delProject(params: API.ProjectDelParams) {
+  return request('/project/delete', {
+    method: 'POST',
+    data: params
+  })
+}
+
+/** 更新项目 POST /api/project/update */
+export async function updateProject(params: API.ProjectUpdateParams) {
+  return request('/project/update', {
+    method: 'POST',
+    data: params
+  })
+}
+/** 更新项目 POST /api/project/update */
+export async function addProject(params: API.ProjectAddParams) {
+  return request('/project/add', {
+    method: 'POST',
+    data: params
+  })
+}

+ 15 - 15
src/services/swagger/store.ts

@@ -1,13 +1,13 @@
 // @ts-ignore
 /* eslint-disable */
-import { request } from 'umi';
+import { request } from 'umi'
 
 /** Returns pet inventories by status Returns a map of status codes to quantities GET /store/inventory */
 export async function getInventory(options?: { [key: string]: any }) {
   return request<Record<string, any>>('/store/inventory', {
     method: 'GET',
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Place an order for a pet POST /store/order */
@@ -15,8 +15,8 @@ export async function placeOrder(body: API.Order, options?: { [key: string]: any
   return request<API.Order>('/store/order', {
     method: 'POST',
     data: body,
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Find purchase order by ID For valid response try integer IDs with value >= 1 and <= 10.         Other values will generated exceptions GET /store/order/${param0} */
@@ -24,16 +24,16 @@ export async function getOrderById(
   params: {
     // path
     /** ID of pet that needs to be fetched */
-    orderId: number;
+    orderId: number
   },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
-  const { orderId: param0 } = params;
+  const { orderId: param0 } = params
   return request<API.Order>(`/store/order/${param0}`, {
     method: 'GET',
     params: { ...params },
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Delete purchase order by ID For valid response try integer IDs with positive integer value.         Negative or non-integer values will generate API errors DELETE /store/order/${param0} */
@@ -41,14 +41,14 @@ export async function deleteOrder(
   params: {
     // path
     /** ID of the order that needs to be deleted */
-    orderId: number;
+    orderId: number
   },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
-  const { orderId: param0 } = params;
+  const { orderId: param0 } = params
   return request<any>(`/store/order/${param0}`, {
     method: 'DELETE',
     params: { ...params },
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }

+ 53 - 0
src/services/api/typings.d.ts

@@ -0,0 +1,53 @@
+// @ts-ignore
+/* eslint-disable */
+
+declare namespace API {
+  type BasicPageParams = {
+    /** 页码 */
+    current: number
+    /** 页数 */
+    pageSize: number
+  }
+
+  type BasicFetchResult<T> = {
+    items: T[]
+    total: number
+  }
+
+  type ProjectList = BasicFetchResult<ProjectListItem>
+
+  type ProjectListItem = {
+    create_time?: string
+    name?: string
+    created?: string
+    created_id?: string
+    project_type?: ProjectTypeListItem
+    update_time?: string
+    id?: string
+  }
+
+  type ProjectListParams = BasicPageParams & {
+    search?: string
+    projectTypeId?: string
+  }
+
+  type ProjectDelParams = {
+    id: string
+  }
+
+  type ProjectUpdateParams = {
+    id: string
+    name: string
+    project_type_id: string
+  }
+  type ProjectAddParams = Omit<ProjectUpdateParams, 'id'>
+
+  type ProjectTypeList = ProjectTypeListItem[]
+
+  type ProjectTypeListItem = {
+    name?: string
+    id?: string
+    update_time?: string
+    create_time?: string
+  }
+}

+ 31 - 31
src/services/swagger/user.ts

@@ -1,26 +1,26 @@
 // @ts-ignore
 /* eslint-disable */
-import { request } from 'umi';
+import { request } from 'umi'
 
 /** Create user This can only be done by the logged in user. POST /user */
 export async function createUser(body: API.User, options?: { [key: string]: any }) {
   return request<any>('/user', {
     method: 'POST',
     data: body,
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Creates list of users with given input array POST /user/createWithArray */
 export async function createUsersWithArrayInput(
   body: API.User[],
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
   return request<any>('/user/createWithArray', {
     method: 'POST',
     data: body,
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Creates list of users with given input array POST /user/createWithList */
@@ -28,8 +28,8 @@ export async function createUsersWithListInput(body: API.User[], options?: { [ke
   return request<any>('/user/createWithList', {
     method: 'POST',
     data: body,
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Logs user into the system GET /user/login */
@@ -37,27 +37,27 @@ export async function loginUser(
   params: {
     // query
     /** The user name for login */
-    username: string;
+    username: string
     /** The password for login in clear text */
-    password: string;
+    password: string
   },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
   return request<string>('/user/login', {
     method: 'GET',
     params: {
-      ...params,
+      ...params
     },
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Logs out current logged in user session GET /user/logout */
 export async function logoutUser(options?: { [key: string]: any }) {
   return request<any>('/user/logout', {
     method: 'GET',
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Get user by user name GET /user/${param0} */
@@ -65,16 +65,16 @@ export async function getUserByName(
   params: {
     // path
     /** The name that needs to be fetched. Use user1 for testing.  */
-    username: string;
+    username: string
   },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
-  const { username: param0 } = params;
+  const { username: param0 } = params
   return request<API.User>(`/user/${param0}`, {
     method: 'GET',
     params: { ...params },
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Updated user This can only be done by the logged in user. PUT /user/${param0} */
@@ -82,18 +82,18 @@ export async function updateUser(
   params: {
     // path
     /** name that need to be updated */
-    username: string;
+    username: string
   },
   body: API.User,
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
-  const { username: param0 } = params;
+  const { username: param0 } = params
   return request<any>(`/user/${param0}`, {
     method: 'PUT',
     params: { ...params },
     data: body,
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }
 
 /** Delete user This can only be done by the logged in user. DELETE /user/${param0} */
@@ -101,14 +101,14 @@ export async function deleteUser(
   params: {
     // path
     /** The name that needs to be deleted */
-    username: string;
+    username: string
   },
-  options?: { [key: string]: any },
+  options?: { [key: string]: any }
 ) {
-  const { username: param0 } = params;
+  const { username: param0 } = params
   return request<any>(`/user/${param0}`, {
     method: 'DELETE',
     params: { ...params },
-    ...(options || {}),
-  });
+    ...(options || {})
+  })
 }

+ 0 - 12
src/services/swagger/index.ts

@@ -1,12 +0,0 @@
-// @ts-ignore
-/* eslint-disable */
-// API 更新时间:
-// API 唯一标识:
-import * as pet from './pet';
-import * as store from './store';
-import * as user from './user';
-export default {
-  pet,
-  store,
-  user,
-};

+ 0 - 52
src/services/swagger/typings.d.ts

@@ -1,52 +0,0 @@
-// @ts-ignore
-/* eslint-disable */
-
-declare namespace API {
-  type Order = {
-    id?: number;
-    petId?: number;
-    quantity?: number;
-    shipDate?: string;
-    /** Order Status */
-    status?: 'placed' | 'approved' | 'delivered';
-    complete?: boolean;
-  };
-
-  type Category = {
-    id?: number;
-    name?: string;
-  };
-
-  type User = {
-    id?: number;
-    username?: string;
-    firstName?: string;
-    lastName?: string;
-    email?: string;
-    password?: string;
-    phone?: string;
-    /** User Status */
-    userStatus?: number;
-  };
-
-  type Tag = {
-    id?: number;
-    name?: string;
-  };
-
-  type Pet = {
-    id?: number;
-    category?: Category;
-    name: string;
-    photoUrls: string[];
-    tags?: Tag[];
-    /** pet status in the store */
-    status?: 'available' | 'pending' | 'sold';
-  };
-
-  type ApiResponse = {
-    code?: number;
-    type?: string;
-    message?: string;
-  };
-}

+ 5 - 0
src/utils/consts.ts

@@ -0,0 +1,5 @@
+export default {
+  RET_CODE: {
+    SUCCESS: 0
+  }
+}