foucui 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/dist/components/QiuCanvasKit/QiuCanvasEditor.vue.d.ts +3 -1
  2. package/dist/components/QiuCanvasKit/components/DataModulesPanel.vue.d.ts +1 -0
  3. package/dist/components/QiuTable/index.vue.d.ts +12 -12
  4. package/dist/foucui.css +1 -1
  5. package/dist/foucui.js +7476 -7373
  6. package/dist/foucui.umd.cjs +19 -19
  7. package/package.json +23 -13
  8. package/components/QiuAffix/index.vue +0 -186
  9. package/components/QiuAlert/index.vue +0 -208
  10. package/components/QiuAnchor/context.ts +0 -18
  11. package/components/QiuAnchor/index.vue +0 -180
  12. package/components/QiuAnchorLink/index.vue +0 -67
  13. package/components/QiuApp/index.vue +0 -9
  14. package/components/QiuAutocomplete/index.vue +0 -408
  15. package/components/QiuAvatar/index.vue +0 -140
  16. package/components/QiuBacktop/index.vue +0 -121
  17. package/components/QiuBadge/api/index.ts +0 -389
  18. package/components/QiuBadge/components/BadgeImagePickerDialog.vue +0 -243
  19. package/components/QiuBadge/components/BadgeLibraryManagerDialog.vue +0 -30
  20. package/components/QiuBadge/components/BadgeLibraryPanel.vue +0 -182
  21. package/components/QiuBadge/composables/useTableHostHeight.ts +0 -53
  22. package/components/QiuBadge/index.ts +0 -18
  23. package/components/QiuBadge/shared/BadgeTemplateRenderer.vue +0 -32
  24. package/components/QiuBadge/shared/assetUrl.ts +0 -26
  25. package/components/QiuBadge/shared/badgeTemplate.ts +0 -309
  26. package/components/QiuBadge/utils/chinaAreaData.ts +0 -44
  27. package/components/QiuBadge/utils/hostRegion.ts +0 -22
  28. package/components/QiuBadge/utils/pca-code.json +0 -1
  29. package/components/QiuBadge/utils/pdfFromElement.ts +0 -348
  30. package/components/QiuBadge/views/BadgeLibraryView.vue +0 -32
  31. package/components/QiuBadge/views/BadgeManageView.vue +0 -1364
  32. package/components/QiuBadge/views/BadgeTemplateEditorView.vue +0 -10
  33. package/components/QiuBadge/views/BadgeTemplateListView.vue +0 -229
  34. package/components/QiuBadge/views/DeskLabelTemplateListView.vue +0 -227
  35. package/components/QiuBadge/views/DeskLabelView.vue +0 -683
  36. package/components/QiuBadgeDot/index.vue +0 -87
  37. package/components/QiuButton/index.vue +0 -247
  38. package/components/QiuButtonGroup/index.vue +0 -63
  39. package/components/QiuCanvasKit/QiuCanvasEditor.vue +0 -5503
  40. package/components/QiuCanvasKit/QiuCanvasRenderer.vue +0 -348
  41. package/components/QiuCanvasKit/assetUrl.ts +0 -11
  42. package/components/QiuCanvasKit/components/DataModulesPanel.vue +0 -352
  43. package/components/QiuCanvasKit/export/html.ts +0 -132
  44. package/components/QiuCanvasKit/export/pdf.ts +0 -48
  45. package/components/QiuCanvasKit/export/png.ts +0 -50
  46. package/components/QiuCanvasKit/index.ts +0 -20
  47. package/components/QiuCanvasKit/modules/badgeCompat.ts +0 -84
  48. package/components/QiuCanvasKit/modules/dataRegistry.ts +0 -207
  49. package/components/QiuCanvasKit/modules/merge.ts +0 -71
  50. package/components/QiuCanvasKit/presets/badge.ts +0 -67
  51. package/components/QiuCanvasKit/presets/banner.ts +0 -79
  52. package/components/QiuCanvasKit/types.ts +0 -138
  53. package/components/QiuCard/index.vue +0 -104
  54. package/components/QiuCarousel/context.ts +0 -16
  55. package/components/QiuCarousel/index.vue +0 -343
  56. package/components/QiuCarouselItem/index.vue +0 -47
  57. package/components/QiuCascader/index.vue +0 -879
  58. package/components/QiuCascader/types.ts +0 -48
  59. package/components/QiuCheckbox/QiuCheckboxGroup.vue +0 -78
  60. package/components/QiuCheckbox/index.vue +0 -231
  61. package/components/QiuCheckbox/types.ts +0 -8
  62. package/components/QiuCode/index.vue +0 -64
  63. package/components/QiuCol/col.scss +0 -55
  64. package/components/QiuCol/index.vue +0 -64
  65. package/components/QiuCollapse/context.ts +0 -10
  66. package/components/QiuCollapse/index.vue +0 -70
  67. package/components/QiuCollapseItem/index.vue +0 -167
  68. package/components/QiuColorField/index.vue +0 -296
  69. package/components/QiuColorPicker/README.md +0 -118
  70. package/components/QiuColorPicker/index.vue +0 -60
  71. package/components/QiuColorfulCard/index.vue +0 -101
  72. package/components/QiuCombobox/index.vue +0 -277
  73. package/components/QiuConfigProvider/index.vue +0 -31
  74. package/components/QiuContextMenu/index.vue +0 -209
  75. package/components/QiuDate/index.vue +0 -1134
  76. package/components/QiuDescriptions/context.ts +0 -20
  77. package/components/QiuDescriptions/index.vue +0 -115
  78. package/components/QiuDescriptionsItem/index.vue +0 -103
  79. package/components/QiuDialog/index.vue +0 -828
  80. package/components/QiuDigitalCard/index.vue +0 -159
  81. package/components/QiuDivider/index.vue +0 -185
  82. package/components/QiuDot/index.vue +0 -83
  83. package/components/QiuDrawer/index.vue +0 -350
  84. package/components/QiuDropdown/QiuDropdownItem.vue +0 -74
  85. package/components/QiuDropdown/QiuDropdownMenu.vue +0 -22
  86. package/components/QiuDropdown/context.ts +0 -9
  87. package/components/QiuDropdown/index.vue +0 -189
  88. package/components/QiuEmpty/index.vue +0 -73
  89. package/components/QiuForm/index.vue +0 -172
  90. package/components/QiuForm/types.ts +0 -39
  91. package/components/QiuFormItem/index.vue +0 -276
  92. package/components/QiuFullscreen/index.vue +0 -11
  93. package/components/QiuGrid/index.vue +0 -408
  94. package/components/QiuHoverCard/index.vue +0 -192
  95. package/components/QiuIcon/index.vue +0 -117
  96. package/components/QiuIconPicker/iconify.libraries.ts +0 -182
  97. package/components/QiuIconPicker/icons.catalog.ts +0 -3072
  98. package/components/QiuIconPicker/index.vue +0 -488
  99. package/components/QiuImage/index.vue +0 -177
  100. package/components/QiuInput/index.vue +0 -328
  101. package/components/QiuInputNumber/index.vue +0 -295
  102. package/components/QiuInputOtp/index.vue +0 -190
  103. package/components/QiuKbd/index.vue +0 -57
  104. package/components/QiuLayoutContainer/index.vue +0 -50
  105. package/components/QiuLinkPreview/index.vue +0 -224
  106. package/components/QiuLoading/index.ts +0 -176
  107. package/components/QiuLoading/spinner.vue +0 -820
  108. package/components/QiuLoading/types.ts +0 -44
  109. package/components/QiuMention/index.vue +0 -299
  110. package/components/QiuMenu/QiuMenuRoot.vue +0 -241
  111. package/components/QiuMenu/components/QiuMenuItem.vue +0 -340
  112. package/components/QiuMenu/components/QiuSubMenu.vue +0 -504
  113. package/components/QiuMenu/context.ts +0 -21
  114. package/components/QiuMenu/index.vue +0 -43
  115. package/components/QiuMenuNav/QiuMenuNavItem.vue +0 -100
  116. package/components/QiuMenuNav/QiuMenuNavSub.vue +0 -120
  117. package/components/QiuMenuNav/context.ts +0 -14
  118. package/components/QiuMenuNav/index.vue +0 -148
  119. package/components/QiuMsg/QiuMsgItem.vue +0 -180
  120. package/components/QiuMsg/index.ts +0 -158
  121. package/components/QiuMsg/types.ts +0 -23
  122. package/components/QiuMsgBox/index.ts +0 -147
  123. package/components/QiuNotification/QiuNotificationItem.vue +0 -168
  124. package/components/QiuNotification/index.ts +0 -155
  125. package/components/QiuNotification/types.ts +0 -14
  126. package/components/QiuPage/index.vue +0 -12
  127. package/components/QiuPageHeader/index.vue +0 -115
  128. package/components/QiuPageMain/index.vue +0 -78
  129. package/components/QiuPagination/index.vue +0 -421
  130. package/components/QiuPasswordStrength/index.vue +0 -101
  131. package/components/QiuPopconfirm/index.vue +0 -196
  132. package/components/QiuPopover/index.vue +0 -277
  133. package/components/QiuProgress/index.vue +0 -235
  134. package/components/QiuQrcode/index.vue +0 -302
  135. package/components/QiuQueryForm/components/QiuQueryFormBottomPanel.vue +0 -13
  136. package/components/QiuQueryForm/components/QiuQueryFormLeftPanel.vue +0 -37
  137. package/components/QiuQueryForm/components/QiuQueryFormRightPanel.vue +0 -37
  138. package/components/QiuQueryForm/components/QiuQueryFormTopPanel.vue +0 -13
  139. package/components/QiuQueryForm/index.vue +0 -117
  140. package/components/QiuRadio/QiuRadioGroup.vue +0 -75
  141. package/components/QiuRadio/index.vue +0 -191
  142. package/components/QiuRadio/types.ts +0 -9
  143. package/components/QiuRate/index.vue +0 -184
  144. package/components/QiuRefresh/index.vue +0 -32
  145. package/components/QiuResult/index.vue +0 -103
  146. package/components/QiuRow/index.vue +0 -60
  147. package/components/QiuRow/types.ts +0 -5
  148. package/components/QiuScrollbar/index.vue +0 -107
  149. package/components/QiuSearchBar/index.vue +0 -154
  150. package/components/QiuSegmented/index.vue +0 -120
  151. package/components/QiuSelect/QiuOption.vue +0 -93
  152. package/components/QiuSelect/index.vue +0 -452
  153. package/components/QiuSelect/types.ts +0 -15
  154. package/components/QiuSkeleton/index.vue +0 -78
  155. package/components/QiuSlider/index.vue +0 -266
  156. package/components/QiuSpace/index.vue +0 -95
  157. package/components/QiuSparkline/index.vue +0 -92
  158. package/components/QiuStatistic/index.vue +0 -4
  159. package/components/QiuStatistics/index.vue +0 -123
  160. package/components/QiuStep/index.vue +0 -220
  161. package/components/QiuSteps/context.ts +0 -25
  162. package/components/QiuSteps/index.vue +0 -84
  163. package/components/QiuSwitch/index.vue +0 -145
  164. package/components/QiuTabBar/index.vue +0 -218
  165. package/components/QiuTabBar/types.ts +0 -19
  166. package/components/QiuTabPane/index.vue +0 -82
  167. package/components/QiuTable/columns.ts +0 -16
  168. package/components/QiuTable/export.ts +0 -102
  169. package/components/QiuTable/index.ts +0 -24
  170. package/components/QiuTable/index.vue +0 -3503
  171. package/components/QiuTable/registry.ts +0 -75
  172. package/components/QiuTable/styles/table.scss +0 -1230
  173. package/components/QiuTable/types.ts +0 -413
  174. package/components/QiuTable/useArea.ts +0 -202
  175. package/components/QiuTable/useColumns.ts +0 -325
  176. package/components/QiuTable/useEdit.ts +0 -136
  177. package/components/QiuTable/useExtras.ts +0 -115
  178. package/components/QiuTable/useHistory.ts +0 -77
  179. package/components/QiuTable/useMerge.ts +0 -105
  180. package/components/QiuTable/useResize.ts +0 -86
  181. package/components/QiuTable/useScrollSync.ts +0 -152
  182. package/components/QiuTable/useVirtual.ts +0 -97
  183. package/components/QiuTable/utils.ts +0 -165
  184. package/components/QiuTableColumn/index.vue +0 -101
  185. package/components/QiuTag/index.vue +0 -143
  186. package/components/QiuText/index.vue +0 -99
  187. package/components/QiuTime/index.vue +0 -548
  188. package/components/QiuTimeAgo/index.vue +0 -103
  189. package/components/QiuTimeline/index.vue +0 -54
  190. package/components/QiuTimelineItem/index.vue +0 -140
  191. package/components/QiuTips/index.vue +0 -323
  192. package/components/QiuTooltip/index.vue +0 -237
  193. package/components/QiuTransfer/index.vue +0 -277
  194. package/components/QiuTree/QiuTreeNode.vue +0 -146
  195. package/components/QiuTree/index.vue +0 -143
  196. package/components/QiuTree/types.ts +0 -30
  197. package/components/QiuTreeSelect/index.vue +0 -259
  198. package/components/QiuTrend/index.vue +0 -92
  199. package/components/QiuUpload/index.vue +0 -628
  200. package/components/QiuUploadCrop/index.vue +0 -1267
  201. package/components/QiuWatermark/index.vue +0 -121
  202. package/components/useBodyScrollLock.ts +0 -28
  203. package/dist/components/QiuBadge/utils/pca-code.json.d.ts +0 -3
  204. package/plugins/qiu.ts +0 -83
  205. package/plugins/shortcuts.ts +0 -69
  206. package/src/bridge/@/api/media.ts +0 -8
  207. package/src/bridge/@/api/notice.ts +0 -5
  208. package/src/bridge/@/config/index.ts +0 -38
  209. package/src/bridge/@/config/media.config.ts +0 -37
  210. package/src/bridge/@/config/security.config.ts +0 -8
  211. package/src/bridge/@/i18n/index.ts +0 -6
  212. package/src/bridge/@/store/modules/bing.ts +0 -9
  213. package/src/bridge/@/store/modules/errorLog.ts +0 -9
  214. package/src/bridge/@/store/modules/media.ts +0 -10
  215. package/src/bridge/@/store/modules/routes.ts +0 -10
  216. package/src/bridge/@/store/modules/settings.ts +0 -9
  217. package/src/bridge/@/store/modules/tabs.ts +0 -9
  218. package/src/bridge/@/store/modules/user.ts +0 -9
  219. package/src/bridge/@/utils/convertToCamelCase.ts +0 -11
  220. package/src/bridge/@/utils/index.ts +0 -9
  221. package/src/bridge/@/utils/pageTitle.ts +0 -4
  222. package/src/bridge/@/utils/routes.ts +0 -14
  223. package/src/bridge/@/utils/validate.ts +0 -17
  224. package/src/bridge/@qiu/plugins/shortcuts.ts +0 -3
  225. package/src/i18n.ts +0 -8
  226. package/src/icons/qiu-logo.svg +0 -1
  227. package/styles/dark.scss +0 -194
  228. package/styles/normalize.css +0 -349
  229. package/styles/plain.scss +0 -423
  230. package/styles/qiu-tokens.scss +0 -40
  231. package/styles/qiu.scss +0 -1149
  232. package/styles/technology.scss +0 -452
  233. package/styles/var.scss +0 -382
  234. package/styles/variables.scss +0 -77
@@ -1,79 +0,0 @@
1
- /**
2
- * Banner 模式默认画布与模块
3
- * @author qiuye
4
- * @email yjk150@qq.com
5
- * @date 2026-08-16
6
- */
7
- import type { CanvasKitDoc, DataModuleDef } from '../types'
8
- import { cloneBuiltinModules } from '../modules/dataRegistry'
9
-
10
- export const BANNER_DEFAULT_MODULES: DataModuleDef[] = cloneBuiltinModules().map((m) => ({
11
- ...m,
12
- enabled: ['school', 'competition'].includes(m.id),
13
- }))
14
-
15
- export function createBannerDoc(partial?: Partial<CanvasKitDoc>): CanvasKitDoc {
16
- return {
17
- version: 1,
18
- mode: 'banner',
19
- canvas: {
20
- widthMm: 320,
21
- heightMm: 90,
22
- widthPx: 1200,
23
- heightPx: 340,
24
- unit: 'px',
25
- background: '#0f766e',
26
- showBorder: false,
27
- },
28
- elements: [
29
- {
30
- id: 'banner-title',
31
- type: 'text',
32
- zIndex: 2,
33
- xMm: 20,
34
- yMm: 25,
35
- wMm: 200,
36
- hMm: 20,
37
- text: '{{school.name}}',
38
- fontSize: 28,
39
- fontFamily: 'Microsoft YaHei, sans-serif',
40
- color: '#ffffff',
41
- link: { href: 'https://example.com', target: '_blank' },
42
- },
43
- {
44
- id: 'banner-sub',
45
- type: 'text',
46
- zIndex: 2,
47
- xMm: 20,
48
- yMm: 50,
49
- wMm: 240,
50
- hMm: 14,
51
- text: '{{competition.name}}',
52
- fontSize: 14,
53
- fontFamily: 'Microsoft YaHei, sans-serif',
54
- color: '#ccfbf1',
55
- },
56
- ],
57
- dataModules: BANNER_DEFAULT_MODULES,
58
- ...partial,
59
- }
60
- }
61
-
62
- export function createBadgeDoc(partial?: Partial<CanvasKitDoc>): CanvasKitDoc {
63
- return {
64
- version: 1,
65
- mode: 'badge',
66
- canvas: {
67
- widthMm: 90,
68
- heightMm: 130,
69
- unit: 'mm',
70
- background: '#ffffff',
71
- showBorder: true,
72
- borderColor: '#334155',
73
- borderWidthMm: 0.35,
74
- },
75
- elements: [],
76
- dataModules: cloneBuiltinModules(),
77
- ...partial,
78
- }
79
- }
@@ -1,138 +0,0 @@
1
- /**
2
- * QiuCanvasKit 类型:统一证件 / 桌签 / Banner 画布文档
3
- * @author qiuye
4
- * @email yjk150@qq.com
5
- * @date 2026-08-16
6
- */
7
-
8
- export type CanvasKitMode = 'badge' | 'desk' | 'banner'
9
-
10
- export type DataFieldType = 'string' | 'number' | 'image' | 'url'
11
-
12
- export type DataFieldDef = {
13
- key: string
14
- label: string
15
- type?: DataFieldType
16
- }
17
-
18
- export type DataModuleDef = {
19
- id: string
20
- label: string
21
- fields: DataFieldDef[]
22
- sample?: Record<string, string>
23
- /** 内置模块不可删;自定义可删 */
24
- builtin?: boolean
25
- enabled?: boolean
26
- }
27
-
28
- /** 嵌套合并上下文:{ student: { name }, classroom: { name } } */
29
- export type MergeContext = Record<string, Record<string, string> | string>
30
-
31
- export type ElementLink = {
32
- href: string
33
- target?: '_blank' | '_self'
34
- }
35
-
36
- export interface CanvasKitCanvas {
37
- widthMm: number
38
- heightMm: number
39
- /** Banner 可用 px;与 widthMm 二选一优先 px */
40
- widthPx?: number
41
- heightPx?: number
42
- background?: string
43
- backgroundImage?: string
44
- showBorder?: boolean
45
- borderColor?: string
46
- borderWidthMm?: number
47
- unit?: 'mm' | 'px'
48
- }
49
-
50
- export interface CanvasKitRegion {
51
- id: string
52
- name: string
53
- xMm: number
54
- yMm: number
55
- wMm: number
56
- hMm: number
57
- background?: string
58
- backgroundImage?: string
59
- }
60
-
61
- export interface CanvasKitElementBase {
62
- id: string
63
- zIndex: number
64
- xMm: number
65
- yMm: number
66
- wMm: number
67
- hMm: number
68
- rotation?: number
69
- flipX?: boolean
70
- flipY?: boolean
71
- groupId?: string
72
- regionId?: string
73
- align?: string
74
- link?: ElementLink
75
- }
76
-
77
- export interface CanvasKitTextElement extends CanvasKitElementBase {
78
- type: 'text'
79
- text: string
80
- fontSize: number
81
- fontFamily: string
82
- color: string
83
- textDirection?: 'horizontal' | 'vertical'
84
- }
85
-
86
- export interface CanvasKitImageElement extends CanvasKitElementBase {
87
- type: 'image' | 'seal'
88
- src: string
89
- clipboardSource?: 'clipboard'
90
- clipboardUploadState?: 'pending' | 'uploaded'
91
- clipboardUploadKey?: string
92
- clipboardImageId?: number
93
- clipboardOrigName?: string
94
- }
95
-
96
- export interface CanvasKitShapeElement extends CanvasKitElementBase {
97
- type: 'shape'
98
- shape: 'rect' | 'circle' | 'triangle' | 'line' | 'polygon' | 'trapezoid'
99
- background?: string
100
- lockAspectRatio?: boolean
101
- showStroke?: boolean
102
- strokeColor?: string
103
- strokeWidthMm?: number
104
- opacity?: number
105
- polygonSides?: number
106
- }
107
-
108
- export type CanvasKitElement =
109
- | CanvasKitTextElement
110
- | CanvasKitImageElement
111
- | CanvasKitShapeElement
112
-
113
- export interface CanvasKitGuideLine {
114
- id: string
115
- axis: 'horizontal' | 'vertical'
116
- offsetMm: number
117
- }
118
-
119
- export interface CanvasKitDoc {
120
- version: number
121
- mode?: CanvasKitMode
122
- canvas: CanvasKitCanvas
123
- elements: CanvasKitElement[]
124
- guides?: CanvasKitGuideLine[]
125
- regions?: CanvasKitRegion[]
126
- /** 模板级数据模块(启用/自定义) */
127
- dataModules?: DataModuleDef[]
128
- }
129
-
130
- /** 兼容旧证件模板类型别名 */
131
- export type BadgeTemplateDoc = CanvasKitDoc
132
- export type BadgeElement = CanvasKitElement
133
- export type BadgeTextElement = CanvasKitTextElement
134
- export type BadgeImageElement = CanvasKitImageElement
135
- export type BadgeShapeElement = CanvasKitShapeElement
136
- export type BadgeTemplateCanvas = CanvasKitCanvas
137
- export type BadgeCanvasRegion = CanvasKitRegion
138
- export type BadgeGuideLine = CanvasKitGuideLine
@@ -1,104 +0,0 @@
1
- <template>
2
- <div class="qiu-card" :class="[`qiu-card--shadow-${shadow}`]">
3
- <div v-if="$slots.header || title" class="qiu-card__header">
4
- <slot v-if="$slots.header" name="header" />
5
- <template v-else>{{ title }}</template>
6
- </div>
7
- <div class="qiu-card__body" :class="bodyClass" :style="bodyStyle">
8
- <qiu-skeleton v-if="skeleton" animated :loading="skeletonShow" :rows="skeletonRows">
9
- <slot />
10
- </qiu-skeleton>
11
- <slot v-else />
12
- </div>
13
- <div v-if="$slots.footer" class="qiu-card__footer">
14
- <slot name="footer" />
15
- </div>
16
- </div>
17
- </template>
18
-
19
- <script lang="ts" setup>
20
- defineOptions({
21
- name: 'QiuCard',
22
- })
23
-
24
- const props = defineProps({
25
- bodyClass: {
26
- type: String,
27
- default: '',
28
- },
29
- bodyStyle: {
30
- type: [Object, String] as () => Record<string, string> | string,
31
- default: () => ({}),
32
- },
33
- shadow: {
34
- type: String as () => 'never' | 'hover' | 'always',
35
- default: 'never',
36
- },
37
- skeleton: {
38
- type: Boolean,
39
- default: false,
40
- },
41
- skeletonRows: {
42
- type: Number,
43
- default: 5,
44
- },
45
- title: {
46
- type: String,
47
- default: '',
48
- },
49
- })
50
-
51
- const skeletonShow = ref<boolean>(true)
52
-
53
- const timer: ReturnType<typeof setTimeout> = setTimeout(() => {
54
- skeletonShow.value = false
55
- }, 500)
56
-
57
- onBeforeUnmount(() => {
58
- clearTimeout(timer)
59
- })
60
- </script>
61
-
62
- <style lang="scss" scoped>
63
- .qiu-card {
64
- overflow: hidden;
65
- background: var(--qiu-bg-color, #fff);
66
- border: 1px solid var(--qiu-border-color-light, #e4e7ed);
67
- border-radius: var(--qiu-border-radius-base, 4px);
68
- transition: box-shadow 0.3s ease;
69
-
70
- &--shadow-always {
71
- box-shadow: var(--qiu-box-shadow-light, 0 2px 12px 0 rgb(0 0 0 / 10%));
72
- }
73
-
74
- &--shadow-hover:hover {
75
- box-shadow: var(--qiu-box-shadow-light, 0 2px 12px 0 rgb(0 0 0 / 10%));
76
- }
77
-
78
- &__header {
79
- padding: calc(var(--qiu-card-padding, 20px) - 2px) var(--qiu-card-padding, 20px);
80
- font-weight: 500;
81
- border-bottom: 1px solid var(--qiu-border-color-light, #e4e7ed);
82
-
83
- :deep([class*='ri-']) {
84
- background-image: linear-gradient(120deg, #bd34fe 30%, var(--qiu-color-primary));
85
- background-clip: text;
86
- -webkit-text-fill-color: transparent;
87
- }
88
- }
89
-
90
- &__body {
91
- padding: var(--qiu-card-padding, 20px);
92
- }
93
-
94
- &__footer {
95
- padding: calc(var(--qiu-card-padding, 20px) - 2px) var(--qiu-card-padding, 20px);
96
- border-top: 1px solid var(--qiu-border-color-light, #e4e7ed);
97
- }
98
-
99
- :deep(.qiu-skeleton) {
100
- height: 100%;
101
- overflow: hidden;
102
- }
103
- }
104
- </style>
@@ -1,16 +0,0 @@
1
- import type { InjectionKey, Ref } from 'vue'
2
-
3
- export interface QiuCarouselItemRegistration {
4
- uid: number
5
- name?: string | number
6
- }
7
-
8
- export interface QiuCarouselContext {
9
- activeIndex: Ref<number>
10
- itemCount: Ref<number>
11
- registerItem: (item: QiuCarouselItemRegistration) => number
12
- unregisterItem: (uid: number) => void
13
- loop: Ref<boolean>
14
- }
15
-
16
- export const QIU_CAROUSEL_KEY: InjectionKey<QiuCarouselContext> = Symbol('QiuCarousel')
@@ -1,343 +0,0 @@
1
- <template>
2
- <div
3
- class="qiu-carousel"
4
- :class="[`qiu-carousel--arrow-${arrow}`]"
5
- :style="rootStyle"
6
- @mouseenter="onMouseEnter"
7
- @mouseleave="onMouseLeave"
8
- >
9
- <div class="qiu-carousel__container">
10
- <Transition :name="transitionName" mode="out-in">
11
- <div :key="activeIndex" class="qiu-carousel__slide">
12
- <component :is="currentVNode" v-if="currentVNode" />
13
- </div>
14
- </Transition>
15
-
16
- <button
17
- v-if="arrow !== 'never'"
18
- type="button"
19
- class="qiu-carousel__arrow qiu-carousel__arrow--left"
20
- aria-label="previous"
21
- @click="prev"
22
- >
23
- <qiu-icon icon="arrow-left-s-line" />
24
- </button>
25
- <button
26
- v-if="arrow !== 'never'"
27
- type="button"
28
- class="qiu-carousel__arrow qiu-carousel__arrow--right"
29
- aria-label="next"
30
- @click="next"
31
- >
32
- <qiu-icon icon="arrow-right-s-line" />
33
- </button>
34
- </div>
35
-
36
- <div
37
- v-if="indicatorPosition !== 'none'"
38
- class="qiu-carousel__indicators"
39
- :class="`qiu-carousel__indicators--${indicatorPosition}`"
40
- >
41
- <button
42
- v-for="(_, idx) in itemCount"
43
- :key="idx"
44
- type="button"
45
- class="qiu-carousel__indicator"
46
- :class="{ 'is-active': idx === activeIndex }"
47
- :aria-label="`slide ${idx + 1}`"
48
- @click="goTo(idx)"
49
- />
50
- </div>
51
-
52
- <div class="qiu-carousel__items" aria-hidden="true">
53
- <slot />
54
- </div>
55
- </div>
56
- </template>
57
-
58
- <script lang="ts" setup>
59
- import type { QiuCarouselContext, QiuCarouselItemRegistration } from './context'
60
- import { QIU_CAROUSEL_KEY } from './context'
61
-
62
- defineOptions({ name: 'QiuCarousel' })
63
-
64
- const props = withDefaults(
65
- defineProps<{
66
- modelValue?: number
67
- autoplay?: boolean
68
- interval?: number
69
- height?: string | number
70
- indicatorPosition?: 'outside' | 'inside' | 'none'
71
- arrow?: 'always' | 'hover' | 'never'
72
- loop?: boolean
73
- }>(),
74
- {
75
- modelValue: 0,
76
- autoplay: true,
77
- interval: 3000,
78
- height: '',
79
- indicatorPosition: 'inside',
80
- arrow: 'hover',
81
- loop: true,
82
- }
83
- )
84
-
85
- const emit = defineEmits<{
86
- 'update:modelValue': [number]
87
- change: [number]
88
- }>()
89
-
90
- const items = ref<QiuCarouselItemRegistration[]>([])
91
- const itemRenders = ref<Map<number, () => any>>(new Map())
92
- const hover = ref(false)
93
- const direction = ref<'next' | 'prev'>('next')
94
- let timer: ReturnType<typeof setInterval> | null = null
95
-
96
- const itemCount = computed(() => items.value.length)
97
-
98
- const activeIndex = computed({
99
- get() {
100
- if (!itemCount.value) return 0
101
- const idx = props.modelValue ?? 0
102
- return ((idx % itemCount.value) + itemCount.value) % itemCount.value
103
- },
104
- set(val: number) {
105
- emit('update:modelValue', val)
106
- emit('change', val)
107
- },
108
- })
109
-
110
- const rootStyle = computed(() => {
111
- if (!props.height && props.height !== 0) return undefined
112
- const h = typeof props.height === 'number' ? `${props.height}px` : props.height
113
- return { height: h }
114
- })
115
-
116
- const transitionName = computed(() =>
117
- direction.value === 'next' ? 'qiu-carousel-slide-next' : 'qiu-carousel-slide-prev'
118
- )
119
-
120
- const currentUid = computed(() => items.value[activeIndex.value]?.uid)
121
- const currentVNode = computed(() => {
122
- const uid = currentUid.value
123
- if (uid === undefined) return null
124
- const render = itemRenders.value.get(uid)
125
- return render ? render : null
126
- })
127
-
128
- const registerItem = (item: QiuCarouselItemRegistration) => {
129
- const idx = items.value.findIndex((i) => i.uid === item.uid)
130
- if (idx >= 0) items.value[idx] = item
131
- else items.value.push(item)
132
- return items.value.findIndex((i) => i.uid === item.uid)
133
- }
134
-
135
- const unregisterItem = (uid: number) => {
136
- items.value = items.value.filter((i) => i.uid !== uid)
137
- itemRenders.value.delete(uid)
138
- }
139
-
140
- provide<QiuCarouselContext>(QIU_CAROUSEL_KEY, {
141
- activeIndex: activeIndex as Ref<number>,
142
- itemCount,
143
- registerItem,
144
- unregisterItem,
145
- loop: toRef(props, 'loop'),
146
- })
147
-
148
- provide('qiuCarouselRegisterRender', (uid: number, render: () => any) => {
149
- itemRenders.value.set(uid, render)
150
- })
151
-
152
- const goTo = (idx: number) => {
153
- if (!itemCount.value) return
154
- direction.value = idx >= activeIndex.value ? 'next' : 'prev'
155
- activeIndex.value = idx
156
- }
157
-
158
- const next = () => {
159
- if (!itemCount.value) return
160
- direction.value = 'next'
161
- if (activeIndex.value >= itemCount.value - 1) {
162
- activeIndex.value = props.loop ? 0 : itemCount.value - 1
163
- } else {
164
- activeIndex.value = activeIndex.value + 1
165
- }
166
- }
167
-
168
- const prev = () => {
169
- if (!itemCount.value) return
170
- direction.value = 'prev'
171
- if (activeIndex.value <= 0) {
172
- activeIndex.value = props.loop ? itemCount.value - 1 : 0
173
- } else {
174
- activeIndex.value = activeIndex.value - 1
175
- }
176
- }
177
-
178
- const startAutoplay = () => {
179
- stopAutoplay()
180
- if (!props.autoplay || itemCount.value <= 1) return
181
- timer = setInterval(() => next(), props.interval)
182
- }
183
-
184
- const stopAutoplay = () => {
185
- if (timer) {
186
- clearInterval(timer)
187
- timer = null
188
- }
189
- }
190
-
191
- const onMouseEnter = () => {
192
- hover.value = true
193
- stopAutoplay()
194
- }
195
-
196
- const onMouseLeave = () => {
197
- hover.value = false
198
- startAutoplay()
199
- }
200
-
201
- watch(
202
- () => [props.autoplay, props.interval, itemCount.value] as const,
203
- () => startAutoplay(),
204
- { immediate: true }
205
- )
206
-
207
- onBeforeUnmount(stopAutoplay)
208
-
209
- defineExpose({ next, prev, goTo })
210
- </script>
211
-
212
- <style lang="scss" scoped>
213
- .qiu-carousel {
214
- position: relative;
215
- width: 100%;
216
- overflow: hidden;
217
- background: var(--qiu-bg-color, var(--qiu-bg-color, #fff));
218
- border-radius: var(--qiu-border-radius, var(--qiu-border-radius-base, 4px));
219
-
220
- &__container {
221
- position: relative;
222
- width: 100%;
223
- height: 100%;
224
- min-height: 180px;
225
- }
226
-
227
- &__slide {
228
- width: 100%;
229
- height: 100%;
230
- min-height: inherit;
231
- }
232
-
233
- &__items {
234
- display: none;
235
- }
236
-
237
- &__arrow {
238
- position: absolute;
239
- top: 50%;
240
- z-index: 2;
241
- display: inline-flex;
242
- align-items: center;
243
- justify-content: center;
244
- width: 36px;
245
- height: 36px;
246
- font-size: 18px;
247
- color: var(--qiu-text-color-primary, var(--qiu-text-color-primary, #303133));
248
- cursor: pointer;
249
- background: rgb(255 255 255 / 85%);
250
- border: 0;
251
- border-radius: 50%;
252
- box-shadow: 0 2px 8px rgb(0 0 0 / 12%);
253
- transform: translateY(-50%);
254
- transition: opacity 0.2s, background 0.2s;
255
-
256
- &:hover {
257
- background: #fff;
258
- }
259
-
260
- &--left {
261
- left: 12px;
262
- }
263
-
264
- &--right {
265
- right: 12px;
266
- }
267
- }
268
-
269
- &--arrow-hover &__arrow {
270
- opacity: 0;
271
- pointer-events: none;
272
- }
273
-
274
- &--arrow-hover:hover &__arrow {
275
- opacity: 1;
276
- pointer-events: auto;
277
- }
278
-
279
- &__indicators {
280
- display: flex;
281
- gap: 8px;
282
- justify-content: center;
283
- padding: 10px 0;
284
-
285
- &--inside {
286
- position: absolute;
287
- right: 0;
288
- bottom: 8px;
289
- left: 0;
290
- z-index: 2;
291
- padding: 0;
292
- }
293
-
294
- &--outside {
295
- position: static;
296
- }
297
- }
298
-
299
- &__indicator {
300
- width: 8px;
301
- height: 8px;
302
- padding: 0;
303
- cursor: pointer;
304
- background: rgb(255 255 255 / 55%);
305
- border: 1px solid var(--qiu-border-color, var(--qiu-border-color, #dcdfe6));
306
- border-radius: 50%;
307
- transition: background 0.2s, transform 0.2s;
308
-
309
- &.is-active {
310
- background: var(--qiu-color-primary, var(--qiu-color-primary, #409eff));
311
- border-color: var(--qiu-color-primary, var(--qiu-color-primary, #409eff));
312
- transform: scale(1.15);
313
- }
314
- }
315
- }
316
-
317
- .qiu-carousel-slide-next-enter-active,
318
- .qiu-carousel-slide-next-leave-active,
319
- .qiu-carousel-slide-prev-enter-active,
320
- .qiu-carousel-slide-prev-leave-active {
321
- transition: opacity 0.35s ease, transform 0.35s ease;
322
- }
323
-
324
- .qiu-carousel-slide-next-enter-from {
325
- opacity: 0;
326
- transform: translateX(24px);
327
- }
328
-
329
- .qiu-carousel-slide-next-leave-to {
330
- opacity: 0;
331
- transform: translateX(-24px);
332
- }
333
-
334
- .qiu-carousel-slide-prev-enter-from {
335
- opacity: 0;
336
- transform: translateX(-24px);
337
- }
338
-
339
- .qiu-carousel-slide-prev-leave-to {
340
- opacity: 0;
341
- transform: translateX(24px);
342
- }
343
- </style>