index.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. <template>
  2. <div class="go-login-box">
  3. <div class="go-login-box-bg">
  4. <aside class="bg-slot"></aside>
  5. <aside class="bg-img-box">
  6. <transition-group name="list-complete">
  7. <template v-for="item in bgList" :key="item">
  8. <div class="bg-img-box-li list-complete-item">
  9. <n-collapse-transition :appear="true" :show="showBg">
  10. <img :src="getImageUrl(item, 'chart')" alt="chart" />
  11. </n-collapse-transition>
  12. </div>
  13. </template>
  14. </transition-group>
  15. </aside>
  16. </div>
  17. <Header>
  18. <template #left></template>
  19. <template #right>
  20. <LangSelect />
  21. <ThemeSelect />
  22. </template>
  23. </Header>
  24. <div class="go-login">
  25. <div class="go-login-carousel">
  26. <n-carousel autoplay :interval="Number(carouselInterval)">
  27. <img
  28. v-for="(item, i) in carouselImgList"
  29. :key="i"
  30. class="go-login-carousel-img"
  31. :src="getImageUrl(item, 'login')"
  32. alt="image"
  33. />
  34. </n-carousel>
  35. </div>
  36. <div class="login-account">
  37. <div class="login-account-container">
  38. <n-collapse-transition :appear="true" :show="show">
  39. <n-card class="login-account-card" :title="$t('login.desc')">
  40. <div class="login-account-top">
  41. <img
  42. class="login-account-top-logo"
  43. src="~@/assets/images/logo.png"
  44. alt="logo"
  45. />
  46. </div>
  47. <n-form
  48. ref="formRef"
  49. label-placement="left"
  50. size="large"
  51. :model="formInline"
  52. :rules="rules"
  53. >
  54. <n-form-item path="username">
  55. <n-input
  56. v-model:value="formInline.username"
  57. :placeholder="$t('global.form_account')"
  58. >
  59. <template #prefix>
  60. <n-icon size="18">
  61. <PersonOutlineIcon />
  62. </n-icon>
  63. </template>
  64. </n-input>
  65. </n-form-item>
  66. <n-form-item path="password">
  67. <n-input
  68. v-model:value="formInline.password"
  69. type="password"
  70. show-password-toggle
  71. :placeholder="$t('global.form_password')"
  72. >
  73. <template #prefix>
  74. <n-icon size="18">
  75. <LockClosedOutlineIcon />
  76. </n-icon>
  77. </template>
  78. </n-input>
  79. </n-form-item>
  80. <n-form-item>
  81. <div class="flex justify-between">
  82. <div class="flex-initial">
  83. <n-checkbox v-model:checked="autoLogin">
  84. {{ $t('login.form_auto') }}
  85. </n-checkbox>
  86. </div>
  87. </div>
  88. </n-form-item>
  89. <n-form-item>
  90. <n-button
  91. type="primary"
  92. @click="handleSubmit"
  93. size="large"
  94. :loading="loading"
  95. block
  96. >
  97. {{ $t('login.form_button') }}
  98. </n-button>
  99. </n-form-item>
  100. </n-form>
  101. </n-card>
  102. </n-collapse-transition>
  103. </div>
  104. </div>
  105. </div>
  106. <div class="go-login-box-footer">
  107. <Footer />
  108. </div>
  109. </div>
  110. </template>
  111. <script lang="ts" setup>
  112. import { reactive, ref, onMounted } from 'vue'
  113. import { useRouter } from 'vue-router'
  114. import { useMessage } from 'naive-ui'
  115. import { requireUrl } from '@/utils'
  116. import { routerTurnByName } from '@/utils'
  117. import shuffle from 'lodash/shuffle'
  118. import { carouselInterval } from '@/settings/designSetting'
  119. import { useDesignStore } from '@/store/modules/designStore/designStore'
  120. import { ThemeSelect } from '@/components/ThemeSelect'
  121. import { LangSelect } from '@/components/LangSelect'
  122. import { Header } from '@/layout/components/Header'
  123. import { Footer } from '@/layout/components/Footer'
  124. import { PageEnum } from '@/enums/pageEnum'
  125. import { icon } from '@/plugins'
  126. const { ChatboxEllipsesIcon, LockClosedOutlineIcon } = icon.ionicons5
  127. interface FormState {
  128. username: string
  129. password: string
  130. }
  131. const router = useRouter()
  132. const formRef = ref()
  133. const message = useMessage()
  134. const loading = ref(false)
  135. const autoLogin = ref(true)
  136. const show = ref(false)
  137. const showBg = ref(false)
  138. const designStore = useDesignStore()
  139. const t = window['$t']
  140. onMounted(() => {
  141. setTimeout(() => {
  142. show.value = true
  143. }, 300)
  144. setTimeout(() => {
  145. showBg.value = true
  146. }, 100)
  147. })
  148. const formInline = reactive({
  149. username: 'admin',
  150. password: '123456'
  151. })
  152. const rules = {
  153. username: {
  154. required: true,
  155. message: t('global.form_account'),
  156. trigger: 'blur'
  157. },
  158. password: {
  159. required: true,
  160. message: t('global.form_password'),
  161. trigger: 'blur'
  162. }
  163. }
  164. // 定时器
  165. const shuffleTimiing = ref()
  166. // 轮播图
  167. const carouselImgList = ['one', 'two', 'three']
  168. // 背景图
  169. const bgList = ref([
  170. 'bar_y',
  171. 'bar_x',
  172. 'line_gradient',
  173. 'line',
  174. 'funnel',
  175. 'heatmap',
  176. 'map',
  177. 'pie',
  178. 'radar'
  179. ])
  180. // 处理url获取
  181. const getImageUrl = (name: string, folder: string) => {
  182. return requireUrl(`../assets/images/${folder}/`, `${name}.png`)
  183. }
  184. // 打乱
  185. const shuffleHandle = () => {
  186. shuffleTimiing.value = setInterval(() => {
  187. bgList.value = shuffle(bgList.value)
  188. }, carouselInterval)
  189. }
  190. // 点击事件
  191. const handleSubmit = (e: Event) => {
  192. e.preventDefault()
  193. formRef.value.validate(async (errors: any) => {
  194. if (!errors) {
  195. const { username, password } = formInline
  196. loading.value = true
  197. message.success(`${t('login.login_success')}!`)
  198. routerTurnByName(PageEnum.BASE_HOME_NAME, true)
  199. } else {
  200. message.error(`${t('login.login_message')}!`)
  201. }
  202. })
  203. }
  204. onMounted(() => {
  205. shuffleHandle()
  206. })
  207. </script>
  208. <style lang="scss" scoped>
  209. $width: 450px;
  210. $go-login-height: 100vh;
  211. $account-img-height: 270px;
  212. $footer-height: 50px;
  213. $carousel-width: 30%;
  214. $carousel-image-height: 60vh;
  215. * {
  216. box-sizing: border-box;
  217. }
  218. @include go(login-box) {
  219. height: $go-login-height;
  220. overflow: hidden;
  221. @include background-image('background-image');
  222. &-header {
  223. display: flex;
  224. justify-content: space-between;
  225. align-items: center;
  226. padding: 0 40px;
  227. height: $--header-height;
  228. }
  229. &-divider {
  230. margin: 0;
  231. padding-top: 0;
  232. }
  233. @include go(login) {
  234. z-index: 2;
  235. display: flex;
  236. justify-content: space-around;
  237. align-items: center;
  238. margin-top: -$--header-height;
  239. height: $go-login-height;
  240. max-width: $--max-width;
  241. &-carousel {
  242. width: $carousel-width;
  243. margin-top: 100px;
  244. min-width: 500px;
  245. &-img {
  246. display: block;
  247. margin: 0 auto;
  248. height: $carousel-image-height;
  249. }
  250. }
  251. .login-account {
  252. display: flex;
  253. flex-direction: column;
  254. margin: 0 160px;
  255. &-container {
  256. width: $width;
  257. }
  258. &-card {
  259. @extend .go-background-filter;
  260. @include filter-bg-color('filter-color');
  261. box-shadow: 0 0 20px 5px rgba(40, 40, 40, 0.5);
  262. }
  263. &-top {
  264. padding-top: 10px;
  265. text-align: center;
  266. height: $account-img-height;
  267. margin-bottom: 20px;
  268. }
  269. }
  270. }
  271. &-footer {
  272. z-index: 2;
  273. position: fixed;
  274. width: 100%;
  275. bottom: 0;
  276. }
  277. &-bg {
  278. z-index: 0;
  279. position: fixed;
  280. display: flex;
  281. justify-content: space-around;
  282. align-items: center;
  283. width: $--max-width;
  284. height: 100vh;
  285. background: url('@/assets/images/login/login-bg.png') no-repeat 0 -120px;
  286. .bg-slot {
  287. width: $carousel-width;
  288. }
  289. .bg-img-box {
  290. position: relative;
  291. display: flex;
  292. flex-wrap: wrap;
  293. width: 770px;
  294. margin-right: -20px;
  295. &-li {
  296. img {
  297. margin-right: 20px;
  298. margin-top: 20px;
  299. height: 230px;
  300. border-radius: 2 * $--border-radius-base;
  301. opacity: 0.9;
  302. }
  303. }
  304. }
  305. }
  306. }
  307. @media only screen and (max-width: 1200px) {
  308. .bg-img-box,
  309. .bg-slot,
  310. .go-login-carousel {
  311. display: none !important;
  312. }
  313. .go-login-box-footer {
  314. position: relative;
  315. }
  316. }
  317. </style>