Preference.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <script setup lang="ts">
  2. import { message } from 'ant-design-vue'
  3. import type { Ref } from 'vue'
  4. import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
  5. import settings from '@/api/settings'
  6. import BasicSettings from '@/views/preference/BasicSettings.vue'
  7. import OpenAISettings from '@/views/preference/OpenAISettings.vue'
  8. import NginxSettings from '@/views/preference/NginxSettings.vue'
  9. import type { Settings } from '@/views/preference/typedef'
  10. import LogrotateSettings from '@/views/preference/LogrotateSettings.vue'
  11. const data = ref<Settings>({
  12. server: {
  13. http_host: '0.0.0.0',
  14. http_port: '9000',
  15. run_mode: 'debug',
  16. jwt_secret: '',
  17. start_cmd: '',
  18. email: '',
  19. http_challenge_port: '9180',
  20. github_proxy: '',
  21. ca_dir: '',
  22. node_secret: '',
  23. cert_renewal_interval: 7,
  24. },
  25. nginx: {
  26. access_log_path: '',
  27. error_log_path: '',
  28. config_dir: '',
  29. pid_path: '',
  30. reload_cmd: '',
  31. restart_cmd: '',
  32. },
  33. openai: {
  34. model: '',
  35. base_url: '',
  36. proxy: '',
  37. token: '',
  38. },
  39. logrotate: {
  40. enabled: false,
  41. cmd: '',
  42. interval: 1440,
  43. },
  44. })
  45. settings.get().then(r => {
  46. data.value = r
  47. })
  48. const errors = ref({}) as Ref<Record<string, Record<string, string>>>
  49. async function save() {
  50. // fix type
  51. data.value.server.http_challenge_port = data.value.server.http_challenge_port.toString()
  52. settings.save(data.value).then(r => {
  53. data.value = r
  54. message.success($gettext('Save successfully'))
  55. errors.value = {}
  56. }).catch(e => {
  57. errors.value = e.errors
  58. message.error(e?.message ?? $gettext('Server error'))
  59. })
  60. }
  61. provide('data', data)
  62. provide('errors', errors)
  63. const router = useRouter()
  64. const route = useRoute()
  65. const activeKey = ref('basic')
  66. watch(activeKey, () => {
  67. router.push({
  68. query: {
  69. tab: activeKey.value,
  70. },
  71. })
  72. })
  73. onMounted(() => {
  74. if (route.query?.tab)
  75. activeKey.value = route.query.tab.toString()
  76. })
  77. </script>
  78. <template>
  79. <ACard :title="$gettext('Preference')">
  80. <div class="preference-container">
  81. <ATabs v-model:activeKey="activeKey">
  82. <ATabPane
  83. key="basic"
  84. :tab="$gettext('Basic')"
  85. >
  86. <BasicSettings />
  87. </ATabPane>
  88. <ATabPane
  89. key="nginx"
  90. :tab="$gettext('Nginx')"
  91. >
  92. <NginxSettings />
  93. </ATabPane>
  94. <ATabPane
  95. key="openai"
  96. :tab="$gettext('OpenAI')"
  97. >
  98. <OpenAISettings />
  99. </ATabPane>
  100. <ATabPane
  101. key="logrotate"
  102. :tab="$gettext('Logrotate')"
  103. >
  104. <LogrotateSettings />
  105. </ATabPane>
  106. </ATabs>
  107. </div>
  108. <FooterToolBar>
  109. <AButton
  110. type="primary"
  111. @click="save"
  112. >
  113. {{ $gettext('Save') }}
  114. </AButton>
  115. </FooterToolBar>
  116. </ACard>
  117. </template>
  118. <style lang="less" scoped>
  119. .preference-container {
  120. width: 100%;
  121. max-width: 600px;
  122. margin: 0 auto;
  123. padding: 0 10px;
  124. }
  125. </style>