npmapps 1.2.0 → 1.3.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.
Files changed (120) hide show
  1. package/README.md +41 -0
  2. package/files/part-002 +4 -0
  3. package/get.js +193 -0
  4. package/manifest.json +28 -0
  5. package/package.json +17 -10
  6. package/PUBLISH.md +0 -268
  7. package/app/wujie-wk/t.html +0 -90
  8. package/app/wujie-wk/wujie-vue2-child/.eslintrc.js +0 -19
  9. package/app/wujie-wk/wujie-vue2-child/README.md +0 -24
  10. package/app/wujie-wk/wujie-vue2-child/babel.config.js +0 -5
  11. package/app/wujie-wk/wujie-vue2-child/docs/superpowers/plans/2026-05-29-quill-editor.md +0 -836
  12. package/app/wujie-wk/wujie-vue2-child/docs/superpowers/specs/2026-05-29-quill-editor-design.md +0 -210
  13. package/app/wujie-wk/wujie-vue2-child/jsconfig.json +0 -19
  14. package/app/wujie-wk/wujie-vue2-child/package-lock.json +0 -21333
  15. package/app/wujie-wk/wujie-vue2-child/package.json +0 -63
  16. package/app/wujie-wk/wujie-vue2-child/postcss.config.js +0 -10
  17. package/app/wujie-wk/wujie-vue2-child/public/favicon.ico +0 -0
  18. package/app/wujie-wk/wujie-vue2-child/public/index.html +0 -17
  19. package/app/wujie-wk/wujie-vue2-child/public/rili.jpg +0 -0
  20. package/app/wujie-wk/wujie-vue2-child/public//344/270/200/351/224/256/351/273/221/346/232/227.html +0 -136
  21. package/app/wujie-wk/wujie-vue2-child/src/App.vue +0 -110
  22. package/app/wujie-wk/wujie-vue2-child/src/assets/bpmn-camunda.jpg +0 -0
  23. package/app/wujie-wk/wujie-vue2-child/src/assets/css/diagram.less +0 -17
  24. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/Icon.less +0 -31
  25. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/app-codes.css +0 -26
  26. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/app.eot +0 -0
  27. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/app.svg +0 -60
  28. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/app.ttf +0 -0
  29. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/app.woff +0 -0
  30. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/app.woff2 +0 -0
  31. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/config.json +0 -248
  32. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/raw/align-bottom-tool.svg +0 -30
  33. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/raw/align-horizontal-center-tool.svg +0 -85
  34. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/raw/align-left-tool.svg +0 -84
  35. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/raw/align-right-tool.svg +0 -80
  36. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/raw/align-top-tool.svg +0 -84
  37. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/raw/align-vertical-center-tool.svg +0 -89
  38. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/raw/distribute-horizontally-tool.svg +0 -95
  39. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/raw/distribute-vertically-tool.svg +0 -99
  40. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/raw/set-color-tool.svg +0 -111
  41. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/symbols/align-bottom-tool.svg +0 -30
  42. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/symbols/align-horizontal-center-tool.svg +0 -30
  43. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/symbols/align-left-tool.svg +0 -30
  44. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/symbols/align-right-tool.svg +0 -30
  45. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/symbols/align-top-tool.svg +0 -30
  46. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/symbols/align-vertical-center-tool.svg +0 -30
  47. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/symbols/distribute-horizontally-tool.svg +0 -30
  48. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/symbols/distribute-vertically-tool.svg +0 -30
  49. package/app/wujie-wk/wujie-vue2-child/src/assets/icon/font/source/symbols/set-color-tool.svg +0 -63
  50. package/app/wujie-wk/wujie-vue2-child/src/assets/logo.png +0 -0
  51. package/app/wujie-wk/wujie-vue2-child/src/components/EllTable/README.md +0 -70
  52. package/app/wujie-wk/wujie-vue2-child/src/components/EllTable/article.md +0 -184
  53. package/app/wujie-wk/wujie-vue2-child/src/components/EllTable/index.js +0 -213
  54. package/app/wujie-wk/wujie-vue2-child/src/components/EventCalendar/CalendarSkeleton.vue +0 -147
  55. package/app/wujie-wk/wujie-vue2-child/src/components/EventCalendar/CodeBlock.vue +0 -199
  56. package/app/wujie-wk/wujie-vue2-child/src/components/EventCalendar/MonthSelect.vue +0 -376
  57. package/app/wujie-wk/wujie-vue2-child/src/components/EventCalendar/README.md +0 -485
  58. package/app/wujie-wk/wujie-vue2-child/src/components/EventCalendar/example.vue +0 -1747
  59. package/app/wujie-wk/wujie-vue2-child/src/components/EventCalendar/index.vue +0 -2720
  60. package/app/wujie-wk/wujie-vue2-child/src/components/EventCalendar/mockData.js +0 -475
  61. package/app/wujie-wk/wujie-vue2-child/src/components/EventCalendar/recruitmentAdapter.js +0 -51
  62. package/app/wujie-wk/wujie-vue2-child/src/components/EventCalendar/utils.js +0 -202
  63. package/app/wujie-wk/wujie-vue2-child/src/components/FormulaEditor/FunctionSelector.vue +0 -123
  64. package/app/wujie-wk/wujie-vue2-child/src/components/FormulaEditor/OperatorSelector.vue +0 -184
  65. package/app/wujie-wk/wujie-vue2-child/src/components/FormulaEditor/ParameterSelector.vue +0 -123
  66. package/app/wujie-wk/wujie-vue2-child/src/components/FormulaEditor/api.js +0 -69
  67. package/app/wujie-wk/wujie-vue2-child/src/components/FormulaEditor/index.vue +0 -435
  68. package/app/wujie-wk/wujie-vue2-child/src/components/HelloWorld.vue +0 -58
  69. package/app/wujie-wk/wujie-vue2-child/src/components/PageHeader/index.vue +0 -158
  70. package/app/wujie-wk/wujie-vue2-child/src/components/Splitter/README.md +0 -144
  71. package/app/wujie-wk/wujie-vue2-child/src/components/Splitter/example.vue +0 -84
  72. package/app/wujie-wk/wujie-vue2-child/src/components/Splitter/index.vue +0 -203
  73. package/app/wujie-wk/wujie-vue2-child/src/components/diagram/ToolBar.vue +0 -357
  74. package/app/wujie-wk/wujie-vue2-child/src/components/diagram/customTranslate/customTranslate.js +0 -12
  75. package/app/wujie-wk/wujie-vue2-child/src/components/diagram/customTranslate/translationsGerman.js +0 -241
  76. package/app/wujie-wk/wujie-vue2-child/src/components/diagram/index.vue +0 -261
  77. package/app/wujie-wk/wujie-vue2-child/src/components/diagram/xmlData.js +0 -29
  78. package/app/wujie-wk/wujie-vue2-child/src/directives/filldown.js +0 -155
  79. package/app/wujie-wk/wujie-vue2-child/src/directives/filldownTable.js +0 -291
  80. package/app/wujie-wk/wujie-vue2-child/src/main.js +0 -40
  81. package/app/wujie-wk/wujie-vue2-child/src/router/index.js +0 -72
  82. package/app/wujie-wk/wujie-vue2-child/src/store/index.js +0 -23
  83. package/app/wujie-wk/wujie-vue2-child/src/utils/winBox.js +0 -23
  84. package/app/wujie-wk/wujie-vue2-child/src/views/Extend/A.vue +0 -12
  85. package/app/wujie-wk/wujie-vue2-child/src/views/Extend/B.vue +0 -10
  86. package/app/wujie-wk/wujie-vue2-child/src/views/Extend/MagicalComponentsForELFormItem.vue +0 -78
  87. package/app/wujie-wk/wujie-vue2-child/src/views/Extend/index.vue +0 -59
  88. package/app/wujie-wk/wujie-vue2-child/src/views/Extend/tableMouseHorizontalWheel.vue +0 -184
  89. package/app/wujie-wk/wujie-vue2-child/src/views/Home.vue +0 -27
  90. package/app/wujie-wk/wujie-vue2-child/src/views/RouterJump.vue +0 -145
  91. package/app/wujie-wk/wujie-vue2-child/src/views/calendar/index.vue +0 -19
  92. package/app/wujie-wk/wujie-vue2-child/src/views/css.vue +0 -57
  93. package/app/wujie-wk/wujie-vue2-child/src/views/cssComponents/EllipsisText.vue +0 -73
  94. package/app/wujie-wk/wujie-vue2-child/src/views/cssComponents/HoverCard.vue +0 -69
  95. package/app/wujie-wk/wujie-vue2-child/src/views/cssComponents/TableHover.vue +0 -130
  96. package/app/wujie-wk/wujie-vue2-child/src/views/cssComponents/inputSlo.vue +0 -42
  97. package/app/wujie-wk/wujie-vue2-child/src/views/cssComponents/tableFixed.vue +0 -148
  98. package/app/wujie-wk/wujie-vue2-child/src/views/echarts/echart-dome.vue +0 -73
  99. package/app/wujie-wk/wujie-vue2-child/src/views/echarts/index.vue +0 -118
  100. package/app/wujie-wk/wujie-vue2-child/src/views/echarts/pei3d.vue +0 -658
  101. package/app/wujie-wk/wujie-vue2-child/src/views/element/bpmn/index.vue +0 -15
  102. package/app/wujie-wk/wujie-vue2-child/src/views/element/components/attendanceCycle/index.vue +0 -131
  103. package/app/wujie-wk/wujie-vue2-child/src/views/element/components/attendanceGroup/index.vue +0 -147
  104. package/app/wujie-wk/wujie-vue2-child/src/views/element/components/attendancePersonnel/index.vue +0 -158
  105. package/app/wujie-wk/wujie-vue2-child/src/views/element/components/companyCalendar/index.vue +0 -147
  106. package/app/wujie-wk/wujie-vue2-child/src/views/element/components/shift/index.vue +0 -147
  107. package/app/wujie-wk/wujie-vue2-child/src/views/element/components/shiftRotationSystem/index.vue +0 -147
  108. package/app/wujie-wk/wujie-vue2-child/src/views/element/elTableJsx/columnManagement.vue +0 -340
  109. package/app/wujie-wk/wujie-vue2-child/src/views/element/elTableJsx/dialogInput.vue +0 -71
  110. package/app/wujie-wk/wujie-vue2-child/src/views/element/elTableJsx/elTableJsx.vue +0 -1826
  111. package/app/wujie-wk/wujie-vue2-child/src/views/element/elTableJsx/formTable.vue +0 -595
  112. package/app/wujie-wk/wujie-vue2-child/src/views/element/elTableJsx/index.vue +0 -29
  113. package/app/wujie-wk/wujie-vue2-child/src/views/element/elTableJsx/simpleTable.vue +0 -189
  114. package/app/wujie-wk/wujie-vue2-child/src/views/element/elTableJsx.zip +0 -0
  115. package/app/wujie-wk/wujie-vue2-child/src/views/element/index.vue +0 -39
  116. package/app/wujie-wk/wujie-vue2-child/src/views/element/quillEditor/README.md +0 -163
  117. package/app/wujie-wk/wujie-vue2-child/src/views/element/quillEditor/example.vue +0 -307
  118. package/app/wujie-wk/wujie-vue2-child/src/views/element/quillEditor/index.vue +0 -409
  119. package/app/wujie-wk/wujie-vue2-child/src/views/element/quillEditor/toolbar.js +0 -122
  120. package/app/wujie-wk/wujie-vue2-child/vue.config.js +0 -15
@@ -1,1747 +0,0 @@
1
- <template>
2
- <div class="doc">
3
- <!-- ============================ 页头 ============================ -->
4
- <header class="doc__hero">
5
- <h1 class="doc__hero-title">EventCalendar 日程日历</h1>
6
- <p class="doc__hero-desc">
7
- 零第三方依赖的月历组件:月份自动补全、下拉切换、自动轮播、可配字段、插槽定制、骨架屏。
8
- 整个 <code>EventCalendar</code> 文件夹可直接拷贝到任意 Vue 2 项目使用。
9
- </p>
10
- <div class="doc__hero-tags">
11
- <span v-for="t in heroTags" :key="t" class="doc__chip">{{ t }}</span>
12
- </div>
13
- </header>
14
-
15
- <div class="doc__body">
16
- <!-- ============================ 侧边目录 ============================ -->
17
- <nav class="doc__toc">
18
- <p class="doc__toc-title">示例目录</p>
19
- <a
20
- v-for="s in sections"
21
- :key="s.id"
22
- class="doc__toc-link"
23
- :class="{ 'is-active': activeSection === s.id }"
24
- href="javascript:void(0)"
25
- @click="scrollTo(s.id)"
26
- >{{ s.title }}</a>
27
- </nav>
28
-
29
- <!-- ============================ 示例主体 ============================ -->
30
- <main class="doc__main">
31
- <!-- ------------------------------------------------------------ -->
32
- <!-- 1. 基础用法 -->
33
- <!-- ------------------------------------------------------------ -->
34
- <section id="basic" class="demo">
35
- <h2 class="demo__title">1. 基础用法</h2>
36
- <p class="demo__desc">
37
- 传入 <code>data</code> 即可渲染。默认一周从<strong>周日</strong>开始,
38
- 当月之外的补位日期自动置灰;每格里的条目就是设计稿中的「学校 + 角标」。
39
- </p>
40
- <div class="demo__stage">
41
- <EventCalendar
42
- :data="basicData"
43
- title="宣讲日历"
44
- subtitle="更多场次陆续上线中,宣讲进程以实际安排为准"
45
- active-month="2026-09"
46
- />
47
- </div>
48
- <CodeBlock :code="code.basic" />
49
- </section>
50
-
51
- <!-- ------------------------------------------------------------ -->
52
- <!-- 2. 异步数据 + 骨架屏 -->
53
- <!-- ------------------------------------------------------------ -->
54
- <section id="async" class="demo">
55
- <h2 class="demo__title">2. 异步数据与骨架屏</h2>
56
- <p class="demo__desc">
57
- 数据由 <code>mockData.js</code> 通过 <code>setTimeout</code> 异步返回。
58
- 返回前 <code>loading</code> 为 <code>true</code>,组件渲染骨架屏,避免白屏和布局跳动。
59
- </p>
60
- <div class="demo__toolbar">
61
- <button class="doc__btn" :disabled="asyncLoading" @click="loadAsync">
62
- {{ asyncLoading ? '加载中…' : '重新加载(1.5s)' }}
63
- </button>
64
- <span class="doc__hint">骨架屏行数由 <code>skeleton-rows</code> 控制</span>
65
- </div>
66
- <div class="demo__stage">
67
- <EventCalendar
68
- :data="asyncData"
69
- :loading="asyncLoading"
70
- :skeleton-rows="5"
71
- title="宣讲日历"
72
- subtitle="数据加载完成前展示骨架屏"
73
- />
74
- </div>
75
- <CodeBlock :code="code.async" />
76
- </section>
77
-
78
- <!-- ------------------------------------------------------------ -->
79
- <!-- 3. 多月份与下拉切换 -->
80
- <!-- ------------------------------------------------------------ -->
81
- <section id="months" class="demo">
82
- <h2 class="demo__title">3. 多月份与下拉切换</h2>
83
- <p class="demo__desc">
84
- 后端返回多个月份时,右上角下拉框自动列出所有月份(下拉框为自研实现,支持键盘上下键与回车)。
85
- 打开 <code>show-arrows</code> 还能得到左右翻月按钮。当前月份可用
86
- <code>v-model</code> 或 <code>:active-month.sync</code> 双向绑定。
87
- </p>
88
- <div class="demo__toolbar">
89
- <span class="doc__hint">
90
- 当前绑定值:<code class="doc__code-inline">{{ monthsActive || '—' }}</code>
91
- </span>
92
- <button class="doc__btn doc__btn--ghost" @click="monthsActive = '2026-11'">
93
- 外部跳到 2026-11
94
- </button>
95
- </div>
96
- <div class="demo__stage">
97
- <EventCalendar
98
- v-model="monthsActive"
99
- :data="multiData"
100
- :loading="multiLoading"
101
- show-arrows
102
- title="宣讲日历"
103
- subtitle="下拉 / 箭头均可切换月份"
104
- @month-change="onMonthChange"
105
- />
106
- </div>
107
- <CodeBlock :code="code.months" />
108
- </section>
109
-
110
- <!-- ------------------------------------------------------------ -->
111
- <!-- 4. 自动轮播 -->
112
- <!-- ------------------------------------------------------------ -->
113
- <section id="autoplay" class="demo">
114
- <h2 class="demo__title">4. 自动轮播</h2>
115
- <p class="demo__desc">
116
- <code>autoplay</code> 开启轮播,<code>autoplay-interval</code> 配置间隔(毫秒)。
117
- 顶部细进度条展示距下次切换的剩余时间。以下情况会<strong>自动暂停</strong>并保留剩余时间:
118
- 鼠标悬停(<code>pause-on-hover</code>)、月份下拉展开、浏览器切到后台、点击暂停按钮。
119
- </p>
120
- <div class="demo__toolbar">
121
- <span class="doc__hint">切换间隔:</span>
122
- <button
123
- v-for="opt in intervalOptions"
124
- :key="opt.value"
125
- class="doc__seg"
126
- :class="{ 'is-active': autoplayInterval === opt.value }"
127
- @click="autoplayInterval = opt.value"
128
- >{{ opt.label }}</button>
129
- <label class="doc__check">
130
- <input v-model="autoplayLoop" type="checkbox" />
131
- <span>循环(关闭则播到最后一个月停止)</span>
132
- </label>
133
- </div>
134
- <div class="demo__stage">
135
- <EventCalendar
136
- :data="multiData"
137
- :loading="multiLoading"
138
- autoplay
139
- :autoplay-interval="autoplayInterval"
140
- :loop="autoplayLoop"
141
- pause-on-hover
142
- title="宣讲日历"
143
- subtitle="鼠标移上来试试,轮播会暂停"
144
- />
145
- </div>
146
- <CodeBlock :code="code.autoplay" />
147
- </section>
148
-
149
- <!-- ------------------------------------------------------------ -->
150
- <!-- 5. 切换动效 -->
151
- <!-- ------------------------------------------------------------ -->
152
- <section id="effect" class="demo">
153
- <h2 class="demo__title">5. 切换动效</h2>
154
- <p class="demo__desc">
155
- 提供 4 种月份切换动效,外加「单元格错峰入场」。动效可通过
156
- <code>transition-effect="none"</code> 完全关闭,时长由
157
- <code>transition-duration</code> 控制。
158
- 切换月份时行数可能从 5 行变 6 行,组件会同步做高度过渡,不会突然跳动。
159
- </p>
160
- <div class="demo__toolbar">
161
- <span class="doc__hint">动效:</span>
162
- <button
163
- v-for="opt in effectOptions"
164
- :key="opt.value"
165
- class="doc__seg"
166
- :class="{ 'is-active': effect === opt.value }"
167
- @click="effect = opt.value"
168
- >{{ opt.label }}</button>
169
- </div>
170
- <div class="demo__toolbar">
171
- <label class="doc__check">
172
- <input v-model="stagger" type="checkbox" />
173
- <span>单元格错峰入场</span>
174
- </label>
175
- <span class="doc__hint">时长 {{ duration }}ms</span>
176
- <input v-model.number="duration" type="range" min="0" max="1200" step="20" class="doc__range" />
177
- </div>
178
- <div class="demo__stage">
179
- <EventCalendar
180
- :data="multiData"
181
- :loading="multiLoading"
182
- :transition-effect="effect"
183
- :transition-duration="duration"
184
- :cell-stagger="stagger"
185
- show-arrows
186
- autoplay
187
- :autoplay-interval="6000"
188
- title="动效预览"
189
- subtitle="每 6 秒自动切换一次,也可以点箭头手动切"
190
- />
191
- </div>
192
- <CodeBlock :code="code.effect" />
193
- </section>
194
-
195
- <!-- ------------------------------------------------------------ -->
196
- <!-- 6. 月份补全与跨年 -->
197
- <!-- ------------------------------------------------------------ -->
198
- <section id="boundary" class="demo">
199
- <h2 class="demo__title">6. 月份补全与跨年边界</h2>
200
- <p class="demo__desc">
201
- 每月天数与「1 号是星期几」都不固定,组件会自动补齐首尾:
202
- 2026 年 2 月 1 号是<strong>周日</strong>,首行无需补位;2 月 28 号是<strong>周六</strong>,
203
- 末行也刚好排满;而 2026 年 1 月要往前补 <strong>2025 年 12 月</strong>的日期,
204
- 12 月则要往后补 <strong>2026 年 1 月</strong>——跨年由原生 <code>Date</code> 的进位机制保证正确。
205
- 切到 <code>2025-12</code> / <code>2026-01</code> 看看灰色补位格。
206
- </p>
207
- <div class="demo__toolbar">
208
- <label class="doc__check">
209
- <input v-model="showAdjacentItems" type="checkbox" />
210
- <span>补位日期也显示条目(关闭后只留灰色日期)</span>
211
- </label>
212
- <label class="doc__check">
213
- <input v-model="mondayFirst" type="checkbox" />
214
- <span>一周从周一开始(first-day-of-week=1)</span>
215
- </label>
216
- </div>
217
- <div class="demo__stage">
218
- <EventCalendar
219
- :data="crossYearData"
220
- :loading="crossYearLoading"
221
- :active-month.sync="crossYearMonth"
222
- :show-adjacent-items="showAdjacentItems"
223
- :first-day-of-week="mondayFirst ? 1 : 0"
224
- show-arrows
225
- title="跨年场次"
226
- subtitle="2025-12 / 2026-01 / 2026-02"
227
- />
228
- </div>
229
- <CodeBlock :code="code.boundary" />
230
- </section>
231
-
232
- <!-- ------------------------------------------------------------ -->
233
- <!-- 7. 自定义字段映射 -->
234
- <!-- ------------------------------------------------------------ -->
235
- <section id="schema" class="demo">
236
- <h2 class="demo__title">7. 自定义字段映射</h2>
237
- <p class="demo__desc">
238
- 后端字段名和组件默认约定不一致时,<strong>不需要改数据</strong>,
239
- 传一个 <code>field-names</code> 即可。下面这份数据用的是
240
- <code>ym / dateList / dayStr / activityList / schoolName / rawAddress</code>,
241
- 字段路径还支持 <code>'a.b.c'</code> 形式。
242
- </p>
243
- <div class="demo__cols">
244
- <div class="demo__col">
245
- <p class="demo__col-title">后端返回(片段)</p>
246
- <CodeBlock :code="code.schemaData" always-open />
247
- </div>
248
- <div class="demo__col">
249
- <p class="demo__col-title">映射配置</p>
250
- <CodeBlock :code="code.schemaMap" always-open />
251
- </div>
252
- </div>
253
- <div class="demo__stage">
254
- <EventCalendar
255
- :data="schemaData"
256
- :loading="schemaLoading"
257
- :field-names="altFieldNames"
258
- title="字段映射示例"
259
- subtitle="数据字段全都不一样,组件照样认识"
260
- />
261
- </div>
262
- </section>
263
-
264
- <!-- ------------------------------------------------------------ -->
265
- <!-- 8. 条目溢出与行高 -->
266
- <!-- ------------------------------------------------------------ -->
267
- <section id="overflow" class="demo">
268
- <h2 class="demo__title">8. 条目溢出与行高</h2>
269
- <p class="demo__desc">
270
- 每天的条目数量不固定。<strong>行高由该行条目最多的那一天决定</strong>(CSS Grid 天然等高,无需 JS 计算)。
271
- 超过 <code>max-visible-items</code> 后有两种处理:
272
- <code>scroll</code> 在格内出现细滚动条,<code>collapse</code> 折叠并显示「还有 N 项」(可监听
273
- <code>more-click</code>)。
274
- </p>
275
- <div class="demo__toolbar">
276
- <span class="doc__hint">溢出方式:</span>
277
- <button
278
- v-for="opt in overflowOptions"
279
- :key="opt.value"
280
- class="doc__seg"
281
- :class="{ 'is-active': overflowMode === opt.value }"
282
- @click="overflowMode = opt.value"
283
- >{{ opt.label }}</button>
284
- <span class="doc__hint">最多显示 {{ maxVisibleItems }} 条</span>
285
- <input v-model.number="maxVisibleItems" type="range" min="1" max="6" step="1" class="doc__range" />
286
- </div>
287
- <div class="demo__stage">
288
- <EventCalendar
289
- :data="overflowData"
290
- :loading="overflowLoading"
291
- :max-visible-items="maxVisibleItems"
292
- :overflow-mode="overflowMode"
293
- :min-row-height="120"
294
- title="溢出演示"
295
- subtitle="部分日期故意放了 6 条数据"
296
- @more-click="onMoreClick"
297
- />
298
- </div>
299
- <CodeBlock :code="code.overflow" />
300
- </section>
301
-
302
- <!-- ------------------------------------------------------------ -->
303
- <!-- 9. 插槽定制 -->
304
- <!-- ------------------------------------------------------------ -->
305
- <section id="slots" class="demo">
306
- <h2 class="demo__title">9. 插槽定制</h2>
307
- <p class="demo__desc">
308
- 左上角 <code>header-left</code>、单条 <code>item</code>、整格 <code>day</code>、
309
- 当天无数据时的 <code>day-empty</code> 等都可以自定义。
310
- 下面这个例子把左上角换成了统计卡片,把条目换成了「时间 + 学校 + 地点」的两行布局。
311
- </p>
312
- <div class="demo__stage">
313
- <EventCalendar
314
- :data="multiData"
315
- :loading="multiLoading"
316
- :min-row-height="140"
317
- :item-height="44"
318
- :max-visible-items="3"
319
- >
320
- <!-- 左上角完全自定义 -->
321
- <template #header-left="{ monthLabel, monthIndex, monthCount }">
322
- <div class="custom-head">
323
- <div class="custom-head__badge">{{ monthLabel }}</div>
324
- <div class="custom-head__meta">
325
- <strong>校园招聘日程</strong>
326
- <span>第 {{ monthIndex + 1 }} / {{ monthCount }} 个月 · 共 {{ monthItemCount }} 场</span>
327
- </div>
328
- </div>
329
- </template>
330
-
331
- <!-- 单条条目自定义 -->
332
- <template #item="{ item, label, badge, type }">
333
- <div class="custom-item" :class="'is-' + type">
334
- <div class="custom-item__row">
335
- <span class="custom-item__time">{{ item.startTime || '—' }}</span>
336
- <span class="custom-item__name">{{ label }}</span>
337
- </div>
338
- <div class="custom-item__row custom-item__row--sub">
339
- <span class="custom-item__addr">{{ item.address || '地点待定' }}</span>
340
- <span v-if="badge" class="custom-item__tag">{{ badge }}</span>
341
- </div>
342
- </div>
343
- </template>
344
-
345
- <!-- 当天没有数据时的占位 -->
346
- <template #day-empty="{ isCurrentMonth }">
347
- <div v-if="isCurrentMonth" class="custom-empty">暂无安排</div>
348
- </template>
349
- </EventCalendar>
350
- </div>
351
- <CodeBlock :code="code.slots" />
352
- </section>
353
-
354
- <!-- ------------------------------------------------------------ -->
355
- <!-- 10. 事件 -->
356
- <!-- ------------------------------------------------------------ -->
357
- <section id="events" class="demo">
358
- <h2 class="demo__title">10. 事件</h2>
359
- <p class="demo__desc">
360
- 点击<strong>格子空白处</strong>触发 <code>day-click</code>,点击<strong>条目</strong>触发
361
- <code>item-click</code>,点击条目右上角<strong>角标</strong>触发 <code>tag-click</code>
362
- (未监听 <code>tag-click</code> 时会退化成 <code>item-click</code>,避免「点了没反应」)。
363
- 回调都会带上完整的原始数据对象。
364
- </p>
365
- <div class="demo__cols demo__cols--events">
366
- <div class="demo__stage demo__stage--flex">
367
- <EventCalendar
368
- :data="basicData"
369
- active-month="2026-09"
370
- title="点点看"
371
- subtitle="日期格 / 条目 / 角标 都可点"
372
- @day-click="onDayClick"
373
- @item-click="onItemClick"
374
- @tag-click="onTagClick"
375
- />
376
- </div>
377
- <div class="event-log">
378
- <div class="event-log__head">
379
- <span>事件日志</span>
380
- <button class="doc__btn doc__btn--ghost doc__btn--sm" @click="logs = []">清空</button>
381
- </div>
382
- <ul v-if="logs.length" class="event-log__list">
383
- <li v-for="(log, i) in logs" :key="i" class="event-log__item">
384
- <span class="event-log__type" :class="'is-' + log.type">{{ log.type }}</span>
385
- <span class="event-log__text">{{ log.text }}</span>
386
- </li>
387
- </ul>
388
- <p v-else class="event-log__empty">还没有事件,点左侧日历试试</p>
389
- </div>
390
- </div>
391
- <CodeBlock :code="code.events" />
392
- </section>
393
-
394
- <!-- ------------------------------------------------------------ -->
395
- <!-- 11. 主题与样式变体 -->
396
- <!-- ------------------------------------------------------------ -->
397
- <section id="theme" class="demo">
398
- <h2 class="demo__title">11. 主题与样式变体</h2>
399
- <p class="demo__desc">
400
- 所有颜色走 CSS 变量,用 <code>theme</code> 传入即可换肤;
401
- <code>type-colors</code> 可为业务类型指定配色;
402
- <code>:colorful="false"</code> 会让角标回到中性灰(更贴近原始设计稿)。
403
- </p>
404
- <div class="demo__toolbar">
405
- <button
406
- v-for="t in themePresets"
407
- :key="t.name"
408
- class="doc__seg"
409
- :class="{ 'is-active': themeName === t.name }"
410
- @click="themeName = t.name"
411
- >{{ t.label }}</button>
412
- <label class="doc__check">
413
- <input v-model="colorful" type="checkbox" />
414
- <span>角标彩色(关闭 = 还原设计稿灰色)</span>
415
- </label>
416
- </div>
417
- <div class="demo__stage">
418
- <EventCalendar
419
- :data="basicData"
420
- active-month="2026-09"
421
- :theme="currentTheme"
422
- :colorful="colorful"
423
- :type-colors="typeColors"
424
- title="主题预览"
425
- :subtitle="'当前:' + themeName"
426
- />
427
- </div>
428
- <CodeBlock :code="code.theme" />
429
- </section>
430
-
431
- <!-- ------------------------------------------------------------ -->
432
- <!-- 12. 空状态 -->
433
- <!-- ------------------------------------------------------------ -->
434
- <section id="empty" class="demo">
435
- <h2 class="demo__title">12. 空状态与无头部</h2>
436
- <p class="demo__desc">
437
- 没有任何月份数据时展示空状态,文案由 <code>empty-text</code> 控制,
438
- 也可以用 <code>empty</code> 插槽整体替换。
439
- <code>:show-header="false"</code> 可以隐藏整个顶部区域,把日历当作纯展示块嵌进别的容器。
440
- </p>
441
- <div class="demo__cols">
442
- <div class="demo__col">
443
- <p class="demo__col-title">空数据</p>
444
- <div class="demo__stage">
445
- <EventCalendar :data="[]" empty-text="本月暂无宣讲安排" :show-header="false" />
446
- </div>
447
- </div>
448
- <div class="demo__col">
449
- <p class="demo__col-title">持续加载中</p>
450
- <div class="demo__stage">
451
- <EventCalendar :data="[]" loading :skeleton-rows="4" :show-header="false" />
452
- </div>
453
- </div>
454
- </div>
455
- </section>
456
-
457
- <!-- ------------------------------------------------------------ -->
458
- <!-- 13. NodeQ 后端数据适配 -->
459
- <!-- ------------------------------------------------------------ -->
460
- <section id="nodeq" class="demo">
461
- <h2 class="demo__title">13. NodeQ 后端数据适配</h2>
462
- <p class="demo__desc">
463
- mock 响应先通过简单转换方法得到标准日历数据,再直接传给
464
- <code>EventCalendar</code>。地址、居中和左右内边距均由组件原生支持。
465
- </p>
466
- <div class="demo__toolbar">
467
- <span class="doc__hint">条目对齐:</span>
468
- <button
469
- v-for="opt in nodeqAlignmentOptions"
470
- :key="opt.value"
471
- class="doc__seg"
472
- :class="{ 'is-active': nodeqAlignment === opt.value }"
473
- @click="nodeqAlignment = opt.value"
474
- >{{ opt.label }}</button>
475
-
476
- <label class="doc__check">
477
- <input v-model="nodeqNoHorizontalPadding" type="checkbox" />
478
- <span>去除条目左右内边距</span>
479
- </label>
480
- </div>
481
- <div class="demo__stage">
482
- <EventCalendar
483
- :data="nodeqData"
484
- :active-month.sync="nodeqActiveMonth"
485
- :item-align="nodeqAlignment"
486
- :item-horizontal-padding="nodeqNoHorizontalPadding ? 0 : 8"
487
- :item-height="40"
488
- :max-visible-items="5"
489
- :min-row-height="142"
490
- show-arrows
491
- title="宣讲日历(NodeQ)"
492
- subtitle="三个月模拟数据 · 每个有安排的日期 3~5 条"
493
- />
494
- </div>
495
- <CodeBlock :code="code.nodeq" />
496
- </section>
497
-
498
- <!-- ------------------------------------------------------------ -->
499
- <!-- 14. 原生布局配置与 JSON 导出 -->
500
- <!-- ------------------------------------------------------------ -->
501
- <section id="layout-config" class="demo">
502
- <h2 class="demo__title">14. 原生布局配置与一键复制</h2>
503
- <p class="demo__desc">
504
- 配置工具栏属于 <code>EventCalendar</code> 自身能力,按 P1~P14 排列常用项:
505
- 条目对齐、日期格/窄屏日期格内边距(各拆「上下 / 左右」两块)、条目边距与间距、
506
- 名称与地址间距、单格最多显示、条目高度、条目背景效果(纯色/渐变,方向可上下或左右)、
507
- 悬浮加深(可关闭)与条目背景/文字色;选定背景色后悬浮会自动调淡一档。
508
- 每张卡片右上角的「还原」可回到初始值,调整后点「复制配置」,JSON 直接进剪贴板,发给研发即可。
509
- 生产环境保持默认隐藏,开发配置时再传入 <code>show-config-toolbar</code>。
510
- </p>
511
- <div class="demo__toolbar">
512
- <label class="doc__check">
513
- <input v-model="layoutToolbarVisible" type="checkbox" />
514
- <span>显示组件内配置工具栏</span>
515
- </label>
516
- <span class="doc__hint">
517
- 当前参数:<code>show-config-toolbar="{{ layoutToolbarVisible }}"</code>
518
- </span>
519
- </div>
520
- <div class="demo__stage">
521
- <EventCalendar
522
- :data="nodeqData"
523
- :active-month.sync="layoutActiveMonth"
524
- v-bind="savedLayoutConfig"
525
- :show-config-toolbar="layoutToolbarVisible"
526
- :item-height="40"
527
- :max-visible-items="5"
528
- :min-row-height="142"
529
- show-arrows
530
- title="可配置宣讲日历"
531
- subtitle="配置结果点「复制配置」,粘贴发给研发即可"
532
- />
533
- </div>
534
- <CodeBlock :code="code.layoutConfig" />
535
- </section>
536
-
537
- <!-- ------------------------------------------------------------ -->
538
- <!-- API -->
539
- <!-- ------------------------------------------------------------ -->
540
- <section id="api" class="demo">
541
- <h2 class="demo__title">API</h2>
542
-
543
- <h3 class="demo__sub">Props</h3>
544
- <div class="doc__table-wrap">
545
- <table class="doc__table">
546
- <thead>
547
- <tr><th>参数</th><th>说明</th><th>类型</th><th>默认值</th></tr>
548
- </thead>
549
- <tbody>
550
- <tr v-for="row in apiProps" :key="row[0]">
551
- <td><code>{{ row[0] }}</code></td>
552
- <td>{{ row[1] }}</td>
553
- <td><span class="doc__type">{{ row[2] }}</span></td>
554
- <td><code>{{ row[3] }}</code></td>
555
- </tr>
556
- </tbody>
557
- </table>
558
- </div>
559
-
560
- <h3 class="demo__sub">Events</h3>
561
- <div class="doc__table-wrap">
562
- <table class="doc__table">
563
- <thead>
564
- <tr><th>事件名</th><th>说明</th><th>回调参数</th></tr>
565
- </thead>
566
- <tbody>
567
- <tr v-for="row in apiEvents" :key="row[0]">
568
- <td><code>{{ row[0] }}</code></td>
569
- <td>{{ row[1] }}</td>
570
- <td><span class="doc__type">{{ row[2] }}</span></td>
571
- </tr>
572
- </tbody>
573
- </table>
574
- </div>
575
-
576
- <h3 class="demo__sub">Slots</h3>
577
- <div class="doc__table-wrap">
578
- <table class="doc__table">
579
- <thead>
580
- <tr><th>名称</th><th>说明</th><th>作用域参数</th></tr>
581
- </thead>
582
- <tbody>
583
- <tr v-for="row in apiSlots" :key="row[0]">
584
- <td><code>{{ row[0] }}</code></td>
585
- <td>{{ row[1] }}</td>
586
- <td><span class="doc__type">{{ row[2] }}</span></td>
587
- </tr>
588
- </tbody>
589
- </table>
590
- </div>
591
-
592
- <h3 class="demo__sub">Methods(通过 ref 调用)</h3>
593
- <div class="doc__table-wrap">
594
- <table class="doc__table">
595
- <thead>
596
- <tr><th>方法</th><th>说明</th></tr>
597
- </thead>
598
- <tbody>
599
- <tr v-for="row in apiMethods" :key="row[0]">
600
- <td><code>{{ row[0] }}</code></td>
601
- <td>{{ row[1] }}</td>
602
- </tr>
603
- </tbody>
604
- </table>
605
- </div>
606
- </section>
607
- </main>
608
- </div>
609
- </div>
610
- </template>
611
-
612
- <script>
613
- /**
614
- * EventCalendar 示例集合
615
- * ------------------------------------------------------------------
616
- * 按 UI 组件库文档的形式,把组件的每一项能力都单独做成一个可交互示例。
617
- * 本文件同样不依赖第三方 UI 库,跟随组件文件夹一起拷走即可运行。
618
- */
619
- import EventCalendar from './index.vue'
620
- import CodeBlock from './CodeBlock.vue'
621
- import {
622
- SIMPLE_DATA,
623
- ALT_FIELD_NAMES,
624
- fetchCalendarData,
625
- fetchCalendarDataV2,
626
- fetchCrossYearData,
627
- NODEQ_MOCK_RESPONSE
628
- } from './mockData'
629
- import { transformNodeqCalendarResponse } from './recruitmentAdapter'
630
-
631
- export default {
632
- name: 'EventCalendarExample',
633
-
634
- components: { EventCalendar, CodeBlock },
635
-
636
- data() {
637
- return {
638
- heroTags: ['零依赖', '自动补月', '轮播动效', '字段可配', '布局配置', 'NodeQ 适配', '插槽定制', '骨架屏'],
639
-
640
- sections: [
641
- { id: 'basic', title: '1. 基础用法' },
642
- { id: 'async', title: '2. 异步与骨架屏' },
643
- { id: 'months', title: '3. 多月份切换' },
644
- { id: 'autoplay', title: '4. 自动轮播' },
645
- { id: 'effect', title: '5. 切换动效' },
646
- { id: 'boundary', title: '6. 补全与跨年' },
647
- { id: 'schema', title: '7. 字段映射' },
648
- { id: 'overflow', title: '8. 溢出与行高' },
649
- { id: 'slots', title: '9. 插槽定制' },
650
- { id: 'events', title: '10. 事件' },
651
- { id: 'theme', title: '11. 主题定制' },
652
- { id: 'empty', title: '12. 空状态' },
653
- { id: 'nodeq', title: '13. NodeQ 后端适配' },
654
- { id: 'layout-config', title: '14. 布局配置与导出' },
655
- { id: 'api', title: 'API' }
656
- ],
657
- activeSection: 'basic',
658
-
659
- /* -------- 1. 基础 -------- */
660
- basicData: SIMPLE_DATA,
661
-
662
- /* -------- 2. 异步 -------- */
663
- asyncData: [],
664
- asyncLoading: true,
665
-
666
- /* -------- 3/4/5/9. 多月份(共用一份数据) -------- */
667
- multiData: [],
668
- multiLoading: true,
669
- monthsActive: '',
670
-
671
- /* -------- 4. 轮播 -------- */
672
- autoplayInterval: 10000,
673
- autoplayLoop: true,
674
- intervalOptions: [
675
- { label: '5 秒', value: 5000 },
676
- { label: '10 秒', value: 10000 },
677
- { label: '30 秒', value: 30000 },
678
- { label: '1 分钟', value: 60000 }
679
- ],
680
-
681
- /* -------- 5. 动效 -------- */
682
- effect: 'slide',
683
- duration: 420,
684
- stagger: true,
685
- effectOptions: [
686
- { label: '滑动 slide', value: 'slide' },
687
- { label: '淡入 fade', value: 'fade' },
688
- { label: '缩放 zoom', value: 'zoom' },
689
- { label: '翻页 flip', value: 'flip' },
690
- { label: '关闭 none', value: 'none' }
691
- ],
692
-
693
- /* -------- 6. 跨年 -------- */
694
- crossYearData: [],
695
- crossYearLoading: true,
696
- crossYearMonth: '2026-01',
697
- showAdjacentItems: true,
698
- mondayFirst: false,
699
-
700
- /* -------- 7. 字段映射 -------- */
701
- schemaData: [],
702
- schemaLoading: true,
703
- altFieldNames: ALT_FIELD_NAMES,
704
-
705
- /* -------- 8. 溢出 -------- */
706
- overflowData: [],
707
- overflowLoading: true,
708
- maxVisibleItems: 4,
709
- overflowMode: 'scroll',
710
- overflowOptions: [
711
- { label: '滚动 scroll', value: 'scroll' },
712
- { label: '折叠 collapse', value: 'collapse' }
713
- ],
714
-
715
- /* -------- 10. 事件 -------- */
716
- logs: [],
717
-
718
- /* -------- 13. NodeQ 后端形状 -------- */
719
- nodeqData: transformNodeqCalendarResponse(NODEQ_MOCK_RESPONSE),
720
- nodeqAlignment: 'left',
721
- nodeqNoHorizontalPadding: false,
722
- nodeqActiveMonth: '2026-09',
723
- nodeqAlignmentOptions: [
724
- { label: '靠左', value: 'left' },
725
- { label: '居中', value: 'center' }
726
- ],
727
-
728
- /* -------- 14. 原生布局配置 -------- */
729
- layoutToolbarVisible: true,
730
- layoutActiveMonth: '2026-09',
731
- savedLayoutConfig: {
732
- itemAlign: 'left',
733
- calendarMargin: 0,
734
- calendarPadding: 0,
735
- headerPadding: '4px 4px 16px',
736
- cellPadding: '12px 10px',
737
- mobileCellPadding: '8px 6px',
738
- itemHorizontalPadding: 8,
739
- itemVerticalPadding: 4,
740
- itemGap: 6,
741
- itemLineGap: 2,
742
- itemBgGradient: false,
743
- itemBgGradientDir: 'to-bottom',
744
- itemBgHover: true,
745
- itemTextColor: '',
746
- itemBgColor: ''
747
- },
748
-
749
- /* -------- 11. 主题 -------- */
750
- themeName: 'default',
751
- colorful: true,
752
- themePresets: [
753
- { name: 'default', label: '默认蓝', vars: {} },
754
- {
755
- name: 'green',
756
- label: '清新绿',
757
- vars: {
758
- primary: '#10a37f',
759
- primaryGhost: 'rgba(16, 163, 127, 0.12)',
760
- itemBg: '#f2f9f6',
761
- cellHover: '#f7fcfa',
762
- radius: '10px'
763
- }
764
- },
765
- {
766
- name: 'violet',
767
- label: '典雅紫',
768
- vars: {
769
- primary: '#7c3aed',
770
- primaryGhost: 'rgba(124, 58, 237, 0.12)',
771
- itemBg: '#f6f4fd',
772
- cellHover: '#faf9fe',
773
- radius: '12px'
774
- }
775
- },
776
- {
777
- name: 'plain',
778
- label: '素净灰',
779
- vars: {
780
- primary: '#4b5563',
781
- primaryGhost: 'rgba(75, 85, 99, 0.1)',
782
- itemBg: '#f4f4f5',
783
- cellHover: '#fafafa',
784
- radius: '4px'
785
- }
786
- }
787
- ],
788
- typeColors: {
789
- talk: { color: '#3d6cf0', bg: 'rgba(61, 108, 240, 0.10)' },
790
- fair: { color: '#e0821b', bg: 'rgba(224, 130, 27, 0.12)' },
791
- live: { color: '#10a37f', bg: 'rgba(16, 163, 127, 0.12)' },
792
- exam: { color: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.12)' }
793
- },
794
-
795
- /* -------- 代码片段(纯字符串,不参与模板编译) -------- */
796
- code: {
797
- basic: `<EventCalendar
798
- :data="data"
799
- title="宣讲日历"
800
- subtitle="更多场次陆续上线中,宣讲进程以实际安排为准"
801
- active-month="2026-09"
802
- />
803
-
804
- // data 结构
805
- [{
806
- month: '2026-09',
807
- monthLabel: '2026年9月',
808
- days: [{
809
- date: '2026-09-09',
810
- items: [
811
- { id: 'a1', label: '香港中文大学(深圳)', badge: '宣讲', type: 'talk' }
812
- ]
813
- }]
814
- }]`,
815
-
816
- async: `<EventCalendar :data="data" :loading="loading" :skeleton-rows="5" />
817
-
818
- import { fetchCalendarData } from '@/components/EventCalendar/mockData'
819
-
820
- async created() {
821
- this.loading = true
822
- try {
823
- this.data = await fetchCalendarData({ delay: 1500 })
824
- } finally {
825
- this.loading = false // 放 finally,接口失败也要收掉骨架屏
826
- }
827
- }`,
828
-
829
- months: `<!-- v-model 与 :active-month.sync 等价,二选一 -->
830
- <EventCalendar
831
- v-model="activeMonth"
832
- :data="data"
833
- show-arrows
834
- @month-change="onMonthChange"
835
- />
836
-
837
- onMonthChange(month, info) {
838
- // info = { index, source, option, raw }
839
- // source: 'select' | 'arrow' | 'autoplay' | 'prop' | 'api'
840
- console.log(month, info.source)
841
- }`,
842
-
843
- autoplay: `<EventCalendar
844
- :data="data"
845
- autoplay
846
- :autoplay-interval="10000"
847
- :loop="true"
848
- pause-on-hover
849
- :show-progress="true"
850
- :show-autoplay-toggle="true"
851
- />`,
852
-
853
- effect: `<EventCalendar
854
- :data="data"
855
- transition-effect="slide"
856
- :transition-duration="420"
857
- :cell-stagger="true"
858
- />
859
-
860
- <!-- 完全关闭动效 -->
861
- <EventCalendar :data="data" transition-effect="none" :cell-stagger="false" />`,
862
-
863
- boundary: `<!-- 补位日期自动置灰;跨年由原生 Date 进位保证正确 -->
864
- <EventCalendar
865
- :data="data"
866
- :active-month.sync="month"
867
- :show-adjacent-items="true"
868
- :first-day-of-week="0"
869
- />`,
870
-
871
- schemaData: `[{
872
- ym: '2026-09',
873
- ymText: '9 月场次',
874
- dateList: [{
875
- dayStr: '2026-09-09',
876
- activityList: [{
877
- activityId: 1,
878
- schoolName: '南方科技大学',
879
- rawAddress: '深圳市南山区校区报告厅',
880
- activityTypeName: '宣讲',
881
- activityType: 'talk',
882
- expired: false
883
- }]
884
- }]
885
- }]`,
886
-
887
- schemaMap: `const fieldNames = {
888
- month: 'ym',
889
- monthLabel: 'ymText',
890
- days: 'dateList',
891
- date: 'dayStr',
892
- items: 'activityList',
893
- itemKey: 'activityId',
894
- itemLabel: 'schoolName',
895
- itemAddress: 'rawAddress',
896
- itemBadge: 'activityTypeName',
897
- itemType: 'activityType',
898
- itemDisabled: 'expired'
899
- }
900
-
901
- <EventCalendar :data="data" :field-names="fieldNames" />`,
902
-
903
- overflow: `<!-- 行高自动取该行条目最多的那一天,超出按 overflow-mode 处理 -->
904
- <EventCalendar
905
- :data="data"
906
- :max-visible-items="4"
907
- overflow-mode="scroll"
908
- :item-height="28"
909
- :item-gap="6"
910
- :min-row-height="120"
911
- @more-click="onMoreClick"
912
- />`,
913
-
914
- slots: `<EventCalendar :data="data" :item-height="44" :max-visible-items="3">
915
- <!-- 左上角:设计稿里的标题区,可放任意内容 -->
916
- <template #header-left="{ monthLabel, monthIndex, monthCount }">
917
- <div class="custom-head">…</div>
918
- </template>
919
-
920
- <!-- 单条条目:不传则用默认「学校名 + 右上角角标」 -->
921
- <template #item="{ item, label, badge, type, day, index }">
922
- <div class="custom-item">…</div>
923
- </template>
924
-
925
- <!-- 当天没有数据时 -->
926
- <template #day-empty="{ isCurrentMonth }">
927
- <div v-if="isCurrentMonth">暂无安排</div>
928
- </template>
929
- </EventCalendar>`,
930
-
931
- events: `<EventCalendar
932
- :data="data"
933
- @day-click="onDayClick"
934
- @item-click="onItemClick"
935
- @tag-click="onTagClick"
936
- />
937
-
938
- onDayClick(scope, event) {
939
- // scope = { day, date, dateKey, items, raw, isCurrentMonth, isToday, ... }
940
- }
941
- onItemClick(scope, event) {
942
- // scope = { item, label, address, badge, type, index, day, dateKey }
943
- // item 是后端返回的原始对象,字段齐全
944
- }
945
- onTagClick(scope, event) {
946
- // 点角标;未监听时会自动退化成 item-click
947
- }`,
948
-
949
- nodeq: `import EventCalendar from '@/components/EventCalendar/index.vue'
950
- import { fetchNodeqCalendarData } from '@/components/EventCalendar/mockData'
951
- import { transformNodeqCalendarResponse } from '@/components/EventCalendar/recruitmentAdapter'
952
-
953
- // 后端原始响应:response.data.nbcbRecAnnJourneyMaps
954
- const response = await fetchNodeqCalendarData()
955
- const data = transformNodeqCalendarResponse(response)
956
-
957
- <EventCalendar
958
- :data="data"
959
- item-align="center"
960
- :item-horizontal-padding="0"
961
- :item-height="40"
962
- />
963
- // address 为空时,组件不会渲染地址行。`,
964
-
965
- layoutConfig: `<!-- 默认不显示工具栏;建议只在开发环境开启 -->
966
- <EventCalendar
967
- :data="data"
968
- v-bind="layoutConfig"
969
- :show-config-toolbar="isDevelopment"
970
- />
971
- <!-- 工具栏里改完点「复制配置」,把 JSON 粘回来赋给 layoutConfig 即可 -->
972
-
973
- export default {
974
- data() {
975
- return {
976
- isDevelopment: process.env.NODE_ENV !== 'production',
977
- // 结构同工具栏「复制配置」得到的 JSON,可直接 v-bind 应用
978
- layoutConfig: {
979
- itemAlign: 'center',
980
- calendarMargin: 0,
981
- calendarPadding: 0,
982
- headerPadding: '4px 4px 16px',
983
- cellPadding: '12px 10px',
984
- mobileCellPadding: '8px 6px',
985
- itemHorizontalPadding: 0,
986
- itemVerticalPadding: 4,
987
- itemGap: 6,
988
- itemLineGap: 2,
989
- itemBgGradient: false,
990
- itemBgGradientDir: 'to-bottom',
991
- itemBgHover: true,
992
- overflowMode: 'scroll',
993
- maxVisibleItems: 4,
994
- itemHeight: 28,
995
- minRowHeight: 118,
996
- badgeScale: 0.75,
997
- // 条目色留空表示沿用 type/主题配色
998
- itemTextColor: '',
999
- itemBgColor: ''
1000
- }
1001
- }
1002
- }
1003
- }`,
1004
-
1005
- theme: `<EventCalendar
1006
- :data="data"
1007
- :theme="{
1008
- primary: '#10a37f',
1009
- primaryGhost: 'rgba(16,163,127,.12)',
1010
- itemBg: '#f2f9f6',
1011
- radius: '10px'
1012
- }"
1013
- :type-colors="{ talk: { color: '#3d6cf0', bg: 'rgba(61,108,240,.1)' } }"
1014
- :colorful="true"
1015
- />`
1016
- },
1017
-
1018
- /* -------- API 表格 -------- */
1019
- apiProps: [
1020
- ['data', '日历数据,支持「按月分组」和「扁平日期数组」两种结构', 'Array', '[]'],
1021
- ['field-names', '字段映射,覆盖默认字段名,支持 a.b.c 点路径', 'Object', '{}'],
1022
- ['loading', '加载中,为 true 时渲染骨架屏', 'Boolean', 'false'],
1023
- ['skeleton-rows', '骨架屏行数', 'Number', '5'],
1024
- ['active-month', '当前月份,支持 v-model / .sync', 'String', "''"],
1025
- ['show-month-select', '是否显示月份下拉框', 'Boolean', 'true'],
1026
- ['show-arrows', '是否显示左右翻月箭头', 'Boolean', 'false'],
1027
- ['autoplay', '是否开启自动轮播', 'Boolean', 'false'],
1028
- ['autoplay-interval', '轮播间隔(毫秒)', 'Number', '60000'],
1029
- ['loop', '轮播到最后一个月后是否回到第一个', 'Boolean', 'true'],
1030
- ['pause-on-hover', '鼠标悬停时暂停轮播', 'Boolean', 'true'],
1031
- ['show-progress', '显示轮播倒计时进度条', 'Boolean', 'true'],
1032
- ['show-autoplay-toggle', '显示播放/暂停按钮', 'Boolean', 'true'],
1033
- ['transition-effect', '切换动效:slide / fade / zoom / flip / none', 'String', "'slide'"],
1034
- ['transition-duration', '动效时长(毫秒)', 'Number', '420'],
1035
- ['cell-stagger', '单元格错峰入场动画', 'Boolean', 'false'],
1036
- ['show-header', '是否显示顶部区域', 'Boolean', 'true'],
1037
- ['title / subtitle', '默认标题与副标题(header-left 未传时生效)', 'String', "''"],
1038
- ['first-day-of-week', '一周起始日,0=周日 1=周一', 'Number', '0'],
1039
- ['week-labels', '星期文案,下标对应 Date.getDay()', 'Array', "['周日'…'周六']"],
1040
- ['max-visible-items', '单日最多显示条目数', 'Number', '4'],
1041
- ['overflow-mode', '溢出处理:scroll / collapse', 'String', "'scroll'"],
1042
- ['item-height', '单条条目高度(px)', 'Number', '28'],
1043
- ['item-gap', '条目间距(px)', 'Number', '6'],
1044
- ['item-align', '条目内容对齐方式:left / center', 'String', "'left'"],
1045
- ['calendar-margin', '日历根节点外边距,Number 按 px 处理,String 支持 CSS 简写', 'Number / String', '0'],
1046
- ['calendar-padding', '日历根节点内边距,Number 按 px 处理,String 支持 CSS 简写', 'Number / String', '0'],
1047
- ['header-padding', '顶部区域内边距,支持 CSS 简写', 'Number / String', "'4px 4px 16px'"],
1048
- ['cell-padding', '日期格内边距,支持 CSS 简写', 'Number / String', "'12px 10px'"],
1049
- ['mobile-cell-padding', '768px 及以下的日期格内边距', 'Number / String', "'8px 6px'"],
1050
- ['item-horizontal-padding', '条目左右内边距(px),传 0 可去除', 'Number', '8'],
1051
- ['item-vertical-padding', '条目上下内边距(px)', 'Number', '4'],
1052
- ['item-line-gap', '条目内名称与地址的行间距(px)', 'Number', '2'],
1053
- ['item-bg-gradient', '条目背景是否启用渐变(在底色上叠柔和渐变)', 'Boolean', 'false'],
1054
- ['item-bg-gradient-dir', '渐变方向:to-bottom 上到下 | to-right 左到右', 'String', "'to-bottom'"],
1055
- ['item-bg-hover', '悬浮时是否自动把条目背景调淡一档', 'Boolean', 'true'],
1056
- ['badge-scale', '右上角角标整体缩放倍率(越小越紧凑)', 'Number', '0.75'],
1057
- ['show-config-toolbar', '显示原生布局配置工具栏,生产环境默认隐藏', 'Boolean', 'false'],
1058
- ['item-bg-color', '条目(.ec__item)背景色覆盖,空串按 type/主题配色(工具栏可取色)', 'String', "''"],
1059
- ['item-text-color', '条目(.ec__item)文字色覆盖,空串按 type/主题配色(工具栏可取色)', 'String', "''"],
1060
- ['min-row-height', '单元格最小高度(px)', 'Number', '118'],
1061
- ['show-adjacent-items', '补位日期是否也渲染条目', 'Boolean', 'true'],
1062
- ['highlight-today', '高亮今天', 'Boolean', 'true'],
1063
- ['colorful', '角标是否按 type 上色', 'Boolean', 'true'],
1064
- ['type-colors', '类型配色 { type: { color, bg } }', 'Object', '内置 4 种'],
1065
- ['day-formatter', '日期文案格式化 (cell) => string', 'Function', "'9月7日'"],
1066
- ['month-formatter', '月份下拉文案格式化 (monthKey, raw) => string', 'Function', 'null'],
1067
- ['empty-text', '空数据文案', 'String', "'暂无日程数据'"],
1068
- ['cell-focusable', '单元格可聚焦(键盘无障碍)', 'Boolean', 'false'],
1069
- ['theme', '主题变量覆盖,如 { primary, radius, itemBg }', 'Object', '{}']
1070
- ],
1071
- apiEvents: [
1072
- ['day-click', '点击日期格子', '(scope, event)'],
1073
- ['item-click', '点击条目', '(scope, event)'],
1074
- ['tag-click', '点击条目右上角角标;未监听时退化为 item-click', '(scope, event)'],
1075
- ['more-click', 'collapse 模式下点击「还有 N 项」', '(scope, event)'],
1076
- ['month-change', '月份变化', '(month, { index, source, option, raw })'],
1077
- ['update:activeMonth', '配合 v-model / .sync', '(month)'],
1078
- ['autoplay-toggle', '点击播放/暂停按钮', '(playing: Boolean)'],
1079
- ['autoplay-end', 'loop=false 时播到最后一个月', '—'],
1080
- ['transition-end', '月份切换动画结束', '(month)'],
1081
- ['config-change', '工具栏配置变化', '(config)']
1082
- ],
1083
- apiSlots: [
1084
- ['header-left', '顶部左侧(设计稿的标题区)', '{ month, monthLabel, monthIndex, monthCount, prev, next, goTo }'],
1085
- ['header-right', '顶部右侧,整体替换默认的按钮 + 下拉', '同上'],
1086
- ['weekday', '星期表头单元', '{ label, weekday, isWeekend, index }'],
1087
- ['day', '整个日期格子(覆盖所有默认内容)', '{ day, dateKey, items, raw, isCurrentMonth, isToday, label }'],
1088
- ['day-header', '格子里的日期行', '同 day'],
1089
- ['items', '格子里的条目列表区域', '同 day'],
1090
- ['item', '单个条目', '{ item, label, badge, type, disabled, index, day, dateKey }'],
1091
- ['day-empty', '当天无数据时的占位', '同 day'],
1092
- ['loading', '自定义骨架屏', '{ rows }'],
1093
- ['empty', '整体空状态', '—']
1094
- ],
1095
- apiMethods: [
1096
- ['prev()', '切到上一个月'],
1097
- ['next()', '切到下一个月'],
1098
- ['goTo(index)', '切到第 index 个月(从 0 开始)'],
1099
- ['setMonth(month)', '切到指定月份,如 setMonth("2026-10")'],
1100
- ['restartAutoplay()', '重置轮播计时'],
1101
- ['getLayoutConfig()', '获取可直接通过 v-bind 应用的当前布局配置']
1102
- ]
1103
- }
1104
- },
1105
-
1106
- computed: {
1107
- currentTheme() {
1108
- const hit = this.themePresets.find((t) => t.name === this.themeName)
1109
- return hit ? hit.vars : {}
1110
- },
1111
-
1112
- /** 插槽示例里用到的当月场次总数 */
1113
- monthItemCount() {
1114
- const month = this.multiData[0]
1115
- if (!month) return 0
1116
- return (month.days || []).reduce((sum, d) => sum + (d.items || []).length, 0)
1117
- }
1118
- },
1119
-
1120
- created() {
1121
- this.loadAsync()
1122
- this.loadMulti()
1123
- this.loadCrossYear()
1124
- this.loadSchema()
1125
- this.loadOverflow()
1126
- },
1127
-
1128
- mounted() {
1129
- window.addEventListener('scroll', this.handleScroll, true)
1130
- },
1131
-
1132
- beforeDestroy() {
1133
- window.removeEventListener('scroll', this.handleScroll, true)
1134
- },
1135
-
1136
- methods: {
1137
- /* ------------------------- 数据加载 ------------------------- */
1138
- async loadAsync() {
1139
- this.asyncLoading = true
1140
- try {
1141
- this.asyncData = await fetchCalendarData({ months: ['2026-09'], delay: 1500 })
1142
- } finally {
1143
- // 放 finally:接口失败也要收掉骨架屏,否则页面会一直卡在加载态
1144
- this.asyncLoading = false
1145
- }
1146
- },
1147
-
1148
- async loadMulti() {
1149
- this.multiLoading = true
1150
- try {
1151
- this.multiData = await fetchCalendarData({
1152
- months: ['2026-09', '2026-10', '2026-11'],
1153
- delay: 1200
1154
- })
1155
- } finally {
1156
- this.multiLoading = false
1157
- }
1158
- },
1159
-
1160
- async loadCrossYear() {
1161
- this.crossYearLoading = true
1162
- try {
1163
- this.crossYearData = await fetchCrossYearData({ delay: 1000 })
1164
- } finally {
1165
- this.crossYearLoading = false
1166
- }
1167
- },
1168
-
1169
- async loadSchema() {
1170
- this.schemaLoading = true
1171
- try {
1172
- this.schemaData = await fetchCalendarDataV2({ months: ['2026-09', '2026-10'], delay: 1400 })
1173
- } finally {
1174
- this.schemaLoading = false
1175
- }
1176
- },
1177
-
1178
- async loadOverflow() {
1179
- this.overflowLoading = true
1180
- try {
1181
- // density=1 + maxItems=6:让几乎每天都有数据,且部分日期超过 4 条
1182
- this.overflowData = await fetchCalendarData({
1183
- months: ['2026-09'],
1184
- delay: 800,
1185
- maxItems: 6,
1186
- density: 0.95
1187
- })
1188
- } finally {
1189
- this.overflowLoading = false
1190
- }
1191
- },
1192
-
1193
- /* ------------------------- 事件回调 ------------------------- */
1194
- onMonthChange(month, info) {
1195
- this.pushLog('month', `切到 ${month}(来源:${info.source})`)
1196
- },
1197
-
1198
- onDayClick(scope) {
1199
- this.pushLog('day', `${scope.dateKey} · ${scope.items.length} 场`)
1200
- },
1201
-
1202
- onItemClick(scope) {
1203
- this.pushLog('item', `${scope.dateKey} · ${scope.label}`)
1204
- },
1205
-
1206
- onTagClick(scope) {
1207
- this.pushLog('tag', `${scope.label} 的角标「${scope.badge}」`)
1208
- },
1209
-
1210
- onMoreClick(scope) {
1211
- this.pushLog('more', `${scope.dateKey} 共 ${scope.items.length} 场`)
1212
- },
1213
-
1214
- pushLog(type, text) {
1215
- this.logs.unshift({ type, text })
1216
- if (this.logs.length > 12) this.logs.pop()
1217
- },
1218
-
1219
- /* ------------------------- 目录导航 ------------------------- */
1220
- scrollTo(id) {
1221
- const el = document.getElementById(id)
1222
- if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' })
1223
- this.activeSection = id
1224
- },
1225
-
1226
- /** 滚动时同步高亮左侧目录 */
1227
- handleScroll() {
1228
- const offset = 120
1229
- let current = this.sections[0].id
1230
- for (const s of this.sections) {
1231
- const el = document.getElementById(s.id)
1232
- if (el && el.getBoundingClientRect().top <= offset) current = s.id
1233
- }
1234
- this.activeSection = current
1235
- }
1236
- }
1237
- }
1238
- </script>
1239
-
1240
- <style scoped>
1241
- /* ============================ 文档页外壳 ============================ */
1242
- .doc {
1243
- padding: 24px;
1244
- background: #fafbfc;
1245
- color: #303133;
1246
- font-size: 14px;
1247
- line-height: 1.6;
1248
- }
1249
-
1250
- .doc code {
1251
- padding: 1px 5px;
1252
- border-radius: 4px;
1253
- background: #eef0f4;
1254
- color: #476582;
1255
- font-family: Consolas, Monaco, 'Courier New', monospace;
1256
- font-size: 0.92em;
1257
- }
1258
-
1259
- /* ------------------------------ 页头 ------------------------------ */
1260
- .doc__hero {
1261
- padding: 28px 32px;
1262
- margin-bottom: 24px;
1263
- border-radius: 14px;
1264
- background: linear-gradient(120deg, #eef3ff 0%, #f7f9ff 45%, #fdf6ff 100%);
1265
- border: 1px solid #e8ecf6;
1266
- }
1267
-
1268
- .doc__hero-title {
1269
- margin: 0 0 10px;
1270
- font-size: 26px;
1271
- font-weight: 700;
1272
- }
1273
-
1274
- .doc__hero-desc {
1275
- max-width: 860px;
1276
- margin: 0 0 16px;
1277
- color: #5c6478;
1278
- }
1279
-
1280
- .doc__hero-tags {
1281
- display: flex;
1282
- flex-wrap: wrap;
1283
- gap: 8px;
1284
- }
1285
-
1286
- .doc__chip {
1287
- padding: 3px 12px;
1288
- border-radius: 999px;
1289
- background: rgba(61, 108, 240, 0.1);
1290
- color: #3d6cf0;
1291
- font-size: 12px;
1292
- font-weight: 500;
1293
- }
1294
-
1295
- /* ------------------------------ 主体布局 ------------------------------ */
1296
- .doc__body {
1297
- display: flex;
1298
- align-items: flex-start;
1299
- gap: 24px;
1300
- }
1301
-
1302
- .doc__toc {
1303
- position: sticky;
1304
- top: 16px;
1305
- flex: none;
1306
- width: 172px;
1307
- padding: 14px;
1308
- border-radius: 12px;
1309
- background: #fff;
1310
- border: 1px solid #ebeef5;
1311
- }
1312
-
1313
- .doc__toc-title {
1314
- margin: 0 0 8px;
1315
- padding-left: 10px;
1316
- color: #909399;
1317
- font-size: 12px;
1318
- }
1319
-
1320
- .doc__toc-link {
1321
- display: block;
1322
- padding: 6px 10px;
1323
- border-radius: 6px;
1324
- color: #606266;
1325
- font-size: 13px;
1326
- text-decoration: none;
1327
- transition: background-color 0.16s, color 0.16s;
1328
- }
1329
-
1330
- .doc__toc-link:hover {
1331
- background: #f5f7fa;
1332
- color: #3d6cf0;
1333
- }
1334
-
1335
- .doc__toc-link.is-active {
1336
- background: rgba(61, 108, 240, 0.1);
1337
- color: #3d6cf0;
1338
- font-weight: 600;
1339
- }
1340
-
1341
- .doc__main {
1342
- flex: 1;
1343
- min-width: 0;
1344
- }
1345
-
1346
- /* ------------------------------ 示例卡片 ------------------------------ */
1347
- .demo {
1348
- padding: 24px;
1349
- margin-bottom: 24px;
1350
- border-radius: 12px;
1351
- background: #fff;
1352
- border: 1px solid #ebeef5;
1353
- scroll-margin-top: 16px;
1354
- }
1355
-
1356
- .demo__title {
1357
- margin: 0 0 8px;
1358
- font-size: 18px;
1359
- font-weight: 600;
1360
- }
1361
-
1362
- .demo__sub {
1363
- margin: 22px 0 10px;
1364
- font-size: 15px;
1365
- font-weight: 600;
1366
- color: #303133;
1367
- }
1368
-
1369
- .demo__desc {
1370
- margin: 0 0 16px;
1371
- color: #5c6478;
1372
- }
1373
-
1374
- .demo__stage {
1375
- padding: 16px;
1376
- border-radius: 10px;
1377
- border: 1px solid #ebeef5;
1378
- background: #fff;
1379
- }
1380
-
1381
- .demo__stage--flex {
1382
- flex: 1;
1383
- min-width: 0;
1384
- }
1385
-
1386
- .demo__toolbar {
1387
- display: flex;
1388
- align-items: center;
1389
- flex-wrap: wrap;
1390
- gap: 10px;
1391
- margin-bottom: 14px;
1392
- }
1393
-
1394
- .demo__cols {
1395
- display: flex;
1396
- gap: 16px;
1397
- flex-wrap: wrap;
1398
- }
1399
-
1400
- .demo__cols--events {
1401
- align-items: stretch;
1402
- flex-wrap: nowrap;
1403
- }
1404
-
1405
- .demo__col {
1406
- flex: 1;
1407
- min-width: 280px;
1408
- }
1409
-
1410
- .demo__col-title {
1411
- margin: 0 0 8px;
1412
- color: #909399;
1413
- font-size: 13px;
1414
- }
1415
-
1416
- /* ------------------------------ 控件 ------------------------------ */
1417
- .doc__btn {
1418
- height: 32px;
1419
- padding: 0 14px;
1420
- border: 1px solid #3d6cf0;
1421
- border-radius: 8px;
1422
- background: #3d6cf0;
1423
- color: #fff;
1424
- font-size: 13px;
1425
- cursor: pointer;
1426
- transition: opacity 0.18s, background-color 0.18s;
1427
- }
1428
-
1429
- .doc__btn:hover:not(:disabled) {
1430
- opacity: 0.88;
1431
- }
1432
-
1433
- .doc__btn:disabled {
1434
- cursor: not-allowed;
1435
- opacity: 0.55;
1436
- }
1437
-
1438
- .doc__btn--ghost {
1439
- background: #fff;
1440
- color: #3d6cf0;
1441
- }
1442
-
1443
- .doc__btn--ghost:hover {
1444
- background: rgba(61, 108, 240, 0.08);
1445
- }
1446
-
1447
- .doc__btn--sm {
1448
- height: 24px;
1449
- padding: 0 10px;
1450
- font-size: 12px;
1451
- }
1452
-
1453
- .doc__seg {
1454
- height: 30px;
1455
- padding: 0 12px;
1456
- border: 1px solid #dcdfe6;
1457
- border-radius: 8px;
1458
- background: #fff;
1459
- color: #606266;
1460
- font-size: 13px;
1461
- cursor: pointer;
1462
- transition: all 0.18s;
1463
- }
1464
-
1465
- .doc__seg:hover {
1466
- border-color: #3d6cf0;
1467
- color: #3d6cf0;
1468
- }
1469
-
1470
- .doc__seg.is-active {
1471
- border-color: #3d6cf0;
1472
- background: #3d6cf0;
1473
- color: #fff;
1474
- }
1475
-
1476
- .doc__check {
1477
- display: inline-flex;
1478
- align-items: center;
1479
- gap: 6px;
1480
- color: #606266;
1481
- font-size: 13px;
1482
- cursor: pointer;
1483
- user-select: none;
1484
- }
1485
-
1486
- .doc__check input {
1487
- cursor: pointer;
1488
- }
1489
-
1490
- .doc__range {
1491
- width: 130px;
1492
- cursor: pointer;
1493
- }
1494
-
1495
- .doc__hint {
1496
- color: #909399;
1497
- font-size: 13px;
1498
- }
1499
-
1500
- .doc__code-inline {
1501
- color: #3d6cf0 !important;
1502
- }
1503
-
1504
-
1505
- /* ------------------------------ 事件日志 ------------------------------ */
1506
- .event-log {
1507
- flex: none;
1508
- width: 280px;
1509
- display: flex;
1510
- flex-direction: column;
1511
- border: 1px solid #ebeef5;
1512
- border-radius: 10px;
1513
- background: #fbfcfe;
1514
- overflow: hidden;
1515
- }
1516
-
1517
- .event-log__head {
1518
- display: flex;
1519
- align-items: center;
1520
- justify-content: space-between;
1521
- padding: 10px 12px;
1522
- border-bottom: 1px solid #ebeef5;
1523
- font-size: 13px;
1524
- font-weight: 600;
1525
- color: #303133;
1526
- }
1527
-
1528
- .event-log__list {
1529
- flex: 1;
1530
- margin: 0;
1531
- padding: 8px;
1532
- list-style: none;
1533
- overflow-y: auto;
1534
- max-height: 420px;
1535
- }
1536
-
1537
- .event-log__item {
1538
- display: flex;
1539
- align-items: flex-start;
1540
- gap: 8px;
1541
- padding: 6px 4px;
1542
- border-bottom: 1px dashed #eef0f4;
1543
- font-size: 12px;
1544
- }
1545
-
1546
- .event-log__item:last-child {
1547
- border-bottom: none;
1548
- }
1549
-
1550
- .event-log__type {
1551
- flex: none;
1552
- padding: 1px 6px;
1553
- border-radius: 4px;
1554
- font-size: 11px;
1555
- background: #eef0f4;
1556
- color: #606266;
1557
- }
1558
-
1559
- .event-log__type.is-day { background: rgba(61, 108, 240, 0.12); color: #3d6cf0; }
1560
- .event-log__type.is-item { background: rgba(16, 163, 127, 0.12); color: #10a37f; }
1561
- .event-log__type.is-tag { background: rgba(224, 130, 27, 0.14); color: #e0821b; }
1562
- .event-log__type.is-month { background: rgba(139, 92, 246, 0.12); color: #8b5cf6; }
1563
- .event-log__type.is-more { background: rgba(107, 114, 128, 0.14); color: #6b7280; }
1564
-
1565
- .event-log__text {
1566
- color: #5c6478;
1567
- word-break: break-all;
1568
- }
1569
-
1570
- .event-log__empty {
1571
- margin: 0;
1572
- padding: 40px 16px;
1573
- color: #c0c4cc;
1574
- font-size: 13px;
1575
- text-align: center;
1576
- }
1577
-
1578
- /* ------------------------------ API 表格 ------------------------------ */
1579
- .doc__table-wrap {
1580
- overflow-x: auto;
1581
- border: 1px solid #ebeef5;
1582
- border-radius: 10px;
1583
- }
1584
-
1585
- .doc__table {
1586
- width: 100%;
1587
- border-collapse: collapse;
1588
- font-size: 13px;
1589
- }
1590
-
1591
- .doc__table th,
1592
- .doc__table td {
1593
- padding: 10px 14px;
1594
- text-align: left;
1595
- border-bottom: 1px solid #f0f2f5;
1596
- vertical-align: top;
1597
- }
1598
-
1599
- .doc__table th {
1600
- background: #fafbfc;
1601
- color: #303133;
1602
- font-weight: 600;
1603
- white-space: nowrap;
1604
- }
1605
-
1606
- .doc__table tbody tr:last-child td {
1607
- border-bottom: none;
1608
- }
1609
-
1610
- .doc__table tbody tr:hover {
1611
- background: #fafbfd;
1612
- }
1613
-
1614
- .doc__type {
1615
- color: #909399;
1616
- font-family: Consolas, Monaco, monospace;
1617
- font-size: 12px;
1618
- }
1619
-
1620
- /* ==================== 插槽示例里的自定义样式 ====================
1621
- * 注意:scoped 样式默认不作用于插槽内容的子组件根节点之外,
1622
- * 但这些 DOM 是在本组件模板里写的,所以带的是本组件的 scopeId,样式生效。
1623
- * ============================================================== */
1624
- .custom-head {
1625
- display: flex;
1626
- align-items: center;
1627
- gap: 12px;
1628
- }
1629
-
1630
- .custom-head__badge {
1631
- padding: 6px 14px;
1632
- border-radius: 10px;
1633
- background: linear-gradient(135deg, #3d6cf0, #6c8ff5);
1634
- color: #fff;
1635
- font-size: 14px;
1636
- font-weight: 600;
1637
- white-space: nowrap;
1638
- }
1639
-
1640
- .custom-head__meta {
1641
- display: flex;
1642
- flex-direction: column;
1643
- line-height: 1.4;
1644
- }
1645
-
1646
- .custom-head__meta strong {
1647
- font-size: 15px;
1648
- }
1649
-
1650
- .custom-head__meta span {
1651
- color: #909399;
1652
- font-size: 12px;
1653
- }
1654
-
1655
- .custom-item {
1656
- width: 100%;
1657
- min-width: 0;
1658
- padding: 2px 0;
1659
- }
1660
-
1661
- .custom-item__row {
1662
- display: flex;
1663
- align-items: center;
1664
- gap: 6px;
1665
- min-width: 0;
1666
- }
1667
-
1668
- .custom-item__row--sub {
1669
- margin-top: 2px;
1670
- }
1671
-
1672
- .custom-item__time {
1673
- flex: none;
1674
- color: #3d6cf0;
1675
- font-size: 11px;
1676
- font-weight: 600;
1677
- }
1678
-
1679
- .custom-item.is-fair .custom-item__time { color: #e0821b; }
1680
- .custom-item.is-live .custom-item__time { color: #10a37f; }
1681
- .custom-item.is-exam .custom-item__time { color: #8b5cf6; }
1682
-
1683
- .custom-item__name {
1684
- flex: 1;
1685
- min-width: 0;
1686
- overflow: hidden;
1687
- white-space: nowrap;
1688
- text-overflow: ellipsis;
1689
- font-size: 12px;
1690
- color: #303133;
1691
- }
1692
-
1693
- .custom-item__addr {
1694
- flex: 1;
1695
- min-width: 0;
1696
- overflow: hidden;
1697
- white-space: nowrap;
1698
- text-overflow: ellipsis;
1699
- color: #a8abb2;
1700
- font-size: 11px;
1701
- }
1702
-
1703
- .custom-item__tag {
1704
- flex: none;
1705
- padding: 0 5px;
1706
- border-radius: 3px;
1707
- background: rgba(0, 0, 0, 0.05);
1708
- color: #909399;
1709
- font-size: 10px;
1710
- }
1711
-
1712
- .custom-item__tag:empty {
1713
- display: none;
1714
- }
1715
-
1716
- .custom-empty {
1717
- padding: 6px 0;
1718
- color: #dcdfe6;
1719
- font-size: 12px;
1720
- text-align: center;
1721
- }
1722
-
1723
- /* ------------------------------ 响应式 ------------------------------ */
1724
- @media (max-width: 1100px) {
1725
- .doc__toc {
1726
- display: none;
1727
- }
1728
- .demo__cols--events {
1729
- flex-wrap: wrap;
1730
- }
1731
- .event-log {
1732
- width: 100%;
1733
- }
1734
- }
1735
-
1736
- @media (max-width: 768px) {
1737
- .doc {
1738
- padding: 12px;
1739
- }
1740
- .doc__hero {
1741
- padding: 20px;
1742
- }
1743
- .demo {
1744
- padding: 16px;
1745
- }
1746
- }
1747
- </style>