wip
This commit is contained in:
@@ -18,6 +18,7 @@ const props = withDefaults(
|
||||
defineProps<{
|
||||
loading?: boolean
|
||||
showToolbar?: boolean
|
||||
showCheckbox?: boolean
|
||||
showPagination?: boolean
|
||||
exportLoading?: boolean
|
||||
importLoading?: boolean
|
||||
@@ -26,6 +27,7 @@ const props = withDefaults(
|
||||
}>(),
|
||||
{
|
||||
loading: true,
|
||||
showCheckbox: false,
|
||||
showToolbar: true,
|
||||
showPagination: true,
|
||||
exportLoading: false,
|
||||
@@ -48,6 +50,7 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
let listRef: any = $ref()
|
||||
let showCheckbox = $ref(false)
|
||||
|
||||
function scrollToBottom() {
|
||||
nextTick(() => {
|
||||
@@ -167,11 +170,7 @@ onMounted(async () => {
|
||||
|
||||
defineRender(() => {
|
||||
const d = item => (
|
||||
<Checkbox
|
||||
modelValue={selectIds.includes(item.id)}
|
||||
onChange={() => toggleSelect(item)}
|
||||
size="large"
|
||||
/>
|
||||
<Checkbox modelValue={selectIds.includes(item.id)} onChange={() => toggleSelect(item)} size="large" />
|
||||
)
|
||||
|
||||
return (
|
||||
@@ -194,27 +193,33 @@ defineRender(() => {
|
||||
<BaseButton onClick={cancelSearch}>取消</BaseButton>
|
||||
</div>
|
||||
) : (
|
||||
<div class="flex justify-between">
|
||||
<div class="flex gap-2 items-center">
|
||||
<Checkbox
|
||||
disabled={!params.list.length}
|
||||
onChange={() => toggleSelectAll()}
|
||||
modelValue={selectAll}
|
||||
size="large"
|
||||
/>
|
||||
<span>
|
||||
<div class="flex justify-between items-center">
|
||||
{showCheckbox ? (
|
||||
<div class="flex gap-2 items-center">
|
||||
<Checkbox
|
||||
disabled={!params.list.length}
|
||||
onChange={() => toggleSelectAll()}
|
||||
modelValue={selectAll}
|
||||
size="large"
|
||||
/>
|
||||
<span>
|
||||
{selectIds.length} / {params.total}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
) : <div>{params.total}条</div>}
|
||||
|
||||
|
||||
<div class="flex gap-2 relative">
|
||||
{selectIds.length ? (
|
||||
{selectIds.length && showCheckbox ? (
|
||||
<PopConfirm title="确认删除所有选中数据?" onConfirm={handleBatchDel}>
|
||||
<BaseIcon class="del" title="删除">
|
||||
<DeleteIcon />
|
||||
</BaseIcon>
|
||||
<BaseButton type="info">确认</BaseButton>
|
||||
</PopConfirm>
|
||||
) : null}
|
||||
|
||||
<BaseIcon onClick={() => (showCheckbox = !showCheckbox)} title="批量删除">
|
||||
<DeleteIcon />
|
||||
</BaseIcon>
|
||||
|
||||
<BaseIcon onClick={() => (showImportDialog = true)} title="导入">
|
||||
<IconSystemUiconsImport />
|
||||
</BaseIcon>
|
||||
@@ -265,7 +270,7 @@ defineRender(() => {
|
||||
return (
|
||||
<div class="list-item-wrapper" key={item.word}>
|
||||
{s.default({
|
||||
checkbox: d,
|
||||
checkbox: showCheckbox ? d : () => void 0,
|
||||
item,
|
||||
index: params.pageSize * (params.pageNo - 1) + index + 1,
|
||||
})}
|
||||
@@ -297,11 +302,7 @@ defineRender(() => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Dialog
|
||||
modelValue={showImportDialog}
|
||||
onUpdate:modelValue={closeImportDialog}
|
||||
title="导入教程"
|
||||
>
|
||||
<Dialog modelValue={showImportDialog} onUpdate:modelValue={closeImportDialog} title="导入教程">
|
||||
<div className="w-100 p-4 pt-0">
|
||||
<div>请按照模板的格式来填写数据</div>
|
||||
<div class="color-red">单词项为必填,其他项可不填</div>
|
||||
|
||||
@@ -418,8 +418,6 @@ defineExpose({ audioRef })
|
||||
|
||||
<!-- 进度条区域 -->
|
||||
<div class="progress-section">
|
||||
<!-- 时间显示 -->
|
||||
<span class="time-display">{{ formatTime(currentTime) }} / {{ formatTime(duration) }}</span>
|
||||
<!-- 进度条 -->
|
||||
<div class="progress-container" @mousedown="handleProgressMouseDown" ref="progressBarRef">
|
||||
<div class="progress-track">
|
||||
@@ -427,7 +425,8 @@ defineExpose({ audioRef })
|
||||
<div class="progress-thumb" :style="{ left: progress + '%' }"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 时间显示 -->
|
||||
<span class="time-display">{{ formatTime(currentTime) }} / {{ formatTime(duration) }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 音量控制 -->
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
||||
import BaseInput from "@/components/base/BaseInput.vue";
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import BaseInput from '@/components/base/BaseInput.vue'
|
||||
|
||||
interface IProps {
|
||||
currentPage?: number;
|
||||
pageSize?: number;
|
||||
pageSizes?: number[];
|
||||
layout?: string;
|
||||
total: number;
|
||||
hideOnSinglePage?: boolean;
|
||||
currentPage?: number
|
||||
pageSize?: number
|
||||
pageSizes?: number[]
|
||||
layout?: string
|
||||
total: number
|
||||
hideOnSinglePage?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<IProps>(), {
|
||||
@@ -17,55 +17,68 @@ const props = withDefaults(defineProps<IProps>(), {
|
||||
pageSizes: () => [10, 20, 30, 40, 50, 100],
|
||||
layout: 'prev, pager, next',
|
||||
hideOnSinglePage: false,
|
||||
});
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:currentPage': [val: number];
|
||||
'update:pageSize': [val: number];
|
||||
'size-change': [val: number];
|
||||
'current-change': [val: number];
|
||||
}>();
|
||||
'update:currentPage': [val: number]
|
||||
'update:pageSize': [val: number]
|
||||
'size-change': [val: number]
|
||||
'current-change': [val: number]
|
||||
}>()
|
||||
|
||||
const internalCurrentPage = ref(props.currentPage);
|
||||
const internalPageSize = ref(props.pageSize);
|
||||
const internalCurrentPage = ref(props.currentPage)
|
||||
const jumpTarget = $ref('')
|
||||
const internalPageSize = ref(props.pageSize)
|
||||
|
||||
// 计算总页数
|
||||
const pageCount = computed(() => {
|
||||
return Math.max(1, Math.ceil(props.total / internalPageSize.value));
|
||||
});
|
||||
return Math.max(1, Math.ceil(props.total / internalPageSize.value))
|
||||
})
|
||||
|
||||
// 可用于显示的页码数量,会根据容器宽度动态计算
|
||||
const availablePagerCount = ref(5); // 默认值
|
||||
const availablePagerCount = ref(5) // 默认值
|
||||
|
||||
// 是否显示分页
|
||||
const shouldShow = computed(() => {
|
||||
return props.hideOnSinglePage ? pageCount.value > 1 : true;
|
||||
});
|
||||
return props.hideOnSinglePage ? pageCount.value > 1 : true
|
||||
})
|
||||
|
||||
// 处理页码变化
|
||||
function jumpPage(val: number) {
|
||||
if (Number(val) > pageCount.value) val = pageCount.value;
|
||||
if (Number(val) <= 0) val = 1;
|
||||
internalCurrentPage.value = val;
|
||||
emit('update:currentPage', Number(val));
|
||||
emit('current-change', Number(val));
|
||||
if (Number(val) > pageCount.value) val = pageCount.value
|
||||
if (Number(val) <= 0) val = 1
|
||||
internalCurrentPage.value = val
|
||||
emit('update:currentPage', Number(val))
|
||||
emit('current-change', Number(val))
|
||||
}
|
||||
|
||||
function jumpToTarget() {
|
||||
let d = Number(jumpTarget)
|
||||
if (d > pageCount.value) {
|
||||
// 这里如果目标值大于页码,那么将目标值作为下标计算,计算出对应的页码再跳转
|
||||
// 按目标值-1整除每页数量,定位属于第几页
|
||||
let page = Math.floor((d - 1) / internalPageSize.value) + 1
|
||||
jumpPage(page)
|
||||
} else {
|
||||
jumpPage(d)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理每页条数变化
|
||||
function handleSizeChange(val: number) {
|
||||
internalPageSize.value = val;
|
||||
emit('update:pageSize', val);
|
||||
emit('size-change', val);
|
||||
internalPageSize.value = val
|
||||
emit('update:pageSize', val)
|
||||
emit('size-change', val)
|
||||
|
||||
// 重新计算可用页码数量
|
||||
calculateAvailablePagerCount();
|
||||
calculateAvailablePagerCount()
|
||||
|
||||
// 重新计算当前页,确保当前页在有效范围内
|
||||
const newPageCount = Math.ceil(props.total / val);
|
||||
const newPageCount = Math.ceil(props.total / val)
|
||||
if (internalCurrentPage.value > newPageCount) {
|
||||
internalCurrentPage.value = newPageCount;
|
||||
emit('update:currentPage', newPageCount);
|
||||
emit('current-change', newPageCount);
|
||||
internalCurrentPage.value = newPageCount
|
||||
emit('update:currentPage', newPageCount)
|
||||
emit('current-change', newPageCount)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,97 +86,85 @@ function handleSizeChange(val: number) {
|
||||
function calculateAvailablePagerCount() {
|
||||
// 在下一个渲染周期执行,确保DOM已更新
|
||||
setTimeout(() => {
|
||||
const paginationEl = document.querySelector('.pagination') as HTMLElement;
|
||||
if (!paginationEl) return;
|
||||
const paginationEl = document.querySelector('.pagination') as HTMLElement
|
||||
if (!paginationEl) return
|
||||
|
||||
const containerWidth = paginationEl.offsetWidth;
|
||||
const buttonWidth = 38; // 按钮宽度(包括margin)
|
||||
const availableWidth = containerWidth - 120; // 减去其他元素占用的空间(前后按钮等)
|
||||
const containerWidth = paginationEl.offsetWidth
|
||||
const buttonWidth = 38 // 按钮宽度(包括margin)
|
||||
const availableWidth = containerWidth - 120 // 减去其他元素占用的空间(前后按钮等)
|
||||
|
||||
// 计算可以显示多少个页码按钮
|
||||
const maxPagers = Math.max(3, Math.floor(availableWidth / buttonWidth) - 2); // 减2是因为第一页和最后一页始终显示
|
||||
availablePagerCount.value = maxPagers;
|
||||
}, 0);
|
||||
const maxPagers = Math.max(3, Math.floor(availableWidth / buttonWidth) - 2) // 减2是因为第一页和最后一页始终显示
|
||||
availablePagerCount.value = maxPagers
|
||||
}, 0)
|
||||
}
|
||||
|
||||
// 监听窗口大小变化
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', calculateAvailablePagerCount);
|
||||
window.addEventListener('resize', calculateAvailablePagerCount)
|
||||
// 初始计算
|
||||
calculateAvailablePagerCount();
|
||||
});
|
||||
calculateAvailablePagerCount()
|
||||
})
|
||||
|
||||
// 组件卸载时移除监听器
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', calculateAvailablePagerCount);
|
||||
window.removeEventListener('resize', calculateAvailablePagerCount)
|
||||
})
|
||||
|
||||
// 上一页
|
||||
function prev() {
|
||||
const newPage = internalCurrentPage.value - 1;
|
||||
const newPage = internalCurrentPage.value - 1
|
||||
if (newPage >= 1) {
|
||||
jumpPage(newPage);
|
||||
jumpPage(newPage)
|
||||
}
|
||||
}
|
||||
|
||||
// 下一页
|
||||
function next() {
|
||||
const newPage = internalCurrentPage.value + 1;
|
||||
const newPage = internalCurrentPage.value + 1
|
||||
if (newPage <= pageCount.value) {
|
||||
jumpPage(newPage);
|
||||
jumpPage(newPage)
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="pagination" v-if="shouldShow">
|
||||
<div class="pagination-container">
|
||||
<!-- 总数 -->
|
||||
<span v-if="layout.includes('total')" class="total text-base"> 共{{ total }}条 </span>
|
||||
<!-- 上一页 -->
|
||||
<button
|
||||
class="btn-prev"
|
||||
:disabled="internalCurrentPage <= 1"
|
||||
@click="prev"
|
||||
>
|
||||
<IconFluentChevronLeft20Filled/>
|
||||
<button class="btn-prev" :disabled="internalCurrentPage <= 1" @click="prev">
|
||||
<IconFluentChevronLeft20Filled />
|
||||
</button>
|
||||
|
||||
<!-- 页码 -->
|
||||
<div class="flex items-center">
|
||||
<div class="w-12">
|
||||
<BaseInput v-model="internalCurrentPage"
|
||||
@enter="jumpPage(internalCurrentPage)"
|
||||
class="text-center"/>
|
||||
<BaseInput v-model="internalCurrentPage" @enter="jumpPage(internalCurrentPage)" class="text-center" />
|
||||
</div>
|
||||
<span class="mx-2">/</span>
|
||||
<span class="text-base">{{ pageCount }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 下一页 -->
|
||||
<button
|
||||
class="btn-next"
|
||||
:disabled="internalCurrentPage >= pageCount"
|
||||
@click="next"
|
||||
>
|
||||
<IconFluentChevronLeft20Filled class="transform-rotate-180"/>
|
||||
<button class="btn-next" :disabled="internalCurrentPage >= pageCount" @click="next">
|
||||
<IconFluentChevronLeft20Filled class="transform-rotate-180" />
|
||||
</button>
|
||||
|
||||
<!-- 每页条数选择器 -->
|
||||
<div v-if="layout.includes('sizes')" class="sizes">
|
||||
<select
|
||||
:value="internalPageSize"
|
||||
@change="handleSizeChange(Number($event.target.value))"
|
||||
>
|
||||
<option v-for="item in pageSizes" :key="item" :value="item">
|
||||
{{ item }}条/页
|
||||
</option>
|
||||
<select :value="internalPageSize" @change="handleSizeChange(Number($event.target.value))">
|
||||
<option v-for="item in pageSizes" :key="item" :value="item">{{ item }}条/页</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 总数 -->
|
||||
<span v-if="layout.includes('total')" class="total text-base">
|
||||
共{{ total }}条
|
||||
</span>
|
||||
<div class="flex items-center gap-1 ml-2">
|
||||
跳至
|
||||
<div class="w-15">
|
||||
<BaseInput placeholder="页/序号" v-model="jumpTarget" @enter="jumpToTarget" class="text-center" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -186,7 +187,8 @@ function next() {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.btn-prev, .btn-next {
|
||||
.btn-prev,
|
||||
.btn-next {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -200,7 +202,7 @@ function next() {
|
||||
padding: 0 0.375rem;
|
||||
margin: 0.25rem 0.25rem;
|
||||
background-color: transparent;
|
||||
transition: all .3s;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.3;
|
||||
@@ -216,7 +218,7 @@ function next() {
|
||||
.sizes {
|
||||
border: 1px solid var(--color-input-border);
|
||||
border-radius: 0.25rem;
|
||||
padding-right: .2rem;
|
||||
padding-right: 0.2rem;
|
||||
background-color: var(--color-bg);
|
||||
overflow: hidden;
|
||||
|
||||
@@ -242,7 +244,6 @@ function next() {
|
||||
}
|
||||
|
||||
.total {
|
||||
margin: 0.25rem 0.5rem;
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,44 +71,29 @@ const ballSize = computed(() => switchHeight.value - 4);
|
||||
|
||||
<style scoped lang="scss">
|
||||
.switch {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
outline: none;
|
||||
background-color: #DCDFE6;
|
||||
position: relative;
|
||||
transition: background-color 0.3s;
|
||||
@apply inline-flex items-center cursor-pointer user-select-none outline-none bg-gray-200 position-relative transition-all duration-300;
|
||||
|
||||
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
@apply cursor-not-allowed opacity-60;
|
||||
}
|
||||
|
||||
&.checked {
|
||||
background-color: #409eff;
|
||||
@apply bg-blue-500;
|
||||
}
|
||||
|
||||
.ball {
|
||||
background-color: #fff;
|
||||
border-radius: 50%;
|
||||
transition: transform 0.3s;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
|
||||
position: absolute;
|
||||
@apply bg-white rounded-full transition-transform duration-300 box-shadow-sm absolute;
|
||||
}
|
||||
|
||||
.text {
|
||||
position: absolute;
|
||||
@apply absolute text-xs text-white user-select-none;
|
||||
font-size: 0.75rem;
|
||||
color: #fff;
|
||||
user-select: none;
|
||||
|
||||
&.left {
|
||||
margin-left: 6px;
|
||||
@apply ml-1.5;
|
||||
}
|
||||
|
||||
&.right {
|
||||
right: 6px;
|
||||
@apply right-1.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +111,8 @@ defineExpose({scrollBottom})
|
||||
</template>
|
||||
</BaseInput>
|
||||
</div>
|
||||
<transition-group name="drag" class="list" tag="div">
|
||||
<div class="item"
|
||||
<transition-group name="drag" class="space-y-3" tag="div">
|
||||
<div class="common-list-item"
|
||||
:class="[
|
||||
(selectItem.id === item.id) && 'active',
|
||||
draggable && 'draggable',
|
||||
@@ -178,42 +178,5 @@ defineExpose({scrollBottom})
|
||||
.search {
|
||||
margin: .6rem 0;
|
||||
}
|
||||
|
||||
.list {
|
||||
.item {
|
||||
box-sizing: border-box;
|
||||
background: var(--color-second);
|
||||
color: var(--color-font-1);
|
||||
border-radius: .5rem;
|
||||
margin-bottom: .6rem;
|
||||
padding: .6rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
transition: all .3s;
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: all .3s;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--color-third);
|
||||
.right {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--color-fourth);
|
||||
color: var(--color-font-1);
|
||||
}
|
||||
|
||||
&.draggable {
|
||||
cursor: move;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,43 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import Switch from '@/components/base/Switch.vue'
|
||||
import Slider from '@/components/base/Slider.vue'
|
||||
import SettingItem from '@/pages/setting/SettingItem.vue'
|
||||
import { useSettingStore } from '@/stores/setting.ts'
|
||||
|
||||
import Switch from "@/components/base/Switch.vue";
|
||||
import Slider from "@/components/base/Slider.vue";
|
||||
import SettingItem from "@/pages/setting/SettingItem.vue";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<!-- 文章练习设置-->
|
||||
<!-- 文章练习设置-->
|
||||
<!-- 文章练习设置-->
|
||||
<div>
|
||||
<!-- 发音-->
|
||||
<!-- 发音-->
|
||||
<!-- 发音-->
|
||||
<SettingItem mainTitle="音效"/>
|
||||
<SettingItem mainTitle="音效" />
|
||||
<SettingItem title="自动播放句子">
|
||||
<Switch v-model="settingStore.articleSound"/>
|
||||
<Switch v-model="settingStore.articleSound" />
|
||||
</SettingItem>
|
||||
<SettingItem title="自动播放下一篇">
|
||||
<Switch v-model="settingStore.articleAutoPlayNext"/>
|
||||
<SettingItem title="结束后播放下一篇">
|
||||
<Switch v-model="settingStore.articleAutoPlayNext" />
|
||||
</SettingItem>
|
||||
<SettingItem title="音量">
|
||||
<Slider v-model="settingStore.articleSoundVolume" showText showValue unit="%"/>
|
||||
<Slider v-model="settingStore.articleSoundVolume" showText showValue unit="%" />
|
||||
</SettingItem>
|
||||
<SettingItem title="倍速">
|
||||
<Slider v-model="settingStore.articleSoundSpeed" :step="0.1" :min="0.5" :max="3" showText showValue/>
|
||||
<Slider v-model="settingStore.articleSoundSpeed" :step="0.1" :min="0.5" :max="3" showText showValue />
|
||||
</SettingItem>
|
||||
|
||||
<div class="line"></div>
|
||||
<SettingItem title="输入时忽略符号/数字/人名">
|
||||
<Switch v-model="settingStore.ignoreSymbol"/>
|
||||
<Switch v-model="settingStore.ignoreSymbol" />
|
||||
</SettingItem>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
@@ -25,9 +25,6 @@ const simpleWords = $computed({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 通用练习设置-->
|
||||
<!-- 通用练习设置-->
|
||||
<!-- 通用练习设置-->
|
||||
<div>
|
||||
<SettingItem
|
||||
title="忽略大小写"
|
||||
|
||||
@@ -12,17 +12,7 @@ const settingStore = useSettingStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 单词练习设置-->
|
||||
<!-- 单词练习设置-->
|
||||
<!-- 单词练习设置-->
|
||||
<div>
|
||||
<!-- <SettingItem title="练习模式">-->
|
||||
<!-- <RadioGroup v-model="settingStore.wordPracticeMode" class="flex-col gap-0!">-->
|
||||
<!-- <Radio :value="WordPracticeMode.System" label="智能模式:自动规划学习、复习、听写、默写"/>-->
|
||||
<!-- <Radio :value="WordPracticeMode.Free" label="自由模式:系统不强制复习与默写"/>-->
|
||||
<!-- </RadioGroup>-->
|
||||
<!-- </SettingItem>-->
|
||||
|
||||
<SettingItem title="显示上一个/下一个单词"
|
||||
desc="开启后,练习中会在上方显示上一个/下一个单词"
|
||||
>
|
||||
@@ -134,4 +124,4 @@ const settingStore = useSettingStore()
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user