@hbdlzy/ui-core 0.1.0 → 0.1.2
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 +61 -3
- package/components.manifest.json +239 -24
- package/dist/index.cjs +1 -1
- package/dist/index.js +3005 -13
- package/dist/style.css +1 -0
- package/package.json +5 -3
- package/src/components/BaseCard/BaseCard.types.ts +38 -0
- package/src/components/BaseCard/BaseCard.vue +250 -0
- package/src/components/BaseCard/README.md +164 -0
- package/src/components/BaseCard/index.ts +5 -0
- package/src/components/BaseEChart/BaseEChart.types.ts +35 -0
- package/src/components/BaseEChart/BaseEChart.vue +327 -0
- package/src/components/BaseEChart/README.md +136 -0
- package/src/components/BaseEChart/index.ts +5 -0
- package/src/components/BaseExportButton/BaseExportButton.vue +1 -1
- package/src/components/BaseExportButton/README.md +104 -8
- package/src/components/BaseTable/BaseTable.types.ts +174 -0
- package/src/components/BaseTable/BaseTable.vue +809 -0
- package/src/components/BaseTable/README.md +398 -0
- package/src/components/BaseTable/index.ts +25 -0
- package/src/components/OutlinedCascader/OutlinedCascader.types.ts +28 -0
- package/src/components/OutlinedCascader/OutlinedCascader.vue +250 -0
- package/src/components/OutlinedCascader/README.md +91 -0
- package/src/components/OutlinedCascader/index.ts +10 -0
- package/src/components/OutlinedDatePicker/OutlinedDatePicker.types.ts +40 -0
- package/src/components/OutlinedDatePicker/OutlinedDatePicker.vue +365 -0
- package/src/components/OutlinedDatePicker/README.md +137 -0
- package/src/components/OutlinedDatePicker/index.ts +11 -0
- package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.types.ts +34 -0
- package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.vue +421 -0
- package/src/components/OutlinedDateTimePicker/README.md +88 -0
- package/src/components/OutlinedDateTimePicker/index.ts +11 -0
- package/src/components/OutlinedInput/OutlinedInput.types.ts +32 -0
- package/src/components/OutlinedInput/OutlinedInput.vue +307 -0
- package/src/components/OutlinedInput/README.md +154 -0
- package/src/components/OutlinedInput/index.ts +10 -0
- package/src/components/OutlinedSelect/OutlinedSelect.types.ts +48 -0
- package/src/components/OutlinedSelect/OutlinedSelect.vue +359 -0
- package/src/components/OutlinedSelect/README.md +166 -0
- package/src/components/OutlinedSelect/index.ts +12 -0
- package/src/components/OutlinedTimePicker/OutlinedTimePicker.types.ts +36 -0
- package/src/components/OutlinedTimePicker/OutlinedTimePicker.vue +303 -0
- package/src/components/OutlinedTimePicker/README.md +93 -0
- package/src/components/OutlinedTimePicker/index.ts +10 -0
- package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.types.ts +56 -0
- package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.vue +354 -0
- package/src/components/OutlinedTreeSelect/README.md +107 -0
- package/src/components/OutlinedTreeSelect/index.ts +12 -0
- package/src/echarts/index.ts +12 -0
- package/src/excel/exportExcel.ts +36 -10
- package/src/index.ts +29 -0
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.base-card[data-v-6bfddf1c]{display:flex;flex-direction:column;min-width:0;min-height:0;padding:var(--base-card-padding);border:1px solid var(--base-card-border-color);background:var(--base-card-background-color);box-shadow:0 0 2px 0 var(--base-card-shadow-color);border-radius:var(--base-card-radius)}.base-card__header[data-v-6bfddf1c]{display:flex;align-items:center;justify-content:space-between;gap:var(--base-card-header-gap);margin-bottom:var(--base-card-header-margin-bottom);min-height:24px;flex-wrap:wrap}.base-card__header-left[data-v-6bfddf1c],.base-card__header-right[data-v-6bfddf1c]{display:flex;align-items:center;min-width:0;flex-wrap:wrap}.base-card__header-left[data-v-6bfddf1c]{flex:1 1 auto;gap:var(--base-card-left-gap)}.base-card__header-right[data-v-6bfddf1c]{flex:0 1 auto;justify-content:flex-end;gap:var(--base-card-right-gap)}.base-card__title-wrap[data-v-6bfddf1c]{display:flex;align-items:center;min-width:0}.base-card__title-marker[data-v-6bfddf1c]{width:var(--base-card-marker-width);height:var(--base-card-marker-height);background:var(--base-card-marker-color);border-radius:var(--base-card-marker-radius);margin-right:var(--base-card-marker-gap);flex:0 0 auto}.base-card__title[data-v-6bfddf1c]{margin:0;min-width:0;color:var(--base-card-title-color);font-size:var(--base-card-title-size);font-weight:var(--base-card-title-weight);line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.base-card__meta[data-v-6bfddf1c]{color:var(--base-card-meta-color);font-size:var(--base-card-meta-size);line-height:1.4}.base-card__export[data-v-6bfddf1c]{border:none;background:transparent;padding:0;color:var(--base-card-export-color);cursor:pointer;font-size:var(--base-card-meta-size);line-height:1.4}.base-card__export[data-v-6bfddf1c]:disabled{opacity:.5;cursor:not-allowed}.base-card__body[data-v-6bfddf1c]{display:flex;flex:1 1 auto;flex-direction:column;min-height:0}.base-card__tip[data-v-6bfddf1c]{flex:0 0 auto}.base-card__content[data-v-6bfddf1c]{flex:1 1 auto;min-height:0}.base-table[data-v-429ba785]{display:flex;flex-direction:column;height:100%;min-height:0}.base-table__toolbar[data-v-429ba785]{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:16px;min-height:32px;flex-wrap:wrap}.base-table__toolbar-left[data-v-429ba785]{flex:1 1 auto;min-width:0}.base-table__toolbar-right[data-v-429ba785]{flex:0 1 auto}.base-table__actions[data-v-429ba785]{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.base-table__link[data-v-429ba785]{padding:0;border:none;background:transparent;color:var(--el-color-primary);cursor:pointer}.base-table__text[data-v-429ba785]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.base-table__tags[data-v-429ba785]{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.base-table__image[data-v-429ba785]{border-radius:4px;overflow:hidden}.base-echart[data-v-51bc4772],.base-echart__inner[data-v-51bc4772]{width:100%;height:100%}.outlined-input[data-v-2bf89ccd]{position:relative}.outlined-input__label[data-v-2bf89ccd]{position:absolute;left:-2px;padding:2px 5px;border-radius:2px;background-color:#fff;font-size:12px;line-height:1;transition:color .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1);pointer-events:none}.outlined-input__label--floating[data-v-2bf89ccd]{top:18px;z-index:1;opacity:1;transform:translate(14px,-6px) scale(1);color:var(--el-color-primary)}.outlined-input__label--placeholder[data-v-2bf89ccd]{top:50%;left:1px;z-index:-1;opacity:0;transform:translate(14px,6px) scale(1)}.outlined-input__label--filled[data-v-2bf89ccd]{color:var(--el-text-color-regular)}.outlined-input__suffix-text[data-v-2bf89ccd]{white-space:nowrap}[data-v-2bf89ccd] .outlined-input--bordered .el-input__wrapper{box-shadow:none;border-radius:0;border-bottom:1px solid #cccccc}[data-v-2bf89ccd] .outlined-input--bordered .el-input__wrapper.is-focus{border-bottom-color:var(--el-color-primary)}[data-v-2bf89ccd] .outlined-input--bordered .el-textarea__inner{border-width:0 0 1px;border-radius:0;box-shadow:none}[data-v-2bf89ccd] .outlined-input--bordered .el-textarea__inner:focus{border-bottom-color:var(--el-color-primary)}[data-v-2bf89ccd] .outlined-input--textarea-default .el-textarea__inner{min-height:100px!important;max-height:180px}.outlined-select[data-v-7bd2b5f2]{position:relative}.outlined-select__label[data-v-7bd2b5f2]{position:absolute;left:-2px;padding:2px 5px;border-radius:2px;background-color:#fff;font-size:12px;line-height:1;transition:color .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1);pointer-events:none}.outlined-select__label--floating[data-v-7bd2b5f2]{top:18px;z-index:1;opacity:1;transform:translate(14px,-6px) scale(1);color:var(--el-color-primary)}.outlined-select__label--placeholder[data-v-7bd2b5f2]{top:50%;left:1px;z-index:-1;opacity:0;transform:translate(14px,6px) scale(1)}.outlined-select__label--filled[data-v-7bd2b5f2]{color:var(--el-text-color-regular)}[data-v-7bd2b5f2] .outlined-select__control.el-select{width:100%}[data-v-7bd2b5f2] .outlined-select__control .el-select__wrapper{min-height:inherit;height:inherit}[data-v-7bd2b5f2] .outlined-select__control .el-select__tags{padding-top:4px}[data-v-7bd2b5f2] .outlined-select__control .el-select__selection{min-height:inherit}[data-v-7bd2b5f2] .outlined-select--bordered .el-select__wrapper{box-shadow:none;border-radius:0;border-bottom:1px solid #cccccc}[data-v-7bd2b5f2] .outlined-select--bordered .el-select__wrapper.is-focused{border-bottom-color:var(--el-color-primary)}.outlined-date-picker[data-v-c95a293c]{position:relative}.outlined-date-picker__label[data-v-c95a293c]{position:absolute;left:-2px;padding:2px 5px;border-radius:2px;background-color:#fff;font-size:12px;line-height:1;transition:color .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1);pointer-events:none}.outlined-date-picker__label--floating[data-v-c95a293c]{top:18px;z-index:1;opacity:1;transform:translate(14px,-6px) scale(1);color:var(--el-color-primary)}.outlined-date-picker__label--placeholder[data-v-c95a293c]{top:50%;left:1px;z-index:-1;opacity:0;transform:translate(14px,6px) scale(1)}.outlined-date-picker__label--filled[data-v-c95a293c]{color:var(--el-text-color-regular)}[data-v-c95a293c] .outlined-date-picker__control.el-date-editor{width:100%}[data-v-c95a293c] .outlined-date-picker__control .el-input__wrapper{position:relative;min-height:inherit;height:inherit}[data-v-c95a293c] .outlined-date-picker__control .el-input__prefix{position:absolute;right:0}[data-v-c95a293c] .outlined-date-picker__control .el-input__suffix{position:absolute;right:30px}[data-v-c95a293c] .outlined-date-picker--bordered .el-input__wrapper{box-shadow:none;border-radius:0;border-bottom:1px solid #cccccc}[data-v-c95a293c] .outlined-date-picker--bordered .el-input__wrapper.is-focus{border-bottom-color:var(--el-color-primary)}.outlined-date-time-picker[data-v-f2fefd22]{display:flex;align-items:center;gap:8px}.outlined-date-time-picker__field[data-v-f2fefd22]{position:relative;flex:1}.outlined-date-time-picker__separator[data-v-f2fefd22]{flex:0 0 auto;color:var(--el-text-color-regular)}.outlined-date-time-picker__label[data-v-f2fefd22]{position:absolute;left:-2px;padding:2px 5px;border-radius:2px;background-color:#fff;font-size:12px;line-height:1;transition:color .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1);pointer-events:none}.outlined-date-time-picker__label--floating[data-v-f2fefd22]{top:18px;z-index:1;opacity:1;transform:translate(14px,-6px) scale(1);color:var(--el-color-primary)}.outlined-date-time-picker__label--placeholder[data-v-f2fefd22]{top:50%;left:1px;z-index:-1;opacity:0;transform:translate(14px,6px) scale(1)}.outlined-date-time-picker__label--filled[data-v-f2fefd22]{color:var(--el-text-color-regular)}[data-v-f2fefd22] .outlined-date-time-picker__control.el-date-editor{width:100%}[data-v-f2fefd22] .outlined-date-time-picker__control .el-input__wrapper{position:relative;min-height:inherit;height:inherit}[data-v-f2fefd22] .outlined-date-time-picker__control .el-input__prefix{position:absolute;right:0}[data-v-f2fefd22] .outlined-date-time-picker__control .el-input__suffix{position:absolute;right:30px}[data-v-f2fefd22] .outlined-date-time-picker__field--bordered .el-input__wrapper{box-shadow:none;border-radius:0;border-bottom:1px solid #cccccc}[data-v-f2fefd22] .outlined-date-time-picker__field--bordered .el-input__wrapper.is-focus{border-bottom-color:var(--el-color-primary)}.outlined-time-picker[data-v-6a467b88]{position:relative}.outlined-time-picker__label[data-v-6a467b88]{position:absolute;left:-2px;padding:2px 5px;border-radius:2px;background-color:#fff;font-size:12px;line-height:1;transition:color .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1);pointer-events:none}.outlined-time-picker__label--floating[data-v-6a467b88]{top:18px;z-index:1;opacity:1;transform:translate(14px,-6px) scale(1);color:var(--el-color-primary)}.outlined-time-picker__label--placeholder[data-v-6a467b88]{top:50%;left:1px;z-index:-1;opacity:0;transform:translate(14px,6px) scale(1)}.outlined-time-picker__label--filled[data-v-6a467b88]{color:var(--el-text-color-regular)}[data-v-6a467b88] .outlined-time-picker__control.el-date-editor{width:100%}[data-v-6a467b88] .outlined-time-picker__control .el-input__wrapper{position:relative;min-height:inherit;height:inherit}[data-v-6a467b88] .outlined-time-picker__control .el-input__prefix{position:absolute;right:0}[data-v-6a467b88] .outlined-time-picker__control .el-input__suffix{position:absolute;right:30px}[data-v-6a467b88] .outlined-time-picker--bordered .el-input__wrapper{box-shadow:none;border-radius:0;border-bottom:1px solid #cccccc}[data-v-6a467b88] .outlined-time-picker--bordered .el-input__wrapper.is-focus{border-bottom-color:var(--el-color-primary)}.outlined-cascader[data-v-2c93c0e4]{position:relative}.outlined-cascader__label[data-v-2c93c0e4]{position:absolute;left:-2px;padding:2px 5px;border-radius:2px;background-color:#fff;font-size:12px;line-height:1;transition:color .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1);pointer-events:none}.outlined-cascader__label--floating[data-v-2c93c0e4]{top:18px;z-index:1;opacity:1;transform:translate(14px,-6px) scale(1);color:var(--el-color-primary)}.outlined-cascader__label--placeholder[data-v-2c93c0e4]{top:50%;left:1px;z-index:-1;opacity:0;transform:translate(14px,6px) scale(1)}.outlined-cascader__label--filled[data-v-2c93c0e4]{color:var(--el-text-color-regular)}[data-v-2c93c0e4] .outlined-cascader__control .el-input{height:100%}[data-v-2c93c0e4] .outlined-cascader--bordered .el-input__wrapper{box-shadow:none;border-radius:0;border-bottom:1px solid #cccccc}[data-v-2c93c0e4] .outlined-cascader--bordered .el-input__wrapper.is-focus{border-bottom-color:var(--el-color-primary)}.outlined-tree-select[data-v-8403e6ea]{position:relative}.outlined-tree-select__label[data-v-8403e6ea]{position:absolute;left:-2px;padding:2px 5px;border-radius:2px;background-color:#fff;font-size:12px;line-height:1;transition:color .2s cubic-bezier(0,0,.2,1),transform .2s cubic-bezier(0,0,.2,1);pointer-events:none}.outlined-tree-select__label--floating[data-v-8403e6ea]{top:18px;z-index:1;opacity:1;transform:translate(14px,-6px) scale(1);color:var(--el-color-primary)}.outlined-tree-select__label--placeholder[data-v-8403e6ea]{top:50%;left:1px;z-index:-1;opacity:0;transform:translate(14px,6px) scale(1)}.outlined-tree-select__label--filled[data-v-8403e6ea]{color:var(--el-text-color-regular)}[data-v-8403e6ea] .outlined-tree-select__control.el-select{width:100%}[data-v-8403e6ea] .outlined-tree-select__control .el-select__wrapper{min-height:inherit;height:inherit}[data-v-8403e6ea] .outlined-tree-select__control .el-select__selection{min-height:inherit}[data-v-8403e6ea] .outlined-tree-select__control .el-select__tags{padding-top:4px}[data-v-8403e6ea] .outlined-tree-select--bordered .el-select__wrapper{box-shadow:none;border-radius:0;border-bottom:1px solid #cccccc}[data-v-8403e6ea] .outlined-tree-select--bordered .el-select__wrapper.is-focused{border-bottom-color:var(--el-color-primary)}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hbdlzy/ui-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Company shared Vue UI core package.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -30,8 +30,10 @@
|
|
|
30
30
|
"vue": "^3.5.14"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"
|
|
34
|
-
"
|
|
33
|
+
"dayjs": "^1.11.13",
|
|
34
|
+
"echarts": "^5.5.1",
|
|
35
|
+
"exceljs": "^4.4.0",
|
|
36
|
+
"file-saver": "2.0.5"
|
|
35
37
|
},
|
|
36
38
|
"sideEffects": [
|
|
37
39
|
"**/*.css",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type BaseCardCssValue = string | number
|
|
2
|
+
|
|
3
|
+
export interface BaseCardDefaultExportPayload {
|
|
4
|
+
title?: string
|
|
5
|
+
metaText?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface BaseCardProps {
|
|
9
|
+
title?: string
|
|
10
|
+
metaText?: string
|
|
11
|
+
showHeader?: boolean
|
|
12
|
+
showRight?: boolean
|
|
13
|
+
showTitleMarker?: boolean
|
|
14
|
+
showExport?: boolean
|
|
15
|
+
exportText?: string
|
|
16
|
+
exportDisabled?: boolean
|
|
17
|
+
exportPayload?: unknown
|
|
18
|
+
padding?: BaseCardCssValue
|
|
19
|
+
radius?: BaseCardCssValue
|
|
20
|
+
borderColor?: string
|
|
21
|
+
backgroundColor?: string
|
|
22
|
+
shadowColor?: string
|
|
23
|
+
headerGap?: BaseCardCssValue
|
|
24
|
+
headerMarginBottom?: BaseCardCssValue
|
|
25
|
+
leftGap?: BaseCardCssValue
|
|
26
|
+
rightGap?: BaseCardCssValue
|
|
27
|
+
titleColor?: string
|
|
28
|
+
titleSize?: BaseCardCssValue
|
|
29
|
+
titleWeight?: string | number
|
|
30
|
+
markerColor?: string
|
|
31
|
+
markerWidth?: BaseCardCssValue
|
|
32
|
+
markerHeight?: BaseCardCssValue
|
|
33
|
+
markerRadius?: BaseCardCssValue
|
|
34
|
+
markerGap?: BaseCardCssValue
|
|
35
|
+
metaColor?: string
|
|
36
|
+
metaSize?: BaseCardCssValue
|
|
37
|
+
exportColor?: string
|
|
38
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="base-card" :style="cardStyles">
|
|
3
|
+
<div v-if="shouldRenderHeader" class="base-card__header">
|
|
4
|
+
<div class="base-card__header-left">
|
|
5
|
+
<div v-if="hasTitleBlock" class="base-card__title-wrap">
|
|
6
|
+
<span v-if="showTitleMarker" class="base-card__title-marker"></span>
|
|
7
|
+
<slot v-if="$slots['title-label']" name="title-label"></slot>
|
|
8
|
+
<h4 v-else class="base-card__title">{{ title }}</h4>
|
|
9
|
+
</div>
|
|
10
|
+
<slot name="title"></slot>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div v-if="hasRightSection" class="base-card__header-right">
|
|
14
|
+
<slot name="header-right"></slot>
|
|
15
|
+
<span v-if="metaText" class="base-card__meta">{{ metaText }}</span>
|
|
16
|
+
<button
|
|
17
|
+
v-if="showExport"
|
|
18
|
+
class="base-card__export"
|
|
19
|
+
type="button"
|
|
20
|
+
:disabled="exportDisabled"
|
|
21
|
+
@click="handleExport"
|
|
22
|
+
>
|
|
23
|
+
{{ exportText }}
|
|
24
|
+
</button>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="base-card__body">
|
|
29
|
+
<div v-if="$slots.tip" class="base-card__tip">
|
|
30
|
+
<slot name="tip"></slot>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="base-card__content">
|
|
33
|
+
<slot></slot>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script setup lang="ts">
|
|
40
|
+
import { computed, useSlots } from 'vue'
|
|
41
|
+
import type { BaseCardCssValue, BaseCardDefaultExportPayload, BaseCardProps } from './BaseCard.types'
|
|
42
|
+
|
|
43
|
+
defineOptions({
|
|
44
|
+
name: 'BaseCard'
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const props = withDefaults(defineProps<BaseCardProps>(), {
|
|
48
|
+
title: '',
|
|
49
|
+
metaText: '',
|
|
50
|
+
showHeader: true,
|
|
51
|
+
showRight: true,
|
|
52
|
+
showTitleMarker: true,
|
|
53
|
+
showExport: false,
|
|
54
|
+
exportText: '导出',
|
|
55
|
+
exportDisabled: false,
|
|
56
|
+
padding: 20,
|
|
57
|
+
radius: 8,
|
|
58
|
+
borderColor: 'var(--border-color)',
|
|
59
|
+
backgroundColor: 'var(--border-bg-color)',
|
|
60
|
+
shadowColor: 'var(--border-projection)',
|
|
61
|
+
headerGap: 16,
|
|
62
|
+
headerMarginBottom: 20,
|
|
63
|
+
leftGap: 16,
|
|
64
|
+
rightGap: 16,
|
|
65
|
+
titleColor: 'var(--el-text-color-primary)',
|
|
66
|
+
titleSize: 18,
|
|
67
|
+
titleWeight: 500,
|
|
68
|
+
markerColor: 'var(--el-color-primary)',
|
|
69
|
+
markerWidth: 4,
|
|
70
|
+
markerHeight: 24,
|
|
71
|
+
markerRadius: '0 4px 4px 0',
|
|
72
|
+
markerGap: 10,
|
|
73
|
+
metaColor: '#808080',
|
|
74
|
+
metaSize: 16,
|
|
75
|
+
exportColor: 'var(--el-color-primary)'
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const emit = defineEmits<{
|
|
79
|
+
(event: 'export', payload?: unknown): void
|
|
80
|
+
}>()
|
|
81
|
+
|
|
82
|
+
const slots = useSlots()
|
|
83
|
+
|
|
84
|
+
const hasTitleBlock = computed(() => Boolean(props.title) || Boolean(slots['title-label']))
|
|
85
|
+
const hasTitleExtra = computed(() => Boolean(slots.title))
|
|
86
|
+
const hasRightExtra = computed(() => Boolean(slots['header-right']))
|
|
87
|
+
|
|
88
|
+
const hasRightSection = computed(
|
|
89
|
+
() => props.showRight && (hasRightExtra.value || Boolean(props.metaText) || props.showExport)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
const shouldRenderHeader = computed(
|
|
93
|
+
() => props.showHeader && (hasTitleBlock.value || hasTitleExtra.value || hasRightSection.value)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
const defaultExportPayload = computed<BaseCardDefaultExportPayload>(() => ({
|
|
97
|
+
title: props.title || undefined,
|
|
98
|
+
metaText: props.metaText || undefined
|
|
99
|
+
}))
|
|
100
|
+
|
|
101
|
+
const cardStyles = computed<Record<string, string | undefined>>(() => ({
|
|
102
|
+
'--base-card-padding': toCssValue(props.padding),
|
|
103
|
+
'--base-card-radius': toCssValue(props.radius),
|
|
104
|
+
'--base-card-border-color': props.borderColor,
|
|
105
|
+
'--base-card-background-color': props.backgroundColor,
|
|
106
|
+
'--base-card-shadow-color': props.shadowColor,
|
|
107
|
+
'--base-card-header-gap': toCssValue(props.headerGap),
|
|
108
|
+
'--base-card-header-margin-bottom': toCssValue(props.headerMarginBottom),
|
|
109
|
+
'--base-card-left-gap': toCssValue(props.leftGap),
|
|
110
|
+
'--base-card-right-gap': toCssValue(props.rightGap),
|
|
111
|
+
'--base-card-title-color': props.titleColor,
|
|
112
|
+
'--base-card-title-size': toCssValue(props.titleSize),
|
|
113
|
+
'--base-card-title-weight': toTextValue(props.titleWeight),
|
|
114
|
+
'--base-card-marker-color': props.markerColor,
|
|
115
|
+
'--base-card-marker-width': toCssValue(props.markerWidth),
|
|
116
|
+
'--base-card-marker-height': toCssValue(props.markerHeight),
|
|
117
|
+
'--base-card-marker-radius': toCssValue(props.markerRadius),
|
|
118
|
+
'--base-card-marker-gap': toCssValue(props.markerGap),
|
|
119
|
+
'--base-card-meta-color': props.metaColor,
|
|
120
|
+
'--base-card-meta-size': toCssValue(props.metaSize),
|
|
121
|
+
'--base-card-export-color': props.exportColor
|
|
122
|
+
}))
|
|
123
|
+
|
|
124
|
+
const handleExport = () => {
|
|
125
|
+
emit('export', props.exportPayload === undefined ? defaultExportPayload.value : props.exportPayload)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function toCssValue(value?: BaseCardCssValue, unit = 'px') {
|
|
129
|
+
if (value === undefined || value === null || value === '') {
|
|
130
|
+
return undefined
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return typeof value === 'number' ? `${value}${unit}` : value
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function toTextValue(value?: string | number) {
|
|
137
|
+
if (value === undefined || value === null || value === '') {
|
|
138
|
+
return undefined
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return String(value)
|
|
142
|
+
}
|
|
143
|
+
</script>
|
|
144
|
+
|
|
145
|
+
<style scoped>
|
|
146
|
+
.base-card {
|
|
147
|
+
display: flex;
|
|
148
|
+
flex-direction: column;
|
|
149
|
+
min-width: 0;
|
|
150
|
+
min-height: 0;
|
|
151
|
+
padding: var(--base-card-padding);
|
|
152
|
+
border: 1px solid var(--base-card-border-color);
|
|
153
|
+
background: var(--base-card-background-color);
|
|
154
|
+
box-shadow: 0 0 2px 0 var(--base-card-shadow-color);
|
|
155
|
+
border-radius: var(--base-card-radius);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.base-card__header {
|
|
159
|
+
display: flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
justify-content: space-between;
|
|
162
|
+
gap: var(--base-card-header-gap);
|
|
163
|
+
margin-bottom: var(--base-card-header-margin-bottom);
|
|
164
|
+
min-height: 24px;
|
|
165
|
+
flex-wrap: wrap;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.base-card__header-left,
|
|
169
|
+
.base-card__header-right {
|
|
170
|
+
display: flex;
|
|
171
|
+
align-items: center;
|
|
172
|
+
min-width: 0;
|
|
173
|
+
flex-wrap: wrap;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.base-card__header-left {
|
|
177
|
+
flex: 1 1 auto;
|
|
178
|
+
gap: var(--base-card-left-gap);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.base-card__header-right {
|
|
182
|
+
flex: 0 1 auto;
|
|
183
|
+
justify-content: flex-end;
|
|
184
|
+
gap: var(--base-card-right-gap);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.base-card__title-wrap {
|
|
188
|
+
display: flex;
|
|
189
|
+
align-items: center;
|
|
190
|
+
min-width: 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.base-card__title-marker {
|
|
194
|
+
width: var(--base-card-marker-width);
|
|
195
|
+
height: var(--base-card-marker-height);
|
|
196
|
+
background: var(--base-card-marker-color);
|
|
197
|
+
border-radius: var(--base-card-marker-radius);
|
|
198
|
+
margin-right: var(--base-card-marker-gap);
|
|
199
|
+
flex: 0 0 auto;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.base-card__title {
|
|
203
|
+
margin: 0;
|
|
204
|
+
min-width: 0;
|
|
205
|
+
color: var(--base-card-title-color);
|
|
206
|
+
font-size: var(--base-card-title-size);
|
|
207
|
+
font-weight: var(--base-card-title-weight);
|
|
208
|
+
line-height: 1.4;
|
|
209
|
+
white-space: nowrap;
|
|
210
|
+
overflow: hidden;
|
|
211
|
+
text-overflow: ellipsis;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.base-card__meta {
|
|
215
|
+
color: var(--base-card-meta-color);
|
|
216
|
+
font-size: var(--base-card-meta-size);
|
|
217
|
+
line-height: 1.4;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.base-card__export {
|
|
221
|
+
border: none;
|
|
222
|
+
background: transparent;
|
|
223
|
+
padding: 0;
|
|
224
|
+
color: var(--base-card-export-color);
|
|
225
|
+
cursor: pointer;
|
|
226
|
+
font-size: var(--base-card-meta-size);
|
|
227
|
+
line-height: 1.4;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.base-card__export:disabled {
|
|
231
|
+
opacity: 0.5;
|
|
232
|
+
cursor: not-allowed;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.base-card__body {
|
|
236
|
+
display: flex;
|
|
237
|
+
flex: 1 1 auto;
|
|
238
|
+
flex-direction: column;
|
|
239
|
+
min-height: 0;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.base-card__tip {
|
|
243
|
+
flex: 0 0 auto;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.base-card__content {
|
|
247
|
+
flex: 1 1 auto;
|
|
248
|
+
min-height: 0;
|
|
249
|
+
}
|
|
250
|
+
</style>
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# BaseCard
|
|
2
|
+
|
|
3
|
+
`BaseCard` 用来统一封装项目里反复出现的卡片容器、标题区、右侧信息区和导出触发区,避免页面层重复写相同的布局和样式代码。
|
|
4
|
+
|
|
5
|
+
## 解决的问题
|
|
6
|
+
|
|
7
|
+
- 页面只传标题和内容就能得到统一卡片样式
|
|
8
|
+
- 内聚边框、背景、圆角、阴影,不再依赖业务项目里的全局 `.border-card`
|
|
9
|
+
- 标题左侧竖杠、标题颜色、右侧信息、导出按钮都可以直接配置
|
|
10
|
+
- 左右两侧都支持插槽扩展,复杂场景不用回退到重复写结构
|
|
11
|
+
|
|
12
|
+
## 适用场景
|
|
13
|
+
|
|
14
|
+
- 看板类页面里的统计卡片、图表卡片、列表卡片
|
|
15
|
+
- 需要统一标题区布局和风格的容器组件
|
|
16
|
+
- 标题右侧要放时间、按钮、筛选器、单选框的场景
|
|
17
|
+
- 希望把“卡片壳子”从业务组件里抽出来统一复用
|
|
18
|
+
|
|
19
|
+
## 不适用场景
|
|
20
|
+
|
|
21
|
+
- 页面需要完全脱离统一卡片风格
|
|
22
|
+
- 整个容器结构与标题区布局都要做高度定制
|
|
23
|
+
- 只是简单边框盒子,不需要标题区、插槽区和统一视觉规范
|
|
24
|
+
|
|
25
|
+
## 基础用法
|
|
26
|
+
|
|
27
|
+
```vue
|
|
28
|
+
<template>
|
|
29
|
+
<BaseCard title="今日收益趋势">
|
|
30
|
+
<div style="height: 320px">这里放图表或其他内容</div>
|
|
31
|
+
</BaseCard>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script setup lang="ts">
|
|
35
|
+
import { BaseCard } from '@hbdlzy/ui-core'
|
|
36
|
+
</script>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 带右侧信息和导出按钮
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<template>
|
|
43
|
+
<BaseCard
|
|
44
|
+
title="收益数据"
|
|
45
|
+
meta-text="2026-04-21 10:30"
|
|
46
|
+
show-export
|
|
47
|
+
:export-payload="{ url: '/report/export' }"
|
|
48
|
+
@export="handleExport"
|
|
49
|
+
>
|
|
50
|
+
<div>内容区域</div>
|
|
51
|
+
</BaseCard>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script setup lang="ts">
|
|
55
|
+
import { BaseCard } from '@hbdlzy/ui-core'
|
|
56
|
+
|
|
57
|
+
const handleExport = (payload?: unknown) => {
|
|
58
|
+
console.log('export payload', payload)
|
|
59
|
+
}
|
|
60
|
+
</script>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 标题区扩展
|
|
64
|
+
|
|
65
|
+
`title` 插槽会出现在左侧标题后面,适合放筛选器、单选框、标签等内容。`header-right` 插槽会出现在右侧信息区里,适合放按钮或自定义操作。
|
|
66
|
+
|
|
67
|
+
```vue
|
|
68
|
+
<template>
|
|
69
|
+
<BaseCard title="市场信息" meta-text="实时更新">
|
|
70
|
+
<template #title>
|
|
71
|
+
<el-radio-group v-model="tabValue">
|
|
72
|
+
<el-radio-button label="日内" />
|
|
73
|
+
<el-radio-button label="周内" />
|
|
74
|
+
</el-radio-group>
|
|
75
|
+
</template>
|
|
76
|
+
|
|
77
|
+
<template #header-right>
|
|
78
|
+
<el-button text>刷新</el-button>
|
|
79
|
+
</template>
|
|
80
|
+
|
|
81
|
+
<template #tip>
|
|
82
|
+
<div style="text-align: right; color: #808080">单位:万元</div>
|
|
83
|
+
</template>
|
|
84
|
+
|
|
85
|
+
<div>内容区域</div>
|
|
86
|
+
</BaseCard>
|
|
87
|
+
</template>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 配置样式
|
|
91
|
+
|
|
92
|
+
```vue
|
|
93
|
+
<BaseCard
|
|
94
|
+
title="自定义样式"
|
|
95
|
+
marker-color="#23c343"
|
|
96
|
+
marker-height="20px"
|
|
97
|
+
title-color="#ffffff"
|
|
98
|
+
border-color="rgba(35, 195, 67, 0.35)"
|
|
99
|
+
background-color="rgba(5, 18, 35, 0.9)"
|
|
100
|
+
:padding="24"
|
|
101
|
+
>
|
|
102
|
+
<div>内容区域</div>
|
|
103
|
+
</BaseCard>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Props
|
|
107
|
+
|
|
108
|
+
- `title`: 标题文本
|
|
109
|
+
- `metaText`: 右侧信息文本,常用于时间、更新时间、单位等
|
|
110
|
+
- `showHeader`: 是否显示标题区
|
|
111
|
+
- `showRight`: 是否显示右侧容器
|
|
112
|
+
- `showTitleMarker`: 是否显示标题左侧竖杠
|
|
113
|
+
- `showExport`: 是否显示内置导出按钮
|
|
114
|
+
- `exportText`: 导出按钮文案,默认 `导出`
|
|
115
|
+
- `exportDisabled`: 是否禁用导出按钮
|
|
116
|
+
- `exportPayload`: 点击导出时回传的自定义载荷
|
|
117
|
+
- `padding`: 卡片内边距
|
|
118
|
+
- `radius`: 卡片圆角
|
|
119
|
+
- `borderColor`: 卡片边框颜色
|
|
120
|
+
- `backgroundColor`: 卡片背景色
|
|
121
|
+
- `shadowColor`: 卡片阴影颜色
|
|
122
|
+
- `headerGap`: 标题区左右块之间的间距
|
|
123
|
+
- `headerMarginBottom`: 标题区和内容区之间的间距
|
|
124
|
+
- `leftGap`: 左侧标题块和扩展插槽之间的间距
|
|
125
|
+
- `rightGap`: 右侧内容之间的间距
|
|
126
|
+
- `titleColor`: 标题颜色
|
|
127
|
+
- `titleSize`: 标题字号
|
|
128
|
+
- `titleWeight`: 标题字重
|
|
129
|
+
- `markerColor`: 标题左侧竖杠颜色
|
|
130
|
+
- `markerWidth`: 标题左侧竖杠宽度
|
|
131
|
+
- `markerHeight`: 标题左侧竖杠高度
|
|
132
|
+
- `markerRadius`: 标题左侧竖杠圆角
|
|
133
|
+
- `markerGap`: 标题左侧竖杠和标题的间距
|
|
134
|
+
- `metaColor`: 右侧信息文字颜色
|
|
135
|
+
- `metaSize`: 右侧信息文字字号
|
|
136
|
+
- `exportColor`: 导出按钮颜色
|
|
137
|
+
|
|
138
|
+
## Slots
|
|
139
|
+
|
|
140
|
+
- 默认插槽:卡片主体内容
|
|
141
|
+
- `title`: 左侧标题后的扩展区域
|
|
142
|
+
- `title-label`: 自定义标题内容,会替代默认标题文本
|
|
143
|
+
- `header-right`: 右侧操作区扩展
|
|
144
|
+
- `tip`: 内容区顶部提示信息
|
|
145
|
+
|
|
146
|
+
## Events
|
|
147
|
+
|
|
148
|
+
- `export`: 点击内置导出按钮时触发
|
|
149
|
+
|
|
150
|
+
如果未传 `exportPayload`,默认会返回:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
{
|
|
154
|
+
title?: string
|
|
155
|
+
metaText?: string
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## 推荐约定
|
|
160
|
+
|
|
161
|
+
- 页面层优先把统计块、图表块、列表块统一包在 `BaseCard` 里
|
|
162
|
+
- 只要不是强业务容器,就尽量不要在页面层重复写卡片壳子
|
|
163
|
+
- 简单场景直接用 `title + 默认插槽`
|
|
164
|
+
- 需要扩展时优先使用 `title` 和 `header-right` 插槽,而不是复制组件结构
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EChartInitOptions,
|
|
3
|
+
EChartInstance,
|
|
4
|
+
EChartLoadingOptions,
|
|
5
|
+
EChartOption,
|
|
6
|
+
EChartResizeOptions,
|
|
7
|
+
EChartSetOptionOptions
|
|
8
|
+
} from '../../echarts'
|
|
9
|
+
|
|
10
|
+
export interface BaseEChartProps {
|
|
11
|
+
option?: EChartOption
|
|
12
|
+
theme?: string | Record<string, unknown>
|
|
13
|
+
initOptions?: EChartInitOptions
|
|
14
|
+
setOptionOptions?: boolean | EChartSetOptionOptions
|
|
15
|
+
loading?: boolean
|
|
16
|
+
loadingOptions?: EChartLoadingOptions
|
|
17
|
+
autoResize?: boolean
|
|
18
|
+
useDefaultColors?: boolean
|
|
19
|
+
colorStorageKey?: string
|
|
20
|
+
defaultColors?: string[]
|
|
21
|
+
group?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface BaseEChartExpose {
|
|
25
|
+
getInstance: () => EChartInstance | null
|
|
26
|
+
setOption: (option: EChartOption, setOptionOptions?: boolean | EChartSetOptionOptions) => EChartInstance | null
|
|
27
|
+
resize: (resizeOptions?: EChartResizeOptions) => void
|
|
28
|
+
dispatchAction: (payload: Record<string, unknown>) => void
|
|
29
|
+
showLoading: (type?: string, loadingOptions?: EChartLoadingOptions) => void
|
|
30
|
+
hideLoading: () => void
|
|
31
|
+
clear: () => void
|
|
32
|
+
dispose: () => void
|
|
33
|
+
on: (eventName: string, handler: (...args: any[]) => void, context?: unknown) => void
|
|
34
|
+
off: (eventName?: string, handler?: (...args: any[]) => void) => void
|
|
35
|
+
}
|