npmapps 1.1.5 → 1.2.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/app/wujie-wk/t.html +90 -0
- package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EventCalendar/README.md +122 -5
- package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EventCalendar/example.vue +203 -7
- package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EventCalendar/index.vue +1124 -50
- package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EventCalendar/mockData.js +126 -0
- package/app/wujie-wk/wujie-vue2-child/src/components/EventCalendar/recruitmentAdapter.js +51 -0
- package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EventCalendar/utils.js +1 -0
- package/package.json +1 -1
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/.eslintrc.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/README.md +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/babel.config.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/docs/superpowers/plans/2026-05-29-quill-editor.md +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/docs/superpowers/specs/2026-05-29-quill-editor-design.md +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/jsconfig.json +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/package-lock.json +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/package.json +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/postcss.config.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/public/favicon.ico +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/public/index.html +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/public/rili.jpg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/public//344/270/200/351/224/256/351/273/221/346/232/227.html" +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/App.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/bpmn-camunda.jpg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/css/diagram.less +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/Icon.less +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/app-codes.css +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/app.eot +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/app.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/app.ttf +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/app.woff +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/app.woff2 +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/config.json +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/raw/align-bottom-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/raw/align-horizontal-center-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/raw/align-left-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/raw/align-right-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/raw/align-top-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/raw/align-vertical-center-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/raw/distribute-horizontally-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/raw/distribute-vertically-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/raw/set-color-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/symbols/align-bottom-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/symbols/align-horizontal-center-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/symbols/align-left-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/symbols/align-right-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/symbols/align-top-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/symbols/align-vertical-center-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/symbols/distribute-horizontally-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/symbols/distribute-vertically-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/icon/font/source/symbols/set-color-tool.svg +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/assets/logo.png +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EllTable/README.md +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EllTable/article.md +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EllTable/index.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EventCalendar/CalendarSkeleton.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EventCalendar/CodeBlock.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EventCalendar/MonthSelect.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/FormulaEditor/FunctionSelector.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/FormulaEditor/OperatorSelector.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/FormulaEditor/ParameterSelector.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/FormulaEditor/api.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/FormulaEditor/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/HelloWorld.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/PageHeader/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/Splitter/README.md +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/Splitter/example.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/Splitter/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/diagram/ToolBar.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/diagram/customTranslate/customTranslate.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/diagram/customTranslate/translationsGerman.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/diagram/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/diagram/xmlData.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/directives/filldown.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/directives/filldownTable.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/main.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/router/index.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/store/index.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/utils/winBox.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/Extend/A.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/Extend/B.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/Extend/MagicalComponentsForELFormItem.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/Extend/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/Extend/tableMouseHorizontalWheel.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/Home.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/RouterJump.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/calendar/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/css.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/cssComponents/EllipsisText.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/cssComponents/HoverCard.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/cssComponents/TableHover.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/cssComponents/inputSlo.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/cssComponents/tableFixed.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/echarts/echart-dome.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/echarts/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/echarts/pei3d.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/bpmn/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/components/attendanceCycle/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/components/attendanceGroup/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/components/attendancePersonnel/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/components/companyCalendar/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/components/shift/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/components/shiftRotationSystem/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/elTableJsx/columnManagement.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/elTableJsx/dialogInput.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/elTableJsx/elTableJsx.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/elTableJsx/formTable.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/elTableJsx/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/elTableJsx/simpleTable.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/elTableJsx.zip +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/quillEditor/README.md +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/quillEditor/example.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/quillEditor/index.vue +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/views/element/quillEditor/toolbar.js +0 -0
- /package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/vue.config.js +0 -0
package/app/{wujie-vue2-child → wujie-wk/wujie-vue2-child}/src/components/EventCalendar/index.vue
RENAMED
|
@@ -6,6 +6,179 @@
|
|
|
6
6
|
@mouseenter="handleMouseEnter"
|
|
7
7
|
@mouseleave="handleMouseLeave"
|
|
8
8
|
>
|
|
9
|
+
<!-- 开发/业务配置工具栏:默认关闭;改完点「复制配置」,把 JSON 发给研发即可 -->
|
|
10
|
+
<section
|
|
11
|
+
v-if="showConfigToolbar"
|
|
12
|
+
class="ec__config"
|
|
13
|
+
aria-label="日历布局配置"
|
|
14
|
+
>
|
|
15
|
+
<div class="ec__config-head">
|
|
16
|
+
<div>
|
|
17
|
+
<strong class="ec__config-title">布局配置</strong>
|
|
18
|
+
<span class="ec__config-caption">调整后点「复制配置」,粘贴发给研发即可</span>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="ec__config-actions">
|
|
21
|
+
<button
|
|
22
|
+
type="button"
|
|
23
|
+
class="ec__config-btn is-primary"
|
|
24
|
+
@click="copyLayoutConfig"
|
|
25
|
+
>复制配置</button>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="ec__config-list">
|
|
30
|
+
<div
|
|
31
|
+
v-for="field in configFields"
|
|
32
|
+
:key="field.key"
|
|
33
|
+
class="ec__config-block"
|
|
34
|
+
:class="'ec__config-block--' + field.kind"
|
|
35
|
+
:title="field.kind === 'spacing' ? '当前简写:' + spacingShorthand(field.key) : undefined"
|
|
36
|
+
>
|
|
37
|
+
<!-- 分段选项:条目对齐 / 溢出方式 -->
|
|
38
|
+
<template v-if="field.kind === 'seg'">
|
|
39
|
+
<p class="ec__config-label">
|
|
40
|
+
<span class="ec__config-priority">P{{ field.priority }}</span>{{ field.label }}
|
|
41
|
+
<button
|
|
42
|
+
type="button"
|
|
43
|
+
class="ec__config-reset"
|
|
44
|
+
:title="'还原「' + field.label + '」为初始值'"
|
|
45
|
+
@click="resetField(field.key)"
|
|
46
|
+
>还原</button>
|
|
47
|
+
</p>
|
|
48
|
+
<div class="ec__config-segment">
|
|
49
|
+
<button
|
|
50
|
+
v-for="option in field.options"
|
|
51
|
+
:key="option.value"
|
|
52
|
+
type="button"
|
|
53
|
+
:class="{ 'is-active': configDraft[field.key] === option.value }"
|
|
54
|
+
:aria-pressed="configDraft[field.key] === option.value ? 'true' : 'false'"
|
|
55
|
+
@click="updateLayoutConfig(field.key, option.value)"
|
|
56
|
+
>{{ option.label }}</button>
|
|
57
|
+
</div>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<!-- 间距:上下 / 左右两块步进 -->
|
|
61
|
+
<template v-else-if="field.kind === 'spacing'">
|
|
62
|
+
<p class="ec__config-label">
|
|
63
|
+
<span class="ec__config-priority">P{{ field.priority }}</span>{{ field.label }}
|
|
64
|
+
<code class="ec__config-shorthand">{{ spacingShorthand(field.key) }}</code>
|
|
65
|
+
<button
|
|
66
|
+
type="button"
|
|
67
|
+
class="ec__config-reset"
|
|
68
|
+
:title="'还原「' + field.label + '」为初始值'"
|
|
69
|
+
@click="resetField(field.key)"
|
|
70
|
+
>还原</button>
|
|
71
|
+
</p>
|
|
72
|
+
<div class="ec__spacing">
|
|
73
|
+
<div v-for="axis in spacingAxes" :key="axis.key" class="ec__spacing-row">
|
|
74
|
+
<span class="ec__spacing-row-label">{{ axis.label }}</span>
|
|
75
|
+
<span class="ec__stepper">
|
|
76
|
+
<button
|
|
77
|
+
type="button"
|
|
78
|
+
class="ec__step-btn"
|
|
79
|
+
:aria-label="field.label + ',' + axis.label + '减 1'"
|
|
80
|
+
title="减 1(按住 Shift ±5)"
|
|
81
|
+
@click="nudgeSpacingAxis(field.key, axis.key, -1, $event)"
|
|
82
|
+
>−</button>
|
|
83
|
+
<label class="ec__stepper-input">
|
|
84
|
+
<input
|
|
85
|
+
type="number"
|
|
86
|
+
min="0"
|
|
87
|
+
step="1"
|
|
88
|
+
:value="spacingAxisValue(field.key, axis.key)"
|
|
89
|
+
:aria-label="field.label + ',' + axis.label + '(px)'"
|
|
90
|
+
@change="updateSpacingAxis(field.key, axis.key, $event)"
|
|
91
|
+
/>
|
|
92
|
+
<span class="ec__stepper-unit" aria-hidden="true">px</span>
|
|
93
|
+
</label>
|
|
94
|
+
<button
|
|
95
|
+
type="button"
|
|
96
|
+
class="ec__step-btn"
|
|
97
|
+
:aria-label="field.label + ',' + axis.label + '加 1'"
|
|
98
|
+
title="加 1(按住 Shift ±5)"
|
|
99
|
+
@click="nudgeSpacingAxis(field.key, axis.key, 1, $event)"
|
|
100
|
+
>+</button>
|
|
101
|
+
</span>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
</template>
|
|
105
|
+
|
|
106
|
+
<!-- 单值数值:输入框左右包 −/+ -->
|
|
107
|
+
<template v-else-if="field.kind === 'number'">
|
|
108
|
+
<p class="ec__config-label">
|
|
109
|
+
<span class="ec__config-priority">P{{ field.priority }}</span>{{ field.label }}
|
|
110
|
+
<button
|
|
111
|
+
type="button"
|
|
112
|
+
class="ec__config-reset"
|
|
113
|
+
:title="'还原「' + field.label + '」为初始值'"
|
|
114
|
+
@click="resetField(field.key)"
|
|
115
|
+
>还原</button>
|
|
116
|
+
</p>
|
|
117
|
+
<span class="ec__stepper">
|
|
118
|
+
<button
|
|
119
|
+
type="button"
|
|
120
|
+
class="ec__step-btn"
|
|
121
|
+
:aria-label="field.label + '减 1'"
|
|
122
|
+
:title="'减 ' + (field.step || 1) + '(按住 Shift ×5)'"
|
|
123
|
+
@click="nudgeNumber(field.key, -1, $event)"
|
|
124
|
+
>−</button>
|
|
125
|
+
<label class="ec__stepper-input">
|
|
126
|
+
<input
|
|
127
|
+
type="number"
|
|
128
|
+
:min="typeof field.min === 'number' ? field.min : 0"
|
|
129
|
+
:step="field.step || 1"
|
|
130
|
+
:value="configDraft[field.key]"
|
|
131
|
+
:aria-label="field.label + '(' + field.unit + ')'"
|
|
132
|
+
@change="updateLayoutConfig(field.key, $event.target.value, 'number')"
|
|
133
|
+
/>
|
|
134
|
+
<span v-if="field.unit" class="ec__stepper-unit" aria-hidden="true">{{ field.unit }}</span>
|
|
135
|
+
</label>
|
|
136
|
+
<button
|
|
137
|
+
type="button"
|
|
138
|
+
class="ec__step-btn"
|
|
139
|
+
:aria-label="field.label + '加 1'"
|
|
140
|
+
:title="'加 ' + (field.step || 1) + '(按住 Shift ×5)'"
|
|
141
|
+
@click="nudgeNumber(field.key, 1, $event)"
|
|
142
|
+
>+</button>
|
|
143
|
+
</span>
|
|
144
|
+
</template>
|
|
145
|
+
|
|
146
|
+
<!-- 颜色 -->
|
|
147
|
+
<template v-else-if="field.kind === 'color'">
|
|
148
|
+
<label class="ec__color-swatch" :title="field.label">
|
|
149
|
+
<input
|
|
150
|
+
type="color"
|
|
151
|
+
:value="colorValue(field.key)"
|
|
152
|
+
:aria-label="field.label"
|
|
153
|
+
@input="updateLayoutConfig(field.key, $event.target.value)"
|
|
154
|
+
/>
|
|
155
|
+
</label>
|
|
156
|
+
<span class="ec__color-meta">
|
|
157
|
+
<span class="ec__config-label">
|
|
158
|
+
<span class="ec__config-priority">P{{ field.priority }}</span>{{ field.label }}
|
|
159
|
+
</span>
|
|
160
|
+
<code class="ec__color-hex">{{ colorValue(field.key) }}</code>
|
|
161
|
+
</span>
|
|
162
|
+
<button
|
|
163
|
+
type="button"
|
|
164
|
+
class="ec__reset-btn"
|
|
165
|
+
title="还原为默认配色"
|
|
166
|
+
:disabled="!configDraft[field.key]"
|
|
167
|
+
@click="resetColor(field.key)"
|
|
168
|
+
>还原</button>
|
|
169
|
+
</template>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<div class="ec__config-output">
|
|
174
|
+
<pre class="ec__config-json">{{ configJsonText }}</pre>
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
<div class="ec__config-feedback" role="status" aria-live="polite">
|
|
178
|
+
{{ copyStatus }}
|
|
179
|
+
</div>
|
|
180
|
+
</section>
|
|
181
|
+
|
|
9
182
|
<!-- ==================== 顶部区域 ==================== -->
|
|
10
183
|
<div v-if="showHeader" class="ec__header">
|
|
11
184
|
<!-- 左侧:完全交给使用者的插槽,未传时回落到 title / subtitle -->
|
|
@@ -115,8 +288,8 @@
|
|
|
115
288
|
<slot name="loading" v-bind="{ rows: skeletonRows }">
|
|
116
289
|
<CalendarSkeleton
|
|
117
290
|
:rows="skeletonRows"
|
|
118
|
-
:min-row-height="
|
|
119
|
-
:item-height="
|
|
291
|
+
:min-row-height="cfgMinRowHeight"
|
|
292
|
+
:item-height="cfgItemHeight"
|
|
120
293
|
/>
|
|
121
294
|
</slot>
|
|
122
295
|
</div>
|
|
@@ -179,15 +352,26 @@
|
|
|
179
352
|
:class="{
|
|
180
353
|
'is-disabled': entry.disabled,
|
|
181
354
|
'has-badge': !!entry.badge,
|
|
182
|
-
'is-colorful': colorful && entry.type
|
|
355
|
+
'is-colorful': colorful && entry.type && !cfgItemBgColor && cfgItemBgHover,
|
|
356
|
+
'is-bg-gradient': cfgItemBgGradient,
|
|
357
|
+
'is-bg-gradient-h': cfgItemBgGradient && cfgGradientDir === 'to-right'
|
|
183
358
|
}"
|
|
184
359
|
:style="itemStyle(entry)"
|
|
185
|
-
:title="entry
|
|
360
|
+
:title="itemTitle(entry)"
|
|
186
361
|
@click.stop="handleItemClick(entry, cell, i, $event)"
|
|
187
362
|
>
|
|
188
363
|
<!-- 单条自定义 -->
|
|
189
364
|
<slot name="item" v-bind="itemScope(entry, cell, i)">
|
|
190
|
-
<
|
|
365
|
+
<div class="ec__item-content">
|
|
366
|
+
<span
|
|
367
|
+
class="ec__item-label"
|
|
368
|
+
:class="{ 'is-long': isLongItemLabel(entry.label) }"
|
|
369
|
+
>{{ entry.label }}</span>
|
|
370
|
+
<span
|
|
371
|
+
v-if="hasText(entry.address)"
|
|
372
|
+
class="ec__item-address"
|
|
373
|
+
>{{ entry.address }}</span>
|
|
374
|
+
</div>
|
|
191
375
|
<span
|
|
192
376
|
v-if="entry.badge"
|
|
193
377
|
class="ec__item-badge"
|
|
@@ -253,6 +437,128 @@ const BUILTIN_TYPE_COLORS = {
|
|
|
253
437
|
default: { color: '#6b7280', bg: 'rgba(107, 114, 128, 0.10)' }
|
|
254
438
|
}
|
|
255
439
|
|
|
440
|
+
/** 布局配置全部对应 EventCalendar 原生 Props,可直接用于 v-bind。 */
|
|
441
|
+
const DEFAULT_LAYOUT_CONFIG = Object.freeze({
|
|
442
|
+
itemAlign: 'left',
|
|
443
|
+
calendarMargin: 0,
|
|
444
|
+
calendarPadding: 0,
|
|
445
|
+
headerPadding: '4px 4px 16px',
|
|
446
|
+
cellPadding: '12px 10px',
|
|
447
|
+
mobileCellPadding: '8px 6px',
|
|
448
|
+
itemHorizontalPadding: 8,
|
|
449
|
+
itemVerticalPadding: 4,
|
|
450
|
+
itemGap: 6,
|
|
451
|
+
// 溢出 / 行高 / 角标缩放:同样是对应原生 Props
|
|
452
|
+
overflowMode: 'scroll',
|
|
453
|
+
maxVisibleItems: 4,
|
|
454
|
+
itemHeight: 28,
|
|
455
|
+
minRowHeight: 118,
|
|
456
|
+
badgeScale: 0.75,
|
|
457
|
+
// 条目内部排版与外观
|
|
458
|
+
itemLineGap: 2, // 名称与地址之间的行间距(px)
|
|
459
|
+
itemBgGradient: false, // 条目背景是否启用渐变效果
|
|
460
|
+
itemBgGradientDir: 'to-bottom', // 渐变方向:to-bottom 上到下 | to-right 左到右
|
|
461
|
+
itemBgHover: true, // 悬浮时是否在底色上自动加深
|
|
462
|
+
// 条目(.ec__item)颜色覆盖:空串 = 按 type/主题配色走
|
|
463
|
+
itemTextColor: '',
|
|
464
|
+
itemBgColor: ''
|
|
465
|
+
})
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* 工具栏统一字段表:按展示顺序排列。
|
|
469
|
+
* kind: seg=分段选项 | spacing=上下/左右两块 | number=单值步进 | color=取色
|
|
470
|
+
*/
|
|
471
|
+
const CONFIG_FIELDS = Object.freeze([
|
|
472
|
+
{ kind: 'seg', key: 'itemAlign', label: '条目对齐', priority: 1, options: [
|
|
473
|
+
{ label: '靠左', value: 'left' },
|
|
474
|
+
{ label: '居中', value: 'center' }
|
|
475
|
+
] },
|
|
476
|
+
|
|
477
|
+
{ kind: 'spacing', key: 'cellPadding', label: '日期格内边距', priority: 2 },
|
|
478
|
+
{ kind: 'spacing', key: 'mobileCellPadding', label: '窄屏日期格内边距', priority: 3 },
|
|
479
|
+
|
|
480
|
+
{ kind: 'number', key: 'itemHorizontalPadding', label: '条目左右内边距', priority: 4, unit: 'px', step: 1 },
|
|
481
|
+
{ kind: 'number', key: 'itemVerticalPadding', label: '条目上下内边距', priority: 5, unit: 'px', step: 1 },
|
|
482
|
+
{ kind: 'number', key: 'itemGap', label: '条目间距', priority: 6, unit: 'px', step: 1 },
|
|
483
|
+
|
|
484
|
+
{ kind: 'number', key: 'maxVisibleItems', label: '单格最多显示', priority: 7, unit: '条', step: 1, min: 1 },
|
|
485
|
+
{ kind: 'number', key: 'itemHeight', label: '条目高度', priority: 8, unit: 'px', step: 1 },
|
|
486
|
+
{ kind: 'number', key: 'itemLineGap', label: '名称地址间距', priority: 9, unit: 'px', step: 1 },
|
|
487
|
+
|
|
488
|
+
{ kind: 'seg', key: 'itemBgGradient', label: '条目背景效果', priority: 10, options: [
|
|
489
|
+
{ label: '纯色', value: false },
|
|
490
|
+
{ label: '渐变', value: true }
|
|
491
|
+
] },
|
|
492
|
+
{ kind: 'seg', key: 'itemBgGradientDir', label: '渐变方向', priority: 11, options: [
|
|
493
|
+
{ label: '上到下', value: 'to-bottom' },
|
|
494
|
+
{ label: '左到右', value: 'to-right' }
|
|
495
|
+
] },
|
|
496
|
+
{ kind: 'seg', key: 'itemBgHover', label: '悬浮加深', priority: 12, options: [
|
|
497
|
+
{ label: '开启', value: true },
|
|
498
|
+
{ label: '关闭', value: false }
|
|
499
|
+
] },
|
|
500
|
+
|
|
501
|
+
{ kind: 'color', key: 'itemTextColor', label: '条目文字色', priority: 13, default: '#606266' },
|
|
502
|
+
{ kind: 'color', key: 'itemBgColor', label: '条目背景色', priority: 14, default: '#f5f7fa' }
|
|
503
|
+
])
|
|
504
|
+
|
|
505
|
+
/** 间距控件的两个轴:vertical=上下(top/bottom),horizontal=左右(left/right) */
|
|
506
|
+
const CONFIG_SPACING_AXES = Object.freeze([
|
|
507
|
+
{ key: 'vertical', label: '上下', sides: ['top', 'bottom'] },
|
|
508
|
+
{ key: 'horizontal', label: '左右', sides: ['left', 'right'] }
|
|
509
|
+
])
|
|
510
|
+
|
|
511
|
+
function createLayoutConfig(vm) {
|
|
512
|
+
return Object.keys(DEFAULT_LAYOUT_CONFIG).reduce((config, key) => {
|
|
513
|
+
config[key] = vm[key]
|
|
514
|
+
return config
|
|
515
|
+
}, {})
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function toCssSpacing(value, fallback) {
|
|
519
|
+
if (typeof value === 'number' && Number.isFinite(value)) return `${Math.max(0, value)}px`
|
|
520
|
+
if (typeof value === 'string' && value.trim()) return value.trim()
|
|
521
|
+
return typeof fallback === 'number' ? `${fallback}px` : fallback
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* 把 CSS 简写(或数字)解析成 { top, right, bottom, left } 的 px 数值。
|
|
526
|
+
* 支持 1~4 个值,如 '12px 10px' -> { top:12, right:10, bottom:12, left:10 }。
|
|
527
|
+
* 解析失败返回全 0,避免方向控件拿不到数。
|
|
528
|
+
*/
|
|
529
|
+
function parseSpacingToSides(value) {
|
|
530
|
+
const zero = { top: 0, right: 0, bottom: 0, left: 0 }
|
|
531
|
+
let nums = null
|
|
532
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
533
|
+
nums = [value, value, value, value]
|
|
534
|
+
} else if (typeof value === 'string') {
|
|
535
|
+
const tokens = value.trim().split(/\s+/).filter(Boolean)
|
|
536
|
+
const parsed = tokens.map((token) => {
|
|
537
|
+
const m = /^(-?\d+(?:\.\d+)?)(?:px)?$/i.exec(token)
|
|
538
|
+
return m ? Number(m[1]) : null
|
|
539
|
+
})
|
|
540
|
+
if (parsed.length && parsed.every((n) => n != null && Number.isFinite(n))) nums = parsed
|
|
541
|
+
}
|
|
542
|
+
if (!nums) return zero
|
|
543
|
+
const top = nums[0]
|
|
544
|
+
const right = nums.length >= 2 ? nums[1] : top
|
|
545
|
+
const bottom = nums.length >= 3 ? nums[2] : top
|
|
546
|
+
const left = nums.length >= 4 ? nums[3] : right
|
|
547
|
+
return { top, right, bottom, left }
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/** 4 个方向的 px 合成 CSS 简写:全等/上下左右两两相等时尽量压缩成 1 项或 2 项 */
|
|
551
|
+
function spacingFromSides(sides) {
|
|
552
|
+
const px = (v) => `${Math.max(0, Math.round(v))}px`
|
|
553
|
+
const top = sides.top
|
|
554
|
+
const right = sides.right
|
|
555
|
+
const bottom = sides.bottom
|
|
556
|
+
const left = sides.left
|
|
557
|
+
if (top === right && right === bottom && bottom === left) return px(top)
|
|
558
|
+
if (top === bottom && right === left) return `${px(top)} ${px(right)}`
|
|
559
|
+
return `${px(top)} ${px(right)} ${px(bottom)} ${px(left)}`
|
|
560
|
+
}
|
|
561
|
+
|
|
256
562
|
export default {
|
|
257
563
|
name: 'EventCalendar',
|
|
258
564
|
|
|
@@ -405,11 +711,86 @@ export default {
|
|
|
405
711
|
type: Number,
|
|
406
712
|
default: 6
|
|
407
713
|
},
|
|
714
|
+
/** 条目内容对齐方式 */
|
|
715
|
+
itemAlign: {
|
|
716
|
+
type: String,
|
|
717
|
+
default: 'left',
|
|
718
|
+
validator: (v) => ['left', 'center'].includes(v)
|
|
719
|
+
},
|
|
720
|
+
/** 日历根节点外边距;Number 按 px 处理,String 支持 CSS 简写 */
|
|
721
|
+
calendarMargin: {
|
|
722
|
+
type: [Number, String],
|
|
723
|
+
default: DEFAULT_LAYOUT_CONFIG.calendarMargin
|
|
724
|
+
},
|
|
725
|
+
/** 日历根节点内边距;Number 按 px 处理,String 支持 CSS 简写 */
|
|
726
|
+
calendarPadding: {
|
|
727
|
+
type: [Number, String],
|
|
728
|
+
default: DEFAULT_LAYOUT_CONFIG.calendarPadding
|
|
729
|
+
},
|
|
730
|
+
/** 顶部区域内边距;支持 CSS 简写 */
|
|
731
|
+
headerPadding: {
|
|
732
|
+
type: [Number, String],
|
|
733
|
+
default: DEFAULT_LAYOUT_CONFIG.headerPadding
|
|
734
|
+
},
|
|
735
|
+
/** 日期格内边距;支持 CSS 简写 */
|
|
736
|
+
cellPadding: {
|
|
737
|
+
type: [Number, String],
|
|
738
|
+
default: DEFAULT_LAYOUT_CONFIG.cellPadding
|
|
739
|
+
},
|
|
740
|
+
/** 768px 及以下日期格内边距;支持 CSS 简写 */
|
|
741
|
+
mobileCellPadding: {
|
|
742
|
+
type: [Number, String],
|
|
743
|
+
default: DEFAULT_LAYOUT_CONFIG.mobileCellPadding
|
|
744
|
+
},
|
|
745
|
+
/** 条目左右内边距(px),传 0 可去除 */
|
|
746
|
+
itemHorizontalPadding: {
|
|
747
|
+
type: Number,
|
|
748
|
+
default: 8,
|
|
749
|
+
validator: (v) => v >= 0
|
|
750
|
+
},
|
|
751
|
+
/** 条目上下内边距(px) */
|
|
752
|
+
itemVerticalPadding: {
|
|
753
|
+
type: Number,
|
|
754
|
+
default: DEFAULT_LAYOUT_CONFIG.itemVerticalPadding,
|
|
755
|
+
validator: (v) => v >= 0
|
|
756
|
+
},
|
|
757
|
+
/** 显示内置布局配置工具栏;生产环境默认隐藏 */
|
|
758
|
+
showConfigToolbar: {
|
|
759
|
+
type: Boolean,
|
|
760
|
+
default: false
|
|
761
|
+
},
|
|
408
762
|
/** 单元格最小高度(px),保证空行不塌陷 */
|
|
409
763
|
minRowHeight: {
|
|
410
764
|
type: Number,
|
|
411
765
|
default: 118
|
|
412
766
|
},
|
|
767
|
+
/** 右上角角标整体缩放倍率(transform scale,越小越紧凑) */
|
|
768
|
+
badgeScale: {
|
|
769
|
+
type: Number,
|
|
770
|
+
default: 0.75
|
|
771
|
+
},
|
|
772
|
+
/** 条目内名称与地址之间的行间距(px) */
|
|
773
|
+
itemLineGap: {
|
|
774
|
+
type: Number,
|
|
775
|
+
default: 2,
|
|
776
|
+
validator: (v) => v >= 0
|
|
777
|
+
},
|
|
778
|
+
/** 条目背景是否启用渐变效果(在所选底色上叠柔和渐变) */
|
|
779
|
+
itemBgGradient: {
|
|
780
|
+
type: Boolean,
|
|
781
|
+
default: false
|
|
782
|
+
},
|
|
783
|
+
/** 渐变方向:to-bottom 上到下 | to-right 左到右(仅渐变开启时生效) */
|
|
784
|
+
itemBgGradientDir: {
|
|
785
|
+
type: String,
|
|
786
|
+
default: 'to-bottom',
|
|
787
|
+
validator: (v) => ['to-bottom', 'to-right'].includes(v)
|
|
788
|
+
},
|
|
789
|
+
/** 悬浮时是否自动把条目背景调淡一档(false 则保持原色) */
|
|
790
|
+
itemBgHover: {
|
|
791
|
+
type: Boolean,
|
|
792
|
+
default: true
|
|
793
|
+
},
|
|
413
794
|
/** 相邻月份补位格子是否也渲染条目 */
|
|
414
795
|
showAdjacentItems: {
|
|
415
796
|
type: Boolean,
|
|
@@ -450,6 +831,16 @@ export default {
|
|
|
450
831
|
type: Boolean,
|
|
451
832
|
default: false
|
|
452
833
|
},
|
|
834
|
+
/** 条目(.ec__item)文字色覆盖,空串 = 按 type/主题配色 */
|
|
835
|
+
itemTextColor: {
|
|
836
|
+
type: String,
|
|
837
|
+
default: ''
|
|
838
|
+
},
|
|
839
|
+
/** 条目(.ec__item)背景色覆盖,空串 = 按 type/主题配色 */
|
|
840
|
+
itemBgColor: {
|
|
841
|
+
type: String,
|
|
842
|
+
default: ''
|
|
843
|
+
},
|
|
453
844
|
/** 主题变量覆盖,如 { primary: '#10a37f', radius: '12px' } */
|
|
454
845
|
theme: {
|
|
455
846
|
type: Object,
|
|
@@ -476,7 +867,13 @@ export default {
|
|
|
476
867
|
/** 每次切换 +1,用于重置进度条 CSS 动画 */
|
|
477
868
|
progressKey: 0,
|
|
478
869
|
/** 骨架屏 -> 内容 的首次切换用淡入,避免莫名其妙的滑动 */
|
|
479
|
-
useFadeOnce: true
|
|
870
|
+
useFadeOnce: true,
|
|
871
|
+
/** 配置工具栏只编辑本地草稿,还原时以此为初始快照 */
|
|
872
|
+
configDraft: createLayoutConfig(this),
|
|
873
|
+
/** 初始配置快照:每个「还原」按钮回到这里 */
|
|
874
|
+
configDefaults: createLayoutConfig(this),
|
|
875
|
+
/** 复制配置按钮的即时反馈文案 */
|
|
876
|
+
copyStatus: ''
|
|
480
877
|
}
|
|
481
878
|
},
|
|
482
879
|
|
|
@@ -486,6 +883,63 @@ export default {
|
|
|
486
883
|
return { ...DEFAULT_FIELD_NAMES, ...this.fieldNames }
|
|
487
884
|
},
|
|
488
885
|
|
|
886
|
+
externalLayoutConfig() {
|
|
887
|
+
return createLayoutConfig(this)
|
|
888
|
+
},
|
|
889
|
+
|
|
890
|
+
effectiveLayoutConfig() {
|
|
891
|
+
return this.showConfigToolbar ? this.configDraft : this.externalLayoutConfig
|
|
892
|
+
},
|
|
893
|
+
|
|
894
|
+
/** 工具栏统一字段表(seg / spacing / number / color) */
|
|
895
|
+
configFields() {
|
|
896
|
+
// 渐变方向只在启用渐变时才显示
|
|
897
|
+
return CONFIG_FIELDS.filter((f) => !(f.key === 'itemBgGradientDir' && !this.configDraft.itemBgGradient))
|
|
898
|
+
},
|
|
899
|
+
|
|
900
|
+
/** 间距控件的「上下 / 左右」两组方向定义 */
|
|
901
|
+
spacingAxes() {
|
|
902
|
+
return CONFIG_SPACING_AXES
|
|
903
|
+
},
|
|
904
|
+
|
|
905
|
+
/** 实时生成的配置 JSON 文本(复制给用户 / 供展示) */
|
|
906
|
+
configJsonText() {
|
|
907
|
+
return JSON.stringify(this.getLayoutConfig(), null, 2)
|
|
908
|
+
},
|
|
909
|
+
|
|
910
|
+
/** 下面几个值统一从布局配置取:工具栏可见时用草稿,否则回落 Props */
|
|
911
|
+
cfgItemHeight() {
|
|
912
|
+
return this.effectiveLayoutConfig.itemHeight
|
|
913
|
+
},
|
|
914
|
+
|
|
915
|
+
cfgMaxVisibleItems() {
|
|
916
|
+
return this.effectiveLayoutConfig.maxVisibleItems
|
|
917
|
+
},
|
|
918
|
+
|
|
919
|
+
cfgOverflowMode() {
|
|
920
|
+
return this.effectiveLayoutConfig.overflowMode
|
|
921
|
+
},
|
|
922
|
+
|
|
923
|
+
cfgMinRowHeight() {
|
|
924
|
+
return this.effectiveLayoutConfig.minRowHeight
|
|
925
|
+
},
|
|
926
|
+
|
|
927
|
+
cfgItemBgColor() {
|
|
928
|
+
return this.effectiveLayoutConfig.itemBgColor
|
|
929
|
+
},
|
|
930
|
+
|
|
931
|
+
cfgItemBgGradient() {
|
|
932
|
+
return this.effectiveLayoutConfig.itemBgGradient
|
|
933
|
+
},
|
|
934
|
+
|
|
935
|
+
cfgGradientDir() {
|
|
936
|
+
return this.effectiveLayoutConfig.itemBgGradientDir
|
|
937
|
+
},
|
|
938
|
+
|
|
939
|
+
cfgItemBgHover() {
|
|
940
|
+
return this.effectiveLayoutConfig.itemBgHover
|
|
941
|
+
},
|
|
942
|
+
|
|
489
943
|
/* --------------------------- 数据归一化 --------------------------- */
|
|
490
944
|
/**
|
|
491
945
|
* 把外部数据统一整理成 [{ month, label, raw }],
|
|
@@ -598,16 +1052,17 @@ export default {
|
|
|
598
1052
|
? String(getByPath(raw, f.itemKey))
|
|
599
1053
|
: `${cell.dateKey}-${i}`,
|
|
600
1054
|
label: getByPath(raw, f.itemLabel),
|
|
1055
|
+
address: getByPath(raw, f.itemAddress),
|
|
601
1056
|
badge: getByPath(raw, f.itemBadge),
|
|
602
1057
|
type: getByPath(raw, f.itemType),
|
|
603
1058
|
disabled: !!getByPath(raw, f.itemDisabled),
|
|
604
1059
|
raw
|
|
605
1060
|
}))
|
|
606
1061
|
|
|
607
|
-
const overflowed = items.length > this.
|
|
608
|
-
const collapse = this.
|
|
1062
|
+
const overflowed = items.length > this.cfgMaxVisibleItems
|
|
1063
|
+
const collapse = this.cfgOverflowMode === 'collapse' && overflowed
|
|
609
1064
|
// collapse 模式留一行给「还有 N 项」
|
|
610
|
-
const visibleItems = collapse ? items.slice(0, this.
|
|
1065
|
+
const visibleItems = collapse ? items.slice(0, this.cfgMaxVisibleItems - 1) : items
|
|
611
1066
|
|
|
612
1067
|
return {
|
|
613
1068
|
...cell,
|
|
@@ -616,7 +1071,7 @@ export default {
|
|
|
616
1071
|
visibleItems,
|
|
617
1072
|
moreCount: collapse ? items.length - visibleItems.length : 0,
|
|
618
1073
|
/** scroll 模式下是否真的会出现滚动条 */
|
|
619
|
-
scrollable: this.
|
|
1074
|
+
scrollable: this.cfgOverflowMode === 'scroll' && overflowed
|
|
620
1075
|
}
|
|
621
1076
|
})
|
|
622
1077
|
},
|
|
@@ -626,6 +1081,7 @@ export default {
|
|
|
626
1081
|
return {
|
|
627
1082
|
'ec--loading': this.loading,
|
|
628
1083
|
'ec--stagger': this.cellStagger && !this.loading,
|
|
1084
|
+
'ec--item-center': this.effectiveLayoutConfig.itemAlign === 'center',
|
|
629
1085
|
[`ec--effect-${this.transitionEffect}`]: true
|
|
630
1086
|
}
|
|
631
1087
|
},
|
|
@@ -633,8 +1089,9 @@ export default {
|
|
|
633
1089
|
/** 主题:全部走 CSS 变量,方便外部覆盖 */
|
|
634
1090
|
cssVars() {
|
|
635
1091
|
const t = this.theme || {}
|
|
636
|
-
const n = this.
|
|
637
|
-
|
|
1092
|
+
const n = this.cfgMaxVisibleItems
|
|
1093
|
+
const layout = this.effectiveLayoutConfig
|
|
1094
|
+
const vars = {
|
|
638
1095
|
'--ec-primary': t.primary || '#3d6cf0',
|
|
639
1096
|
'--ec-primary-ghost': t.primaryGhost || 'rgba(61, 108, 240, 0.12)',
|
|
640
1097
|
'--ec-border': t.border || '#e4e7ed',
|
|
@@ -643,16 +1100,31 @@ export default {
|
|
|
643
1100
|
'--ec-text-secondary': t.textSecondary || '#606266',
|
|
644
1101
|
'--ec-text-placeholder': t.textPlaceholder || '#c0c4cc',
|
|
645
1102
|
'--ec-muted': t.muted || '#c8ccd4',
|
|
646
|
-
|
|
1103
|
+
// 条目颜色:工具栏配置的条目色优先于 theme,theme 优先于默认
|
|
1104
|
+
'--ec-item-bg': layout.itemBgColor || t.itemBg || '#f5f7fa',
|
|
647
1105
|
'--ec-cell-hover': t.cellHover || '#fafbfd',
|
|
648
1106
|
'--ec-radius': t.radius || '8px',
|
|
649
1107
|
'--ec-duration': this.transitionDuration + 'ms',
|
|
650
|
-
'--ec-item-h': this.
|
|
651
|
-
'--ec-
|
|
652
|
-
'--ec-
|
|
1108
|
+
'--ec-item-h': this.cfgItemHeight + 'px',
|
|
1109
|
+
'--ec-badge-scale': Number.isFinite(Number(layout.badgeScale)) ? Number(layout.badgeScale) : 0.75,
|
|
1110
|
+
'--ec-calendar-margin': toCssSpacing(layout.calendarMargin, DEFAULT_LAYOUT_CONFIG.calendarMargin),
|
|
1111
|
+
'--ec-calendar-padding': toCssSpacing(layout.calendarPadding, DEFAULT_LAYOUT_CONFIG.calendarPadding),
|
|
1112
|
+
'--ec-header-padding': toCssSpacing(layout.headerPadding, DEFAULT_LAYOUT_CONFIG.headerPadding),
|
|
1113
|
+
'--ec-cell-padding': toCssSpacing(layout.cellPadding, DEFAULT_LAYOUT_CONFIG.cellPadding),
|
|
1114
|
+
'--ec-cell-padding-mobile': toCssSpacing(layout.mobileCellPadding, DEFAULT_LAYOUT_CONFIG.mobileCellPadding),
|
|
1115
|
+
'--ec-item-gap': layout.itemGap + 'px',
|
|
1116
|
+
'--ec-item-padding-x': layout.itemHorizontalPadding + 'px',
|
|
1117
|
+
'--ec-item-padding-y': layout.itemVerticalPadding + 'px',
|
|
1118
|
+
'--ec-item-line-gap': layout.itemLineGap + 'px',
|
|
1119
|
+
// 悬浮自动调淡一档(白色叠层);关闭则为透明
|
|
1120
|
+
'--ec-item-hover-mask': layout.itemBgHover === false ? 'transparent' : 'rgba(255, 255, 255, 0.18)',
|
|
1121
|
+
'--ec-min-row-h': this.cfgMinRowHeight + 'px',
|
|
653
1122
|
// 滚动区域最大高度 = n 个条目 + (n-1) 个间距
|
|
654
|
-
'--ec-items-max-h': `${n * this.
|
|
1123
|
+
'--ec-items-max-h': `${n * this.cfgItemHeight + (n - 1) * layout.itemGap}px`
|
|
655
1124
|
}
|
|
1125
|
+
// 条目文字色只在显式配置时覆盖;未配置时走 --ec-text-secondary(hover 走 --ec-text)
|
|
1126
|
+
if (layout.itemTextColor) vars['--ec-item-text'] = layout.itemTextColor
|
|
1127
|
+
return vars
|
|
656
1128
|
},
|
|
657
1129
|
|
|
658
1130
|
stageStyle() {
|
|
@@ -661,7 +1133,7 @@ export default {
|
|
|
661
1133
|
|
|
662
1134
|
itemsStyle() {
|
|
663
1135
|
// collapse 模式不限制高度(本来就已经截断了),scroll 模式限高触发滚动条
|
|
664
|
-
return this.
|
|
1136
|
+
return this.cfgOverflowMode === 'scroll'
|
|
665
1137
|
? { maxHeight: 'var(--ec-items-max-h)' }
|
|
666
1138
|
: {}
|
|
667
1139
|
},
|
|
@@ -737,6 +1209,14 @@ export default {
|
|
|
737
1209
|
if (val && val !== this.innerMonth) this.setMonth(val, 'prop')
|
|
738
1210
|
},
|
|
739
1211
|
|
|
1212
|
+
/** 父组件通过 v-bind 更新已保存配置时,同步到工具栏草稿。 */
|
|
1213
|
+
externalLayoutConfig: {
|
|
1214
|
+
deep: true,
|
|
1215
|
+
handler(val) {
|
|
1216
|
+
this.configDraft = { ...val }
|
|
1217
|
+
}
|
|
1218
|
+
},
|
|
1219
|
+
|
|
740
1220
|
/** 数据变化后校正当前月份(比如接口返回了新的月份列表) */
|
|
741
1221
|
monthOptions: {
|
|
742
1222
|
immediate: true,
|
|
@@ -794,6 +1274,123 @@ export default {
|
|
|
794
1274
|
},
|
|
795
1275
|
|
|
796
1276
|
methods: {
|
|
1277
|
+
/* ========================= 布局配置 ========================= */
|
|
1278
|
+
/** 间距字段某个轴的当前 px 值(vertical 取上下、horizontal 取左右) */
|
|
1279
|
+
spacingAxisValue(key, axisKey) {
|
|
1280
|
+
const sides = parseSpacingToSides(this.configDraft[key])
|
|
1281
|
+
const axis = this.spacingAxes.find((a) => a.key === axisKey)
|
|
1282
|
+
return axis ? sides[axis.sides[0]] : 0
|
|
1283
|
+
},
|
|
1284
|
+
|
|
1285
|
+
/** 间距字段的可读简写,如 12px 10px(也用于标题 tooltip) */
|
|
1286
|
+
spacingShorthand(key) {
|
|
1287
|
+
return spacingFromSides(parseSpacingToSides(this.configDraft[key]))
|
|
1288
|
+
},
|
|
1289
|
+
|
|
1290
|
+
/** 按「上下 / 左右」整轴步进 ±delta px */
|
|
1291
|
+
nudgeSpacingAxis(key, axisKey, delta, event) {
|
|
1292
|
+
const step = event && event.shiftKey ? 5 : 1
|
|
1293
|
+
const sides = parseSpacingToSides(this.configDraft[key])
|
|
1294
|
+
const axis = this.spacingAxes.find((a) => a.key === axisKey)
|
|
1295
|
+
if (!axis) return
|
|
1296
|
+
const current = sides[axis.sides[0]] || 0
|
|
1297
|
+
const next = Math.max(0, Math.round(current + delta * step))
|
|
1298
|
+
if (next === current) return
|
|
1299
|
+
axis.sides.forEach((side) => { sides[side] = next })
|
|
1300
|
+
this.updateLayoutConfig(key, spacingFromSides(sides))
|
|
1301
|
+
},
|
|
1302
|
+
|
|
1303
|
+
/** 直接输入间距字段某个轴(上下/左右)的值,两端一起生效 */
|
|
1304
|
+
updateSpacingAxis(key, axisKey, event) {
|
|
1305
|
+
const raw = Number(event.target.value)
|
|
1306
|
+
const sides = parseSpacingToSides(this.configDraft[key])
|
|
1307
|
+
const axis = this.spacingAxes.find((a) => a.key === axisKey)
|
|
1308
|
+
if (!axis) return
|
|
1309
|
+
const next = Number.isFinite(raw) ? Math.max(0, Math.round(raw)) : 0
|
|
1310
|
+
axis.sides.forEach((side) => { sides[side] = next })
|
|
1311
|
+
this.updateLayoutConfig(key, spacingFromSides(sides))
|
|
1312
|
+
},
|
|
1313
|
+
|
|
1314
|
+
/** 数值字段步进:步长取字段 step(整数 ±1、角标缩放 ±0.05),按住 Shift ×5 */
|
|
1315
|
+
nudgeNumber(key, delta, event) {
|
|
1316
|
+
const field = CONFIG_FIELDS.find((f) => f.key === key)
|
|
1317
|
+
const unit = field && Number(field.step) ? Number(field.step) : 1
|
|
1318
|
+
const multi = event && event.shiftKey ? 5 : 1
|
|
1319
|
+
const current = Number(this.configDraft[key])
|
|
1320
|
+
const base = Number.isFinite(current) ? current : 0
|
|
1321
|
+
this.updateLayoutConfig(key, base + delta * unit * multi, 'number')
|
|
1322
|
+
},
|
|
1323
|
+
|
|
1324
|
+
/** 取色器展示值:未配置(空串)时给一个与默认主题一致的兜底色 */
|
|
1325
|
+
colorValue(key) {
|
|
1326
|
+
const hit = CONFIG_FIELDS.find((f) => f.key === key && f.kind === 'color')
|
|
1327
|
+
return this.configDraft[key] || (hit ? hit.default : '#000000')
|
|
1328
|
+
},
|
|
1329
|
+
|
|
1330
|
+
/** 还原颜色为默认配色(存空串) */
|
|
1331
|
+
resetColor(key) {
|
|
1332
|
+
this.updateLayoutConfig(key, '')
|
|
1333
|
+
},
|
|
1334
|
+
|
|
1335
|
+
/** 还原某个配置项到初始快照(configDefaults) */
|
|
1336
|
+
resetField(key) {
|
|
1337
|
+
if (!Object.prototype.hasOwnProperty.call(this.configDefaults, key)) return
|
|
1338
|
+
this.$set(this.configDraft, key, this.configDefaults[key])
|
|
1339
|
+
this.copyStatus = ''
|
|
1340
|
+
this.$emit('config-change', this.getLayoutConfig())
|
|
1341
|
+
},
|
|
1342
|
+
|
|
1343
|
+
updateLayoutConfig(key, value, inputType) {
|
|
1344
|
+
let nextValue = value
|
|
1345
|
+
if (inputType === 'number') {
|
|
1346
|
+
const parsed = Number(value)
|
|
1347
|
+
const field = CONFIG_FIELDS.find((f) => f.key === key)
|
|
1348
|
+
const min = field && typeof field.min === 'number' ? field.min : 0
|
|
1349
|
+
nextValue = Number.isFinite(parsed)
|
|
1350
|
+
? Math.max(min, Math.round(parsed * 100) / 100)
|
|
1351
|
+
: min
|
|
1352
|
+
}
|
|
1353
|
+
this.$set(this.configDraft, key, nextValue)
|
|
1354
|
+
this.copyStatus = ''
|
|
1355
|
+
this.$emit('config-change', this.getLayoutConfig())
|
|
1356
|
+
},
|
|
1357
|
+
|
|
1358
|
+
/** 返回可直接 <EventCalendar v-bind="config" /> 的配置对象。 */
|
|
1359
|
+
getLayoutConfig() {
|
|
1360
|
+
return { ...this.effectiveLayoutConfig }
|
|
1361
|
+
},
|
|
1362
|
+
|
|
1363
|
+
/** 复制当前配置 JSON 到剪贴板(用户直接粘贴发回,研发贴到组件上即可) */
|
|
1364
|
+
copyLayoutConfig() {
|
|
1365
|
+
const json = this.configJsonText
|
|
1366
|
+
const fallback = () => {
|
|
1367
|
+
if (typeof document === 'undefined') {
|
|
1368
|
+
this.copyStatus = '已复制,可粘贴发送给研发。'
|
|
1369
|
+
return
|
|
1370
|
+
}
|
|
1371
|
+
const ta = document.createElement('textarea')
|
|
1372
|
+
ta.value = json
|
|
1373
|
+
ta.setAttribute('readonly', '')
|
|
1374
|
+
ta.style.position = 'fixed'
|
|
1375
|
+
ta.style.opacity = '0'
|
|
1376
|
+
document.body.appendChild(ta)
|
|
1377
|
+
ta.select()
|
|
1378
|
+
let ok = false
|
|
1379
|
+
try { ok = document.execCommand('copy') } catch (e) { ok = false }
|
|
1380
|
+
document.body.removeChild(ta)
|
|
1381
|
+
this.copyStatus = ok
|
|
1382
|
+
? '已复制,可粘贴发送给研发。'
|
|
1383
|
+
: '复制失败,请手动全选下方 JSON 后复制。'
|
|
1384
|
+
}
|
|
1385
|
+
if (typeof navigator !== 'undefined' && navigator.clipboard && window.isSecureContext) {
|
|
1386
|
+
navigator.clipboard.writeText(json).then(() => {
|
|
1387
|
+
this.copyStatus = '已复制,可粘贴发送给研发。'
|
|
1388
|
+
}, fallback)
|
|
1389
|
+
} else {
|
|
1390
|
+
fallback()
|
|
1391
|
+
}
|
|
1392
|
+
},
|
|
1393
|
+
|
|
797
1394
|
/* ========================= 月份切换 ========================= */
|
|
798
1395
|
/**
|
|
799
1396
|
* 切换到指定月份
|
|
@@ -1050,6 +1647,7 @@ export default {
|
|
|
1050
1647
|
item: entry.raw,
|
|
1051
1648
|
raw: entry.raw,
|
|
1052
1649
|
label: entry.label,
|
|
1650
|
+
address: entry.address,
|
|
1053
1651
|
badge: entry.badge,
|
|
1054
1652
|
type: entry.type,
|
|
1055
1653
|
disabled: entry.disabled,
|
|
@@ -1082,6 +1680,22 @@ export default {
|
|
|
1082
1680
|
this.$emit('more-click', this.cellScope(cell), event)
|
|
1083
1681
|
},
|
|
1084
1682
|
|
|
1683
|
+
hasText(value) {
|
|
1684
|
+
return value !== undefined && value !== null && String(value).trim() !== ''
|
|
1685
|
+
},
|
|
1686
|
+
|
|
1687
|
+
itemTitle(entry) {
|
|
1688
|
+
const label = this.hasText(entry.label) ? String(entry.label) : ''
|
|
1689
|
+
const address = this.hasText(entry.address) ? `\n${entry.address}` : ''
|
|
1690
|
+
return label + address
|
|
1691
|
+
},
|
|
1692
|
+
|
|
1693
|
+
/** 大学名称超过 7 个字符时使用 12px,否则使用 14px。 */
|
|
1694
|
+
isLongItemLabel(label) {
|
|
1695
|
+
const text = label == null ? '' : String(label)
|
|
1696
|
+
return text.length > 7
|
|
1697
|
+
},
|
|
1698
|
+
|
|
1085
1699
|
/* ========================= 配色 ========================= */
|
|
1086
1700
|
resolveTypeColor(type) {
|
|
1087
1701
|
const merged = { ...BUILTIN_TYPE_COLORS, ...this.typeColors }
|
|
@@ -1113,13 +1727,415 @@ export default {
|
|
|
1113
1727
|
.ec {
|
|
1114
1728
|
position: relative;
|
|
1115
1729
|
box-sizing: border-box;
|
|
1116
|
-
width:
|
|
1730
|
+
width: auto;
|
|
1731
|
+
margin: var(--ec-calendar-margin);
|
|
1732
|
+
padding: var(--ec-calendar-padding);
|
|
1117
1733
|
color: var(--ec-text);
|
|
1118
1734
|
font-size: 14px;
|
|
1119
1735
|
line-height: 1.5;
|
|
1120
1736
|
-webkit-font-smoothing: antialiased;
|
|
1121
1737
|
}
|
|
1122
1738
|
|
|
1739
|
+
/* -------------------------- 布局配置工具栏 -------------------------- */
|
|
1740
|
+
.ec__config {
|
|
1741
|
+
margin-bottom: 16px;
|
|
1742
|
+
padding: 14px;
|
|
1743
|
+
border: 1px solid var(--ec-border);
|
|
1744
|
+
border-radius: calc(var(--ec-radius) + 2px);
|
|
1745
|
+
background: #f8fafc;
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
.ec__config-head,
|
|
1749
|
+
.ec__config-actions,
|
|
1750
|
+
.ec__config-segment {
|
|
1751
|
+
display: flex;
|
|
1752
|
+
align-items: center;
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
.ec__config-head {
|
|
1756
|
+
justify-content: space-between;
|
|
1757
|
+
gap: 12px;
|
|
1758
|
+
margin-bottom: 12px;
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
.ec__config-title {
|
|
1762
|
+
color: var(--ec-text);
|
|
1763
|
+
font-size: 14px;
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
.ec__config-caption {
|
|
1767
|
+
margin-left: 8px;
|
|
1768
|
+
color: var(--ec-text-secondary);
|
|
1769
|
+
font-size: 12px;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
.ec__config-actions {
|
|
1773
|
+
gap: 8px;
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
.ec__config-btn,
|
|
1777
|
+
.ec__config-segment button {
|
|
1778
|
+
min-height: 34px;
|
|
1779
|
+
border: 1px solid var(--ec-border);
|
|
1780
|
+
border-radius: 6px;
|
|
1781
|
+
background: #fff;
|
|
1782
|
+
color: var(--ec-text-secondary);
|
|
1783
|
+
font: inherit;
|
|
1784
|
+
font-size: 12px;
|
|
1785
|
+
cursor: pointer;
|
|
1786
|
+
transition: color 0.18s, border-color 0.18s, background-color 0.18s;
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
.ec__config-btn {
|
|
1790
|
+
padding: 0 12px;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
.ec__config-btn.is-primary,
|
|
1794
|
+
.ec__config-segment button.is-active {
|
|
1795
|
+
border-color: var(--ec-primary);
|
|
1796
|
+
background: var(--ec-primary);
|
|
1797
|
+
color: #fff;
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
.ec__config-btn:hover,
|
|
1801
|
+
.ec__config-segment button:hover {
|
|
1802
|
+
border-color: var(--ec-primary);
|
|
1803
|
+
color: var(--ec-primary);
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
.ec__config-btn.is-primary:hover,
|
|
1807
|
+
.ec__config-segment button.is-active:hover {
|
|
1808
|
+
color: #fff;
|
|
1809
|
+
opacity: 0.9;
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
.ec__config-btn:focus-visible,
|
|
1813
|
+
.ec__config-segment button:focus-visible,
|
|
1814
|
+
.ec__stepper:focus-within,
|
|
1815
|
+
.ec__reset-btn:focus-visible,
|
|
1816
|
+
.ec__config input[type='color']:focus-visible {
|
|
1817
|
+
outline: 2px solid var(--ec-primary);
|
|
1818
|
+
outline-offset: 2px;
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
/* 自带 +/− 步进按钮,隐藏数字框原生上下箭头 */
|
|
1822
|
+
.ec__config input[type='number'] {
|
|
1823
|
+
-moz-appearance: textfield;
|
|
1824
|
+
appearance: textfield;
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
.ec__config input[type='number']::-webkit-outer-spin-button,
|
|
1828
|
+
.ec__config input[type='number']::-webkit-inner-spin-button {
|
|
1829
|
+
-webkit-appearance: none;
|
|
1830
|
+
margin: 0;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
/* 取色器只保留色块 */
|
|
1834
|
+
.ec__config input[type='color'] {
|
|
1835
|
+
appearance: none;
|
|
1836
|
+
-webkit-appearance: none;
|
|
1837
|
+
width: 34px;
|
|
1838
|
+
height: 34px;
|
|
1839
|
+
padding: 0;
|
|
1840
|
+
border: 0;
|
|
1841
|
+
border-radius: 8px;
|
|
1842
|
+
background: transparent;
|
|
1843
|
+
cursor: pointer;
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
.ec__config input[type='color']::-webkit-color-swatch-wrapper {
|
|
1847
|
+
padding: 0;
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
.ec__config input[type='color']::-webkit-color-swatch,
|
|
1851
|
+
.ec__config input[type='color']::-moz-color-swatch {
|
|
1852
|
+
border: 1px solid var(--ec-border);
|
|
1853
|
+
border-radius: 8px;
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
/* 字段网格:默认 5 列一排,卡片更小更矮 */
|
|
1857
|
+
.ec__config-list {
|
|
1858
|
+
display: grid;
|
|
1859
|
+
grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
1860
|
+
gap: 8px;
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
/* 每个字段一张白色小卡片 */
|
|
1864
|
+
.ec__config-block {
|
|
1865
|
+
min-width: 0;
|
|
1866
|
+
margin: 0;
|
|
1867
|
+
padding: 8px;
|
|
1868
|
+
border: 1px solid var(--ec-border);
|
|
1869
|
+
border-radius: 8px;
|
|
1870
|
+
background: #fff;
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
.ec__config-block--seg {
|
|
1874
|
+
display: flex;
|
|
1875
|
+
flex-direction: column;
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
.ec__config-label {
|
|
1879
|
+
display: flex;
|
|
1880
|
+
align-items: baseline;
|
|
1881
|
+
gap: 3px;
|
|
1882
|
+
flex-wrap: wrap;
|
|
1883
|
+
margin: 0 0 6px;
|
|
1884
|
+
color: var(--ec-text-secondary);
|
|
1885
|
+
font-size: 11px;
|
|
1886
|
+
line-height: 16px;
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
.ec__config-block--color .ec__config-label {
|
|
1890
|
+
margin: 0;
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
.ec__config-priority {
|
|
1894
|
+
color: var(--ec-primary);
|
|
1895
|
+
font-weight: 600;
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
.ec__config-shorthand {
|
|
1899
|
+
margin-left: 6px;
|
|
1900
|
+
max-width: 55%;
|
|
1901
|
+
overflow: hidden;
|
|
1902
|
+
color: var(--ec-text-placeholder);
|
|
1903
|
+
font-family: Consolas, Monaco, monospace;
|
|
1904
|
+
font-size: 10px;
|
|
1905
|
+
font-weight: 400;
|
|
1906
|
+
text-overflow: ellipsis;
|
|
1907
|
+
white-space: nowrap;
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
.ec__config-segment button {
|
|
1911
|
+
min-height: 28px;
|
|
1912
|
+
flex: 1;
|
|
1913
|
+
padding: 0 8px;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
.ec__config-segment button + button {
|
|
1917
|
+
margin-left: 6px;
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
/* ------------ 间距控件:每个字段只拆「上下」「左右」两大块 ------------ */
|
|
1921
|
+
.ec__spacing {
|
|
1922
|
+
display: flex;
|
|
1923
|
+
flex-direction: column;
|
|
1924
|
+
gap: 4px;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
.ec__spacing-row {
|
|
1928
|
+
display: flex;
|
|
1929
|
+
align-items: center;
|
|
1930
|
+
gap: 6px;
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
.ec__spacing-row-label {
|
|
1934
|
+
flex: none;
|
|
1935
|
+
width: 30px;
|
|
1936
|
+
color: var(--ec-text-secondary);
|
|
1937
|
+
font-size: 11px;
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
.ec__spacing-row .ec__stepper {
|
|
1941
|
+
flex: 1;
|
|
1942
|
+
min-width: 0;
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
/* ------------ 单值数值字段:输入框左右包 −/+ ------------ */
|
|
1946
|
+
.ec__stepper {
|
|
1947
|
+
display: flex;
|
|
1948
|
+
align-items: stretch;
|
|
1949
|
+
height: 30px;
|
|
1950
|
+
border: 1px solid var(--ec-border);
|
|
1951
|
+
border-radius: 6px;
|
|
1952
|
+
background: #fff;
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
.ec__step-btn {
|
|
1956
|
+
flex: none;
|
|
1957
|
+
width: 27px;
|
|
1958
|
+
border: 0;
|
|
1959
|
+
background: transparent;
|
|
1960
|
+
color: var(--ec-text-secondary);
|
|
1961
|
+
font-size: 15px;
|
|
1962
|
+
line-height: 1;
|
|
1963
|
+
cursor: pointer;
|
|
1964
|
+
transition: color 0.16s, background-color 0.16s;
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
.ec__step-btn:first-child {
|
|
1968
|
+
border-right: 1px solid var(--ec-border-light);
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
.ec__step-btn:last-child {
|
|
1972
|
+
border-left: 1px solid var(--ec-border-light);
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
.ec__step-btn:hover {
|
|
1976
|
+
color: var(--ec-primary);
|
|
1977
|
+
background: var(--ec-primary-ghost);
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
.ec__stepper-input {
|
|
1981
|
+
position: relative;
|
|
1982
|
+
flex: 1;
|
|
1983
|
+
min-width: 0;
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
.ec__stepper-input input {
|
|
1987
|
+
width: 100%;
|
|
1988
|
+
height: 100%;
|
|
1989
|
+
border: 0;
|
|
1990
|
+
outline: 0;
|
|
1991
|
+
padding: 0 22px 0 4px;
|
|
1992
|
+
background: transparent;
|
|
1993
|
+
color: var(--ec-text);
|
|
1994
|
+
font: inherit;
|
|
1995
|
+
font-size: 11px;
|
|
1996
|
+
text-align: center;
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
.ec__stepper-unit {
|
|
2000
|
+
position: absolute;
|
|
2001
|
+
top: 50%;
|
|
2002
|
+
right: 6px;
|
|
2003
|
+
transform: translateY(-50%);
|
|
2004
|
+
color: var(--ec-text-placeholder);
|
|
2005
|
+
font-size: 10px;
|
|
2006
|
+
pointer-events: none;
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
/* ------------ 颜色控件(并入字段网格的小卡片) ------------ */
|
|
2010
|
+
.ec__config-block--color {
|
|
2011
|
+
display: flex;
|
|
2012
|
+
align-items: center;
|
|
2013
|
+
gap: 8px;
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
.ec__config-block--color input[type='color'] {
|
|
2017
|
+
width: 28px;
|
|
2018
|
+
height: 28px;
|
|
2019
|
+
border-radius: 6px;
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
.ec__color-swatch {
|
|
2023
|
+
flex: none;
|
|
2024
|
+
width: 30px;
|
|
2025
|
+
height: 30px;
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
.ec__color-meta {
|
|
2029
|
+
display: flex;
|
|
2030
|
+
flex: 1;
|
|
2031
|
+
flex-direction: column;
|
|
2032
|
+
min-width: 0;
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
.ec__color-hex {
|
|
2036
|
+
margin-top: 1px;
|
|
2037
|
+
color: var(--ec-text);
|
|
2038
|
+
font-family: Consolas, Monaco, monospace;
|
|
2039
|
+
font-size: 11px;
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
.ec__reset-btn {
|
|
2043
|
+
flex: none;
|
|
2044
|
+
height: 24px;
|
|
2045
|
+
padding: 0 7px;
|
|
2046
|
+
border: 1px solid var(--ec-border);
|
|
2047
|
+
border-radius: 6px;
|
|
2048
|
+
background: #fff;
|
|
2049
|
+
color: var(--ec-text-secondary);
|
|
2050
|
+
font-size: 10px;
|
|
2051
|
+
cursor: pointer;
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
.ec__reset-btn:disabled {
|
|
2055
|
+
cursor: not-allowed;
|
|
2056
|
+
opacity: 0.45;
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
.ec__reset-btn:hover:not(:disabled) {
|
|
2060
|
+
border-color: var(--ec-primary);
|
|
2061
|
+
color: var(--ec-primary);
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
/* 卡片标题行右上角的「还原」 */
|
|
2065
|
+
.ec__config-reset {
|
|
2066
|
+
flex: none;
|
|
2067
|
+
align-self: center;
|
|
2068
|
+
margin-left: auto;
|
|
2069
|
+
padding: 0 6px;
|
|
2070
|
+
height: 20px;
|
|
2071
|
+
border: 1px solid transparent;
|
|
2072
|
+
border-radius: 5px;
|
|
2073
|
+
background: transparent;
|
|
2074
|
+
color: var(--ec-text-placeholder);
|
|
2075
|
+
font-size: 10px;
|
|
2076
|
+
line-height: 1;
|
|
2077
|
+
cursor: pointer;
|
|
2078
|
+
transition: color 0.16s, border-color 0.16s, background-color 0.16s;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
.ec__config-reset:hover {
|
|
2082
|
+
border-color: var(--ec-border);
|
|
2083
|
+
background: #fff;
|
|
2084
|
+
color: var(--ec-primary);
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
/* ------------ 配置 JSON 输出区 ------------ */
|
|
2088
|
+
.ec__config-output {
|
|
2089
|
+
margin-top: 10px;
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
.ec__config-json {
|
|
2093
|
+
max-height: 170px;
|
|
2094
|
+
margin: 0;
|
|
2095
|
+
padding: 10px 12px;
|
|
2096
|
+
overflow: auto;
|
|
2097
|
+
border-radius: 8px;
|
|
2098
|
+
background: #111827;
|
|
2099
|
+
color: #e5e7eb;
|
|
2100
|
+
font: 11px/1.6 Consolas, Monaco, monospace;
|
|
2101
|
+
white-space: pre-wrap;
|
|
2102
|
+
word-break: break-word;
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
.ec__config-feedback {
|
|
2106
|
+
min-height: 16px;
|
|
2107
|
+
margin-top: 6px;
|
|
2108
|
+
color: #059669;
|
|
2109
|
+
font-size: 12px;
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
@media (max-width: 1100px) {
|
|
2113
|
+
.ec__config-list {
|
|
2114
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
@media (max-width: 900px) {
|
|
2119
|
+
.ec__config-list {
|
|
2120
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
@media (max-width: 640px) {
|
|
2125
|
+
.ec__config-list {
|
|
2126
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
2127
|
+
}
|
|
2128
|
+
.ec__spacing-row-label {
|
|
2129
|
+
width: 26px;
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
@media (max-width: 420px) {
|
|
2134
|
+
.ec__config-list {
|
|
2135
|
+
grid-template-columns: 1fr;
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
|
|
1123
2139
|
.ec *,
|
|
1124
2140
|
.ec *::before,
|
|
1125
2141
|
.ec *::after {
|
|
@@ -1132,7 +2148,7 @@ export default {
|
|
|
1132
2148
|
align-items: center;
|
|
1133
2149
|
justify-content: space-between;
|
|
1134
2150
|
gap: 16px;
|
|
1135
|
-
padding:
|
|
2151
|
+
padding: var(--ec-header-padding);
|
|
1136
2152
|
}
|
|
1137
2153
|
|
|
1138
2154
|
.ec__header-left {
|
|
@@ -1263,7 +2279,7 @@ export default {
|
|
|
1263
2279
|
display: flex;
|
|
1264
2280
|
flex-direction: column;
|
|
1265
2281
|
min-width: 0;
|
|
1266
|
-
padding:
|
|
2282
|
+
padding: var(--ec-cell-padding);
|
|
1267
2283
|
border-right: 1px solid var(--ec-border-light);
|
|
1268
2284
|
border-bottom: 1px solid var(--ec-border-light);
|
|
1269
2285
|
transition: background-color 0.2s;
|
|
@@ -1372,31 +2388,52 @@ export default {
|
|
|
1372
2388
|
display: flex;
|
|
1373
2389
|
align-items: center;
|
|
1374
2390
|
min-height: var(--ec-item-h);
|
|
1375
|
-
padding:
|
|
2391
|
+
padding: var(--ec-item-padding-y) var(--ec-item-padding-x);
|
|
1376
2392
|
border-radius: 4px;
|
|
1377
2393
|
background: var(--ec-item-bg);
|
|
1378
|
-
|
|
1379
|
-
|
|
2394
|
+
/* 未显式配置文字色时沿用次要文字色;hover 回落到主文字色 */
|
|
2395
|
+
color: var(--ec-item-text, var(--ec-text-secondary));
|
|
1380
2396
|
cursor: pointer;
|
|
1381
2397
|
transition: background-color 0.18s, color 0.18s, box-shadow 0.18s;
|
|
1382
2398
|
}
|
|
1383
2399
|
|
|
1384
|
-
/* 有角标时右侧让位,没有角标则占满,避免留白 */
|
|
1385
|
-
.ec__item.has-badge {
|
|
1386
|
-
padding-right: 30px;
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
2400
|
/* 注意:外层 .ec__items 有 overflow-x: hidden(滚动条需要),
|
|
1390
|
-
* 所以 hover
|
|
2401
|
+
* 所以 hover 不能用水平位移,否则会被裁切;这里改用内阴影。
|
|
2402
|
+
* 悬浮背景 = 在底色上叠一层半透明白(--ec-item-hover-mask),自动调淡一档;
|
|
2403
|
+
* 文字画在阴影之上,不受影响。item-bg-hover=false 时 mask 为透明。 */
|
|
1391
2404
|
.ec__item:hover {
|
|
1392
|
-
color: var(--ec-text);
|
|
1393
|
-
box-shadow:
|
|
2405
|
+
color: var(--ec-item-text, var(--ec-text));
|
|
2406
|
+
box-shadow:
|
|
2407
|
+
inset 0 0 0 9999px var(--ec-item-hover-mask, rgba(255, 255, 255, 0.18)),
|
|
2408
|
+
inset 0 0 0 1px rgba(0, 0, 0, 0.08);
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
/* 渐变背景:纯色底上叠一层白色,默认上→下 */
|
|
2412
|
+
.ec__item.is-bg-gradient {
|
|
2413
|
+
background-image: linear-gradient(
|
|
2414
|
+
180deg,
|
|
2415
|
+
rgba(255, 255, 255, 0.55) 0%,
|
|
2416
|
+
rgba(255, 255, 255, 0.12) 46%,
|
|
2417
|
+
rgba(255, 255, 255, 0) 74%
|
|
2418
|
+
);
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2421
|
+
/* 渐变方向:左→右 */
|
|
2422
|
+
.ec__item.is-bg-gradient.is-bg-gradient-h {
|
|
2423
|
+
background-image: linear-gradient(
|
|
2424
|
+
90deg,
|
|
2425
|
+
rgba(255, 255, 255, 0.55) 0%,
|
|
2426
|
+
rgba(255, 255, 255, 0.12) 46%,
|
|
2427
|
+
rgba(255, 255, 255, 0) 74%
|
|
2428
|
+
);
|
|
1394
2429
|
}
|
|
1395
2430
|
|
|
1396
2431
|
.ec__item.is-colorful:hover {
|
|
1397
2432
|
background: var(--ec-item-accent-bg, var(--ec-item-bg));
|
|
1398
|
-
color: var(--ec-item-accent, var(--ec-text));
|
|
1399
|
-
box-shadow:
|
|
2433
|
+
color: var(--ec-item-text, var(--ec-item-accent, var(--ec-text)));
|
|
2434
|
+
box-shadow:
|
|
2435
|
+
inset 0 0 0 9999px rgba(255, 255, 255, 0.15),
|
|
2436
|
+
inset 0 0 0 1px var(--ec-item-accent-bg, transparent);
|
|
1400
2437
|
}
|
|
1401
2438
|
|
|
1402
2439
|
.ec__item.is-disabled {
|
|
@@ -1408,14 +2445,48 @@ export default {
|
|
|
1408
2445
|
box-shadow: none;
|
|
1409
2446
|
}
|
|
1410
2447
|
|
|
1411
|
-
.ec__item-
|
|
2448
|
+
.ec__item-content {
|
|
2449
|
+
display: flex;
|
|
1412
2450
|
flex: 1;
|
|
2451
|
+
flex-direction: column;
|
|
2452
|
+
min-width: 0;
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
.ec--item-center .ec__item {
|
|
2456
|
+
justify-content: center;
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
.ec--item-center .ec__item-content {
|
|
2460
|
+
align-items: center;
|
|
2461
|
+
text-align: center;
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2464
|
+
.ec__item-label,
|
|
2465
|
+
.ec__item-address {
|
|
2466
|
+
display: block;
|
|
1413
2467
|
min-width: 0;
|
|
2468
|
+
max-width: 100%;
|
|
1414
2469
|
overflow: hidden;
|
|
1415
2470
|
white-space: nowrap;
|
|
1416
2471
|
text-overflow: ellipsis;
|
|
1417
2472
|
}
|
|
1418
2473
|
|
|
2474
|
+
.ec__item-label {
|
|
2475
|
+
font-size: 14px;
|
|
2476
|
+
line-height: 16px;
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
.ec__item-label.is-long {
|
|
2480
|
+
font-size: 12px;
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
.ec__item-address {
|
|
2484
|
+
/* 名称与地址的行间距可配(item-line-gap) */
|
|
2485
|
+
margin-top: var(--ec-item-line-gap, 2px);
|
|
2486
|
+
font-size: 12px;
|
|
2487
|
+
line-height: 16px;
|
|
2488
|
+
}
|
|
2489
|
+
|
|
1419
2490
|
/* 角标:贴在条目右上角,与设计图一致 */
|
|
1420
2491
|
.ec__item-badge {
|
|
1421
2492
|
position: absolute;
|
|
@@ -1425,10 +2496,14 @@ export default {
|
|
|
1425
2496
|
border-radius: 0 4px 0 4px;
|
|
1426
2497
|
background: rgba(0, 0, 0, 0.06);
|
|
1427
2498
|
color: var(--ec-text-placeholder);
|
|
1428
|
-
font-size:
|
|
2499
|
+
font-size: 12px;
|
|
1429
2500
|
line-height: 16px;
|
|
1430
2501
|
white-space: nowrap;
|
|
1431
2502
|
cursor: pointer;
|
|
2503
|
+
/* 字号保持 12px 渲染,scale 倍率由配置 badge-scale 控制(默认 0.75);
|
|
2504
|
+
* 锚点在右上角,缩放后仍紧贴条目右上角,不占内容宽度 */
|
|
2505
|
+
transform: scale(var(--ec-badge-scale, 0.75));
|
|
2506
|
+
transform-origin: top right;
|
|
1432
2507
|
transition: filter 0.18s;
|
|
1433
2508
|
}
|
|
1434
2509
|
|
|
@@ -1618,6 +2693,17 @@ export default {
|
|
|
1618
2693
|
|
|
1619
2694
|
/* ------------------------------ 响应式 ------------------------------ */
|
|
1620
2695
|
@media (max-width: 768px) {
|
|
2696
|
+
.ec__config-head {
|
|
2697
|
+
align-items: flex-start;
|
|
2698
|
+
flex-direction: column;
|
|
2699
|
+
}
|
|
2700
|
+
.ec__config-actions {
|
|
2701
|
+
width: 100%;
|
|
2702
|
+
}
|
|
2703
|
+
.ec__config-btn {
|
|
2704
|
+
flex: 1;
|
|
2705
|
+
min-height: 40px;
|
|
2706
|
+
}
|
|
1621
2707
|
.ec__header {
|
|
1622
2708
|
flex-direction: column;
|
|
1623
2709
|
align-items: stretch;
|
|
@@ -1627,20 +2713,8 @@ export default {
|
|
|
1627
2713
|
justify-content: flex-end;
|
|
1628
2714
|
}
|
|
1629
2715
|
.ec__cell {
|
|
1630
|
-
padding:
|
|
1631
|
-
}
|
|
1632
|
-
.ec__item {
|
|
1633
|
-
font-size: 12px;
|
|
1634
|
-
}
|
|
1635
|
-
/* 窄屏下角标改为常规内联,不再绝对定位,因此收回右侧让位的内边距。
|
|
1636
|
-
* 这里必须带 .has-badge,否则选择器权重低于上面的 .ec__item.has-badge。 */
|
|
1637
|
-
.ec__item.has-badge {
|
|
1638
|
-
padding-right: 8px;
|
|
1639
|
-
}
|
|
1640
|
-
.ec__item-badge {
|
|
1641
|
-
position: static;
|
|
1642
|
-
margin-left: 6px;
|
|
1643
|
-
border-radius: 3px;
|
|
2716
|
+
padding: var(--ec-cell-padding-mobile);
|
|
1644
2717
|
}
|
|
2718
|
+
/* 角标在任何屏宽下都绝对定位、悬浮于条目右上角,不占内容宽度 */
|
|
1645
2719
|
}
|
|
1646
2720
|
</style>
|