@ -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 @@ |
|||||||
/** |
|
||||||
* @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 @@ |
|||||||
/** |
|
||||||
* @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 @@ |
|||||||
/** |
|
||||||
* @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,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 @@ |
|||||||
<template> |
<script lang="tsx"> |
||||||
<div :class="[`${prefixCls}__header px-2 py-5`, $attrs.class]"> |
import { defineComponent, computed, unref, type ExtractPropTypes } from 'vue'; |
||||||
<BasicTitle :helpMessage="helpMessage" normal> |
import { useDesign } from '/@/hooks/web/useDesign'; |
||||||
<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'; |
|
||||||
import { BasicArrow, BasicTitle } from '/@/components/Basic'; |
import { BasicArrow, BasicTitle } from '/@/components/Basic'; |
||||||
|
|
||||||
const props = { |
const collapseHeaderProps = { |
||||||
prefixCls: { type: String }, |
prefixCls: String, |
||||||
|
title: String, |
||||||
|
show: Boolean, |
||||||
|
canExpan: Boolean, |
||||||
helpMessage: { |
helpMessage: { |
||||||
type: [Array, String] as PropType<string[] | string>, |
type: [Array, String] as PropType<string[] | string>, |
||||||
default: '', |
default: '', |
||||||
}, |
}, |
||||||
title: { type: String }, |
|
||||||
show: { type: Boolean }, |
|
||||||
canExpan: { type: Boolean }, |
|
||||||
}; |
}; |
||||||
|
|
||||||
|
export type CollapseHeaderProps = ExtractPropTypes<typeof collapseHeaderProps>; |
||||||
|
|
||||||
export default defineComponent({ |
export default defineComponent({ |
||||||
components: { BasicArrow, BasicTitle }, |
name: 'CollapseHeader', |
||||||
inheritAttrs: false, |
inheritAttrs: false, |
||||||
props, |
props: collapseHeaderProps, |
||||||
emits: ['expand'], |
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> |
</script> |
||||||
|
@ -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 @@ |
|||||||
import { withInstall } from '/@/utils'; |
import { withInstall } from '/@/utils'; |
||||||
import markDown from './src/Markdown.vue'; |
import markDown from './src/Markdown.vue'; |
||||||
|
import markDownViewer from './src/MarkdownViewer.vue'; |
||||||
|
|
||||||
export const MarkDown = withInstall(markDown); |
export const MarkDown = withInstall(markDown); |
||||||
|
export const MarkdownViewer = withInstall(markDownViewer); |
||||||
export * from './src/typing'; |
export * from './src/typing'; |
||||||
|
@ -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 @@ |
|||||||
|
/** |
||||||
|
* 获取主题类型 深色浅色模式 对应的值 |
||||||
|
* @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'; |
||||||
|
} |
||||||
|
}; |