优化

pull/48/head
smallbun 2023-09-13 22:10:12 +08:00
parent 7929cede90
commit 21c38dbce0
15 changed files with 117 additions and 76 deletions

View File

@ -139,40 +139,29 @@ export default [
name: 'app',
icon: 'AppstoreOutlined',
path: '/app',
routes: [
// 应用列表
{
path: '/app',
redirect: '/app/list',
},
// 应用列表
{
name: 'list',
path: '/app/list',
component: './app/AppList',
},
//创建应用
{
name: 'create',
path: '/app/list/create',
name: 'app.create',
path: '/app/create',
hideInMenu: true,
component: './app/AppCreate',
},
//应用配置
{
name: 'config',
path: '/app/list/config',
name: 'app.config',
path: '/app/config',
hideInMenu: true,
component: './app/AppConfig',
},
// 应用分组
//应用分组
{
name: 'group',
name: 'app.group',
path: '/app/group',
hideInMenu: true,
component: './app/AppGroup',
},
],
},
//行为审计
{
name: 'audit',

View File

@ -98,6 +98,7 @@ export default {
'custom.selected.item': '项',
'custom.unchecked': '暂未选中',
'custom.search_button': '搜索',
'custom.upload': '上传',
...menu,
...component,
...pages,

View File

@ -108,6 +108,9 @@ export default () => {
label={intl.formatMessage({
id: 'pages.account.user_group_detail.pro_descriptions.name',
})}
fieldProps={{
maxLength: 8,
}}
copyable
/>
<ProDescriptions.Item

View File

@ -72,6 +72,9 @@ export default (props: {
placeholder={intl.formatMessage({
id: 'pages.account.user_group_list.form.name.placeholder',
})}
fieldProps={{
maxLength: 8,
}}
rules={[
{
required: true,

View File

@ -15,7 +15,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { updateApp } from '@/services/app';
import { getAllAppGroupList, updateApp } from '@/services/app';
import { ProCard, ProDescriptions } from '@ant-design/pro-components';
import { useAsyncEffect } from 'ahooks';
@ -67,10 +67,11 @@ const AppBasic = (props: { appId: string }) => {
*/
const onSave = async (key: React.Key | React.Key[], record: GetApp): Promise<any | void> => {
//调用接口修改
let params: Record<string, string> = {
let params: Record<string, any> = {
id: record.id,
name: record.name,
remark: record.remark,
groupIds: record.groupIds,
};
if (uploadIconUrl) {
params = { ...params, icon: uploadIconUrl };
@ -208,6 +209,22 @@ const AppBasic = (props: { appId: string }) => {
],
}}
/>
<ProDescriptions.Item
dataIndex="groupIds"
label={intl.formatMessage({ id: 'pages.app.config.basic.group' })}
valueType={'select'}
request={async () => {
const { success, data } = await getAllAppGroupList({}, {}, {});
if (success && data) {
return data.map((i) => {
return { label: i.name, value: i.id };
});
}
return [];
}}
fieldProps={{ rows: 2, maxLength: 20, maxTagCount: 'responsive', mode: 'multiple' }}
copyable={false}
/>
<ProDescriptions.Item
dataIndex="enabled"
label={intl.formatMessage({ id: 'pages.app.config.basic.enabled' })}
@ -239,15 +256,9 @@ const AppBasic = (props: { appId: string }) => {
},
}}
/>
<ProDescriptions.Item
dataIndex="protocolName"
label={intl.formatMessage({ id: 'pages.app.config.basic.protocol_name' })}
editable={false}
/>
{app?.clientId && (
<>
<ProDescriptions.Item
dataIndex="clientId"
ellipsis
label={intl.formatMessage({ id: 'pages.app.config.basic.client_id' })}
valueType={'text'}
editable={false}
@ -260,8 +271,6 @@ const AppBasic = (props: { appId: string }) => {
editable={false}
copyable={true}
/>
</>
)}
<ProDescriptions.Item
dataIndex="createTime"
label={intl.formatMessage({ id: 'pages.app.config.basic.create_time' })}
@ -273,7 +282,7 @@ const AppBasic = (props: { appId: string }) => {
dataIndex="remark"
label={intl.formatMessage({ id: 'pages.app.config.basic.remark' })}
valueType={'textarea'}
fieldProps={{ rows: 2, maxLength: 20 }}
fieldProps={{ rows: 2, maxLength: 200 }}
copyable={false}
/>
</ProDescriptions>

View File

@ -37,6 +37,7 @@ export type GetApp = {
authorizationType: string;
enabled: boolean;
remark: string;
groupIds: string[];
};
/**

View File

@ -16,10 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
export default {
'pages.app.config.basic': '基本配置',
'pages.app.config.basic': '基本信息',
'pages.app.config.basic.name': '应用名称',
'pages.app.config.basic.name.rule.0.message': '应用名称为必填项',
'pages.app.config.basic.icon': '应用图标',
'pages.app.config.basic.icon.rule.0.message': '应用图标为必填项',
'pages.app.config.basic.icon.rule.1.message': '应用图标上传失败',
'pages.app.config.basic.icon.desc.1': '必须为 PNG/JPG 格式',
'pages.app.config.basic.icon.desc.2': '建议使用 256 * 256 像素方形图标',
'pages.app.config.basic.enabled': '应用状态',

View File

@ -108,7 +108,7 @@ const CreateApp = (props: {
onOk: () => {
successModal.destroy();
history.push(
`/app/list/config?id=${result.id}&name=${values.name}&protocol=${protocol}`,
`/app/config?id=${result.id}&name=${values.name}&protocol=${protocol}`,
);
},
});
@ -131,9 +131,12 @@ const CreateApp = (props: {
]}
/>
<ProFormSelect
name="groups"
name="groupIds"
mode="multiple"
label={'归属分组'}
fieldProps={{
maxTagCount: 'responsive',
}}
label={intl.formatMessage({ id: 'pages.app.create.modal_form.group' })}
request={async () => {
setLoading(true);
const { success, data } = await getAllAppGroupList({}, {}, {}).finally(() => {

View File

@ -24,6 +24,7 @@ export default {
'pages.app.create.header_title': '标准协议',
'pages.app.create.modal_form.title': '添加应用',
'pages.app.create.modal_form.name': '应用名称',
'pages.app.create.modal_form.group': '应用分组',
'pages.app.create.modal_form.name.placeholder': '请输入应用名称',
'pages.app.create.modal_form.name.message': '应用名称为必填项',
'pages.app.create.modal_form.name.rule.0': '应用名称为必填项',

View File

@ -23,7 +23,7 @@ import { useRef, useState } from 'react';
import CreateModal from './components/CreateModal';
import UpdateModal from './components/UpdateModal';
import { createAppGroup, removeAppGroup, updateAppGroup } from './service';
import { useIntl } from '@@/exports';
import { history, useIntl } from '@@/exports';
import { getAppGroupList } from '@/services/app';
export default () => {
@ -73,7 +73,7 @@ export default () => {
</Tag>
)}
{record.type === 'default' && (
<Tag color={'#2db7f5'} key={'default'}>
<Tag color={'#4fc2fa'} key={'default'}>
{intl.formatMessage({
id: 'pages.app_group.list.column.type.default',
})}
@ -108,10 +108,15 @@ export default () => {
setId(record.id);
setUpdateModalOpen(true);
}}
style={{
pointerEvents: record.type === 'default' ? 'none' : 'auto',
...(record.type === 'default' ? { opacity: 0.2 } : {}),
}}
>
{intl.formatMessage({ id: 'app.update' })}
</a>,
<Popconfirm
disabled={record.type === 'default'}
title={intl.formatMessage({
id: 'pages.app_group.list.actions.popconfirm.delete',
})}
@ -135,7 +140,15 @@ export default () => {
cancelText={intl.formatMessage({ id: 'app.no' })}
key="delete"
>
<a target="_blank" key="remove" style={{ color: 'red' }}>
<a
target="_blank"
key="remove"
style={{
color: 'red',
pointerEvents: record.type === 'default' ? 'none' : 'auto',
...(record.type === 'default' ? { opacity: 0.2 } : {}),
}}
>
{intl.formatMessage({ id: 'app.delete' })}
</a>
</Popconfirm>,
@ -144,7 +157,12 @@ export default () => {
];
return (
<PageContainer>
<PageContainer
content={intl.formatMessage({ id: 'pages.app_group.list.desc' })}
onBack={() => {
history.push('/app');
}}
>
<ProTable<AppAPI.AppGroupList>
columns={columns}
actionRef={actionRef}

View File

@ -17,13 +17,15 @@
*/
export default {
'pages.app_group.list.create': '创建分组',
'pages.app_group.list.desc':
'应用分组管理是一种将多个应用程序或功能按照一定的逻辑或相关性进行组织和管理的方法。通过应用分组,可以更有效地管理大量应用程序,提供更好的用户体验。',
'pages.app_group.list.column.name': '分组名称',
'pages.app_group.list.column.code': '分组编码',
'pages.app_group.list.column.create_time': '创建时间',
'pages.app_group.list.column.remark': '备注',
'pages.app_group.list.column.app_count': '应用数量',
'pages.app_group.list.column.type': '分组类型',
'pages.app_group.list.column.type.default': '系统默认',
'pages.app_group.list.column.type.default': '内置',
'pages.app_group.list.column.type.custom': '自定义',
'pages.app_group.list.column.option': '操作',
'pages.app_group.list.actions.popconfirm.delete': '您确定要删除此应用分组?',

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { getAllAppGroupList, getAppList } from '@/services/app';
import { PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { PlusOutlined, QuestionCircleOutlined, GroupOutlined } from '@ant-design/icons';
import type { ActionType } from '@ant-design/pro-components';
import { PageContainer, ProList } from '@ant-design/pro-components';
import { App, Avatar, Button, Popconfirm, Space, Tag } from 'antd';
@ -86,12 +86,21 @@ export default () => {
key={'create'}
type="primary"
onClick={() => {
history.push('/app/list/create');
history.push('/app/create');
}}
>
<PlusOutlined />
{intl.formatMessage({ id: 'pages.app.list.tool_bar_render.add_app' })}
</Button>,
<Button
key="app-group"
icon={<GroupOutlined />}
onClick={() => {
history.push('/app/group');
}}
>
</Button>,
]}
metas={{
title: {
@ -102,7 +111,7 @@ export default () => {
<span
onClick={() => {
history.push(
`/app/list/config?id=${row.id}&protocol=${row.protocol}&name=${row.name}`,
`/app/config?id=${row.id}&protocol=${row.protocol}&name=${row.name}`,
);
}}
>
@ -177,7 +186,7 @@ export default () => {
key="config"
onClick={() => {
history.push(
`/app/list/config?id=${row.id}&protocol=${row.protocol}&name=${row.name}`,
`/app/config?id=${row.id}&protocol=${row.protocol}&name=${row.name}`,
);
}}
>
@ -213,15 +222,12 @@ export default () => {
</Popconfirm>,
],
},
status: {
groupId: {
// 自己扩展的字段,主要用于筛选,不在列表中显示
title: intl.formatMessage({
id: 'pages.app.list.metas.group',
}),
valueType: 'select',
fieldProps: {
mode: 'multiple',
},
request: async () => {
const { success, data } = await getAllAppGroupList({}, {}, {});
if (success && data) {

View File

@ -48,7 +48,7 @@ export default (props: { visible: boolean }) => {
async function getList() {
setLoading(true);
// 加载列表
const { success, result } = await getMailTemplateList();
const { success, result } = await getMailTemplateList({});
if (success) {
setDataSource(result);
}
@ -76,6 +76,7 @@ export default (props: { visible: boolean }) => {
*
*
* @param browseTitle
* @param browseContent
*/
const browseOnClick = (browseTitle: string, browseContent: string) => {
setTitle(<span>{`${browseTitle}`}</span>);

View File

@ -22,14 +22,16 @@ import { request } from '@umijs/max';
*
* @param file
* @param fileName
* @param onUploadProgress
* @returns
*/
export async function uploadFile(
file: string | RcFile | Blob,
fileName?: string,
onUploadProgress?: (progressEvent: ProgressEvent) => void,
): Promise<API.ApiResult<string>> {
const formData = new FormData();
formData.append('file', file);
if (fileName) formData.append('fileName', fileName);
return request('/api/v1/storage/upload', { method: 'POST', data: formData });
return request('/api/v1/storage/upload', { method: 'POST', data: formData, onUploadProgress });
}