Complete main UI #37
38
src/assets/css/pages/system/settings.scss
Normal file
38
src/assets/css/pages/system/settings.scss
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
@use '@/assets/css/constants' as constants;
|
||||||
|
|
||||||
|
.root-content {
|
||||||
|
padding: 30px;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
.settings-card {
|
||||||
|
padding: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
> .head {
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: constants.$SIZE_ICON_MD;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-reset {
|
||||||
|
color: constants.$font-main-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bt-save {
|
||||||
|
color: constants.$main-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/assets/svg/back.svg
Normal file
1
src/assets/svg/back.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M471.893333 149.333333a42.666667 42.666667 0 0 0-73.258666-29.781333l-343.893334 352.981333a42.666667 42.666667 0 0 0-0.768 58.709334l343.893334 372.352a42.666667 42.666667 0 0 0 73.984-28.928v-190.677334c56.917333-5.248 116.821333-1.365333 179.882666 11.989334 65.834667 13.994667 150.528 76.032 253.909334 202.24a42.666667 42.666667 0 0 0 75.477333-31.36c-15.445333-152.32-73.984-281.301333-176.170667-384.853334-92.757333-93.994667-204.373333-146.432-333.098666-156.586666V149.333333z" /></svg>
|
||||||
|
After Width: | Height: | Size: 570 B |
1
src/assets/svg/email.svg
Normal file
1
src/assets/svg/email.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M926.47619 355.644952V780.190476a73.142857 73.142857 0 0 1-73.142857 73.142857H170.666667a73.142857 73.142857 0 0 1-73.142857-73.142857V355.644952l304.103619 257.828572a170.666667 170.666667 0 0 0 220.745142 0L926.47619 355.644952zM853.333333 170.666667a74.044952 74.044952 0 0 1 26.087619 4.778666 72.704 72.704 0 0 1 30.622477 22.186667 73.508571 73.508571 0 0 1 10.678857 17.67619c3.169524 7.509333 5.12 15.652571 5.607619 24.210286L926.47619 243.809524v24.380952L559.469714 581.241905a73.142857 73.142857 0 0 1-91.306666 2.901333l-3.632762-2.925714L97.52381 268.190476v-24.380952a72.899048 72.899048 0 0 1 40.155428-65.292191A72.97219 72.97219 0 0 1 170.666667 170.666667h682.666666z" /></svg>
|
||||||
|
After Width: | Height: | Size: 770 B |
1
src/assets/svg/save.svg
Normal file
1
src/assets/svg/save.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" ><path d="M931.882 259.882l-167.764-167.764A96 96 0 0 0 696.236 64H160C106.98 64 64 106.98 64 160v704c0 53.02 42.98 96 96 96h704c53.02 0 96-42.98 96-96V327.764a96 96 0 0 0-28.118-67.882zM512 832c-70.692 0-128-57.308-128-128 0-70.692 57.308-128 128-128s128 57.308 128 128c0 70.692-57.308 128-128 128z m192-609.04V424c0 13.254-10.746 24-24 24H216c-13.254 0-24-10.746-24-24V216c0-13.254 10.746-24 24-24h457.04c6.366 0 12.47 2.528 16.97 7.03l6.96 6.96A23.992 23.992 0 0 1 704 222.96z" /></svg>
|
||||||
|
After Width: | Height: | Size: 553 B |
@@ -9,5 +9,8 @@ export const URL_SYS_POWER_LIST = '/system/power/list'
|
|||||||
export const URL_SYS_ROLE_LIST = '/system/role/list'
|
export const URL_SYS_ROLE_LIST = '/system/role/list'
|
||||||
export const URL_SYS_GROUP = '/system/group'
|
export const URL_SYS_GROUP = '/system/group'
|
||||||
export const URL_SYS_GROUP_LIST = '/system/group/list'
|
export const URL_SYS_GROUP_LIST = '/system/group/list'
|
||||||
|
export const URL_SYS_SETTINGS = '/system/settings'
|
||||||
|
export const URL_SYS_SETTINGS_MAIL = `${URL_SYS_SETTINGS}/mail`
|
||||||
|
|
||||||
export const URL_API_V1_AVATAR_RANDOM_BASE64 = '/api/v1/avatar/base64'
|
export const URL_API_V1 = '/api/v1'
|
||||||
|
export const URL_API_V1_AVATAR_RANDOM_BASE64 = `${URL_API_V1}/avatar/base64`
|
||||||
|
|||||||
20
src/global.d.ts
vendored
20
src/global.d.ts
vendored
@@ -294,3 +294,23 @@ interface GroupChangeStatusParam {
|
|||||||
interface AvatarBase64Vo {
|
interface AvatarBase64Vo {
|
||||||
base64: string
|
base64: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SystemSettingVo {
|
||||||
|
mail: MailSettingsVo
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MailSettingsVo {
|
||||||
|
host?: string
|
||||||
|
port?: number
|
||||||
|
username?: string
|
||||||
|
password?: string
|
||||||
|
from?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MailSettingsParam {
|
||||||
|
host?: string
|
||||||
|
port?: number
|
||||||
|
username?: string
|
||||||
|
password?: string
|
||||||
|
from?: string
|
||||||
|
}
|
||||||
|
|||||||
123
src/pages/system/Settings.tsx
Normal file
123
src/pages/system/Settings.tsx
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Icon from '@ant-design/icons'
|
||||||
|
import '@/assets/css/pages/system/settings.scss'
|
||||||
|
import FitFullScreen from '@/components/common/FitFullScreen'
|
||||||
|
import HideScrollbar from '@/components/common/HideScrollbar'
|
||||||
|
import Card from '@/components/common/Card'
|
||||||
|
import FlexBox from '@/components/common/FlexBox'
|
||||||
|
import { useUpdatedEffect } from '@/util/hooks.tsx'
|
||||||
|
import { r_sys_settings_get, r_sys_settings_mail_update } from '@/services/system.tsx'
|
||||||
|
|
||||||
|
interface SettingsCardProps extends React.PropsWithChildren {
|
||||||
|
icon: IconComponent
|
||||||
|
title: string
|
||||||
|
onReset?: () => void
|
||||||
|
onSave?: () => void
|
||||||
|
}
|
||||||
|
const SettingsCard: React.FC<SettingsCardProps> = (props) => {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<FlexBox className={'settings-card'}>
|
||||||
|
<FlexBox direction={'horizontal'} className={'head'}>
|
||||||
|
<Icon component={props.icon} className={'icon'} />
|
||||||
|
<div className={'title'}>{props.title}</div>
|
||||||
|
<AntdButton className={'bt bt-reset'} onClick={props.onReset}>
|
||||||
|
<Icon component={IconFatwebBack} />
|
||||||
|
</AntdButton>
|
||||||
|
<AntdButton className={'bt bt-save'} onClick={props.onSave}>
|
||||||
|
<Icon component={IconFatwebSave} />
|
||||||
|
</AntdButton>
|
||||||
|
</FlexBox>
|
||||||
|
{props.children}
|
||||||
|
</FlexBox>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const MailSettings: React.FC<{ mail?: MailSettingsVo; onSave?: () => void }> = (props) => {
|
||||||
|
const [mailForm] = AntdForm.useForm<MailSettingsParam>()
|
||||||
|
const mailFormValues = AntdForm.useWatch([], mailForm)
|
||||||
|
|
||||||
|
const handleOnReset = () => {
|
||||||
|
props.mail && mailForm.setFieldsValue(props.mail)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleOnSave = () => {
|
||||||
|
void r_sys_settings_mail_update(mailFormValues).then((res) => {
|
||||||
|
const response = res.data
|
||||||
|
if (response.success) {
|
||||||
|
void message.success('保存设置成功')
|
||||||
|
props.onSave && props.onSave()
|
||||||
|
} else {
|
||||||
|
void message.error('保存设置失败,请稍后重试')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useUpdatedEffect(() => {
|
||||||
|
props.mail && mailForm.setFieldsValue(props.mail)
|
||||||
|
}, [props.mail])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsCard
|
||||||
|
icon={IconFatwebEmail}
|
||||||
|
title={'邮件'}
|
||||||
|
onReset={handleOnReset}
|
||||||
|
onSave={handleOnSave}
|
||||||
|
>
|
||||||
|
<AntdForm form={mailForm} labelCol={{ flex: '8em' }}>
|
||||||
|
<AntdForm.Item label={'SMTP 服务器'} name={'host'}>
|
||||||
|
<AntdInput />
|
||||||
|
</AntdForm.Item>
|
||||||
|
<AntdForm.Item label={'端口'} name={'port'}>
|
||||||
|
<AntdInputNumber min={0} max={65535} style={{ width: '100%' }} />
|
||||||
|
</AntdForm.Item>
|
||||||
|
<AntdForm.Item label={'用户名'} name={'username'}>
|
||||||
|
<AntdInput />
|
||||||
|
</AntdForm.Item>
|
||||||
|
<AntdForm.Item label={'密码'} name={'password'}>
|
||||||
|
<AntdInput.Password />
|
||||||
|
</AntdForm.Item>
|
||||||
|
<AntdForm.Item label={'发送者'} name={'from'}>
|
||||||
|
<AntdInput />
|
||||||
|
</AntdForm.Item>
|
||||||
|
</AntdForm>
|
||||||
|
</SettingsCard>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Settings: React.FC = () => {
|
||||||
|
const [systemSetting, setSystemSetting] = useState<SystemSettingVo>()
|
||||||
|
|
||||||
|
const getSystemSetting = () => {
|
||||||
|
void r_sys_settings_get().then((res) => {
|
||||||
|
const response = res.data
|
||||||
|
if (response.success) {
|
||||||
|
const data = response.data
|
||||||
|
data && setSystemSetting(data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleOnSave = () => {
|
||||||
|
getSystemSetting()
|
||||||
|
}
|
||||||
|
|
||||||
|
useUpdatedEffect(() => {
|
||||||
|
getSystemSetting()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FitFullScreen>
|
||||||
|
<HideScrollbar isShowVerticalScrollbar autoHideWaitingTime={500}>
|
||||||
|
<FlexBox className={'root-content'}>
|
||||||
|
<MailSettings mail={systemSetting?.mail} onSave={handleOnSave} />
|
||||||
|
</FlexBox>
|
||||||
|
</HideScrollbar>
|
||||||
|
</FitFullScreen>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Settings
|
||||||
@@ -11,6 +11,16 @@ const system: RouteJsonObject[] = [
|
|||||||
icon: React.lazy(() => import('~icons/fatweb/setting.jsx')),
|
icon: React.lazy(() => import('~icons/fatweb/setting.jsx')),
|
||||||
menu: true
|
menu: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'settings',
|
||||||
|
absolutePath: '/system/settings',
|
||||||
|
id: 'system-settings',
|
||||||
|
component: React.lazy(() => import('@/pages/system/Settings')),
|
||||||
|
name: '系统设置',
|
||||||
|
icon: React.lazy(() => import('~icons/fatweb/setting.jsx')),
|
||||||
|
menu: true,
|
||||||
|
autoHide: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'user',
|
path: 'user',
|
||||||
absolutePath: '/system/user',
|
absolutePath: '/system/user',
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import {
|
|||||||
URL_SYS_ROLE_LIST,
|
URL_SYS_ROLE_LIST,
|
||||||
URL_SYS_GROUP,
|
URL_SYS_GROUP,
|
||||||
URL_SYS_GROUP_LIST,
|
URL_SYS_GROUP_LIST,
|
||||||
URL_SYS_LOG
|
URL_SYS_LOG,
|
||||||
|
URL_SYS_SETTINGS,
|
||||||
|
URL_SYS_SETTINGS_MAIL
|
||||||
} from '@/constants/urls.constants'
|
} from '@/constants/urls.constants'
|
||||||
import request from '@/services/index'
|
import request from '@/services/index'
|
||||||
|
|
||||||
@@ -63,3 +65,8 @@ export const r_sys_group_delete_list = (ids: React.Key[]) => request.delete(URL_
|
|||||||
|
|
||||||
export const r_sys_log_get = (param: SysLogGetParam) =>
|
export const r_sys_log_get = (param: SysLogGetParam) =>
|
||||||
request.get<PageVo<SysLogGetVo>>(URL_SYS_LOG, param)
|
request.get<PageVo<SysLogGetVo>>(URL_SYS_LOG, param)
|
||||||
|
|
||||||
|
export const r_sys_settings_get = () => request.get<SystemSettingVo>(URL_SYS_SETTINGS)
|
||||||
|
|
||||||
|
export const r_sys_settings_mail_update = (param: MailSettingsParam) =>
|
||||||
|
request.put(URL_SYS_SETTINGS_MAIL, param)
|
||||||
|
|||||||
Reference in New Issue
Block a user