diff --git a/easytier-web/frontend-lib/package.json b/easytier-web/frontend-lib/package.json index 0455925..b502fbf 100644 --- a/easytier-web/frontend-lib/package.json +++ b/easytier-web/frontend-lib/package.json @@ -25,11 +25,9 @@ "floating-vue": "^5.2", "ip-num": "1.5.1", "primeicons": "^7.0.0", - "primevue": "^4.3.9", "tailwindcss-primeui": "^0.3.4", "ts-md5": "^1.3.1", "uuid": "^11.0.2", - "vue": "^3.5.12", "vue-chartjs": "^5.3.2", "vue-i18n": "^10.0.4" }, @@ -46,5 +44,9 @@ "vite": "^5.4.10", "vite-plugin-dts": "^4.3.0", "vue-tsc": "^2.1.10" + }, + "peerDependencies": { + "vue": "^3.5.12", + "primevue": "^4.3.9" } } \ No newline at end of file diff --git a/easytier-web/frontend-lib/src/components/RemoteManagement.vue b/easytier-web/frontend-lib/src/components/RemoteManagement.vue new file mode 100644 index 0000000..3a71d27 --- /dev/null +++ b/easytier-web/frontend-lib/src/components/RemoteManagement.vue @@ -0,0 +1,595 @@ + + + + + + + + + + + + + + + + {{ + t('web.device_management.network') }} + + + + + + + + + + + + + + + + + + + + + + + + {{ isEditing ? t('web.device_management.edit_network') : + t('web.device_management.create_network') }} + + + + + + + + + + + + + + + + + {{ t('web.device_management.network_status') }} + + + + + + + + + + + + + + {{ t('web.device_management.network_configuration') }} + + + + + + + + {{ t('web.device_management.loading_network_configuration') }} + + + + + + + + {{ t('web.device_management.no_network_selected') }} + + + {{ t('web.device_management.select_existing_network_or_create_new') }} + + + + + + + + + + + + + \ No newline at end of file diff --git a/easytier-web/frontend-lib/src/components/index.ts b/easytier-web/frontend-lib/src/components/index.ts index 9d26d14..a1ddfab 100644 --- a/easytier-web/frontend-lib/src/components/index.ts +++ b/easytier-web/frontend-lib/src/components/index.ts @@ -1,3 +1,4 @@ export { default as Config } from './Config.vue'; export { default as Status } from './Status.vue'; export { default as ConfigEditDialog } from './ConfigEditDialog.vue'; +export { default as RemoteManagement } from './RemoteManagement.vue'; \ No newline at end of file diff --git a/easytier-web/frontend-lib/src/easytier-frontend-lib.ts b/easytier-web/frontend-lib/src/easytier-frontend-lib.ts index d5a7b73..a47503f 100644 --- a/easytier-web/frontend-lib/src/easytier-frontend-lib.ts +++ b/easytier-web/frontend-lib/src/easytier-frontend-lib.ts @@ -1,7 +1,7 @@ import './style.css' import type { App } from 'vue'; -import { Config, Status, ConfigEditDialog } from "./components"; +import { Config, Status, ConfigEditDialog, RemoteManagement } from "./components"; import Aura from '@primeuix/themes/aura'; import PrimeVue from 'primevue/config' @@ -44,8 +44,9 @@ export default { app.component('ConfigEditDialog', ConfigEditDialog); app.component('Status', Status); app.component('HumanEvent', HumanEvent); + app.component('RemoteManagement', RemoteManagement); app.directive('tooltip', vTooltip as any); } }; -export { Config, ConfigEditDialog, Status, I18nUtils, NetworkTypes, Api, Utils }; +export { Config, ConfigEditDialog, RemoteManagement, Status, I18nUtils, NetworkTypes, Api, Utils }; diff --git a/easytier-web/frontend-lib/src/modules/api.ts b/easytier-web/frontend-lib/src/modules/api.ts index 5a0a1fb..b8a5dcf 100644 --- a/easytier-web/frontend-lib/src/modules/api.ts +++ b/easytier-web/frontend-lib/src/modules/api.ts @@ -1,5 +1,3 @@ -import axios, { AxiosError, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from 'axios'; -import { Md5 } from 'ts-md5' import { UUID } from './utils'; import { NetworkConfig } from '../types/network'; @@ -7,235 +5,29 @@ export interface ValidateConfigResponse { toml_config: string; } -// 定义接口返回的数据结构 -export interface LoginResponse { - success: boolean; - message: string; -} - -export interface RegisterResponse { - success: boolean; - message: string; -} - -// 定义请求体数据结构 -export interface Credential { - username: string; - password: string; -} - -export interface RegisterData { - credentials: Credential; - captcha: string; -} - -export interface Summary { - device_count: number; -} - export interface ListNetworkInstanceIdResponse { running_inst_ids: Array, disabled_inst_ids: Array, } -export interface GenerateConfigRequest { - config: NetworkConfig; -} - export interface GenerateConfigResponse { toml_config?: string; error?: string; } -export interface ParseConfigRequest { - toml_config: string; -} - export interface ParseConfigResponse { config?: NetworkConfig; error?: string; } -export class ApiClient { - private client: AxiosInstance; - private authFailedCb: Function | undefined; - - constructor(baseUrl: string, authFailedCb: Function | undefined = undefined) { - this.client = axios.create({ - baseURL: baseUrl + '/api/v1', - withCredentials: true, // 如果需要支持跨域携带cookie - headers: { - 'Content-Type': 'application/json', - }, - }); - this.authFailedCb = authFailedCb; - - // 添加请求拦截器 - this.client.interceptors.request.use((config: InternalAxiosRequestConfig) => { - return config; - }, (error: any) => { - return Promise.reject(error); - }); - - // 添加响应拦截器 - this.client.interceptors.response.use((response: AxiosResponse) => { - console.debug('Axios Response:', response); - return response.data; // 假设服务器返回的数据都在data属性中 - }, (error: any) => { - if (error.response) { - let response: AxiosResponse = error.response; - if (response.status == 401 && this.authFailedCb) { - console.error('Unauthorized:', response.data); - this.authFailedCb(); - } else { - // 请求已发出,但是服务器响应的状态码不在2xx范围 - console.error('Response Error:', error.response.data); - } - } else if (error.request) { - // 请求已发出,但是没有收到响应 - console.error('Request Error:', error.request); - } else { - // 发生了一些问题导致请求未发出 - console.error('Error:', error.message); - } - return Promise.reject(error); - }); - } - - // 注册 - public async register(data: RegisterData): Promise { - try { - data.credentials.password = Md5.hashStr(data.credentials.password); - const response = await this.client.post('/auth/register', data); - console.log("register response:", response); - return { success: true, message: 'Register success', }; - } catch (error) { - if (error instanceof AxiosError) { - return { success: false, message: 'Failed to register, error: ' + JSON.stringify(error.response?.data), }; - } - return { success: false, message: 'Unknown error, error: ' + error, }; - } - } - - // 登录 - public async login(data: Credential): Promise { - try { - data.password = Md5.hashStr(data.password); - const response = await this.client.post('/auth/login', data); - console.log("login response:", response); - return { success: true, message: 'Login success', }; - } catch (error) { - if (error instanceof AxiosError) { - if (error.response?.status === 401) { - return { success: false, message: 'Invalid username or password', }; - } else { - return { success: false, message: 'Unknown error, status code: ' + error.response?.status, }; - } - } - return { success: false, message: 'Unknown error, error: ' + error, }; - } - } - - public async logout() { - await this.client.get('/auth/logout'); - if (this.authFailedCb) { - this.authFailedCb(); - } - } - - public async change_password(new_password: string) { - await this.client.put('/auth/password', { new_password: Md5.hashStr(new_password) }); - } - - public async check_login_status() { - try { - await this.client.get('/auth/check_login_status'); - return true; - } catch (error) { - return false; - } - } - - public async list_session() { - const response = await this.client.get('/sessions'); - return response; - } - - public async list_machines(): Promise> { - const response = await this.client.get>>('/machines'); - return response.machines; - } - - public async list_deivce_instance_ids(machine_id: string): Promise { - const response = await this.client.get('/machines/' + machine_id + '/networks'); - return response; - } - - public async update_device_instance_state(machine_id: string, inst_id: string, disabled: boolean): Promise { - await this.client.put('/machines/' + machine_id + '/networks/' + inst_id, { - disabled: disabled, - }); - } - - public async get_network_info(machine_id: string, inst_id: string): Promise { - const response = await this.client.get>('/machines/' + machine_id + '/networks/info/' + inst_id); - return response.info.map; - } - - public async get_network_config(machine_id: string, inst_id: string): Promise { - const response = await this.client.get>('/machines/' + machine_id + '/networks/config/' + inst_id); - return response; - } - - public async validate_config(machine_id: string, config: any): Promise { - const response = await this.client.post(`/machines/${machine_id}/validate-config`, { - config: config, - }); - return response; - } - - public async run_network(machine_id: string, config: any): Promise { - await this.client.post(`/machines/${machine_id}/networks`, { - config: config, - }); - } - - public async delete_network(machine_id: string, inst_id: string): Promise { - await this.client.delete(`/machines/${machine_id}/networks/${inst_id}`); - } - - public async get_summary(): Promise { - const response = await this.client.get('/summary'); - return response; - } - - public captcha_url() { - return this.client.defaults.baseURL + '/auth/captcha'; - } - - public async generate_config(config: GenerateConfigRequest): Promise { - try { - const response = await this.client.post('/generate-config', config); - return response; - } catch (error) { - if (error instanceof AxiosError) { - return { error: error.response?.data }; - } - return { error: 'Unknown error: ' + error }; - } - } - - public async parse_config(config: ParseConfigRequest): Promise { - try { - const response = await this.client.post('/parse-config', config); - return response; - } catch (error) { - if (error instanceof AxiosError) { - return { error: error.response?.data }; - } - return { error: 'Unknown error: ' + error }; - } - } -} - -export default ApiClient; \ No newline at end of file +export interface RemoteClient { + validate_config(config: any): Promise; + run_network(config: any): Promise; + get_network_info(inst_id: string): Promise; + list_network_instance_ids(): Promise; + delete_network(inst_id: string): Promise; + update_network_instance_state(inst_id: string, disabled: boolean): Promise; + get_network_config(inst_id: string): Promise; + generate_config(config: NetworkConfig): Promise; + parse_config(toml_config: string): Promise; +} \ No newline at end of file diff --git a/easytier-web/frontend-lib/vite.config.ts b/easytier-web/frontend-lib/vite.config.ts index 9fbcd47..1b19c6c 100644 --- a/easytier-web/frontend-lib/vite.config.ts +++ b/easytier-web/frontend-lib/vite.config.ts @@ -24,12 +24,13 @@ export default defineConfig({ }, // make sure to externalize deps that shouldn't be bundled // into your library - external: ['vue'], + external: ['vue', 'primevue'], output: { // Provide global variables to use in the UMD build // for externalized deps globals: { vue: 'Vue', + primevue: 'primevue', }, exports: "named" }, diff --git a/easytier-web/frontend/package.json b/easytier-web/frontend/package.json index 1d5fba5..af3ff66 100644 --- a/easytier-web/frontend/package.json +++ b/easytier-web/frontend/package.json @@ -15,6 +15,7 @@ "easytier-frontend-lib": "workspace:*", "primevue": "^4.3.9", "tailwindcss-primeui": "^0.3.4", + "ts-md5": "^1.3.1", "vue": "^3.5.12", "vue-i18n": "^9.9.1", "vue-router": "4" diff --git a/easytier-web/frontend/src/components/ChangePassword.vue b/easytier-web/frontend/src/components/ChangePassword.vue index 8b66011..c90a16e 100644 --- a/easytier-web/frontend/src/components/ChangePassword.vue +++ b/easytier-web/frontend/src/components/ChangePassword.vue @@ -1,11 +1,11 @@ - - - - - - - - - - - - {{ - t('web.device_management.network') }} - - - - - - - - - - - - - - - - - - - - - - - - {{ isEditing ? t('web.device_management.edit_network') : - t('web.device_management.create_network') }} - - - - - - - - - - - - - - - - - {{ t('web.device_management.network_status') }} - - - - - - - - - - - - - - {{ t('web.device_management.network_configuration') }} - - - - - - - - {{ t('web.device_management.loading_network_configuration') }} - - - - - - - - {{ t('web.device_management.no_network_selected') }} - - - {{ t('web.device_management.select_existing_network_or_create_new') }} - - - - - - - - - - +
+ {{ t('web.device_management.select_existing_network_or_create_new') }} +
- {{ t('web.device_management.select_existing_network_or_create_new') }} -