mirror of
https://github.com/gkd-kit/docs.git
synced 2024-11-16 13:52:19 +08:00
feat: ApkTable
This commit is contained in:
parent
4e78aeff39
commit
06cc806834
|
@ -1,84 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed, onMounted, shallowRef } from 'vue';
|
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
beta?: boolean;
|
|
||||||
}>(),
|
|
||||||
{},
|
|
||||||
);
|
|
||||||
|
|
||||||
const apkUrl = shallowRef('');
|
|
||||||
const apkName = computed(() =>
|
|
||||||
(apkUrl.value.split('/').at(-1) || '').replace('.wasm', '.apk'),
|
|
||||||
);
|
|
||||||
|
|
||||||
const loading = shallowRef(false);
|
|
||||||
const downloadApk = async () => {
|
|
||||||
if (!apkUrl.value || loading.value) return;
|
|
||||||
loading.value = true;
|
|
||||||
try {
|
|
||||||
const file = await fetch(apkUrl.value)
|
|
||||||
.then((r) => r.arrayBuffer())
|
|
||||||
.then(
|
|
||||||
(b) =>
|
|
||||||
new File([b], apkName.value, {
|
|
||||||
type: 'application/vnd.android.package-archive',
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
const { saveAs } = await import('file-saver');
|
|
||||||
saveAs(file, apkName.value);
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// preload file-saver in browser
|
|
||||||
if (globalThis.document) {
|
|
||||||
import('file-saver');
|
|
||||||
}
|
|
||||||
|
|
||||||
const pkg = computed(() => (props.beta ? 'app-beta' : 'app'));
|
|
||||||
const key = computed(() => `apkUrl-${pkg.value}`);
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
apkUrl.value = localStorage.getItem(key.value) || '';
|
|
||||||
const versionUrl = `https://registry.npmmirror.com/@gkd-kit/${pkg.value}/latest/files`;
|
|
||||||
const r = await fetch(versionUrl);
|
|
||||||
const data = await r.json();
|
|
||||||
apkUrl.value = new URL(data.downloadUrl, r.url).href;
|
|
||||||
localStorage.setItem(key.value, apkUrl.value);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div inline-flex items-center gap-10px>
|
|
||||||
<a
|
|
||||||
:class="{
|
|
||||||
'cursor-progress': loading,
|
|
||||||
'opacity-50': loading,
|
|
||||||
'cursor-pointer': !loading,
|
|
||||||
}"
|
|
||||||
@click="downloadApk"
|
|
||||||
>
|
|
||||||
{{ apkName }}
|
|
||||||
</a>
|
|
||||||
<svg v-if="loading" animate-spin size-16px viewBox="0 0 16 16" fill="none">
|
|
||||||
<circle
|
|
||||||
cx="8"
|
|
||||||
cy="8"
|
|
||||||
r="7"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-opacity="0.25"
|
|
||||||
stroke-width="2"
|
|
||||||
vector-effect="non-scaling-stroke"
|
|
||||||
></circle>
|
|
||||||
<path
|
|
||||||
d="M15 8a7.002 7.002 0 00-7-7"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
vector-effect="non-scaling-stroke"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
34
docs/.vitepress/components/ApkTable.vue
Normal file
34
docs/.vitepress/components/ApkTable.vue
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import DownloadText from './DownloadText.vue';
|
||||||
|
import { data } from '../data/apk.data';
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>版本</th>
|
||||||
|
<th>下载链接</th>
|
||||||
|
<th>更新日期</th>
|
||||||
|
<th>备注</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>正式版</td>
|
||||||
|
<td>
|
||||||
|
<DownloadText :href="data.stable.href" :name="data.stable.filename" />
|
||||||
|
</td>
|
||||||
|
<td>{{ data.stable.date }}</td>
|
||||||
|
<td>稳定版</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>测试版</td>
|
||||||
|
<td>
|
||||||
|
<DownloadText :href="data.beta.href" :name="data.beta.filename" />
|
||||||
|
</td>
|
||||||
|
<td>{{ data.beta.date }}</td>
|
||||||
|
<td>更新快不稳定</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</template>
|
88
docs/.vitepress/components/DownloadText.vue
Normal file
88
docs/.vitepress/components/DownloadText.vue
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, shallowRef } from 'vue';
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
href: string;
|
||||||
|
name?: string;
|
||||||
|
type?: string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
type: 'application/vnd.android.package-archive',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const filename = computed(() => {
|
||||||
|
if (props.name) return props.name;
|
||||||
|
return props.href.split('/').at(-1)!;
|
||||||
|
});
|
||||||
|
|
||||||
|
const loading = shallowRef(false);
|
||||||
|
const download = async () => {
|
||||||
|
if (loading.value) return;
|
||||||
|
loading.value = true;
|
||||||
|
import('file-saver');
|
||||||
|
try {
|
||||||
|
const file = await fetch(props.href)
|
||||||
|
.then((r) => r.arrayBuffer())
|
||||||
|
.then((b) => {
|
||||||
|
return new File([b], filename.value, {
|
||||||
|
type: props.type,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const { saveAs } = await import('file-saver');
|
||||||
|
saveAs(file, filename.value);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<a
|
||||||
|
relative
|
||||||
|
:class="{
|
||||||
|
'cursor-progress': loading,
|
||||||
|
'cursor-pointer': !loading,
|
||||||
|
}"
|
||||||
|
@click="download"
|
||||||
|
:data-href="href"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
:class="{
|
||||||
|
'opacity-50': loading,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ filename }}
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
v-if="loading"
|
||||||
|
pointer-events-none
|
||||||
|
absolute
|
||||||
|
left="1/1"
|
||||||
|
top-0
|
||||||
|
bottom-0
|
||||||
|
flex
|
||||||
|
items-center
|
||||||
|
pl-4px
|
||||||
|
>
|
||||||
|
<svg animate-spin size-16px viewBox="0 0 16 16" fill="none">
|
||||||
|
<circle
|
||||||
|
cx="8"
|
||||||
|
cy="8"
|
||||||
|
r="7"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-opacity="0.25"
|
||||||
|
stroke-width="2"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
></circle>
|
||||||
|
<path
|
||||||
|
d="M15 8a7.002 7.002 0 00-7-7"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
vector-effect="non-scaling-stroke"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</template>
|
|
@ -1,13 +1,13 @@
|
||||||
import naiveComponents from './naive';
|
import ApkTable from './ApkTable.vue';
|
||||||
import GImg from './GImg';
|
import GImg from './GImg';
|
||||||
import ImageTable from './ImageTable.vue';
|
|
||||||
import IdentifierField from './IdentifierField.vue';
|
import IdentifierField from './IdentifierField.vue';
|
||||||
import ApkDownloadButton from './ApkDownloadButton.vue';
|
import ImageTable from './ImageTable.vue';
|
||||||
|
import naiveComponents from './naive';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...naiveComponents,
|
...naiveComponents,
|
||||||
GImg,
|
GImg,
|
||||||
ImageTable,
|
ImageTable,
|
||||||
IdentifierField,
|
IdentifierField,
|
||||||
ApkDownloadButton
|
ApkTable,
|
||||||
};
|
};
|
||||||
|
|
39
docs/.vitepress/data/apk.data.ts
Normal file
39
docs/.vitepress/data/apk.data.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
export interface VersionInfo {
|
||||||
|
name: string;
|
||||||
|
date: string;
|
||||||
|
href: string;
|
||||||
|
filename: string;
|
||||||
|
}
|
||||||
|
export interface ApkData {
|
||||||
|
stable: VersionInfo;
|
||||||
|
beta: VersionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getVersionInfo = async (url: string): Promise<VersionInfo> => {
|
||||||
|
const r = await fetch(url).then((r) => r.json());
|
||||||
|
return {
|
||||||
|
name: r.versionName,
|
||||||
|
href: new URL(r.downloadUrl, url).href,
|
||||||
|
date: String(r.date || '').substring(0, 10),
|
||||||
|
filename: 'gkd-v' + r.versionName + '.apk',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const stableRelease = await getVersionInfo(
|
||||||
|
'https://registry.npmmirror.com/@gkd-kit/app/latest/files/index.json',
|
||||||
|
);
|
||||||
|
const betaRelease = await getVersionInfo(
|
||||||
|
'https://registry.npmmirror.com/@gkd-kit/app-beta/latest/files/index.json',
|
||||||
|
);
|
||||||
|
|
||||||
|
const load = async (): Promise<ApkData> => {
|
||||||
|
return {
|
||||||
|
stable: stableRelease,
|
||||||
|
beta: betaRelease,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
load,
|
||||||
|
};
|
||||||
|
export declare const data: ApkData;
|
12
docs/.vitepress/data/mirror.data.ts
Normal file
12
docs/.vitepress/data/mirror.data.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
const load = async (): Promise<string> => {
|
||||||
|
const version = await fetch(
|
||||||
|
'https://registry.npmmirror.com/@gkd-kit/assets/latest/files/package.json',
|
||||||
|
).then((r) => r.json().then((j) => j.version as string));
|
||||||
|
|
||||||
|
return `https://registry.npmmirror.com/@gkd-kit/assets/${version}/files/assets/`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
load,
|
||||||
|
};
|
||||||
|
export declare const data: string;
|
2
docs/.vitepress/env.d.ts
vendored
2
docs/.vitepress/env.d.ts
vendored
|
@ -1,3 +1 @@
|
||||||
/// <reference types="vitepress/client" />
|
/// <reference types="vitepress/client" />
|
||||||
|
|
||||||
declare const ASSETS_VERSION: string
|
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
const mirrorHost = () => {
|
import { data as mirrorHost } from '../data/mirror.data';
|
||||||
return `https://registry.npmmirror.com/@gkd-kit/assets/${ASSETS_VERSION}/files/assets/`;
|
|
||||||
};
|
|
||||||
const imgHost = 'https://a.gkd.li/';
|
const imgHost = 'https://a.gkd.li/';
|
||||||
|
|
||||||
export const convertSrc = (name: string): string => {
|
export const convertSrc = (name: string): string => {
|
||||||
if (name && name.startsWith('https:')) {
|
if (name && name.startsWith('https:')) {
|
||||||
if (name.startsWith(imgHost)) {
|
if (name.startsWith(imgHost)) {
|
||||||
return mirrorHost() + name.slice(imgHost.length);
|
return mirrorHost + name.slice(imgHost.length);
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
return mirrorHost() + name;
|
return mirrorHost + name;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,10 +2,7 @@
|
||||||
|
|
||||||
## 安装 {#install}
|
## 安装 {#install}
|
||||||
|
|
||||||
| 版本 | 下载链接 | 更新日期 | 备注 |
|
<ApkTable />
|
||||||
| ------ | -------------------------- | ---------- | ------------ |
|
|
||||||
| 正式版 | <ApkDownloadButton /> | 2024-08-27 | 稳定版 |
|
|
||||||
| 测试版 | <ApkDownloadButton beta /> | 2024-10-03 | 更新快不稳定 |
|
|
||||||
|
|
||||||
或前往 [Github Releases](https://github.com/gkd-kit/gkd/releases/latest) 下载
|
或前往 [Github Releases](https://github.com/gkd-kit/gkd/releases/latest) 下载
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,9 @@
|
||||||
import { defineConfig } from 'vite';
|
|
||||||
import unocss from 'unocss/vite';
|
import unocss from 'unocss/vite';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
import { mirror } from './.vitepress/plugins';
|
import { mirror } from './.vitepress/plugins';
|
||||||
|
|
||||||
const ASSETS_VERSION = await fetch(
|
|
||||||
'https://registry.npmmirror.com/@gkd-kit/assets/latest/files/package.json',
|
|
||||||
).then((r) => r.json().then((j) => j.version as string));
|
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
define: { ASSETS_VERSION: JSON.stringify(ASSETS_VERSION) },
|
plugins: [unocss(), mirror()],
|
||||||
plugins: [
|
|
||||||
unocss(),
|
|
||||||
mirror(),
|
|
||||||
],
|
|
||||||
server: {
|
server: {
|
||||||
host: '127.0.0.1',
|
host: '127.0.0.1',
|
||||||
port: 8633,
|
port: 8633,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user