@vela-studio/ui 1.0.1
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 +152 -0
- package/dist/index.d.ts +696 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +11786 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.umd.js +10 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/style.css +1 -0
- package/index.ts +150 -0
- package/package.json +73 -0
- package/src/components/advanced/scripting/Scripting.vue +189 -0
- package/src/components/advanced/state/State.vue +231 -0
- package/src/components/advanced/trigger/Trigger.vue +256 -0
- package/src/components/basic/button/Button.vue +120 -0
- package/src/components/basic/container/Container.vue +22 -0
- package/src/components/chart/barChart/barChart.vue +176 -0
- package/src/components/chart/doughnutChart/doughnutChart.vue +128 -0
- package/src/components/chart/funnelChart/funnelChart.vue +128 -0
- package/src/components/chart/gaugeChart/gaugeChart.vue +144 -0
- package/src/components/chart/lineChart/lineChart.vue +188 -0
- package/src/components/chart/pieChart/pieChart.vue +114 -0
- package/src/components/chart/radarChart/radarChart.vue +115 -0
- package/src/components/chart/sankeyChart/sankeyChart.vue +144 -0
- package/src/components/chart/scatterChart/scatterChart.vue +162 -0
- package/src/components/chart/stackedBarChart/stackedBarChart.vue +184 -0
- package/src/components/content/html/Html.vue +104 -0
- package/src/components/content/iframe/Iframe.vue +111 -0
- package/src/components/content/markdown/Markdown.vue +174 -0
- package/src/components/controls/breadcrumb/Breadcrumb.vue +79 -0
- package/src/components/controls/buttonGroup/ButtonGroup.vue +93 -0
- package/src/components/controls/checkboxGroup/CheckboxGroup.vue +147 -0
- package/src/components/controls/dateRange/DateRange.vue +174 -0
- package/src/components/controls/multiSelect/MultiSelect.vue +155 -0
- package/src/components/controls/navButton/NavButton.vue +97 -0
- package/src/components/controls/pagination/Pagination.vue +94 -0
- package/src/components/controls/searchBox/SearchBox.vue +170 -0
- package/src/components/controls/select/Select.vue +134 -0
- package/src/components/controls/slider/Slider.vue +167 -0
- package/src/components/controls/switch/Switch.vue +107 -0
- package/src/components/data/cardGrid/CardGrid.vue +318 -0
- package/src/components/data/list/List.vue +282 -0
- package/src/components/data/pivot/Pivot.vue +270 -0
- package/src/components/data/table/Table.vue +150 -0
- package/src/components/data/timeline/Timeline.vue +315 -0
- package/src/components/group/Group.vue +75 -0
- package/src/components/kpi/box/Box.vue +98 -0
- package/src/components/kpi/countUp/CountUp.vue +193 -0
- package/src/components/kpi/progress/Progress.vue +159 -0
- package/src/components/kpi/stat/Stat.vue +205 -0
- package/src/components/kpi/text/Text.vue +74 -0
- package/src/components/layout/badge/Badge.vue +105 -0
- package/src/components/layout/col/Col.vue +114 -0
- package/src/components/layout/flex/Flex.vue +105 -0
- package/src/components/layout/grid/Grid.vue +89 -0
- package/src/components/layout/modal/Modal.vue +118 -0
- package/src/components/layout/panel/Panel.vue +162 -0
- package/src/components/layout/row/Row.vue +99 -0
- package/src/components/layout/tabs/Tabs.vue +117 -0
- package/src/components/media/image/Image.vue +132 -0
- package/src/components/media/video/Video.vue +115 -0
- package/src/components/v2/basic/BaseButton.vue +179 -0
- package/src/components/v2/kpi/KpiCard.vue +215 -0
- package/src/components/v2/layout/GridBox.vue +55 -0
- package/src/hooks/useDataSource.ts +123 -0
- package/src/types/gis.ts +251 -0
- package/src/utils/chartUtils.ts +349 -0
- package/src/utils/dataUtils.ts +403 -0
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.scripting-container[data-v-a842ba5d]{display:flex;flex-direction:column;gap:12px;height:100%}.header[data-v-a842ba5d]{display:flex;justify-content:space-between;align-items:center;padding-bottom:8px;border-bottom:1px solid #3c3c3c}.title[data-v-a842ba5d]{display:flex;align-items:center;gap:6px;font-weight:600;font-size:16px}.section-title[data-v-a842ba5d]{font-size:12px;opacity:.7;margin-bottom:6px;text-transform:uppercase}.code-section[data-v-a842ba5d]{flex-shrink:0}.code-block[data-v-a842ba5d]{margin:0;padding:12px;background:#0000004d;border-radius:4px;overflow-x:auto;white-space:pre-wrap;word-wrap:break-word}.output-section[data-v-a842ba5d]{flex:1;min-height:0;display:flex;flex-direction:column}.output-block[data-v-a842ba5d]{flex:1;margin:0;padding:12px;background:#0003;border-radius:4px;overflow:auto;white-space:pre-wrap;word-wrap:break-word;color:#4ec9b0}.error-output[data-v-a842ba5d]{flex:1;padding:12px;background:#dc26261a;border:1px solid rgba(220,38,38,.3);border-radius:4px;color:#f87171;overflow:auto}.placeholder[data-v-a842ba5d]{display:flex;flex-direction:column;justify-content:center;align-items:center;flex:1;gap:8px;opacity:.5}.placeholder .el-icon[data-v-a842ba5d]{font-size:32px}.state-container[data-v-d334f558]{display:flex;flex-direction:column;gap:12px;height:100%}.header[data-v-d334f558]{display:flex;justify-content:space-between;align-items:center;padding-bottom:8px;border-bottom:1px solid #3c3c3c}.title[data-v-d334f558]{display:flex;align-items:center;gap:6px;font-weight:600;font-size:16px}.state-list[data-v-d334f558]{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:8px}.state-item[data-v-d334f558]{padding:12px;background:#0003;border-radius:4px;border:1px solid rgba(255,255,255,.1)}.state-key[data-v-d334f558]{display:flex;align-items:center;gap:6px;font-weight:600;margin-bottom:6px;color:#4fc3f7}.state-value[data-v-d334f558]{display:flex;align-items:center;gap:8px;padding-left:24px}.value-text[data-v-d334f558]{flex:1;word-break:break-all}.json-view[data-v-d334f558]{flex:1;overflow:auto}.json-block[data-v-d334f558]{margin:0;padding:12px;background:#0000004d;border-radius:4px;white-space:pre;overflow-x:auto;color:#9cdcfe}.table-view[data-v-d334f558]{flex:1;overflow:auto}.placeholder[data-v-d334f558]{display:flex;flex-direction:column;justify-content:center;align-items:center;flex:1;gap:8px;opacity:.5}.placeholder .el-icon[data-v-d334f558]{font-size:32px}.trigger-container[data-v-8a732abe]{display:flex;flex-direction:column;gap:12px;height:100%}.header[data-v-8a732abe]{display:flex;justify-content:space-between;align-items:center;padding-bottom:8px;border-bottom:1px solid #3c3c3c}.title[data-v-8a732abe]{display:flex;align-items:center;gap:6px;font-weight:600;font-size:16px}.controls[data-v-8a732abe]{display:flex;gap:8px;align-items:center}.info-section[data-v-8a732abe]{display:flex;gap:16px;flex-wrap:wrap;padding:8px 0}.info-item[data-v-8a732abe]{display:flex;align-items:center;gap:6px}.label[data-v-8a732abe]{opacity:.7;font-size:12px}.section-title[data-v-8a732abe]{font-size:12px;opacity:.7;margin-bottom:8px;text-transform:uppercase}.logs-section[data-v-8a732abe]{flex:1;min-height:0;display:flex;flex-direction:column}.logs-container[data-v-8a732abe]{flex:1;overflow-y:auto;background:#0000004d;border-radius:4px;padding:8px}.log-item[data-v-8a732abe]{display:flex;gap:12px;padding:6px 8px;margin-bottom:4px;border-radius:3px;font-size:12px;border-left:3px solid transparent}.log-info[data-v-8a732abe]{background:#3b82f61a;border-left-color:#3b82f6}.log-success[data-v-8a732abe]{background:#22c55e1a;border-left-color:#22c55e}.log-warning[data-v-8a732abe]{background:#fbbf241a;border-left-color:#fbbf24}.log-error[data-v-8a732abe]{background:#ef44441a;border-left-color:#ef4444}.log-time[data-v-8a732abe]{opacity:.6;flex-shrink:0;width:80px}.log-message[data-v-8a732abe]{flex:1;word-break:break-all}.placeholder[data-v-8a732abe]{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;gap:8px;opacity:.5}.placeholder .el-icon[data-v-8a732abe]{font-size:32px}.v-container[data-v-b420dc1d]{box-sizing:border-box;position:relative;min-height:50px}.v-bar-chart[data-v-63999390],.echart[data-v-63999390],.v-doughnut-chart[data-v-1651b0b6],.echart[data-v-1651b0b6],.v-funnel-chart[data-v-0beabf00],.echart[data-v-0beabf00],.v-gauge-chart[data-v-f996aeef],.echart[data-v-f996aeef],.v-line-chart[data-v-da6535a9],.echart[data-v-da6535a9],.v-pie-chart[data-v-721c1618],.echart[data-v-721c1618],.v-radar-chart[data-v-a6f641d1],.echart[data-v-a6f641d1],.v-sankey-chart[data-v-b5838036],.echart[data-v-b5838036],.v-scatter-chart[data-v-312d4826],.echart[data-v-312d4826],.v-stacked-bar-chart[data-v-6ed5b757],.echart[data-v-6ed5b757]{width:100%;height:100%}.html-container[data-v-6e6f6510],.html-container[data-v-6e6f6510] *{box-sizing:border-box}.html-container[data-v-6e6f6510] img{max-width:100%;height:auto}.html-container[data-v-6e6f6510] table{border-collapse:collapse;width:100%}.html-container[data-v-6e6f6510] table th,.html-container[data-v-6e6f6510] table td{padding:8px;border:1px solid #ddd}.html-container[data-v-6e6f6510] a{color:#409eff;text-decoration:none}.html-container[data-v-6e6f6510] a:hover{text-decoration:underline}.iframe-container[data-v-7d8f952d]{position:relative}.iframe-mask[data-v-7d8f952d]{position:absolute;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1;pointer-events:auto}.runtime-mode{display:none}.iframe-placeholder[data-v-7d8f952d]{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%;color:#909399;font-size:14px;gap:8px;background-color:#f5f7fa}.iframe-placeholder .el-icon[data-v-7d8f952d]{font-size:48px;color:#c0c4cc}.markdown-body[data-v-73416739]{box-sizing:border-box}.markdown-body[data-v-73416739] h1,.markdown-body[data-v-73416739] h2,.markdown-body[data-v-73416739] h3,.markdown-body[data-v-73416739] h4,.markdown-body[data-v-73416739] h5,.markdown-body[data-v-73416739] h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body[data-v-73416739] h1{font-size:2em;border-bottom:1px solid #eaecef;padding-bottom:.3em}.markdown-body[data-v-73416739] h2{font-size:1.5em;border-bottom:1px solid #eaecef;padding-bottom:.3em}.markdown-body[data-v-73416739] h3{font-size:1.25em}.markdown-body[data-v-73416739] p{margin-top:0;margin-bottom:16px}.markdown-body[data-v-73416739] ul,.markdown-body[data-v-73416739] ol{padding-left:2em;margin-top:0;margin-bottom:16px}.markdown-body[data-v-73416739] li{margin-bottom:4px}.markdown-body[data-v-73416739] code{padding:.2em .4em;margin:0;font-size:85%;background-color:#afb8c133;border-radius:6px;font-family:monospace}.markdown-body[data-v-73416739] pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:6px;margin-bottom:16px}.markdown-body[data-v-73416739] pre code{background-color:transparent;padding:0}.markdown-body[data-v-73416739] blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5;margin:0 0 16px}.markdown-body[data-v-73416739] table{border-collapse:collapse;width:100%;margin-bottom:16px}.markdown-body[data-v-73416739] table th,.markdown-body[data-v-73416739] table td{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body[data-v-73416739] table th{font-weight:600;background-color:#f6f8fa}.markdown-body[data-v-73416739] img{max-width:100%;box-sizing:content-box}.markdown-body[data-v-73416739] a{color:#0366d6;text-decoration:none}.markdown-body[data-v-73416739] a:hover{text-decoration:underline}.custom-breadcrumb[data-v-a480654b]{padding:8px 16px}.link[data-v-a480654b]{cursor:pointer;color:var(--breadcrumb-link-color, #409eff)}.link[data-v-a480654b]:hover{text-decoration:underline}.current[data-v-a480654b]{color:var(--breadcrumb-active-color, #909399)}[data-v-812ca27f] .el-button-group{display:flex}[data-v-baa6f88d] .el-checkbox-group{display:flex;flex-direction:var(--v0c48ab70);gap:var(--v02d3b180)}[data-v-baa6f88d] .el-checkbox{--el-checkbox-checked-bg-color: var(--v531127bf);--el-checkbox-checked-input-border-color: var(--v53533c6e);--el-checkbox-input-border-color: var(--v69bc1e63);--el-checkbox-text-color: var(--v29640901)}[data-v-baa6f88d] .el-checkbox-button{--el-checkbox-button-checked-bg-color: var(--v531127bf);--el-checkbox-button-checked-border-color: var(--v53533c6e)}.date-range-container[data-v-4992eb7f],.multi-select-container[data-v-b009a2c2]{box-sizing:border-box}.nav-button[data-v-4f78f794]{-webkit-user-select:none;user-select:none;font-weight:500}.nav-button[data-v-4f78f794]:hover{filter:brightness(1.1);transform:translateY(-1px)}.nav-button[data-v-4f78f794]:active{transform:translateY(0);filter:brightness(.95)}.nav-icon[data-v-4f78f794]{flex-shrink:0}.nav-label[data-v-4f78f794]{white-space:nowrap}.pagination-container[data-v-36bfc009]{display:flex;justify-content:center;padding:8px}[data-v-36bfc009] .el-pagination{justify-content:center}.el-input[data-v-75e631db]{width:var(--v548c0e80);font-size:var(--v05978894)}[data-v-75e631db] .el-input__wrapper{--el-input-border-color: var(--fc02e812);--el-input-focus-border-color: var(--v78a9160c);--el-input-hover-border-color: var(--v1ade65b0)}[data-v-75e631db] .el-input__inner{color:var(--v7b9fe278)}[data-v-75e631db] .el-input__inner::placeholder{color:var(--v74d660ec)}.select-container[data-v-34a8e7c2]{box-sizing:border-box}.slider-value[data-v-19b2dde7]{margin-top:8px}[data-v-19b2dde7] .el-slider{--el-slider-main-bg-color: var(--v106b612d);--el-slider-runway-bg-color: var(--v2f9594c2);--el-slider-button-size: var(--v6b7e6a0c)}[data-v-6666ea8d] .el-switch{--el-switch-on-color: var(--f73eaa90);--el-switch-off-color: var(--v094fa838);--el-switch-border-color: var(--v69c07005)}.card-grid-container[data-v-76760ba3]{box-sizing:border-box}.empty-state[data-v-76760ba3]{display:flex;align-items:center;justify-content:center;min-height:200px}.grid-wrapper[data-v-76760ba3]{width:100%}.grid-card[data-v-76760ba3]:hover{transform:translateY(-4px);box-shadow:0 4px 12px #00000026}.card-image img[data-v-76760ba3]{width:100%;height:100%;object-fit:cover}.card-content[data-v-76760ba3]{display:flex;flex-direction:column}.card-tags[data-v-76760ba3]{display:flex;flex-wrap:wrap;margin-top:4px;margin-right:-6px}.list-container[data-v-48008813]{box-sizing:border-box}.empty-state[data-v-48008813]{display:flex;align-items:center;justify-content:center;min-height:200px}.list-wrapper[data-v-48008813]{width:100%}.list-item[data-v-48008813]{display:flex;align-items:center;gap:12px;box-sizing:border-box}.list-item[data-v-48008813]:hover{background-color:#f5f7fa!important}.item-icon[data-v-48008813]{flex-shrink:0;display:flex;align-items:center;justify-content:center}.item-content[data-v-48008813]{flex:1;min-width:0}.item-title[data-v-48008813]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.item-description[data-v-48008813]{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical}.item-extra[data-v-48008813]{margin-top:4px}.item-action[data-v-48008813]{flex-shrink:0;color:#c0c4cc;display:flex;align-items:center}.pivot-container[data-v-0b1303d7]{box-sizing:border-box}.empty-state[data-v-0b1303d7]{display:flex;align-items:center;justify-content:center;min-height:200px}.table-container[data-v-a1dc5b93]{box-sizing:border-box;padding:0}[data-v-a1dc5b93] .el-table{width:100%;height:100%}.timeline-container[data-v-6ae929c9]{box-sizing:border-box}.empty-state[data-v-6ae929c9]{display:flex;align-items:center;justify-content:center;min-height:200px}.card-header[data-v-6ae929c9]{display:flex;justify-content:space-between;align-items:center}.card-title[data-v-6ae929c9]{flex:1}.card-time[data-v-6ae929c9]{font-size:13px;color:#909399;font-weight:400;margin-left:12px}.card-content[data-v-6ae929c9]{margin:0}.card-extra[data-v-6ae929c9]{padding-top:8px;border-top:1px solid #ebeef5}.timeline-content[data-v-6ae929c9]{padding:8px 0}.content-title[data-v-6ae929c9]{margin-bottom:4px}.content-text[data-v-6ae929c9]{margin:0}.content-extra[data-v-6ae929c9]{padding-top:6px}.group-container[data-v-3fa8648d]{position:relative;width:100%;height:100%}.group-placeholder[data-v-3fa8648d]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#909399;font-size:12px;opacity:.5;pointer-events:none}.v-box-container[data-v-96ba1c0c]{box-sizing:border-box}.v-box-content[data-v-96ba1c0c]{word-break:break-word;white-space:pre-wrap}.v-countup-container[data-v-44399741]{box-sizing:border-box}[data-v-44399741] .el-statistic{text-align:center;display:flex;align-items:center;justify-content:center;box-sizing:border-box}.v-progress-container[data-v-02d37fd3]{box-sizing:border-box}[data-v-02d37fd3] .el-progress{width:100%}[data-v-02d37fd3] .el-progress__text{font-size:inherit!important;color:var(--v13e3249a)}.v-stat-card[data-v-c0db472f]{box-sizing:border-box}.v-stat-header[data-v-c0db472f]{margin-bottom:8px}.v-stat-title[data-v-c0db472f]{font-size:14px;color:#909399;margin:0}.v-stat-body[data-v-c0db472f]{display:flex;align-items:center;gap:12px;flex:1}.v-stat-icon[data-v-c0db472f]{display:flex;align-items:center}.v-stat-value[data-v-c0db472f]{line-height:1}.v-stat-footer[data-v-c0db472f]{margin-top:8px}.v-stat-change[data-v-c0db472f]{font-weight:500}.v-text[data-v-0045cea2]{word-break:break-word;white-space:pre-wrap}.v-badge-container[data-v-97776e64]{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box}[data-v-97776e64] .el-badge{display:inline-flex;align-items:center;justify-content:center}[data-v-97776e64] .el-badge__content{font-size:inherit!important}.v-col[data-v-082964dd]{box-sizing:border-box}.v-col-placeholder[data-v-082964dd]{width:100%}.v-flex-container[data-v-162d144a]{box-sizing:border-box}.v-flex-placeholder[data-v-162d144a]{width:100%}.v-grid-container[data-v-8229882e]{box-sizing:border-box;width:100%}.v-grid-placeholder-item[data-v-8229882e]{padding:12px;background-color:#f3f4f6;border-radius:4px;text-align:center}.v-modal-footer[data-v-a28442e3]{display:flex;justify-content:flex-end;gap:8px}.v-modal-body[data-v-a28442e3]{box-sizing:border-box}.v-panel[data-v-e72601fb]{box-sizing:border-box;width:100%}.v-panel-header[data-v-e72601fb]{-webkit-user-select:none;user-select:none}.v-panel-collapse-icon[data-v-e72601fb]{font-size:12px}.v-panel-body[data-v-e72601fb],.v-panel-footer[data-v-e72601fb]{box-sizing:border-box}.v-row[data-v-c97c26e7]{width:100%;box-sizing:border-box}.v-row-placeholder[data-v-c97c26e7]{width:100%}.v-tabs-container[data-v-97eccaf6]{box-sizing:border-box;width:100%}.image-error[data-v-07b84e1b],.image-loading[data-v-07b84e1b],.image-placeholder[data-v-07b84e1b]{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%;color:#909399;font-size:14px;gap:8px;background-color:#f5f7fa}.image-error .el-icon[data-v-07b84e1b],.image-loading .el-icon[data-v-07b84e1b],.image-placeholder .el-icon[data-v-07b84e1b]{font-size:48px;color:#c0c4cc}.is-loading[data-v-07b84e1b]{animation:rotating-07b84e1b 2s linear infinite}@keyframes rotating-07b84e1b{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.video-placeholder[data-v-ef4cae83]{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%;color:#909399;font-size:14px;gap:8px;background-color:#000}.video-placeholder .el-icon[data-v-ef4cae83]{font-size:64px;color:#606266}.v-button[data-v-14cbbdfe]{display:inline-flex;justify-content:center;align-items:center;line-height:1;height:32px;white-space:nowrap;cursor:pointer;color:#606266;text-align:center;box-sizing:border-box;outline:none;margin:0;transition:.1s;font-weight:500;-webkit-user-select:none;user-select:none;vertical-align:middle;background-color:#fff;border:1px solid #dcdfe6;padding:8px 15px;font-size:14px;border-radius:4px}.v-button[data-v-14cbbdfe]:hover,.v-button[data-v-14cbbdfe]:focus{color:#409eff;border-color:#c6e2ff;background-color:#ecf5ff}.v-button[data-v-14cbbdfe]:active{color:#3a8ee6;border-color:#3a8ee6;outline:none}.v-button.is-disabled[data-v-14cbbdfe]{color:#c0c4cc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#ebeef5}.v-button--large[data-v-14cbbdfe]{height:40px;padding:12px 19px;font-size:14px}.v-button--small[data-v-14cbbdfe]{height:24px;padding:5px 11px;font-size:12px}.v-button--primary[data-v-14cbbdfe]{color:#fff;background-color:#409eff;border-color:#409eff}.v-button--primary[data-v-14cbbdfe]:not(.is-disabled):hover{background-color:#66b1ff;border-color:#66b1ff}.v-button.is-round[data-v-14cbbdfe]{border-radius:20px}.v-button.is-circle[data-v-14cbbdfe]{border-radius:50%;padding:8px;min-width:32px}.v-stat-card__header[data-v-cfba101d]{display:flex;align-items:center;margin-bottom:8px}.v-stat-card__tooltip-icon[data-v-cfba101d]{margin-left:4px;cursor:help;font-size:12px;color:#909399}.v-stat-card__content[data-v-cfba101d]{flex:1;display:flex;align-items:center}.v-stat-card__value-wrapper[data-v-cfba101d]{display:flex;align-items:baseline}.v-stat-card__prefix[data-v-cfba101d],.v-stat-card__suffix[data-v-cfba101d]{font-size:14px;color:#606266;margin:0 4px}.v-stat-card__footer[data-v-cfba101d]{margin-top:12px;padding-top:12px;border-top:1px solid #ebeef5}.v-stat-card__trend[data-v-cfba101d]{display:flex;align-items:center;font-size:12px}.v-stat-card__trend.is-up[data-v-cfba101d]{color:#f56c6c}.v-stat-card__trend.is-down[data-v-cfba101d]{color:#67c23a}.v-stat-card__trend.is-normal[data-v-cfba101d]{color:#909399}.trend-label[data-v-cfba101d]{margin-right:8px}.trend-icon[data-v-cfba101d]{margin-left:4px;font-weight:700}.v-grid[data-v-db3ad218]{margin:0;padding:0}
|
package/index.ts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type { App, Component } from 'vue'
|
|
2
|
+
// @vela/ui/index.ts
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 使用 Vite 的 import.meta.glob 动态导入所有组件
|
|
6
|
+
* 这样新增组件只需在对应目录创建 .vue 文件,无需手动注册
|
|
7
|
+
*/
|
|
8
|
+
const componentModules = import.meta.glob<{ default: Component }>('./src/components/**/*.vue', {
|
|
9
|
+
eager: true,
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 从文件路径提取组件名称
|
|
14
|
+
* 例如:'./src/components/chart/lineChart/lineChart.vue' -> 'lineChart'
|
|
15
|
+
* './src/components/kpi/text/Text.vue' -> 'vText'
|
|
16
|
+
*/
|
|
17
|
+
function extractComponentName(path: string): string {
|
|
18
|
+
const match = path.match(/\/([^/]+)\.vue$/)
|
|
19
|
+
if (!match || !match[1]) return ''
|
|
20
|
+
|
|
21
|
+
const fileName = match[1]
|
|
22
|
+
|
|
23
|
+
// 对于非图表组件,如果文件名首字母是大写,添加 'v' 前缀
|
|
24
|
+
// 图表组件保持原名(如 lineChart, barChart)
|
|
25
|
+
if (path.includes('/chart/')) {
|
|
26
|
+
return fileName
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 其他组件:如果首字母大写,加 'v' 前缀
|
|
30
|
+
const firstChar = fileName.charAt(0)
|
|
31
|
+
if (firstChar && firstChar === firstChar.toUpperCase()) {
|
|
32
|
+
return `v${fileName}`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return fileName
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 动态构建组件注册表
|
|
39
|
+
const componentRegistry: Record<string, Component> = {}
|
|
40
|
+
|
|
41
|
+
for (const path in componentModules) {
|
|
42
|
+
const mod = componentModules[path]
|
|
43
|
+
const componentName = extractComponentName(path)
|
|
44
|
+
if (componentName && mod?.default) {
|
|
45
|
+
componentRegistry[componentName] = mod.default
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 图表组件
|
|
50
|
+
export const lineChart = componentRegistry.lineChart
|
|
51
|
+
export const barChart = componentRegistry.barChart
|
|
52
|
+
export const pieChart = componentRegistry.pieChart
|
|
53
|
+
export const doughnutChart = componentRegistry.doughnutChart
|
|
54
|
+
export const radarChart = componentRegistry.radarChart
|
|
55
|
+
export const gaugeChart = componentRegistry.gaugeChart
|
|
56
|
+
export const funnelChart = componentRegistry.funnelChart
|
|
57
|
+
export const scatterChart = componentRegistry.scatterChart
|
|
58
|
+
export const sankeyChart = componentRegistry.sankeyChart
|
|
59
|
+
export const stackedBarChart = componentRegistry.stackedBarChart
|
|
60
|
+
|
|
61
|
+
// KPI 组件
|
|
62
|
+
export const vText = componentRegistry.vText
|
|
63
|
+
export const vBox = componentRegistry.vBox
|
|
64
|
+
export const vStat = componentRegistry.vStat
|
|
65
|
+
export const vProgress = componentRegistry.vProgress
|
|
66
|
+
export const vCountUp = componentRegistry.vCountUp
|
|
67
|
+
|
|
68
|
+
// 基础组件
|
|
69
|
+
export const vContainer = componentRegistry.vContainer
|
|
70
|
+
export const vButton = componentRegistry.vButton
|
|
71
|
+
|
|
72
|
+
// 布局组件
|
|
73
|
+
export const vBadge = componentRegistry.vBadge
|
|
74
|
+
export const vPanel = componentRegistry.vPanel
|
|
75
|
+
export const vFlex = componentRegistry.vFlex
|
|
76
|
+
export const vGrid = componentRegistry.vGrid
|
|
77
|
+
export const vTabs = componentRegistry.vTabs
|
|
78
|
+
export const vModal = componentRegistry.vModal
|
|
79
|
+
export const vRow = componentRegistry.vRow
|
|
80
|
+
export const vCol = componentRegistry.vCol
|
|
81
|
+
|
|
82
|
+
// 数据组件
|
|
83
|
+
export const vTimeline = componentRegistry.vTimeline
|
|
84
|
+
export const vTable = componentRegistry.vTable
|
|
85
|
+
export const vList = componentRegistry.vList
|
|
86
|
+
export const vCardGrid = componentRegistry.vCardGrid
|
|
87
|
+
export const vPivot = componentRegistry.vPivot
|
|
88
|
+
|
|
89
|
+
// 控件组件
|
|
90
|
+
export const vButtonGroup = componentRegistry.vButtonGroup
|
|
91
|
+
export const vCheckboxGroup = componentRegistry.vCheckboxGroup
|
|
92
|
+
export const vDateRange = componentRegistry.vDateRange
|
|
93
|
+
export const vMultiSelect = componentRegistry.vMultiSelect
|
|
94
|
+
export const vSearchBox = componentRegistry.vSearchBox
|
|
95
|
+
export const vSelect = componentRegistry.vSelect
|
|
96
|
+
export const vSlider = componentRegistry.vSlider
|
|
97
|
+
export const vSwitch = componentRegistry.vSwitch
|
|
98
|
+
export const vNavButton = componentRegistry.vNavButton
|
|
99
|
+
export const vBreadcrumb = componentRegistry.vBreadcrumb
|
|
100
|
+
export const vPagination = componentRegistry.vPagination
|
|
101
|
+
|
|
102
|
+
// 内容组件
|
|
103
|
+
export const vHtml = componentRegistry.vHtml
|
|
104
|
+
export const vIframe = componentRegistry.vIframe
|
|
105
|
+
export const vMarkdown = componentRegistry.vMarkdown
|
|
106
|
+
|
|
107
|
+
// 媒体组件
|
|
108
|
+
export const vImage = componentRegistry.vImage
|
|
109
|
+
export const vVideo = componentRegistry.vVideo
|
|
110
|
+
|
|
111
|
+
// 高级组件
|
|
112
|
+
export const vScripting = componentRegistry.vScripting
|
|
113
|
+
export const vState = componentRegistry.vState
|
|
114
|
+
export const vTrigger = componentRegistry.vTrigger
|
|
115
|
+
|
|
116
|
+
// Group 组件
|
|
117
|
+
export const vGroup = componentRegistry.vGroup
|
|
118
|
+
|
|
119
|
+
// Standard Components (New Architecture) - Static Imports for reliability
|
|
120
|
+
import vBaseButton from './src/components/v2/basic/BaseButton.vue'
|
|
121
|
+
import vKpiCard from './src/components/v2/kpi/KpiCard.vue'
|
|
122
|
+
import vGridBox from './src/components/v2/layout/GridBox.vue'
|
|
123
|
+
|
|
124
|
+
export { vBaseButton, vKpiCard, vGridBox }
|
|
125
|
+
|
|
126
|
+
// 导出组件注册表,供外部使用
|
|
127
|
+
export { componentRegistry }
|
|
128
|
+
|
|
129
|
+
// 导出 Hooks
|
|
130
|
+
export * from './src/hooks/useDataSource'
|
|
131
|
+
|
|
132
|
+
// 导出工具函数
|
|
133
|
+
export * from './src/utils/dataUtils'
|
|
134
|
+
|
|
135
|
+
// 导出类型
|
|
136
|
+
export type { TriggerLog } from './src/components/advanced/trigger/Trigger.vue'
|
|
137
|
+
export type { GroupProps } from './src/components/group/Group.vue'
|
|
138
|
+
|
|
139
|
+
// 导出 GIS 类型
|
|
140
|
+
export * from './src/types/gis'
|
|
141
|
+
|
|
142
|
+
// 提供 Vue 插件式的安装方法
|
|
143
|
+
export default {
|
|
144
|
+
install(app: App) {
|
|
145
|
+
// 自动注册所有组件
|
|
146
|
+
for (const [name, component] of Object.entries(componentRegistry)) {
|
|
147
|
+
app.component(name, component)
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vela-studio/ui",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Vela LowCode UI Component Library - Data visualization components for Vue 3",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"vue3",
|
|
7
|
+
"ui",
|
|
8
|
+
"components",
|
|
9
|
+
"lowcode",
|
|
10
|
+
"echarts",
|
|
11
|
+
"data-visualization",
|
|
12
|
+
"dashboard"
|
|
13
|
+
],
|
|
14
|
+
"author": "twi1i9ht",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/TWILIGHT-wyf/vela-lowcode-editor.git",
|
|
19
|
+
"directory": "packages/ui"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/TWILIGHT-wyf/vela-lowcode-editor/issues"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/TWILIGHT-wyf/vela-lowcode-editor#readme",
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public",
|
|
27
|
+
"registry": "https://registry.npmjs.org/"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"index.ts",
|
|
32
|
+
"src"
|
|
33
|
+
],
|
|
34
|
+
"main": "./dist/index.js",
|
|
35
|
+
"module": "./dist/index.mjs",
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"import": "./dist/index.mjs",
|
|
41
|
+
"require": "./dist/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./dist/style.css": "./dist/style.css",
|
|
44
|
+
"./*": {
|
|
45
|
+
"types": "./dist/*.d.ts",
|
|
46
|
+
"import": "./dist/*.mjs",
|
|
47
|
+
"require": "./dist/*.js"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "vite build",
|
|
52
|
+
"build:lib": "vite build --config vite.lib.config.ts",
|
|
53
|
+
"prepublishOnly": "pnpm build:lib"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"element-plus": "^2.0.0",
|
|
57
|
+
"vue": "^3.0.0"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"dompurify": "^3.3.1",
|
|
61
|
+
"echarts": "^6.0.0",
|
|
62
|
+
"highlight.js": "^11.11.1",
|
|
63
|
+
"marked": "^17.0.1",
|
|
64
|
+
"vue-echarts": "^8.0.1"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@types/dompurify": "^3.2.0",
|
|
68
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
69
|
+
"vite": "^5.0.0",
|
|
70
|
+
"vite-plugin-dts": "^4.5.4",
|
|
71
|
+
"vue": "^3.5.22"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :style="containerStyle">
|
|
3
|
+
<div class="scripting-container">
|
|
4
|
+
<div class="header">
|
|
5
|
+
<span class="title">
|
|
6
|
+
<el-icon><Document /></el-icon>
|
|
7
|
+
{{ title }}
|
|
8
|
+
</span>
|
|
9
|
+
<el-button
|
|
10
|
+
v-if="!autoRun && showControls"
|
|
11
|
+
type="primary"
|
|
12
|
+
size="small"
|
|
13
|
+
@click="$emit('execute')"
|
|
14
|
+
>
|
|
15
|
+
执行
|
|
16
|
+
</el-button>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div v-if="showCode" class="code-section">
|
|
20
|
+
<div class="section-title">代码:</div>
|
|
21
|
+
<pre class="code-block">{{ scriptCode }}</pre>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div v-if="output || error" class="output-section">
|
|
25
|
+
<div class="section-title">输出:</div>
|
|
26
|
+
<div v-if="error" class="error-output">{{ error }}</div>
|
|
27
|
+
<pre v-else class="output-block">{{ output }}</pre>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div v-if="!output && !error && showPlaceholder" class="placeholder">
|
|
31
|
+
<el-icon><VideoPlay /></el-icon>
|
|
32
|
+
<span>{{ placeholder }}</span>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<script setup lang="ts">
|
|
39
|
+
import { computed, type CSSProperties } from 'vue'
|
|
40
|
+
import { Document, VideoPlay } from '@element-plus/icons-vue'
|
|
41
|
+
|
|
42
|
+
export interface ScriptingProps {
|
|
43
|
+
title?: string
|
|
44
|
+
scriptCode?: string
|
|
45
|
+
output?: string
|
|
46
|
+
error?: string
|
|
47
|
+
autoRun?: boolean
|
|
48
|
+
showCode?: boolean
|
|
49
|
+
showControls?: boolean
|
|
50
|
+
showPlaceholder?: boolean
|
|
51
|
+
placeholder?: string
|
|
52
|
+
// 样式
|
|
53
|
+
padding?: number
|
|
54
|
+
backgroundColor?: string
|
|
55
|
+
textColor?: string
|
|
56
|
+
fontSize?: number
|
|
57
|
+
lineHeight?: number
|
|
58
|
+
borderRadius?: number
|
|
59
|
+
border?: string
|
|
60
|
+
fontFamily?: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const props = withDefaults(defineProps<ScriptingProps>(), {
|
|
64
|
+
title: '脚本执行器',
|
|
65
|
+
scriptCode: '// 请输入 JavaScript 代码\nconsole.log("Hello World");',
|
|
66
|
+
output: '',
|
|
67
|
+
error: '',
|
|
68
|
+
autoRun: false,
|
|
69
|
+
showCode: true,
|
|
70
|
+
showControls: true,
|
|
71
|
+
showPlaceholder: true,
|
|
72
|
+
placeholder: '点击执行按钮运行脚本',
|
|
73
|
+
padding: 16,
|
|
74
|
+
backgroundColor: '#1e1e1e',
|
|
75
|
+
textColor: '#d4d4d4',
|
|
76
|
+
fontSize: 14,
|
|
77
|
+
lineHeight: 1.6,
|
|
78
|
+
borderRadius: 4,
|
|
79
|
+
border: '1px solid #3c3c3c',
|
|
80
|
+
fontFamily: 'Consolas, Monaco, "Courier New", monospace',
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
defineEmits<{
|
|
84
|
+
execute: []
|
|
85
|
+
}>()
|
|
86
|
+
|
|
87
|
+
const containerStyle = computed<CSSProperties>(() => ({
|
|
88
|
+
width: '100%',
|
|
89
|
+
height: '100%',
|
|
90
|
+
padding: `${props.padding}px`,
|
|
91
|
+
backgroundColor: props.backgroundColor,
|
|
92
|
+
color: props.textColor,
|
|
93
|
+
fontSize: `${props.fontSize}px`,
|
|
94
|
+
lineHeight: props.lineHeight,
|
|
95
|
+
borderRadius: `${props.borderRadius}px`,
|
|
96
|
+
border: props.border,
|
|
97
|
+
overflow: 'auto',
|
|
98
|
+
fontFamily: props.fontFamily,
|
|
99
|
+
}))
|
|
100
|
+
</script>
|
|
101
|
+
|
|
102
|
+
<style scoped>
|
|
103
|
+
.scripting-container {
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: column;
|
|
106
|
+
gap: 12px;
|
|
107
|
+
height: 100%;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.header {
|
|
111
|
+
display: flex;
|
|
112
|
+
justify-content: space-between;
|
|
113
|
+
align-items: center;
|
|
114
|
+
padding-bottom: 8px;
|
|
115
|
+
border-bottom: 1px solid #3c3c3c;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.title {
|
|
119
|
+
display: flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
gap: 6px;
|
|
122
|
+
font-weight: 600;
|
|
123
|
+
font-size: 16px;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.section-title {
|
|
127
|
+
font-size: 12px;
|
|
128
|
+
opacity: 0.7;
|
|
129
|
+
margin-bottom: 6px;
|
|
130
|
+
text-transform: uppercase;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.code-section {
|
|
134
|
+
flex-shrink: 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.code-block {
|
|
138
|
+
margin: 0;
|
|
139
|
+
padding: 12px;
|
|
140
|
+
background: rgba(0, 0, 0, 0.3);
|
|
141
|
+
border-radius: 4px;
|
|
142
|
+
overflow-x: auto;
|
|
143
|
+
white-space: pre-wrap;
|
|
144
|
+
word-wrap: break-word;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.output-section {
|
|
148
|
+
flex: 1;
|
|
149
|
+
min-height: 0;
|
|
150
|
+
display: flex;
|
|
151
|
+
flex-direction: column;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.output-block {
|
|
155
|
+
flex: 1;
|
|
156
|
+
margin: 0;
|
|
157
|
+
padding: 12px;
|
|
158
|
+
background: rgba(0, 0, 0, 0.2);
|
|
159
|
+
border-radius: 4px;
|
|
160
|
+
overflow: auto;
|
|
161
|
+
white-space: pre-wrap;
|
|
162
|
+
word-wrap: break-word;
|
|
163
|
+
color: #4ec9b0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.error-output {
|
|
167
|
+
flex: 1;
|
|
168
|
+
padding: 12px;
|
|
169
|
+
background: rgba(220, 38, 38, 0.1);
|
|
170
|
+
border: 1px solid rgba(220, 38, 38, 0.3);
|
|
171
|
+
border-radius: 4px;
|
|
172
|
+
color: #f87171;
|
|
173
|
+
overflow: auto;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.placeholder {
|
|
177
|
+
display: flex;
|
|
178
|
+
flex-direction: column;
|
|
179
|
+
justify-content: center;
|
|
180
|
+
align-items: center;
|
|
181
|
+
flex: 1;
|
|
182
|
+
gap: 8px;
|
|
183
|
+
opacity: 0.5;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.placeholder .el-icon {
|
|
187
|
+
font-size: 32px;
|
|
188
|
+
}
|
|
189
|
+
</style>
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :style="containerStyle">
|
|
3
|
+
<div class="state-container">
|
|
4
|
+
<div class="header">
|
|
5
|
+
<span class="title">
|
|
6
|
+
<el-icon><DataLine /></el-icon>
|
|
7
|
+
{{ title }}
|
|
8
|
+
</span>
|
|
9
|
+
<el-tag size="small" type="info"> {{ stateItems.length }} 项 </el-tag>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div v-if="viewMode === 'list'" class="state-list">
|
|
13
|
+
<div v-for="item in stateItems" :key="item.key" class="state-item">
|
|
14
|
+
<div class="state-key">
|
|
15
|
+
<el-icon><Key /></el-icon>
|
|
16
|
+
{{ item.key }}
|
|
17
|
+
</div>
|
|
18
|
+
<div class="state-value">
|
|
19
|
+
<el-tag :type="getTagType(item.type)" size="small">{{ item.type }}</el-tag>
|
|
20
|
+
<span class="value-text">{{ formatValue(item.value) }}</span>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div v-else-if="viewMode === 'json'" class="json-view">
|
|
26
|
+
<pre class="json-block">{{ jsonValue }}</pre>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div v-else-if="viewMode === 'table'" class="table-view">
|
|
30
|
+
<el-table :data="stateItems" size="small" :border="true">
|
|
31
|
+
<el-table-column prop="key" label="键" width="120" />
|
|
32
|
+
<el-table-column prop="type" label="类型" width="80">
|
|
33
|
+
<template #default="{ row }">
|
|
34
|
+
<el-tag :type="getTagType(row.type)" size="small">{{ row.type }}</el-tag>
|
|
35
|
+
</template>
|
|
36
|
+
</el-table-column>
|
|
37
|
+
<el-table-column prop="value" label="值">
|
|
38
|
+
<template #default="{ row }">
|
|
39
|
+
{{ formatValue(row.value) }}
|
|
40
|
+
</template>
|
|
41
|
+
</el-table-column>
|
|
42
|
+
</el-table>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div v-if="stateItems.length === 0" class="placeholder">
|
|
46
|
+
<el-icon><FolderOpened /></el-icon>
|
|
47
|
+
<span>{{ placeholder }}</span>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<script setup lang="ts">
|
|
54
|
+
import { computed, type CSSProperties } from 'vue'
|
|
55
|
+
import { DataLine, Key, FolderOpened } from '@element-plus/icons-vue'
|
|
56
|
+
|
|
57
|
+
export interface StateItem {
|
|
58
|
+
key: string
|
|
59
|
+
value: unknown
|
|
60
|
+
type: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface StateProps {
|
|
64
|
+
title?: string
|
|
65
|
+
stateData?: Record<string, unknown>
|
|
66
|
+
viewMode?: 'list' | 'json' | 'table'
|
|
67
|
+
placeholder?: string
|
|
68
|
+
// 样式
|
|
69
|
+
padding?: number
|
|
70
|
+
backgroundColor?: string
|
|
71
|
+
textColor?: string
|
|
72
|
+
fontSize?: number
|
|
73
|
+
lineHeight?: number
|
|
74
|
+
borderRadius?: number
|
|
75
|
+
border?: string
|
|
76
|
+
fontFamily?: string
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const props = withDefaults(defineProps<StateProps>(), {
|
|
80
|
+
title: '状态管理器',
|
|
81
|
+
stateData: () => ({}),
|
|
82
|
+
viewMode: 'list',
|
|
83
|
+
placeholder: '暂无状态数据',
|
|
84
|
+
padding: 16,
|
|
85
|
+
backgroundColor: '#2d2d2d',
|
|
86
|
+
textColor: '#cccccc',
|
|
87
|
+
fontSize: 14,
|
|
88
|
+
lineHeight: 1.6,
|
|
89
|
+
borderRadius: 4,
|
|
90
|
+
border: '1px solid #3c3c3c',
|
|
91
|
+
fontFamily: 'Consolas, Monaco, "Courier New", monospace',
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
const containerStyle = computed<CSSProperties>(() => ({
|
|
95
|
+
width: '100%',
|
|
96
|
+
height: '100%',
|
|
97
|
+
padding: `${props.padding}px`,
|
|
98
|
+
backgroundColor: props.backgroundColor,
|
|
99
|
+
color: props.textColor,
|
|
100
|
+
fontSize: `${props.fontSize}px`,
|
|
101
|
+
lineHeight: props.lineHeight,
|
|
102
|
+
borderRadius: `${props.borderRadius}px`,
|
|
103
|
+
border: props.border,
|
|
104
|
+
overflow: 'auto',
|
|
105
|
+
fontFamily: props.fontFamily,
|
|
106
|
+
}))
|
|
107
|
+
|
|
108
|
+
const stateItems = computed<StateItem[]>(() => {
|
|
109
|
+
return Object.entries(props.stateData).map(([key, value]) => ({
|
|
110
|
+
key,
|
|
111
|
+
value,
|
|
112
|
+
type: typeof value,
|
|
113
|
+
}))
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const jsonValue = computed(() => {
|
|
117
|
+
return JSON.stringify(props.stateData, null, 2)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
function getTagType(type: string): 'success' | 'info' | 'warning' | 'danger' | '' {
|
|
121
|
+
const typeMap: Record<string, 'success' | 'info' | 'warning' | 'danger'> = {
|
|
122
|
+
string: 'success',
|
|
123
|
+
number: 'info',
|
|
124
|
+
boolean: 'warning',
|
|
125
|
+
object: 'danger',
|
|
126
|
+
}
|
|
127
|
+
return typeMap[type] || ''
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function formatValue(value: unknown): string {
|
|
131
|
+
if (value === null) return 'null'
|
|
132
|
+
if (value === undefined) return 'undefined'
|
|
133
|
+
if (typeof value === 'object') return JSON.stringify(value)
|
|
134
|
+
return String(value)
|
|
135
|
+
}
|
|
136
|
+
</script>
|
|
137
|
+
|
|
138
|
+
<style scoped>
|
|
139
|
+
.state-container {
|
|
140
|
+
display: flex;
|
|
141
|
+
flex-direction: column;
|
|
142
|
+
gap: 12px;
|
|
143
|
+
height: 100%;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.header {
|
|
147
|
+
display: flex;
|
|
148
|
+
justify-content: space-between;
|
|
149
|
+
align-items: center;
|
|
150
|
+
padding-bottom: 8px;
|
|
151
|
+
border-bottom: 1px solid #3c3c3c;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.title {
|
|
155
|
+
display: flex;
|
|
156
|
+
align-items: center;
|
|
157
|
+
gap: 6px;
|
|
158
|
+
font-weight: 600;
|
|
159
|
+
font-size: 16px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.state-list {
|
|
163
|
+
flex: 1;
|
|
164
|
+
overflow-y: auto;
|
|
165
|
+
display: flex;
|
|
166
|
+
flex-direction: column;
|
|
167
|
+
gap: 8px;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.state-item {
|
|
171
|
+
padding: 12px;
|
|
172
|
+
background: rgba(0, 0, 0, 0.2);
|
|
173
|
+
border-radius: 4px;
|
|
174
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.state-key {
|
|
178
|
+
display: flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
gap: 6px;
|
|
181
|
+
font-weight: 600;
|
|
182
|
+
margin-bottom: 6px;
|
|
183
|
+
color: #4fc3f7;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.state-value {
|
|
187
|
+
display: flex;
|
|
188
|
+
align-items: center;
|
|
189
|
+
gap: 8px;
|
|
190
|
+
padding-left: 24px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.value-text {
|
|
194
|
+
flex: 1;
|
|
195
|
+
word-break: break-all;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.json-view {
|
|
199
|
+
flex: 1;
|
|
200
|
+
overflow: auto;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.json-block {
|
|
204
|
+
margin: 0;
|
|
205
|
+
padding: 12px;
|
|
206
|
+
background: rgba(0, 0, 0, 0.3);
|
|
207
|
+
border-radius: 4px;
|
|
208
|
+
white-space: pre;
|
|
209
|
+
overflow-x: auto;
|
|
210
|
+
color: #9cdcfe;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.table-view {
|
|
214
|
+
flex: 1;
|
|
215
|
+
overflow: auto;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.placeholder {
|
|
219
|
+
display: flex;
|
|
220
|
+
flex-direction: column;
|
|
221
|
+
justify-content: center;
|
|
222
|
+
align-items: center;
|
|
223
|
+
flex: 1;
|
|
224
|
+
gap: 8px;
|
|
225
|
+
opacity: 0.5;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.placeholder .el-icon {
|
|
229
|
+
font-size: 32px;
|
|
230
|
+
}
|
|
231
|
+
</style>
|