element-whale-ui 0.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -0
- package/element-whale-ui/element-whale-ui.css +2 -0
- package/element-whale-ui/element-whale-ui.es.js +65 -0
- package/element-whale-ui/element-whale-ui.umd.js +1 -0
- package/element-whale-ui/favicon.ico +0 -0
- package/package.json +85 -0
- package/src/packages/dk-tooltip-collapse/index.ts +6 -0
- package/src/packages/dk-tooltip-collapse/src/index.vue +408 -0
- package/src/packages/dk-tooltip-collapse/view/index.vue +421 -0
- package/src/packages/index.ts +3 -0
- package/src/packages/roll-number/index.ts +6 -0
- package/src/packages/roll-number/src/index.vue +183 -0
- package/src/packages/roll-number/view/index.vue +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# ShimmerUI
|
|
2
|
+
|
|
3
|
+
This template should help get you started developing with Vue 3 in Vite.
|
|
4
|
+
|
|
5
|
+
## Recommended IDE Setup
|
|
6
|
+
|
|
7
|
+
[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
|
8
|
+
|
|
9
|
+
## Recommended Browser Setup
|
|
10
|
+
|
|
11
|
+
- Chromium-based browsers (Chrome, Edge, Brave, etc.):
|
|
12
|
+
- [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
|
|
13
|
+
- [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters)
|
|
14
|
+
- Firefox:
|
|
15
|
+
- [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/)
|
|
16
|
+
- [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/)
|
|
17
|
+
|
|
18
|
+
## Type Support for `.vue` Imports in TS
|
|
19
|
+
|
|
20
|
+
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
|
|
21
|
+
|
|
22
|
+
## Customize configuration
|
|
23
|
+
|
|
24
|
+
See [Vite Configuration Reference](https://vite.dev/config/).
|
|
25
|
+
|
|
26
|
+
## Project Setup
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
pnpm install
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Compile and Hot-Reload for Development
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
pnpm dev
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Type-Check, Compile and Minify for Production
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
pnpm build
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Run Unit Tests with [Vitest](https://vitest.dev/)
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
pnpm test:unit
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Run End-to-End Tests with [Cypress](https://www.cypress.io/)
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
pnpm test:e2e:dev
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This runs the end-to-end tests against the Vite development server.
|
|
57
|
+
It is much faster than the production build.
|
|
58
|
+
|
|
59
|
+
But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments):
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
pnpm build
|
|
63
|
+
pnpm test:e2e
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Lint with [ESLint](https://eslint.org/)
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
pnpm lint
|
|
70
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { computed as e, createElementBlock as t, defineComponent as n, onMounted as r, onUnmounted as i, openBlock as a, ref as o, toDisplayString as s, watch as c } from "vue";
|
|
2
|
+
//#region src/packages/roll-number/src/index.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
+
var l = { class: "counter number-tabular number-modern" }, u = /* @__PURE__ */ ((e, t) => {
|
|
4
|
+
let n = e.__vccOpts || e;
|
|
5
|
+
for (let [e, r] of t) n[e] = r;
|
|
6
|
+
return n;
|
|
7
|
+
})(/* @__PURE__ */ n({
|
|
8
|
+
__name: "index",
|
|
9
|
+
props: {
|
|
10
|
+
value: { default: 0 },
|
|
11
|
+
duration: { default: 1200 },
|
|
12
|
+
easing: { default: "easeOutQuad" },
|
|
13
|
+
thousandsSeparator: {
|
|
14
|
+
type: Boolean,
|
|
15
|
+
default: !1
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
setup(n) {
|
|
19
|
+
let u = n, d = o(0), f = null, p = null, m = 0, h = {
|
|
20
|
+
linear: (e) => e,
|
|
21
|
+
easeOutQuad: (e) => e * (2 - e),
|
|
22
|
+
easeOutCubic: (e) => --e * e * e + 1
|
|
23
|
+
};
|
|
24
|
+
function g(e) {
|
|
25
|
+
p ||= e;
|
|
26
|
+
let t = Math.min((e - p) / u.duration, 1), n = h[u.easing], r = n(t);
|
|
27
|
+
d.value = m + (u.value - m) * r, t < 1 ? f = requestAnimationFrame(g) : (d.value = u.value, f = null);
|
|
28
|
+
}
|
|
29
|
+
function _() {
|
|
30
|
+
f && cancelAnimationFrame(f), p = null, m = d.value, f = requestAnimationFrame(g);
|
|
31
|
+
}
|
|
32
|
+
function v(e) {
|
|
33
|
+
let t = e.toString(), n = t.indexOf(".");
|
|
34
|
+
return n === -1 ? 0 : t.length - n - 1;
|
|
35
|
+
}
|
|
36
|
+
function y(e) {
|
|
37
|
+
let t = e.indexOf(".");
|
|
38
|
+
if (t === -1) return e;
|
|
39
|
+
let n = e.length;
|
|
40
|
+
for (; n > t + 1 && e.charAt(n - 1) === "0";) n--;
|
|
41
|
+
return e.slice(0, n);
|
|
42
|
+
}
|
|
43
|
+
let b = e(() => {
|
|
44
|
+
let e = v(u.value), t = y(d.value.toFixed(e));
|
|
45
|
+
if (u.thousandsSeparator) {
|
|
46
|
+
let e = t.split(".");
|
|
47
|
+
return e[0] = e[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","), e.join(".");
|
|
48
|
+
}
|
|
49
|
+
return t;
|
|
50
|
+
});
|
|
51
|
+
return c([
|
|
52
|
+
() => u.value,
|
|
53
|
+
() => u.duration,
|
|
54
|
+
() => u.easing
|
|
55
|
+
], () => {
|
|
56
|
+
_();
|
|
57
|
+
}), r(() => {
|
|
58
|
+
_();
|
|
59
|
+
}), i(() => {
|
|
60
|
+
f && cancelAnimationFrame(f);
|
|
61
|
+
}), (e, n) => (a(), t("div", l, s(b.value), 1));
|
|
62
|
+
}
|
|
63
|
+
}), [["__scopeId", "data-v-c63c3e32"]]);
|
|
64
|
+
//#endregion
|
|
65
|
+
export { u as RollNumber };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`vue`)):typeof define==`function`&&define.amd?define([`exports`,`vue`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ElementWhaleUI={},e.Vue))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n={class:`counter number-tabular number-modern`};e.RollNumber=((e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n})((0,t.defineComponent)({__name:`index`,props:{value:{default:0},duration:{default:1200},easing:{default:`easeOutQuad`},thousandsSeparator:{type:Boolean,default:!1}},setup(e){let r=e,i=(0,t.ref)(0),a=null,o=null,s=0,c={linear:e=>e,easeOutQuad:e=>e*(2-e),easeOutCubic:e=>--e*e*e+1};function l(e){o||=e;let t=Math.min((e-o)/r.duration,1),n=c[r.easing],u=n(t);i.value=s+(r.value-s)*u,t<1?a=requestAnimationFrame(l):(i.value=r.value,a=null)}function u(){a&&cancelAnimationFrame(a),o=null,s=i.value,a=requestAnimationFrame(l)}function d(e){let t=e.toString(),n=t.indexOf(`.`);return n===-1?0:t.length-n-1}function f(e){let t=e.indexOf(`.`);if(t===-1)return e;let n=e.length;for(;n>t+1&&e.charAt(n-1)===`0`;)n--;return e.slice(0,n)}let p=(0,t.computed)(()=>{let e=d(r.value),t=f(i.value.toFixed(e));if(r.thousandsSeparator){let e=t.split(`.`);return e[0]=e[0].replace(/\B(?=(\d{3})+(?!\d))/g,`,`),e.join(`.`)}return t});return(0,t.watch)([()=>r.value,()=>r.duration,()=>r.easing],()=>{u()}),(0,t.onMounted)(()=>{u()}),(0,t.onUnmounted)(()=>{a&&cancelAnimationFrame(a)}),(e,r)=>((0,t.openBlock)(),(0,t.createElementBlock)(`div`,n,(0,t.toDisplayString)(p.value),1))}}),[[`__scopeId`,`data-v-c63c3e32`]])});
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "element-whale-ui",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.0-beta.0",
|
|
5
|
+
"private": false,
|
|
6
|
+
"description": "A Vue 3 UI component library",
|
|
7
|
+
"main": "./element-whale-ui/element-whale-ui.umd.js",
|
|
8
|
+
"module": "./element-whale-ui/element-whale-ui.es.js",
|
|
9
|
+
"types": "./element-whale-ui/packages/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"element-whale-ui",
|
|
12
|
+
"src/packages"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "vite",
|
|
19
|
+
"build": "run-p type-check \"build-only {@}\" --",
|
|
20
|
+
"build:lib": "vite build",
|
|
21
|
+
"preview": "vite preview",
|
|
22
|
+
"test:unit": "vitest",
|
|
23
|
+
"prepare": "husky",
|
|
24
|
+
"test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'",
|
|
25
|
+
"test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'",
|
|
26
|
+
"build-only": "vite build",
|
|
27
|
+
"type-check": "vue-tsc --build",
|
|
28
|
+
"lint": "run-s lint:*",
|
|
29
|
+
"lint:eslint": "eslint . --fix --cache",
|
|
30
|
+
"lint:style": "stylelint \"**/*.{vue,css,scss}\" --fix",
|
|
31
|
+
"format": "prettier --write --experimental-cli src/"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@element-plus/icons-vue": "^2.3.2",
|
|
35
|
+
"dompurify": "^3.4.7",
|
|
36
|
+
"element-plus": "^2.14.0",
|
|
37
|
+
"highlight.js": "^11.11.1",
|
|
38
|
+
"marked": "^18.0.4",
|
|
39
|
+
"marked-highlight": "^2.2.4",
|
|
40
|
+
"pinia": "^3.0.4",
|
|
41
|
+
"vue": "^3.5.32",
|
|
42
|
+
"vue-router": "^5.0.4",
|
|
43
|
+
"vuejs-code-block": "^1.0.1"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@antfu/eslint-config": "^9.0.0",
|
|
47
|
+
"@stylelint/postcss-css-in-js": "^0.38.0",
|
|
48
|
+
"@tsconfig/node24": "^24.0.4",
|
|
49
|
+
"@types/jsdom": "^28.0.1",
|
|
50
|
+
"@types/node": "^24.12.2",
|
|
51
|
+
"@vitejs/plugin-vue": "^6.0.6",
|
|
52
|
+
"@vitejs/plugin-vue-jsx": "^5.1.5",
|
|
53
|
+
"@vitest/eslint-plugin": "^1.6.16",
|
|
54
|
+
"@vue/eslint-config-typescript": "^14.7.0",
|
|
55
|
+
"@vue/test-utils": "^2.4.6",
|
|
56
|
+
"@vue/tsconfig": "^0.9.1",
|
|
57
|
+
"cypress": "^15.14.0",
|
|
58
|
+
"eslint": "^10.2.1",
|
|
59
|
+
"eslint-config-prettier": "^10.1.8",
|
|
60
|
+
"eslint-plugin-cypress": "^6.3.1",
|
|
61
|
+
"eslint-plugin-oxlint": "~1.60.0",
|
|
62
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
63
|
+
"eslint-plugin-vue": "~10.8.0",
|
|
64
|
+
"husky": "^9.1.7",
|
|
65
|
+
"jiti": "^2.6.1",
|
|
66
|
+
"jsdom": "^29.0.2",
|
|
67
|
+
"lint-staged": "^17.0.4",
|
|
68
|
+
"npm-run-all2": "^8.0.4",
|
|
69
|
+
"oxlint": "~1.60.0",
|
|
70
|
+
"pinia-plugin-persistedstate": "^4.7.1",
|
|
71
|
+
"prettier": "3.8.3",
|
|
72
|
+
"sass": "^1.99.0",
|
|
73
|
+
"start-server-and-test": "^2.1.5",
|
|
74
|
+
"stylelint": "^17.11.0",
|
|
75
|
+
"stylelint-config-recommended-vue": "^1.6.1",
|
|
76
|
+
"stylelint-prettier": "^5.0.3",
|
|
77
|
+
"typescript": "~6.0.0",
|
|
78
|
+
"unplugin-auto-import": "^21.0.0",
|
|
79
|
+
"vite": "^8.0.8",
|
|
80
|
+
"vite-plugin-vue-devtools": "^8.1.1",
|
|
81
|
+
"vitepress": "^1.6.4",
|
|
82
|
+
"vitest": "^4.1.4",
|
|
83
|
+
"vue-tsc": "^3.2.6"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue'
|
|
3
|
+
import { computed, nextTick, onMounted, onUnmounted, ref, useSlots } from 'vue'
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
6
|
+
text: '',
|
|
7
|
+
width: '',
|
|
8
|
+
placement: 'top',
|
|
9
|
+
tooltipContent: '',
|
|
10
|
+
effect: 'dark',
|
|
11
|
+
disabled: undefined,
|
|
12
|
+
tooltip: true,
|
|
13
|
+
lineClamp: 1,
|
|
14
|
+
lineHeight: '20px',
|
|
15
|
+
tooltipMaxWidth: '90%',
|
|
16
|
+
toggleBg: '',
|
|
17
|
+
toggleHoverBg: '',
|
|
18
|
+
tooltipLineClamp: 0,
|
|
19
|
+
})
|
|
20
|
+
/** 折叠状态,true为收起状态 */
|
|
21
|
+
const isCollapsed = defineModel('isCollapsed', { type: Boolean, default: true })
|
|
22
|
+
/** 组件属性接口 */
|
|
23
|
+
interface Props {
|
|
24
|
+
/** 显示的文本内容 */
|
|
25
|
+
text?: string
|
|
26
|
+
/** 容器最小宽度 */
|
|
27
|
+
width?: string
|
|
28
|
+
/** tooltip弹出位置 */
|
|
29
|
+
placement?:
|
|
30
|
+
| 'top'
|
|
31
|
+
| 'top-start'
|
|
32
|
+
| 'top-end'
|
|
33
|
+
| 'bottom'
|
|
34
|
+
| 'bottom-start'
|
|
35
|
+
| 'bottom-end'
|
|
36
|
+
| 'left'
|
|
37
|
+
| 'left-start'
|
|
38
|
+
| 'left-end'
|
|
39
|
+
| 'right'
|
|
40
|
+
| 'right-start'
|
|
41
|
+
| 'right-end'
|
|
42
|
+
/** tooltip提示内容,不设置则使用text */
|
|
43
|
+
tooltipContent?: string
|
|
44
|
+
/** tooltip最大宽度 */
|
|
45
|
+
tooltipMaxWidth?: string
|
|
46
|
+
/** tooltip主题色 */
|
|
47
|
+
effect?: 'dark' | 'light'
|
|
48
|
+
/** 是否禁用 */
|
|
49
|
+
disabled?: boolean
|
|
50
|
+
/** 是否使用tooltip模式,false则使用折叠模式 */
|
|
51
|
+
tooltip?: boolean
|
|
52
|
+
/** 折叠模式显示的最大行数 */
|
|
53
|
+
lineClamp?: number
|
|
54
|
+
/** 每行的高度,用于计算展开/收起按钮的位置 */
|
|
55
|
+
lineHeight?: string
|
|
56
|
+
/** 展开/收起按钮的背景色,不设置则使用父元素背景色 */
|
|
57
|
+
toggleBg?: string
|
|
58
|
+
/** 展开/收起按钮的悬停背景色,不设置则使用父元素背景色 */
|
|
59
|
+
toggleHoverBg?: string
|
|
60
|
+
/** tooltip模式下显示的最大行数,默认1(单行省略),设为0或不设置则不限制 */
|
|
61
|
+
tooltipLineClamp?: number
|
|
62
|
+
}
|
|
63
|
+
const slots = useSlots()
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* tooltip弹窗样式,计算最大宽度
|
|
67
|
+
*/
|
|
68
|
+
const tooltipStyle = computed(() => {
|
|
69
|
+
return props.tooltipMaxWidth ? { maxWidth: props.tooltipMaxWidth } : {}
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 获取文本容器的样式
|
|
74
|
+
* 支持多行省略(tooltipLineClamp > 0)
|
|
75
|
+
*/
|
|
76
|
+
function getTextStyle() {
|
|
77
|
+
const style: Record<string, string> = {
|
|
78
|
+
minWidth: props.width || '100%',
|
|
79
|
+
lineHeight: props.lineHeight,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (props.tooltipLineClamp > 0) {
|
|
83
|
+
style.display = '-webkit-box'
|
|
84
|
+
style.WebkitLineClamp = String(props.tooltipLineClamp)
|
|
85
|
+
style.WebkitBoxOrient = 'vertical'
|
|
86
|
+
style.overflow = 'hidden'
|
|
87
|
+
style.textOverflow = 'ellipsis'
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return style
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** 文本容器的DOM引用 */
|
|
94
|
+
const containerRef = ref<HTMLElement>()
|
|
95
|
+
/** 文本是否溢出 */
|
|
96
|
+
const isOverflow = ref(false)
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 判断tooltip是否禁用
|
|
100
|
+
* - 如果手动设置了disabled,使用手动设置的值
|
|
101
|
+
* - 如果是非tooltip模式且有content,则启用
|
|
102
|
+
* - 否则根据文本是否溢出来决定
|
|
103
|
+
*/
|
|
104
|
+
const isDisabled = computed(() => {
|
|
105
|
+
if (props.tooltipContent || slots.tooltipContent) {
|
|
106
|
+
return false
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (props.disabled !== undefined) {
|
|
110
|
+
return props.disabled
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return !isOverflow.value
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 检测文本是否溢出
|
|
118
|
+
* - 单行模式:比较文本宽度和容器宽度
|
|
119
|
+
* - 多行模式:比较scrollHeight和clientHeight(垂直溢出)
|
|
120
|
+
*/
|
|
121
|
+
function checkOverflow() {
|
|
122
|
+
if (!containerRef.value) {
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 多行模式:检测垂直溢出
|
|
127
|
+
if (props.lineClamp && props.lineClamp > 1) {
|
|
128
|
+
if (!isCollapsed.value) {
|
|
129
|
+
isOverflow.value = true
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
const textContent: any = containerRef.value.querySelector('.dk-tooltip-text-content')
|
|
133
|
+
if (!textContent) {
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
const originalDisplay = textContent.style.display
|
|
137
|
+
const originalLineClamp = textContent.style.webkitLineClamp
|
|
138
|
+
textContent.style.display = 'block'
|
|
139
|
+
textContent.style.webkitLineClamp = 'none'
|
|
140
|
+
const naturalHeight = textContent.scrollHeight
|
|
141
|
+
textContent.style.display = originalDisplay
|
|
142
|
+
textContent.style.webkitLineClamp = originalLineClamp
|
|
143
|
+
const limitedHeight = containerRef.value.clientHeight
|
|
144
|
+
isOverflow.value = naturalHeight > limitedHeight + 1
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// 单行模式:检测水平溢出
|
|
149
|
+
let parentWidth: number
|
|
150
|
+
|
|
151
|
+
// 如果设置了固定宽度,使用该宽度
|
|
152
|
+
if (props.width) {
|
|
153
|
+
parentWidth = Number.parseFloat(props.width)
|
|
154
|
+
} else {
|
|
155
|
+
// 否则获取父元素的宽度
|
|
156
|
+
const parent = containerRef.value.parentElement
|
|
157
|
+
if (!parent) {
|
|
158
|
+
isOverflow.value = containerRef.value.scrollWidth > containerRef.value.clientWidth
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
parentWidth = parent.clientWidth
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 计算文本宽度并比较
|
|
165
|
+
const textWidth = getTextWidth(props.text)
|
|
166
|
+
isOverflow.value = textWidth > parentWidth
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 使用canvas测量文本宽度
|
|
171
|
+
* @param text 要测量的文本
|
|
172
|
+
* @returns 文本宽度(像素)
|
|
173
|
+
*/
|
|
174
|
+
function getTextWidth(text: string): number {
|
|
175
|
+
const canvas = document.createElement('canvas')
|
|
176
|
+
const context = canvas.getContext('2d')
|
|
177
|
+
if (!context) {
|
|
178
|
+
return 0
|
|
179
|
+
}
|
|
180
|
+
context.font = getComputedStyle(containerRef.value!).font || '14px system-ui'
|
|
181
|
+
const metrics = context.measureText(text)
|
|
182
|
+
return metrics.width
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* 获取父元素的背景色
|
|
187
|
+
* 用于折叠按钮的背景色,使其与父元素融合
|
|
188
|
+
*/
|
|
189
|
+
const fatherBg = computed(() => {
|
|
190
|
+
if (props.toggleBg) {
|
|
191
|
+
return props.toggleBg
|
|
192
|
+
}
|
|
193
|
+
const parent = containerRef.value?.parentElement
|
|
194
|
+
if (!parent) {
|
|
195
|
+
return ''
|
|
196
|
+
}
|
|
197
|
+
return window.getComputedStyle(parent).backgroundColor
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
/** 监听容器尺寸变化的Observer */
|
|
201
|
+
let resizeObserver: ResizeObserver | null = null
|
|
202
|
+
/** 监听父元素尺寸变化的Observer */
|
|
203
|
+
let parentObserver: ResizeObserver | null = null
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 切换折叠/展开状态
|
|
207
|
+
*/
|
|
208
|
+
function toggleCollapse() {
|
|
209
|
+
isCollapsed.value = !isCollapsed.value
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 组件挂载后初始化
|
|
214
|
+
* - 检测文本溢出
|
|
215
|
+
* - 创建ResizeObserver监听容器和父元素尺寸变化
|
|
216
|
+
*/
|
|
217
|
+
onMounted(() => {
|
|
218
|
+
nextTick(() => {
|
|
219
|
+
checkOverflow()
|
|
220
|
+
if (containerRef.value) {
|
|
221
|
+
// 监听容器尺寸变化
|
|
222
|
+
resizeObserver = new ResizeObserver(() => {
|
|
223
|
+
checkOverflow()
|
|
224
|
+
})
|
|
225
|
+
resizeObserver.observe(containerRef.value)
|
|
226
|
+
|
|
227
|
+
// 监听父元素尺寸变化
|
|
228
|
+
const parent = containerRef.value.parentElement
|
|
229
|
+
if (parent) {
|
|
230
|
+
parentObserver = new ResizeObserver(() => {
|
|
231
|
+
checkOverflow()
|
|
232
|
+
})
|
|
233
|
+
parentObserver.observe(parent)
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* 组件卸载时断开所有Observer连接
|
|
241
|
+
*/
|
|
242
|
+
onUnmounted(() => {
|
|
243
|
+
resizeObserver?.disconnect()
|
|
244
|
+
parentObserver?.disconnect()
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
defineExpose({
|
|
248
|
+
toggleCollapse,
|
|
249
|
+
})
|
|
250
|
+
</script>
|
|
251
|
+
|
|
252
|
+
<template>
|
|
253
|
+
<!-- tooltip模式:当设置了tooltip且文本溢出时显示el-tooltip提示 -->
|
|
254
|
+
<el-tooltip
|
|
255
|
+
v-if="tooltip"
|
|
256
|
+
:effect="effect"
|
|
257
|
+
:placement="placement"
|
|
258
|
+
:disabled="isDisabled"
|
|
259
|
+
:popper-style="tooltipStyle"
|
|
260
|
+
>
|
|
261
|
+
<template #content>
|
|
262
|
+
<slot name="tooltipContent">
|
|
263
|
+
{{ tooltipContent || text }}
|
|
264
|
+
</slot>
|
|
265
|
+
</template>
|
|
266
|
+
<div
|
|
267
|
+
ref="containerRef"
|
|
268
|
+
class="dk-tooltip-text"
|
|
269
|
+
:class="{ 'is-multiline': props.tooltipLineClamp && props.tooltipLineClamp > 1 }"
|
|
270
|
+
:style="getTextStyle()"
|
|
271
|
+
>
|
|
272
|
+
<slot>
|
|
273
|
+
{{ text }}
|
|
274
|
+
</slot>
|
|
275
|
+
</div>
|
|
276
|
+
</el-tooltip>
|
|
277
|
+
|
|
278
|
+
<!-- 折叠模式:当tooltip为false时启用,支持多行显示和展开/收起功能 -->
|
|
279
|
+
<div
|
|
280
|
+
v-else
|
|
281
|
+
ref="containerRef"
|
|
282
|
+
class="dk-tooltip-collapse"
|
|
283
|
+
:class="{ 'is-expanded': !isCollapsed }"
|
|
284
|
+
:style="{ minWidth: props.width || '100%', lineHeight: props.lineHeight }"
|
|
285
|
+
>
|
|
286
|
+
<!-- 文本内容区域 -->
|
|
287
|
+
<div
|
|
288
|
+
class="dk-tooltip-text-content"
|
|
289
|
+
:style="
|
|
290
|
+
isCollapsed
|
|
291
|
+
? {
|
|
292
|
+
display: '-webkit-box',
|
|
293
|
+
WebkitLineClamp: props.lineClamp,
|
|
294
|
+
WebkitBoxOrient: 'vertical',
|
|
295
|
+
}
|
|
296
|
+
: {}
|
|
297
|
+
"
|
|
298
|
+
>
|
|
299
|
+
{{ text }}
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
<!-- 展开/收起触发器:当文本溢出时显示 -->
|
|
303
|
+
<div
|
|
304
|
+
v-if="isOverflow"
|
|
305
|
+
class="dk-tooltip-toggle"
|
|
306
|
+
:style="{
|
|
307
|
+
'height': props.lineHeight,
|
|
308
|
+
'background': fatherBg,
|
|
309
|
+
'bottom': !isCollapsed ? `-${props.lineHeight}` : '0',
|
|
310
|
+
'--toggle-hover-bg': props.toggleHoverBg || 'inherit',
|
|
311
|
+
}"
|
|
312
|
+
@click.stop="toggleCollapse"
|
|
313
|
+
>
|
|
314
|
+
<!-- 自定义折叠触发器的插槽,默认显示展开/收起按钮和图标 -->
|
|
315
|
+
<slot name="collapse-trigger" :is-collapsed="isCollapsed">
|
|
316
|
+
<span>{{ isCollapsed ? '展开' : '收起' }}</span>
|
|
317
|
+
<el-icon v-if="isCollapsed">
|
|
318
|
+
<ArrowDown />
|
|
319
|
+
</el-icon>
|
|
320
|
+
<el-icon v-else>
|
|
321
|
+
<ArrowUp />
|
|
322
|
+
</el-icon>
|
|
323
|
+
</slot>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
</template>
|
|
327
|
+
|
|
328
|
+
<style scoped lang="scss">
|
|
329
|
+
/** tooltip模式的文本样式,单行省略 */
|
|
330
|
+
.dk-tooltip-text {
|
|
331
|
+
overflow: hidden;
|
|
332
|
+
text-overflow: ellipsis;
|
|
333
|
+
white-space: nowrap;
|
|
334
|
+
display: inline-block;
|
|
335
|
+
width: 0;
|
|
336
|
+
min-width: 100%;
|
|
337
|
+
// font-size: 12px;
|
|
338
|
+
|
|
339
|
+
/** 多行省略模式 */
|
|
340
|
+
&.is-multiline {
|
|
341
|
+
white-space: normal;
|
|
342
|
+
word-break: break-word;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/** 折叠模式的容器样式 */
|
|
347
|
+
.dk-tooltip-collapse {
|
|
348
|
+
position: relative;
|
|
349
|
+
width: 0;
|
|
350
|
+
min-width: 100%;
|
|
351
|
+
box-sizing: border-box;
|
|
352
|
+
|
|
353
|
+
/** 文本内容区域 */
|
|
354
|
+
.dk-tooltip-text-content {
|
|
355
|
+
display: block;
|
|
356
|
+
overflow: hidden;
|
|
357
|
+
text-overflow: ellipsis;
|
|
358
|
+
word-break: break-all;
|
|
359
|
+
font-size: 12px;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/** 展开/收起触发按钮 */
|
|
363
|
+
.dk-tooltip-toggle {
|
|
364
|
+
position: absolute;
|
|
365
|
+
right: 0;
|
|
366
|
+
bottom: 0;
|
|
367
|
+
color: inherit;
|
|
368
|
+
cursor: pointer;
|
|
369
|
+
background: #fff;
|
|
370
|
+
padding-left: 16px;
|
|
371
|
+
display: flex;
|
|
372
|
+
align-items: center;
|
|
373
|
+
font-size: 12px;
|
|
374
|
+
|
|
375
|
+
/** 省略号装饰,折叠时显示 */
|
|
376
|
+
&::before {
|
|
377
|
+
content: '...';
|
|
378
|
+
position: absolute;
|
|
379
|
+
left: 0;
|
|
380
|
+
top: 0;
|
|
381
|
+
width: 100%;
|
|
382
|
+
height: 100%;
|
|
383
|
+
color: inherit;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
&:hover {
|
|
388
|
+
.dk-tooltip-toggle {
|
|
389
|
+
background: var(--toggle-hover-bg, inherit) !important;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/** 展开状态样式 */
|
|
394
|
+
&.is-expanded {
|
|
395
|
+
.dk-tooltip-text-content {
|
|
396
|
+
white-space: normal;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/** 展开时隐藏省略号 */
|
|
400
|
+
.dk-tooltip-toggle {
|
|
401
|
+
padding-left: 0;
|
|
402
|
+
&::before {
|
|
403
|
+
display: none;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
</style>
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue'
|
|
3
|
+
import { ref } from 'vue'
|
|
4
|
+
import ComCollapse from '@/components/CodeCollapse.vue'
|
|
5
|
+
import MarkdownRenderer from '@/components/MarkdownRenderer.vue'
|
|
6
|
+
import DkTooltipCollapse from '../src/index.vue'
|
|
7
|
+
|
|
8
|
+
const collapsedVal = ref(false)
|
|
9
|
+
const aaRef = ref<any>(null)
|
|
10
|
+
function changeVal() {
|
|
11
|
+
aaRef.value?.toggleCollapse()
|
|
12
|
+
}
|
|
13
|
+
const wVal = ref(
|
|
14
|
+
'春江潮水连海月共潮生月共潮生滟波滟随波千万里,何处春江无月明!江流宛转绕芳甸,月照花林皆似霰。白云一片去悠悠,何处相思明月楼',
|
|
15
|
+
)
|
|
16
|
+
const wVal2 = ref(
|
|
17
|
+
'春江潮水连海月共潮生月共潮生滟波滟随波千万里,何处春江无月明!江流宛转绕芳甸,月照花林皆似霰。白云一片去悠悠,何处相',
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
const textVal = ref(`春江潮水连海月共潮生月共潮生。
|
|
21
|
+
滟波滟随波千万里,何处春江无月明!
|
|
22
|
+
江流宛转绕芳甸,月照花林皆似霰。
|
|
23
|
+
空里流霜不觉飞,汀上白沙看不见。
|
|
24
|
+
江天一色无纤尘,皎皎空中孤月轮。
|
|
25
|
+
江畔何人初见月?江月何年初照人?
|
|
26
|
+
人生代代无穷已,江月年年望相似。
|
|
27
|
+
不知江月待何人,但见长江送流水。
|
|
28
|
+
白云一片去悠悠,青枫浦上不胜愁。
|
|
29
|
+
谁家今夜扁舟子?何处相思明月楼?
|
|
30
|
+
可怜楼上月徘徊,应照离人妆镜台。
|
|
31
|
+
玉户帘中卷不去,捣衣砧上拂还来。
|
|
32
|
+
此时相望不相闻,愿逐月华流照君。
|
|
33
|
+
鸿雁长飞光不度,鱼龙潜跃水成文。
|
|
34
|
+
昨夜闲潭梦落花,可怜春半不还家。
|
|
35
|
+
江水流春去欲尽,江潭落月复西斜。
|
|
36
|
+
斜月沉沉藏海雾,碣石潇湘无限路。
|
|
37
|
+
不知乘月几人归,落月摇情满江树。`)
|
|
38
|
+
const textVal2 = ref(`坐上那朵离家的云霞
|
|
39
|
+
飘去无人知晓的天涯
|
|
40
|
+
背着妈妈说的那句话
|
|
41
|
+
孩子人生其实不复杂
|
|
42
|
+
|
|
43
|
+
喔~眼泪轻轻地擦
|
|
44
|
+
别管那多嘴乌鸦
|
|
45
|
+
咽下那些风沙
|
|
46
|
+
你才能慢慢长大
|
|
47
|
+
要错过几个她
|
|
48
|
+
用你最好的年华
|
|
49
|
+
这是青春的代价
|
|
50
|
+
|
|
51
|
+
【副歌】
|
|
52
|
+
当离别开出花 伸出新长的枝桠
|
|
53
|
+
像冬去春又来 等待心雪融化
|
|
54
|
+
你每次离开家 带着远方的牵挂
|
|
55
|
+
那城市的繁华 盖住了月牙
|
|
56
|
+
|
|
57
|
+
当离别开出花 它生长在悬崖
|
|
58
|
+
在最高的山顶 才听得见回答
|
|
59
|
+
没什么好害怕 孩子放心去飞吧
|
|
60
|
+
在你的身后 有个等你的家
|
|
61
|
+
|
|
62
|
+
坐上那朵离家的云霞
|
|
63
|
+
飘去无人知晓的天涯
|
|
64
|
+
背着妈妈说的那句话
|
|
65
|
+
孩子人生其实不复杂
|
|
66
|
+
|
|
67
|
+
喔~眼泪轻轻地擦
|
|
68
|
+
别忘那童年梦话
|
|
69
|
+
散在远方的花 也随风慢慢长大
|
|
70
|
+
要错过几个她
|
|
71
|
+
用你最真的年华
|
|
72
|
+
这是青春的回答
|
|
73
|
+
|
|
74
|
+
【副歌重复】
|
|
75
|
+
|
|
76
|
+
当离别开出花 伸出新长的枝桠
|
|
77
|
+
像冬去春又来 等待心雪融化
|
|
78
|
+
你每次离开家 带着远方的牵挂
|
|
79
|
+
那城市的繁华 盖住了月牙
|
|
80
|
+
|
|
81
|
+
当离别开出花 它生长在悬崖
|
|
82
|
+
在最高的山顶 才听得见回答
|
|
83
|
+
没什么好害怕 孩子放心去飞吧
|
|
84
|
+
在你的身后 有个等你的家`)
|
|
85
|
+
const tooltipContent = ref(
|
|
86
|
+
'这是唐代诗人张若虚的作品。这首诗共三十六句,描绘了春江月夜的壮丽景色,并由此引发对宇宙、人生的哲理思考以及游子思妇的离愁别绪,素有“孤篇盖全唐”的美誉',
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
const demoCode01 = ref(
|
|
90
|
+
`<DkTooltipCollapse :text="textVal" />
|
|
91
|
+
|
|
92
|
+
const textVal = ref('xxxxxxxxxxxxxxxxxxx')
|
|
93
|
+
import { DkTooltipCollapse } from '@dk-component/comp';`,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
const demoCode02 = ref(
|
|
97
|
+
`<div style="width: 500px;">
|
|
98
|
+
<DkTooltipCollapse :text="'弹框宽度默认为100%。'+textVal" />
|
|
99
|
+
<DkTooltipCollapse :text="'弹框宽度为350px。'+textVal" tooltip-max-width="350px" />
|
|
100
|
+
<br>
|
|
101
|
+
<DkTooltipCollapse :text="'tooltipLineClamp为2行。'+textVal" tooltip-max-width="400px" :tooltip-line-clamp="2" />
|
|
102
|
+
|
|
103
|
+
<div style="width: 100%; display: flex; text-indent: 24px;">
|
|
104
|
+
<div style="flex: 1;">
|
|
105
|
+
<DkTooltipCollapse :text="textVal2" tooltip-max-width="400px" :tooltip-line-clamp="2" />
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
<br>
|
|
109
|
+
|
|
110
|
+
<h3>自定义 slot</h3>
|
|
111
|
+
<h4>1.slot 显示内容 完全自定义 :</h4>
|
|
112
|
+
<DkTooltipCollapse :text="'弹框宽度默认为100%'+textVal">
|
|
113
|
+
<div>
|
|
114
|
+
<span style="color: red; font-weight: 800;">我是额外的内容, </span>
|
|
115
|
+
<span>{{ textVal }}</span>
|
|
116
|
+
</div>
|
|
117
|
+
</DkTooltipCollapse>
|
|
118
|
+
<h4>2.slot 显示内容 通过 text 传递 :</h4>
|
|
119
|
+
<DkTooltipCollapse text="弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容" width="135px" :tooltip-content="tooltipContent" />
|
|
120
|
+
|
|
121
|
+
<h4>3.slot 弹框内容 自定义 :</h4>
|
|
122
|
+
<DkTooltipCollapse text="弹框-中是自定义内容" width="150px">
|
|
123
|
+
<template #tooltipContent>
|
|
124
|
+
<p>33333333333</p>
|
|
125
|
+
multiple lines<br>second line
|
|
126
|
+
multiple lines<br>second line
|
|
127
|
+
multiple lines<br>second line
|
|
128
|
+
multiple lines<br>second line
|
|
129
|
+
multiple lines<br>second line
|
|
130
|
+
</template>
|
|
131
|
+
</DkTooltipCollapse>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
const textVal = ref('xxxxxxxxxxxxxxxxxxx');
|
|
135
|
+
const tooltipContent = ref("这是唐代诗人张若虚的作品。这首诗共三十六句,描绘了春江月夜的壮丽景色,并由此引发对宇宙、人生的哲理思考以及游子思妇的离愁别绪,素有“孤篇盖全唐”的美誉");
|
|
136
|
+
|
|
137
|
+
import { DkTooltipCollapse } from '@dk-component/comp';`,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
const demoCode03 = ref(
|
|
141
|
+
`<h4>设置 展开 还是收起</h4>
|
|
142
|
+
<div>
|
|
143
|
+
<h4>设置 展开 还是收起</h4>
|
|
144
|
+
<button @click="changeVal">
|
|
145
|
+
通过 ref 控制 展开/收起
|
|
146
|
+
</button>
|
|
147
|
+
<DkTooltipCollapse ref="aaRef" :text="textVal" :tooltip="false" toggle-bg="cyan" toggle-hover-bg="red" :is-collapsed="collapsedVal" />
|
|
148
|
+
</div>
|
|
149
|
+
<br>
|
|
150
|
+
|
|
151
|
+
<h4>设置展开行数</h4>
|
|
152
|
+
<div style="display: flex;">
|
|
153
|
+
<div style="flex: 1;">
|
|
154
|
+
<DkTooltipCollapse :text="textVal" :tooltip="false" toggle-bg="cyan" toggle-hover-bg="red" />
|
|
155
|
+
</div>
|
|
156
|
+
<div style="flex: 1; background: yellow; color: red;">
|
|
157
|
+
<DkTooltipCollapse :text="textVal" :tooltip="false" :line-clamp="3" />
|
|
158
|
+
</div>
|
|
159
|
+
<div style="flex: 1; background: #999;">
|
|
160
|
+
<DkTooltipCollapse :text="textVal" :tooltip="false" :line-clamp="2" line-height="40px" />
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
|
|
164
|
+
const textVal = ref('xxxxxxxxxxxxxxxxxxx')
|
|
165
|
+
import { DkTooltipCollapse } from '@dk-component/comp';
|
|
166
|
+
|
|
167
|
+
const collapsedVal = ref(false);
|
|
168
|
+
const aaRef = ref<any>(null);
|
|
169
|
+
function changeVal() {
|
|
170
|
+
aaRef.value?.toggleCollapse();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
`,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
const demoCode04 = ref(
|
|
177
|
+
`<DkTooltipCollapse :text="textVal" toggle-bg="cyan" class="my-box">
|
|
178
|
+
<template #collapse-trigger="{ isCollapsed }">
|
|
179
|
+
<el-icon>
|
|
180
|
+
<ArrowDown v-if="isCollapsed" />
|
|
181
|
+
<ArrowUp v-else />
|
|
182
|
+
</el-icon>
|
|
183
|
+
</template>
|
|
184
|
+
</DkTooltipCollapse>
|
|
185
|
+
|
|
186
|
+
const textVal = ref('xxxxxxxxxxxxxxxxxxx')
|
|
187
|
+
import { DkTooltipCollapse } from '@dk-component/comp';
|
|
188
|
+
|
|
189
|
+
<style lang="scss" scoped>
|
|
190
|
+
:deep(.my-box) {
|
|
191
|
+
&.is-expanded {
|
|
192
|
+
.dk-tooltip-toggle {
|
|
193
|
+
bottom: 0 !important;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
</style>
|
|
198
|
+
`,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
// Markdown表格内容
|
|
202
|
+
const propsTable = ref(`
|
|
203
|
+
| 参数名 | 类型 | 默认值 | 说明 |
|
|
204
|
+
|--------|------|--------|------|
|
|
205
|
+
| text | string | "" | 显示的文本内容 |
|
|
206
|
+
| width | string | "" | 容器最小宽度,例如 "200px" |
|
|
207
|
+
| placement | string | "top" | tooltip 弹框 弹出位置,可选值:top /bottom /left /right /top-start /top-end /bottom-start /bottom-end /left-start /left-end /right-start /right-end |
|
|
208
|
+
| tooltip-content | string | "" | tooltip 弹框 提示内容,不设置则使用 text |
|
|
209
|
+
| tooltip-max-width | string | "90%" | tooltip 弹框 最大宽度 |
|
|
210
|
+
| effect | string | "dark" | tooltip 弹框 主题色,可选值:dark /light |
|
|
211
|
+
| disabled | boolean | undefined | 是否禁用 |
|
|
212
|
+
| tooltip | boolean | true | true-弹框模式; false-折叠模式 |
|
|
213
|
+
| isCollapsed | boolean | true | 起始状态: true-收起; false-展开 |
|
|
214
|
+
| line-clamp | number | 1 | 折叠模式-'展开'时显示的最大行数 |
|
|
215
|
+
| line-height | string | "20px" | 每行的高度,用于计算展开/收起 的位置 |
|
|
216
|
+
| toggleBg | string | "" | 展开/收起 的背景色,默认使用 父元素 的背景色 |
|
|
217
|
+
| toggleHoverBg | string | "" | 展开/收起 的悬停背景色,默认使用 父元素 的背景色 |
|
|
218
|
+
| 事件: toggleCollapse | Function | 折叠模式-点击展开/收起 通过 ref 触发 |
|
|
219
|
+
`)
|
|
220
|
+
|
|
221
|
+
const slotsTable = ref(`
|
|
222
|
+
| 插槽名 | 说明 | 参数 |
|
|
223
|
+
|--------|------|------|
|
|
224
|
+
| default | 自定义 text 显示内容 | html |
|
|
225
|
+
| tooltipContent | 自定义 tooltip 弹框 提示内容 | string/html |
|
|
226
|
+
| collapse-trigger | 展开+收起时:展开+收起的自定义插槽 | html |
|
|
227
|
+
`)
|
|
228
|
+
</script>
|
|
229
|
+
|
|
230
|
+
<template>
|
|
231
|
+
<div class="demo-container height-stretch overflow-auto-y custom-scrollbar-gradient">
|
|
232
|
+
<h1>文本溢出显示省略号并支持展开/收起的组件,同时支持 tooltip 模式显示完整文本</h1>
|
|
233
|
+
<div>
|
|
234
|
+
<h2>1.基础用法</h2>
|
|
235
|
+
<code>不设置宽度,就随父级宽度变化, 默认 100%</code>
|
|
236
|
+
<DkTooltipCollapse :text="textVal" />
|
|
237
|
+
<ComCollapse class="com-collapse" :code="demoCode01" />
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<h2>2.父级宽度为500px时</h2>
|
|
241
|
+
<div style="width: 500px">
|
|
242
|
+
<DkTooltipCollapse :text="`弹框宽度默认为100%。${textVal}`" />
|
|
243
|
+
<DkTooltipCollapse :text="`弹框宽度为350px。${textVal}`" tooltip-max-width="350px" />
|
|
244
|
+
<br>
|
|
245
|
+
<DkTooltipCollapse
|
|
246
|
+
:text="`tooltipLineClamp为2行。${textVal}`"
|
|
247
|
+
tooltip-max-width="400px"
|
|
248
|
+
:tooltip-line-clamp="2"
|
|
249
|
+
/>
|
|
250
|
+
|
|
251
|
+
<div style="width: 100%; display: flex; text-indent: 24px">
|
|
252
|
+
<div style="flex: 1">
|
|
253
|
+
<DkTooltipCollapse :text="textVal2" tooltip-max-width="400px" :tooltip-line-clamp="2" />
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
<br>
|
|
257
|
+
|
|
258
|
+
<h3>自定义 slot</h3>
|
|
259
|
+
<h4>1.slot 显示内容 完全自定义 :</h4>
|
|
260
|
+
<DkTooltipCollapse :text="`弹框宽度默认为100%。${textVal}`">
|
|
261
|
+
<div>
|
|
262
|
+
<span style="color: red; font-weight: 800">我是额外的内容, </span>
|
|
263
|
+
<span>{{ textVal }}</span>
|
|
264
|
+
</div>
|
|
265
|
+
</DkTooltipCollapse>
|
|
266
|
+
<h4>2.slot 显示内容 通过 text 传递 :</h4>
|
|
267
|
+
<DkTooltipCollapse
|
|
268
|
+
text="弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容弹框-中是其他内容"
|
|
269
|
+
width="135px"
|
|
270
|
+
:tooltip-content="tooltipContent"
|
|
271
|
+
/>
|
|
272
|
+
|
|
273
|
+
<h4>3.slot 弹框内容 自定义 :</h4>
|
|
274
|
+
<DkTooltipCollapse text="弹框-中是自定义内容" width="150px">
|
|
275
|
+
<template #tooltipContent>
|
|
276
|
+
<p>33333333333</p>
|
|
277
|
+
multiple lines<br>second line multiple lines<br>second line multiple lines<br>second
|
|
278
|
+
line multiple lines<br>second line multiple lines<br>second line
|
|
279
|
+
</template>
|
|
280
|
+
</DkTooltipCollapse>
|
|
281
|
+
</div>
|
|
282
|
+
<ComCollapse class="com-collapse" :code="demoCode02" />
|
|
283
|
+
|
|
284
|
+
<h2>3.折叠模式: 展开+收起</h2>
|
|
285
|
+
<code>设置 `tooltip` 为 `false` 启用折叠模式,支持多行省略和展开/收起功能。</code>
|
|
286
|
+
|
|
287
|
+
<div>
|
|
288
|
+
<h4>设置 展开 还是收起</h4>
|
|
289
|
+
<button @click="changeVal">
|
|
290
|
+
通过 ref 控制 展开/收起
|
|
291
|
+
</button>
|
|
292
|
+
<DkTooltipCollapse
|
|
293
|
+
ref="aaRef"
|
|
294
|
+
:text="textVal"
|
|
295
|
+
:tooltip="false"
|
|
296
|
+
toggle-bg="cyan"
|
|
297
|
+
toggle-hover-bg="red"
|
|
298
|
+
:is-collapsed="collapsedVal"
|
|
299
|
+
/>
|
|
300
|
+
</div>
|
|
301
|
+
<br>
|
|
302
|
+
|
|
303
|
+
<h4>设置展开行数</h4>
|
|
304
|
+
<div style="display: flex">
|
|
305
|
+
<div style="flex: 1">
|
|
306
|
+
<DkTooltipCollapse
|
|
307
|
+
:text="`默认1行:${textVal}`"
|
|
308
|
+
:tooltip="false"
|
|
309
|
+
toggle-bg="cyan"
|
|
310
|
+
toggle-hover-bg="red"
|
|
311
|
+
/>
|
|
312
|
+
</div>
|
|
313
|
+
<div style="flex: 1; background: yellow; color: red">
|
|
314
|
+
<DkTooltipCollapse :text="`显示3行:${textVal}`" :tooltip="false" :line-clamp="3" />
|
|
315
|
+
</div>
|
|
316
|
+
<div style="flex: 1; background: #999">
|
|
317
|
+
<DkTooltipCollapse
|
|
318
|
+
:text="`行高48px,显示2行:${textVal}`"
|
|
319
|
+
:tooltip="false"
|
|
320
|
+
:line-clamp="2"
|
|
321
|
+
line-height="40px"
|
|
322
|
+
/>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
<ComCollapse class="com-collapse" :code="demoCode03" />
|
|
326
|
+
|
|
327
|
+
<div style="margin-top: 20px; width: 350px; border: 1px solid #ccc">
|
|
328
|
+
<p>设置默认最多显示2行,如果文字不够2行,就不显示展开/收起</p>
|
|
329
|
+
<DkTooltipCollapse
|
|
330
|
+
:text="wVal"
|
|
331
|
+
:tooltip="false"
|
|
332
|
+
toggle-bg="cyan"
|
|
333
|
+
toggle-hover-bg="red"
|
|
334
|
+
:line-clamp="2"
|
|
335
|
+
/>
|
|
336
|
+
<p>文字不够2行</p>
|
|
337
|
+
<DkTooltipCollapse
|
|
338
|
+
:text="wVal2"
|
|
339
|
+
:tooltip="false"
|
|
340
|
+
toggle-bg="cyan"
|
|
341
|
+
toggle-hover-bg="red"
|
|
342
|
+
:line-clamp="2"
|
|
343
|
+
/>
|
|
344
|
+
</div>
|
|
345
|
+
|
|
346
|
+
<div style="width: 500px">
|
|
347
|
+
<br>
|
|
348
|
+
<h6>注意:默认展开/收起按钮的背景色为父级背景色;如果父级不设置背景色,默认为透明:</h6>
|
|
349
|
+
<DkTooltipCollapse :text="textVal" :tooltip="false" />
|
|
350
|
+
<br>
|
|
351
|
+
<h6>设置 `toggleBg` 为自定义颜色,即可改变展开/收起按钮的背景色:</h6>
|
|
352
|
+
<DkTooltipCollapse :text="textVal" :tooltip="false" toggle-bg="#f5f5f5" />
|
|
353
|
+
<code>
|
|
354
|
+
此时会出现一个问题:"...展开"会把部分文字遮住部分,是因为设置父级的宽度不合理造成的,
|
|
355
|
+
可以自己设置 "...展开"的 css 样式,例如:
|
|
356
|
+
<pre>
|
|
357
|
+
:deep(.dk-tooltip-collapse){
|
|
358
|
+
.dk-tooltip-toggle{
|
|
359
|
+
padding-left: 25px;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
</pre>
|
|
363
|
+
</code>
|
|
364
|
+
</div>
|
|
365
|
+
|
|
366
|
+
<h3>自定义:展开/收起按钮</h3>
|
|
367
|
+
<div style="width: 472px" class="list-box">
|
|
368
|
+
<DkTooltipCollapse :tooltip="false" :text="textVal" class="my-box" toggle-hover-bg="red">
|
|
369
|
+
<template #collapse-trigger="{ isCollapsed }">
|
|
370
|
+
<el-icon>
|
|
371
|
+
<ArrowDown v-if="isCollapsed" />
|
|
372
|
+
<ArrowUp v-else />
|
|
373
|
+
</el-icon>
|
|
374
|
+
</template>
|
|
375
|
+
</DkTooltipCollapse>
|
|
376
|
+
</div>
|
|
377
|
+
<ComCollapse class="com-collapse" :code="demoCode04" />
|
|
378
|
+
|
|
379
|
+
<!-- 参数表格 -->
|
|
380
|
+
<section class="markdown-section">
|
|
381
|
+
<h2>DkTooltipCollapse 参数</h2>
|
|
382
|
+
<MarkdownRenderer :content="propsTable" />
|
|
383
|
+
<h2>Slots 插槽</h2>
|
|
384
|
+
<MarkdownRenderer :content="slotsTable" />
|
|
385
|
+
</section>
|
|
386
|
+
</div>
|
|
387
|
+
</template>
|
|
388
|
+
|
|
389
|
+
<style lang="scss" scoped>
|
|
390
|
+
// @import url('@/assets/styles/demo.scss');
|
|
391
|
+
.box-item {
|
|
392
|
+
:deep(.el-tooltip__popper) {
|
|
393
|
+
transform: translate(-60%, -100%) !important;
|
|
394
|
+
margin: 0 !important;
|
|
395
|
+
}
|
|
396
|
+
:deep(.el-tooltip__popper.is-dark) {
|
|
397
|
+
transform: translate(-60%, -100%) !important;
|
|
398
|
+
margin: 0 !important;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
:deep(.my-box) {
|
|
403
|
+
&.is-expanded {
|
|
404
|
+
.dk-tooltip-toggle {
|
|
405
|
+
bottom: 0 !important;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.list-box {
|
|
411
|
+
background: yellowgreen;
|
|
412
|
+
&:hover {
|
|
413
|
+
background: red;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
:deep(.com-collapse) {
|
|
417
|
+
.el-collapse-item__header {
|
|
418
|
+
padding-left: 20px;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
</style>
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 组件属性接口
|
|
6
|
+
*/
|
|
7
|
+
interface Props {
|
|
8
|
+
/** 目标数字 */
|
|
9
|
+
value?: number
|
|
10
|
+
/** 动画持续时间(毫秒),默认 1200ms */
|
|
11
|
+
duration?: number
|
|
12
|
+
/** 缓动函数类型,默认 'easeOutQuad' */
|
|
13
|
+
easing?: 'easeOutQuad' | 'easeOutCubic' | 'linear'
|
|
14
|
+
/** 是否显示千分号,默认 false */
|
|
15
|
+
thousandsSeparator?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
19
|
+
/** 目标数字 */
|
|
20
|
+
value: 0,
|
|
21
|
+
/** 动画持续时间(毫秒),默认 1200ms */
|
|
22
|
+
duration: 1200,
|
|
23
|
+
/** 缓动函数类型,默认 'easeOutQuad' */
|
|
24
|
+
easing: 'easeOutQuad',
|
|
25
|
+
/** 是否显示千分号,默认 false */
|
|
26
|
+
thousandsSeparator: false,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
/** 当前显示的数字 */
|
|
30
|
+
const count = ref(0)
|
|
31
|
+
/** 动画请求 ID,用于取消动画 */
|
|
32
|
+
let animationId: number | null = null
|
|
33
|
+
/** 动画开始时间戳 */
|
|
34
|
+
let startTime: number | null = null
|
|
35
|
+
/** 动画起始数值 */
|
|
36
|
+
let startValue = 0
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 缓动函数集合
|
|
40
|
+
*/
|
|
41
|
+
const easingFunctions = {
|
|
42
|
+
/** 线性缓动 */
|
|
43
|
+
linear: (t: number) => t,
|
|
44
|
+
/** 二次缓动(先快后慢) */
|
|
45
|
+
easeOutQuad: (t: number) => t * (2 - t),
|
|
46
|
+
/** 三次缓动(更柔和的先快后慢) */
|
|
47
|
+
easeOutCubic: (t: number) => --t * t * t + 1,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 动画帧回调函数
|
|
52
|
+
* @param timestamp - 时间戳
|
|
53
|
+
*/
|
|
54
|
+
function animate(timestamp: number) {
|
|
55
|
+
// 记录开始时间
|
|
56
|
+
if (!startTime) {
|
|
57
|
+
startTime = timestamp
|
|
58
|
+
}
|
|
59
|
+
// 计算动画进度 (0-1)
|
|
60
|
+
const progress = Math.min((timestamp - startTime) / props.duration, 1)
|
|
61
|
+
// 获取缓动函数
|
|
62
|
+
const easingFn = easingFunctions[props.easing]
|
|
63
|
+
// 应用缓动函数
|
|
64
|
+
const easedProgress = easingFn(progress)
|
|
65
|
+
// 计算当前数字
|
|
66
|
+
const currentNumber = startValue + (props.value - startValue) * easedProgress
|
|
67
|
+
count.value = currentNumber
|
|
68
|
+
|
|
69
|
+
// 继续下一帧或结束动画
|
|
70
|
+
if (progress < 1) {
|
|
71
|
+
animationId = requestAnimationFrame(animate)
|
|
72
|
+
} else {
|
|
73
|
+
count.value = props.value
|
|
74
|
+
animationId = null
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 开始数字滚动动画
|
|
80
|
+
*/
|
|
81
|
+
function startAnimation() {
|
|
82
|
+
// 取消之前的动画
|
|
83
|
+
if (animationId) {
|
|
84
|
+
cancelAnimationFrame(animationId)
|
|
85
|
+
}
|
|
86
|
+
// 重置开始时间
|
|
87
|
+
startTime = null
|
|
88
|
+
// 记录当前值作为起始值
|
|
89
|
+
startValue = count.value
|
|
90
|
+
// 开始新动画
|
|
91
|
+
animationId = requestAnimationFrame(animate)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 获取数字的小数位数
|
|
96
|
+
* @param num - 数字
|
|
97
|
+
* @returns 小数位数
|
|
98
|
+
*/
|
|
99
|
+
function getDecimalPlaces(num: number): number {
|
|
100
|
+
const str = num.toString()
|
|
101
|
+
const dotIndex = str.indexOf('.')
|
|
102
|
+
return dotIndex === -1 ? 0 : str.length - dotIndex - 1
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 去除小数尾部多余的零
|
|
107
|
+
* @param str - 数字字符串
|
|
108
|
+
* @returns 处理后的字符串
|
|
109
|
+
*/
|
|
110
|
+
function stripTrailingZeros(str: string): string {
|
|
111
|
+
// 更安全的正则,避免超线性回溯
|
|
112
|
+
const dotIndex = str.indexOf('.')
|
|
113
|
+
if (dotIndex === -1) {
|
|
114
|
+
return str
|
|
115
|
+
}
|
|
116
|
+
let end = str.length
|
|
117
|
+
while (end > dotIndex + 1 && str.charAt(end - 1) === '0') {
|
|
118
|
+
end--
|
|
119
|
+
}
|
|
120
|
+
return str.slice(0, end)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 格式化显示的数字
|
|
125
|
+
*/
|
|
126
|
+
const formattedCount = computed(() => {
|
|
127
|
+
const decimalPlaces = getDecimalPlaces(props.value)
|
|
128
|
+
const fixedNumber = count.value.toFixed(decimalPlaces)
|
|
129
|
+
const stripped = stripTrailingZeros(fixedNumber)
|
|
130
|
+
if (props.thousandsSeparator) {
|
|
131
|
+
const parts = stripped.split('.')
|
|
132
|
+
parts[0]! = parts[0]!.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
133
|
+
return parts.join('.')
|
|
134
|
+
}
|
|
135
|
+
return stripped
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 监听关键属性变化,重新触发动画
|
|
140
|
+
*/
|
|
141
|
+
watch([() => props.value, () => props.duration, () => props.easing], () => {
|
|
142
|
+
startAnimation()
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* 组件挂载时启动动画
|
|
147
|
+
*/
|
|
148
|
+
onMounted(() => {
|
|
149
|
+
startAnimation()
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 组件卸载时清理动画,防止内存泄漏
|
|
154
|
+
*/
|
|
155
|
+
onUnmounted(() => {
|
|
156
|
+
if (animationId) {
|
|
157
|
+
cancelAnimationFrame(animationId)
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
</script>
|
|
161
|
+
|
|
162
|
+
<template>
|
|
163
|
+
<!-- 数字滚动组件 -->
|
|
164
|
+
<div class="counter number-tabular number-modern">
|
|
165
|
+
{{ formattedCount }}
|
|
166
|
+
</div>
|
|
167
|
+
</template>
|
|
168
|
+
|
|
169
|
+
<style scoped lang="scss">
|
|
170
|
+
.counter {
|
|
171
|
+
font-weight: 800;
|
|
172
|
+
}
|
|
173
|
+
/* 示例:为数字指定一个等宽字体,让它们占位宽度相同,利于对齐 */
|
|
174
|
+
.number-tabular {
|
|
175
|
+
/* 'Courier New', 'Consolas' 等是常见的等宽字体,数字默认等宽 */
|
|
176
|
+
font-family: 'Courier New', 'SF Mono', 'Consolas', monospace;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* 示例:使用系统默认的 sans-serif 字体,让数字显示更现代 */
|
|
180
|
+
.number-modern {
|
|
181
|
+
font-family: 'Inter', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
|
|
182
|
+
}
|
|
183
|
+
</style>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import ComCollapse from '@/components/CodeCollapse.vue'
|
|
3
|
+
import MarkdownRenderer from '@/components/MarkdownRenderer.vue'
|
|
4
|
+
import RollNumber from '../src/index.vue'
|
|
5
|
+
|
|
6
|
+
const code = ref(`
|
|
7
|
+
<p>基础用法</p>
|
|
8
|
+
<RollNumber :value="50000" :duration="3000" />
|
|
9
|
+
<p>小数位</p>
|
|
10
|
+
<RollNumber :value="50000.123456789" :duration="3000" />
|
|
11
|
+
<p>千分位</p>
|
|
12
|
+
<RollNumber :value="1234567" :duration="3000" :thousands-separator="true" />
|
|
13
|
+
<p class="color-jb">千分位+小数位</p>
|
|
14
|
+
<RollNumber
|
|
15
|
+
:value="1234567.123456789"
|
|
16
|
+
:duration="3000"
|
|
17
|
+
:thousands-separator="true"
|
|
18
|
+
/>
|
|
19
|
+
|
|
20
|
+
import { RollNumber } from '@shimmerUI/comp';
|
|
21
|
+
`)
|
|
22
|
+
|
|
23
|
+
// Markdown表格内容
|
|
24
|
+
const propsTable = ref(`
|
|
25
|
+
| 参数名 | 说明 | 类型 | 默认值 |
|
|
26
|
+
|--------|------|------|-------|
|
|
27
|
+
| value | 值 | Number | |
|
|
28
|
+
| duration | 动画持续时间(毫秒) | Number | 1200 |
|
|
29
|
+
| easing | 缓动函数类型 | String | 'easeOutQuad' |
|
|
30
|
+
| thousandsSeparator | 是否显示千分号 | Boolean | false |
|
|
31
|
+
`)
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<div class="demo-container height-stretch overflow-auto-y custom-scrollbar-gradient">
|
|
36
|
+
<!-- 标题 -->
|
|
37
|
+
<h2>数字滚动组件-RollNumber</h2>
|
|
38
|
+
|
|
39
|
+
<!-- 组件示例展示 -->
|
|
40
|
+
<section class="demo-section">
|
|
41
|
+
<div class="demo-block">
|
|
42
|
+
<p>基础用法</p>
|
|
43
|
+
<RollNumber :value="50000" :duration="3000" />
|
|
44
|
+
<p>小数位</p>
|
|
45
|
+
<RollNumber :value="50000.123456789" :duration="3000" />
|
|
46
|
+
<p>千分位</p>
|
|
47
|
+
<RollNumber :value="1234567" :duration="3000" :thousands-separator="true" />
|
|
48
|
+
<p class="color-jb">
|
|
49
|
+
千分位+小数位
|
|
50
|
+
</p>
|
|
51
|
+
<RollNumber :value="1234567.123456789" :duration="3000" :thousands-separator="true" />
|
|
52
|
+
</div>
|
|
53
|
+
<ComCollapse class="com-collapse" :code="code" />
|
|
54
|
+
</section>
|
|
55
|
+
|
|
56
|
+
<!-- 参数表格 -->
|
|
57
|
+
<section>
|
|
58
|
+
<h2>RollNumber API</h2>
|
|
59
|
+
<MarkdownRenderer :content="propsTable" />
|
|
60
|
+
</section>
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
|
|
64
|
+
<style scoped lang="scss">
|
|
65
|
+
.demo-container {
|
|
66
|
+
padding: 20px;
|
|
67
|
+
background-color: #fff;
|
|
68
|
+
}
|
|
69
|
+
.demo-block {
|
|
70
|
+
font-size: 30px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
:deep(.com-collapse) {
|
|
74
|
+
.el-collapse-item__header {
|
|
75
|
+
padding-left: 20px;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
</style>
|