index.vue 9.3 KB

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