Optimize file name
This commit is contained in:
81
src/pages/System/Settings/Base.tsx
Normal file
81
src/pages/System/Settings/Base.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import React from 'react'
|
||||
import { useUpdatedEffect } from '@/util/hooks'
|
||||
import { hasPermission } from '@/util/auth'
|
||||
import { r_sys_settings_base_get, r_sys_settings_base_update } from '@/services/system'
|
||||
import { SettingsCard } from '@/pages/System/Settings'
|
||||
|
||||
const Base: React.FC = () => {
|
||||
const [baseForm] = AntdForm.useForm<BaseSettingsParam>()
|
||||
const baseFormValues = AntdForm.useWatch([], baseForm)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const handleOnReset = () => {
|
||||
getBaseSettings()
|
||||
}
|
||||
|
||||
const handleOnSave = () => {
|
||||
void r_sys_settings_base_update(baseFormValues).then((res) => {
|
||||
const response = res.data
|
||||
if (response.success) {
|
||||
void message.success('保存设置成功')
|
||||
getBaseSettings()
|
||||
} else {
|
||||
void message.error('保存设置失败,请稍后重试')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getBaseSettings = () => {
|
||||
if (loading) {
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
|
||||
void r_sys_settings_base_get().then((res) => {
|
||||
const response = res.data
|
||||
if (response.success) {
|
||||
const data = response.data
|
||||
data && baseForm.setFieldsValue(data)
|
||||
setLoading(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useUpdatedEffect(() => {
|
||||
getBaseSettings()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsCard
|
||||
icon={IconOxygenEmail}
|
||||
title={'基础'}
|
||||
loading={loading}
|
||||
onReset={handleOnReset}
|
||||
onSave={handleOnSave}
|
||||
modifyOperationCode={'system:settings:modify:base'}
|
||||
>
|
||||
<AntdForm
|
||||
form={baseForm}
|
||||
labelCol={{ flex: '7em' }}
|
||||
disabled={!hasPermission('system:settings:modify:base')}
|
||||
>
|
||||
<AntdForm.Item label={'应用名称'} name={'appName'}>
|
||||
<AntdInput />
|
||||
</AntdForm.Item>
|
||||
<AntdForm.Item label={'应用 URL'} name={'appUrl'}>
|
||||
<AntdInput />
|
||||
</AntdForm.Item>
|
||||
<AntdForm.Item label={'验证邮箱 URL'} name={'verifyUrl'}>
|
||||
<AntdInput placeholder={'验证码使用 ${verifyCode} 代替'} />
|
||||
</AntdForm.Item>
|
||||
<AntdForm.Item label={'找回密码 URL'} name={'retrieveUrl'}>
|
||||
<AntdInput placeholder={'验证码使用 ${retrieveCode} 代替'} />
|
||||
</AntdForm.Item>
|
||||
</AntdForm>
|
||||
</SettingsCard>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Base
|
||||
155
src/pages/System/Settings/Mail.tsx
Normal file
155
src/pages/System/Settings/Mail.tsx
Normal file
@@ -0,0 +1,155 @@
|
||||
import React from 'react'
|
||||
import Icon from '@ant-design/icons'
|
||||
import { useUpdatedEffect } from '@/util/hooks'
|
||||
import { hasPermission } from '@/util/auth'
|
||||
import {
|
||||
r_sys_settings_mail_get,
|
||||
r_sys_settings_mail_send,
|
||||
r_sys_settings_mail_update
|
||||
} from '@/services/system'
|
||||
import { SettingsCard } from '@/pages/System/Settings'
|
||||
|
||||
const Mail: React.FC = () => {
|
||||
const [modal, contextHolder] = AntdModal.useModal()
|
||||
const [mailForm] = AntdForm.useForm<MailSettingsParam>()
|
||||
const mailFormValues = AntdForm.useWatch([], mailForm)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [mailSendForm] = AntdForm.useForm<MailSendParam>()
|
||||
|
||||
const handleOnTest = () => {
|
||||
void modal.confirm({
|
||||
title: '发送测试邮件',
|
||||
content: (
|
||||
<>
|
||||
<AntdForm form={mailSendForm}>
|
||||
<AntdForm.Item
|
||||
name={'to'}
|
||||
label={'接收人'}
|
||||
style={{ marginTop: 10 }}
|
||||
rules={[{ required: true, type: 'email' }]}
|
||||
>
|
||||
<AntdInput />
|
||||
</AntdForm.Item>
|
||||
</AntdForm>
|
||||
<AntdTag style={{ whiteSpace: 'normal' }}>
|
||||
将使用服务器已保存的邮件设置进行发送邮件,请保证编辑的内容已保存
|
||||
</AntdTag>
|
||||
</>
|
||||
),
|
||||
onOk: () =>
|
||||
mailSendForm.validateFields().then(
|
||||
() => {
|
||||
return new Promise((resolve) => {
|
||||
void r_sys_settings_mail_send({
|
||||
to: mailSendForm.getFieldValue('to') as string
|
||||
}).then((res) => {
|
||||
const response = res.data
|
||||
|
||||
if (response.success) {
|
||||
void message.success('发送成功')
|
||||
resolve(true)
|
||||
} else {
|
||||
void message.error('发送失败,请检查配置后重试')
|
||||
resolve(true)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
() => {
|
||||
return new Promise((_, reject) => {
|
||||
reject('未输入接收者')
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const handleOnReset = () => {
|
||||
getMailSettings()
|
||||
}
|
||||
|
||||
const handleOnSave = () => {
|
||||
void r_sys_settings_mail_update(mailFormValues).then((res) => {
|
||||
const response = res.data
|
||||
if (response.success) {
|
||||
void message.success('保存设置成功')
|
||||
getMailSettings()
|
||||
} else {
|
||||
void message.error('保存设置失败,请稍后重试')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getMailSettings = () => {
|
||||
if (loading) {
|
||||
return
|
||||
}
|
||||
|
||||
setLoading(true)
|
||||
void r_sys_settings_mail_get().then((res) => {
|
||||
const response = res.data
|
||||
if (response.success) {
|
||||
const data = response.data
|
||||
data && mailForm.setFieldsValue(data)
|
||||
setLoading(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useUpdatedEffect(() => {
|
||||
getMailSettings()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsCard
|
||||
icon={IconOxygenEmail}
|
||||
title={'邮件'}
|
||||
loading={loading}
|
||||
onReset={handleOnReset}
|
||||
onSave={handleOnSave}
|
||||
modifyOperationCode={'system:settings:modify:mail'}
|
||||
expand={
|
||||
<AntdButton onClick={handleOnTest} title={'测试'}>
|
||||
<Icon component={IconOxygenTest} />
|
||||
</AntdButton>
|
||||
}
|
||||
>
|
||||
<AntdForm
|
||||
form={mailForm}
|
||||
labelCol={{ flex: '8em' }}
|
||||
disabled={!hasPermission('system:settings:modify:mail')}
|
||||
>
|
||||
<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={'securityType'}>
|
||||
<AntdSelect>
|
||||
<AntdSelect.Option key={'None'}>None</AntdSelect.Option>
|
||||
<AntdSelect.Option key={'SSL/TLS'}>SSL/TLS</AntdSelect.Option>
|
||||
<AntdSelect.Option key={'StartTls'}>StartTls</AntdSelect.Option>
|
||||
</AntdSelect>
|
||||
</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.Item label={'发送者名称'} name={'fromName'}>
|
||||
<AntdInput />
|
||||
</AntdForm.Item>
|
||||
</AntdForm>
|
||||
</SettingsCard>
|
||||
{contextHolder}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Mail
|
||||
163
src/pages/System/Settings/SensitiveWord.tsx
Normal file
163
src/pages/System/Settings/SensitiveWord.tsx
Normal file
@@ -0,0 +1,163 @@
|
||||
import React, { useState } from 'react'
|
||||
import Icon from '@ant-design/icons'
|
||||
import { DATABASE_DUPLICATE_KEY, DATABASE_INSERT_SUCCESS } from '@/constants/common.constants'
|
||||
import { useUpdatedEffect } from '@/util/hooks'
|
||||
import {
|
||||
r_sys_settings_sensitive_add,
|
||||
r_sys_settings_sensitive_delete,
|
||||
r_sys_settings_sensitive_get,
|
||||
r_sys_settings_sensitive_update
|
||||
} from '@/services/system'
|
||||
import { SettingsCard } from '@/pages/System/Settings'
|
||||
|
||||
const SensitiveWord: React.FC = () => {
|
||||
const [dataSource, setDataSource] = useState<SensitiveWordVo[]>()
|
||||
const [targetKeys, setTargetKeys] = useState<string[]>([])
|
||||
const [selectedKeys, setSelectedKeys] = useState<string[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [isAdding, setIsAdding] = useState(false)
|
||||
const [newWord, setNewWord] = useState('')
|
||||
|
||||
const handleOnReset = () => {
|
||||
getSensitiveWordSettings()
|
||||
}
|
||||
|
||||
const handleOnSave = () => {
|
||||
targetKeys &&
|
||||
void r_sys_settings_sensitive_update({ ids: targetKeys }).then((res) => {
|
||||
const response = res.data
|
||||
if (response.success) {
|
||||
void message.success('保存成功')
|
||||
getSensitiveWordSettings()
|
||||
} else {
|
||||
void message.error('保存失败,请稍后重试')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleOnDelete = () => {
|
||||
void r_sys_settings_sensitive_delete(selectedKeys[0]).then((res) => {
|
||||
const response = res.data
|
||||
if (response.success) {
|
||||
void message.success('删除成功')
|
||||
getSensitiveWordSettings()
|
||||
} else {
|
||||
void message.error('删除失败,请稍后重试')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getSensitiveWordSettings = () => {
|
||||
if (loading) {
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
|
||||
void r_sys_settings_sensitive_get().then((res) => {
|
||||
const response = res.data
|
||||
if (response.success) {
|
||||
const data = response.data
|
||||
data && setDataSource(data)
|
||||
data && setTargetKeys(data.filter((value) => value.enable).map((value) => value.id))
|
||||
setLoading(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setNewWord(e.target.value)
|
||||
}
|
||||
|
||||
const handleOnAdd = () => {
|
||||
if (isAdding) {
|
||||
return
|
||||
}
|
||||
setIsAdding(true)
|
||||
|
||||
void r_sys_settings_sensitive_add({ word: newWord, enable: false })
|
||||
.then((res) => {
|
||||
const response = res.data
|
||||
switch (response.code) {
|
||||
case DATABASE_INSERT_SUCCESS:
|
||||
void message.success('添加成功')
|
||||
setNewWord('')
|
||||
getSensitiveWordSettings()
|
||||
break
|
||||
case DATABASE_DUPLICATE_KEY:
|
||||
void message.error('该词已存在')
|
||||
break
|
||||
default:
|
||||
void message.error('出错了,请稍后重试')
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
setIsAdding(false)
|
||||
})
|
||||
}
|
||||
|
||||
useUpdatedEffect(() => {
|
||||
getSensitiveWordSettings()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsCard
|
||||
icon={IconOxygenSensitive}
|
||||
title={'敏感词'}
|
||||
loading={loading}
|
||||
onReset={handleOnReset}
|
||||
onSave={handleOnSave}
|
||||
modifyOperationCode={'system:settings:modify:sensitive'}
|
||||
>
|
||||
<AntdTransfer
|
||||
listStyle={{ width: '100%', height: 400 }}
|
||||
oneWay
|
||||
showSearch
|
||||
pagination
|
||||
disabled={isAdding}
|
||||
titles={[
|
||||
<span
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end'
|
||||
}}
|
||||
>
|
||||
{selectedKeys?.length === 1 ? (
|
||||
<AntdTooltip title={'删除选中项'}>
|
||||
<Icon
|
||||
style={{ fontSize: '1.2em' }}
|
||||
component={IconOxygenDelete}
|
||||
onClick={handleOnDelete}
|
||||
/>
|
||||
</AntdTooltip>
|
||||
) : undefined}
|
||||
备选
|
||||
</span>,
|
||||
'拦截'
|
||||
]}
|
||||
dataSource={dataSource}
|
||||
targetKeys={targetKeys}
|
||||
selectedKeys={selectedKeys}
|
||||
onChange={setTargetKeys}
|
||||
onSelectChange={setSelectedKeys}
|
||||
rowKey={(item) => item.id}
|
||||
render={(item) => item.word}
|
||||
/>
|
||||
<AntdInput
|
||||
value={newWord}
|
||||
onChange={handleOnChange}
|
||||
onPressEnter={handleOnAdd}
|
||||
disabled={isAdding}
|
||||
suffix={
|
||||
<AntdButton type={'primary'} onClick={handleOnAdd} disabled={isAdding}>
|
||||
<Icon component={IconOxygenPlus} />
|
||||
</AntdButton>
|
||||
}
|
||||
></AntdInput>
|
||||
</SettingsCard>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default SensitiveWord
|
||||
79
src/pages/System/Settings/index.tsx
Normal file
79
src/pages/System/Settings/index.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
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 LoadingMask from '@/components/common/LoadingMask'
|
||||
import Permission from '@/components/common/Permission'
|
||||
import Base from '@/pages/System/Settings/Base'
|
||||
import Mail from '@/pages/System/Settings/Mail'
|
||||
import SensitiveWord from '@/pages/System/Settings/SensitiveWord'
|
||||
|
||||
interface SettingsCardProps extends React.PropsWithChildren {
|
||||
icon: IconComponent
|
||||
title: string
|
||||
loading?: boolean
|
||||
modifyOperationCode?: string
|
||||
expand?: React.ReactNode
|
||||
onReset?: () => void
|
||||
onSave?: () => void
|
||||
}
|
||||
export 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>
|
||||
{!props.loading ? (
|
||||
<Permission operationCode={props.modifyOperationCode}>
|
||||
{props.expand}
|
||||
<AntdButton onClick={props.onReset} title={'重置'}>
|
||||
<Icon component={IconOxygenBack} />
|
||||
</AntdButton>
|
||||
<AntdButton className={'bt-save'} onClick={props.onSave} title={'保存'}>
|
||||
<Icon component={IconOxygenSave} />
|
||||
</AntdButton>
|
||||
</Permission>
|
||||
) : undefined}
|
||||
</FlexBox>
|
||||
<LoadingMask
|
||||
maskContent={<AntdSkeleton active paragraph={{ rows: 6 }} />}
|
||||
hidden={!props.loading}
|
||||
>
|
||||
{props.children}
|
||||
</LoadingMask>
|
||||
</FlexBox>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
const Settings: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<FitFullscreen data-component={'system-settings'}>
|
||||
<HideScrollbar isShowVerticalScrollbar autoHideWaitingTime={500}>
|
||||
<FlexBox direction={'horizontal'} className={'root-content'}>
|
||||
<FlexBox className={'root-col'}>
|
||||
<Permission operationCode={'system:settings:query:base'}>
|
||||
<Base />
|
||||
</Permission>
|
||||
<Permission operationCode={'system:settings:query:sensitive'}>
|
||||
<SensitiveWord />
|
||||
</Permission>
|
||||
</FlexBox>
|
||||
<FlexBox className={'root-col'}>
|
||||
<Permission operationCode={'system:settings:query:mail'}>
|
||||
<Mail />
|
||||
</Permission>
|
||||
</FlexBox>
|
||||
</FlexBox>
|
||||
</HideScrollbar>
|
||||
</FitFullscreen>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Settings
|
||||
Reference in New Issue
Block a user