Commit 7db0c5c49f23a4ab4958b3f73d47516deafa6166

Authored by vben
1 parent 10cd4fcd

fix: add an example of markdown embedded in the form #138

CHANGELOG.zh_CN.md
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 4
5 - 新增 `v-ripple`水波纹指令 5 - 新增 `v-ripple`水波纹指令
6 - 新增左侧菜单混合模式 6 - 新增左侧菜单混合模式
  7 +- 新增 markdown 嵌入表单内示例
7 8
8 ### 🐛 Bug Fixes 9 ### 🐛 Bug Fixes
9 10
src/components/Container/src/ScrollContainer.vue
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 :wrapClass="`scrollbar__wrap`" 4 :wrapClass="`scrollbar__wrap`"
5 :viewClass="`scrollbar__view`" 5 :viewClass="`scrollbar__view`"
6 class="scroll-container" 6 class="scroll-container"
  7 + v-bind="$attrs"
7 > 8 >
8 <slot /> 9 <slot />
9 </Scrollbar> 10 </Scrollbar>
src/components/Markdown/src/index.vue
@@ -2,14 +2,25 @@ @@ -2,14 +2,25 @@
2 <div class="markdown" ref="wrapRef" /> 2 <div class="markdown" ref="wrapRef" />
3 </template> 3 </template>
4 <script lang="ts"> 4 <script lang="ts">
5 - import { defineComponent, ref, onMounted, unref, onUnmounted, nextTick, watchEffect } from 'vue'; 5 + import {
  6 + defineComponent,
  7 + ref,
  8 + onMounted,
  9 + unref,
  10 + onUnmounted,
  11 + nextTick,
  12 + // watch,
  13 + computed,
  14 + } from 'vue';
6 import Vditor from 'vditor'; 15 import Vditor from 'vditor';
7 import 'vditor/dist/index.css'; 16 import 'vditor/dist/index.css';
8 17
9 import { propTypes } from '/@/utils/propTypes'; 18 import { propTypes } from '/@/utils/propTypes';
  19 + import { useLocale } from '/@/hooks/web/useLocale';
10 20
  21 + type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
11 export default defineComponent({ 22 export default defineComponent({
12 - emits: ['update:value'], 23 + emits: ['change'],
13 props: { 24 props: {
14 height: propTypes.number.def(360), 25 height: propTypes.number.def(360),
15 value: propTypes.string.def(''), 26 value: propTypes.string.def(''),
@@ -19,17 +30,42 @@ @@ -19,17 +30,42 @@
19 const vditorRef = ref<Nullable<Vditor>>(null); 30 const vditorRef = ref<Nullable<Vditor>>(null);
20 const initedRef = ref(false); 31 const initedRef = ref(false);
21 32
  33 + const lang = ref<Lang>();
  34 +
  35 + const { getLang } = useLocale();
  36 +
  37 + const getCurrentLang = computed((): 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' => {
  38 + switch (unref(getLang)) {
  39 + case 'en':
  40 + lang.value = 'en_US';
  41 + break;
  42 + case 'ja':
  43 + lang.value = 'ja_JP';
  44 + break;
  45 + case 'ko':
  46 + lang.value = 'ko_KR';
  47 + break;
  48 + default:
  49 + lang.value = 'zh_CN';
  50 + }
  51 + return lang.value;
  52 + });
22 function init() { 53 function init() {
23 const wrapEl = unref(wrapRef); 54 const wrapEl = unref(wrapRef);
24 if (!wrapEl) return; 55 if (!wrapEl) return;
25 const bindValue = { ...attrs, ...props }; 56 const bindValue = { ...attrs, ...props };
26 vditorRef.value = new Vditor(wrapEl, { 57 vditorRef.value = new Vditor(wrapEl, {
  58 + lang: unref(getCurrentLang),
27 mode: 'sv', 59 mode: 'sv',
28 preview: { 60 preview: {
29 actions: [], 61 actions: [],
30 }, 62 },
31 input: (v) => { 63 input: (v) => {
32 - emit('update:value', v); 64 + // emit('update:value', v);
  65 + emit('change', v);
  66 + },
  67 + blur: () => {
  68 + unref(vditorRef)?.setValue(props.value);
33 }, 69 },
34 ...bindValue, 70 ...bindValue,
35 cache: { 71 cache: {
@@ -39,14 +75,20 @@ @@ -39,14 +75,20 @@
39 initedRef.value = true; 75 initedRef.value = true;
40 } 76 }
41 77
42 - watchEffect(() => {  
43 - nextTick(() => {  
44 - const vditor = unref(vditorRef);  
45 - if (unref(initedRef) && props.value && vditor) {  
46 - vditor.setValue(props.value);  
47 - }  
48 - });  
49 - }); 78 + // watch(
  79 + // () => props.value,
  80 + // () => {
  81 + // nextTick(() => {
  82 + // const vditor = unref(vditorRef);
  83 + // if (unref(initedRef) && props.value && vditor) {
  84 + // vditor.setValue(props.value);
  85 + // }
  86 + // });
  87 + // },
  88 + // {
  89 + // immediate: true,
  90 + // }
  91 + // );
50 92
51 onMounted(() => { 93 onMounted(() => {
52 nextTick(() => { 94 nextTick(() => {
src/components/Scrollbar/index.ts
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 import { withInstall } from '../util'; 5 import { withInstall } from '../util';
6 6
7 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; 7 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
8 -export const Scrollbar = createAsyncComponent(() => import('./src/Scrollbar')); 8 +export const Scrollbar = createAsyncComponent(() => import('./src/index.vue'));
9 9
10 withInstall(Scrollbar); 10 withInstall(Scrollbar);
11 11
src/components/Scrollbar/src/Bar.tsx deleted 100644 → 0
1 -import type { PropType } from 'vue';  
2 -  
3 -import { renderThumbStyle, BAR_MAP } from './util';  
4 -import { defineComponent, computed, unref, inject, Ref, reactive, ref, onBeforeUnmount } from 'vue';  
5 -import { on, off } from '/@/utils/domUtils';  
6 -  
7 -export default defineComponent({  
8 - name: 'Bar',  
9 - props: {  
10 - vertical: {  
11 - type: Boolean as PropType<boolean>,  
12 - default: false,  
13 - },  
14 - size: String as PropType<string>,  
15 - move: Number as PropType<number>,  
16 - },  
17 - setup(props) {  
18 - const thumbRef = ref<Nullable<HTMLDivElement>>(null);  
19 - const elRef = ref<Nullable<HTMLDivElement>>(null);  
20 - const commonState = reactive<Indexable>({});  
21 - const getBarRef = computed(() => {  
22 - return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'];  
23 - });  
24 - const parentElRef = inject('scroll-bar-wrap') as Ref<Nullable<HTMLDivElement>>;  
25 -  
26 - function clickThumbHandler(e: any) {  
27 - const { ctrlKey, button, currentTarget } = e;  
28 - // prevent click event of right button  
29 - if (ctrlKey || button === 2 || !currentTarget) {  
30 - return;  
31 - }  
32 - startDrag(e);  
33 - const bar = unref(getBarRef);  
34 - commonState[bar.axis] =  
35 - currentTarget[bar.offset] -  
36 - (e[bar.client as keyof typeof e] - currentTarget.getBoundingClientRect()[bar.direction]);  
37 - }  
38 -  
39 - function clickTrackHandler(e: any) {  
40 - const bar = unref(getBarRef);  
41 - const offset = Math.abs(e.target.getBoundingClientRect()[bar.direction] - e[bar.client]);  
42 - const thumbEl = unref(thumbRef) as any;  
43 - const parentEl = unref(parentElRef) as any;  
44 - const el = unref(elRef) as any;  
45 - if (!thumbEl || !el || !parentEl) return;  
46 - const thumbHalf = thumbEl[bar.offset] / 2;  
47 - const thumbPositionPercentage = ((offset - thumbHalf) * 100) / el[bar.offset];  
48 - parentEl[bar.scroll] = (thumbPositionPercentage * parentEl[bar.scrollSize]) / 100;  
49 - }  
50 -  
51 - function startDrag(e: Event) {  
52 - e.stopImmediatePropagation();  
53 - commonState.cursorDown = true;  
54 -  
55 - on(document, 'mousemove', mouseMoveDocumentHandler);  
56 - on(document, 'mouseup', mouseUpDocumentHandler);  
57 - document.onselectstart = () => false;  
58 - }  
59 -  
60 - function mouseMoveDocumentHandler(e: any) {  
61 - if (commonState.cursorDown === false) return;  
62 - const bar = unref(getBarRef);  
63 - const prevPage = commonState[bar.axis];  
64 - const el = unref(elRef) as any;  
65 - const parentEl = unref(parentElRef) as any;  
66 - const thumbEl = unref(thumbRef) as any;  
67 - if (!prevPage || !el || !thumbEl || !parentEl) return;  
68 - const rect = el.getBoundingClientRect() as any;  
69 - const offset = (rect[bar.direction] - e[bar.client]) * -1;  
70 - const thumbClickPosition = thumbEl[bar.offset] - prevPage;  
71 - const thumbPositionPercentage = ((offset - thumbClickPosition) * 100) / el[bar.offset];  
72 -  
73 - parentEl[bar.scroll] = (thumbPositionPercentage * parentEl[bar.scrollSize]) / 100;  
74 - }  
75 -  
76 - function mouseUpDocumentHandler() {  
77 - const bar = unref(getBarRef);  
78 - commonState.cursorDown = false;  
79 - commonState[bar.axis] = 0;  
80 - off(document, 'mousemove', mouseMoveDocumentHandler);  
81 - document.onselectstart = null;  
82 - }  
83 -  
84 - onBeforeUnmount(() => {  
85 - off(document, 'mouseup', mouseUpDocumentHandler);  
86 - });  
87 - return () => {  
88 - const bar = unref(getBarRef);  
89 - const { size, move } = props;  
90 - return (  
91 - <div  
92 - class={['scrollbar__bar', 'is-' + bar.key]}  
93 - onMousedown={clickTrackHandler}  
94 - ref={elRef}  
95 - >  
96 - <div  
97 - ref={thumbRef}  
98 - class="scrollbar__thumb"  
99 - onMousedown={clickThumbHandler}  
100 - style={renderThumbStyle({ size, move, bar })}  
101 - />  
102 - </div>  
103 - );  
104 - };  
105 - },  
106 -});  
src/components/Scrollbar/src/Scrollbar.tsx deleted 100644 → 0
1 -import { addResizeListener, removeResizeListener } from '/@/utils/event/resizeEvent';  
2 -import scrollbarWidth from '/@/utils/scrollbarWidth';  
3 -import { toObject } from './util';  
4 -import Bar from './Bar';  
5 -import { isString } from '/@/utils/is';  
6 -import {  
7 - defineComponent,  
8 - PropType,  
9 - unref,  
10 - reactive,  
11 - ref,  
12 - provide,  
13 - onMounted,  
14 - nextTick,  
15 - onBeforeUnmount,  
16 -} from 'vue';  
17 -import { getSlot } from '/@/utils/helper/tsxHelper';  
18 -import './index.less';  
19 -import { useExpose } from '/@/hooks/core/useExpose';  
20 -import { ScrollbarType } from './types';  
21 -  
22 -export default defineComponent({  
23 - name: 'Scrollbar',  
24 - props: {  
25 - native: Boolean as PropType<boolean>,  
26 - wrapStyle: {  
27 - type: Object as PropType<any>,  
28 - },  
29 - wrapClass: { type: String as PropType<string>, required: false },  
30 - viewClass: { type: String as PropType<string> },  
31 - viewStyle: { type: Object as PropType<any> },  
32 - noresize: Boolean as PropType<boolean>,  
33 - tag: {  
34 - type: String as PropType<string>,  
35 - default: 'div',  
36 - },  
37 - },  
38 - setup(props, { slots }) {  
39 - const resizeRef = ref<Nullable<HTMLDivElement>>(null);  
40 - const wrapElRef = ref<Nullable<HTMLDivElement>>(null);  
41 - provide('scroll-bar-wrap', wrapElRef);  
42 - const state = reactive({  
43 - sizeWidth: '0',  
44 - sizeHeight: '0',  
45 - moveX: 0,  
46 - moveY: 0,  
47 - });  
48 -  
49 - function handleScroll() {  
50 - const warpEl = unref(wrapElRef);  
51 - if (!warpEl) return;  
52 - const { scrollTop, scrollLeft, clientHeight, clientWidth } = warpEl;  
53 -  
54 - state.moveY = (scrollTop * 100) / clientHeight;  
55 - state.moveX = (scrollLeft * 100) / clientWidth;  
56 - }  
57 - function update() {  
58 - const warpEl = unref(wrapElRef);  
59 - if (!warpEl) return;  
60 - const { scrollHeight, scrollWidth, clientHeight, clientWidth } = warpEl;  
61 - const heightPercentage = (clientHeight * 100) / scrollHeight;  
62 - const widthPercentage = (clientWidth * 100) / scrollWidth;  
63 -  
64 - state.sizeHeight = heightPercentage < 100 ? heightPercentage + '%' : '';  
65 - state.sizeWidth = widthPercentage < 100 ? widthPercentage + '%' : '';  
66 - }  
67 -  
68 - onMounted(() => {  
69 - useExpose<ScrollbarType>({  
70 - wrap: unref(wrapElRef),  
71 - });  
72 - const { native, noresize } = props;  
73 - const resizeEl = unref(resizeRef);  
74 - const warpEl = unref(wrapElRef);  
75 - if (native || !resizeEl || !warpEl) return;  
76 - nextTick(update);  
77 - if (!noresize) {  
78 - addResizeListener(resizeEl, update);  
79 - addResizeListener(warpEl, update);  
80 - }  
81 - });  
82 - onBeforeUnmount(() => {  
83 - const { native, noresize } = props;  
84 - const resizeEl = unref(resizeRef);  
85 - const warpEl = unref(wrapElRef);  
86 - if (native || !resizeEl || !warpEl) return;  
87 - if (!noresize) {  
88 - removeResizeListener(resizeEl, update);  
89 - removeResizeListener(warpEl, update);  
90 - }  
91 - });  
92 - return () => {  
93 - const { native, tag, viewClass, viewStyle, wrapClass, wrapStyle } = props;  
94 - let style: any = wrapStyle;  
95 - const gutter = scrollbarWidth();  
96 -  
97 - if (gutter) {  
98 - const gutterWith = `-${gutter}px`;  
99 - const gutterStyle = `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`;  
100 -  
101 - if (Array.isArray(wrapStyle)) {  
102 - style = toObject(wrapStyle);  
103 - style.marginRight = style.marginBottom = gutterWith;  
104 - } else if (isString(wrapStyle)) {  
105 - style += gutterStyle;  
106 - } else {  
107 - style = gutterStyle;  
108 - }  
109 - }  
110 -  
111 - const Tag = tag as any;  
112 - const view = (  
113 - <Tag class={['scrollbar__view', viewClass]} style={viewStyle} ref={resizeRef}>  
114 - {getSlot(slots)}  
115 - </Tag>  
116 - );  
117 - const wrap = (  
118 - <div  
119 - ref={wrapElRef}  
120 - style={style}  
121 - onScroll={handleScroll}  
122 - class={[wrapClass, 'scrollbar__wrap', gutter ? '' : 'scrollbar__wrap--hidden-default']}  
123 - >  
124 - {[view]}  
125 - </div>  
126 - );  
127 - let nodes: any[] = [];  
128 - const { moveX, sizeWidth, moveY, sizeHeight } = state;  
129 - if (!native) {  
130 - nodes = [  
131 - wrap,  
132 - /* eslint-disable */  
133 - <Bar move={moveX} size={sizeWidth}></Bar>,  
134 - <Bar vertical move={moveY} size={sizeHeight}></Bar>,  
135 - ];  
136 - } else {  
137 - nodes = [  
138 - <div ref="wrap" class={[wrapClass, 'scrollbar__wrap']} style={style}>  
139 - {[view]}  
140 - </div>,  
141 - ];  
142 - }  
143 - return <div class="scrollbar">{nodes}</div>;  
144 - };  
145 - },  
146 -});  
src/components/Scrollbar/src/bar.ts 0 → 100644
  1 +import {
  2 + defineComponent,
  3 + h,
  4 + computed,
  5 + ref,
  6 + getCurrentInstance,
  7 + onUnmounted,
  8 + inject,
  9 + Ref,
  10 +} from 'vue';
  11 +import { on, off } from '/@/utils/domUtils';
  12 +
  13 +import { renderThumbStyle, BAR_MAP } from './util';
  14 +
  15 +export default defineComponent({
  16 + name: 'Bar',
  17 +
  18 + props: {
  19 + vertical: Boolean,
  20 + size: String,
  21 + move: Number,
  22 + },
  23 +
  24 + setup(props) {
  25 + const instance = getCurrentInstance();
  26 + const thumb = ref<any>(null);
  27 + const wrap = inject('scroll-bar-wrap', {} as Ref<Nullable<HTMLElement>>) as any;
  28 + const bar = computed(() => {
  29 + return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'];
  30 + });
  31 + const barStore = ref<Indexable>({});
  32 + const cursorDown = ref<any>(null);
  33 + const clickThumbHandler = (e: any) => {
  34 + // prevent click event of right button
  35 + if (e.ctrlKey || e.button === 2) {
  36 + return;
  37 + }
  38 + startDrag(e);
  39 + barStore.value[bar.value.axis] =
  40 + e.currentTarget[bar.value.offset] -
  41 + (e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]);
  42 + };
  43 +
  44 + const clickTrackHandler = (e: any) => {
  45 + const offset = Math.abs(
  46 + e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]
  47 + );
  48 + const thumbHalf = thumb.value[bar.value.offset] / 2;
  49 + const thumbPositionPercentage =
  50 + ((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset];
  51 +
  52 + wrap.value[bar.value.scroll] =
  53 + (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
  54 + };
  55 + const startDrag = (e: any) => {
  56 + e.stopImmediatePropagation();
  57 + cursorDown.value = true;
  58 + on(document, 'mousemove', mouseMoveDocumentHandler);
  59 + on(document, 'mouseup', mouseUpDocumentHandler);
  60 + document.onselectstart = () => false;
  61 + };
  62 +
  63 + const mouseMoveDocumentHandler = (e: any) => {
  64 + if (cursorDown.value === false) return;
  65 + const prevPage = barStore.value[bar.value.axis];
  66 +
  67 + if (!prevPage) return;
  68 +
  69 + const offset =
  70 + (instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) *
  71 + -1;
  72 + const thumbClickPosition = thumb.value[bar.value.offset] - prevPage;
  73 + const thumbPositionPercentage =
  74 + ((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset];
  75 + wrap.value[bar.value.scroll] =
  76 + (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
  77 + };
  78 +
  79 + function mouseUpDocumentHandler() {
  80 + cursorDown.value = false;
  81 + barStore.value[bar.value.axis] = 0;
  82 + off(document, 'mousemove', mouseMoveDocumentHandler);
  83 + document.onselectstart = null;
  84 + }
  85 +
  86 + onUnmounted(() => {
  87 + off(document, 'mouseup', mouseUpDocumentHandler);
  88 + });
  89 +
  90 + return () =>
  91 + h(
  92 + 'div',
  93 + {
  94 + class: ['scrollbar__bar', 'is-' + bar.value.key],
  95 + onMousedown: clickTrackHandler,
  96 + },
  97 + h('div', {
  98 + ref: thumb,
  99 + class: 'scrollbar__thumb',
  100 + onMousedown: clickThumbHandler,
  101 + style: renderThumbStyle({
  102 + size: props.size,
  103 + move: props.move,
  104 + bar: bar.value,
  105 + }),
  106 + })
  107 + );
  108 + },
  109 +});
src/components/Scrollbar/src/index.less deleted 100644 → 0
1 -.scrollbar {  
2 - position: relative;  
3 - overflow: hidden;  
4 -  
5 - &__wrap {  
6 - height: 100%;  
7 - overflow: scroll;  
8 -  
9 - &--hidden-default {  
10 - scrollbar-width: none;  
11 -  
12 - &::-webkit-scrollbar {  
13 - width: 0;  
14 - height: 0;  
15 - }  
16 - }  
17 - }  
18 -  
19 - &__thumb {  
20 - position: relative;  
21 - display: block;  
22 - width: 0;  
23 - height: 0;  
24 - cursor: pointer;  
25 - background-color: rgba(144, 147, 153, 0.3);  
26 - border-radius: inherit;  
27 - transition: 0.3s background-color;  
28 -  
29 - &:hover {  
30 - background-color: rgba(144, 147, 153, 0.5);  
31 - }  
32 - }  
33 -  
34 - &__bar {  
35 - position: absolute;  
36 - right: 2px;  
37 - bottom: 2px;  
38 - z-index: 1;  
39 - border-radius: 4px;  
40 - opacity: 0;  
41 - -webkit-transition: opacity 80ms ease;  
42 - transition: opacity 80ms ease;  
43 -  
44 - &.is-vertical {  
45 - top: 2px;  
46 - width: 5px;  
47 -  
48 - & > div {  
49 - width: 100%;  
50 - }  
51 - }  
52 -  
53 - &.is-horizontal {  
54 - left: 2px;  
55 - height: 5px;  
56 -  
57 - & > div {  
58 - height: 100%;  
59 - }  
60 - }  
61 - }  
62 -}  
63 -  
64 -.scrollbar:active > .scrollbar__bar,  
65 -.scrollbar:focus > .scrollbar__bar,  
66 -.scrollbar:hover > .scrollbar__bar {  
67 - opacity: 1;  
68 - transition: opacity 180ms ease;  
69 -}  
src/components/Scrollbar/src/index.vue 0 → 100644
  1 +<template>
  2 + <div class="scrollbar">
  3 + <div
  4 + ref="wrap"
  5 + :class="[wrapClass, 'scrollbar__wrap', native ? '' : 'scrollbar__wrap--hidden-default']"
  6 + :style="style"
  7 + @scroll="handleScroll"
  8 + >
  9 + <component :is="tag" ref="resize" :class="['scrollbar__view', viewClass]" :style="viewStyle">
  10 + <slot></slot>
  11 + </component>
  12 + </div>
  13 + <template v-if="!native">
  14 + <bar :move="moveX" :size="sizeWidth" />
  15 + <bar vertical :move="moveY" :size="sizeHeight" />
  16 + </template>
  17 + </div>
  18 +</template>
  19 +<script lang="ts">
  20 + import { addResizeListener, removeResizeListener } from '/@/utils/event/resizeEvent';
  21 +
  22 + import { toObject } from './util';
  23 + import {
  24 + defineComponent,
  25 + ref,
  26 + onMounted,
  27 + onBeforeUnmount,
  28 + nextTick,
  29 + provide,
  30 + computed,
  31 + } from 'vue';
  32 + import Bar from './bar';
  33 +
  34 + export default defineComponent({
  35 + name: 'Scrollbar',
  36 + components: { Bar },
  37 + props: {
  38 + native: {
  39 + type: Boolean,
  40 + default: false,
  41 + },
  42 + wrapStyle: {
  43 + type: [String, Array],
  44 + default: '',
  45 + },
  46 + wrapClass: {
  47 + type: [String, Array],
  48 + default: '',
  49 + },
  50 + viewClass: {
  51 + type: [String, Array],
  52 + default: '',
  53 + },
  54 + viewStyle: {
  55 + type: [String, Array],
  56 + default: '',
  57 + },
  58 + noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能
  59 + tag: {
  60 + type: String,
  61 + default: 'div',
  62 + },
  63 + },
  64 + setup(props) {
  65 + const sizeWidth = ref('0');
  66 + const sizeHeight = ref('0');
  67 + const moveX = ref(0);
  68 + const moveY = ref(0);
  69 + const wrap = ref<any>(null);
  70 + const resize = ref<any>(null);
  71 +
  72 + provide('scroll-bar-wrap', wrap);
  73 +
  74 + const handleScroll = () => {
  75 + if (!props.native) {
  76 + moveY.value = (wrap.value.scrollTop * 100) / wrap.value.clientHeight;
  77 + moveX.value = (wrap.value.scrollLeft * 100) / wrap.value.clientWidth;
  78 + }
  79 + };
  80 +
  81 + const update = () => {
  82 + if (!wrap.value) return;
  83 +
  84 + const heightPercentage = (wrap.value.clientHeight * 100) / wrap.value.scrollHeight;
  85 + const widthPercentage = (wrap.value.clientWidth * 100) / wrap.value.scrollWidth;
  86 +
  87 + sizeHeight.value = heightPercentage < 100 ? heightPercentage + '%' : '';
  88 + sizeWidth.value = widthPercentage < 100 ? widthPercentage + '%' : '';
  89 + };
  90 +
  91 + onMounted(() => {
  92 + if (props.native) return;
  93 + nextTick(update);
  94 + !props.noresize && addResizeListener(resize.value, update);
  95 + });
  96 +
  97 + onBeforeUnmount(() => {
  98 + if (props.native) return;
  99 + !props.noresize && removeResizeListener(resize.value, update);
  100 + });
  101 + const style = computed(() => {
  102 + let style: any = props.wrapStyle;
  103 + if (Array.isArray(props.wrapStyle)) {
  104 + style = toObject(props.wrapStyle);
  105 + }
  106 + return style;
  107 + });
  108 + return {
  109 + moveX,
  110 + moveY,
  111 + sizeWidth,
  112 + sizeHeight,
  113 + style,
  114 + wrap,
  115 + resize,
  116 + update,
  117 + handleScroll,
  118 + };
  119 + },
  120 + });
  121 +</script>
  122 +<style lang="less">
  123 + .scrollbar {
  124 + position: relative;
  125 + height: 100%;
  126 + overflow: hidden;
  127 +
  128 + &__wrap {
  129 + height: 100%;
  130 + overflow: scroll;
  131 +
  132 + &--hidden-default {
  133 + scrollbar-width: none;
  134 +
  135 + &::-webkit-scrollbar {
  136 + display: none;
  137 + width: 0;
  138 + height: 0;
  139 + opacity: 0;
  140 + }
  141 + }
  142 + }
  143 +
  144 + &__thumb {
  145 + position: relative;
  146 + display: block;
  147 + width: 0;
  148 + height: 0;
  149 + cursor: pointer;
  150 + background-color: rgba(144, 147, 153, 0.3);
  151 + border-radius: inherit;
  152 + transition: 0.3s background-color;
  153 +
  154 + &:hover {
  155 + background-color: rgba(144, 147, 153, 0.5);
  156 + }
  157 + }
  158 +
  159 + &__bar {
  160 + position: absolute;
  161 + right: 2px;
  162 + bottom: 2px;
  163 + z-index: 1;
  164 + border-radius: 4px;
  165 + opacity: 0;
  166 + -webkit-transition: opacity 80ms ease;
  167 + transition: opacity 80ms ease;
  168 +
  169 + &.is-vertical {
  170 + top: 2px;
  171 + width: 6px;
  172 +
  173 + & > div {
  174 + width: 100%;
  175 + }
  176 + }
  177 +
  178 + &.is-horizontal {
  179 + left: 2px;
  180 + height: 6px;
  181 +
  182 + & > div {
  183 + height: 100%;
  184 + }
  185 + }
  186 + }
  187 + }
  188 +
  189 + .scrollbar:active > .scrollbar__bar,
  190 + .scrollbar:focus > .scrollbar__bar,
  191 + .scrollbar:hover > .scrollbar__bar {
  192 + opacity: 1;
  193 + transition: opacity 340ms ease-out;
  194 + }
  195 +</style>
src/components/Transition/src/ExpandTransition.vue
@@ -59,6 +59,8 @@ @@ -59,6 +59,8 @@
59 if (el.scrollHeight !== 0) { 59 if (el.scrollHeight !== 0) {
60 // for safari: add class after set height, or it will jump to zero height suddenly, weired 60 // for safari: add class after set height, or it will jump to zero height suddenly, weired
61 addClass(el, 'collapse-transition'); 61 addClass(el, 'collapse-transition');
  62 + // in vue3.0.4, transitionProperty is set 'none' to avoid 'v-leave-from' issue
  63 + el.style.transitionProperty = 'height';
62 el.style.height = 0; 64 el.style.height = 0;
63 el.style.paddingTop = 0; 65 el.style.paddingTop = 0;
64 el.style.paddingBottom = 0; 66 el.style.paddingBottom = 0;
src/locales/types.ts
1 -export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja'; 1 +export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja' | 'ko';
src/router/menus/modules/demo/comp.ts
@@ -180,6 +180,16 @@ const menu: MenuModule = { @@ -180,6 +180,16 @@ const menu: MenuModule = {
180 { 180 {
181 path: 'markdown', 181 path: 'markdown',
182 name: t('routes.demo.editor.markdown'), 182 name: t('routes.demo.editor.markdown'),
  183 + children: [
  184 + {
  185 + path: 'index',
  186 + name: t('routes.demo.editor.tinymceBasic'),
  187 + },
  188 + {
  189 + path: 'editor',
  190 + name: t('routes.demo.editor.tinymceForm'),
  191 + },
  192 + ],
183 }, 193 },
184 { 194 {
185 path: 'tinymce', 195 path: 'tinymce',
src/router/routes/modules/demo/comp.ts
@@ -288,12 +288,32 @@ const comp: AppRouteModule = { @@ -288,12 +288,32 @@ const comp: AppRouteModule = {
288 children: [ 288 children: [
289 { 289 {
290 path: 'markdown', 290 path: 'markdown',
  291 + component: getParentLayout('MarkdownDemo'),
291 name: 'MarkdownDemo', 292 name: 'MarkdownDemo',
292 - component: () => import('/@/views/demo/editor/Markdown.vue'),  
293 meta: { 293 meta: {
294 title: t('routes.demo.editor.markdown'), 294 title: t('routes.demo.editor.markdown'),
295 }, 295 },
  296 + redirect: '/comp/editor/markdown/index',
  297 + children: [
  298 + {
  299 + path: 'index',
  300 + name: 'MarkDownBasicDemo',
  301 + component: () => import('/@/views/demo/editor/markdown/index.vue'),
  302 + meta: {
  303 + title: t('routes.demo.editor.tinymceBasic'),
  304 + },
  305 + },
  306 + {
  307 + path: 'editor',
  308 + name: 'MarkDownFormDemo',
  309 + component: () => import('/@/views/demo/editor/markdown/Editor.vue'),
  310 + meta: {
  311 + title: t('routes.demo.editor.tinymceForm'),
  312 + },
  313 + },
  314 + ],
296 }, 315 },
  316 +
297 { 317 {
298 path: 'tinymce', 318 path: 'tinymce',
299 component: getParentLayout('TinymceDemo'), 319 component: getParentLayout('TinymceDemo'),
src/views/demo/editor/markdown/Editor.vue 0 → 100644
  1 +<template>
  2 + <div class="m-4">
  3 + <CollapseContainer title="MarkDown表单">
  4 + <BasicForm
  5 + :labelWidth="100"
  6 + :schemas="schemas"
  7 + :actionColOptions="{ span: 24 }"
  8 + @submit="handleSubmit"
  9 + >
  10 + </BasicForm>
  11 + </CollapseContainer>
  12 + </div>
  13 +</template>
  14 +<script lang="ts">
  15 + import { defineComponent, h } from 'vue';
  16 + import { BasicForm, FormSchema } from '/@/components/Form/index';
  17 + import { CollapseContainer } from '/@/components/Container/index';
  18 + import { useMessage } from '/@/hooks/web/useMessage';
  19 + import { MarkDown } from '/@/components/Markdown';
  20 +
  21 + const schemas: FormSchema[] = [
  22 + {
  23 + field: 'title',
  24 + component: 'Input',
  25 + label: 'title',
  26 + defaultValue: '标题',
  27 + rules: [{ required: true }],
  28 + },
  29 + {
  30 + field: 'markdown',
  31 + component: 'Input',
  32 + label: 'markdown',
  33 + defaultValue: 'defaultValue',
  34 + rules: [{ required: true, trigger: 'blur' }],
  35 + render: ({ model, field }) => {
  36 + return h(MarkDown, {
  37 + value: model[field],
  38 + onChange: (value: string) => {
  39 + model[field] = value;
  40 + },
  41 + });
  42 + },
  43 + },
  44 + ];
  45 + export default defineComponent({
  46 + components: { BasicForm, CollapseContainer },
  47 + setup() {
  48 + const { createMessage } = useMessage();
  49 +
  50 + return {
  51 + schemas,
  52 + handleSubmit: (values: any) => {
  53 + createMessage.success('click search,values:' + JSON.stringify(values));
  54 + },
  55 + };
  56 + },
  57 + });
  58 +</script>
src/views/demo/editor/Markdown.vue renamed to src/views/demo/editor/markdown/index.vue
1 <template> 1 <template>
2 <div class="p-4"> 2 <div class="p-4">
3 <a-button @click="toggleTheme" class="mb-2" type="primary">黑暗主题</a-button> 3 <a-button @click="toggleTheme" class="mb-2" type="primary">黑暗主题</a-button>
4 - <MarkDown v-model:value="value" ref="markDownRef" /> 4 + <MarkDown :value="value" @change="handleChange" ref="markDownRef" />
5 </div> 5 </div>
6 </template> 6 </template>
7 <script lang="ts"> 7 <script lang="ts">
@@ -23,10 +23,16 @@ @@ -23,10 +23,16 @@
23 const vditor = markDown.getVditor(); 23 const vditor = markDown.getVditor();
24 vditor.setTheme('dark'); 24 vditor.setTheme('dark');
25 } 25 }
  26 +
  27 + function handleChange(v: string) {
  28 + valueRef.value = v;
  29 + }
  30 +
26 return { 31 return {
27 value: valueRef, 32 value: valueRef,
28 toggleTheme, 33 toggleTheme,
29 markDownRef, 34 markDownRef,
  35 + handleChange,
30 }; 36 };
31 }, 37 },
32 }); 38 });
tsconfig.json
@@ -15,16 +15,11 @@ @@ -15,16 +15,11 @@
15 "noUnusedLocals": true, 15 "noUnusedLocals": true,
16 "noUnusedParameters": true, 16 "noUnusedParameters": true,
17 "experimentalDecorators": true, 17 "experimentalDecorators": true,
18 - "lib": [  
19 - "dom",  
20 - "esnext"  
21 - ], 18 + "lib": ["dom", "esnext"],
22 "incremental": true, 19 "incremental": true,
23 "skipLibCheck": true, 20 "skipLibCheck": true,
24 "paths": { 21 "paths": {
25 - "/@/*": [  
26 - "src/*"  
27 - ] 22 + "/@/*": ["src/*"]
28 } 23 }
29 }, 24 },
30 "plugins": [ 25 "plugins": [
@@ -32,15 +27,6 @@ @@ -32,15 +27,6 @@
32 "name": "@vuedx/typescript-plugin-vue" 27 "name": "@vuedx/typescript-plugin-vue"
33 } 28 }
34 ], 29 ],
35 - "include": [  
36 - "src/**/*.ts",  
37 - "src/**/*.d.ts",  
38 - "src/**/*.tsx",  
39 - "src/**/*.vue"  
40 - ],  
41 - "exclude": [  
42 - "node_modules",  
43 - "dist",  
44 - "**/*.js"  
45 - ] 30 + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  31 + "exclude": ["node_modules", "dist", "**/*.js"]
46 } 32 }