Install.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <script setup lang="ts">
  2. import type { InstallLockResponse } from '@/api/install'
  3. import install from '@/api/install'
  4. import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
  5. import SwitchAppearance from '@/components/SwitchAppearance/SwitchAppearance.vue'
  6. import { DatabaseOutlined, LockOutlined, MailOutlined, UserOutlined } from '@ant-design/icons-vue'
  7. import { Form, message } from 'ant-design-vue'
  8. const thisYear = new Date().getFullYear()
  9. const loading = ref(false)
  10. const installTimeout = ref(false)
  11. const router = useRouter()
  12. function init() {
  13. install.get_lock().then(async (r: InstallLockResponse) => {
  14. if (r.lock)
  15. await router.push('/login')
  16. if (r.timeout) {
  17. installTimeout.value = true
  18. }
  19. })
  20. }
  21. onMounted(() => {
  22. if (import.meta.env.DEV) {
  23. const route = useRoute()
  24. if (route.query.install !== 'false') {
  25. init()
  26. }
  27. else {
  28. installTimeout.value = route.query.timeout === 'true'
  29. }
  30. }
  31. else {
  32. init()
  33. }
  34. })
  35. const modelRef = reactive({
  36. email: '',
  37. username: '',
  38. password: '',
  39. database: '',
  40. })
  41. const rulesRef = reactive({
  42. email: [
  43. {
  44. required: true,
  45. type: 'email',
  46. message: () => $gettext('Please input your E-mail!'),
  47. },
  48. ],
  49. username: [
  50. {
  51. required: true,
  52. message: () => $gettext('Please input your username!'),
  53. },
  54. ],
  55. password: [
  56. {
  57. required: true,
  58. message: () => $gettext('Please input your password!'),
  59. },
  60. {
  61. max: 20,
  62. message: () => $gettext('Password length cannot exceed 20 characters'),
  63. },
  64. ],
  65. database: [
  66. {
  67. message: () =>
  68. $gettext('The filename cannot contain the following characters: %{c}', { c: '& &quot; ? < > # {} % ~ / \\' }),
  69. },
  70. ],
  71. })
  72. const { validate, validateInfos } = Form.useForm(modelRef, rulesRef)
  73. function onSubmit() {
  74. validate().then(() => {
  75. // modelRef
  76. loading.value = true
  77. install.install_nginx_ui(modelRef).then(async () => {
  78. message.success($gettext('Install successfully'))
  79. await router.push('/login')
  80. }).catch(error => {
  81. if (error && error.code === 40308) {
  82. installTimeout.value = true
  83. }
  84. }).finally(() => {
  85. loading.value = false
  86. })
  87. })
  88. }
  89. </script>
  90. <template>
  91. <ALayout>
  92. <ALayoutContent>
  93. <div class="login-container">
  94. <div class="login-form">
  95. <div class="project-title">
  96. <h1>Nginx UI</h1>
  97. </div>
  98. <AAlert
  99. v-if="installTimeout"
  100. type="warning"
  101. :message="$gettext('Installation is not allowed after 10 minutes of system startup, please restart the Nginx UI.')"
  102. show-icon
  103. style="margin-bottom: 20px;"
  104. />
  105. <AForm v-else id="components-form-install">
  106. <AFormItem v-bind="validateInfos.email">
  107. <AInput
  108. v-model:value="modelRef.email"
  109. :placeholder="$gettext('Email (*)')"
  110. >
  111. <template #prefix>
  112. <MailOutlined />
  113. </template>
  114. </AInput>
  115. </AFormItem>
  116. <AFormItem v-bind="validateInfos.username">
  117. <AInput
  118. v-model:value="modelRef.username"
  119. :placeholder="$gettext('Username (*)')"
  120. >
  121. <template #prefix>
  122. <UserOutlined />
  123. </template>
  124. </AInput>
  125. </AFormItem>
  126. <AFormItem v-bind="validateInfos.password">
  127. <AInputPassword
  128. v-model:value="modelRef.password"
  129. :placeholder="$gettext('Password (*)')"
  130. >
  131. <template #prefix>
  132. <LockOutlined />
  133. </template>
  134. </AInputPassword>
  135. </AFormItem>
  136. <AFormItem>
  137. <AInput
  138. v-bind="validateInfos.database"
  139. v-model:value="modelRef.database"
  140. :placeholder="$gettext('Database (Optional, default: database)')"
  141. >
  142. <template #prefix>
  143. <DatabaseOutlined />
  144. </template>
  145. </AInput>
  146. </AFormItem>
  147. <AFormItem>
  148. <AButton
  149. type="primary"
  150. block
  151. html-type="submit"
  152. :loading="loading"
  153. :disabled="installTimeout"
  154. @click="onSubmit"
  155. >
  156. {{ $gettext('Install') }}
  157. </AButton>
  158. </AFormItem>
  159. </AForm>
  160. <div class="footer">
  161. <p>Copyright © 2021 - {{ thisYear }} Nginx UI</p>
  162. Language
  163. <SetLanguage class="inline" />
  164. <div class="flex justify-center mt-4">
  165. <SwitchAppearance />
  166. </div>
  167. </div>
  168. </div>
  169. </div>
  170. </ALayoutContent>
  171. </ALayout>
  172. </template>
  173. <style lang="less" scoped>
  174. .ant-layout-content {
  175. background: #fff;
  176. }
  177. .dark .ant-layout-content {
  178. background: transparent;
  179. }
  180. .login-container {
  181. display: flex;
  182. align-items: center;
  183. justify-content: center;
  184. height: 100vh;
  185. .login-form {
  186. max-width: 400px;
  187. width: 80%;
  188. .project-title {
  189. margin: 50px;
  190. h1 {
  191. font-size: 50px;
  192. font-weight: 100;
  193. text-align: center;
  194. }
  195. }
  196. .anticon {
  197. color: #a8a5a5 !important;
  198. }
  199. .footer {
  200. padding: 30px;
  201. text-align: center;
  202. font-size: 14px;
  203. }
  204. }
  205. }
  206. </style>