Browse Source

fix(style): dark mode style

0xJacky 1 year ago
parent
commit
2679527cce

+ 4 - 0
app/index.html

@@ -9,6 +9,10 @@
       height: auto !important;
       height: auto !important;
       min-height: 100%;
       min-height: 100%;
     }
     }
+    body.dark {
+      background-color: #141414;
+      color: #fff;
+    }
     #app {
     #app {
       height: 100%;
       height: 100%;
     }
     }

+ 64 - 1
app/src/App.vue

@@ -3,6 +3,11 @@
 // This starter template is using Vue 3 <script setup> SFCs
 // This starter template is using Vue 3 <script setup> SFCs
 // Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
 // Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
 import { computed, provide } from 'vue'
 import { computed, provide } from 'vue'
+import { theme } from 'ant-design-vue'
+import zh_CN from 'ant-design-vue/es/locale/zh_CN'
+import zh_TW from 'ant-design-vue/es/locale/zh_TW'
+import en_US from 'ant-design-vue/es/locale/en_US'
+import gettext from '@/gettext'
 import { useSettingsStore } from '@/pinia'
 import { useSettingsStore } from '@/pinia'
 
 
 const media = window.matchMedia('(prefers-color-scheme: dark)')
 const media = window.matchMedia('(prefers-color-scheme: dark)')
@@ -29,14 +34,72 @@ const devicePrefersTheme = computed(() => {
 provide('devicePrefersTheme', devicePrefersTheme)
 provide('devicePrefersTheme', devicePrefersTheme)
 
 
 media.addEventListener('change', callback)
 media.addEventListener('change', callback)
+
+const lang = computed(() => {
+  switch (gettext.current) {
+    case 'zh_CN':
+      return zh_CN
+    case 'zh_TW':
+      return zh_TW
+    default:
+      return en_US
+  }
+})
+
+const settings = useSettingsStore()
+const is_theme_dark = computed(() => settings.theme === 'dark')
 </script>
 </script>
 
 
 <template>
 <template>
-  <RouterView />
+  <AConfigProvider
+    :theme="{
+      algorithm: is_theme_dark ? theme.darkAlgorithm : theme.defaultAlgorithm,
+    }"
+    :locale="lang"
+    :auto-insert-space-in-button="false"
+  >
+    <RouterView />
+  </AConfigProvider>
 </template>
 </template>
 
 
 <style lang="less">
 <style lang="less">
 @import "ant-design-vue/dist/reset.css";
 @import "ant-design-vue/dist/reset.css";
+
+.dark {
+  h1, h2, h3, h4, h5, h6, p, div {
+    color: #fafafa;
+  }
+
+  .ant-checkbox-indeterminate {
+    .ant-checkbox-inner {
+      background-color: transparent !important;
+    }
+  }
+
+  .ant-layout-header {
+    background-color: #141414 !important;
+  }
+
+  .ant-layout-sider {
+    .ant-menu {
+      border-right: 0 !important;
+    }
+    &.ant-layout-sider-has-trigger {
+      padding-bottom: 0;
+    }
+  }
+}
+
+.ant-layout-header {
+  padding: 0 !important;
+  background-color: #fff !important;
+}
+
+.ant-layout-sider {
+  .ant-menu {
+    border-inline-end: none !important;
+  }
+}
 </style>
 </style>
 
 
 <style lang="less" scoped>
 <style lang="less" scoped>

+ 1 - 1
app/src/components/PageHeader/PageHeader.vue

@@ -39,7 +39,7 @@ const name = computed(() => {
 <style lang="less" scoped>
 <style lang="less" scoped>
 .dark {
 .dark {
   .page-header {
   .page-header {
-    background: #28292c !important;
+    background: #090909 !important;
     border-bottom: unset;
     border-bottom: unset;
 
 
     h1 {
     h1 {

+ 0 - 2
app/src/components/StdDesign/StdDataEntry/components/StdSelector.vue

@@ -138,10 +138,8 @@ const _selectedKey = computed({
     font-feature-settings: 'tnum';
     font-feature-settings: 'tnum';
     height: 32px;
     height: 32px;
     padding: 4px 11px;
     padding: 4px 11px;
-    color: rgba(0, 0, 0, 0.85);
     font-size: 14px;
     font-size: 14px;
     line-height: 1.5;
     line-height: 1.5;
-    background-color: #fff;
     background-image: none;
     background-image: none;
     border: 1px solid #d9d9d9;
     border: 1px solid #d9d9d9;
     border-radius: 4px;
     border-radius: 4px;

+ 44 - 120
app/src/layouts/BaseLayout.vue

@@ -1,18 +1,10 @@
 <script setup lang="ts">
 <script setup lang="ts">
-import zh_CN from 'ant-design-vue/es/locale/zh_CN'
-import zh_TW from 'ant-design-vue/es/locale/zh_TW'
-import en_US from 'ant-design-vue/es/locale/en_US'
-import { computed, ref } from 'vue'
-import { theme } from 'ant-design-vue'
 import _ from 'lodash'
 import _ from 'lodash'
 import FooterLayout from './FooterLayout.vue'
 import FooterLayout from './FooterLayout.vue'
 import SideBar from './SideBar.vue'
 import SideBar from './SideBar.vue'
 import HeaderLayout from './HeaderLayout.vue'
 import HeaderLayout from './HeaderLayout.vue'
 import PageHeader from '@/components/PageHeader/PageHeader.vue'
 import PageHeader from '@/components/PageHeader/PageHeader.vue'
 
 
-import gettext from '@/gettext'
-import { useSettingsStore } from '@/pinia'
-
 const drawer_visible = ref(false)
 const drawer_visible = ref(false)
 const collapsed = ref(collapse())
 const collapsed = ref(collapse())
 
 
@@ -27,78 +19,56 @@ function getClientWidth() {
 function collapse() {
 function collapse() {
   return getClientWidth() < 1280
   return getClientWidth() < 1280
 }
 }
-
-const lang = computed(() => {
-  switch (gettext.current) {
-    case 'zh_CN':
-      return zh_CN
-    case 'zh_TW':
-      return zh_TW
-    default:
-      return en_US
-  }
-})
-
-const settings = useSettingsStore()
-const is_theme_dark = computed(() => settings.theme === 'dark')
 </script>
 </script>
 
 
 <template>
 <template>
-  <AConfigProvider
-    :theme="{
-      algorithm: is_theme_dark ? theme.darkAlgorithm : theme.defaultAlgorithm,
-    }"
-    :locale="lang"
-    :auto-insert-space-in-button="false"
-  >
-    <ALayout style="min-height: 100vh">
-      <div class="drawer-sidebar">
-        <ADrawer
-          v-model:open="drawer_visible"
-          :closable="false"
-          placement="left"
-          width="256"
-          @close="drawer_visible = false"
-        >
-          <SideBar />
-        </ADrawer>
-      </div>
-
-      <ALayoutSider
-        v-model:collapsed="collapsed"
-        collapsible
-        :style="{ zIndex: 11 }"
-        theme="light"
-        class="layout-sider"
+  <ALayout class="min-h-screen">
+    <div class="drawer-sidebar">
+      <ADrawer
+        v-model:open="drawer_visible"
+        :closable="false"
+        placement="left"
+        width="256"
+        @close="drawer_visible = false"
       >
       >
         <SideBar />
         <SideBar />
-      </ALayoutSider>
-
-      <ALayout>
-        <ALayoutHeader :style="{ position: 'sticky', top: '0', zIndex: 10, width: '100%' }">
-          <HeaderLayout @click-un-fold="drawer_visible = true" />
-        </ALayoutHeader>
-
-        <ALayoutContent>
-          <PageHeader />
-          <div class="router-view">
-            <RouterView v-slot="{ Component, route }">
-              <Transition name="slide-fade">
-                <component
-                  :is="Component"
-                  :key="route.path"
-                />
-              </Transition>
-            </RouterView>
-          </div>
-        </ALayoutContent>
-
-        <ALayoutFooter>
-          <FooterLayout />
-        </ALayoutFooter>
-      </ALayout>
+      </ADrawer>
+    </div>
+
+    <ALayoutSider
+      v-model:collapsed="collapsed"
+      collapsible
+      :style="{ zIndex: 11 }"
+      theme="light"
+      class="layout-sider"
+    >
+      <SideBar />
+    </ALayoutSider>
+
+    <ALayout>
+      <ALayoutHeader :style="{ position: 'sticky', top: '0', zIndex: 10, width: '100%' }">
+        <HeaderLayout @click-un-fold="drawer_visible = true" />
+      </ALayoutHeader>
+
+      <ALayoutContent>
+        <PageHeader />
+        <div class="router-view">
+          <RouterView v-slot="{ Component, route }">
+            <Transition name="slide-fade">
+              <component
+                :is="Component"
+                :key="route.path"
+              />
+            </Transition>
+          </RouterView>
+        </div>
+      </ALayoutContent>
+
+      <ALayoutFooter>
+        <FooterLayout />
+      </ALayoutFooter>
     </ALayout>
     </ALayout>
-  </AConfigProvider>
+  </ALayout>
 </template>
 </template>
 
 
 <style lang="less" scoped>
 <style lang="less" scoped>
@@ -154,57 +124,11 @@ body {
   overflow: unset !important;
   overflow: unset !important;
 }
 }
 
 
-.dark {
-  h1, h2, h3, h4, h5, h6, p {
-    color: #fafafa !important;
-  }
-
-  .ant-checkbox-indeterminate {
-    .ant-checkbox-inner {
-      background-color: transparent !important;
-    }
-  }
-
-  .ant-menu {
-    background: unset !important;
-  }
-
-  .ant-layout-header {
-    background-color: #1f1f1f !important;
-  }
-
-  .ant-card {
-    background-color: #1f1f1f !important;
-  }
-
-  .ant-layout-sider {
-    background-color: rgb(20, 20, 20) !important;
-
-    .ant-layout-sider-trigger {
-      background-color: rgb(20, 20, 20) !important;
-    }
-
-    .ant-menu {
-      border-right: 0 !important;
-    }
-
-    &.ant-layout-sider-has-trigger {
-      padding-bottom: 0;
-    }
-
-    box-shadow: 2px 0 8px rgba(29, 35, 41, 0.05);
-  }
-
-}
-
 .ant-layout-header {
 .ant-layout-header {
   padding: 0 !important;
   padding: 0 !important;
-  background-color: #fff !important;
 }
 }
 
 
 .ant-layout-sider {
 .ant-layout-sider {
-  background-color: #ffffff;
-
   &.ant-layout-sider-has-trigger {
   &.ant-layout-sider-has-trigger {
     padding-bottom: 0;
     padding-bottom: 0;
   }
   }

+ 0 - 1
app/src/routes/index.ts

@@ -50,7 +50,6 @@ export const routes: Route[] = [
         component: () => import('@/views/dashboard/DashBoard.vue'),
         component: () => import('@/views/dashboard/DashBoard.vue'),
         name: () => $gettext('Dashboard'),
         name: () => $gettext('Dashboard'),
         meta: {
         meta: {
-          // hiddenHeaderContent: true,
           icon: HomeOutlined,
           icon: HomeOutlined,
         },
         },
       },
       },

+ 0 - 1
app/src/views/config/InspectConfig.vue

@@ -1,6 +1,5 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { useGettext } from 'vue3-gettext'
 import { useGettext } from 'vue3-gettext'
-import { ref } from 'vue'
 import ngx from '@/api/ngx'
 import ngx from '@/api/ngx'
 import { logLevel } from '@/views/config/constants'
 import { logLevel } from '@/views/config/constants'
 
 

+ 5 - 0
app/src/views/domain/cert/IssueCert.vue

@@ -68,6 +68,11 @@ async function onchange() {
 </template>
 </template>
 
 
 <style lang="less">
 <style lang="less">
+.dark {
+  .issue-cert-log-container {
+    background-color: rgba(0, 0, 0, 0.84);
+  }
+}
 .issue-cert-log-container {
 .issue-cert-log-container {
   height: 320px;
   height: 320px;
   overflow: scroll;
   overflow: scroll;

+ 40 - 36
app/src/views/domain/cert/components/ObtainCert.vue

@@ -1,7 +1,6 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { useGettext } from 'vue3-gettext'
 import { useGettext } from 'vue3-gettext'
-import Modal from 'ant-design-vue/lib/modal'
-import { message } from 'ant-design-vue'
+import { Modal, message } from 'ant-design-vue'
 import type { Ref } from 'vue'
 import type { Ref } from 'vue'
 import websocket from '@/lib/websocket'
 import websocket from '@/lib/websocket'
 import template from '@/api/template'
 import template from '@/api/template'
@@ -19,6 +18,8 @@ const modalVisible = ref(false)
 const step = ref(1)
 const step = ref(1)
 const directivesMap = inject('directivesMap') as Ref<Record<string, NgxDirective[]>>
 const directivesMap = inject('directivesMap') as Ref<Record<string, NgxDirective[]>>
 
 
+const [modal, ContextHolder] = Modal.useModal()
+
 const progressStrokeColor = {
 const progressStrokeColor = {
   from: '#108ee9',
   from: '#108ee9',
   to: '#87d068',
   to: '#87d068',
@@ -202,7 +203,7 @@ function log(msg: string) {
 
 
 function toggle(status: boolean) {
 function toggle(status: boolean) {
   if (status) {
   if (status) {
-    Modal.confirm({
+    modal.confirm({
       title: $gettext('Do you want to disable auto-cert renewal?'),
       title: $gettext('Do you want to disable auto-cert renewal?'),
       content: $gettext('We will remove the HTTPChallenge configuration from '
       content: $gettext('We will remove the HTTPChallenge configuration from '
         + 'this file and reload the Nginx. Are you sure you want to continue?'),
         + 'this file and reload the Nginx. Are you sure you want to continue?'),
@@ -244,41 +245,44 @@ function next() {
 </script>
 </script>
 
 
 <template>
 <template>
-  <AModal
-    v-model:open="modalVisible"
-    :title="$gettext('Obtain certificate')"
-    :mask-closable="modalClosable"
-    :footer="null"
-    :closable="modalClosable"
-    force-render
-  >
-    <template v-if="step === 1">
-      <AutoCertStepOne />
-    </template>
-    <template v-else-if="step === 2">
-      <AProgress
-        :stroke-color="progressStrokeColor"
-        :percent="progressPercent"
-        :status="progressStatus"
-      />
-
-      <div
-        ref="logContainer"
-        class="issue-cert-log-container"
-      />
-    </template>
-    <div
-      v-if="can_next"
-      class="control-btn"
+  <div>
+    <ContextHolder />
+    <AModal
+      v-model:open="modalVisible"
+      :title="$gettext('Obtain certificate')"
+      :mask-closable="modalClosable"
+      :footer="null"
+      :closable="modalClosable"
+      force-render
     >
     >
-      <AButton
-        type="primary"
-        @click="next"
+      <template v-if="step === 1">
+        <AutoCertStepOne />
+      </template>
+      <template v-else-if="step === 2">
+        <AProgress
+          :stroke-color="progressStrokeColor"
+          :percent="progressPercent"
+          :status="progressStatus"
+        />
+
+        <div
+          ref="logContainer"
+          class="issue-cert-log-container"
+        />
+      </template>
+      <div
+        v-if="can_next"
+        class="control-btn"
       >
       >
-        {{ $gettext('Next') }}
-      </AButton>
-    </div>
-  </AModal>
+        <AButton
+          type="primary"
+          @click="next"
+        >
+          {{ $gettext('Next') }}
+        </AButton>
+      </div>
+    </AModal>
+  </div>
 </template>
 </template>
 
 
 <style lang="less" scoped>
 <style lang="less" scoped>

+ 4 - 4
app/src/views/domain/components/Deploy.vue

@@ -2,8 +2,7 @@
 import { useGettext } from 'vue3-gettext'
 import { useGettext } from 'vue3-gettext'
 import { inject, reactive, ref } from 'vue'
 import { inject, reactive, ref } from 'vue'
 import { InfoCircleOutlined } from '@ant-design/icons-vue'
 import { InfoCircleOutlined } from '@ant-design/icons-vue'
-import Modal from 'ant-design-vue/lib/modal'
-import { notification } from 'ant-design-vue'
+import { Modal, notification } from 'ant-design-vue'
 import domain from '@/api/domain'
 import domain from '@/api/domain'
 import NodeSelector from '@/components/NodeSelector/NodeSelector.vue'
 import NodeSelector from '@/components/NodeSelector/NodeSelector.vue'
 
 
@@ -14,9 +13,9 @@ const target = ref([])
 const overwrite = ref(false)
 const overwrite = ref(false)
 const enabled = ref(false)
 const enabled = ref(false)
 const name = inject('name') as Ref<string>
 const name = inject('name') as Ref<string>
-
+const [modal, ContextHolder] = Modal.useModal()
 function deploy() {
 function deploy() {
-  Modal.confirm({
+  modal.confirm({
     title: () => $ngettext('Do you want to deploy this file to remote server?',
     title: () => $ngettext('Do you want to deploy this file to remote server?',
       'Do you want to deploy this file to remote servers?', target.value.length),
       'Do you want to deploy this file to remote servers?', target.value.length),
     mask: false,
     mask: false,
@@ -79,6 +78,7 @@ function deploy() {
 </script>
 </script>
 
 
 <template>
 <template>
+  <ContextHolder />
   <NodeSelector
   <NodeSelector
     v-model:target="target"
     v-model:target="target"
     hidden-local
     hidden-local

+ 5 - 3
app/src/views/domain/components/RightSettings.vue

@@ -1,7 +1,6 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { useGettext } from 'vue3-gettext'
 import { useGettext } from 'vue3-gettext'
-import Modal from 'ant-design-vue/lib/modal'
-import { message } from 'ant-design-vue'
+import { Modal, message } from 'ant-design-vue'
 import type { Ref } from 'vue'
 import type { Ref } from 'vue'
 import type { Site } from '@/api/domain'
 import type { Site } from '@/api/domain'
 import domain from '@/api/domain'
 import domain from '@/api/domain'
@@ -22,6 +21,8 @@ const history_chatgpt_record = inject('history_chatgpt_record') as Ref<ChatCompl
 const filename = inject('filename')
 const filename = inject('filename')
 const data: Ref<Site> = inject('data') as Ref<Site>
 const data: Ref<Site> = inject('data') as Ref<Site>
 
 
+const [modal, ContextHolder] = Modal.useModal()
+
 const active_key = ref(['1', '2', '3'])
 const active_key = ref(['1', '2', '3'])
 
 
 function enable() {
 function enable() {
@@ -43,7 +44,7 @@ function disable() {
 }
 }
 
 
 function on_change_enabled(checked: boolean) {
 function on_change_enabled(checked: boolean) {
-  Modal.confirm({
+  modal.confirm({
     title: checked ? $gettext('Do you want to enable this site?') : $gettext('Do you want to disable this site?'),
     title: checked ? $gettext('Do you want to enable this site?') : $gettext('Do you want to disable this site?'),
     mask: false,
     mask: false,
     centered: true,
     centered: true,
@@ -62,6 +63,7 @@ function on_change_enabled(checked: boolean) {
 
 
 <template>
 <template>
   <ACard class="right-settings">
   <ACard class="right-settings">
+    <ContextHolder />
     <ACollapse
     <ACollapse
       v-model:activeKey="active_key"
       v-model:activeKey="active_key"
       ghost
       ghost

+ 5 - 2
app/src/views/domain/ngx_conf/NgxConfigEditor.vue

@@ -29,6 +29,8 @@ const { $gettext } = useGettext()
 
 
 const save_site_config = inject('save_site_config') as () => Promise<void>
 const save_site_config = inject('save_site_config') as () => Promise<void>
 
 
+const [modal, ContextHolder] = Modal.useModal()
+
 const route = useRoute()
 const route = useRoute()
 
 
 const current_server_index = ref(0)
 const current_server_index = ref(0)
@@ -37,7 +39,7 @@ const name = ref(route.params.name) as Ref<string>
 const ngx_config = inject('ngx_config') as NgxConfig
 const ngx_config = inject('ngx_config') as NgxConfig
 
 
 function confirm_change_tls(status: boolean) {
 function confirm_change_tls(status: boolean) {
-  Modal.confirm({
+  modal.confirm({
     title: $gettext('Do you want to enable TLS?'),
     title: $gettext('Do you want to enable TLS?'),
     content: $gettext('To make sure the certification auto-renewal can work normally, '
     content: $gettext('To make sure the certification auto-renewal can work normally, '
       + 'we need to add a location which can proxy the request from authority to backend, '
       + 'we need to add a location which can proxy the request from authority to backend, '
@@ -208,7 +210,7 @@ function add_server() {
 }
 }
 
 
 function remove_server(index: number) {
 function remove_server(index: number) {
-  Modal.confirm({
+  modal.confirm({
     title: $gettext('Do you want to remove this server?'),
     title: $gettext('Do you want to remove this server?'),
     mask: false,
     mask: false,
     centered: true,
     centered: true,
@@ -230,6 +232,7 @@ provide('directivesMap', directivesMap)
 
 
 <template>
 <template>
   <div>
   <div>
+    <ContextHolder />
     <AFormItem
     <AFormItem
       v-if="!support_ssl"
       v-if="!support_ssl"
       :label="$gettext('Enable TLS')"
       :label="$gettext('Enable TLS')"

+ 69 - 72
app/src/views/other/Install.vue

@@ -6,6 +6,7 @@ import { DatabaseOutlined, LockOutlined, MailOutlined, UserOutlined } from '@ant
 import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
 import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
 import gettext from '@/gettext'
 import gettext from '@/gettext'
 import install from '@/api/install'
 import install from '@/api/install'
+import SwitchAppearance from '@/components/SwitchAppearance/SwitchAppearance.vue'
 
 
 const { $gettext, interpolate } = gettext
 const { $gettext, interpolate } = gettext
 
 
@@ -77,75 +78,75 @@ const onSubmit = () => {
 </script>
 </script>
 
 
 <template>
 <template>
-  <div class="login-form">
-    <div class="project-title">
-      <h1>Nginx UI</h1>
+  <ALayout>
+    <div class="login-form">
+      <div class="project-title">
+        <h1>Nginx UI</h1>
+      </div>
+      <AForm
+        id="components-form-install"
+        class="login-form"
+      >
+        <AFormItem v-bind="validateInfos.email">
+          <AInput
+            v-model:value="modelRef.email"
+            :placeholder="$gettext('Email (*)')"
+          >
+            <template #prefix>
+              <MailOutlined />
+            </template>
+          </AInput>
+        </AFormItem>
+        <AFormItem v-bind="validateInfos.username">
+          <AInput
+            v-model:value="modelRef.username"
+            :placeholder="$gettext('Username (*)')"
+          >
+            <template #prefix>
+              <UserOutlined />
+            </template>
+          </AInput>
+        </AFormItem>
+        <AFormItem v-bind="validateInfos.password">
+          <AInputPassword
+            v-model:value="modelRef.password"
+            :placeholder="$gettext('Password (*)')"
+          >
+            <template #prefix>
+              <LockOutlined />
+            </template>
+          </AInputPassword>
+        </AFormItem>
+        <AFormItem>
+          <AInput
+            v-bind="validateInfos.database"
+            v-model:value="modelRef.database"
+            :placeholder="$gettext('Database (Optional, default: database)')"
+          >
+            <template #prefix>
+              <DatabaseOutlined />
+            </template>
+          </AInput>
+        </AFormItem>
+        <AFormItem>
+          <AButton
+            type="primary"
+            block
+            html-type="submit"
+            :loading="loading"
+            @click="onSubmit"
+          >
+            {{ $gettext('Install') }}
+          </AButton>
+        </AFormItem>
+      </AForm>
+      <footer>
+        Copyright © 2020 - {{ thisYear }} Nginx UI | Language
+        <SetLanguage class="inline" />
+        <SwitchAppearance />
+      </footer>
     </div>
     </div>
-    <AForm
-      id="components-form-install"
-      class="login-form"
-    >
-      <AFormItem v-bind="validateInfos.email">
-        <AInput
-          v-model:value="modelRef.email"
-          :placeholder="$gettext('Email (*)')"
-        >
-          <template #prefix>
-            <MailOutlined />
-          </template>
-        </AInput>
-      </AFormItem>
-      <AFormItem v-bind="validateInfos.username">
-        <AInput
-          v-model:value="modelRef.username"
-          :placeholder="$gettext('Username (*)')"
-        >
-          <template #prefix>
-            <UserOutlined />
-          </template>
-        </AInput>
-      </AFormItem>
-      <AFormItem v-bind="validateInfos.password">
-        <AInputPassword
-          v-model:value="modelRef.password"
-          :placeholder="$gettext('Password (*)')"
-        >
-          <template #prefix>
-            <LockOutlined />
-          </template>
-        </AInputPassword>
-      </AFormItem>
-      <AFormItem>
-        <AInput
-          v-bind="validateInfos.database"
-          v-model:value="modelRef.database"
-          :placeholder="$gettext('Database (Optional, default: database)')"
-        >
-          <template #prefix>
-            <DatabaseOutlined />
-          </template>
-        </AInput>
-      </AFormItem>
-      <AFormItem>
-        <AButton
-          type="primary"
-          block
-          html-type="submit"
-          :loading="loading"
-          @click="onSubmit"
-        >
-          {{ $gettext('Install') }}
-        </AButton>
-      </AFormItem>
-    </AForm>
-    <footer>
-      Copyright © 2020 - {{ thisYear }} Nginx UI | Language
-      <SetLanguage
-        class="set_lang"
-        style="display: inline"
-      />
-    </footer>
-  </div>
+  </ALayout>
 </template>
 </template>
 
 
 <style lang="less">
 <style lang="less">
@@ -164,10 +165,6 @@ const onSubmit = () => {
   margin: 0 auto;
   margin: 0 auto;
 }
 }
 
 
-.login-form-button {
-
-}
-
 footer {
 footer {
   padding: 30px;
   padding: 30px;
   text-align: center;
   text-align: center;

+ 64 - 55
app/src/views/other/Login.vue

@@ -9,6 +9,7 @@ import auth from '@/api/auth'
 import install from '@/api/install'
 import install from '@/api/install'
 import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
 import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
 import http from '@/lib/http'
 import http from '@/lib/http'
+import SwitchAppearance from '@/components/SwitchAppearance/SwitchAppearance.vue'
 
 
 const thisYear = new Date().getFullYear()
 const thisYear = new Date().getFullYear()
 
 
@@ -110,66 +111,78 @@ if (route.query?.code !== undefined && route.query?.state !== undefined) {
 </script>
 </script>
 
 
 <template>
 <template>
-  <div class="login-container">
-    <div class="login-form">
-      <div class="project-title">
-        <h1>Nginx UI</h1>
-      </div>
-      <AForm id="components-form-demo-normal-login">
-        <AFormItem v-bind="validateInfos.username">
-          <AInput
-            v-model:value="modelRef.username"
-            :placeholder="$gettext('Username')"
-          >
-            <template #prefix>
-              <UserOutlined style="color: rgba(0, 0, 0, 0.25)" />
-            </template>
-          </AInput>
-        </AFormItem>
-        <AFormItem v-bind="validateInfos.password">
-          <AInputPassword
-            v-model:value="modelRef.password"
-            :placeholder="$gettext('Password')"
-          >
-            <template #prefix>
-              <LockOutlined style="color: rgba(0, 0, 0, 0.25)" />
-            </template>
-          </AInputPassword>
-        </AFormItem>
-        <AFormItem>
+  <ALayout>
+    <ALayoutContent>
+      <div class="login-container">
+        <div class="login-form">
+          <div class="project-title">
+            <h1>Nginx UI</h1>
+          </div>
+          <AForm id="components-form-demo-normal-login">
+            <AFormItem v-bind="validateInfos.username">
+              <AInput
+                v-model:value="modelRef.username"
+                :placeholder="$gettext('Username')"
+              >
+                <template #prefix>
+                  <UserOutlined style="color: rgba(0, 0, 0, 0.25)" />
+                </template>
+              </AInput>
+            </AFormItem>
+            <AFormItem v-bind="validateInfos.password">
+              <AInputPassword
+                v-model:value="modelRef.password"
+                :placeholder="$gettext('Password')"
+              >
+                <template #prefix>
+                  <LockOutlined style="color: rgba(0, 0, 0, 0.25)" />
+                </template>
+              </AInputPassword>
+            </AFormItem>
+            <AFormItem>
+              <AButton
+                type="primary"
+                block
+                html-type="submit"
+                :loading="loading"
+                @click="onSubmit"
+              >
+                {{ $gettext('Login') }}
+              </AButton>
+            </AFormItem>
+          </AForm>
           <AButton
           <AButton
-            type="primary"
+            v-if="has_casdoor"
             block
             block
             html-type="submit"
             html-type="submit"
             :loading="loading"
             :loading="loading"
-            @click="onSubmit"
+            @click="loginWithCasdoor"
           >
           >
-            {{ $gettext('Login') }}
+            {{ $gettext('SSO Login') }}
           </AButton>
           </AButton>
-        </AFormItem>
-      </AForm>
-      <AButton
-        v-if="has_casdoor"
-        block
-        html-type="submit"
-        :loading="loading"
-        @click="loginWithCasdoor"
-      >
-        {{ $gettext('SSO Login') }}
-      </AButton>
-      <div class="footer">
-        <p>Copyright © 2020 - {{ thisYear }} Nginx UI</p>
-        Language
-        <SetLanguage
-          class="set_lang"
-          style="display: inline"
-        />
+          <div class="footer">
+            <p>Copyright © 2020 - {{ thisYear }} Nginx UI</p>
+            Language
+            <SetLanguage class="inline" />
+            <div class="flex justify-center mt-4">
+              <SwitchAppearance />
+            </div>
+          </div>
+        </div>
       </div>
       </div>
-    </div>
-  </div>
+    </ALayoutContent>
+  </ALayout>
 </template>
 </template>
 
 
-<style lang="less">
+<style lang="less" scoped>
+.ant-layout-content {
+  background: #fff;
+}
+
+.dark .ant-layout-content {
+  background: transparent;
+}
+
 .login-container {
 .login-container {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
@@ -194,10 +207,6 @@ if (route.query?.code !== undefined && route.query?.state !== undefined) {
       color: #a8a5a5 !important;
       color: #a8a5a5 !important;
     }
     }
 
 
-    .login-form-button {
-
-    }
-
     .footer {
     .footer {
       padding: 30px;
       padding: 30px;
       text-align: center;
       text-align: center;