沙钢智慧能源系统前端代码
houzhongjian
2024-10-31 8e4ab7acddbdb84fd755acf7e75cf471f50cba60
提交 | 用户 | 时间
314507 1 <template>
H 2   <el-form
3     v-show="getShow"
4     ref="formLogin"
5     :model="loginData.loginForm"
6     :rules="LoginRules"
7     class="login-form"
8     label-position="top"
9     label-width="120px"
10     size="large"
11   >
12     <el-row style="margin-right: -10px; margin-left: -10px">
13       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
14         <el-form-item>
15           <LoginFormTitle style="width: 100%" />
16         </el-form-item>
17       </el-col>
18       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
19         <el-form-item prop="username">
20           <el-input
21             v-model="loginData.loginForm.username"
22             :placeholder="t('login.usernamePlaceholder')"
23             :prefix-icon="iconAvatar"
24           />
25         </el-form-item>
26       </el-col>
27       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
28         <el-form-item prop="password">
29           <el-input
30             v-model="loginData.loginForm.password"
31             :placeholder="t('login.passwordPlaceholder')"
32             :prefix-icon="iconLock"
33             show-password
34             type="password"
35             @keyup.enter="getCode()"
36           />
37         </el-form-item>
38       </el-col>
39       <el-col
40         :span="24"
41         style="padding-right: 10px; padding-left: 10px; margin-top: -20px; margin-bottom: -20px"
42       >
43         <el-form-item>
44           <el-row justify="space-between" style="width: 100%">
45             <el-col :span="6">
46               <el-checkbox v-model="loginData.loginForm.rememberMe">
47                 {{ t('login.remember') }}
48               </el-checkbox>
49             </el-col>
50             <el-col :offset="6" :span="12">
51               <el-link style="float: right" type="primary">{{ t('login.forgetPassword') }}</el-link>
52             </el-col>
53           </el-row>
54         </el-form-item>
55       </el-col>
56       <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
57         <el-form-item>
58           <XButton
59             :loading="loginLoading"
60             :title="t('login.login')"
61             class="w-[100%]"
62             type="primary"
63             @click="getCode()"
64           />
65         </el-form-item>
66       </el-col>
8e4ab7 67       <Verify
H 68         ref="verify"
69         :captchaType="captchaType"
70         :imgSize="{ width: '400px', height: '200px' }"
71         mode="pop"
72         @success="handleLogin"
73       />
314507 74     </el-row>
8e4ab7 75
H 76 <!--    &lt;!&ndash;                统一身份登录&ndash;&gt;-->
77 <!--    <el-divider content-position="center">统一身份登录</el-divider>-->
78 <!--    <el-col :span="24" style="padding-right: 10px; padding-left: 10px">-->
79 <!--      <el-form-item>-->
80 <!--        <el-row :gutter="10" justify="space-between" style="width: 100%">-->
81 <!--          <el-col :span="8">-->
82 <!--            <el-button type="primary" style="width: 100%;"-->
83 <!--                       @click="ssoPasswordLogin">-->
84 <!--              {{ ssoLoginPasswordTitle }}-->
85 <!--            </el-button>-->
86 <!--          </el-col>-->
87 <!--          <el-col :span="8">-->
88 <!--            <el-button type="primary" style="width: 100%;"-->
89 <!--                       @click="ssoCodeLogin">-->
90 <!--              {{ ssoLoginCodeTitle }}-->
91 <!--            </el-button>-->
92 <!--          </el-col>-->
93 <!--        </el-row>-->
94 <!--      </el-form-item>-->
95 <!--    </el-col>-->
314507 96   </el-form>
H 97 </template>
98 <script lang="ts" setup>
99 import { ElLoading } from 'element-plus'
100 import LoginFormTitle from './LoginFormTitle.vue'
101 import type { RouteLocationNormalizedLoaded } from 'vue-router'
102
103 import { useIcon } from '@/hooks/web/useIcon'
104
105 import * as authUtil from '@/utils/auth'
106 import * as LoginApi from '@/api/login'
107 import { LoginStateEnum, useFormValid, useLoginState } from './useLogin'
8e4ab7 108 // import axios from "axios";
314507 109
H 110 defineOptions({ name: 'LoginForm' })
111
112 const { t } = useI18n()
113 const iconAvatar = useIcon({ icon: 'ep:avatar' })
114 const iconLock = useIcon({ icon: 'ep:lock' })
115 const formLogin = ref()
116 const { validForm } = useFormValid(formLogin)
117 const { getLoginState } = useLoginState()
118 const { currentRoute, push } = useRouter()
119 const redirect = ref<string>('')
120 const loginLoading = ref(false)
8e4ab7 121 // const ssoLoginPasswordTitle = ref('账号密码模式')
H 122 // const ssoLoginCodeTitle = ref('授权码模式')
314507 123 const verify = ref()
8e4ab7 124 const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字
314507 125
H 126 const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN)
127
128 const LoginRules = {
129   username: [required],
130   password: [required]
131 }
132 const loginData = reactive({
133   isShowPassword: false,
134   captchaEnable: import.meta.env.VITE_APP_CAPTCHA_ENABLE,
135   loginForm: {
136     username: import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME || '',
137     password: import.meta.env.VITE_APP_DEFAULT_LOGIN_PASSWORD || '',
138     scope: 'user.read user.write',
139     grantType: 'password',
8e4ab7 140     captchaVerification: '',
314507 141     rememberMe: true // 默认记录我。如果不需要,可手动修改
H 142   }
143 })
8e4ab7 144
H 145 // const ssoLoginData = reactive({
146 //   loginParam: {
147 //     username: '',
148 //     password: '',
149 //     token: ''
150 //   }
151 // })
152 //
153 // const oauth2Token = reactive({
154 //   oauthParam: {
155 //     clientId: 'shasteel',
156 //     clientSecret: 'shasteel111111111111111',
157 //     grantType: 'password',
158 //     username: '',
159 //     password: '',
160 //     scope: ''
161 //   }
162 // })
314507 163
H 164 // 获取验证码
165 const getCode = async () => {
166   // 情况一,未开启:则直接登录
167   if (loginData.captchaEnable === 'false') {
8e4ab7 168     await handleLogin({})
314507 169   } else {
H 170     // 情况二,已开启:则展示验证码;只有完成验证码的情况,才进行登录
171     // 弹出验证码
172     verify.value.show()
173   }
174 }
175
176 // 记住我
177 const getLoginFormCache = () => {
178   const loginForm = authUtil.getLoginForm()
179   if (loginForm) {
180     loginData.loginForm = {
181       ...loginData.loginForm,
182       username: loginForm.username ? loginForm.username : loginData.loginForm.username,
183       password: loginForm.password ? loginForm.password : loginData.loginForm.password,
184       rememberMe: loginForm.rememberMe,
185     }
186   }
187 }
188
189 const loading = ref() // ElLoading.service 返回的实例
190 // 登录
8e4ab7 191 const handleLogin = async (params) => {
314507 192   loginLoading.value = true
H 193   try {
194     const data = await validForm()
195     if (!data) {
196       return
197     }
8e4ab7 198     loginData.loginForm.captchaVerification = params.captchaVerification
314507 199     const res = await LoginApi.login(loginData.loginForm)
H 200     if (!res) {
201       return
202     }
203     loading.value = ElLoading.service({
204       lock: true,
205       text: '正在加载系统中...',
206       background: 'rgba(0, 0, 0, 0.7)'
207     })
208     if (loginData.loginForm.rememberMe) {
209       authUtil.setLoginForm(loginData.loginForm)
210     } else {
211       authUtil.removeLoginForm()
212     }
213     authUtil.setToken(res)
214     if (!redirect.value) {
8e4ab7 215       redirect.value = '/index'
314507 216     }
H 217     // 判断是否为SSO登录
218     if (redirect.value.indexOf('sso') !== -1) {
219       window.location.href = window.location.href.replace('/login?redirect=', '')
220     } else {
221       push({ path: redirect.value })
222     }
223   } finally {
224     loginLoading.value = false
225     loading.value.close()
226   }
227 }
228
8e4ab7 229 // const ssoPasswordLogin = () => {
H 230 //   // 发起请求
231 //   axios({
232 //     url: "http://localhost:48080/admin-api/system/oauth2/token?"
233 //       // 客户端
234 //       + "client_id=" + oauth2Token.oauthParam.clientId
235 //       + "&client_secret=" + oauth2Token.oauthParam.clientSecret
236 //       // 密码模式的参数
237 //       + "&grant_type=" + oauth2Token.oauthParam.grantType
238 //       + "&username=" + loginData.loginForm.username
239 //       + "&password=" + loginData.loginForm.password
240 //       + '&scope=user.read user.write',
241 //     method: 'POST',
242 //     headers: {
243 //       'tenant-id': '172', // 多租户编号,写死
314507 244 //     }
8e4ab7 245 //   }).then((result) => {
H 246 //     const res = result.data
247 //     if (res.code !== 0) {
248 //       alert('授权失败,原因:' + res.msg)
249 //       return;
250 //     }
251 //     const auth_token = res.data.access_token
252 //     // 设置token
253 //     authUtil.setToken(res.data)
254 //     // 提示登录成功
255 //     alert('授权成功!校验系统用户及权限');
256 //     ssoLoginData.loginParam.token = auth_token
257 //     if (!!redirect.value) {
258 //       location.href = decodeURIComponent(redirect.value);
314507 259 //     } else {
8e4ab7 260 //       push({ path: '/index' })
314507 261 //     }
8e4ab7 262 //   }).catch((e) => {
H 263 //     ElMessage.error('授权失败:' + e.message);
264 //   });
265 // }
266
267 // const ssoCodeLogin = () => {
268 //   alert('暂未开通');
269 //   // const clientId = 'shasteel';
270 //   // const redirectUri = encodeURIComponent('http://127.0.0.1:9000/callback');
271 //   // const responseType = 'code'; // 1)授权码模式,对应 code;2)简化模式,对应 token
272 //   // window.location.href = 'http://localhost/sso?client_id=' + clientId
273 //   //   + '&redirect_uri=' + redirectUri
274 //   //   + '&response_type=' + responseType;
314507 275 // }
H 276
277 watch(
278   () => currentRoute.value,
279   (route: RouteLocationNormalizedLoaded) => {
280     redirect.value = route?.query?.redirect as string
281   },
282   {
283     immediate: true
284   }
285 )
286 onMounted(() => {
287   getLoginFormCache()
288 })
289 </script>
290
291 <style lang="scss" scoped>
292 :deep(.anticon) {
293   &:hover {
294     color: var(--el-color-primary) !important;
295   }
296 }
297
298 .login-code {
299   float: right;
300   width: 100%;
301   height: 38px;
302
303   img {
304     width: 100%;
305     height: auto;
306     max-width: 100px;
307     vertical-align: middle;
308     cursor: pointer;
309   }
310 }
311 </style>