index.vue 8.1 KB

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