@ -1,52 +0,0 @@
@@ -1,52 +0,0 @@
|
||||
# PROJECT: kicc-ui |
||||
# DESCRIPTION: 配置yarn install后清除并从软件包依赖关系中删除不必要的文件 |
||||
# VERSION: 1.0.0 |
||||
# Author: 康来生物科技有限公司-王翔 |
||||
|
||||
# test directories |
||||
test |
||||
tests |
||||
powered-test |
||||
|
||||
# asset directories |
||||
docs |
||||
doc |
||||
website |
||||
images |
||||
assets |
||||
|
||||
# examples |
||||
example |
||||
examples |
||||
|
||||
# code coverage directories |
||||
coverage |
||||
.nyc_output |
||||
|
||||
# build scripts |
||||
Makefile |
||||
Gulpfile.js |
||||
Gruntfile.js |
||||
|
||||
# configs |
||||
appveyor.yml |
||||
circle.yml |
||||
codeship-services.yml |
||||
codeship-steps.yml |
||||
wercker.yml |
||||
.tern-project |
||||
.gitattributes |
||||
.editorconfig |
||||
.*ignore |
||||
.eslintrc |
||||
.jshintrc |
||||
.flowconfig |
||||
.documentup.json |
||||
.yarn-metadata.json |
||||
.travis.yml |
||||
|
||||
# misc |
||||
*.md |
||||
|
||||
!istanbul-reports/lib/html/assets |
||||
!istanbul-api/node_modules/istanbul-reports/lib/html/assets |
@ -1,27 +0,0 @@
@@ -1,27 +0,0 @@
|
||||
/** |
||||
* @program: kicc-ui |
||||
* @description: 解决HMR(模块热部署)循环依赖问题 |
||||
* todo: 目前解决方案直接清除已经导入的模块然后直接热部署,暂时解决Vite循环依赖问题,等以后有更好的解决方案修复,不知道这样写会带来什么问题 |
||||
* @author: entfrm开发团队-王翔 |
||||
* @create: 2022/4/5 |
||||
*/ |
||||
|
||||
import type { Plugin } from 'vite'; |
||||
|
||||
export function configHmrPlugin(): Plugin { |
||||
return { |
||||
name: 'singleHMR', |
||||
handleHotUpdate({ modules, file }) { |
||||
if (file.match(/xml$/)) return []; |
||||
|
||||
modules.forEach((m) => { |
||||
if (!m.url.match(/\.(css|less)/)) { |
||||
m.importedModules = new Set(); |
||||
m.importers = new Set(); |
||||
} |
||||
}); |
||||
|
||||
return modules; |
||||
}, |
||||
}; |
||||
} |
Before Width: | Height: | Size: 272 KiB After Width: | Height: | Size: 254 KiB |
After Width: | Height: | Size: 456 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 155 KiB |
After Width: | Height: | Size: 525 KiB |
After Width: | Height: | Size: 456 KiB |
@ -1,268 +0,0 @@
@@ -1,268 +0,0 @@
|
||||
/** |
||||
* @program: kicc-ui |
||||
* @description: kicc系统相关样式 |
||||
* 在kicc系统中全局调用的样式全部在这里配置 |
||||
* @author: entfrm开发团队-王翔 |
||||
* @create: 2022/4/7 |
||||
*/ |
||||
|
||||
.table-settings { |
||||
& > * { |
||||
margin-right: 12px; |
||||
} |
||||
|
||||
svg { |
||||
width: 1.3em; |
||||
height: 1.3em; |
||||
} |
||||
} |
||||
|
||||
|
||||
// 基础表格样式 |
||||
[data-theme='dark'] { |
||||
.ant-table-tbody > tr:hover.ant-table-row-selected > td, |
||||
.ant-table-tbody > tr.ant-table-row-selected td { |
||||
background-color: #262626; |
||||
} |
||||
|
||||
.@{basic-table-prefix-cls} { |
||||
// [黑暗模式]table顶部插槽多选栏样式 |
||||
.alert { |
||||
background-color: #323232; |
||||
border-color: #424242; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.@{basic-table-prefix-cls} { |
||||
max-width: 100%; |
||||
|
||||
&-row__striped { |
||||
td { |
||||
background-color: @app-content-background; |
||||
} |
||||
} |
||||
|
||||
&-form-container { |
||||
padding: 16px; |
||||
|
||||
.ant-form { |
||||
padding: 12px 10px 6px 10px; |
||||
margin-bottom: 16px; |
||||
background-color: @component-background; |
||||
border-radius: 2px; |
||||
} |
||||
} |
||||
|
||||
.ant-tag { |
||||
margin-right: 0; |
||||
} |
||||
|
||||
.ant-table-wrapper { |
||||
padding: 6px; |
||||
background-color: @component-background; |
||||
border-radius: 2px; |
||||
|
||||
.ant-table-title { |
||||
min-height: 40px; |
||||
padding: 0 0 8px 0 !important; |
||||
} |
||||
|
||||
.ant-table.ant-table-bordered .ant-table-title { |
||||
border: none !important; |
||||
} |
||||
} |
||||
|
||||
.ant-table { |
||||
width: 100%; |
||||
overflow-x: hidden; |
||||
|
||||
&-title { |
||||
display: flex; |
||||
padding: 8px 6px; |
||||
border-bottom: none; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
} |
||||
|
||||
.ant-table-tbody > tr.ant-table-row-selected td { |
||||
background-color: fade(@primary-color, 8%) !important; |
||||
} |
||||
} |
||||
|
||||
.ant-pagination { |
||||
margin: 10px 0 0 0; |
||||
} |
||||
|
||||
.ant-table-footer { |
||||
padding: 0; |
||||
|
||||
.ant-table-wrapper { |
||||
padding: 0; |
||||
} |
||||
|
||||
table { |
||||
border: none !important; |
||||
} |
||||
|
||||
.ant-table-body { |
||||
overflow-x: hidden !important; |
||||
overflow-y: scroll !important; |
||||
} |
||||
|
||||
td { |
||||
padding: 12px 8px; |
||||
} |
||||
|
||||
// [明亮模式]table顶部插槽多选栏样式 |
||||
.alert { |
||||
height: 38px; |
||||
background-color: #f3f3f3; |
||||
border-color: #e3e3e3; |
||||
} |
||||
|
||||
&--inset { |
||||
.ant-table-wrapper { |
||||
padding: 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// 表格头部样式 |
||||
.@{basic-table-header-prefix-cls} { |
||||
&__toolbar { |
||||
flex: 1; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: flex-end; |
||||
|
||||
> * { |
||||
margin-right: 8px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// 表格动作样式 |
||||
.@{basic-table-action-prefix-cls} { |
||||
display: flex; |
||||
align-items: center; |
||||
|
||||
.action-divider { |
||||
display: table; |
||||
} |
||||
|
||||
&.left { |
||||
justify-content: flex-start; |
||||
} |
||||
|
||||
&.center { |
||||
justify-content: center; |
||||
} |
||||
|
||||
&.right { |
||||
justify-content: flex-end; |
||||
} |
||||
|
||||
button { |
||||
display: flex; |
||||
align-items: center; |
||||
|
||||
span { |
||||
margin-left: 0 !important; |
||||
} |
||||
} |
||||
|
||||
button.ant-btn-circle { |
||||
span { |
||||
margin: auto !important; |
||||
} |
||||
} |
||||
|
||||
.ant-divider, |
||||
.ant-divider-vertical { |
||||
margin: 0 2px; |
||||
} |
||||
|
||||
.icon-more { |
||||
transform: rotate(90deg); |
||||
|
||||
svg { |
||||
font-size: 1.1em; |
||||
font-weight: 700; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// 表格设置样式 |
||||
.table-coulmn-drag-icon { |
||||
margin: 0 5px; |
||||
cursor: move; |
||||
} |
||||
.@{basic-column-setting-prefix-cls} { |
||||
&__popover-title { |
||||
position: relative; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
} |
||||
|
||||
&__check-item { |
||||
display: flex; |
||||
align-items: center; |
||||
min-width: 100%; |
||||
padding: 4px 16px 8px 0; |
||||
|
||||
.ant-checkbox-wrapper { |
||||
width: 100%; |
||||
|
||||
&:hover { |
||||
color: @primary-color; |
||||
} |
||||
} |
||||
} |
||||
|
||||
&__fixed-left, |
||||
&__fixed-right { |
||||
color: rgba(0, 0, 0, 0.45); |
||||
cursor: pointer; |
||||
|
||||
&.active, |
||||
&:hover { |
||||
color: @primary-color; |
||||
} |
||||
|
||||
&.disabled { |
||||
color: @disabled-color; |
||||
cursor: not-allowed; |
||||
} |
||||
} |
||||
|
||||
&__fixed-right { |
||||
transform: rotate(180deg); |
||||
} |
||||
|
||||
&__cloumn-list { |
||||
svg { |
||||
width: 1em !important; |
||||
height: 1em !important; |
||||
} |
||||
|
||||
.ant-popover-inner-content { |
||||
// max-height: 360px; |
||||
padding-right: 0; |
||||
padding-left: 0; |
||||
// overflow: auto; |
||||
} |
||||
|
||||
.ant-checkbox-group { |
||||
width: 100%; |
||||
min-width: 260px; |
||||
// flex-wrap: wrap; |
||||
} |
||||
|
||||
.scrollbar { |
||||
height: 220px; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
/** |
||||
* @program: kicc-ui |
||||
* @description: kicc系统相关变量定义 |
||||
* 在kicc系统中全局调用的变量全部在这里配置 |
||||
* @author: entfrm开发团队-王翔 |
||||
* @create: 2022/4/7 |
||||
*/ |
||||
|
||||
// 基础表格变量 |
||||
@basic-table-prefix-cls: ~'@{namespace}-basic-table'; |
||||
@basic-table-header-prefix-cls: ~'@{namespace}-basic-table-header'; |
||||
@basic-table-action-prefix-cls: ~'@{namespace}-basic-table-action'; |
||||
@basic-column-setting-prefix-cls: ~'@{namespace}-basic-column-setting'; |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
@import './vxe.dark.less'; |
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
[data-theme='dark'] .@{vxe-table-prefix-cls} { |
||||
@fontColor: #c9d1d9; |
||||
@bgColor: #151515; |
||||
@borderColor: #606060; |
||||
|
||||
.vxe-cell--item, |
||||
.vxe-cell--title, |
||||
.vxe-cell, |
||||
.vxe-body--expanded-cell { |
||||
color: @fontColor; |
||||
} |
||||
|
||||
.vxe-toolbar { |
||||
background-color: @bgColor; |
||||
} |
||||
|
||||
.vxe-table--render-default .vxe-table--body-wrapper, |
||||
.vxe-table--render-default .vxe-table--footer-wrapper { |
||||
background-color: @bgColor; |
||||
} |
||||
|
||||
// 外边框 |
||||
.vxe-table--render-default .vxe-table--border-line { |
||||
border-color: @borderColor; |
||||
} |
||||
|
||||
// header 下边框 |
||||
.vxe-table .vxe-table--header-wrapper .vxe-table--header-border-line { |
||||
border-bottom-color: @borderColor; |
||||
} |
||||
|
||||
// footer 上边框 |
||||
.vxe-table--render-default .vxe-table--footer-wrapper { |
||||
border-top-color: @borderColor; |
||||
} |
||||
|
||||
// 展开行 边框 |
||||
.vxe-table--render-default .vxe-body--expanded-column { |
||||
border-bottom-color: @borderColor; |
||||
} |
||||
|
||||
// 行斑马纹 |
||||
.vxe-table--render-default .vxe-body--row.row--stripe { |
||||
background-color: #1e1e1e; |
||||
} |
||||
|
||||
// 行hover |
||||
.vxe-table--render-default .vxe-body--row.row--hover { |
||||
background-color: #262626; |
||||
} |
||||
|
||||
// 选中行 |
||||
.vxe-table--render-default .vxe-body--row.row--checked { |
||||
background-color: #44403a; |
||||
|
||||
&.row--hover { |
||||
background-color: #59524b; |
||||
} |
||||
} |
||||
|
||||
.vxe-table--render-default.border--default .vxe-table--header-wrapper, |
||||
.vxe-table--render-default.border--full .vxe-table--header-wrapper, |
||||
.vxe-table--render-default.border--outer .vxe-table--header-wrapper { |
||||
background-color: #1d1d1d; |
||||
} |
||||
|
||||
.vxe-table--render-default.border--default .vxe-body--column, |
||||
.vxe-table--render-default.border--default .vxe-footer--column, |
||||
.vxe-table--render-default.border--default .vxe-header--column, |
||||
.vxe-table--render-default.border--inner .vxe-body--column, |
||||
.vxe-table--render-default.border--inner .vxe-footer--column, |
||||
.vxe-table--render-default.border--inner .vxe-header--column { |
||||
background-image: linear-gradient(#1d1d1d, #1d1d1d); |
||||
} |
||||
|
||||
// 列宽拖动 |
||||
.vxe-header--column .vxe-resizable.is--line:before { |
||||
background-color: #505050; |
||||
} |
||||
|
||||
// checkbox |
||||
.vxe-custom--option .vxe-checkbox--icon:before, |
||||
.vxe-export--panel-column-option .vxe-checkbox--icon:before, |
||||
.vxe-table--filter-option .vxe-checkbox--icon:before, |
||||
.vxe-table--render-default .vxe-cell--checkbox .vxe-checkbox--icon:before { |
||||
background-color: @bgColor; |
||||
border-color: @borderColor; |
||||
} |
||||
|
||||
.vxe-toolbar .vxe-custom--option-wrapper { |
||||
background-color: @bgColor; |
||||
} |
||||
|
||||
.vxe-button { |
||||
background-color: @bgColor; |
||||
border-color: @borderColor; |
||||
} |
||||
|
||||
.vxe-button.type--button:not(.is--disabled):active { |
||||
background-color: @bgColor; |
||||
} |
||||
|
||||
.vxe-toolbar .vxe-custom--wrapper.is--active > .vxe-button { |
||||
background-color: @bgColor; |
||||
} |
||||
|
||||
.vxe-toolbar .vxe-custom--option-wrapper .vxe-custom--footer button { |
||||
color: @fontColor; |
||||
} |
||||
} |
@ -1,42 +1,44 @@
@@ -1,42 +1,44 @@
|
||||
<template> |
||||
<div :class="[`${prefixCls}__header px-2 py-5`, $attrs.class]"> |
||||
<BasicTitle :helpMessage="helpMessage" normal> |
||||
<template v-if="title"> |
||||
{{ title }} |
||||
</template> |
||||
<template v-else> |
||||
<slot name="title"/> |
||||
</template> |
||||
</BasicTitle> |
||||
<div :class="`${prefixCls}__action`"> |
||||
<slot name="action"/> |
||||
<BasicArrow v-if="canExpan" |
||||
up |
||||
:expand="show" |
||||
@click="$emit('expand')" |
||||
/> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script lang="ts"> |
||||
import { defineComponent } from 'vue'; |
||||
<script lang="tsx"> |
||||
import { defineComponent, computed, unref, type ExtractPropTypes } from 'vue'; |
||||
import { useDesign } from '/@/hooks/web/useDesign'; |
||||
import { BasicArrow, BasicTitle } from '/@/components/Basic'; |
||||
|
||||
const props = { |
||||
prefixCls: { type: String }, |
||||
const collapseHeaderProps = { |
||||
prefixCls: String, |
||||
title: String, |
||||
show: Boolean, |
||||
canExpan: Boolean, |
||||
helpMessage: { |
||||
type: [Array, String] as PropType<string[] | string>, |
||||
default: '', |
||||
}, |
||||
title: { type: String }, |
||||
show: { type: Boolean }, |
||||
canExpan: { type: Boolean }, |
||||
}; |
||||
|
||||
export type CollapseHeaderProps = ExtractPropTypes<typeof collapseHeaderProps>; |
||||
|
||||
export default defineComponent({ |
||||
components: { BasicArrow, BasicTitle }, |
||||
name: 'CollapseHeader', |
||||
inheritAttrs: false, |
||||
props, |
||||
props: collapseHeaderProps, |
||||
emits: ['expand'], |
||||
setup(props, { slots, attrs, emit }) { |
||||
const { prefixCls } = useDesign('collapse-container'); |
||||
const _prefixCls = computed(() => props.prefixCls || unref(prefixCls)); |
||||
return () => ( |
||||
<div class={[`${unref(_prefixCls)}__header px-2 py-5`, attrs.class]}> |
||||
<BasicTitle helpMessage={props.helpMessage} normal> |
||||
{slots.title?.() || props.title} |
||||
</BasicTitle> |
||||
|
||||
<div class={`${unref(_prefixCls)}__action`}> |
||||
{slots.action |
||||
? slots.action({ expand: props.show, onClick: () => emit('expand') }) |
||||
: props.canExpan && ( |
||||
<BasicArrow up expand={props.show} onClick={() => emit('expand')} /> |
||||
)} |
||||
</div> |
||||
</div> |
||||
); |
||||
}, |
||||
}); |
||||
</script> |
||||
|
@ -0,0 +1,138 @@
@@ -0,0 +1,138 @@
|
||||
<template> |
||||
<Transfer |
||||
:data-source="getDataSource" |
||||
:filter-option="filterOption" |
||||
:render="(item) => item.title" |
||||
:showSelectAll="showSelectAll" |
||||
:selectedKeys="selectedKeys" |
||||
:targetKeys="getTargetKeys" |
||||
:showSearch="showSearch" |
||||
@change="handleChange" |
||||
/> |
||||
</template> |
||||
|
||||
<script lang="ts"> |
||||
import { computed, defineComponent, watch, ref, unref, watchEffect } from 'vue'; |
||||
import { Transfer } from 'ant-design-vue'; |
||||
import { isFunction } from '/@/utils/is'; |
||||
import { get, omit } from 'lodash-es'; |
||||
import { propTypes } from '/@/utils/propTypes'; |
||||
import { useI18n } from '/@/hooks/web/useI18n'; |
||||
import { TransferDirection, TransferItem } from 'ant-design-vue/lib/transfer'; |
||||
|
||||
export default defineComponent({ |
||||
name: 'ApiTransfer', |
||||
components: { Transfer }, |
||||
props: { |
||||
value: { type: Array as PropType<Array<string>> }, |
||||
api: { |
||||
type: Function as PropType<(arg?: Recordable) => Promise<TransferItem[]>>, |
||||
default: null, |
||||
}, |
||||
params: { type: Object }, |
||||
dataSource: { type: Array as PropType<Array<TransferItem>> }, |
||||
immediate: propTypes.bool.def(true), |
||||
alwaysLoad: propTypes.bool.def(false), |
||||
afterFetch: { type: Function as PropType<Fn> }, |
||||
resultField: propTypes.string.def(''), |
||||
labelField: propTypes.string.def('title'), |
||||
valueField: propTypes.string.def('key'), |
||||
showSearch: { type: Boolean, default: false }, |
||||
disabled: { type: Boolean, default: false }, |
||||
filterOption: { |
||||
type: Function as PropType<(inputValue: string, item: TransferItem) => boolean>, |
||||
}, |
||||
selectedKeys: { type: Array as PropType<Array<string>> }, |
||||
showSelectAll: { type: Boolean, default: false }, |
||||
targetKeys: { type: Array as PropType<Array<string>> }, |
||||
}, |
||||
emits: ['options-change', 'change'], |
||||
setup(props, { attrs, emit }) { |
||||
const _dataSource = ref<TransferItem[]>([]); |
||||
const _targetKeys = ref<string[]>([]); |
||||
const { t } = useI18n(); |
||||
|
||||
const getAttrs = computed(() => { |
||||
return { |
||||
...(!props.api ? { dataSource: unref(_dataSource) } : {}), |
||||
...attrs, |
||||
}; |
||||
}); |
||||
const getDataSource = computed(() => { |
||||
const { labelField, valueField } = props; |
||||
|
||||
return unref(_dataSource).reduce((prev, next: Recordable) => { |
||||
if (next) { |
||||
prev.push({ |
||||
...omit(next, [labelField, valueField]), |
||||
title: next[labelField], |
||||
key: next[valueField], |
||||
}); |
||||
} |
||||
return prev; |
||||
}, [] as TransferItem[]); |
||||
}); |
||||
const getTargetKeys = computed<string[]>(() => { |
||||
if (unref(_targetKeys).length > 0) { |
||||
return unref(_targetKeys); |
||||
} |
||||
if (Array.isArray(props.value)) { |
||||
return props.value; |
||||
} |
||||
if (Array.isArray(props.targetKeys)){ |
||||
return props.targetKeys; |
||||
} |
||||
return []; |
||||
}); |
||||
|
||||
function handleChange(keys: string[], direction: TransferDirection, moveKeys: string[]) { |
||||
_targetKeys.value = keys; |
||||
console.log(direction); |
||||
console.log(moveKeys); |
||||
emit('change', keys); |
||||
} |
||||
|
||||
watchEffect(() => { |
||||
props.immediate && !props.alwaysLoad && fetch(); |
||||
}); |
||||
|
||||
watch( |
||||
() => props.params, |
||||
() => { |
||||
fetch(); |
||||
}, |
||||
{ deep: true }, |
||||
); |
||||
|
||||
async function fetch() { |
||||
const api = props.api; |
||||
if (!api || !isFunction(api)) { |
||||
if (Array.isArray(props.dataSource)) { |
||||
_dataSource.value = props.dataSource; |
||||
} |
||||
return; |
||||
} |
||||
_dataSource.value = []; |
||||
try { |
||||
const res = await api(props.params); |
||||
if (Array.isArray(res)) { |
||||
_dataSource.value = res; |
||||
emitChange(); |
||||
return; |
||||
} |
||||
if (props.resultField) { |
||||
_dataSource.value = get(res, props.resultField) || []; |
||||
} |
||||
emitChange(); |
||||
} catch (error) { |
||||
console.warn(error); |
||||
} finally { |
||||
} |
||||
} |
||||
function emitChange() { |
||||
emit('options-change', unref(getDataSource)); |
||||
} |
||||
return { getTargetKeys, getDataSource, t, getAttrs, handleChange }; |
||||
}, |
||||
}); |
||||
</script> |
@ -1,5 +1,7 @@
@@ -1,5 +1,7 @@
|
||||
import { withInstall } from '/@/utils'; |
||||
import markDown from './src/Markdown.vue'; |
||||
import markDownViewer from './src/MarkdownViewer.vue'; |
||||
|
||||
export const MarkDown = withInstall(markDown); |
||||
export const MarkdownViewer = withInstall(markDownViewer); |
||||
export * from './src/typing'; |
||||
|
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
<template> |
||||
<div id="markdownViewer" ref="viewerRef" :class="$props.class"/> |
||||
</template> |
||||
|
||||
<script lang="ts" setup> |
||||
import { defineProps, onBeforeUnmount, onDeactivated, Ref, ref, unref, watch } from 'vue'; |
||||
import VditorPreview from 'vditor/dist/method.min'; |
||||
import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated'; |
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; |
||||
import { getTheme } from './getTheme'; |
||||
const props = defineProps({ |
||||
value: { type: String }, |
||||
class: { type: String }, |
||||
}); |
||||
const viewerRef = ref<ElRef>(null); |
||||
const vditorPreviewRef = ref(null) as Ref<Nullable<VditorPreview>>; |
||||
const { getDarkMode } = useRootSetting(); |
||||
|
||||
function init() { |
||||
const viewerEl = unref(viewerRef) as HTMLElement; |
||||
vditorPreviewRef.value = VditorPreview.preview(viewerEl, props.value, { |
||||
mode: getTheme(getDarkMode.value, 'content'), |
||||
theme: { |
||||
// 设置内容主题 |
||||
current: getTheme(getDarkMode.value, 'content'), |
||||
}, |
||||
hljs: { |
||||
// 设置代码块主题 |
||||
style: getTheme(getDarkMode.value, 'code'), |
||||
}, |
||||
}); |
||||
} |
||||
watch( |
||||
() => getDarkMode.value, |
||||
(val) => { |
||||
VditorPreview.setContentTheme(getTheme(val, 'content')); |
||||
VditorPreview.setCodeTheme(getTheme(val, 'code')); |
||||
init(); |
||||
}, |
||||
); |
||||
|
||||
watch( |
||||
() => props.value, |
||||
(v, oldValue) => { |
||||
v !== oldValue && init(); |
||||
}, |
||||
); |
||||
|
||||
function destroy() { |
||||
const vditorInstance = unref(vditorPreviewRef); |
||||
if (!vditorInstance) return; |
||||
try { |
||||
vditorInstance?.destroy?.(); |
||||
} catch (error) {} |
||||
vditorPreviewRef.value = null; |
||||
} |
||||
|
||||
onMountedOrActivated(init); |
||||
|
||||
onBeforeUnmount(destroy); |
||||
onDeactivated(destroy); |
||||
</script> |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
/** |
||||
* 获取主题类型 深色浅色模式 对应的值 |
||||
* @param darkModeVal 深色模式值 |
||||
* @param themeMode 主题类型——外观(默认), 内容, 代码块 |
||||
*/ |
||||
export const getTheme = ( |
||||
darkModeVal: 'light' | 'dark' | string, |
||||
themeMode: 'default' | 'content' | 'code' = 'default', |
||||
) => { |
||||
const isDark = darkModeVal === 'dark'; |
||||
switch (themeMode) { |
||||
case 'default': |
||||
return isDark ? 'dark' : 'classic'; |
||||
case 'content': |
||||
return isDark ? 'dark' : 'light'; |
||||
case 'code': |
||||
return isDark ? 'dracula' : 'github'; |
||||
} |
||||
}; |