From 944836c74817ebda3c2cfdf5ff658e93e0cd213d Mon Sep 17 00:00:00 2001 From: Xujiacheng Date: Mon, 19 Jan 2026 10:00:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E6=A8=A1=E6=80=81=E6=A1=86=E7=BB=84=E4=BB=B6=E5=B9=B6=E5=9C=A8?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E9=A1=B5=E9=9D=A2=E4=B8=AD=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=92=8C=E9=80=80=E5=87=BA=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/BbConfirmModal.vue | 154 ++++++++++++++++++ apps/extension/src/options/pages/MorePage.vue | 34 +++- apps/extension/src/options/pages/MyPage.vue | 33 +++- .../src/options/pages/PublicPage.vue | 39 ++++- apps/extension/src/popup/PopupApp.vue | 33 +++- apps/web/src/App.vue | 49 +++++- apps/web/src/pages/AdminPage.vue | 66 +++++++- apps/web/src/pages/MyPage.vue | 63 ++++++- apps/web/src/pages/PublicPage.vue | 23 ++- apps/web/src/style.css | 34 ++++ 10 files changed, 503 insertions(+), 25 deletions(-) create mode 100644 apps/extension/src/components/BbConfirmModal.vue diff --git a/apps/extension/src/components/BbConfirmModal.vue b/apps/extension/src/components/BbConfirmModal.vue new file mode 100644 index 0000000..82f9ac9 --- /dev/null +++ b/apps/extension/src/components/BbConfirmModal.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/apps/extension/src/options/pages/MorePage.vue b/apps/extension/src/options/pages/MorePage.vue index 3ca72d9..9533f48 100644 --- a/apps/extension/src/options/pages/MorePage.vue +++ b/apps/extension/src/options/pages/MorePage.vue @@ -2,6 +2,7 @@ import { computed, onMounted, ref } from "vue"; import { useRouter } from "vue-router"; import { getToken, setToken } from "../../lib/extStorage"; +import BbConfirmModal from "../../components/BbConfirmModal.vue"; const router = useRouter(); @@ -21,12 +22,30 @@ function openWeb() { else window.open(url, "_blank", "noopener,noreferrer"); } -async function logout() { +const logoutModalOpen = ref(false); +const logoutStep = ref(1); + +function startLogout() { + logoutStep.value = 1; + logoutModalOpen.value = true; +} + +async function confirmLogout() { + if (logoutStep.value === 1) { + logoutStep.value = 2; + return; + } await setToken(""); + logoutModalOpen.value = false; await refresh(); await router.replace("/login"); } +function cancelLogout() { + logoutModalOpen.value = false; + logoutStep.value = 1; +} + onMounted(refresh); @@ -38,9 +57,20 @@ onMounted(refresh);
- +

Web 地址来自环境变量:VITE_WEB_BASE_URL

+ + diff --git a/apps/extension/src/options/pages/MyPage.vue b/apps/extension/src/options/pages/MyPage.vue index 23a088f..e140efc 100644 --- a/apps/extension/src/options/pages/MyPage.vue +++ b/apps/extension/src/options/pages/MyPage.vue @@ -3,6 +3,7 @@ import { computed, onMounted, ref } from "vue"; import { apiFetch } from "../../lib/api"; import { getToken } from "../../lib/extStorage"; import { listLocalBookmarks, markLocalDeleted, upsertLocalBookmark } from "../../lib/localData"; +import BbConfirmModal from "../../components/BbConfirmModal.vue"; const token = ref(""); const loggedIn = computed(() => Boolean(token.value)); @@ -44,11 +45,30 @@ async function add() { async function remove(id) { if (mode.value !== "local") return; - if (!confirm("确定删除该书签?")) return; + pendingDeleteId.value = id; + deleteConfirmOpen.value = true; +} + +const deleteConfirmOpen = ref(false); +const pendingDeleteId = ref(""); + +async function confirmDelete() { + const id = pendingDeleteId.value; + if (!id) { + deleteConfirmOpen.value = false; + return; + } await markLocalDeleted(id); + pendingDeleteId.value = ""; + deleteConfirmOpen.value = false; await load(); } +function cancelDelete() { + pendingDeleteId.value = ""; + deleteConfirmOpen.value = false; +} + onMounted(load); @@ -74,6 +94,17 @@ onMounted(load);
{{ b.url }}
+ + diff --git a/apps/extension/src/options/pages/PublicPage.vue b/apps/extension/src/options/pages/PublicPage.vue index d9b20ab..fa8fcd3 100644 --- a/apps/extension/src/options/pages/PublicPage.vue +++ b/apps/extension/src/options/pages/PublicPage.vue @@ -1,5 +1,5 @@ @@ -26,8 +41,10 @@ onMounted(load);

公开书签

- - +
+ + +

{{ error }}

    @@ -41,7 +58,21 @@ onMounted(load); diff --git a/apps/web/src/pages/AdminPage.vue b/apps/web/src/pages/AdminPage.vue index 385c73c..a1ffe2f 100644 --- a/apps/web/src/pages/AdminPage.vue +++ b/apps/web/src/pages/AdminPage.vue @@ -1,6 +1,7 @@ @@ -583,10 +625,9 @@ onBeforeUnmount(() => {
    快速搜索
    - -
    - - +
    + +
    @@ -616,6 +657,14 @@ onBeforeUnmount(() => {
    + +
    {{ confirmMessage }}
    +
    + + +
    +
    +

    {{ error }}

    加载中…

    diff --git a/apps/web/src/pages/PublicPage.vue b/apps/web/src/pages/PublicPage.vue index a304db5..f755aeb 100644 --- a/apps/web/src/pages/PublicPage.vue +++ b/apps/web/src/pages/PublicPage.vue @@ -1,5 +1,5 @@ @@ -107,8 +122,10 @@ onMounted(loadFolders);
    - - +
    + + +

    {{ error }}

    diff --git a/apps/web/src/style.css b/apps/web/src/style.css index 3c6f739..092b5d1 100644 --- a/apps/web/src/style.css +++ b/apps/web/src/style.css @@ -120,6 +120,40 @@ input:focus-visible { color: var(--bb-text); } +.bb-searchWrap { + position: relative; + flex: 1; + min-width: 220px; +} + +.bb-input.bb-input--withClear { + padding-right: 44px; +} + +.bb-input.bb-input--sm.bb-input--withClear { + padding-right: 38px; +} + +.bb-searchClear { + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%); + width: 28px; + height: 28px; + border-radius: 999px; + border: 1px solid rgba(255,255,255,0.55); + background: rgba(255,255,255,0.65); + cursor: pointer; + display: grid; + place-items: center; + color: rgba(19, 78, 74, 0.75); +} + +.bb-searchClear:hover { + background: rgba(255,255,255,0.82); +} + /* Hide native file control (we use styled buttons) */ .bb-fileInput { position: absolute;