ElementPlus Form一些简单的组件整合 #
将datePicker,一个时间点,在年/月/日的开始时间、结束时间,分别绑定在两个属性上 #
用法:
<WddDatePickerRange
v-model:start="searchModel.startTime"
v-model:end="searchModel.endTime"
clearable
value-format="YYYY-MM-DD HH:mm:ss"
/>
<WddDatePickerRange
v-model:start="searchModel.startTime"
v-model:end="searchModel.endTime"
clearable
value-format="YYYY-MM-DD HH:mm:ss"
/>
组件代码:
<script lang="ts" setup>
import dayjs from 'dayjs'
type DateValue = string | Date | number
const props = defineProps<{
start?: DateValue
end?: DateValue
valueFormat?: string
type?: 'year' | 'month' | 'date' | 'week'
}>()
const emit = defineEmits<IEmit>()
interface IEmit {
(event: 'update:start', value: typeof props.start): void
(event: 'update:end', value: typeof props.end): void
}
const DateModel = computed({
get: () => props.start,
set: (value) => {
if (value ?? dayjs(value).isValid()) {
const time = dayjs(value)
const start = time.startOf(props.type || 'date')
const end = time.endOf(props.type || 'date')
emit('update:start', props.valueFormat === undefined ? start.toDate() : start.format(props.valueFormat))
emit('update:end', props.valueFormat === undefined ? end.toDate() : end.format(props.valueFormat))
}
else {
emit('update:start', value)
emit('update:end', value)
}
},
})
</script>
<template>
<el-date-picker
v-model="DateModel"
:value-format="valueFormat"
:type="type"
/>
</template>
<style lang="scss" scoped>
</style>
<script lang="ts" setup>
import dayjs from 'dayjs'
type DateValue = string | Date | number
const props = defineProps<{
start?: DateValue
end?: DateValue
valueFormat?: string
type?: 'year' | 'month' | 'date' | 'week'
}>()
const emit = defineEmits<IEmit>()
interface IEmit {
(event: 'update:start', value: typeof props.start): void
(event: 'update:end', value: typeof props.end): void
}
const DateModel = computed({
get: () => props.start,
set: (value) => {
if (value ?? dayjs(value).isValid()) {
const time = dayjs(value)
const start = time.startOf(props.type || 'date')
const end = time.endOf(props.type || 'date')
emit('update:start', props.valueFormat === undefined ? start.toDate() : start.format(props.valueFormat))
emit('update:end', props.valueFormat === undefined ? end.toDate() : end.format(props.valueFormat))
}
else {
emit('update:start', value)
emit('update:end', value)
}
},
})
</script>
<template>
<el-date-picker
v-model="DateModel"
:value-format="valueFormat"
:type="type"
/>
</template>
<style lang="scss" scoped>
</style>
将datePicker(range类型)分别绑定在两个属性上,而不是绑定在一个值(数组)上 #
用法:
<WddDateRangePicker
v-model:start="form.beginDate"
v-model:end="form.endDate"
type="daterange"
size="large"
value-format="YYYY-MM-DD HH:mm:ss"
range-separator="~"
start-placeholder="开始日期"
end-placeholder="结束日期"
clearable
/>
<WddDateRangePicker
v-model:start="form.beginDate"
v-model:end="form.endDate"
type="daterange"
size="large"
value-format="YYYY-MM-DD HH:mm:ss"
range-separator="~"
start-placeholder="开始日期"
end-placeholder="结束日期"
clearable
/>
组件代码:
<script lang="ts" setup>
type DateValue = string | Date | number
const props = defineProps<{
start?: DateValue
end?: DateValue
}>()
const emit = defineEmits<IEmit>()
interface IEmit {
(event: 'update:start', value: typeof props.start): void
(event: 'update:end', value: typeof props.end): void
}
const DateModel = computed({
get: () => [props.start, props.end],
set: (value) => {
emit('update:start', value?.[0])
emit('update:end', value?.[1])
},
})
</script>
<template>
<el-date-picker
v-model="DateModel"
/>
</template>
<style lang="scss" scoped>
</style>
<script lang="ts" setup>
type DateValue = string | Date | number
const props = defineProps<{
start?: DateValue
end?: DateValue
}>()
const emit = defineEmits<IEmit>()
interface IEmit {
(event: 'update:start', value: typeof props.start): void
(event: 'update:end', value: typeof props.end): void
}
const DateModel = computed({
get: () => [props.start, props.end],
set: (value) => {
emit('update:start', value?.[0])
emit('update:end', value?.[1])
},
})
</script>
<template>
<el-date-picker
v-model="DateModel"
/>
</template>
<style lang="scss" scoped>
</style>
把 ‘a,b,c’ 这种形式的,绑定到多选组件上 #
用法:
<WddSelectMultiString v-if="![null, undefined].includes(row?.zone)" v-model="row.zone" placeholder="请选择" clearable collapse-tags>
<el-option
v-for="(value, key) in zoneMap"
:key="key"
:label="value"
:value="value"
/>
</WddSelectMultiString>
<WddSelectMultiString v-if="![null, undefined].includes(row?.zone)" v-model="row.zone" placeholder="请选择" clearable collapse-tags>
<el-option
v-for="(value, key) in zoneMap"
:key="key"
:label="value"
:value="value"
/>
</WddSelectMultiString>
组件代码:
<script lang="ts" setup>
const props = defineProps<{
modelValue: string
}>()
const emit = defineEmits<IEmit>()
interface IEmit {
(event: 'update:modelValue', value: typeof props.modelValue): void
}
const model = computed({
get: () => (props.modelValue === '' ? [] : props.modelValue.split(',')),
set: (value) => {
if (Array.isArray(value))
emit('update:modelValue', value.join(','))
},
})
</script>
<template>
<el-select v-model="model" multiple>
<slot />
</el-select>
</template>
<style lang="scss" scoped>
</style>
<script lang="ts" setup>
const props = defineProps<{
modelValue: string
}>()
const emit = defineEmits<IEmit>()
interface IEmit {
(event: 'update:modelValue', value: typeof props.modelValue): void
}
const model = computed({
get: () => (props.modelValue === '' ? [] : props.modelValue.split(',')),
set: (value) => {
if (Array.isArray(value))
emit('update:modelValue', value.join(','))
},
})
</script>
<template>
<el-select v-model="model" multiple>
<slot />
</el-select>
</template>
<style lang="scss" scoped>
</style>
在view模式下使用el-image来展示图片的上传 #
用法:
``
组件代码:
```vue
<script lang="ts" setup>
import type { UploadProps } from 'element-plus/es'
const props = defineProps<{
fileList?: any
}>()
const emit = defineEmits<IEmit>()
interface IEmit {
(event: 'update:fileList', value: typeof props.fileList): void
}
const fileListModel = computed({
get: () => props.fileList,
set: value => emit('update:fileList', value),
})
const onPreview: UploadProps['onPreview'] = (uploadFile) => {
if (uploadFile.url)
download('channeldredging', uploadFile.url, uploadFile.name)
}
const pictureUrls = ref<Record<string, string>>({})
watch(() => props.fileList, (val) => {
if (!val) {
fileListModel.value = []
return
}
val.forEach(async (file: any) => {
pictureUrls.value = {}
if (!file.url)
return
const suffix = file.url?.split('.').pop()
const isPicture = ['jpg', 'png'].includes(suffix as string)
if (isPicture)
pictureUrls.value[file.url] = file.url // 这里本意是想对图片url进行处理的
})
}, {
immediate: true,
})
</script>
<template>
<el-upload
v-model:file-list="fileListModel" class="dr-upload" multiple drag action="#"
:auto-upload="false" :limit="10"
v-bind="$attrs"
>
<i class="upload-icon">
<div class="i-t-file-upload" />
</i>
<div class="el-upload__text">
<span>点击或将文件拖拽到这里上传</span>
<div class="tip">
支持扩展名:.jpg, .png
</div>
</div>
<template #tip>
<div class="dr-upload-file-list">
<div v-for="(file, index) in fileListModel" :key="index">
<el-image
v-if="pictureUrls[file.url]"
style="height: 100px"
:src="pictureUrls[file.url]"
hide-on-click-modal
:preview-src-list="fileListModel.map((item: any) => pictureUrls[item.url])"
:initial-index="index"
fit="cover"
/>
<el-link v-else w-fit :underline="false" @click="onPreview(file)">
<el-icon mr1>
<Link />
</el-icon>{{ file.name }}
</el-link>
</div>
</div>
</template>
</el-upload>
</template>
<style lang="scss" scoped>
.dr-upload-file-list {
display: none;
}
</style>
``
组件代码:
```vue
<script lang="ts" setup>
import type { UploadProps } from 'element-plus/es'
const props = defineProps<{
fileList?: any
}>()
const emit = defineEmits<IEmit>()
interface IEmit {
(event: 'update:fileList', value: typeof props.fileList): void
}
const fileListModel = computed({
get: () => props.fileList,
set: value => emit('update:fileList', value),
})
const onPreview: UploadProps['onPreview'] = (uploadFile) => {
if (uploadFile.url)
download('channeldredging', uploadFile.url, uploadFile.name)
}
const pictureUrls = ref<Record<string, string>>({})
watch(() => props.fileList, (val) => {
if (!val) {
fileListModel.value = []
return
}
val.forEach(async (file: any) => {
pictureUrls.value = {}
if (!file.url)
return
const suffix = file.url?.split('.').pop()
const isPicture = ['jpg', 'png'].includes(suffix as string)
if (isPicture)
pictureUrls.value[file.url] = file.url // 这里本意是想对图片url进行处理的
})
}, {
immediate: true,
})
</script>
<template>
<el-upload
v-model:file-list="fileListModel" class="dr-upload" multiple drag action="#"
:auto-upload="false" :limit="10"
v-bind="$attrs"
>
<i class="upload-icon">
<div class="i-t-file-upload" />
</i>
<div class="el-upload__text">
<span>点击或将文件拖拽到这里上传</span>
<div class="tip">
支持扩展名:.jpg, .png
</div>
</div>
<template #tip>
<div class="dr-upload-file-list">
<div v-for="(file, index) in fileListModel" :key="index">
<el-image
v-if="pictureUrls[file.url]"
style="height: 100px"
:src="pictureUrls[file.url]"
hide-on-click-modal
:preview-src-list="fileListModel.map((item: any) => pictureUrls[item.url])"
:initial-index="index"
fit="cover"
/>
<el-link v-else w-fit :underline="false" @click="onPreview(file)">
<el-icon mr1>
<Link />
</el-icon>{{ file.name }}
</el-link>
</div>
</div>
</template>
</el-upload>
</template>
<style lang="scss" scoped>
.dr-upload-file-list {
display: none;
}
</style>