mirror of
https://gitee.com/fantastic-admin/basic.git
synced 2024-12-02 03:57:37 +08:00
公用组件用 script setup 语法糖重写
This commit is contained in:
parent
86434bbc9b
commit
5934ecc492
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -7,12 +7,6 @@
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Copyright'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
footer {
|
||||
margin: 40px 0 20px 0;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user