feat: 🎸 v0.0.4发布
This commit is contained in:
133
src/components/Avatars/index.vue
Normal file
133
src/components/Avatars/index.vue
Normal file
@@ -0,0 +1,133 @@
|
||||
<template>
|
||||
<div class="avatars-wrap">
|
||||
<template v-if="tooltip">
|
||||
<el-tooltip
|
||||
v-for="(item, $index) in avatarsData"
|
||||
:key="$index"
|
||||
:content="item.text"
|
||||
effect="dark"
|
||||
placement="top"
|
||||
>
|
||||
<div :class="showAvatar ? 'avatars-item-img' : ['avatars-item', `avatars-${item.type || 'default'}`]">
|
||||
<el-avatar v-if="showAvatar" :size="40" :src="item.url">
|
||||
<img :src="require('@/assets/img/avatar.png')">
|
||||
</el-avatar>
|
||||
<span v-else>{{ item.text.substr(0, 1) }}</span>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<div v-if="max && data.length - max > 0" :class="['avatars-item', 'avatars-item-img']">
|
||||
<span>+{{ data.length - max }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div
|
||||
v-for="(item, $index) in avatarsData"
|
||||
:key="$index"
|
||||
:class="showAvatar ? 'avatars-item-img' : ['avatars-item', `avatars-${item.type || 'default'}`]"
|
||||
>
|
||||
<el-avatar v-if="showAvatar" :size="40" :src="item.url">
|
||||
<img :src="require('@/assets/img/avatar.png')">
|
||||
</el-avatar>
|
||||
<span v-else>{{ item.text.substr(0, 1) }}</span>
|
||||
</div>
|
||||
<div v-if="max && data.length - max > 0" :class="['avatars-item', 'avatars-item-img']">
|
||||
<span>+{{ data.length - max }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed } from 'vue'
|
||||
import { deepClone } from '@/utils'
|
||||
import { DataConfig } from './types'
|
||||
export default defineComponent({
|
||||
name: 'Avatars',
|
||||
props: {
|
||||
// 展示的数据
|
||||
data: {
|
||||
type: Array as PropType<DataConfig[]>,
|
||||
default: () => []
|
||||
},
|
||||
// 最大展示数量
|
||||
max: {
|
||||
type: Number as PropType<number>,
|
||||
default: 0
|
||||
},
|
||||
// 是否使用头像
|
||||
showAvatar: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
},
|
||||
// 是否显示完整名称
|
||||
tooltip: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const avatarsData = computed(() => {
|
||||
if (props.max) {
|
||||
if (props.data.length <= props.max) {
|
||||
return props.data
|
||||
} else {
|
||||
const data = deepClone(props.data).splice(0, props.max)
|
||||
return data
|
||||
}
|
||||
} else {
|
||||
return props.data
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
avatarsData
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.avatars-wrap {
|
||||
display: flex;
|
||||
.avatars-item {
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #fff;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
background: #2d8cf0;
|
||||
}
|
||||
.avatars-item-img {
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
.el-avatar--circle {
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
}
|
||||
.avatars-item-img + .avatars-item-img {
|
||||
margin-left: -12px;
|
||||
}
|
||||
.avatars-item + .avatars-item {
|
||||
margin-left: -12px;
|
||||
}
|
||||
.avatars-default {
|
||||
color: #bae7ff;
|
||||
background: #096dd9;
|
||||
}
|
||||
.avatars-success {
|
||||
color: #f6ffed;
|
||||
background: #52c41a;
|
||||
}
|
||||
.avatars-danger {
|
||||
color: #fff1f0;
|
||||
background: #f5222d;
|
||||
}
|
||||
.avatars-warning {
|
||||
color: #fffbe6;
|
||||
background: #faad14;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
5
src/components/Avatars/types.ts
Normal file
5
src/components/Avatars/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface DataConfig {
|
||||
text: string
|
||||
type?: string
|
||||
url?: string
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
class="detail__content"
|
||||
:style="contentStyleObj"
|
||||
>
|
||||
<el-row>
|
||||
<el-row type="flex">
|
||||
<el-col
|
||||
v-for="(item, $index) in schema"
|
||||
:key="$index"
|
||||
@@ -192,6 +192,9 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
.detail__content {
|
||||
@{deep}(.el-row) {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.detail__content--flex {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
|
||||
69
src/components/Highlight/index.vue
Normal file
69
src/components/Highlight/index.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed, h } from 'vue'
|
||||
export default defineComponent({
|
||||
name: 'Highlight',
|
||||
props: {
|
||||
tag: {
|
||||
type: String as PropType<string>,
|
||||
default: 'span'
|
||||
},
|
||||
keys: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => []
|
||||
},
|
||||
color: {
|
||||
type: String as PropType<string>,
|
||||
default: '#2d8cf0'
|
||||
}
|
||||
},
|
||||
emits: ['click'],
|
||||
setup(props, { emit }) {
|
||||
const keyNodes = computed(() => {
|
||||
return props.keys.map(key => {
|
||||
return h('span', {
|
||||
onClick: () => {
|
||||
emit('click', key)
|
||||
},
|
||||
style: {
|
||||
color: props.color,
|
||||
cursor: 'pointer'
|
||||
}
|
||||
}, key)
|
||||
})
|
||||
})
|
||||
|
||||
function parseText(text: string) {
|
||||
props.keys.forEach((key, index) => {
|
||||
const regexp = new RegExp(key, 'g')
|
||||
text = text.replace(regexp, `{{${index}}}`)
|
||||
})
|
||||
return text.split(/{{|}}/)
|
||||
}
|
||||
|
||||
return {
|
||||
keyNodes,
|
||||
parseText
|
||||
}
|
||||
},
|
||||
render(props: any) {
|
||||
if (!props.$slots.default) return null
|
||||
const node = props.$slots.default()[0].children
|
||||
if (!node) {
|
||||
console.warn('Highlight组件的插槽必须要是文本')
|
||||
return props.$slots.default()[0]
|
||||
}
|
||||
const textArray = props.parseText(node)
|
||||
const regexp = /^[0-9]*$/
|
||||
const nodes = textArray.map((t: any) => {
|
||||
if (regexp.test(t)) {
|
||||
return props.keyNodes[Math.floor(t)] || t
|
||||
}
|
||||
return t
|
||||
})
|
||||
return h(props.tag, nodes)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, watch, PropType, computed } from 'vue'
|
||||
import { appStore } from '_p/index/store/modules/app'
|
||||
import { appStore } from '_@/store/modules/app'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Logo',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { computed, ref, unref, ComponentInternalInstance, getCurrentInstance } from 'vue'
|
||||
|
||||
import { tagsViewStore, PAGE_LAYOUT_KEY } from '_p/index/store/modules/tagsView'
|
||||
import { tagsViewStore, PAGE_LAYOUT_KEY } from '_@/store/modules/tagsView'
|
||||
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-tooltip placement="bottom" :content="isFullscreen ? '退出全屏' : '全屏'">
|
||||
<div style="height: 100%;" class="screenfull-svg" @click="click">
|
||||
<div id="screenfull-container" style="height: 100%;" class="screenfull-svg" @click="click">
|
||||
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" />
|
||||
</div>
|
||||
</el-tooltip>
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, ref } from 'vue'
|
||||
import { appStore } from '_p/index/store/modules/app'
|
||||
import { appStore } from '_@/store/modules/app'
|
||||
export default defineComponent({
|
||||
name: 'Setting',
|
||||
setup() {
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, PropType } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { permissionStore } from '_p/index/store/modules/permission'
|
||||
import { appStore } from '_p/index/store/modules/app'
|
||||
import { permissionStore } from '_@/store/modules/permission'
|
||||
import { appStore } from '_@/store/modules/app'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import SiderItem from './SiderItem.vue'
|
||||
import variables from '@/styles/variables.less'
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
import ScrollPane from './ScrollPane.vue'
|
||||
import path from 'path'
|
||||
import { defineComponent, ref, unref, computed, watch, onMounted, nextTick } from 'vue'
|
||||
import { tagsViewStore } from '_p/index/store/modules/tagsView'
|
||||
import { permissionStore } from '_p/index/store/modules/permission'
|
||||
import { tagsViewStore } from '_@/store/modules/tagsView'
|
||||
import { permissionStore } from '_@/store/modules/permission'
|
||||
import { useRouter } from 'vue-router'
|
||||
import type { RouteLocationNormalizedLoaded, RouteRecordRaw } from 'vue-router'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-dropdown class="avatar-container" trigger="hover">
|
||||
<div>
|
||||
<div id="user-container">
|
||||
<div class="avatar-wrapper">
|
||||
<img :src="require('@/assets/img/avatar.png')" class="user-avatar">
|
||||
<span class="name-item">管理员</span>
|
||||
@@ -21,11 +21,11 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { resetRouter } from '_p/index/router'
|
||||
import { resetRouter } from '_@/router'
|
||||
import wsCache from '@/cache'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { tagsViewStore } from '_p/index/store/modules/tagsView'
|
||||
import { appStore } from '_p/index/store/modules/app'
|
||||
import { tagsViewStore } from '_@/store/modules/tagsView'
|
||||
import { appStore } from '_@/store/modules/app'
|
||||
export default defineComponent({
|
||||
name: 'UserInfo',
|
||||
setup() {
|
||||
|
||||
Reference in New Issue
Block a user