From 4aaa7766618d4a7e215a815a888d6d365387b457 Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Fri, 15 Sep 2023 17:46:13 +0800 Subject: [PATCH] feat: add data tracker for app detail modal (#25) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 访问应用详情时支持发送浏览数据到 Halo 应用市场服务端。 TODO: - [x] 添加隐私政策说明 /kind feature ```release-note 支持浏览数据统计,添加服务条款和隐私政策。 ``` --- console/.eslintrc.cjs | 1 + console/env.d.ts | 12 ++ console/package.json | 1 + console/pnpm-lock.yaml | 170 +++++++++++++++++ console/src/components/AgreementsModal.vue | 107 +++++++++++ console/src/components/AppDetailModal.vue | 37 +++- console/src/components/AppStoreTab.vue | 195 ++++++++++---------- console/src/composables/use-configmap.ts | 43 +++++ console/src/constant/index.ts | 3 + console/src/index.ts | 12 ++ console/src/types/index.ts | 2 +- console/src/views/AppStore.vue | 4 + console/src/views/PrivacyPolicy.md | 51 +++++ console/src/views/PrivacyPolicy.vue | 21 +++ console/tailwind.config.js | 2 +- console/vite.config.ts | 3 +- src/main/resources/extensions/settings.yaml | 37 ++++ src/main/resources/plugin.yaml | 2 + 18 files changed, 601 insertions(+), 102 deletions(-) create mode 100644 console/src/components/AgreementsModal.vue create mode 100644 console/src/composables/use-configmap.ts create mode 100644 console/src/views/PrivacyPolicy.md create mode 100644 console/src/views/PrivacyPolicy.vue create mode 100644 src/main/resources/extensions/settings.yaml diff --git a/console/.eslintrc.cjs b/console/.eslintrc.cjs index 85045fc..adbf025 100644 --- a/console/.eslintrc.cjs +++ b/console/.eslintrc.cjs @@ -14,5 +14,6 @@ module.exports = { }, rules: { "vue/no-v-html": "off", + "@typescript-eslint/ban-ts-comment": "off", }, }; diff --git a/console/env.d.ts b/console/env.d.ts index 9b09646..ef7a69a 100644 --- a/console/env.d.ts +++ b/console/env.d.ts @@ -9,3 +9,15 @@ declare module "axios" { mute?: boolean; } } + +declare module "*.vue" { + import type { ComponentOptions } from "vue"; + const Component: ComponentOptions; + export default Component; +} + +declare module "*.md" { + import type { ComponentOptions } from "vue"; + const Component: ComponentOptions; + export default Component; +} diff --git a/console/package.json b/console/package.json index f52c0f2..48a2719 100644 --- a/console/package.json +++ b/console/package.json @@ -47,6 +47,7 @@ "tailwindcss": "^3.3.3", "typescript": "~5.0.4", "unplugin-icons": "^0.15.3", + "unplugin-vue-markdown": "^0.24.3", "vite": "^4.4.9", "vitest": "^0.24.5", "vue-tsc": "^1.8.8" diff --git a/console/pnpm-lock.yaml b/console/pnpm-lock.yaml index 8ffe8ef..248cd7c 100644 --- a/console/pnpm-lock.yaml +++ b/console/pnpm-lock.yaml @@ -118,6 +118,9 @@ devDependencies: unplugin-icons: specifier: ^0.15.3 version: 0.15.3 + unplugin-vue-markdown: + specifier: ^0.24.3 + version: 0.24.3(vite@4.4.9) vite: specifier: ^4.4.9 version: 4.4.9(@types/node@18.17.14)(sass@1.66.1) @@ -595,6 +598,26 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /@mdit-vue/plugin-component@0.12.1: + resolution: {integrity: sha512-L3elbvuKUufXwPLHrmJGd/ijd/QKxfcHXy3kRy4O+P7UIV7HSWePpfB0k+wWee+by3MviYYxjVAi392z+DGy3Q==} + dependencies: + '@types/markdown-it': 13.0.1 + markdown-it: 13.0.1 + dev: true + + /@mdit-vue/plugin-frontmatter@0.12.1: + resolution: {integrity: sha512-C6ycNjrJ+T4JgbVxwo9cUkfLacOO841Yl8ogqd5PJmAVpc5cM2OLBkqqkZxNRXos3g9xM1VvIQ7gK/047UNADg==} + dependencies: + '@mdit-vue/types': 0.12.0 + '@types/markdown-it': 13.0.1 + gray-matter: 4.0.3 + markdown-it: 13.0.1 + dev: true + + /@mdit-vue/types@0.12.0: + resolution: {integrity: sha512-mrC4y8n88BYvgcgzq9bvTlDgFyi2zuvzmPilRvRc3Uz1iIvq8mDhxJ0rHKFUNzPEScpDvJdIujqiDrulMqiudA==} + dev: true + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -620,6 +643,20 @@ packages: resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} dev: true + /@rollup/pluginutils@5.0.4: + resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.1 + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + /@rushstack/eslint-patch@1.3.3: resolution: {integrity: sha512-0xd7qez0AQ+MbHatZTlI1gu5vkG8r7MYRUJAHPAHJBmGLs16zpkrpAVLvjQKQOqaXPDUBwOiJzNc00znHSCVBw==} dev: true @@ -678,6 +715,10 @@ packages: resolution: {integrity: sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==} dev: true + /@types/estree@1.0.1: + resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} + dev: true + /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: @@ -690,6 +731,21 @@ packages: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} dev: true + /@types/linkify-it@3.0.3: + resolution: {integrity: sha512-pTjcqY9E4nOI55Wgpz7eiI8+LzdYnw3qxXCfHyBDdPbYvbyLgWLJGh8EdPvqawwMK1Uo1794AUkkR38Fr0g+2g==} + dev: true + + /@types/markdown-it@13.0.1: + resolution: {integrity: sha512-SUEb8Frsxs3D5Gg9xek6i6EG6XQ5s+O+ZdQzIPESZVZw3Pv3CPQfjCJBI+RgqZd1IBeu18S0Rn600qpPnEK37w==} + dependencies: + '@types/linkify-it': 3.0.3 + '@types/mdurl': 1.0.2 + dev: true + + /@types/mdurl@1.0.2: + resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} + dev: true + /@types/node@18.17.14: resolution: {integrity: sha512-ZE/5aB73CyGqgQULkLG87N9GnyGe5TcQjv34pwS8tfBs1IkCh0ASM69mydb2znqd6v0eX+9Ytvk6oQRqu8T1Vw==} dev: true @@ -1159,6 +1215,12 @@ packages: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} dev: true + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true @@ -1510,6 +1572,11 @@ packages: resolution: {integrity: sha512-4LODxAzKGVy7CJyhhN5mebwe7U2L29P+0G+HUriHnabm0d7LSff8Yn7t+Wq+2/9ze2Fu1dhX7mww090xfv7qXQ==} dev: true + /entities@3.0.1: + resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} + engines: {node: '>=0.12'} + dev: true + /entities@4.4.0: resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} engines: {node: '>=0.12'} @@ -2029,6 +2096,13 @@ packages: strip-final-newline: 2.0.0 dev: true + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: true + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -2278,6 +2352,16 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /gray-matter@4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + dependencies: + js-yaml: 3.14.1 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + dev: true + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true @@ -2459,6 +2543,11 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: true + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2556,6 +2645,14 @@ packages: nopt: 6.0.0 dev: true + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + /js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -2617,6 +2714,11 @@ packages: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + /kolorist@1.7.0: resolution: {integrity: sha512-ymToLHqL02udwVdbkowNpzjFd6UzozMtshPQKVi5k1EjKRqKqBrOnE9QbLEb0/pV76SAiIT13hdL8R6suc+f3g==} dev: true @@ -2650,6 +2752,12 @@ packages: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true + /linkify-it@4.0.1: + resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==} + dependencies: + uc.micro: 1.0.6 + dev: true + /load-json-file@4.0.0: resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} engines: {node: '>=4'} @@ -2703,6 +2811,21 @@ packages: dependencies: '@jridgewell/sourcemap-codec': 1.4.13 + /markdown-it@13.0.1: + resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==} + hasBin: true + dependencies: + argparse: 2.0.1 + entities: 3.0.1 + linkify-it: 4.0.1 + mdurl: 1.0.1 + uc.micro: 1.0.6 + dev: true + + /mdurl@1.0.1: + resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} + dev: true + /memorystream@0.3.1: resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} engines: {node: '>= 0.10.0'} @@ -3290,6 +3413,14 @@ packages: xmlchars: 2.2.0 dev: true + /section-matter@1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + dev: true + /semver@5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true @@ -3377,6 +3508,10 @@ packages: resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==} dev: true + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + /string.prototype.padend@3.1.3: resolution: {integrity: sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==} engines: {node: '>= 0.4'} @@ -3409,6 +3544,11 @@ packages: ansi-regex: 5.0.1 dev: true + /strip-bom-string@1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + dev: true + /strip-bom@3.0.0: resolution: {integrity: sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=} engines: {node: '>=4'} @@ -3604,6 +3744,10 @@ packages: hasBin: true dev: true + /uc.micro@1.0.6: + resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} + dev: true + /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: @@ -3646,6 +3790,23 @@ packages: - supports-color dev: true + /unplugin-vue-markdown@0.24.3(vite@4.4.9): + resolution: {integrity: sha512-v9fNupSfGnQTYrzpDO51DTppR6IsR/ufNdKycBe7HK0nApuXYiLzo5i5ejG63NSnMauTDFZB1kYOlUjJZ5auvQ==} + peerDependencies: + vite: ^2.0.0 || ^3.0.0-0 || ^4.0.0 + dependencies: + '@mdit-vue/plugin-component': 0.12.1 + '@mdit-vue/plugin-frontmatter': 0.12.1 + '@mdit-vue/types': 0.12.0 + '@rollup/pluginutils': 5.0.4 + '@types/markdown-it': 13.0.1 + markdown-it: 13.0.1 + unplugin: 1.4.0 + vite: 4.4.9(@types/node@18.17.14)(sass@1.66.1) + transitivePeerDependencies: + - rollup + dev: true + /unplugin@1.0.1: resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==} dependencies: @@ -3655,6 +3816,15 @@ packages: webpack-virtual-modules: 0.5.0 dev: true + /unplugin@1.4.0: + resolution: {integrity: sha512-5x4eIEL6WgbzqGtF9UV8VEC/ehKptPXDS6L2b0mv4FRMkJxRtjaJfOWDd6a8+kYbqsjklix7yWP0N3SUepjXcg==} + dependencies: + acorn: 8.10.0 + chokidar: 3.5.3 + webpack-sources: 3.2.3 + webpack-virtual-modules: 0.5.0 + dev: true + /update-browserslist-db@1.0.11(browserslist@4.21.10): resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} hasBin: true diff --git a/console/src/components/AgreementsModal.vue b/console/src/components/AgreementsModal.vue new file mode 100644 index 0000000..2d5b152 --- /dev/null +++ b/console/src/components/AgreementsModal.vue @@ -0,0 +1,107 @@ + + + diff --git a/console/src/components/AppDetailModal.vue b/console/src/components/AppDetailModal.vue index ba60ece..5a782a6 100644 --- a/console/src/components/AppDetailModal.vue +++ b/console/src/components/AppDetailModal.vue @@ -1,11 +1,11 @@
-
+
diff --git a/console/src/components/AppStoreTab.vue b/console/src/components/AppStoreTab.vue index 1bcc03b..2d5c98f 100644 --- a/console/src/components/AppStoreTab.vue +++ b/console/src/components/AppStoreTab.vue @@ -21,6 +21,7 @@ import type { ApplicationSearchResult, ListResponse } from "@/types"; import storeApiClient from "@/utils/store-api-client"; import { useElementVisibility } from "@vueuse/core"; import { computed } from "vue"; +import AgreementsModal from "./AgreementsModal.vue"; const props = withDefaults( defineProps<{ @@ -129,106 +130,108 @@ watch([selectedPriceMode, selectedSort, keyword], () => { diff --git a/console/src/composables/use-configmap.ts b/console/src/composables/use-configmap.ts new file mode 100644 index 0000000..672d385 --- /dev/null +++ b/console/src/composables/use-configmap.ts @@ -0,0 +1,43 @@ +import { PLUGIN_NAME } from "@/constant"; +import { apiClient } from "@/utils/api-client"; +import type { ConfigMap } from "@halo-dev/api-client"; +import { useQuery } from "@tanstack/vue-query"; +import { computed } from "vue"; + +interface AppStoreConfigMapData { + agreements?: { + privacyPolicy?: boolean; + termsOfService?: boolean; + }; +} + +export function useConfigMap() { + const { data: configMap } = useQuery({ + queryKey: [`${PLUGIN_NAME}-configMap`], + queryFn: async () => { + const { data } = await apiClient.plugin.fetchPluginConfig( + { + name: PLUGIN_NAME, + }, + { mute: true } + ); + return data; + }, + cacheTime: 0, + }); + + const configMapData = computed(() => { + return JSON.parse(JSON.stringify(configMap.value?.data) || "{}", (key, value) => { + if (typeof value === "string") { + try { + return JSON.parse(value); + } catch (error) { + return value; + } + } + return value; + }) as AppStoreConfigMapData; + }); + + return { configMap, configMapData }; +} diff --git a/console/src/constant/index.ts b/console/src/constant/index.ts index 9782d6a..54be03c 100644 --- a/console/src/constant/index.ts +++ b/console/src/constant/index.ts @@ -5,3 +5,6 @@ export enum AppType { PLUGIN = "PLUGIN", THEME = "THEME", } + +export const PLUGIN_NAME = "app-store-integration"; +export const CONFIG_MAP_NAME = "plugin-app-store-integration-configmap"; diff --git a/console/src/index.ts b/console/src/index.ts index b4548ac..ab09427 100644 --- a/console/src/index.ts +++ b/console/src/index.ts @@ -6,6 +6,7 @@ import "github-markdown-css/github-markdown-light.css"; import "./styles/index.scss"; import RiApps2Line from "~icons/ri/apps-2-line"; import AppStore from "./views/AppStore.vue"; +import PrivacyPolicy from "./views/PrivacyPolicy.vue"; import type { Plugin, Theme } from "@halo-dev/api-client"; import PluginVersionCheckField from "./components/entity-fields/PluginVersionCheckField.vue"; import ThemeVersionCheckOperationItem from "./components/operation-items/ThemeVersionCheckOperationItem.vue"; @@ -34,6 +35,17 @@ export default definePlugin({ }, }, }, + { + parentName: "Root", + route: { + path: "/app-store/privacy-policy", + name: "PrivacyPolicy", + component: PrivacyPolicy, + meta: { + title: "Halo 应用市场隐私政策", + }, + }, + }, ], extensionPoints: { "plugin:installation:tabs:create": () => { diff --git a/console/src/types/index.ts b/console/src/types/index.ts index b55f47d..acabae9 100644 --- a/console/src/types/index.ts +++ b/console/src/types/index.ts @@ -1,4 +1,4 @@ -import type { Content, Metadata } from "@halo-dev/api-client"; +import type { Metadata } from "@halo-dev/api-client"; export interface Application { apiVersion: string; diff --git a/console/src/views/AppStore.vue b/console/src/views/AppStore.vue index 38a326b..e05f860 100644 --- a/console/src/views/AppStore.vue +++ b/console/src/views/AppStore.vue @@ -1,4 +1,5 @@ + diff --git a/console/tailwind.config.js b/console/tailwind.config.js index d1f4719..e2cad9a 100644 --- a/console/tailwind.config.js +++ b/console/tailwind.config.js @@ -1,6 +1,6 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"], + content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}", "../src/main/resources/extensions/settings.yaml"], prefix: "as-", theme: { extend: {}, diff --git a/console/vite.config.ts b/console/vite.config.ts index 5c37443..2bbb6bb 100644 --- a/console/vite.config.ts +++ b/console/vite.config.ts @@ -3,6 +3,7 @@ import { fileURLToPath, URL } from "url"; import { defineConfig } from "vite"; import Vue from "@vitejs/plugin-vue"; import Icons from "unplugin-icons/vite"; +import Markdown from "unplugin-vue-markdown/vite"; const pluginEntryName = "app-store-integration"; @@ -11,7 +12,7 @@ export default ({ mode }: { mode: string }) => { const outDir = isProduction ? "../src/main/resources/console" : "../build/resources/main/console"; return defineConfig({ - plugins: [Vue(), Icons({ compiler: "vue3" })], + plugins: [Vue({ include: [/\.vue$/, /\.md$/] }), Icons({ compiler: "vue3" }), Markdown()], resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)), diff --git a/src/main/resources/extensions/settings.yaml b/src/main/resources/extensions/settings.yaml new file mode 100644 index 0000000..337acbd --- /dev/null +++ b/src/main/resources/extensions/settings.yaml @@ -0,0 +1,37 @@ +apiVersion: v1alpha1 +kind: Setting +metadata: + name: plugin-app-store-integration-setting +spec: + forms: + - group: agreements + label: 条款与协议 + formSchema: + - $el: ul + attrs: + class: "formkit-outer as-space-y-1 as-text-sm as-text-gray-600 formkit-disabled:opacity-50 py-4 first:pt-0 last:pb-0 transition-all as-list-decimal as-list-inside" + children: + - $el: li + children: + - $el: a + attrs: + href: https://halo.run/terms-of-service + target: _blank + class: "as-text-indigo-600" + children: "《Halo 应用市场服务条款》" + - $el: li + children: + - $el: a + attrs: + href: /console/app-store/privacy-policy + target: _blank + class: "as-text-indigo-600" + children: "《隐私政策》" + - $formkit: checkbox + label: 我已阅读并同意:《Halo 应用市场服务条款》 + name: termsOfService + value: false + - $formkit: checkbox + label: 我已阅读并同意:《隐私政策》 + name: privacyPolicy + value: false diff --git a/src/main/resources/plugin.yaml b/src/main/resources/plugin.yaml index 8c49de7..4d2e8da 100644 --- a/src/main/resources/plugin.yaml +++ b/src/main/resources/plugin.yaml @@ -14,6 +14,8 @@ spec: homepage: https://github.com/halo-dev/plugin-app-store displayName: "应用市场" description: "Console 集成 Halo 官方应用市场" + settingName: plugin-app-store-integration-setting + configMapName: plugin-app-store-integration-configmap license: - name: "GPL-3.0" url: "https://github.com/halo-dev/plugin-app-store/blob/main/LICENSE"