mirror of https://github.com/halo-dev/halo
feat: post tags support color settings (halo-dev/console#395)
* feat: post tags support color settings * feat: add tag color picker * feat: support choose tag color Co-authored-by: guqing <1484563614@qq.com>pull/3445/head
parent
50e3f8ae94
commit
a57442284e
|
@ -0,0 +1,28 @@
|
||||||
|
<template>
|
||||||
|
<a-tag :color="tag.color" :style="{ color: labelColor }">
|
||||||
|
{{ tag.name }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { isHex, isLight } from '@/utils/colorUtil'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'PostTag',
|
||||||
|
props: {
|
||||||
|
tag: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
labelColor() {
|
||||||
|
const { color } = this.tag || {}
|
||||||
|
if (!color) return 'inherit'
|
||||||
|
if (!isHex(color)) {
|
||||||
|
return 'inherit'
|
||||||
|
}
|
||||||
|
return !isLight(color) ? '#fff' : 'inherit'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -6,6 +6,7 @@ import FilePondUpload from '@/components/Upload/FilePondUpload'
|
||||||
import AttachmentSelectDrawer from './Attachment/AttachmentSelectDrawer'
|
import AttachmentSelectDrawer from './Attachment/AttachmentSelectDrawer'
|
||||||
import AttachmentUploadModal from './Attachment/AttachmentUploadModal'
|
import AttachmentUploadModal from './Attachment/AttachmentUploadModal'
|
||||||
import ReactiveButton from './Button/ReactiveButton'
|
import ReactiveButton from './Button/ReactiveButton'
|
||||||
|
import PostTag from './Post/PostTag'
|
||||||
|
|
||||||
const _components = {
|
const _components = {
|
||||||
Ellipsis,
|
Ellipsis,
|
||||||
|
@ -13,7 +14,8 @@ const _components = {
|
||||||
FilePondUpload,
|
FilePondUpload,
|
||||||
AttachmentSelectDrawer,
|
AttachmentSelectDrawer,
|
||||||
AttachmentUploadModal,
|
AttachmentUploadModal,
|
||||||
ReactiveButton
|
ReactiveButton,
|
||||||
|
PostTag
|
||||||
}
|
}
|
||||||
|
|
||||||
const components = {}
|
const components = {}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
const isLight = color => {
|
||||||
|
if (!isHex(color)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the format of the color, HEX or RGB?
|
||||||
|
let r, g, b, hsp
|
||||||
|
if (color.match(/^rgb/)) {
|
||||||
|
// If HEX --> store the red, green, blue values in separate variables
|
||||||
|
color = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/)
|
||||||
|
|
||||||
|
r = color[1]
|
||||||
|
g = color[2]
|
||||||
|
b = color[3]
|
||||||
|
} else {
|
||||||
|
// If RGB --> Convert it to HEX: http://gist.github.com/983661
|
||||||
|
color = +('0x' + color.slice(1).replace(color.length < 5 && /./g, '$&$&'))
|
||||||
|
|
||||||
|
r = color >> 16
|
||||||
|
g = (color >> 8) & 255
|
||||||
|
b = color & 255
|
||||||
|
}
|
||||||
|
|
||||||
|
// HSP (Highly Sensitive Poo) equation from http://alienryderflex.com/hsp.html
|
||||||
|
hsp = Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b))
|
||||||
|
|
||||||
|
// Using the HSP value, determine whether the color is light or dark
|
||||||
|
return hsp > 127.5
|
||||||
|
}
|
||||||
|
|
||||||
|
const randomHex = () => {
|
||||||
|
return '#' + Math.floor(Math.random() * 16777215).toString(16)
|
||||||
|
}
|
||||||
|
const hexRegExp = /(^#[0-9A-F])/i
|
||||||
|
|
||||||
|
const isHex = color => {
|
||||||
|
return hexRegExp.test(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
const isRgb = color => {
|
||||||
|
return /^rgb/.test(color)
|
||||||
|
}
|
||||||
|
const isHsl = color => {
|
||||||
|
return /^hsl/.test(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { isLight, randomHex, isHex, hexRegExp, isRgb, isHsl }
|
|
@ -201,7 +201,7 @@
|
||||||
<a-tag
|
<a-tag
|
||||||
v-for="(tag, tagIndex) in item.tags"
|
v-for="(tag, tagIndex) in item.tags"
|
||||||
:key="'tag_' + tagIndex"
|
:key="'tag_' + tagIndex"
|
||||||
color="green"
|
:color="tag.color"
|
||||||
style="margin-bottom: 8px"
|
style="margin-bottom: 8px"
|
||||||
>{{ tag.name }}
|
>{{ tag.name }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
|
@ -268,7 +268,7 @@
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span slot="tags" slot-scope="tags">
|
<span slot="tags" slot-scope="tags">
|
||||||
<a-tag v-for="(tag, index) in tags" :key="index" color="green" style="margin-bottom: 8px">
|
<a-tag v-for="(tag, index) in tags" :key="index" :color="tag.color" style="margin-bottom: 8px">
|
||||||
{{ tag.name }}
|
{{ tag.name }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -10,6 +10,13 @@
|
||||||
<a-form-model-item help="* 一般为单个标签页面的标识,最好为英文" label="别名:" prop="slug">
|
<a-form-model-item help="* 一般为单个标签页面的标识,最好为英文" label="别名:" prop="slug">
|
||||||
<a-input v-model="form.model.slug" />
|
<a-input v-model="form.model.slug" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="颜色:" prop="color">
|
||||||
|
<a-input v-model="form.model.color">
|
||||||
|
<template #addonAfter>
|
||||||
|
<verte v-model="form.model.color" model="hex" picker="square" style="cursor: pointer"></verte>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
</a-form-model-item>
|
||||||
<a-form-model-item help="* 在标签页面可展示,需要主题支持" label="封面图:" prop="thumbnail">
|
<a-form-model-item help="* 在标签页面可展示,需要主题支持" label="封面图:" prop="thumbnail">
|
||||||
<a-input v-model="form.model.thumbnail">
|
<a-input v-model="form.model.thumbnail">
|
||||||
<a slot="addonAfter" href="javascript:void(0);" @click="thumbnailDrawer.visible = true">
|
<a slot="addonAfter" href="javascript:void(0);" @click="thumbnailDrawer.visible = true">
|
||||||
|
@ -63,9 +70,7 @@
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<span>{{ tag.postCount }} 篇文章</span>
|
<span>{{ tag.postCount }} 篇文章</span>
|
||||||
</template>
|
</template>
|
||||||
<a-tag color="blue" style="margin-bottom: 8px;cursor:pointer;" @click="form.model = tag"
|
<post-tag :tag="tag" style="margin-bottom: 8px;cursor:pointer;" @click.native="form.model = tag" />
|
||||||
>{{ tag.name }}
|
|
||||||
</a-tag>
|
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
@ -83,9 +88,15 @@
|
||||||
<script>
|
<script>
|
||||||
import { PageView } from '@/layouts'
|
import { PageView } from '@/layouts'
|
||||||
import apiClient from '@/utils/api-client'
|
import apiClient from '@/utils/api-client'
|
||||||
|
import { hexRegExp } from '@/utils/colorUtil'
|
||||||
|
import Verte from 'verte'
|
||||||
|
import 'verte/dist/verte.css'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { PageView },
|
components: {
|
||||||
|
PageView,
|
||||||
|
Verte
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
list: {
|
list: {
|
||||||
|
@ -93,7 +104,9 @@ export default {
|
||||||
loading: false
|
loading: false
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
model: {},
|
model: {
|
||||||
|
color: '#cfd3d7'
|
||||||
|
},
|
||||||
saving: false,
|
saving: false,
|
||||||
errored: false,
|
errored: false,
|
||||||
rules: {
|
rules: {
|
||||||
|
@ -102,7 +115,8 @@ export default {
|
||||||
{ max: 255, message: '* 标签名称的字符长度不能超过 255', trigger: ['change'] }
|
{ max: 255, message: '* 标签名称的字符长度不能超过 255', trigger: ['change'] }
|
||||||
],
|
],
|
||||||
slug: [{ max: 255, message: '* 标签别名的字符长度不能超过 255', trigger: ['change'] }],
|
slug: [{ max: 255, message: '* 标签别名的字符长度不能超过 255', trigger: ['change'] }],
|
||||||
thumbnail: [{ max: 1023, message: '* 封面图链接的字符长度不能超过 1023', trigger: ['change'] }]
|
thumbnail: [{ max: 1023, message: '* 封面图链接的字符长度不能超过 1023', trigger: ['change'] }],
|
||||||
|
color: [{ max: 7, pattern: hexRegExp, message: '仅支持 hex 颜色值' }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
thumbnailDrawer: {
|
thumbnailDrawer: {
|
||||||
|
@ -112,10 +126,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
title() {
|
title() {
|
||||||
if (this.isUpdateMode) {
|
return this.isUpdateMode ? '修改标签' : '添加标签'
|
||||||
return '修改标签'
|
|
||||||
}
|
|
||||||
return '添加标签'
|
|
||||||
},
|
},
|
||||||
isUpdateMode() {
|
isUpdateMode() {
|
||||||
return !!this.form.model.id
|
return !!this.form.model.id
|
||||||
|
@ -138,7 +149,9 @@ export default {
|
||||||
},
|
},
|
||||||
handleDeleteTag(tagId) {
|
handleDeleteTag(tagId) {
|
||||||
apiClient.tag.delete(tagId).finally(() => {
|
apiClient.tag.delete(tagId).finally(() => {
|
||||||
this.form.model = {}
|
this.form.model = {
|
||||||
|
color: '#cfd3d7'
|
||||||
|
}
|
||||||
this.handleListTags()
|
this.handleListTags()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -178,7 +191,9 @@ export default {
|
||||||
if (_this.form.errored) {
|
if (_this.form.errored) {
|
||||||
_this.form.errored = false
|
_this.form.errored = false
|
||||||
} else {
|
} else {
|
||||||
_this.form.model = {}
|
_this.form.model = {
|
||||||
|
color: '#cfd3d7'
|
||||||
|
}
|
||||||
_this.handleListTags()
|
_this.handleListTags()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue