mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-06 18:36:55 +08:00
feat: 更新依赖和增强动态表单功能
- 在 package.json 中添加 hammerjs 和 tui-image-editor 依赖 - 在 DynamicForm.vue 中引入并实现装饰性图片功能,支持图片上传、删除和属性调整 - 优化颜色处理逻辑,支持 RGBA 格式 - 更新常量和类型定义,增强代码可读性和可维护性
This commit is contained in:
@@ -241,12 +241,37 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, computed, nextTick, onUnmounted, watch } from 'vue';
|
||||
import { NCard, NGrid, NGridItem, NSpin, NStatistic, NTabPane, NTabs, useMessage, NTag, NIcon, NDivider, NFlex, NSpace } from 'naive-ui';
|
||||
import * as echarts from 'echarts';
|
||||
import * as echarts from 'echarts/core';
|
||||
import { LineChart, BarChart } from 'echarts/charts';
|
||||
import {
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
LegendComponent,
|
||||
MarkPointComponent,
|
||||
MarkLineComponent,
|
||||
DataZoomComponent
|
||||
} from 'echarts/components';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
import { QueryGetAPI } from '@/api/query';
|
||||
import { ANALYZE_API_URL } from '@/data/constants';
|
||||
import { useThemeVars } from 'naive-ui';
|
||||
import { TrendingDown, TrendingUp } from '@vicons/ionicons5';
|
||||
|
||||
// 注册必要的组件
|
||||
echarts.use([
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
LegendComponent,
|
||||
LineChart,
|
||||
BarChart,
|
||||
CanvasRenderer,
|
||||
MarkPointComponent,
|
||||
MarkLineComponent,
|
||||
DataZoomComponent
|
||||
]);
|
||||
|
||||
// types.ts
|
||||
interface ChartItem {
|
||||
income: number;
|
||||
|
||||
@@ -62,8 +62,9 @@ const shareModalVisiable = ref(false) // 分享模态框可见性
|
||||
const showOBSModal = ref(false) // OBS预览模态框可见性
|
||||
const replyMessage = ref('') // 回复输入框内容
|
||||
const addTagName = ref('') // 添加标签输入框内容
|
||||
const useCNUrl = useStorage('Settings.UseCNUrl', false) // 是否使用国内镜像URL (持久化存储)
|
||||
const shareCardRef = ref<HTMLElement | null>(null) // 分享卡片DOM引用
|
||||
const selectedShareTag = ref<string | null>(null) // 分享时选择的标签
|
||||
const selectedDirectShareTag = ref<string | null>(null) // 主链接区域选择的标签
|
||||
const ps = ref(20) // 分页大小 (每页条数)
|
||||
const pn = ref(1) // 当前页码
|
||||
const savedCardSize = useStorage<{ width: number; height: number }>('Settings.QuestionDisplay.CardSize', { // 问题展示卡片尺寸 (持久化存储)
|
||||
@@ -85,10 +86,17 @@ const setting = computed({
|
||||
},
|
||||
})
|
||||
|
||||
// 分享链接 (当前域名)
|
||||
const shareUrl = computed(() => `${CURRENT_HOST}@${accountInfo.value?.name}/question-box`)
|
||||
// 分享链接 (国内镜像)
|
||||
const shareUrlCN = computed(() => `${CN_HOST}@${accountInfo.value?.name}/question-box`)
|
||||
// 分享链接 (统一 Host, 根据选择的标签附加参数)
|
||||
const shareUrlWithTag = (tag: string | null) => {
|
||||
const base = `${CURRENT_HOST}@${accountInfo.value?.name}/question-box`
|
||||
return tag ? `${base}?tag=${encodeURIComponent(tag)}` : base
|
||||
}
|
||||
|
||||
// 主链接区域显示的链接
|
||||
const directShareUrl = computed(() => shareUrlWithTag(selectedDirectShareTag.value))
|
||||
|
||||
// 分享模态框中的二维码/卡片链接 (也基于selectedShareTag)
|
||||
const modalShareUrl = computed(() => shareUrlWithTag(selectedShareTag.value))
|
||||
|
||||
// 分页后的问题列表 (仅限收到的问题)
|
||||
const pagedQuestions = computed(() =>
|
||||
@@ -181,9 +189,9 @@ function saveShareImage() {
|
||||
|
||||
// 保存二维码图片
|
||||
function saveQRCode() {
|
||||
if (!shareUrl.value || !accountInfo.value?.name) return
|
||||
if (!modalShareUrl.value || !accountInfo.value?.name) return
|
||||
// 使用 QR Server API 生成并下载二维码
|
||||
downloadImage(`https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(shareUrl.value)}`, `vtsuru-提问箱二维码-${accountInfo.value.name}.png`)
|
||||
downloadImage(`https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(modalShareUrl.value)}`, `vtsuru-提问箱二维码-${accountInfo.value.name}.png`)
|
||||
message.success('二维码已开始下载')
|
||||
}
|
||||
|
||||
@@ -362,21 +370,28 @@ watch(() => accountInfo.value?.settings?.questionBox?.saftyLevel, (newLevel) =>
|
||||
提问页链接
|
||||
</NDivider>
|
||||
<NFlex align="center">
|
||||
<NInputGroup style="max-width: 400px;">
|
||||
<!-- 主链接区域输入框和复制按钮 -->
|
||||
<NInputGroup style="flex-grow: 1; max-width: 500px;">
|
||||
<NInput
|
||||
:value="`${useCNUrl ? shareUrlCN : shareUrl}`"
|
||||
:value="directShareUrl"
|
||||
readonly
|
||||
/>
|
||||
<NButton
|
||||
secondary
|
||||
@click="copyToClipboard(`${useCNUrl ? shareUrlCN : shareUrl}`)"
|
||||
@click="copyToClipboard(directShareUrl)"
|
||||
>
|
||||
复制
|
||||
</NButton>
|
||||
</NInputGroup>
|
||||
<NCheckbox v-model:checked="useCNUrl">
|
||||
使用国内镜像(访问更快)
|
||||
</NCheckbox>
|
||||
<!-- 主链接区域标签选择器 -->
|
||||
<NSelect
|
||||
v-model:value="selectedDirectShareTag"
|
||||
placeholder="附加话题 (可选)"
|
||||
filterable
|
||||
clearable
|
||||
:options="useQB.tags.filter(t => t.visiable).map((s) => ({ label: s.name, value: s.name }))"
|
||||
style="min-width: 150px; max-width: 200px;"
|
||||
/>
|
||||
</NFlex>
|
||||
|
||||
<!-- 审核中提示 -->
|
||||
@@ -696,7 +711,7 @@ watch(() => accountInfo.value?.settings?.questionBox?.saftyLevel, (newLevel) =>
|
||||
closable
|
||||
style="margin-bottom: 10px;"
|
||||
>
|
||||
这里存放的是被内容审查机制自动过滤的提问。您可以查看、删除或将其标记为正常提问。标记为正常后,提问将移至“我收到的”列表。
|
||||
这里存放的是被内容审查机制自动过滤的提问。您可以查看、删除或将其标记为正常提问。标记为正常后,提问将移至"我收到的"列表。
|
||||
</NAlert>
|
||||
<NEmpty
|
||||
v-if="useQB.trashQuestions.length === 0"
|
||||
@@ -1034,7 +1049,7 @@ watch(() => accountInfo.value?.settings?.questionBox?.saftyLevel, (newLevel) =>
|
||||
</div>
|
||||
<div class="share-card-qr">
|
||||
<QrcodeVue
|
||||
:value="shareUrl"
|
||||
:value="modalShareUrl"
|
||||
level="Q"
|
||||
:size="90"
|
||||
background="#FFFFFF"
|
||||
@@ -1046,31 +1061,32 @@ watch(() => accountInfo.value?.settings?.questionBox?.saftyLevel, (newLevel) =>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NDivider style="margin-top: 20px; margin-bottom: 10px;">
|
||||
分享链接设置
|
||||
</NDivider>
|
||||
<NSpace vertical>
|
||||
<NSelect
|
||||
v-model:value="selectedShareTag"
|
||||
placeholder="选择要附加到链接的话题 (可选)"
|
||||
filterable
|
||||
clearable
|
||||
:options="useQB.tags.filter(t => t.visiable).map((s) => ({ label: s.name, value: s.name }))"
|
||||
style="width: 100%;"
|
||||
/>
|
||||
</NSpace>
|
||||
|
||||
<NDivider style="margin-top: 20px; margin-bottom: 10px;">
|
||||
分享链接
|
||||
</NDivider>
|
||||
<NInputGroup>
|
||||
<NInputGroupLabel> 默认 </NInputGroupLabel>
|
||||
<NInputGroupLabel> 链接 </NInputGroupLabel>
|
||||
<NInput
|
||||
:value="shareUrl"
|
||||
:value="modalShareUrl"
|
||||
readonly
|
||||
/>
|
||||
<NButton
|
||||
secondary
|
||||
@click="copyToClipboard(shareUrl)"
|
||||
>
|
||||
复制
|
||||
</NButton>
|
||||
</NInputGroup>
|
||||
<NInputGroup style="margin-top: 5px;">
|
||||
<NInputGroupLabel> 国内 </NInputGroupLabel>
|
||||
<NInput
|
||||
:value="shareUrlCN"
|
||||
readonly
|
||||
/>
|
||||
<NButton
|
||||
secondary
|
||||
@click="copyToClipboard(shareUrlCN)"
|
||||
@click="copyToClipboard(modalShareUrl)"
|
||||
>
|
||||
复制
|
||||
</NButton>
|
||||
|
||||
@@ -136,8 +136,6 @@ const showCopyModal = ref(false)
|
||||
const updateScheduleModel = ref<ScheduleWeekInfo>({} as ScheduleWeekInfo)
|
||||
const selectedExistTag = ref()
|
||||
|
||||
const useCNUrl = useStorage('Settings.UseCNUrl', false)
|
||||
|
||||
const selectedDay = ref(0)
|
||||
const selectedScheduleYear = ref(new Date().getFullYear())
|
||||
const selectedScheduleWeek = ref(Number(format(Date.now(), 'w')) + 1)
|
||||
@@ -270,35 +268,51 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<NSpace align="center">
|
||||
<NAlert :type="accountInfo.settings.enableFunctions.includes(FunctionTypes.Schedule) ? 'success' : 'warning'"
|
||||
style="max-width: 200px">
|
||||
<NAlert
|
||||
:type="accountInfo.settings.enableFunctions.includes(FunctionTypes.Schedule) ? 'success' : 'warning'"
|
||||
style="max-width: 200px"
|
||||
>
|
||||
启用日程表
|
||||
<NDivider vertical />
|
||||
<NSwitch :value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.Schedule)"
|
||||
@update:value="setFunctionEnable" />
|
||||
<NSwitch
|
||||
:value="accountInfo?.settings.enableFunctions.includes(FunctionTypes.Schedule)"
|
||||
@update:value="setFunctionEnable"
|
||||
/>
|
||||
</NAlert>
|
||||
<NButton type="primary" @click="showAddModal = true">
|
||||
<NButton
|
||||
type="primary"
|
||||
@click="showAddModal = true"
|
||||
>
|
||||
添加周程
|
||||
</NButton>
|
||||
<NButton @click="$router.push({ name: 'manage-index', query: { tab: 'template', template: 'schedule' } })">
|
||||
<NButton @click="$router.push({ name: 'manage-index', query: { tab: 'setting', setting: 'template', template: 'schedule' } })">
|
||||
修改模板
|
||||
</NButton>
|
||||
</NSpace>
|
||||
<NDivider style="margin: 16px 0 16px 0" title-placement="left">
|
||||
<NDivider
|
||||
style="margin: 16px 0 16px 0"
|
||||
title-placement="left"
|
||||
>
|
||||
日程表展示页链接
|
||||
</NDivider>
|
||||
<NFlex align="center">
|
||||
<NInputGroup style="max-width: 400px;">
|
||||
<NInput :value="`${useCNUrl ? CN_HOST : CURRENT_HOST}@${accountInfo.name}/schedule`" readonly />
|
||||
<NButton secondary @click="copyToClipboard(`${useCNUrl ? CN_HOST : CURRENT_HOST}@${accountInfo.name}/schedule`)">
|
||||
<NInput
|
||||
:value="`${CURRENT_HOST}@${accountInfo.name}/schedule`"
|
||||
readonly
|
||||
/>
|
||||
<NButton
|
||||
secondary
|
||||
@click="copyToClipboard(`${CURRENT_HOST}@${accountInfo.name}/schedule`)"
|
||||
>
|
||||
复制
|
||||
</NButton>
|
||||
</NInputGroup>
|
||||
<NCheckbox v-model:checked="useCNUrl">
|
||||
使用国内镜像(访问更快)
|
||||
</NCheckbox>
|
||||
</NFlex>
|
||||
<NDivider style="margin: 16px 0 16px 0" title-placement="left">
|
||||
<NDivider
|
||||
style="margin: 16px 0 16px 0"
|
||||
title-placement="left"
|
||||
>
|
||||
订阅链接
|
||||
<NTooltip>
|
||||
<template #trigger>
|
||||
@@ -311,42 +325,84 @@ onMounted(() => {
|
||||
</NDivider>
|
||||
<NFlex align="center">
|
||||
<NInputGroup style="max-width: 400px;">
|
||||
<NInput :value="`${SCHEDULE_API_URL}${accountInfo.id}.ics`" readonly />
|
||||
<NButton secondary @click="copyToClipboard(`${SCHEDULE_API_URL}${accountInfo.id}.ics`)">
|
||||
<NInput
|
||||
:value="`${SCHEDULE_API_URL}${accountInfo.id}.ics`"
|
||||
readonly
|
||||
/>
|
||||
<NButton
|
||||
secondary
|
||||
@click="copyToClipboard(`${SCHEDULE_API_URL}${accountInfo.id}.ics`)"
|
||||
>
|
||||
复制
|
||||
</NButton>
|
||||
</NInputGroup>
|
||||
</NFlex>
|
||||
<NDivider />
|
||||
<NModal v-model:show="showAddModal" style="width: 600px; max-width: 90vw" preset="card" title="添加周程">
|
||||
<NModal
|
||||
v-model:show="showAddModal"
|
||||
style="width: 600px; max-width: 90vw"
|
||||
preset="card"
|
||||
title="添加周程"
|
||||
>
|
||||
<NSpace vertical>
|
||||
年份
|
||||
<NSelect v-model:value="selectedScheduleYear" :options="yearOptions" />
|
||||
<NSelect
|
||||
v-model:value="selectedScheduleYear"
|
||||
:options="yearOptions"
|
||||
/>
|
||||
第几周
|
||||
<NSelect v-model:value="selectedScheduleWeek" :options="weekOptions" />
|
||||
<NSelect
|
||||
v-model:value="selectedScheduleWeek"
|
||||
:options="weekOptions"
|
||||
/>
|
||||
</NSpace>
|
||||
<NDivider />
|
||||
<NButton :loading="isFetching" @click="addSchedule">
|
||||
<NButton
|
||||
:loading="isFetching"
|
||||
@click="addSchedule"
|
||||
>
|
||||
添加
|
||||
</NButton>
|
||||
</NModal>
|
||||
<NModal v-model:show="showCopyModal" style="width: 600px; max-width: 90vw" preset="card" title="复制周程">
|
||||
<NModal
|
||||
v-model:show="showCopyModal"
|
||||
style="width: 600px; max-width: 90vw"
|
||||
preset="card"
|
||||
title="复制周程"
|
||||
>
|
||||
<NAlert type="info">
|
||||
复制为
|
||||
</NAlert>
|
||||
<NSpace vertical>
|
||||
年份
|
||||
<NSelect v-model:value="selectedScheduleYear" :options="yearOptions" />
|
||||
<NSelect
|
||||
v-model:value="selectedScheduleYear"
|
||||
:options="yearOptions"
|
||||
/>
|
||||
第几周
|
||||
<NSelect v-model:value="selectedScheduleWeek" :options="weekOptions" />
|
||||
<NSelect
|
||||
v-model:value="selectedScheduleWeek"
|
||||
:options="weekOptions"
|
||||
/>
|
||||
</NSpace>
|
||||
<NDivider />
|
||||
<NButton :loading="isFetching" @click="onCopySchedule">
|
||||
<NButton
|
||||
:loading="isFetching"
|
||||
@click="onCopySchedule"
|
||||
>
|
||||
复制
|
||||
</NButton>
|
||||
</NModal>
|
||||
<NModal v-model:show="showUpdateModal" style="width: 600px; max-width: 90vw" preset="card" title="编辑周程">
|
||||
<NSelect v-model:value="selectedDay" :options="dayOptions" />
|
||||
<NModal
|
||||
v-model:show="showUpdateModal"
|
||||
style="width: 600px; max-width: 90vw"
|
||||
preset="card"
|
||||
title="编辑周程"
|
||||
>
|
||||
<NSelect
|
||||
v-model:value="selectedDay"
|
||||
:options="dayOptions"
|
||||
/>
|
||||
<NDivider />
|
||||
<template v-if="updateScheduleModel">
|
||||
<NSpace vertical>
|
||||
@@ -355,29 +411,66 @@ onMounted(() => {
|
||||
<NInputGroupLabel type="primary">
|
||||
标签
|
||||
</NInputGroupLabel>
|
||||
<NInput v-model:value="updateScheduleModel.days[selectedDay].tag" placeholder="标签 | 留空视为无安排"
|
||||
style="max-width: 300px" maxlength="10" show-count />
|
||||
<NInput
|
||||
v-model:value="updateScheduleModel.days[selectedDay].tag"
|
||||
placeholder="标签 | 留空视为无安排"
|
||||
style="max-width: 300px"
|
||||
maxlength="10"
|
||||
show-count
|
||||
/>
|
||||
</NInputGroup>
|
||||
<NSelect v-model:value="selectedExistTag" :options="existTagOptions" filterable clearable placeholder="使用过的标签"
|
||||
style="max-width: 150px" :render-option="renderOption" @update:value="onSelectChange" />
|
||||
<NSelect
|
||||
v-model:value="selectedExistTag"
|
||||
:options="existTagOptions"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="使用过的标签"
|
||||
style="max-width: 150px"
|
||||
:render-option="renderOption"
|
||||
@update:value="onSelectChange"
|
||||
/>
|
||||
</NSpace>
|
||||
<NInputGroup>
|
||||
<NInputGroupLabel> 内容 </NInputGroupLabel>
|
||||
<NInput v-model:value="updateScheduleModel.days[selectedDay].title" placeholder="内容" style="max-width: 200px"
|
||||
maxlength="30" show-count />
|
||||
<NInput
|
||||
v-model:value="updateScheduleModel.days[selectedDay].title"
|
||||
placeholder="内容"
|
||||
style="max-width: 200px"
|
||||
maxlength="30"
|
||||
show-count
|
||||
/>
|
||||
</NInputGroup>
|
||||
<NTimePicker v-model:formatted-value="updateScheduleModel.days[selectedDay].time"
|
||||
default-formatted-value="20:00" format="HH:mm" />
|
||||
<NColorPicker v-model:value="updateScheduleModel.days[selectedDay].tagColor"
|
||||
:swatches="['#FFFFFF', '#18A058', '#2080F0', '#F0A020', 'rgba(208, 48, 80, 1)']" default-value="#61B589"
|
||||
:show-alpha="false" :modes="['hex']" />
|
||||
<NButton :loading="isFetching" @click="onUpdateSchedule()">
|
||||
<NTimePicker
|
||||
v-model:formatted-value="updateScheduleModel.days[selectedDay].time"
|
||||
default-formatted-value="20:00"
|
||||
format="HH:mm"
|
||||
/>
|
||||
<NColorPicker
|
||||
v-model:value="updateScheduleModel.days[selectedDay].tagColor"
|
||||
:swatches="['#FFFFFF', '#18A058', '#2080F0', '#F0A020', 'rgba(208, 48, 80, 1)']"
|
||||
default-value="#61B589"
|
||||
:show-alpha="false"
|
||||
:modes="['hex']"
|
||||
/>
|
||||
<NButton
|
||||
:loading="isFetching"
|
||||
@click="onUpdateSchedule()"
|
||||
>
|
||||
保存
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</template>
|
||||
</NModal>
|
||||
<NSpin v-if="isLoading" show />
|
||||
<ScheduleList v-else :schedules="schedules ?? []" is-self @on-update="onOpenUpdateModal" @on-delete="onDeleteSchedule"
|
||||
@on-copy="onOpenCopyModal" />
|
||||
<NSpin
|
||||
v-if="isLoading"
|
||||
show
|
||||
/>
|
||||
<ScheduleList
|
||||
v-else
|
||||
:schedules="schedules ?? []"
|
||||
is-self
|
||||
@on-update="onOpenUpdateModal"
|
||||
@on-delete="onDeleteSchedule"
|
||||
@on-copy="onOpenCopyModal"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -58,7 +58,6 @@ const accountInfo = useAccount()
|
||||
const isLoading = ref(true)
|
||||
const showModal = ref(false)
|
||||
const showModalRenderKey = ref(0)
|
||||
const useCNUrl = useStorage('Settings.UseCNUrl', false)
|
||||
const onlyResetNameOnAdded = ref(true)
|
||||
|
||||
// 歌曲列表数据
|
||||
@@ -750,19 +749,16 @@ onMounted(async () => {
|
||||
<NFlex align="center">
|
||||
<NInputGroup style="max-width: 400px;">
|
||||
<NInput
|
||||
:value="`${useCNUrl ? CN_HOST : CURRENT_HOST}@${accountInfo.name}/song-list`"
|
||||
:value="`${CURRENT_HOST}@${accountInfo.name}/song-list`"
|
||||
readonly
|
||||
/>
|
||||
<NButton
|
||||
secondary
|
||||
@click="copyToClipboard(`${useCNUrl ? CN_HOST : CURRENT_HOST}@${accountInfo.name}/song-list`)"
|
||||
@click="copyToClipboard(`${CURRENT_HOST}@${accountInfo.name}/song-list`)"
|
||||
>
|
||||
复制
|
||||
</NButton>
|
||||
</NInputGroup>
|
||||
<NCheckbox v-model:checked="useCNUrl">
|
||||
使用国内镜像(访问更快)
|
||||
</NCheckbox>
|
||||
</NFlex>
|
||||
<NDivider style="margin: 16px 0 16px 0" />
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@ const useBiliAuth = useAuthStore()
|
||||
const formRef = ref()
|
||||
const isUpdating = ref(false)
|
||||
const isAllowedPrivacyPolicy = ref(false)
|
||||
const useCNUrl = useStorage('Settings.UseCNUrl', false)
|
||||
const showAddGoodsModal = ref(false)
|
||||
|
||||
// 路由哈希处理
|
||||
@@ -401,7 +400,7 @@ onMounted(() => { })
|
||||
|
||||
<!-- 礼物展示页链接 -->
|
||||
<NDivider
|
||||
style="margin: 16px 0"
|
||||
style="margin: 0"
|
||||
title-placement="left"
|
||||
>
|
||||
礼物展示页链接
|
||||
@@ -413,19 +412,16 @@ onMounted(() => { })
|
||||
>
|
||||
<NInputGroup style="max-width: 400px;">
|
||||
<NInput
|
||||
:value="`${useCNUrl ? CN_HOST : CURRENT_HOST}@${accountInfo.name}/goods`"
|
||||
:value="`${CURRENT_HOST}@${accountInfo.name}/goods`"
|
||||
readonly
|
||||
/>
|
||||
<NButton
|
||||
secondary
|
||||
@click="copyToClipboard(`${useCNUrl ? CN_HOST : CURRENT_HOST}@${accountInfo.name}/goods`)"
|
||||
@click="copyToClipboard(`${CURRENT_HOST}@${accountInfo.name}/goods`)"
|
||||
>
|
||||
复制
|
||||
</NButton>
|
||||
</NInputGroup>
|
||||
<NCheckbox v-model:checked="useCNUrl">
|
||||
使用国内镜像(访问更快)
|
||||
</NCheckbox>
|
||||
</NFlex>
|
||||
</NFlex>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user