mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-28 04:10:31 +08:00
Merge pull request #76 from JeremyYu-cn/feat-upgrade-vue3
Feat: Convert setting component to composition API
This commit is contained in:
commit
79d39217f3
@ -6,128 +6,137 @@
|
||||
<div class="content">
|
||||
<el-popover placement="left-end" trigger="click" width="auto" @after-enter="enter" @before-leave="hide">
|
||||
<!-- eslint-disable-next-line vue/no-v-model-argument -->
|
||||
<color-picker v-model:value="innerColor" :modes="modes" @change="colorChange" @nativePick="dropColor" />
|
||||
<color-picker v-model:value="state.innerColor" :modes="modes" @change="colorChange" @nativePick="dropColor" />
|
||||
<template #reference>
|
||||
<div class="color__bar" :style="{ background: innerColor }"></div>
|
||||
<div class="color__bar" :style="{ background: state.innerColor }"></div>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
const NAME = 'color-select'
|
||||
import { defineComponent, toRefs, reactive, computed, onMounted, watch } from 'vue'
|
||||
<script lang="ts" setup>
|
||||
// const NAME = 'color-select'
|
||||
import {reactive, onMounted, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
// import { debounce } from 'throttle-debounce'
|
||||
// import { toolTip } from '@/common/methods/helper'
|
||||
// import colorPicker from '@/utils/plugins/color-picker/index.vue'
|
||||
import colorPicker from '@palxp/color-picker'
|
||||
|
||||
export default defineComponent({
|
||||
name: NAME,
|
||||
components: { colorPicker },
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
label: {
|
||||
default: '',
|
||||
},
|
||||
modelValue: {
|
||||
default: '',
|
||||
},
|
||||
width: {
|
||||
default: '100%',
|
||||
},
|
||||
modes: {
|
||||
default: () => ['纯色'],
|
||||
},
|
||||
},
|
||||
emits: ['finish', 'update:modelValue', 'change'],
|
||||
setup(props, { emit }) {
|
||||
const store = useStore()
|
||||
const state: any = reactive({
|
||||
innerColor: '',
|
||||
// colorLength: 0,
|
||||
// hasEyeDrop: 'EyeDropper' in window,
|
||||
})
|
||||
let first = true
|
||||
type TProps = {
|
||||
label?: string
|
||||
modelValue?: string
|
||||
width?: string
|
||||
modes?: string[]
|
||||
}
|
||||
|
||||
type TEmits = {
|
||||
(event: 'finish', data: string): void
|
||||
(event: 'update:modelValue', data: string): void
|
||||
(event: 'change', data: string): void
|
||||
}
|
||||
|
||||
type TState = {
|
||||
innerColor: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<TProps>(), {
|
||||
label: '',
|
||||
modelValue: '',
|
||||
width: '100%',
|
||||
modes: () => (['纯色'])
|
||||
})
|
||||
|
||||
const emit = defineEmits<TEmits>()
|
||||
|
||||
const store = useStore()
|
||||
const state = reactive<TState>({
|
||||
innerColor: '',
|
||||
// colorLength: 0,
|
||||
// hasEyeDrop: 'EyeDropper' in window,
|
||||
})
|
||||
let first = true
|
||||
|
||||
// const dColorHistory = computed(() => {
|
||||
// return store.getters.dColorHistory
|
||||
// })
|
||||
|
||||
onMounted(() => {
|
||||
if (props.modelValue) {
|
||||
let fixColor = props.modelValue + (props.modelValue.length === 7 ? 'ff' : '')
|
||||
// 当前@palxp/color-picker对部分小写16进制颜色处理有异常,统一转为大写
|
||||
state.innerColor = fixColor.toLocaleUpperCase()
|
||||
}
|
||||
})
|
||||
const dropColor = async (e: any) => {
|
||||
console.log('取色: ', e)
|
||||
}
|
||||
onMounted(() => {
|
||||
if (props.modelValue) {
|
||||
let fixColor = props.modelValue + (props.modelValue.length === 7 ? 'ff' : '')
|
||||
// 当前@palxp/color-picker对部分小写16进制颜色处理有异常,统一转为大写
|
||||
state.innerColor = fixColor.toLocaleUpperCase()
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => state.innerColor,
|
||||
(value) => {
|
||||
activeChange(value)
|
||||
if (first) {
|
||||
first = false
|
||||
return
|
||||
}
|
||||
// addHistory(value)
|
||||
},
|
||||
)
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
val !== state.innerColor && (state.innerColor = val)
|
||||
},
|
||||
)
|
||||
const dropColor = async (color: string) => {
|
||||
console.log('取色: ', color)
|
||||
}
|
||||
|
||||
const updateValue = (value: any) => {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
const activeChange = (value: any) => {
|
||||
updateValue(value)
|
||||
}
|
||||
const onChange = () => {
|
||||
emit('finish', state.innerColor)
|
||||
}
|
||||
// const addHistory = debounce(300, false, async (value) => {
|
||||
// store.dispatch('pushColorToHistory', value)
|
||||
// })
|
||||
// const colorChange = debounce(150, false, async (e) => {
|
||||
// state.innerColor = e + (e.length === 7 ? 'ff' : '')
|
||||
// })
|
||||
|
||||
const inputBlur = (color: string) => {
|
||||
state.innerColor = color
|
||||
}
|
||||
|
||||
const enter = () => {
|
||||
store.commit('setShowMoveable', false) // 清理掉上一次的选择框
|
||||
}
|
||||
|
||||
const hide = () => {
|
||||
store.commit('setShowMoveable', true) // 恢复上一次的选择框
|
||||
}
|
||||
|
||||
const colorChange = (e) => {
|
||||
emit('change', e)
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
// dColorHistory,
|
||||
activeChange,
|
||||
onChange,
|
||||
dropColor,
|
||||
inputBlur,
|
||||
enter,
|
||||
hide,
|
||||
colorChange,
|
||||
watch(
|
||||
() => state.innerColor,
|
||||
(value) => {
|
||||
activeChange(value)
|
||||
if (first) {
|
||||
first = false
|
||||
return
|
||||
}
|
||||
// addHistory(value)
|
||||
},
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
val !== state.innerColor && (state.innerColor = val)
|
||||
},
|
||||
)
|
||||
|
||||
const updateValue = (value: any) => {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
|
||||
const activeChange = (value: any) => {
|
||||
updateValue(value)
|
||||
}
|
||||
|
||||
const onChange = () => {
|
||||
emit('finish', state.innerColor)
|
||||
}
|
||||
|
||||
// const addHistory = debounce(300, false, async (value) => {
|
||||
// store.dispatch('pushColorToHistory', value)
|
||||
// })
|
||||
// const colorChange = debounce(150, false, async (e) => {
|
||||
// state.innerColor = e + (e.length === 7 ? 'ff' : '')
|
||||
// })
|
||||
|
||||
const inputBlur = (color: string) => {
|
||||
state.innerColor = color
|
||||
}
|
||||
|
||||
const enter = () => {
|
||||
store.commit('setShowMoveable', false) // 清理掉上一次的选择框
|
||||
}
|
||||
|
||||
const hide = () => {
|
||||
store.commit('setShowMoveable', true) // 恢复上一次的选择框
|
||||
}
|
||||
|
||||
const colorChange = (color: string) => {
|
||||
emit('change', color)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
// dColorHistory,
|
||||
activeChange,
|
||||
onChange,
|
||||
dropColor,
|
||||
inputBlur,
|
||||
enter,
|
||||
hide,
|
||||
colorChange,
|
||||
})
|
||||
</script>
|
||||
|
||||
|
@ -18,34 +18,40 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts" setup>
|
||||
// 图标按钮选择组件
|
||||
const NAME = 'icon-item-select'
|
||||
// const NAME = 'icon-item-select'
|
||||
|
||||
export default {
|
||||
name: NAME,
|
||||
props: {
|
||||
label: {
|
||||
default: '',
|
||||
},
|
||||
data: {
|
||||
required: true,
|
||||
type: Array,
|
||||
},
|
||||
},
|
||||
emits: ['finish'],
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
selectItem(item) {
|
||||
if (typeof item.select !== 'undefined') {
|
||||
item.select = !item.select
|
||||
}
|
||||
this.$emit('finish', item)
|
||||
},
|
||||
},
|
||||
type TPropData = {
|
||||
select: boolean,
|
||||
extraIcon: boolean,
|
||||
tip: string
|
||||
icon?: string
|
||||
}
|
||||
|
||||
type TProps = {
|
||||
label?: string
|
||||
data: TPropData[]
|
||||
}
|
||||
|
||||
type TEmits = {
|
||||
(event: 'finish', data: TPropData): void
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<TProps>(), {
|
||||
label: ''
|
||||
})
|
||||
|
||||
const emit = defineEmits<TEmits>()
|
||||
|
||||
|
||||
function selectItem(item: TPropData) {
|
||||
if (typeof item.select !== 'undefined') {
|
||||
item.select = !item.select
|
||||
}
|
||||
emit('finish', item)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
@ -13,11 +13,26 @@
|
||||
</div> -->
|
||||
<div v-if="type === 'simple'">
|
||||
<span class="prepend">{{ prepend }}</span>
|
||||
<input :class="{ 'small-input': true, disable: !editable }" type="text" :value="modelValue" :readonly="editable ? false : 'readonly'" @input="updateValue($event.target.value)" @focus="focusInput" @blur="blurInput" @keyup="verifyNumber" @keydown="(e) => opNumber(e)" />
|
||||
<input
|
||||
:class="{ 'small-input': true, disable: !editable }" type="text" :value="modelValue"
|
||||
:readonly="!props.editable"
|
||||
@input="updateValue($event && $event.target ? ($event.target as HTMLInputElement).value : '')"
|
||||
@focus="focusInput"
|
||||
@blur="blurInput"
|
||||
@keyup="verifyNumber"
|
||||
@keydown="(e) => opNumber(e)" />
|
||||
</div>
|
||||
<div v-else class="number-input2">
|
||||
<div class="input-wrap" @click="edit">
|
||||
<input :class="{ 'real-input': true, disable: !editable }" type="text" :value="modelValue" :readonly="editable ? false : 'readonly'" @input="updateValue($event.target.value)" @focus="focusInput" @blur="blurInput" @keyup="verifyNumber" @keydown="(e) => opNumber(e)" />
|
||||
<div class="input-wrap">
|
||||
<input
|
||||
:class="{ 'real-input': true, disable: !editable }"
|
||||
type="text" :value="modelValue" :readonly="!props.editable"
|
||||
@input="updateValue($event && $event.target ? ($event.target as HTMLInputElement).value : '')"
|
||||
@focus="focusInput"
|
||||
@blur="blurInput"
|
||||
@keyup="verifyNumber"
|
||||
@keydown="(e) => opNumber(e)"
|
||||
/>
|
||||
</div>
|
||||
<span style="color: rgba(0, 0, 0, 0.45)">{{ label }}</span>
|
||||
<!-- <div :class="{ 'input-wrap': true, active: inputBorder }">
|
||||
@ -30,125 +45,130 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
// 数字输入组件
|
||||
const NAME = 'number-input'
|
||||
// const NAME = 'number-input'
|
||||
|
||||
export default {
|
||||
name: NAME,
|
||||
props: {
|
||||
label: {
|
||||
default: '',
|
||||
},
|
||||
modelValue: {
|
||||
default: '',
|
||||
},
|
||||
editable: {
|
||||
default: true,
|
||||
},
|
||||
step: {
|
||||
default: 1,
|
||||
},
|
||||
maxValue: {},
|
||||
minValue: {},
|
||||
type: {},
|
||||
prepend: {},
|
||||
},
|
||||
emits: ['finish', 'update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
inputBorder: false,
|
||||
tagText: '',
|
||||
showEdit: false,
|
||||
type TProps = {
|
||||
label?: string
|
||||
modelValue?: string | number
|
||||
editable?: boolean
|
||||
step?: number
|
||||
maxValue?: string | number
|
||||
minValue?: string | number
|
||||
type?: string
|
||||
prepend?: string
|
||||
}
|
||||
|
||||
type TEmits = {
|
||||
(event: 'finish', data: number | string): void
|
||||
(event: 'update:modelValue', data: number | string): void
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<TProps>(), {
|
||||
label: '',
|
||||
modelValue: '',
|
||||
editable: true,
|
||||
step: 1
|
||||
})
|
||||
|
||||
const emit = defineEmits<TEmits>()
|
||||
|
||||
const inputBorder = ref<boolean>(false)
|
||||
const tagText = ref<string | number>('')
|
||||
const showEdit = ref<boolean>(false)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => fixedNum()
|
||||
)
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
fixedNum()
|
||||
})
|
||||
|
||||
function fixedNum() {
|
||||
// 小数点过长时
|
||||
const decimal = String(props.modelValue).split('.')[1]
|
||||
if (decimal && decimal.length > 2) {
|
||||
setTimeout(() => {
|
||||
updateValue(Number(props.modelValue).toFixed(2))
|
||||
}, 10)
|
||||
}
|
||||
// 限定数字范围
|
||||
if (props.maxValue && props.modelValue > props.maxValue) {
|
||||
setTimeout(() => {
|
||||
updateValue(Number(props.maxValue))
|
||||
}, 10)
|
||||
} else if (typeof props.minValue === 'number' && Number(props.modelValue) < Number(props.minValue)) {
|
||||
setTimeout(() => {
|
||||
updateValue(Number(props.minValue))
|
||||
}, 10)
|
||||
}
|
||||
}
|
||||
|
||||
function updateValue(value: string | number) {
|
||||
emit('update:modelValue', value === '-' ? '-' : Number(value))
|
||||
}
|
||||
|
||||
function up() {
|
||||
updateValue(parseInt(`${props.modelValue}` ?? '0', 10) + props.step)
|
||||
}
|
||||
function down() {
|
||||
let value = parseInt(`${props.modelValue}` ?? '0', 10) - props.step
|
||||
updateValue(value)
|
||||
}
|
||||
|
||||
function opNumber(e: KeyboardEvent) {
|
||||
e.stopPropagation()
|
||||
switch (e.keyCode) {
|
||||
case 38:
|
||||
up()
|
||||
return
|
||||
case 40:
|
||||
down()
|
||||
return
|
||||
}
|
||||
}
|
||||
function verifyNumber() {
|
||||
let value = String(props.modelValue)
|
||||
let len = value.length
|
||||
let newValue = ''
|
||||
let isNegative = value[0] === '-'
|
||||
// 判断是否连续字符,否则置为0
|
||||
for (let i = isNegative ? 1 : 0; i < len; ++i) {
|
||||
let c = value[i]
|
||||
if (c == '.' || (c >= '0' && c <= '9')) {
|
||||
newValue += c
|
||||
} else {
|
||||
break
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
watch: {
|
||||
modelValue() {
|
||||
this.fixedNum()
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fixedNum()
|
||||
},
|
||||
methods: {
|
||||
fixedNum() {
|
||||
// 小数点过长时
|
||||
const decimal = String(this.modelValue).split('.')[1]
|
||||
if (decimal && decimal.length > 2) {
|
||||
setTimeout(() => {
|
||||
this.updateValue(Number(this.modelValue).toFixed(2))
|
||||
}, 10)
|
||||
}
|
||||
// 限定数字范围
|
||||
if (this.maxValue && this.modelValue > this.maxValue) {
|
||||
setTimeout(() => {
|
||||
this.updateValue(Number(this.maxValue))
|
||||
}, 10)
|
||||
} else if (typeof this.minValue === 'number' && this.modelValue < this.minValue) {
|
||||
setTimeout(() => {
|
||||
this.updateValue(Number(this.minValue))
|
||||
}, 10)
|
||||
}
|
||||
},
|
||||
updateValue(value) {
|
||||
this.$emit('update:modelValue', value === '-' ? '-' : Number(value))
|
||||
},
|
||||
up() {
|
||||
this.updateValue(parseInt(this.modelValue || 0, 10) + this.step)
|
||||
},
|
||||
down() {
|
||||
let value = parseInt(this.modelValue || 0, 10) - this.step
|
||||
this.updateValue(value)
|
||||
},
|
||||
opNumber(e) {
|
||||
e.stopPropagation()
|
||||
switch (e.keyCode) {
|
||||
case 38:
|
||||
this.up()
|
||||
return
|
||||
case 40:
|
||||
this.down()
|
||||
return
|
||||
}
|
||||
},
|
||||
verifyNumber() {
|
||||
let value = String(this.modelValue)
|
||||
let len = value.length
|
||||
let newValue = ''
|
||||
let isNegative = value[0] === '-'
|
||||
// 判断是否连续字符,否则置为0
|
||||
for (let i = isNegative ? 1 : 0; i < len; ++i) {
|
||||
let c = value[i]
|
||||
if (c == '.' || (c >= '0' && c <= '9')) {
|
||||
newValue += c
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (newValue === '') {
|
||||
newValue = '0'
|
||||
}
|
||||
if (isNegative) {
|
||||
newValue = '-' + (newValue === '0' ? '' : newValue)
|
||||
}
|
||||
this.updateValue(newValue)
|
||||
// this.updateValue(parseInt(newValue, 10))
|
||||
},
|
||||
focusInput() {
|
||||
this.inputBorder = true
|
||||
this.tagText = this.modelValue
|
||||
},
|
||||
blurInput() {
|
||||
if (this.modelValue === '-') {
|
||||
this.updateValue(0)
|
||||
}
|
||||
this.inputBorder = false
|
||||
if (this.modelValue !== this.tagText) {
|
||||
this.$emit('finish', this.modelValue)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
if (newValue === '') {
|
||||
newValue = '0'
|
||||
}
|
||||
if (isNegative) {
|
||||
newValue = '-' + (newValue === '0' ? '' : newValue)
|
||||
}
|
||||
updateValue(newValue)
|
||||
// this.updateValue(parseInt(newValue, 10))
|
||||
}
|
||||
|
||||
function focusInput() {
|
||||
inputBorder.value = true
|
||||
tagText.value = props.modelValue
|
||||
}
|
||||
|
||||
function blurInput() {
|
||||
if (props.modelValue === '-') {
|
||||
updateValue(0)
|
||||
}
|
||||
inputBorder.value = false
|
||||
if (props.modelValue !== tagText.value) {
|
||||
emit('finish', props.modelValue)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user