Copilot commented on code in PR #8088:
URL: https://github.com/apache/incubator-seata/pull/8088#discussion_r3181148070
##########
console/src/main/resources/static/console-fe/src/utils/request.ts:
##########
@@ -14,62 +14,103 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import axios, { AxiosInstance, AxiosResponse } from 'axios';
-import { Message } from '@alifd/next';
-import { get } from 'lodash';
-import { AUTHORIZATION_HEADER } from '@/contants';
-import { getCurrentLocaleObj } from '@/reducers/locale';
-
-const createRequest = (baseURL: string, generalErrorMessage: string = 'Request
error, please try again later!') => {
- const instance: AxiosInstance = axios.create({
+import axios, {
+ type AxiosError,
+ type AxiosInstance,
+ type AxiosResponse,
+ type InternalAxiosRequestConfig,
+} from 'axios'
+import { ElMessage } from 'element-plus'
+import 'element-plus/theme-chalk/el-message.css';
+import i18n from '@/i18n'
+import router from '@/router'
+import { useAppStore } from '@/stores/app'
+
+const AUTHORIZATION_HEADER = 'Authorization'
+const DEFAULT_GENERAL_ERROR_MESSAGE = 'Request error, please try again later!'
+
+type LocaleMessages = {
+ codeMessage?: Record<string, string>
+}
+
+type ResponseBody = {
+ code?: string | number
+ message?: string
+ errorMsg?: string
+}
+
+function getCurrentLocaleMessages(): LocaleMessages {
+ const locale = i18n.global.locale.value
+ return i18n.global.getLocaleMessage(locale) as LocaleMessages
+}
+
+function setAuthorizationHeader(config: InternalAxiosRequestConfig, token:
string | null) {
+ if (config.headers && typeof config.headers.set === 'function') {
+ config.headers.set(AUTHORIZATION_HEADER, token ?? '')
+ return
+ }
+
+ config.headers = {
+ ...config.headers,
+ [AUTHORIZATION_HEADER]: token,
+ }
+}
+
+const createRequest = (
+ baseURL: string,
+ generalErrorMessage: string = DEFAULT_GENERAL_ERROR_MESSAGE,
+): AxiosInstance => {
+ const instance = axios.create({
baseURL,
method: 'get',
- });
+ })
- instance.interceptors.request.use((config: any) => {
- let authHeader: string | null = localStorage.getItem(AUTHORIZATION_HEADER);
- // add jwt header
- if (config.headers) {
- config.headers[AUTHORIZATION_HEADER] = authHeader;
- }
- return config;
- });
+ instance.interceptors.request.use((config) => {
+ const appStore = useAppStore()
+ const authHeader = appStore.getToken()
+ setAuthorizationHeader(config, authHeader)
+ return config
+ })
instance.interceptors.response.use(
- (response: AxiosResponse): Promise<any> => {
- const code = get(response, 'data.code');
+ (response: AxiosResponse<ResponseBody>) => {
+ const code = response.data?.code
+
if (response.status === 200 && String(code) === '200') {
- return Promise.resolve(get(response, 'data'));
- } else {
- const currentLocale = getCurrentLocaleObj();
- const errorText =
- (currentLocale.codeMessage as any)[code] ||
- get(response, 'data.message') ||
- get(response, 'data.errorMsg') ||
- response.statusText;
- Message.error(errorText || `Request error ${code}: ${get(response,
'config.url', '')}`);
- return Promise.reject(response);
+ return Promise.resolve(response.data)
}
+
+ const currentLocale = getCurrentLocaleMessages()
+ const errorText =
+ currentLocale.codeMessage?.[String(code)] ||
+ response.data?.message ||
+ response.data?.errorMsg ||
+ response.statusText
+
+ ElMessage.error(errorText || `Request error ${code}:
${response.config.url ?? ''}`)
+ return Promise.reject(response)
},
- error => {
+ (error: AxiosError<ResponseBody>) => {
if (error.response) {
- const { status } = error.response;
+ const { status } = error.response
+
if (status === 403 || status === 401) {
- (window as any).globalHistory.replace('/login');
- return;
+ window.location.replace('/login')
+ return Promise.reject(error)
}
- Message.error(`HTTP ERROR: ${status}`);
+ ElMessage.error(`HTTP ERROR: ${status}`)
Review Comment:
On 401/403 the interceptor redirects to `/login` but keeps the stale
token/username in storage, which can cause repeated unauthorized requests after
navigation. Consider clearing auth state (e.g., via the app store) before
redirecting, and prefer `router.replace('/login')` to avoid a full page reload.
##########
console/src/main/resources/static/console-fe/src/utils/request.ts:
##########
@@ -14,62 +14,103 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import axios, { AxiosInstance, AxiosResponse } from 'axios';
-import { Message } from '@alifd/next';
-import { get } from 'lodash';
-import { AUTHORIZATION_HEADER } from '@/contants';
-import { getCurrentLocaleObj } from '@/reducers/locale';
-
-const createRequest = (baseURL: string, generalErrorMessage: string = 'Request
error, please try again later!') => {
- const instance: AxiosInstance = axios.create({
+import axios, {
+ type AxiosError,
+ type AxiosInstance,
+ type AxiosResponse,
+ type InternalAxiosRequestConfig,
+} from 'axios'
+import { ElMessage } from 'element-plus'
+import 'element-plus/theme-chalk/el-message.css';
+import i18n from '@/i18n'
+import router from '@/router'
+import { useAppStore } from '@/stores/app'
Review Comment:
`router` is imported but never used in this module. This will trip TS/ESLint
no-unused-vars in many setups; remove the unused import (or use it for
navigation on auth failures).
##########
console/src/main/resources/static/console-fe/src/views/LoginView.vue:
##########
@@ -0,0 +1,232 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<template>
+ <div class="login-page">
+ <div class="top-section">
+ <!-- Animated particles (positioned relative to the full area) -->
+ <div class="animation animation1" />
+ <div class="animation animation2" />
+ <div class="animation animation3" />
+ <div class="animation animation4" />
+ <div class="animation animation5" />
+
+ <!-- Content constraint container -->
+ <div class="login-content">
+ <!-- Left product area -->
+ <div class="product-area">
+ <img class="product-logo" src="@/assets/seata_logo_white.png"
alt="Seata Logo" />
+ <p class="product-desc">{{ t('login.description') }}</p>
+ </div>
+
+ <!-- Right login panel -->
+ <div class="login-panel">
+ <el-card :header="t('login.title')" shadow="always" class="login-card">
+ <el-alert
+ :title="t('login.warning')"
+ type="warning"
+ :closable="false"
+ show-icon
+ class="login-warning"
+ />
+
+ <el-form
+ ref="formRef"
+ :model="form"
+ :rules="rules"
+ :label-col="{ span: 8 }"
+ :wrapper-col="{ span: 16 }"
+ class="login-form"
Review Comment:
`el-form` from Element Plus does not support `label-col` / `wrapper-col`
props (these are Ant Design Vue props). Keeping them will have no effect and
may emit warnings; use Element Plus APIs such as `label-width`,
`label-position`, and layout components instead.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]