|
@@ -1,44 +1,104 @@
|
|
|
<template>
|
|
|
- <switch
|
|
|
- class="fs-switch"
|
|
|
- :checked="checked"
|
|
|
- :color="color"
|
|
|
- :disabled="disabled"
|
|
|
- :class="[size]"
|
|
|
- @change="change">
|
|
|
- </switch>
|
|
|
+ <view
|
|
|
+ class="fs-switch"
|
|
|
+ :class="[{ 'fs-switch-checked': modelValue, 'fs-switch-disabled': disabled }, 'fs-switch-' + size]"
|
|
|
+ @click="handleClick"
|
|
|
+ >
|
|
|
+ <view class="fs-switch-text">{{ modelValue ? activeText : inactiveText }}</view>
|
|
|
+ </view>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
+import { watch, ref } from 'vue'
|
|
|
+
|
|
|
const props = defineProps({
|
|
|
- checked: Boolean,
|
|
|
+ modelValue: Boolean,
|
|
|
disabled: Boolean,
|
|
|
- color: {
|
|
|
+ activeColor: {
|
|
|
type: String,
|
|
|
default: '#0063F5'
|
|
|
},
|
|
|
+ inactiveColor: {
|
|
|
+ type: String,
|
|
|
+ default: '#fdfdfd'
|
|
|
+ },
|
|
|
+ activeText: String,
|
|
|
+ inactiveText: String,
|
|
|
size: {
|
|
|
type: String,
|
|
|
validator(value) {
|
|
|
- return ['small', 'medium'].includes(value)
|
|
|
+ return ['small', 'default', 'large'].includes(value)
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
-const emits = defineEmits(['change'])
|
|
|
+const emits = defineEmits(['change', 'update:modelValue'])
|
|
|
|
|
|
-const change = e => {
|
|
|
- emits('change', e.detail.value)
|
|
|
+const handleClick = () => {
|
|
|
+ if (!props.disabled) {
|
|
|
+ emits('update:modelValue', !props.modelValue)
|
|
|
+ emits('change', !props.modelValue)
|
|
|
+ }
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.fs-switch{
|
|
|
- transform: scale(0.8);
|
|
|
- &.medium{
|
|
|
- transform: scale(0.6);
|
|
|
+.fs-switch {
|
|
|
+ width: 80rpx;
|
|
|
+ height: 40rpx;
|
|
|
+ border-radius: 50rpx;
|
|
|
+ position: relative;
|
|
|
+ background-color: v-bind(inactiveColor);
|
|
|
+ border: 2rpx solid rgba(0, 0, 0, 0.12);
|
|
|
+ transition: background-color 0.1s;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ width: 36rpx;
|
|
|
+ height: 36rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ background-color: #fff;
|
|
|
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
|
|
|
+ transition: transform 0.3s;
|
|
|
+ z-index: 10;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-text {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ font-size: 12px;
|
|
|
+ transition: all 0.3s;
|
|
|
+ text-align: center;
|
|
|
+ width: 30rpx;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-disabled {
|
|
|
+ opacity: 0.5;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-checked {
|
|
|
+ background-color: v-bind(activeColor);
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ transform: translateX(40rpx);
|
|
|
+ }
|
|
|
+
|
|
|
+ .fs-switch-text {
|
|
|
+ color: #fff;
|
|
|
+ margin-left: -30rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &-large {
|
|
|
+ transform: scale(1.2);
|
|
|
}
|
|
|
- &.small{
|
|
|
- transform: scale(0.5);
|
|
|
+ &-small {
|
|
|
+ transform: scale(0.8);
|
|
|
}
|
|
|
}
|
|
|
</style>
|