feat:移除ElSwitch组件

This commit is contained in:
zyronon
2025-08-13 01:59:38 +08:00
parent 7986d25c28
commit b0a10d520c
2 changed files with 119 additions and 9 deletions

View File

@@ -14,9 +14,10 @@ import {saveAs} from "file-saver";
import {GITHUB} from "@/config/ENV.ts";
import dayjs from "dayjs";
import BasePage from "@/pages/pc/components/BasePage.vue";
import {ElInputNumber, ElRadio, ElRadioGroup, ElSlider, ElSwitch} from 'element-plus'
import {ElInputNumber, ElRadio, ElRadioGroup, ElSlider} from 'element-plus'
import Toast from '@/pages/pc/components/Toast/Toast.ts'
import {Option, Select} from "@/pages/pc/components/Select";
import Switch from "@/pages/pc/components/Switch.vue";
const emit = defineEmits<{
toggleDisabledDialogEscKey: [val: boolean]
@@ -163,9 +164,8 @@ function importData(e) {
<div class="row">
<label class="main-title">所有音效</label>
<div class="wrapper">
<ElSwitch v-model="settingStore.allSound"
<Switch v-model="settingStore.allSound"
@change="useChangeAllSound"
inline-prompt
active-text=""
inactive-text=""
/>
@@ -175,7 +175,7 @@ function importData(e) {
<div class="row">
<label class="item-title">单词/句子自动发音</label>
<div class="wrapper">
<ElSwitch v-model="settingStore.wordSound"
<Switch v-model="settingStore.wordSound"
inline-prompt
active-text=""
inactive-text=""
@@ -212,7 +212,7 @@ function importData(e) {
<div class="row">
<label class="item-title">按键音</label>
<div class="wrapper">
<ElSwitch v-model="settingStore.keyboardSound"
<Switch v-model="settingStore.keyboardSound"
inline-prompt
active-text=""
inactive-text=""
@@ -253,7 +253,7 @@ function importData(e) {
<div class="row">
<label class="item-title">效果音输入错误完成时的音效</label>
<div class="wrapper">
<ElSwitch v-model="settingStore.effectSound"
<Switch v-model="settingStore.effectSound"
inline-prompt
active-text=""
inactive-text=""
@@ -292,7 +292,7 @@ function importData(e) {
<div class="row">
<label class="item-title">显示上一个/下一个单词</label>
<div class="wrapper">
<ElSwitch v-model="settingStore.showNearWord"
<Switch v-model="settingStore.showNearWord"
inline-prompt
active-text=""
inactive-text=""
@@ -306,7 +306,7 @@ function importData(e) {
<div class="row">
<label class="item-title">忽略大小写</label>
<div class="wrapper">
<ElSwitch v-model="settingStore.ignoreCase"
<Switch v-model="settingStore.ignoreCase"
inline-prompt
active-text=""
inactive-text=""
@@ -320,7 +320,7 @@ function importData(e) {
<div class="row">
<label class="item-title">允许默写模式下显示提示</label>
<div class="wrapper">
<ElSwitch v-model="settingStore.allowWordTip"
<Switch v-model="settingStore.allowWordTip"
inline-prompt
active-text=""
inactive-text=""

View File

@@ -0,0 +1,110 @@
<script setup lang="ts">
import {ref, computed, defineProps, defineEmits, watch} from 'vue';
const props = defineProps<{
modelValue: boolean;
disabled?: boolean;
width?: number; // 开关宽度,默认 40px
activeText?: string; // 开启状态显示文字
inactiveText?: string;// 关闭状态显示文字
}>();
const emit = defineEmits(['update:modelValue']);
const isChecked = ref(props.modelValue);
watch(() => props.modelValue, (val) => {
isChecked.value = val;
});
const toggle = () => {
if (props.disabled) return;
isChecked.value = !isChecked.value;
emit('update:modelValue', isChecked.value);
};
const onKeydown = (e: KeyboardEvent) => {
if (e.code === 'Space' || e.key === ' ') {
e.preventDefault();
toggle();
}
};
const switchWidth = computed(() => props.width ?? 40);
const switchHeight = computed(() => (switchWidth.value / 2) | 0);
const ballSize = computed(() => switchHeight.value - 4);
</script>
<template>
<div
class="switch"
:class="{ 'checked': isChecked, 'disabled': disabled }"
:tabindex="disabled ? -1 : 0"
role="switch"
:aria-checked="isChecked"
@click="toggle"
@keydown="onKeydown"
:style="{ width: switchWidth + 'px', height: switchHeight + 'px' ,borderRadius: switchHeight + 'px'}"
>
<transition name="fade">
<span class="text left" v-if="isChecked && activeText">{{ activeText }}</span>
</transition>
<div
class="ball"
:style="{
width: ballSize + 'px',
height: ballSize + 'px',
transform: isChecked ? 'translateX(' + (switchWidth - ballSize - 2) + 'px)' : 'translateX(2px)'
}"
></div>
<transition name="fade">
<span class="text right" v-if="!isChecked && inactiveText">{{ inactiveText }}</span>
</transition>
</div>
</template>
<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;
&.disabled {
cursor: not-allowed;
opacity: 0.6;
}
&.checked {
background-color: #409eff;
}
.ball {
background-color: #fff;
border-radius: 50%;
transition: transform 0.3s;
box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
position: absolute;
}
.text {
position: absolute;
font-size: 0.75rem;
color: #fff;
user-select: none;
top: 0;
&.left {
margin-left: 6px;
}
&.right {
right: 6px;
}
}
}
</style>