mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-15 16:02:19 +08:00
feat: convert value select component to composition API
This commit is contained in:
parent
c63ca83894
commit
83f7f5e485
@ -24,7 +24,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
// 文本输入组件
|
// 文本输入组件
|
||||||
const NAME = 'text-input'
|
// const NAME = 'text-input'
|
||||||
|
|
||||||
type TProps = {
|
type TProps = {
|
||||||
label?: string
|
label?: string
|
||||||
|
@ -9,61 +9,65 @@
|
|||||||
<div id="text-input-area">
|
<div id="text-input-area">
|
||||||
<p v-if="label" class="input-label">{{ label }}</p>
|
<p v-if="label" class="input-label">{{ label }}</p>
|
||||||
<div :class="{ 'input-wrap': true, active: inputBorder }">
|
<div :class="{ 'input-wrap': true, active: inputBorder }">
|
||||||
<textarea :maxlength="max" :class="{ 'real-input': true, disable: !editable }" type="text" rows="3" :value="dealValue" :readonly="editable ? false : 'readonly'" @input="updateValue($event.target.value)" @focus="focusInput" @blur="blurInput" />
|
<textarea
|
||||||
|
:maxlength="max" :class="{ 'real-input': true, disable: !editable }"
|
||||||
|
type="text" rows="3" :value="dealValue"
|
||||||
|
:readonly="!editable" @input="updateValue(($event.target as HTMLTextAreaElement).value)"
|
||||||
|
@focus="focusInput" @blur="blurInput"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
// 文本域输入组件
|
// 文本域输入组件
|
||||||
const NAME = 'text-input-area'
|
// const NAME = 'text-input-area'
|
||||||
|
|
||||||
export default {
|
type TProps = {
|
||||||
name: NAME,
|
label?: string
|
||||||
props: {
|
modelValue?: string
|
||||||
label: {
|
editable?: boolean
|
||||||
default: '',
|
max?: string
|
||||||
},
|
}
|
||||||
modelValue: {
|
|
||||||
default: '',
|
type TEmits = {
|
||||||
},
|
(event:'update:modelValue', data: string): void
|
||||||
editable: {
|
(event: 'finish', data: string): void
|
||||||
default: true,
|
}
|
||||||
},
|
|
||||||
max: {},
|
const props = withDefaults(defineProps<TProps>(), {
|
||||||
},
|
label: '',
|
||||||
emits: ['update:modelValue', 'finish'],
|
modelValue: '',
|
||||||
data() {
|
editable: true,
|
||||||
return {
|
})
|
||||||
inputBorder: false,
|
|
||||||
tagText: '',
|
const emit = defineEmits<TEmits>()
|
||||||
}
|
const inputBorder = ref(false)
|
||||||
},
|
const tagText = ref<string>('')
|
||||||
computed: {
|
|
||||||
dealValue() {
|
const dealValue = computed(() => {
|
||||||
return this.modelValue
|
return props.modelValue
|
||||||
// return this.modelValue.replace(/<br\/>/g, '\r\n').replace(/ /g, ' ')
|
})
|
||||||
},
|
|
||||||
},
|
function updateValue(value: string) {
|
||||||
methods: {
|
emit('update:modelValue', getValue(value))
|
||||||
updateValue(value) {
|
}
|
||||||
this.$emit('update:modelValue', this.getValue(value))
|
|
||||||
},
|
function focusInput() {
|
||||||
focusInput() {
|
inputBorder.value = true
|
||||||
this.inputBorder = true
|
tagText.value = props.modelValue
|
||||||
this.tagText = this.modelValue
|
}
|
||||||
},
|
|
||||||
blurInput() {
|
function blurInput() {
|
||||||
this.inputBorder = false
|
inputBorder.value = false
|
||||||
let v = this.getValue(this.modelValue)
|
let v = getValue(props.modelValue)
|
||||||
if (v !== this.tagText) {
|
if (v !== tagText.value) {
|
||||||
this.$emit('finish', v)
|
emit('finish', v)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
getValue(value) {
|
function getValue(value: string) {
|
||||||
return value.replace(/\n|\r\n/g, '<br/>').replace(/ /g, ' ')
|
return value.replace(/\n|\r\n/g, '<br/>').replace(/ /g, ' ')
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -13,18 +13,22 @@
|
|||||||
<el-popover placement="bottom-end" trigger="click" width="auto">
|
<el-popover placement="bottom-end" trigger="click" width="auto">
|
||||||
<!-- 单列表 -->
|
<!-- 单列表 -->
|
||||||
<ul v-if="data && Array.isArray(data)" class="list-ul">
|
<ul v-if="data && Array.isArray(data)" class="list-ul">
|
||||||
<li v-for="listItem in data" :key="typeof listItem === 'object' ? listItem.alias : listItem" :class="{ active: listItem == innerValue }" @click="selectItem(listItem)">
|
<li
|
||||||
<img v-if="listItem.preview" class="preview" :src="listItem.preview" />
|
v-for="listItem in data" :key="typeof listItem === 'object' ? listItem.alias : listItem"
|
||||||
|
:class="{ active: listItem == state.innerValue }"
|
||||||
|
@click="selectItem(listItem)"
|
||||||
|
>
|
||||||
|
<img v-if="listItem.preview" class="preview" :src="listItem.preview" alt="preview" />
|
||||||
<span v-else>{{ (typeof listItem === 'object' ? listItem.alias : listItem) + suffix }}</span>
|
<span v-else>{{ (typeof listItem === 'object' ? listItem.alias : listItem) + suffix }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- tab分类列表 -->
|
<!-- tab分类列表 -->
|
||||||
<div v-else class="tabs-wrap">
|
<div v-else class="tabs-wrap">
|
||||||
<el-tabs v-model="activeTab">
|
<el-tabs v-model="state.activeTab">
|
||||||
<el-tab-pane v-for="(val, key, i) in data" :key="'tab' + i" :label="key" :name="key">
|
<el-tab-pane v-for="(val, key, i) in data" :key="'tab' + i" :label="key" :name="key">
|
||||||
<ul class="list-ul">
|
<ul class="list-ul">
|
||||||
<li v-for="listItem in data[key]" :key="typeof listItem === 'object' ? listItem.alias : listItem" :class="{ active: listItem == innerValue }" @click="selectItem(listItem)">
|
<li v-for="listItem in data[key]" :key="typeof listItem === 'object' ? listItem.alias : listItem" :class="{ active: listItem == state.innerValue }" @click="selectItem(listItem)">
|
||||||
<img v-if="listItem.preview" class="preview" :src="listItem.preview" />
|
<img v-if="listItem.preview" class="preview" :src="listItem.preview" alt="preview" />
|
||||||
<span v-else :style="{ fontFamily: `'${listItem.value}'` }">{{ (typeof listItem === 'object' ? listItem.alias : listItem) + suffix }}</span>
|
<span v-else :style="{ fontFamily: `'${listItem.value}'` }">{{ (typeof listItem === 'object' ? listItem.alias : listItem) + suffix }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -32,9 +36,16 @@
|
|||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<div :class="['input-wrap', { active: inputBorder }]" :style="{ width: inputWidth }">
|
<div :class="['input-wrap', { active: state.inputBorder }]" :style="{ width: inputWidth }">
|
||||||
<!-- <img v-if="innerPreview" class="preview" :src="innerPreview" /> -->
|
<!-- <img v-if="innerPreview" class="preview" :src="innerPreview" /> -->
|
||||||
<input :style="{ fontFamily: modelValue.value }" :class="['real-input', { disable: !disable }]" :readonly="readonly ? 'readonly' : false" type="text" :value="showValue" @input="inputText" @focus="inputBorder = true" @blur="inputBorder = false" @keydown="(e) => opNumber(e)" />
|
<input
|
||||||
|
:style="{ fontFamily: modelValue.value }"
|
||||||
|
:class="['real-input', { disable: !disable }]"
|
||||||
|
:readonly="readonly" type="text"
|
||||||
|
:value="showValue"
|
||||||
|
@input="inputText" @focus="state.inputBorder = true"
|
||||||
|
@blur="state.inputBorder = false" @keydown="(e) => opNumber(e)"
|
||||||
|
/>
|
||||||
<!-- <span class="input-unit">{{ suffix }}</span> -->
|
<!-- <span class="input-unit">{{ suffix }}</span> -->
|
||||||
<div class="op-btn">
|
<div class="op-btn">
|
||||||
<!-- <div class="down" @click="inputBorder = !inputBorder"></div> -->
|
<!-- <div class="down" @click="inputBorder = !inputBorder"></div> -->
|
||||||
@ -46,124 +57,127 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts" setup>
|
||||||
// 下拉选择框
|
// 下拉选择框
|
||||||
const NAME = 'value-input'
|
const NAME = 'value-input'
|
||||||
import { ElTabPane, ElTabs } from 'element-plus'
|
import { ElTabPane, ElTabs } from 'element-plus'
|
||||||
|
import { computed, onMounted, reactive, ref, watch } from 'vue';
|
||||||
|
|
||||||
export default {
|
type TProps = {
|
||||||
name: NAME,
|
label?: string
|
||||||
components: { ElTabPane, ElTabs },
|
modelValue?: Record<string, any>
|
||||||
props: {
|
suffix?: string
|
||||||
label: {
|
data: Record<string, any>
|
||||||
default: '',
|
disable?: boolean
|
||||||
},
|
inputWidth?: string
|
||||||
modelValue: {
|
readonly?: boolean
|
||||||
default: '',
|
step?: number
|
||||||
},
|
}
|
||||||
suffix: {
|
|
||||||
default: '',
|
type TEmits = {
|
||||||
},
|
(event:'update:modelValue', data: Record<string, any> | string | number): void
|
||||||
data: {
|
(event: 'finish', data: Record<string, any> | string | number): void
|
||||||
required: true,
|
}
|
||||||
},
|
|
||||||
disable: {
|
type TState = {
|
||||||
default: true,
|
inputBorder: boolean
|
||||||
},
|
tagText: string
|
||||||
inputWidth: {
|
width: string | number
|
||||||
default: '80px',
|
innerValue: string
|
||||||
},
|
innerPreview: string
|
||||||
// textAlign: {
|
activeTab: string
|
||||||
// default: 'center',
|
}
|
||||||
// },
|
|
||||||
readonly: {
|
const props = withDefaults(defineProps<TProps>(), {
|
||||||
default: false,
|
label: '',
|
||||||
},
|
modelValue: () => ({}),
|
||||||
step: {
|
suffic: '',
|
||||||
default: 1,
|
data: () => ({}),
|
||||||
},
|
disable: true,
|
||||||
},
|
inputWidth: '80px',
|
||||||
emits: ['finish', 'update:modelValue'],
|
readonly: false,
|
||||||
data() {
|
step: 1,
|
||||||
return {
|
})
|
||||||
inputBorder: false,
|
const emit = defineEmits<TEmits>()
|
||||||
tagText: '',
|
const state = reactive<TState>({
|
||||||
width: '0',
|
inputBorder: false,
|
||||||
innerValue: '',
|
tagText: '',
|
||||||
innerPreview: '',
|
width: '0',
|
||||||
activeTab: '中文',
|
innerValue: '',
|
||||||
|
innerPreview: '',
|
||||||
|
activeTab: '中文',
|
||||||
|
})
|
||||||
|
const selectRef = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
|
const showValue = computed(() => {
|
||||||
|
return state.innerValue
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
() => {
|
||||||
|
state.innerValue = typeof props.modelValue === 'object' ? props.modelValue.alias : props.modelValue
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => state.inputBorder,
|
||||||
|
(value) => {
|
||||||
|
if (value) {
|
||||||
|
state.tagText = state.innerValue
|
||||||
|
} else {
|
||||||
|
if (state.innerValue !== state.tagText) {
|
||||||
|
emit('finish', state.innerValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
computed: {
|
)
|
||||||
showValue() {
|
|
||||||
// return this.innerValue + this.suffix
|
onMounted(() => {
|
||||||
return this.innerValue
|
state.innerValue = typeof props.modelValue === 'object' ? props.modelValue.alias : props.modelValue
|
||||||
},
|
if (selectRef.value) {
|
||||||
},
|
state.width = selectRef.value.offsetWidth
|
||||||
watch: {
|
}
|
||||||
modelValue(value) {
|
})
|
||||||
this.innerValue = typeof this.modelValue === 'object' ? this.modelValue.alias : this.modelValue
|
|
||||||
},
|
function selectItem(item: Record<string, any>) {
|
||||||
inputBorder(value) {
|
let value = typeof item === 'object' ? item.alias : item
|
||||||
if (value) {
|
if (state.innerValue !== value) {
|
||||||
this.tagText = this.innerValue
|
state.innerValue = value
|
||||||
} else {
|
state.innerPreview = item.preview
|
||||||
if (this.innerValue !== this.tagText) {
|
emit('finish', item)
|
||||||
this.$emit('finish', this.innerValue)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
function inputText(e: Event) {
|
||||||
},
|
// this.innerValue = e.target.value.replace(RegExp(this.suffix), '')
|
||||||
created() {
|
state.innerValue = (e.target as HTMLInputElement).value
|
||||||
this.innerValue = typeof this.modelValue === 'object' ? this.modelValue.alias : this.modelValue
|
setTimeout(() => {
|
||||||
},
|
emit('finish', state.innerValue)
|
||||||
mounted() {
|
}, 100)
|
||||||
this.width = this.$refs.select.offsetWidth
|
}
|
||||||
// if (Object.prototype.toString.call(this.data) === '[Object Object]') {
|
function opNumber(e: KeyboardEvent) {
|
||||||
// for (const key in this.data) {
|
e.stopPropagation()
|
||||||
// console.log(key)
|
switch (e.keyCode) {
|
||||||
// break
|
case 38:
|
||||||
// }
|
typeof state.innerValue === 'number' && up()
|
||||||
// }
|
return
|
||||||
},
|
case 40:
|
||||||
methods: {
|
typeof state.innerValue === 'number' && down()
|
||||||
selectItem(item) {
|
return
|
||||||
let value = typeof item === 'object' ? item.alias : item
|
}
|
||||||
if (this.innerValue !== value) {
|
}
|
||||||
this.innerValue = value
|
|
||||||
this.innerPreview = item.preview
|
function up() {
|
||||||
this.$emit('finish', item)
|
emit('update:modelValue', parseInt(`${props.modelValue}` ?? '0', 10) + props.step)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
inputText(e) {
|
function down() {
|
||||||
// this.innerValue = e.target.value.replace(RegExp(this.suffix), '')
|
let value = parseInt(`${props.modelValue}` ?? '0', 10) - props.step
|
||||||
this.innerValue = e.target.value
|
if (value < 0) {
|
||||||
setTimeout(() => {
|
value = 0
|
||||||
this.$emit('finish', this.innerValue)
|
}
|
||||||
}, 100)
|
emit('update:modelValue', value)
|
||||||
},
|
|
||||||
opNumber(e) {
|
|
||||||
e.stopPropagation()
|
|
||||||
switch (e.keyCode) {
|
|
||||||
case 38:
|
|
||||||
typeof this.innerValue === 'number' && this.up()
|
|
||||||
return
|
|
||||||
case 40:
|
|
||||||
typeof this.innerValue === 'number' && this.down()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
},
|
|
||||||
up() {
|
|
||||||
this.$emit('update:modelValue', parseInt(this.modelValue || 0, 10) + this.step)
|
|
||||||
},
|
|
||||||
down() {
|
|
||||||
let value = parseInt(this.modelValue || 0, 10) - this.step
|
|
||||||
if (value < 0) {
|
|
||||||
value = 0
|
|
||||||
}
|
|
||||||
this.$emit('update:modelValue', value)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user