公用组件用 script setup 语法糖重写

This commit is contained in:
hooray 2021-09-04 11:14:51 +08:00
parent 86434bbc9b
commit 5934ecc492
18 changed files with 656 additions and 719 deletions

View File

@ -4,18 +4,6 @@
</div>
</template>
<script>
export default {
name: 'AbsoluteContainer',
props: {},
data() {
return {}
},
mounted() {},
methods: {}
}
</script>
<style lang="scss" scoped>
.absolute-container {
position: absolute;

View File

@ -5,21 +5,18 @@
</div>
</template>
<script>
<script setup>
import { auth } from '@/util'
import { defineProps } from 'vue'
export default {
name: 'Auth',
props: {
value: {
type: [String, Array],
default: ''
}
},
methods: {
check() {
return auth(this.value)
}
const props = defineProps({
value: {
type: [String, Array],
default: ''
}
})
function check() {
return auth(props.value)
}
</script>

View File

@ -5,21 +5,18 @@
</div>
</template>
<script>
<script setup>
import { authAll } from '@/util'
import { defineProps } from 'vue'
export default {
name: 'AuthAll',
props: {
value: {
type: Array,
default: () => []
}
},
methods: {
check() {
return authAll(this.value)
}
const props = defineProps({
value: {
type: Array,
default: () => []
}
})
function check() {
return authAll(props.value)
}
</script>

View File

@ -8,48 +8,42 @@
</div>
</template>
<script>
export default {
name: 'BatchActionBar',
props: {
data: {
type: Array,
default: () => []
},
selectionData: {
type: Array,
default: () => []
<script setup>
import { defineProps, defineEmits, computed } from 'vue'
const props = defineProps({
data: {
type: Array,
default: () => []
},
selectionData: {
type: Array,
default: () => []
}
})
const emit = defineEmits(['check-all', 'check-null'])
const checkAll = computed({
get: function() {
let flag = false
if (props.data.length != 0 && props.data.length == props.selectionData.length) {
flag = true
}
return flag
},
emits: ['check-all', 'check-null'],
data() {
return {}
},
computed: {
checkAll: {
get: function() {
let flag = false
if (this.data.length != 0 && this.data.length == this.selectionData.length) {
flag = true
}
return flag
},
set: function(newVal) {
newVal ? this.$emit('check-all') : this.$emit('check-null')
}
},
isIndeterminate() {
let flag = false
if (this.selectionData.length > 0 && this.selectionData.length < this.data.length) {
flag = true
}
return flag
}
},
created() {},
mounted() {},
methods: {}
}
set: function(newVal) {
newVal ? emit('check-all') : emit('check-null')
}
})
const isIndeterminate = computed(() => {
let flag = false
if (props.selectionData.length > 0 && props.selectionData.length < props.data.length) {
flag = true
}
return flag
})
</script>
<style lang="scss" scoped>

View File

@ -1,91 +1,88 @@
<template>
<div>
<el-cascader v-model="myValue" :options="options" :props="props" :size="size" :disabled="disabled" clearable filterable />
<el-cascader v-model="myValue" :options="data.options" :props="data.props" :size="size" :disabled="disabled" clearable filterable />
</div>
</template>
<script>
<script setup>
import area from '@/util/area'
import { defineProps, defineEmits, ref, computed } from 'vue'
export default {
name: 'CascaderArea',
const props = defineProps({
// ['', '', '']
modelValue: {
type: Array,
default: () => []
},
size: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:modelValue'])
const data = ref({
options: area,
props: {
// ['', '', '']
modelValue: {
type: Array,
default: () => []
},
size: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
}
},
emits: ['update:modelValue'],
data() {
return {
options: area,
props: {
value: 'code',
label: 'name'
}
}
},
computed: {
myValue: {
// code
get: function() {
const myValue = []
if (this.modelValue.length === 3) {
const [pName, cName, aName] = this.modelValue
area.map(p => {
if (p.name === pName) {
myValue.push(p.code)
p.children.map(c => {
if (c.name === cName) {
myValue.push(c.code)
c.children.map(a => {
if (a.name === aName) {
myValue.push(a.code)
}
})
value: 'code',
label: 'name'
}
})
const myValue = computed({
// code
get: () => {
const myValue = []
if (props.modelValue.length === 3) {
const [pName, cName, aName] = props.modelValue
area.map(p => {
if (p.name === pName) {
myValue.push(p.code)
p.children.map(c => {
if (c.name === cName) {
myValue.push(c.code)
c.children.map(a => {
if (a.name === aName) {
myValue.push(a.code)
}
})
}
})
}
return myValue
},
// code
set: function(value) {
if (value) {
let [pCode, cCode, aCode] = value
area.map(p => {
if (p.code === pCode) {
pCode = p.name
p.children.map(c => {
if (c.code === cCode) {
cCode = c.name
c.children.map(a => {
if (a.code === aCode) {
aCode = a.name
}
})
})
}
return myValue
},
// code
set: value => {
if (value) {
let [pCode, cCode, aCode] = value
area.map(p => {
if (p.code === pCode) {
pCode = p.name
p.children.map(c => {
if (c.code === cCode) {
cCode = c.name
c.children.map(a => {
if (a.code === aCode) {
aCode = a.name
}
})
}
})
this.$emit('update:modelValue', [pCode, cCode, aCode])
} else {
this.$emit('update:modelValue', [])
}
}
})
emit('update:modelValue', [pCode, cCode, aCode])
} else {
emit('update:modelValue', [])
}
}
}
})
</script>
<style lang="scss" scoped>

View File

@ -7,12 +7,6 @@
</footer>
</template>
<script>
export default {
name: 'Copyright'
}
</script>
<style lang="scss" scoped>
footer {
margin: 40px 0 20px 0;

View File

@ -4,7 +4,7 @@
</div>
</template>
<script>
<script setup>
import tinymce from 'tinymce/tinymce'
import TinymceEditor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver/theme'
@ -28,71 +28,66 @@ import 'tinymce/plugins/wordcount'
import 'tinymce/plugins/code'
import 'tinymce/plugins/searchreplace'
export default {
name: 'Editor',
components: {
TinymceEditor
import { defineProps, defineEmits, ref, computed, watch, onMounted } from 'vue'
const props = defineProps({
modelValue: {
type: String,
default: ''
},
props: {
modelValue: {
type: String,
default: ''
},
setting: {
type: Object,
default: () => {}
},
disabled: {
type: Boolean,
default: false
}
setting: {
type: Object,
default: () => {}
},
emits: ['update:modelValue'],
data() {
return {
defaultSetting: {
language_url: 'tinymce/langs/zh_CN.js',
language: 'zh_CN',
skin_url: 'tinymce/skins/ui/oxide',
min_height: 250,
max_height: 600,
selector: 'textarea',
plugins: 'autolink autoresize contextmenu fullscreen hr image imagetools insertdatetime link lists media preview table textcolor wordcount code searchreplace',
toolbar: 'undo redo | formatselect | bold italic strikethrough forecolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | hr link image media table insertdatetime searchreplace removeformat | preview code fullscreen',
branding: false,
menubar: false,
toolbar_mode: 'sliding',
insertdatetime_formats: [
'%Y年%m月%d日',
'%H点%M分%S秒',
'%Y-%m-%d',
'%H:%M:%S'
],
images_upload_handler: (blobInfo, success) => {
const img = 'data:image/jpeg;base64,' + blobInfo.base64()
success(img)
}
},
myValue: this.modelValue
}
},
computed: {
completeSetting() {
return Object.assign(this.defaultSetting, this.setting)
}
},
watch: {
myValue(newValue) {
this.$emit('update:modelValue', newValue)
},
value(newValue) {
this.myValue = newValue
}
},
mounted() {
tinymce.init({})
disabled: {
type: Boolean,
default: false
}
}
})
const emit = defineEmits(['update:modelValue'])
const defaultSetting = ref({
language_url: 'tinymce/langs/zh_CN.js',
language: 'zh_CN',
skin_url: 'tinymce/skins/ui/oxide',
min_height: 250,
max_height: 600,
selector: 'textarea',
plugins: 'autolink autoresize contextmenu fullscreen hr image imagetools insertdatetime link lists media preview table textcolor wordcount code searchreplace',
toolbar: 'undo redo | formatselect | bold italic strikethrough forecolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | hr link image media table insertdatetime searchreplace removeformat | preview code fullscreen',
branding: false,
menubar: false,
toolbar_mode: 'sliding',
insertdatetime_formats: [
'%Y年%m月%d日',
'%H点%M分%S秒',
'%Y-%m-%d',
'%H:%M:%S'
],
images_upload_handler: (blobInfo, success) => {
const img = 'data:image/jpeg;base64,' + blobInfo.base64()
success(img)
}
})
const myValue = ref(props.modelValue)
const completeSetting = computed(() => {
return Object.assign(defaultSetting.value, props.setting)
})
watch(() => myValue.value, newValue => {
emit('update:modelValue', newValue)
})
watch(() => props.modelValue, newValue => {
myValue.value = newValue
})
onMounted(() => {
tinymce.init({})
})
</script>
<style lang="scss" scoped>

View File

@ -24,69 +24,70 @@
</el-upload>
</template>
<script>
export default {
name: 'FileUpload',
props: {
action: {
type: String,
required: true
},
headers: {
type: Object,
default: () => {}
},
data: {
type: Object,
default: () => {}
},
name: {
type: String,
default: 'file'
},
size: {
type: Number,
default: 2
},
max: {
type: Number,
default: 3
},
files: {
type: Array,
default: () => []
},
notip: {
type: Boolean,
default: false
},
ext: {
type: Array,
default: () => ['zip', 'rar']
}
<script setup>
import { defineProps, defineEmits, getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
const props = defineProps({
action: {
type: String,
required: true
},
emits: ['on-success'],
methods: {
beforeUpload(file) {
const fileName = file.name.split('.')
const fileExt = fileName[fileName.length - 1]
const isTypeOk = this.ext.indexOf(fileExt) >= 0
const isSizeOk = file.size / 1024 / 1024 < this.size
if (!isTypeOk) {
this.$message.error(`上传文件只支持 ${ this.ext.join(' / ') } 格式!`)
}
if (!isSizeOk) {
this.$message.error(`上传文件大小不能超过 ${this.size}MB`)
}
return isTypeOk && isSizeOk
},
onExceed() {
this.$message.warning('文件上传超过限制')
},
onSuccess(res, file) {
this.$emit('on-success', res, file)
}
headers: {
type: Object,
default: () => {}
},
data: {
type: Object,
default: () => {}
},
name: {
type: String,
default: 'file'
},
size: {
type: Number,
default: 2
},
max: {
type: Number,
default: 3
},
files: {
type: Array,
default: () => []
},
notip: {
type: Boolean,
default: false
},
ext: {
type: Array,
default: () => ['zip', 'rar']
}
})
const emit = defineEmits(['on-success'])
function beforeUpload(file) {
const fileName = file.name.split('.')
const fileExt = fileName[fileName.length - 1]
const isTypeOk = props.ext.indexOf(fileExt) >= 0
const isSizeOk = file.size / 1024 / 1024 < props.size
if (!isTypeOk) {
proxy.$message.error(`上传文件只支持 ${ props.ext.join(' / ') } 格式!`)
}
if (!isSizeOk) {
proxy.$message.error(`上传文件大小不能超过 ${props.size}MB`)
}
return isTypeOk && isSizeOk
}
function onExceed() {
proxy.$message.warning('文件上传超过限制')
}
function onSuccess(res, file) {
emit('on-success', res, file)
}
</script>

View File

@ -1,43 +1,37 @@
<template>
<div :class="{
'actionbar': true,
'shadow': !isBottom
}" data-fixed-calc-width
>
<div class="actionbar" :class="{'shadow': !data.isBottom}" data-fixed-calc-width>
<slot />
</div>
</template>
<script>
export default {
name: 'FixedActionBar',
data() {
return {
isBottom: true
}
},
mounted() {
this.onScroll()
window.addEventListener('scroll', this.onScroll)
},
unmounted() {
window.removeEventListener('scroll', this.onScroll)
},
methods: {
onScroll() {
// scrollTop
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
// windowHeight
var windowHeight = document.documentElement.clientHeight || document.body.clientHeight
// scrollHeight
var scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight
//
if (Math.ceil(scrollTop + windowHeight) >= scrollHeight) {
this.isBottom = true
} else {
this.isBottom = false
}
}
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const data = ref({
isBottom: true
})
onMounted(() => {
onScroll()
window.addEventListener('scroll', onScroll)
})
onUnmounted(() => {
window.removeEventListener('scroll', onScroll)
})
function onScroll() {
// scrollTop
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
// windowHeight
var windowHeight = document.documentElement.clientHeight || document.body.clientHeight
// scrollHeight
var scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight
//
if (Math.ceil(scrollTop + windowHeight) >= scrollHeight) {
data.value.isBottom = true
} else {
data.value.isBottom = false
}
}
</script>

View File

@ -8,40 +8,31 @@
</el-image>
</template>
<script>
export default {
name: 'ImagePreview',
props: {
src: {
type: String,
required: true
},
width: {
type: [Number, String],
default: ''
},
height: {
type: [Number, String],
default: ''
}
<script setup>
import { defineProps, computed } from 'vue'
const props = defineProps({
src: {
type: String,
required: true
},
data() {
return {
dialogVisible: false
}
width: {
type: [Number, String],
default: ''
},
computed: {
realWidth() {
return typeof this.width == 'string' ? this.width : `${this.width}px`
},
realHeight() {
return typeof this.height == 'string' ? this.height : `${this.height}px`
}
},
created() {},
mounted() {},
methods: {}
}
height: {
type: [Number, String],
default: ''
}
})
const realWidth = computed(() => {
return typeof props.width == 'string' ? props.width : `${props.width}px`
})
const realHeight = computed(() => {
return typeof props.height == 'string' ? props.height : `${props.height}px`
})
</script>
<style lang="scss" scoped>

View File

@ -31,9 +31,9 @@
</div>
</div>
</div>
<div v-show="progress.percent" class="progress" :style="`width:${width}px;height:${height}px;`">
<el-image :src="progress.preview" :style="`width:${width}px;height:${height}px;`" fit="fill" />
<el-progress type="circle" :width="Math.min(width, height) * 0.8" :percentage="progress.percent" />
<div v-show="data.progress.percent" class="progress" :style="`width:${width}px;height:${height}px;`">
<el-image :src="data.progress.preview" :style="`width:${width}px;height:${height}px;`" fit="fill" />
<el-progress type="circle" :width="Math.min(width, height) * 0.8" :percentage="data.progress.percent" />
</div>
</el-upload>
<div v-if="!notip" class="el-upload__tip">
@ -41,103 +41,107 @@
<el-alert :title="`上传图片支持 ${ ext.join(' / ') } 格式,且图片大小不超过 ${ size }MB建议图片尺寸为 ${width}*${height}`" type="info" show-icon :closable="false" />
</div>
</div>
<el-image-viewer v-if="imageViewerVisible" :url-list="[url]" @close="() => {imageViewerVisible = false}" />
<el-image-viewer v-if="data.imageViewerVisible" :url-list="[url]" @close="previewClose" />
</div>
</template>
<script>
export default {
name: 'ImageUpload',
props: {
action: {
type: String,
required: true
},
headers: {
type: Object,
default: () => {}
},
data: {
type: Object,
default: () => {}
},
name: {
type: String,
default: 'file'
},
url: {
type: String,
default: ''
},
size: {
type: Number,
default: 2
},
width: {
type: Number,
default: 150
},
height: {
type: Number,
default: 150
},
placeholder: {
type: String,
default: ''
},
notip: {
type: Boolean,
default: false
},
ext: {
type: Array,
default: () => ['jpg', 'png', 'gif', 'bmp']
}
<script setup>
import { defineProps, defineEmits, ref, getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
const props = defineProps({
action: {
type: String,
required: true
},
emits: ['update:url', 'on-success'],
data() {
return {
imageViewerVisible: false,
progress: {
preview: '',
percent: 0
}
}
headers: {
type: Object,
default: () => {}
},
methods: {
//
remove() {
this.$emit('update:url', '')
},
beforeUpload(file) {
const fileName = file.name.split('.')
const fileExt = fileName[fileName.length - 1]
const isTypeOk = this.ext.indexOf(fileExt) >= 0
const isSizeOk = file.size / 1024 / 1024 < this.size
if (!isTypeOk) {
this.$message.error(`上传图片只支持 ${ this.ext.join(' / ') } 格式!`)
}
if (!isSizeOk) {
this.$message.error(`上传图片大小不能超过 ${this.size}MB`)
}
if (isTypeOk && isSizeOk) {
this.progress.preview = URL.createObjectURL(file)
}
return isTypeOk && isSizeOk
},
onProgress(file) {
this.progress.percent = ~~file.percent
if (this.progress.percent == 100) {
setTimeout(() => {
this.progress.preview = ''
this.progress.percent = 0
}, 1000)
}
},
onSuccess(res) {
this.$emit('on-success', res)
}
data: {
type: Object,
default: () => {}
},
name: {
type: String,
default: 'file'
},
url: {
type: String,
default: ''
},
size: {
type: Number,
default: 2
},
width: {
type: Number,
default: 150
},
height: {
type: Number,
default: 150
},
placeholder: {
type: String,
default: ''
},
notip: {
type: Boolean,
default: false
},
ext: {
type: Array,
default: () => ['jpg', 'png', 'gif', 'bmp']
}
})
const emit = defineEmits(['update:url', 'on-success'])
const data = ref({
imageViewerVisible: false,
progress: {
preview: '',
percent: 0
}
})
//
function previewClose() {
data.value.imageViewerVisible = false
}
//
function remove() {
emit('update:url', '')
}
function beforeUpload(file) {
const fileName = file.name.split('.')
const fileExt = fileName[fileName.length - 1]
const isTypeOk = props.ext.indexOf(fileExt) >= 0
const isSizeOk = file.size / 1024 / 1024 < props.size
if (!isTypeOk) {
proxy.$message.error(`上传图片只支持 ${ props.ext.join(' / ') } 格式!`)
}
if (!isSizeOk) {
proxy.$message.error(`上传图片大小不能超过 ${props.size}MB`)
}
if (isTypeOk && isSizeOk) {
data.value.progress.preview = URL.createObjectURL(file)
}
return isTypeOk && isSizeOk
}
function onProgress(file) {
data.value.progress.percent = ~~file.percent
if (data.value.progress.percent == 100) {
setTimeout(() => {
data.value.progress.preview = ''
data.value.progress.percent = 0
}, 1000)
}
}
function onSuccess(res) {
emit('on-success', res)
}
</script>

View File

@ -35,9 +35,9 @@
<div class="image-slot" :style="`width:${width}px;height:${height}px;`">
<i class="el-icon-plus" />
</div>
<div v-show="progress.percent" class="progress" :style="`width:${width}px;height:${height}px;`">
<el-image :src="progress.preview" :style="`width:${width}px;height:${height}px;`" fit="fill" />
<el-progress type="circle" :width="Math.min(width, height) * 0.8" :percentage="progress.percent" />
<div v-show="data.progress.percent" class="progress" :style="`width:${width}px;height:${height}px;`">
<el-image :src="data.progress.preview" :style="`width:${width}px;height:${height}px;`" fit="fill" />
<el-progress type="circle" :width="Math.min(width, height) * 0.8" :percentage="data.progress.percent" />
</div>
</el-upload>
<div v-if="!notip" class="el-upload__tip">
@ -45,124 +45,128 @@
<el-alert :title="`上传图片支持 ${ ext.join(' / ') } 格式,单张图片大小不超过 ${ size }MB建议图片尺寸为 ${width}*${height},且图片数量不超过 ${ max } 张`" type="info" show-icon :closable="false" />
</div>
</div>
<el-image-viewer v-if="imageViewerVisible" :url-list="url" :initial-index="dialogImageIndex" @close="() => {imageViewerVisible = false}" />
<el-image-viewer v-if="data.imageViewerVisible" :url-list="url" :initial-index="data.dialogImageIndex" @close="previewClose" />
</div>
</template>
<script>
export default {
name: 'ImagesUpload',
props: {
action: {
type: String,
required: true
},
headers: {
type: Object,
default: () => {}
},
data: {
type: Object,
default: () => {}
},
name: {
type: String,
default: 'file'
},
url: {
type: Array,
default: () => []
},
max: {
type: Number,
default: 3
},
size: {
type: Number,
default: 2
},
width: {
type: Number,
default: 150
},
height: {
type: Number,
default: 150
},
placeholder: {
type: String,
default: ''
},
notip: {
type: Boolean,
default: false
},
ext: {
type: Array,
default: () => ['jpg', 'png', 'gif', 'bmp']
}
<script setup>
import { defineProps, defineEmits, ref, getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
const props = defineProps({
action: {
type: String,
required: true
},
emits: ['update:url', 'on-success'],
data() {
return {
dialogImageIndex: 0,
imageViewerVisible: false,
progress: {
preview: '',
percent: 0
}
}
headers: {
type: Object,
default: () => {}
},
methods: {
//
preview(index) {
this.dialogImageIndex = index
this.imageViewerVisible = true
},
//
remove(index) {
let url = this.url
url.splice(index, 1)
this.$emit('update:url', url)
},
//
move(index, type) {
let url = this.url
if (type == 'left' && index != 0) {
url[index] = url.splice(index - 1, 1, url[index])[0]
}
if (type == 'right' && index != url.length - 1) {
url[index] = url.splice(index + 1, 1, url[index])[0]
}
this.$emit('update:url', url)
},
beforeUpload(file) {
const fileName = file.name.split('.')
const fileExt = fileName[fileName.length - 1]
const isTypeOk = this.ext.indexOf(fileExt) >= 0
const isSizeOk = file.size / 1024 / 1024 < this.size
if (!isTypeOk) {
this.$message.error(`上传图片只支持 ${ this.ext.join(' / ') } 格式!`)
}
if (!isSizeOk) {
this.$message.error(`上传图片大小不能超过 ${this.size}MB`)
}
if (isTypeOk && isSizeOk) {
this.progress.preview = URL.createObjectURL(file)
}
return isTypeOk && isSizeOk
},
onProgress(file) {
this.progress.percent = ~~file.percent
if (this.progress.percent == 100) {
this.progress.preview = ''
this.progress.percent = 0
}
},
onSuccess(res) {
this.$emit('on-success', res)
}
data: {
type: Object,
default: () => {}
},
name: {
type: String,
default: 'file'
},
url: {
type: Array,
default: () => []
},
max: {
type: Number,
default: 3
},
size: {
type: Number,
default: 2
},
width: {
type: Number,
default: 150
},
height: {
type: Number,
default: 150
},
placeholder: {
type: String,
default: ''
},
notip: {
type: Boolean,
default: false
},
ext: {
type: Array,
default: () => ['jpg', 'png', 'gif', 'bmp']
}
})
const emit = defineEmits(['update:url', 'on-success'])
const data = ref({
dialogImageIndex: 0,
imageViewerVisible: false,
progress: {
preview: '',
percent: 0
}
})
//
function preview(index) {
data.value.dialogImageIndex = index
data.value.imageViewerVisible = true
}
//
function previewClose() {
data.value.imageViewerVisible = false
}
//
function remove(index) {
let url = props.url
url.splice(index, 1)
emit('update:url', url)
}
//
function move(index, type) {
let url = props.url
if (type == 'left' && index != 0) {
url[index] = url.splice(index - 1, 1, url[index])[0]
}
if (type == 'right' && index != url.length - 1) {
url[index] = url.splice(index + 1, 1, url[index])[0]
}
emit('update:url', url)
}
function beforeUpload(file) {
const fileName = file.name.split('.')
const fileExt = fileName[fileName.length - 1]
const isTypeOk = props.ext.indexOf(fileExt) >= 0
const isSizeOk = file.size / 1024 / 1024 < props.size
if (!isTypeOk) {
proxy.$message.error(`上传图片只支持 ${ props.ext.join(' / ') } 格式!`)
}
if (!isSizeOk) {
proxy.$message.error(`上传图片大小不能超过 ${props.size}MB`)
}
if (isTypeOk && isSizeOk) {
data.value.progress.preview = URL.createObjectURL(file)
}
return isTypeOk && isSizeOk
}
function onProgress(file) {
data.value.progress.percent = ~~file.percent
if (data.value.progress.percent == 100) {
data.value.progress.preview = ''
data.value.progress.percent = 0
}
}
function onSuccess(res) {
emit('on-success', res)
}
</script>

View File

@ -12,20 +12,19 @@
</div>
</template>
<script>
export default {
name: 'PageHeader',
props: {
title: {
type: String,
required: true
},
content: {
type: String,
default: ''
}
<script setup>
import { defineProps } from 'vue'
defineProps({
title: {
type: String,
required: true
},
content: {
type: String,
default: ''
}
}
})
</script>
<style lang="scss" scoped>

View File

@ -8,39 +8,34 @@
>
<div v-if="title" class="title-container">{{ title }}</div>
<slot />
<div v-if="collaspeData" class="collaspe" title="展开" @click="uncollaspe">
<div v-if="collaspeData" class="collaspe" title="展开" @click="unCollaspe">
<i class="el-icon-arrow-down" />
</div>
</div>
</template>
<script>
export default {
name: 'PageMain',
props: {
title: {
type: String,
default: ''
},
collaspe: {
type: Boolean,
default: false
},
height: {
type: String,
default: ''
}
<script setup>
import { defineProps, ref } from 'vue'
const props = defineProps({
title: {
type: String,
default: ''
},
data() {
return {
collaspeData: this.collaspe
}
collaspe: {
type: Boolean,
default: false
},
methods: {
uncollaspe() {
this.collaspeData = false
}
height: {
type: String,
default: ''
}
})
const collaspeData = ref(props.collaspe)
function unCollaspe() {
collaspeData.value = false
}
</script>
@ -61,7 +56,7 @@ export default {
text-align: center;
font-size: 24px;
color: #ccc;
text-shadow: 0 0 1px #000;
text-shadow: 0 0 1px #fff;
background: linear-gradient(to bottom, transparent, #fff);
cursor: pointer;
transition: 0.3s;

View File

@ -20,25 +20,24 @@
</div>
</template>
<script>
export default {
name: 'Result',
props: {
type: {
type: String,
validator: val => ['success', 'warning', 'error'].includes(val),
required: true
},
title: {
type: String,
required: true
},
desc: {
type: String,
default: ''
}
<script setup>
import { defineProps } from 'vue'
defineProps({
type: {
type: String,
validator: val => ['success', 'warning', 'error'].includes(val),
required: true
},
title: {
type: String,
required: true
},
desc: {
type: String,
default: ''
}
}
})
</script>
<style lang="scss" scoped>

View File

@ -7,39 +7,31 @@
</div>
</template>
<script>
export default {
name: 'SearchBar',
props: {
showMore: {
type: Boolean,
default: false
},
unfold: {
type: Boolean,
default: false
}
<script setup>
import { defineProps, defineEmits, ref, watch } from 'vue'
const props = defineProps({
showMore: {
type: Boolean,
default: false
},
emits: ['toggle'],
data() {
return {
isUnfold: !this.unfold
}
},
watch: {
unfold: {
handler() {
this.toggle()
},
immediate: true
}
},
methods: {
toggle() {
this.isUnfold = !this.isUnfold
this.$emit('toggle', this.isUnfold)
}
unfold: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['toggle'])
const isUnfold = ref(!props.unfold)
watch(() => props.unfold, () => toggle(), {
immediate: true
})
function toggle() {
isUnfold.value = !isUnfold.value
emit('toggle', isUnfold.value)
}
</script>

View File

@ -1,57 +1,55 @@
<template>
<i v-if="name.indexOf('el-icon-') === 0" :class="name" />
<i v-if="name.indexOf('el-icon-') === 0 || name.indexOf('ri-') === 0" class="svg-icon" :style="transformStyle" :class="name" />
<svg v-else class="svg-icon" :style="transformStyle" aria-hidden="true">
<use :xlink:href="`#icon-${name}`" />
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
name: {
type: String,
required: true
},
flip: {
type: String,
validator(value) {
return ['', 'horizontal', 'vertical', 'both'].includes(value)
},
default: ''
},
rotate: {
type: Number,
validator(value) {
return value >= 0 && value <= 360
},
default: 0
}
<script setup>
import { defineProps, computed } from 'vue'
const props = defineProps({
name: {
type: String,
required: true
},
computed: {
transformStyle() {
let style = []
if (this.flip != '') {
switch (this.flip) {
case 'horizontal':
style.push('rotateY(180deg)')
break
case 'vertical':
style.push('rotateX(180deg)')
break
case 'both':
style.push('rotateX(180deg)')
style.push('rotateY(180deg)')
break
}
}
if (this.rotate != 0) {
style.push(`rotate(${this.rotate}deg)`)
}
return `transform: ${style.join(' ')};`
flip: {
type: String,
validator(value) {
return ['', 'horizontal', 'vertical', 'both'].includes(value)
},
default: ''
},
rotate: {
type: Number,
validator(value) {
return value >= 0 && value <= 360
},
default: 0
}
})
const transformStyle = computed(() => {
let style = []
if (props.flip != '') {
switch (props.flip) {
case 'horizontal':
style.push('rotateY(180deg)')
break
case 'vertical':
style.push('rotateX(180deg)')
break
case 'both':
style.push('rotateX(180deg)')
style.push('rotateY(180deg)')
break
}
}
}
if (props.rotate != 0) {
style.push(`rotate(${props.rotate}deg)`)
}
return `transform: ${style.join(' ')};`
})
</script>
<style scoped>

View File

@ -7,42 +7,40 @@
</div>
</template>
<script>
export default {
name: 'Trend',
props: {
value: {
type: String,
required: true
},
type: {
type: String,
validator: val => ['up', 'down'].includes(val),
default: 'up'
},
prefix: {
type: String,
default: ''
},
suffix: {
type: String,
default: ''
},
reverse: {
type: Boolean,
default: false
}
<script setup>
import { defineProps, computed } from 'vue'
const props = defineProps({
value: {
type: String,
required: true
},
computed: {
isUp() {
let isUp = this.type === 'up'
if (this.reverse) {
isUp = !isUp
}
return isUp
}
type: {
type: String,
validator: val => ['up', 'down'].includes(val),
default: 'up'
},
prefix: {
type: String,
default: ''
},
suffix: {
type: String,
default: ''
},
reverse: {
type: Boolean,
default: false
}
}
})
const isUp = computed(() => {
let isUp = props.type === 'up'
if (props.reverse) {
isUp = !isUp
}
return isUp
})
</script>
<style lang="scss" scoped>