@didaoktv/didaoui-uniapp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -0
  3. package/components/dd-action-sheet/dd-action-sheet.vue +207 -0
  4. package/components/dd-alert/dd-alert.vue +240 -0
  5. package/components/dd-avatar/dd-avatar.vue +168 -0
  6. package/components/dd-backtop/dd-backtop.vue +75 -0
  7. package/components/dd-badge/dd-badge.vue +150 -0
  8. package/components/dd-button/dd-button.vue +215 -0
  9. package/components/dd-capsule-button/dd-capsule-button.vue +109 -0
  10. package/components/dd-card/dd-card.vue +155 -0
  11. package/components/dd-cell/dd-cell.vue +201 -0
  12. package/components/dd-cell-group/dd-cell-group.vue +56 -0
  13. package/components/dd-champion-card/dd-champion-card.vue +258 -0
  14. package/components/dd-checkbox/dd-checkbox.vue +145 -0
  15. package/components/dd-collapse/dd-collapse.vue +63 -0
  16. package/components/dd-collapse-item/dd-collapse-item.vue +154 -0
  17. package/components/dd-count-down/dd-count-down.vue +163 -0
  18. package/components/dd-date-picker/dd-date-picker.vue +253 -0
  19. package/components/dd-dialog/dd-dialog.vue +264 -0
  20. package/components/dd-divider/dd-divider.vue +104 -0
  21. package/components/dd-drawer/dd-drawer.vue +214 -0
  22. package/components/dd-dropdown-item/dd-dropdown-item.vue +203 -0
  23. package/components/dd-dropdown-menu/dd-dropdown-menu.vue +177 -0
  24. package/components/dd-empty-state/dd-empty-state.vue +140 -0
  25. package/components/dd-feature-grid/dd-feature-grid.vue +139 -0
  26. package/components/dd-field/dd-field.vue +240 -0
  27. package/components/dd-icon/dd-icon.vue +464 -0
  28. package/components/dd-image/dd-image.vue +158 -0
  29. package/components/dd-input/dd-input.vue +172 -0
  30. package/components/dd-list-cell/dd-list-cell.vue +152 -0
  31. package/components/dd-loading/dd-loading.vue +187 -0
  32. package/components/dd-loadmore/dd-loadmore.vue +152 -0
  33. package/components/dd-mini-program-navbar/dd-mini-program-navbar.vue +245 -0
  34. package/components/dd-modal/dd-modal.vue +286 -0
  35. package/components/dd-navigation/dd-navigation.vue +134 -0
  36. package/components/dd-overlay/dd-overlay.vue +114 -0
  37. package/components/dd-picker/dd-picker.vue +203 -0
  38. package/components/dd-popover/dd-popover.vue +190 -0
  39. package/components/dd-popover-item/dd-popover-item.vue +88 -0
  40. package/components/dd-popup/dd-popup.vue +243 -0
  41. package/components/dd-progress/dd-progress.vue +255 -0
  42. package/components/dd-pull-refresh/dd-pull-refresh.vue +232 -0
  43. package/components/dd-radio/dd-radio.vue +129 -0
  44. package/components/dd-rate/dd-rate.vue +133 -0
  45. package/components/dd-room-card/dd-room-card.vue +309 -0
  46. package/components/dd-search-bar/dd-search-bar.vue +176 -0
  47. package/components/dd-segmented-tab/dd-segmented-tab.vue +187 -0
  48. package/components/dd-skeleton/dd-skeleton.vue +184 -0
  49. package/components/dd-slider/dd-slider.vue +227 -0
  50. package/components/dd-stat-card/dd-stat-card.vue +174 -0
  51. package/components/dd-step/dd-step.vue +188 -0
  52. package/components/dd-stepper/dd-stepper.vue +171 -0
  53. package/components/dd-steps/dd-steps.vue +61 -0
  54. package/components/dd-sticky/dd-sticky.vue +132 -0
  55. package/components/dd-swipe/dd-swipe.vue +146 -0
  56. package/components/dd-swipe-action/dd-swipe-action.vue +248 -0
  57. package/components/dd-swipe-item/dd-swipe-item.vue +27 -0
  58. package/components/dd-swipeable-tab/dd-swipeable-tab.vue +202 -0
  59. package/components/dd-switch/dd-switch.vue +106 -0
  60. package/components/dd-tabbar/dd-tabbar.vue +112 -0
  61. package/components/dd-tabbar-item/dd-tabbar-item.vue +122 -0
  62. package/components/dd-tag/dd-tag.vue +178 -0
  63. package/components/dd-toast/dd-toast.vue +195 -0
  64. package/components/dd-top-navbar/dd-top-navbar.vue +184 -0
  65. package/components/dd-upload/dd-upload.vue +187 -0
  66. package/index.ts +127 -0
  67. package/libs/utils.ts +106 -0
  68. package/package.json +58 -0
  69. package/scss/_functions.scss +68 -0
  70. package/scss/_mixins.scss +154 -0
  71. package/scss/_reset.scss +30 -0
  72. package/scss/_variables.scss +317 -0
  73. package/uni.scss +4 -0
@@ -0,0 +1,187 @@
1
+ <template>
2
+ <view class="dd-upload" :class="{ 'dd-upload--disabled': disabled }">
3
+ <view
4
+ v-for="(file, index) in fileList"
5
+ :key="file.url || index"
6
+ class="dd-upload__item"
7
+ @click="onPreview(index)"
8
+ >
9
+ <image
10
+ class="dd-upload__img"
11
+ :src="file.url"
12
+ :mode="imageMode"
13
+ />
14
+ <view
15
+ v-if="!disabled"
16
+ class="dd-upload__delete"
17
+ @click.stop="onDelete(index)"
18
+ >
19
+ <dd-icon name="cross" />
20
+ </view>
21
+ </view>
22
+ <view
23
+ v-if="showAdd"
24
+ class="dd-upload__add"
25
+ :hover-class="disabled ? '' : 'dd-upload__add--active'"
26
+ @click="onChoose"
27
+ >
28
+ <dd-icon name="plus" />
29
+ </view>
30
+ </view>
31
+ </template>
32
+
33
+ <script setup lang="ts">
34
+ import { computed } from 'vue'
35
+ import DdIcon from '../dd-icon/dd-icon.vue'
36
+
37
+ interface UploadFileItem {
38
+ url: string
39
+ [key: string]: any
40
+ }
41
+
42
+ interface Props {
43
+ fileList?: UploadFileItem[]
44
+ maxCount?: number
45
+ maxSize?: number
46
+ multiple?: boolean
47
+ disabled?: boolean
48
+ imageFit?: 'cover' | 'contain' | 'fill'
49
+ sourceType?: ('album' | 'camera')[]
50
+ }
51
+
52
+ const props = withDefaults(defineProps<Props>(), {
53
+ fileList: () => [],
54
+ maxCount: 9,
55
+ maxSize: 0,
56
+ multiple: true,
57
+ disabled: false,
58
+ imageFit: 'cover',
59
+ sourceType: () => ['album', 'camera'],
60
+ })
61
+
62
+ const emit = defineEmits<{
63
+ (e: 'update:fileList', val: UploadFileItem[]): void
64
+ (e: 'change', val: UploadFileItem[]): void
65
+ (e: 'oversize', val: UploadFileItem[]): void
66
+ (e: 'delete', val: { index: number; file: UploadFileItem }): void
67
+ (e: 'afterRead', val: UploadFileItem[]): void
68
+ }>()
69
+
70
+ const modeMap = {
71
+ cover: 'aspectFill',
72
+ contain: 'aspectFit',
73
+ fill: 'scaleToFill',
74
+ } as const
75
+
76
+ const imageMode = computed(() => modeMap[props.imageFit])
77
+ const showAdd = computed(
78
+ () => !props.disabled && props.fileList.length < props.maxCount
79
+ )
80
+
81
+ function onChoose() {
82
+ if (props.disabled) return
83
+ const remaining = props.maxCount - props.fileList.length
84
+ if (remaining <= 0) return
85
+ const count = props.multiple ? Math.min(remaining, 9) : 1
86
+ uni.chooseImage({
87
+ count,
88
+ sourceType: props.sourceType as any,
89
+ success: (res) => {
90
+ const paths = (res.tempFilePaths as string[]) || []
91
+ const sizes = (res.tempFiles as any[] | undefined)?.map((f: any) => f.size) || []
92
+ const accepted: UploadFileItem[] = []
93
+ const rejected: UploadFileItem[] = []
94
+ paths.forEach((p, i) => {
95
+ const item: UploadFileItem = { url: p }
96
+ if (props.maxSize && sizes[i] && sizes[i] > props.maxSize) {
97
+ rejected.push(item)
98
+ } else {
99
+ accepted.push(item)
100
+ }
101
+ })
102
+ if (rejected.length) emit('oversize', rejected)
103
+ if (accepted.length) {
104
+ const next = [...props.fileList, ...accepted]
105
+ emit('update:fileList', next)
106
+ emit('change', next)
107
+ emit('afterRead', accepted)
108
+ }
109
+ },
110
+ })
111
+ }
112
+
113
+ function onDelete(index: number) {
114
+ const file = props.fileList[index]
115
+ const next = props.fileList.filter((_, i) => i !== index)
116
+ emit('update:fileList', next)
117
+ emit('change', next)
118
+ emit('delete', { index, file })
119
+ }
120
+
121
+ function onPreview(index: number) {
122
+ if (props.disabled) return
123
+ const urls = props.fileList.map((f) => f.url).filter(Boolean)
124
+ if (!urls.length) return
125
+ uni.previewImage({ urls, current: urls[index] })
126
+ }
127
+ </script>
128
+
129
+ <style lang="scss" scoped>
130
+ @import '../../scss/variables';
131
+ @import '../../scss/mixins';
132
+
133
+ .dd-upload {
134
+ display: flex;
135
+ flex-wrap: wrap;
136
+ gap: 16rpx;
137
+
138
+ &__item {
139
+ position: relative;
140
+ width: 160rpx;
141
+ height: 160rpx;
142
+ border-radius: $dd-radius-md;
143
+ background: $dd-neutral-800;
144
+ overflow: hidden;
145
+ }
146
+
147
+ &__img {
148
+ width: 100%;
149
+ height: 100%;
150
+ display: block;
151
+ }
152
+
153
+ &__delete {
154
+ position: absolute;
155
+ top: 8rpx;
156
+ right: 8rpx;
157
+ width: 36rpx;
158
+ height: 36rpx;
159
+ border-radius: 50%;
160
+ background: $dd-error;
161
+ color: $dd-color-white;
162
+ font-size: $dd-font-size-caption;
163
+ @include dd-flex-center;
164
+ }
165
+
166
+ &__add {
167
+ @include dd-flex-center;
168
+ width: 160rpx;
169
+ height: 160rpx;
170
+ border: 1px dashed $dd-border-default;
171
+ border-radius: $dd-radius-md;
172
+ background: $dd-neutral-800;
173
+ color: $dd-text-tertiary;
174
+ font-size: 48rpx;
175
+ box-sizing: border-box;
176
+ @include dd-transition(background 0.2s);
177
+
178
+ &--active {
179
+ background: $dd-border-default;
180
+ }
181
+ }
182
+
183
+ &--disabled {
184
+ @include dd-no-touch;
185
+ }
186
+ }
187
+ </style>
package/index.ts ADDED
@@ -0,0 +1,127 @@
1
+ import type { App } from 'vue'
2
+
3
+ // === Input (13) ===
4
+ import DdButton from './components/dd-button/dd-button.vue'
5
+ import DdInput from './components/dd-input/dd-input.vue'
6
+ import DdSwitch from './components/dd-switch/dd-switch.vue'
7
+ import DdCheckbox from './components/dd-checkbox/dd-checkbox.vue'
8
+ import DdRadio from './components/dd-radio/dd-radio.vue'
9
+ import DdSearchBar from './components/dd-search-bar/dd-search-bar.vue'
10
+ import DdSlider from './components/dd-slider/dd-slider.vue'
11
+ import DdStepper from './components/dd-stepper/dd-stepper.vue'
12
+ import DdDatePicker from './components/dd-date-picker/dd-date-picker.vue'
13
+ import DdField from './components/dd-field/dd-field.vue'
14
+ import DdPicker from './components/dd-picker/dd-picker.vue'
15
+ import DdRate from './components/dd-rate/dd-rate.vue'
16
+ import DdUpload from './components/dd-upload/dd-upload.vue'
17
+ import DdIcon from './components/dd-icon/dd-icon.vue'
18
+
19
+ // === Navigation (12) ===
20
+ import DdNavigation from './components/dd-navigation/dd-navigation.vue'
21
+ import DdTopNavbar from './components/dd-top-navbar/dd-top-navbar.vue'
22
+ import DdSegmentedTab from './components/dd-segmented-tab/dd-segmented-tab.vue'
23
+ import DdSwipeableTab from './components/dd-swipeable-tab/dd-swipeable-tab.vue'
24
+ import DdDrawer from './components/dd-drawer/dd-drawer.vue'
25
+ import DdTabbar from './components/dd-tabbar/dd-tabbar.vue'
26
+ import DdTabbarItem from './components/dd-tabbar-item/dd-tabbar-item.vue'
27
+ import DdBacktop from './components/dd-backtop/dd-backtop.vue'
28
+ import DdCollapse from './components/dd-collapse/dd-collapse.vue'
29
+ import DdCollapseItem from './components/dd-collapse-item/dd-collapse-item.vue'
30
+ import DdDropdownMenu from './components/dd-dropdown-menu/dd-dropdown-menu.vue'
31
+ import DdDropdownItem from './components/dd-dropdown-item/dd-dropdown-item.vue'
32
+
33
+ // === Layout (4) ===
34
+ import DdCard from './components/dd-card/dd-card.vue'
35
+ import DdRoomCard from './components/dd-room-card/dd-room-card.vue'
36
+ import DdFeatureGrid from './components/dd-feature-grid/dd-feature-grid.vue'
37
+ import DdSticky from './components/dd-sticky/dd-sticky.vue'
38
+
39
+ // === Display (16) ===
40
+ import DdTag from './components/dd-tag/dd-tag.vue'
41
+ import DdStatCard from './components/dd-stat-card/dd-stat-card.vue'
42
+ import DdChampionCard from './components/dd-champion-card/dd-champion-card.vue'
43
+ import DdAvatar from './components/dd-avatar/dd-avatar.vue'
44
+ import DdBadge from './components/dd-badge/dd-badge.vue'
45
+ import DdListCell from './components/dd-list-cell/dd-list-cell.vue'
46
+ import DdCell from './components/dd-cell/dd-cell.vue'
47
+ import DdCellGroup from './components/dd-cell-group/dd-cell-group.vue'
48
+ import DdCountDown from './components/dd-count-down/dd-count-down.vue'
49
+ import DdDivider from './components/dd-divider/dd-divider.vue'
50
+ import DdImage from './components/dd-image/dd-image.vue'
51
+ import DdProgress from './components/dd-progress/dd-progress.vue'
52
+ import DdSkeleton from './components/dd-skeleton/dd-skeleton.vue'
53
+ import DdEmptyState from './components/dd-empty-state/dd-empty-state.vue'
54
+ import DdStep from './components/dd-step/dd-step.vue'
55
+ import DdSteps from './components/dd-steps/dd-steps.vue'
56
+
57
+ // === Overlay (10) ===
58
+ import DdModal from './components/dd-modal/dd-modal.vue'
59
+ import DdActionSheet from './components/dd-action-sheet/dd-action-sheet.vue'
60
+ import DdToast from './components/dd-toast/dd-toast.vue'
61
+ import DdAlert from './components/dd-alert/dd-alert.vue'
62
+ import DdLoading from './components/dd-loading/dd-loading.vue'
63
+ import DdDialog from './components/dd-dialog/dd-dialog.vue'
64
+ import DdOverlay from './components/dd-overlay/dd-overlay.vue'
65
+ import DdPopup from './components/dd-popup/dd-popup.vue'
66
+ import DdPopover from './components/dd-popover/dd-popover.vue'
67
+ import DdPopoverItem from './components/dd-popover-item/dd-popover-item.vue'
68
+
69
+ // === Interaction (5) ===
70
+ import DdSwipeAction from './components/dd-swipe-action/dd-swipe-action.vue'
71
+ import DdSwipe from './components/dd-swipe/dd-swipe.vue'
72
+ import DdSwipeItem from './components/dd-swipe-item/dd-swipe-item.vue'
73
+ import DdPullRefresh from './components/dd-pull-refresh/dd-pull-refresh.vue'
74
+ import DdLoadmore from './components/dd-loadmore/dd-loadmore.vue'
75
+
76
+ // === Mini Program (2) ===
77
+ import DdCapsuleButton from './components/dd-capsule-button/dd-capsule-button.vue'
78
+ import DdMiniProgramNavbar from './components/dd-mini-program-navbar/dd-mini-program-navbar.vue'
79
+
80
+ const components = {
81
+ DdButton, DdInput, DdSwitch, DdCheckbox, DdRadio,
82
+ DdSearchBar, DdSlider, DdStepper, DdDatePicker, DdField,
83
+ DdPicker, DdRate, DdUpload, DdIcon,
84
+ DdNavigation, DdTopNavbar, DdSegmentedTab, DdSwipeableTab,
85
+ DdDrawer, DdTabbar, DdTabbarItem, DdBacktop,
86
+ DdCollapse, DdCollapseItem, DdDropdownMenu, DdDropdownItem,
87
+ DdCard, DdRoomCard, DdFeatureGrid, DdSticky,
88
+ DdTag, DdStatCard, DdChampionCard, DdAvatar, DdBadge,
89
+ DdListCell, DdCell, DdCellGroup, DdCountDown, DdDivider,
90
+ DdImage, DdProgress, DdSkeleton, DdEmptyState, DdStep, DdSteps,
91
+ DdModal, DdActionSheet, DdToast, DdAlert, DdLoading,
92
+ DdDialog, DdOverlay, DdPopup, DdPopover, DdPopoverItem,
93
+ DdSwipeAction, DdSwipe, DdSwipeItem, DdPullRefresh, DdLoadmore,
94
+ DdCapsuleButton, DdMiniProgramNavbar,
95
+ }
96
+
97
+ export function install(app: App) {
98
+ Object.entries(components).forEach(([name, comp]) => {
99
+ app.component(name, comp)
100
+ })
101
+ }
102
+
103
+ export default { install }
104
+
105
+ // 全量具名导出
106
+ export {
107
+ components,
108
+ DdButton, DdInput, DdSwitch, DdCheckbox, DdRadio,
109
+ DdSearchBar, DdSlider, DdStepper, DdDatePicker, DdField,
110
+ DdPicker, DdRate, DdUpload, DdIcon,
111
+ DdNavigation, DdTopNavbar, DdSegmentedTab, DdSwipeableTab,
112
+ DdDrawer, DdTabbar, DdTabbarItem, DdBacktop,
113
+ DdCollapse, DdCollapseItem, DdDropdownMenu, DdDropdownItem,
114
+ DdCard, DdRoomCard, DdFeatureGrid, DdSticky,
115
+ DdTag, DdStatCard, DdChampionCard, DdAvatar, DdBadge,
116
+ DdListCell, DdCell, DdCellGroup, DdCountDown, DdDivider,
117
+ DdImage, DdProgress, DdSkeleton, DdEmptyState, DdStep, DdSteps,
118
+ DdModal, DdActionSheet, DdToast, DdAlert, DdLoading,
119
+ DdDialog, DdOverlay, DdPopup, DdPopover, DdPopoverItem,
120
+ DdSwipeAction, DdSwipe, DdSwipeItem, DdPullRefresh, DdLoadmore,
121
+ DdCapsuleButton, DdMiniProgramNavbar,
122
+ }
123
+
124
+ export * from './libs/utils'
125
+
126
+ // 图标元数据(供 demo/文档消费,与 dd-icon.vue 内 SCSS &-- 规则保持一致)
127
+ export { iconNames, iconGroups } from './components/dd-icon/dd-icon.vue'
package/libs/utils.ts ADDED
@@ -0,0 +1,106 @@
1
+ // ============================================================
2
+ // DidaoUI-uniapp Utility Functions
3
+ // ============================================================
4
+
5
+ // 平台检测
6
+ // ponytail: vue-tsc 不识别 #ifdef 注释,四个 const 块会被视为重复声明,
7
+ // 故改为单次 let 声明 + 条件编译赋值。代价:失去编译期常量的 tree-shake
8
+ // (升级路径:改用 process.env.UNI_PLATFORM 判定)。
9
+ export let isH5 = false
10
+ export let isMP = false
11
+ export let isMPWeixin = false
12
+ export let isMPToutiao = false
13
+ export let isApp = false
14
+
15
+ // #ifdef H5
16
+ isH5 = true
17
+ // #endif
18
+ // #ifdef MP-WEIXIN
19
+ isMP = true
20
+ isMPWeixin = true
21
+ // #endif
22
+ // #ifdef MP-TOUTIAO
23
+ isMP = true
24
+ isMPToutiao = true
25
+ // #endif
26
+ // #ifdef APP-PLUS
27
+ isApp = true
28
+ // #endif
29
+
30
+ // 防抖
31
+ export function debounce<T extends (...args: any[]) => any>(
32
+ fn: T,
33
+ delay = 300
34
+ ): (...args: Parameters<T>) => void {
35
+ let timer: ReturnType<typeof setTimeout> | null = null
36
+ return (...args: Parameters<T>) => {
37
+ if (timer) clearTimeout(timer)
38
+ timer = setTimeout(() => fn(...args), delay)
39
+ }
40
+ }
41
+
42
+ // 节流
43
+ export function throttle<T extends (...args: any[]) => any>(
44
+ fn: T,
45
+ delay = 300
46
+ ): (...args: Parameters<T>) => void {
47
+ let last = 0
48
+ return (...args: Parameters<T>) => {
49
+ const now = Date.now()
50
+ if (now - last >= delay) {
51
+ last = now
52
+ fn(...args)
53
+ }
54
+ }
55
+ }
56
+
57
+ // rpx → px (仅 H5 需要)
58
+ export function rpx2px(rpx: number): number {
59
+ // #ifdef H5
60
+ const screenWidth = window.screen.width
61
+ return (rpx / 750) * screenWidth
62
+ // #endif
63
+ // #ifndef H5
64
+ return rpx
65
+ // #endif
66
+ }
67
+
68
+ // 获取状态栏高度
69
+ export function getStatusBarHeight(): number {
70
+ // #ifdef H5
71
+ return 0
72
+ // #endif
73
+ // ponytail: 运行时兜底 —— 条件编译失效时(如 H5 构建配置错误),
74
+ // 防止走到 MP/APP 分支拿到非零 statusBarHeight
75
+ // #ifndef H5
76
+ const sysInfo = uni.getWindowInfo()
77
+ return sysInfo.statusBarHeight || 20
78
+ // #endif
79
+ }
80
+
81
+ // 获取胶囊按钮位置信息 (仅微信小程序)
82
+ export function getMenuButtonBoundingClientRect() {
83
+ // #ifdef MP-WEIXIN
84
+ return uni.getMenuButtonBoundingClientRect()
85
+ // #endif
86
+ // #ifndef MP-WEIXIN
87
+ return null
88
+ // #endif
89
+ }
90
+
91
+ // 查询节点尺寸
92
+ export function getRect(selector: string): Promise<UniApp.NodeInfo> {
93
+ return new Promise((resolve) => {
94
+ uni.createSelectorQuery()
95
+ .select(selector)
96
+ .boundingClientRect((rect) => {
97
+ resolve(rect as UniApp.NodeInfo)
98
+ })
99
+ .exec()
100
+ })
101
+ }
102
+
103
+ // 获取事件值 (跨端兼容)
104
+ export function getEventValue(e: any): string {
105
+ return e?.detail?.value ?? e?.target?.value ?? ''
106
+ }
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@didaoktv/didaoui-uniapp",
3
+ "version": "1.0.0",
4
+ "description": "帝到KTV UniApp 组件库",
5
+ "main": "index.ts",
6
+ "types": "index.ts",
7
+ "exports": {
8
+ ".": "./index.ts",
9
+ "./uni.scss": "./uni.scss",
10
+ "./scss/variables": "./scss/_variables.scss",
11
+ "./scss/mixins": "./scss/_mixins.scss",
12
+ "./scss/functions": "./scss/_functions.scss",
13
+ "./components/*": "./components/*"
14
+ },
15
+ "files": [
16
+ "components/",
17
+ "scss/",
18
+ "libs/",
19
+ "index.ts",
20
+ "uni.scss"
21
+ ],
22
+ "scripts": {
23
+ "dev:h5": "cd ../DidaoUI-uniapp-docs/h5-demo && npm run dev:h5",
24
+ "build:docs": "cd ../DidaoUI-uniapp-docs && npm run build",
25
+ "type-check": "vue-tsc --noEmit",
26
+ "prepublishOnly": "node -e \"const p=require('./package.json');if(p.publishConfig&&p.publishConfig.access==='public'){process.exit(0)}console.error('publishConfig.access must be public');process.exit(1)\""
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "peerDependencies": {
32
+ "vue": "^3.4.0"
33
+ },
34
+ "devDependencies": {
35
+ "vue": "^3.4.0",
36
+ "vue-tsc": "^2.0.0",
37
+ "typescript": "^5.4.0",
38
+ "sass": "^1.70.0",
39
+ "@dcloudio/types": "^3.4.8"
40
+ },
41
+ "keywords": [
42
+ "uniapp",
43
+ "vue3",
44
+ "ui",
45
+ "component-library",
46
+ "typescript",
47
+ "didaoktv"
48
+ ],
49
+ "license": "MIT",
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "https://github.com/didaoktv/didaoui-uniapp"
53
+ },
54
+ "sideEffects": [
55
+ "*.scss",
56
+ "*.css"
57
+ ]
58
+ }
@@ -0,0 +1,68 @@
1
+ // ============================================================
2
+ // DidaoUI-uniapp SCSS Functions
3
+ // ============================================================
4
+
5
+ // px → rpx 转换 (750rpx = 375px 屏幕宽度)
6
+ @function dd-px-to-rpx($px) {
7
+ @return $px * 2rpx;
8
+ }
9
+
10
+ // 颜色变暗
11
+ @function dd-darken($color, $amount) {
12
+ @return darken($color, $amount);
13
+ }
14
+
15
+ // 颜色变亮
16
+ @function dd-lighten($color, $amount) {
17
+ @return lighten($color, $amount);
18
+ }
19
+
20
+ // 色阶获取
21
+ @function dd-color($name, $level: 500) {
22
+ $map: (
23
+ primary: (
24
+ 50: $dd-primary-50, 100: $dd-primary-100, 200: $dd-primary-200,
25
+ 300: $dd-primary-300, 400: $dd-primary-400, 500: $dd-primary-500,
26
+ 600: $dd-primary-600, 700: $dd-primary-700, 800: $dd-primary-800,
27
+ 900: $dd-primary-900,
28
+ ),
29
+ accent: (
30
+ 50: $dd-accent-50, 100: $dd-accent-100, 200: $dd-accent-200,
31
+ 300: $dd-accent-300, 400: $dd-accent-400, 500: $dd-accent-500,
32
+ 600: $dd-accent-600, 700: $dd-accent-700, 800: $dd-accent-800,
33
+ 900: $dd-accent-900,
34
+ ),
35
+ neutral: (
36
+ 50: $dd-neutral-50, 100: $dd-neutral-100, 200: $dd-neutral-200,
37
+ 300: $dd-neutral-300, 400: $dd-neutral-400, 500: $dd-neutral-500,
38
+ 600: $dd-neutral-600, 700: $dd-neutral-700, 800: $dd-neutral-800,
39
+ 900: $dd-neutral-900,
40
+ ),
41
+ success: (
42
+ 50: $dd-success-50, 100: $dd-success-100, 200: $dd-success-200,
43
+ 300: $dd-success-300, 400: $dd-success-400, 500: $dd-success-500,
44
+ 600: $dd-success-600, 700: $dd-success-700, 800: $dd-success-800,
45
+ 900: $dd-success-900,
46
+ ),
47
+ warning: (
48
+ 50: $dd-warning-50, 100: $dd-warning-100, 200: $dd-warning-200,
49
+ 300: $dd-warning-300, 400: $dd-warning-400, 500: $dd-warning-500,
50
+ 600: $dd-warning-600, 700: $dd-warning-700, 800: $dd-warning-800,
51
+ 900: $dd-warning-900,
52
+ ),
53
+ error: (
54
+ 50: $dd-error-50, 100: $dd-error-100, 200: $dd-error-200,
55
+ 300: $dd-error-300, 400: $dd-error-400, 500: $dd-error-500,
56
+ 600: $dd-error-600, 700: $dd-error-700, 800: $dd-error-800,
57
+ 900: $dd-error-900,
58
+ ),
59
+ info: (
60
+ 50: $dd-info-50, 100: $dd-info-100, 200: $dd-info-200,
61
+ 300: $dd-info-300, 400: $dd-info-400, 500: $dd-info-500,
62
+ 600: $dd-info-600, 700: $dd-info-700, 800: $dd-info-800,
63
+ 900: $dd-info-900,
64
+ ),
65
+ );
66
+ $group: map-get($map, $name);
67
+ @return map-get($group, $level);
68
+ }
@@ -0,0 +1,154 @@
1
+ // ============================================================
2
+ // DidaoUI-uniapp SCSS Mixins
3
+ // ============================================================
4
+
5
+ // 玻璃拟态 (H5: backdrop-filter; MP: 降级为 solid bg)
6
+ @mixin dd-glass($intensity: default) {
7
+ $blur: $dd-glass-blur;
8
+ @if $intensity == sm { $blur: $dd-glass-blur-sm; }
9
+ @else if $intensity == md { $blur: $dd-glass-blur-md; }
10
+ @else if $intensity == lg { $blur: $dd-glass-blur-lg; }
11
+ background: $dd-glass-bg;
12
+ border: 1px solid $dd-glass-border;
13
+ /* #ifdef H5 */
14
+ backdrop-filter: blur($blur);
15
+ -webkit-backdrop-filter: blur($blur);
16
+ /* #endif */
17
+ }
18
+
19
+ @mixin dd-glass-strong {
20
+ background: $dd-glass-bg-strong;
21
+ border: 1px solid $dd-glass-border;
22
+ /* #ifdef H5 */
23
+ backdrop-filter: blur($dd-glass-blur);
24
+ -webkit-backdrop-filter: blur($dd-glass-blur);
25
+ /* #endif */
26
+ }
27
+
28
+ // 发光阴影 — 支持 size: sm / md / lg
29
+ @mixin dd-glow($color: gold, $size: md) {
30
+ $shadows: (
31
+ gold-sm: $dd-shadow-glow-gold-sm,
32
+ gold-md: $dd-shadow-glow-gold-md,
33
+ gold-lg: $dd-shadow-glow-gold-lg,
34
+ blue-sm: $dd-shadow-glow-blue-sm,
35
+ blue-md: $dd-shadow-glow-blue-md,
36
+ blue-lg: $dd-shadow-glow-blue-lg,
37
+ success-sm: $dd-shadow-glow-success-sm,
38
+ success-md: $dd-shadow-glow-success-md,
39
+ success-lg: $dd-shadow-glow-success-lg,
40
+ warning-sm: $dd-shadow-glow-warning-sm,
41
+ warning-md: $dd-shadow-glow-warning-md,
42
+ warning-lg: $dd-shadow-glow-warning-lg,
43
+ error-sm: $dd-shadow-glow-error-sm,
44
+ error-md: $dd-shadow-glow-error-md,
45
+ error-lg: $dd-shadow-glow-error-lg,
46
+ info-sm: $dd-shadow-glow-info-sm,
47
+ info-md: $dd-shadow-glow-info-md,
48
+ info-lg: $dd-shadow-glow-info-lg,
49
+ vip-sm: $dd-shadow-glow-vip-sm,
50
+ vip-md: $dd-shadow-glow-vip-md,
51
+ vip-lg: $dd-shadow-glow-vip-lg,
52
+ );
53
+ $key: $color + '-' + $size;
54
+ box-shadow: map-get($shadows, $key);
55
+ }
56
+
57
+ // 文字渐变
58
+ @mixin dd-text-gradient($color: gold) {
59
+ $gradients: (
60
+ gold: $dd-gradient-text-gold,
61
+ 'gold-light': $dd-gradient-text-gold-light,
62
+ blue: $dd-gradient-text-blue,
63
+ );
64
+ background: map-get($gradients, $color);
65
+ -webkit-background-clip: text;
66
+ -webkit-text-fill-color: transparent;
67
+ background-clip: text;
68
+ }
69
+
70
+ // 文本溢出省略
71
+ @mixin dd-ellipsis($lines: 1) {
72
+ @if $lines == 1 {
73
+ overflow: hidden;
74
+ text-overflow: ellipsis;
75
+ white-space: nowrap;
76
+ } @else {
77
+ display: -webkit-box;
78
+ -webkit-box-orient: vertical;
79
+ -webkit-line-clamp: $lines;
80
+ overflow: hidden;
81
+ }
82
+ }
83
+
84
+ // 安全区域
85
+ @mixin dd-safe-area-top {
86
+ padding-top: var(--status-bar-height, 20px);
87
+ }
88
+
89
+ @mixin dd-safe-area-bottom {
90
+ padding-bottom: constant(safe-area-inset-bottom);
91
+ padding-bottom: env(safe-area-inset-bottom);
92
+ }
93
+
94
+ // 1px 边框 (retina)
95
+ @mixin dd-hairline-bottom($color: $dd-border-default) {
96
+ position: relative;
97
+ &::after {
98
+ content: '';
99
+ position: absolute;
100
+ left: 0;
101
+ right: 0;
102
+ bottom: 0;
103
+ height: 1px;
104
+ background: $color;
105
+ transform: scaleY(0.5);
106
+ transform-origin: 0 100%;
107
+ }
108
+ }
109
+
110
+ @mixin dd-hairline-top($color: $dd-border-default) {
111
+ position: relative;
112
+ &::before {
113
+ content: '';
114
+ position: absolute;
115
+ left: 0;
116
+ right: 0;
117
+ top: 0;
118
+ height: 1px;
119
+ background: $color;
120
+ transform: scaleY(0.5);
121
+ transform-origin: 0 0;
122
+ }
123
+ }
124
+
125
+ // flex 居中
126
+ @mixin dd-flex-center {
127
+ display: flex;
128
+ align-items: center;
129
+ justify-content: center;
130
+ }
131
+
132
+ @mixin dd-flex-between {
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: space-between;
136
+ }
137
+
138
+ // 过渡:arglist 直传
139
+ // 支持单属性 dd-transition(transform 0.3s ease) 与多属性
140
+ // dd-transition(opacity 0.3s, transform 0.3s);旧的位置参数写法
141
+ // (transform, 0.3s, ease) 会把第二段时间值当成 CSS delay,造成隐性延时
142
+ @mixin dd-transition($args...) {
143
+ @if length($args) == 0 {
144
+ transition: all 0.3s linear;
145
+ } @else {
146
+ transition: $args;
147
+ }
148
+ }
149
+
150
+ // 禁止点击
151
+ @mixin dd-no-touch {
152
+ pointer-events: none;
153
+ user-select: none;
154
+ }