From d2937c97b8789055978d4d316e2c79776003ad8f Mon Sep 17 00:00:00 2001 From: AMagicPear Date: Sat, 7 Feb 2026 00:45:39 +0800 Subject: [PATCH 01/12] =?UTF-8?q?feat(scaffolding):=20=E6=B7=BB=E5=8A=A0Te?= =?UTF-8?q?rracotta=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86=E5=92=8C=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/lib.rs | 8 ++++++-- src-tauri/src/util/scaffolding.rs | 33 ++++++++++++++++++++++++++++++- src/views/Tools/LinkLobby.vue | 11 +++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 8f7edde..11d2d70 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -78,11 +78,15 @@ pub fn run() { util::server_query::server_query, util::skin::fetch_username_uuid, util::skin::fetch_uuid_profile, - // util::scaffolding::start_connection_from_code, - // util::scaffolding::collect_instance_info, core::api_client::fetch_with_modrinth, util::skin::fetch_skin_from_uuid_cached, util::skin::fetch_skin_from_url, + // scaffolding + util::scaffolding::get_terracotta_meta, + util::scaffolding::get_terracotta_state, + util::scaffolding::set_terracotta_waiting, + util::scaffolding::set_terracotta_host_scanning, + util::scaffolding::set_terracotta_guesting, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src-tauri/src/util/scaffolding.rs b/src-tauri/src/util/scaffolding.rs index 70f64ff..9c67b36 100644 --- a/src-tauri/src/util/scaffolding.rs +++ b/src-tauri/src/util/scaffolding.rs @@ -1,6 +1,37 @@ +use terracotta::controller; + +#[tauri::command] +pub fn get_terracotta_meta() -> serde_json::Value { + todo!() +} + +#[tauri::command] +pub fn get_terracotta_state() -> serde_json::Value { + controller::get_state() +} + +#[tauri::command] +pub fn set_terracotta_waiting() { + controller::set_waiting() +} + +#[tauri::command] +pub fn set_terracotta_host_scanning(player: String) { + controller::set_scanning(None, Some(player)); +} + +#[tauri::command] +pub fn set_terracotta_guesting(room_code: String, player: String) -> Result<(), String> { + let room = controller::Room::from(&room_code).ok_or("invalid room code")?; + if controller::set_guesting(room, Some(player)) { + Ok(()) + } else { + Err("set guesting failed".to_string()) + } +} + #[cfg(test)] mod tests { - use super::*; use terracotta::controller::*; #[test] diff --git a/src/views/Tools/LinkLobby.vue b/src/views/Tools/LinkLobby.vue index 39326eb..f9bdd24 100644 --- a/src/views/Tools/LinkLobby.vue +++ b/src/views/Tools/LinkLobby.vue @@ -31,6 +31,15 @@ const createLobby = async (port: number) => { }, }) } + +const test = async () => { + await invoke('set_terracotta_host_scanning', { player: 'PCL.Proto Anonymous Host' }) +} + +const getState = async () => { + let state = await invoke('get_terracotta_state') + console.info('[scaffolding] get state', state) +} -``` - -**Template Language:** - -- Use **Pug** for templates (`lang="pug"`) -- Use kebab-case for template attributes and events -- Use Vue directives (`v-if`, `v-for`, `v-model`) - -**State Management:** - -- Use **Pinia** stores for global state -- Use `ref` and `computed` for component state -- Store naming: `useStoreName()` pattern - -### Rust (Backend) - -**File Structure:** - -- Backend code in `src-tauri/src/` -- Core logic in `src-tauri/src/core/` -- Utilities in `src-tauri/src/util/` - -**Naming:** - -- **Modules**: snake_case (`api_client`, `game_launcher`) -- **Structs/Enums**: PascalCase (`GameInstance`, `GameJava`) -- **Functions**: snake_case (`from_version_folder`) -- **Variables**: snake_case (`version_folder`, `json_files`) - -**Error Handling:** - -- Use `thiserror` crate for custom error types -- Use `Result` for fallible operations -- Use `?` operator for error propagation - -**Imports:** - -- Group standard library imports first -- Then external crate imports -- Then internal module imports -- Example from `src-tauri/src/core/game.rs:1-6`: - - ```rust - use std::{fs, path::PathBuf, sync::Arc}; - - use crate::core::{ - api_client::game::VersionDetails, java::JavaRuntime, launcher::GameLaunchError, - mcmod::PluginType, repository::GameRepository, - }; - ``` - -## Project Structure - +## 代码风格要点 + +### TypeScript/Vue +- **导入**:使用 `@/` 别名,外部库在前 +- **命名**: + - 变量/函数:camelCase + - 类型/接口:PascalCase + - 组件文件:PascalCase(如 `Modal.vue`) + - Store命名:kebab-case(如 `account-info`) +- **格式化**:无分号、单引号、100字符行宽 +- **错误处理**:async操作必须用 try/catch +- **组件**:使用 ` diff --git a/src/views/Tools/LinkLobbyInner.vue b/src/views/Tools/LinkLobbyInner.vue index 7cb3764..1495630 100644 --- a/src/views/Tools/LinkLobbyInner.vue +++ b/src/views/Tools/LinkLobbyInner.vue @@ -4,16 +4,37 @@ import PCard from '@/components/widget/PCard.vue' import router from '@/router' import useTerracottaStore from '@/stores/terracotta' import { useRouteQuery } from '@vueuse/router' +import IconBtnConnectUserType from '@/assets/icons/IconBtnConnectUserType.svg' +import IconBtnConnectUserName from '@/assets/icons/IconBtnConnectUserName.svg' +import IconBtnFinishQuality from '@/assets/icons/BtnFinishQuality.svg' +import IconBtnFinishId from '@/assets/icons/BtnFinishId.svg' +import { onMounted, onUnmounted } from 'vue' +import sideTip from '@/composables/sideTip' +import { useI18n } from 'vue-i18n' const terracotta = useTerracottaStore() const roomCode = useRouteQuery('code') +const t = useI18n() const closeLobby = async () => { - if (!roomCode.value) return terracotta.setWaiting() router.back() console.info('[scaffolding] closed room code', roomCode.value) } + +const copyRoomCode = () => { + navigator.clipboard.writeText(roomCode.value as string) + sideTip.show('复制成功', 'success') +} + +onMounted(() => { + terracotta.update() + terracotta.startAutoUpdate() +}) + +onUnmounted(() => { + terracotta.stopAutoUpdate() +})