refactor(preference): use pinia store

This commit is contained in:
Jacky 2025-04-21 07:34:35 +00:00
parent d079e805e5
commit 4aa42da642
No known key found for this signature in database
GPG key ID: 215C21B10DF38B4D
39 changed files with 282 additions and 171 deletions

View file

@ -25,6 +25,7 @@ func GetSettings(c *gin.Context) {
settings.NginxSettings.ErrorLogPath = nginx.GetErrorLogPath() settings.NginxSettings.ErrorLogPath = nginx.GetErrorLogPath()
settings.NginxSettings.ConfigDir = nginx.GetConfPath() settings.NginxSettings.ConfigDir = nginx.GetConfPath()
settings.NginxSettings.PIDPath = nginx.GetPIDPath() settings.NginxSettings.PIDPath = nginx.GetPIDPath()
settings.NginxSettings.StubStatusPort = settings.NginxSettings.GetStubStatusPort()
if settings.NginxSettings.ReloadCmd == "" { if settings.NginxSettings.ReloadCmd == "" {
settings.NginxSettings.ReloadCmd = "nginx -s reload" settings.NginxSettings.ReloadCmd = "nginx -s reload"

View file

@ -64,6 +64,7 @@ export interface NginxSettings {
reload_cmd: string reload_cmd: string
restart_cmd: string restart_cmd: string
stub_status_port: number stub_status_port: number
container_name: string
} }
export interface NodeSettings { export interface NodeSettings {

View file

@ -0,0 +1,3 @@
import Breadcrumb from './Breadcrumb.vue'
export default Breadcrumb

View file

@ -0,0 +1,3 @@
import EnvGroupTabs from './EnvGroupTabs.vue'
export default EnvGroupTabs

View file

@ -0,0 +1,3 @@
import EnvIndicator from './EnvIndicator.vue'
export default EnvIndicator

View file

@ -0,0 +1,3 @@
import ICP from './ICP.vue'
export default ICP

View file

@ -0,0 +1,3 @@
import Logo from './Logo.vue'
export default Logo

View file

@ -0,0 +1,3 @@
import NginxControl from './NginxControl.vue'
export default NginxControl

View file

@ -0,0 +1,3 @@
import NodeSelector from './NodeSelector.vue'
export default NodeSelector

View file

@ -0,0 +1,3 @@
import Notification from './Notification.vue'
export default Notification

View file

@ -0,0 +1,3 @@
import OTPInput from './OTPInput.vue'
export default OTPInput

View file

@ -0,0 +1,3 @@
import PageHeader from './PageHeader.vue'
export default PageHeader

View file

@ -0,0 +1,3 @@
import ReactiveFromNow from './ReactiveFromNow.vue'
export default ReactiveFromNow

View file

@ -0,0 +1,3 @@
import SensitiveString from './SensitiveString.vue'
export default SensitiveString

View file

@ -0,0 +1,3 @@
import SetLanguage from './SetLanguage.vue'
export default SetLanguage

View file

@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Ref } from 'vue' import type { Ref } from 'vue'
import VPSwitch from '@/components/VPSwitch/VPSwitch.vue' import VPSwitch from '@/components/VPSwitch'
import { useSettingsStore } from '@/pinia' import { useSettingsStore } from '@/pinia'
import VPIconMoon from './icons/VPIconMoon.vue' import VPIconMoon from './icons/VPIconMoon.vue'
import VPIconSun from './icons/VPIconSun.vue' import VPIconSun from './icons/VPIconSun.vue'

View file

@ -0,0 +1,3 @@
import SwitchAppearance from './SwitchAppearance.vue'
export default SwitchAppearance

View file

@ -0,0 +1,3 @@
import SystemRestoreContainer from './SystemRestoreContent.vue'
export default SystemRestoreContainer

View file

@ -0,0 +1,8 @@
import Authorization from './Authorization.vue'
import use2FAModal from './use2FAModal'
export default Authorization
export {
use2FAModal,
}

View file

@ -0,0 +1,3 @@
import VPSwitch from './VPSwitch.vue'
export default VPSwitch

View file

@ -1,137 +1,23 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Settings } from '@/api/settings' import FooterToolBar from '@/components/FooterToolbar'
import settings from '@/api/settings' import {
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue' AppSettings,
import use2FAModal from '@/components/TwoFA/use2FAModal' AuthSettings,
import { useSettingsStore } from '@/pinia' CertSettings,
import AppSettings from '@/views/preference/AppSettings.vue' ExternalNotify,
import AuthSettings from '@/views/preference/AuthSettings.vue' HTTPSettings,
import CertSettings from '@/views/preference/CertSettings.vue' LogrotateSettings,
import ExternalNotify from '@/views/preference/ExternalNotify.vue' NginxSettings,
import HTTPSettings from '@/views/preference/HTTPSettings.vue' NodeSettings,
import LogrotateSettings from '@/views/preference/LogrotateSettings.vue' OpenAISettings,
import NginxSettings from '@/views/preference/NginxSettings.vue' ServerSettings,
import NodeSettings from '@/views/preference/NodeSettings.vue' TerminalSettings,
import OpenAISettings from '@/views/preference/OpenAISettings.vue' } from '@/views/preference/tabs'
import ServerSettings from '@/views/preference/ServerSettings.vue' import useSystemSettingsStore from './store'
import TerminalSettings from '@/views/preference/TerminalSettings.vue'
import { message } from 'ant-design-vue'
import { storeToRefs } from 'pinia'
const data = ref<Settings>({ const systemSettingsStore = useSystemSettingsStore()
app: {
page_size: 10,
jwt_secret: '',
},
server: {
host: '0.0.0.0',
port: 9000,
run_mode: 'debug',
enable_https: false,
ssl_cert: '',
ssl_key: '',
},
database: {
name: '',
},
auth: {
ip_white_list: [],
ban_threshold_minutes: 10,
max_attempts: 10,
},
casdoor: {
endpoint: '',
client_id: '',
client_secret: '',
certificate_path: '',
organization: '',
application: '',
redirect_uri: '',
},
cert: {
email: '',
ca_dir: '',
renewal_interval: 7,
recursive_nameservers: [],
http_challenge_port: '9180',
},
http: {
github_proxy: '',
insecure_skip_verify: false,
},
logrotate: {
enabled: false,
cmd: '',
interval: 1440,
},
nginx: {
access_log_path: '',
error_log_path: '',
config_dir: '',
config_path: '',
log_dir_white_list: [],
pid_path: '',
test_config_cmd: '',
reload_cmd: '',
restart_cmd: '',
stub_status_port: 51820,
},
node: {
name: '',
secret: '',
skip_installation: false,
demo: false,
icp_number: '',
public_security_number: '',
},
openai: {
model: '',
base_url: '',
proxy: '',
token: '',
api_type: 'OPEN_AI',
enable_code_completion: false,
code_completion_model: '',
},
terminal: {
start_cmd: '',
},
webauthn: {
rp_display_name: '',
rpid: '',
rp_origins: [],
},
})
settings.get().then(r => { systemSettingsStore.getSettings()
data.value = r
})
const settingsStore = useSettingsStore()
const { server_name } = storeToRefs(settingsStore)
const errors = ref<Record<string, Record<string, string>>>({})
const refAuthSettings = useTemplateRef('refAuthSettings')
async function save() {
// fix type
data.value.cert.http_challenge_port = data.value.cert.http_challenge_port.toString()
const otpModal = use2FAModal()
otpModal.open().then(() => {
settings.save(data.value).then(r => {
if (!settingsStore.is_remote)
server_name.value = r?.server?.name ?? ''
data.value = r
refAuthSettings.value?.getBannedIPs?.()
message.success($gettext('Save successfully'))
errors.value = {}
})
})
}
provide('data', data)
provide('errors', errors)
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
@ -195,7 +81,7 @@ onMounted(() => {
key="auth" key="auth"
:tab="$gettext('Auth')" :tab="$gettext('Auth')"
> >
<AuthSettings ref="refAuthSettings" /> <AuthSettings />
</ATabPane> </ATabPane>
<ATabPane <ATabPane
key="cert" key="cert"
@ -226,7 +112,7 @@ onMounted(() => {
<FooterToolBar v-if="activeKey !== 'external_notify'"> <FooterToolBar v-if="activeKey !== 'external_notify'">
<AButton <AButton
type="primary" type="primary"
@click="save" @click="systemSettingsStore.save"
> >
{{ $gettext('Save') }} {{ $gettext('Save') }}
</AButton> </AButton>

View file

@ -1,14 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Passkey } from '@/api/passkey' import type { Passkey } from '@/api/passkey'
import passkey from '@/api/passkey' import passkey from '@/api/passkey'
import ReactiveFromNow from '@/components/ReactiveFromNow/ReactiveFromNow.vue' import ReactiveFromNow from '@/components/ReactiveFromNow'
import { formatDateTime } from '@/lib/helper' import { formatDateTime } from '@/lib/helper'
import { useUserStore } from '@/pinia' import { useUserStore } from '@/pinia'
import AddPasskey from '@/views/preference/components/AddPasskey.vue'
import { DeleteOutlined, EditOutlined, KeyOutlined } from '@ant-design/icons-vue' import { DeleteOutlined, EditOutlined, KeyOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime' import relativeTime from 'dayjs/plugin/relativeTime'
import AddPasskey from './AddPasskey.vue'
dayjs.extend(relativeTime) dayjs.extend(relativeTime)

View file

@ -2,7 +2,7 @@
import type { TwoFAStatus } from '@/api/2fa' import type { TwoFAStatus } from '@/api/2fa'
import type { RecoveryCode } from '@/api/recovery' import type { RecoveryCode } from '@/api/recovery'
import recovery from '@/api/recovery' import recovery from '@/api/recovery'
import use2FAModal from '@/components/TwoFA/use2FAModal' import { use2FAModal } from '@/components/TwoFA'
import { CopyOutlined, WarningOutlined } from '@ant-design/icons-vue' import { CopyOutlined, WarningOutlined } from '@ant-design/icons-vue'
import { UseClipboard } from '@vueuse/components' import { UseClipboard } from '@vueuse/components'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'

View file

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { RecoveryCode } from '@/api/recovery' import type { RecoveryCode } from '@/api/recovery'
import otp from '@/api/otp' import otp from '@/api/otp'
import OTPInput from '@/components/OTPInput/OTPInput.vue' import OTPInput from '@/components/OTPInput'
import use2FAModal from '@/components/TwoFA/use2FAModal' import { use2FAModal } from '@/components/TwoFA'
import { CheckCircleOutlined } from '@ant-design/icons-vue' import { CheckCircleOutlined } from '@ant-design/icons-vue'
import { UseClipboard } from '@vueuse/components' import { UseClipboard } from '@vueuse/components'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'

View file

@ -0,0 +1,11 @@
import AddPasskey from './AddPasskey.vue'
import Passkey from './Passkey.vue'
import RecoveryCodes from './RecoveryCodes.vue'
import TOTP from './TOTP.vue'
export {
AddPasskey,
Passkey,
RecoveryCodes,
TOTP,
}

View file

@ -0,0 +1,127 @@
import type { Settings } from '@/api/settings'
import settings from '@/api/settings'
import { use2FAModal } from '@/components/TwoFA'
import { useSettingsStore } from '@/pinia'
import { message } from 'ant-design-vue'
import { defineStore } from 'pinia'
const useSystemSettingsStore = defineStore('systemSettings', () => {
const data = ref<Settings>({
app: {
page_size: 10,
jwt_secret: '',
},
server: {
host: '0.0.0.0',
port: 9000,
run_mode: 'debug',
enable_https: false,
ssl_cert: '',
ssl_key: '',
},
database: {
name: '',
},
auth: {
ip_white_list: [],
ban_threshold_minutes: 10,
max_attempts: 10,
},
casdoor: {
endpoint: '',
client_id: '',
client_secret: '',
certificate_path: '',
organization: '',
application: '',
redirect_uri: '',
},
cert: {
email: '',
ca_dir: '',
renewal_interval: 7,
recursive_nameservers: [],
http_challenge_port: '9180',
},
http: {
github_proxy: '',
insecure_skip_verify: false,
},
logrotate: {
enabled: false,
cmd: '',
interval: 1440,
},
nginx: {
access_log_path: '',
error_log_path: '',
config_dir: '',
config_path: '',
log_dir_white_list: [],
pid_path: '',
test_config_cmd: '',
reload_cmd: '',
restart_cmd: '',
stub_status_port: 51820,
container_name: '',
},
node: {
name: '',
secret: '',
skip_installation: false,
demo: false,
icp_number: '',
public_security_number: '',
},
openai: {
model: '',
base_url: '',
proxy: '',
token: '',
api_type: 'OPEN_AI',
enable_code_completion: false,
code_completion_model: '',
},
terminal: {
start_cmd: '',
},
webauthn: {
rp_display_name: '',
rpid: '',
rp_origins: [],
},
})
const errors = ref<Record<string, Record<string, string>>>({})
function getSettings() {
settings.get().then(r => {
data.value = r
})
}
async function save() {
if (!data.value)
return
// fix type
data.value.cert.http_challenge_port = data.value.cert.http_challenge_port.toString()
const otpModal = use2FAModal()
otpModal.open().then(() => {
settings.save(data.value!).then(r => {
const settingsStore = useSettingsStore()
const { server_name } = storeToRefs(settingsStore)
if (!settingsStore.is_remote)
server_name.value = r?.server?.name ?? ''
data.value = r
message.success($gettext('Save successfully'))
errors.value = {}
})
})
}
return { data, errors, getSettings, save }
})
export default useSystemSettingsStore

View file

@ -1,8 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Settings } from '@/api/settings' import SensitiveString from '@/components/SensitiveString'
import SensitiveString from '@/components/SensitiveString/SensitiveString.vue' import useSystemSettingsStore from '../store'
const data: Ref<Settings> = inject('data') as Ref<Settings> const systemSettingsStore = useSystemSettingsStore()
const { data } = storeToRefs(systemSettingsStore)
</script> </script>
<template> <template>

View file

@ -1,18 +1,18 @@
<script setup lang="tsx"> <script setup lang="tsx">
import type { TwoFAStatus } from '@/api/2fa' import type { TwoFAStatus } from '@/api/2fa'
import type { RecoveryCode } from '@/api/recovery' import type { RecoveryCode } from '@/api/recovery'
import type { BannedIP, Settings } from '@/api/settings' import type { BannedIP } from '@/api/settings'
import type { CustomRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer' import type { CustomRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import twoFA from '@/api/2fa' import twoFA from '@/api/2fa'
import setting from '@/api/settings' import setting from '@/api/settings'
import RecoveryCodes from '@/views/preference/components/RecoveryCodes.vue'
import TOTP from '@/views/preference/components/TOTP.vue'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import PasskeyRegistration from './components/Passkey.vue' import { Passkey, RecoveryCodes, TOTP } from '../components/AuthSettings'
import useSystemSettingsStore from '../store'
const data: Ref<Settings> = inject('data') as Ref<Settings> const systemSettingsStore = useSystemSettingsStore()
const { data } = storeToRefs(systemSettingsStore)
const bannedIPColumns = [{ const bannedIPColumns = [{
title: $gettext('IP'), title: $gettext('IP'),
@ -68,7 +68,7 @@ get2FAStatus()
<div class="flex justify-center"> <div class="flex justify-center">
<div> <div>
<h2>{{ $gettext('2FA Settings') }}</h2> <h2>{{ $gettext('2FA Settings') }}</h2>
<PasskeyRegistration class="mb-4" /> <Passkey class="mb-4" />
<TOTP <TOTP
v-model:recovery-codes="recoveryCodes" v-model:recovery-codes="recoveryCodes"

View file

@ -1,10 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Settings } from '@/api/settings'
import { DeleteOutlined, HolderOutlined } from '@ant-design/icons-vue' import { DeleteOutlined, HolderOutlined } from '@ant-design/icons-vue'
import Draggable from 'vuedraggable' import Draggable from 'vuedraggable'
import useSystemSettingsStore from '../store'
const data: Ref<Settings> = inject('data') as Ref<Settings> const systemSettingsStore = useSystemSettingsStore()
const errors: Record<string, Record<string, string>> = inject('errors') as Record<string, Record<string, string>> const { data, errors } = storeToRefs(systemSettingsStore)
</script> </script>
<template> <template>

View file

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import externalNotify from '@/api/external_notify' import externalNotify from '@/api/external_notify'
import { StdCurd } from '@/components/StdDesign/StdDataDisplay' import { StdCurd } from '@/components/StdDesign/StdDataDisplay'
import columns from './components/ExternalNotify/columns' import ExternalNotifyEditor from '../components/ExternalNotify'
import ExternalNotifyEditor from './components/ExternalNotify/ExternalNotifyEditor.vue' import columns from '../components/ExternalNotify/columns'
</script> </script>
<template> <template>

View file

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Settings } from '@/api/settings' import useSystemSettingsStore from '../store'
const data: Ref<Settings> = inject('data') as Ref<Settings> const systemSettingsStore = useSystemSettingsStore()
const errors: Record<string, Record<string, string>> = inject('errors') as Record<string, Record<string, string>> const { data, errors } = storeToRefs(systemSettingsStore)
</script> </script>
<template> <template>

View file

@ -1,7 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Settings } from '@/api/settings' import useSystemSettingsStore from '../store'
const data: Ref<Settings> = inject('data') as Ref<Settings> const systemSettingsStore = useSystemSettingsStore()
const { data } = storeToRefs(systemSettingsStore)
</script> </script>
<template> <template>

View file

@ -1,7 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Settings } from '@/api/settings' import useSystemSettingsStore from '../store'
const data: Ref<Settings> = inject('data') as Ref<Settings> const systemSettingsStore = useSystemSettingsStore()
const { data } = storeToRefs(systemSettingsStore)
</script> </script>
<template> <template>
@ -42,6 +43,19 @@ const data: Ref<Settings> = inject('data') as Ref<Settings>
<AFormItem :label="$gettext('Nginx Restart Command')"> <AFormItem :label="$gettext('Nginx Restart Command')">
{{ data.nginx.restart_cmd }} {{ data.nginx.restart_cmd }}
</AFormItem> </AFormItem>
<AFormItem :label="$gettext('Nginx Control Mode')">
<div v-if="data.nginx.container_name">
<ATag color="blue" tag>
{{ $gettext('External Docker Container') }}
</ATag>
{{ data.nginx.container_name }}
</div>
<div v-else>
<ATag color="green" tag>
{{ $gettext('Local') }}
</ATag>
</div>
</AFormItem>
</AForm> </AForm>
</template> </template>

View file

@ -1,9 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Settings } from '@/api/settings' import SensitiveString from '@/components/SensitiveString'
import SensitiveString from '@/components/SensitiveString/SensitiveString.vue' import useSystemSettingsStore from '../store'
const data: Ref<Settings> = inject('data') as Ref<Settings> const systemSettingsStore = useSystemSettingsStore()
const errors: Record<string, Record<string, string>> = inject('errors') as Record<string, Record<string, string>> const { data, errors } = storeToRefs(systemSettingsStore)
</script> </script>
<template> <template>

View file

@ -1,9 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Settings } from '@/api/settings'
import { LLM_MODELS, LLM_PROVIDERS } from '@/constants/llm' import { LLM_MODELS, LLM_PROVIDERS } from '@/constants/llm'
import useSystemSettingsStore from '../store'
const data: Ref<Settings> = inject('data') as Ref<Settings> const systemSettingsStore = useSystemSettingsStore()
const errors: Record<string, Record<string, string>> = inject('errors') as Record<string, Record<string, string>> const { data, errors } = storeToRefs(systemSettingsStore)
const models = LLM_MODELS.map(model => ({ const models = LLM_MODELS.map(model => ({
value: model, value: model,

View file

@ -1,9 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Cert } from '@/api/cert' import type { Cert } from '@/api/cert'
import type { Settings } from '@/api/settings'
import ChangeCert from '@/views/site/site_edit/components/Cert/ChangeCert.vue' import ChangeCert from '@/views/site/site_edit/components/Cert/ChangeCert.vue'
import useSystemSettingsStore from '../store'
const data: Ref<Settings> = inject('data') as Ref<Settings> const systemSettingsStore = useSystemSettingsStore()
const { data } = storeToRefs(systemSettingsStore)
function handleCertChange(certs: Cert[]) { function handleCertChange(certs: Cert[]) {
if (certs.length > 0 && data.value?.server) { if (certs.length > 0 && data.value?.server) {

View file

@ -1,7 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Settings } from '@/api/settings' import useSystemSettingsStore from '../store'
const data: Ref<Settings> = inject('data') as Ref<Settings> const systemSettingsStore = useSystemSettingsStore()
const { data } = storeToRefs(systemSettingsStore)
</script> </script>
<template> <template>

View file

@ -0,0 +1,11 @@
export { default as AppSettings } from './AppSettings.vue'
export { default as AuthSettings } from './AuthSettings.vue'
export { default as CertSettings } from './CertSettings.vue'
export { default as ExternalNotify } from './ExternalNotify.vue'
export { default as HTTPSettings } from './HTTPSettings.vue'
export { default as LogrotateSettings } from './LogrotateSettings.vue'
export { default as NginxSettings } from './NginxSettings.vue'
export { default as NodeSettings } from './NodeSettings.vue'
export { default as OpenAISettings } from './OpenAISettings.vue'
export { default as ServerSettings } from './ServerSettings.vue'
export { default as TerminalSettings } from './TerminalSettings.vue'