@ecolovo/uniapp-components 1.0.10 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +202 -66
- package/components/aspect/aspect.vue +24 -15
- package/components/badge/badge.scss +20 -0
- package/components/badge/badge.vue +49 -40
- package/components/button/button.scss +15 -0
- package/components/button/button.vue +121 -177
- package/components/checkbox/checkbox.scss +10 -0
- package/components/checkbox/checkbox.vue +118 -146
- package/components/checkbox-group/checkbox-group.vue +79 -85
- package/components/checkbox-group2/checkbox-group2.vue +111 -107
- package/components/checkbox-group2/checkbox2.vue +104 -0
- package/components/data-list/data-list.scss +9 -0
- package/components/data-list/data-list.vue +70 -79
- package/components/date-picker/date-picker-view.vue +125 -124
- package/components/date-picker/date-picker.vue +145 -146
- package/components/dialog/dialog-content.vue +39 -47
- package/components/dialog/dialog.scss +11 -0
- package/components/dialog/dialog.vue +125 -138
- package/components/dropdown/dropdown.scss +11 -0
- package/components/dropdown/dropdown.vue +55 -97
- package/components/empty/empty.scss +14 -0
- package/components/empty/empty.vue +42 -41
- package/components/flex/flex.vue +45 -54
- package/components/form/form.vue +29 -24
- package/components/form-item/form-item.scss +11 -0
- package/components/form-item/form-item.vue +43 -40
- package/components/icon/icon.vue +70 -85
- package/components/image/image.vue +35 -38
- package/components/input/input.vue +65 -79
- package/components/input/password-input.vue +34 -42
- package/components/list-page/list-page.vue +73 -99
- package/components/load-more/load-more.scss +12 -0
- package/components/load-more/load-more.vue +29 -29
- package/components/loading/animations/loading-animation1.vue +8 -8
- package/components/loading/animations/loading-animation2.vue +8 -9
- package/components/loading/animations/loading-animation3.vue +11 -11
- package/components/loading/animations/loading-animation4.vue +8 -8
- package/components/loading/loading.vue +19 -20
- package/components/message-box/message-box.vue +59 -41
- package/components/number-dialog/number-dialog.scss +9 -0
- package/components/number-dialog/number-dialog.vue +209 -204
- package/components/number-input/number-input.scss +9 -0
- package/components/number-input/number-input.vue +233 -232
- package/components/numpad/numpad.scss +9 -0
- package/components/numpad/numpad.vue +133 -150
- package/components/page/page-body.scss +15 -0
- package/components/page/page-body.vue +137 -119
- package/components/page/page-footer.scss +13 -0
- package/components/page/page-footer.vue +31 -33
- package/components/page/page-header.scss +17 -0
- package/components/page/page-header.vue +89 -94
- package/components/page/page.scss +9 -0
- package/components/page/page.vue +105 -81
- package/components/picker/picker-popup.vue +218 -209
- package/components/picker/picker.vue +99 -104
- package/components/popover/popover-content.vue +54 -63
- package/components/popover/popover-mask.vue +63 -63
- package/components/popover/popover.scss +28 -0
- package/components/popover/popover.vue +49 -47
- package/components/popup/popup-content.vue +49 -53
- package/components/popup/popup.scss +11 -0
- package/components/popup/popup.vue +117 -132
- package/components/price/price.scss +20 -0
- package/components/price/price.vue +31 -42
- package/components/search/search.scss +12 -0
- package/components/search/search.vue +93 -117
- package/components/searching/searching.vue +33 -40
- package/components/selector/selector.vue +43 -48
- package/components/switch/switch.scss +12 -0
- package/components/switch/switch.vue +99 -96
- package/components/tab/tab.scss +19 -0
- package/components/tab/tab.vue +151 -145
- package/components/textarea/textarea.vue +104 -101
- package/composable/component-name.d.ts +2 -0
- package/composable/component-name.js +8 -0
- package/composable/component-name.ts +10 -0
- package/configs/index.d.ts +25 -10
- package/configs/index.js +14 -23
- package/configs/index.ts +82 -0
- package/easyCom.d.ts +9 -0
- package/easyCom.js +1 -2
- package/easyCom.ts +31 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/index.ts +1 -0
- package/init.d.ts +4 -7
- package/init.js +5 -4
- package/init.ts +34 -0
- package/package.json +14 -4
- package/styles/utils/css-var.scss +12 -15
- package/styles/utils/ellipsis.scss +0 -7
- package/styles/utils/z-index.scss +1 -1
- package/styles/var/component.scss +21 -245
- package/utils/date.d.ts +47 -0
- package/utils/date.js +23 -43
- package/utils/date.ts +153 -0
- package/utils/freezeDeep.d.ts +1 -0
- package/utils/freezeDeep.js +4 -14
- package/utils/freezeDeep.ts +9 -0
- package/utils/price.d.ts +24 -0
- package/utils/price.js +14 -8
- package/utils/price.ts +57 -0
- package/utils/round.d.ts +2 -0
- package/utils/round.js +2 -14
- package/utils/round.ts +11 -0
- package/utils/windowInfo.d.ts +24 -0
- package/utils/windowInfo.js +8 -36
- package/utils/windowInfo.ts +50 -0
- package/components/checkbox-group2/checkbox.vue +0 -109
- package/components/datetime-picker/datetime-picker-view.vue +0 -209
- package/components/datetime-picker/datetime-picker.vue +0 -235
- package/components/form/mixin.js +0 -13
- package/components/list-page/list-page.js +0 -10
- package/components/table/table.vue +0 -112
- package/components/time-picker/time-picker-view.vue +0 -127
- package/components/time-picker/time-picker.vue +0 -140
- package/components/uploader/download.js +0 -81
- package/components/uploader/file-uploader.vue +0 -52
- package/components/uploader/files.js +0 -225
- package/components/uploader/media-uploader.vue +0 -189
- package/components/uploader/mixin.js +0 -171
- package/components/uploader/uni.js +0 -38
- package/components/uploader/upload-button.vue +0 -29
- package/components/uploader/uploader copy.vue +0 -547
- package/components/uploader/uploader.vue +0 -117
- package/mixins/componentName.js +0 -32
- package/mixins/listPage.js +0 -1
- package/mixins/windowInfo.js +0 -1
- package/utils/fileSize.js +0 -39
- package/utils/floor.js +0 -20
package/README.md
CHANGED
|
@@ -1,117 +1,253 @@
|
|
|
1
1
|
# @ecolovo/uniapp-components
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
UniApp **Vue3** 组件库。
|
|
4
4
|
|
|
5
|
+
本项目是为基于 `cli` 脚手架创建的项目开发的,未在 HBuilderX 项目中实践,请自行验证是否可以正常使用。
|
|
5
6
|
|
|
6
|
-
##
|
|
7
|
+
## 安装
|
|
7
8
|
|
|
8
9
|
使用 npm / yarn 安装
|
|
9
10
|
|
|
10
11
|
```bash
|
|
11
|
-
|
|
12
|
+
npm install @ecolovo/uniapp-components
|
|
12
13
|
```
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
## 组件库的配置
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
npm install uni-pages-hot-modules --save-dev
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## Usage
|
|
21
|
-
|
|
22
|
-
### 1. 配置 `vue.config.js` 文件
|
|
23
|
-
|
|
24
|
-
```javascript
|
|
25
|
-
// vue.config.js
|
|
26
|
-
|
|
27
|
-
module.exports = {
|
|
28
|
-
// configs...
|
|
29
|
-
transpileDependencies: ['@ecolovo/uniapp-components'],
|
|
30
|
-
// other configs...
|
|
31
|
-
}
|
|
32
|
-
```
|
|
17
|
+
使用前,请按照以下步骤进行一些必要的配置。
|
|
33
18
|
|
|
34
|
-
###
|
|
19
|
+
### 1. 在 `src/main.js` 文件中初始化组件库
|
|
35
20
|
|
|
36
21
|
```javascript
|
|
37
22
|
// src/main.js
|
|
38
23
|
|
|
39
|
-
import init from '@ecolovo/uniapp-components
|
|
24
|
+
import { init } from '@ecolovo/uniapp-components';
|
|
40
25
|
|
|
41
26
|
init({
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
27
|
+
// 配置组件前缀
|
|
28
|
+
// 在使用时加上前缀,如 button 组件,使用 <ui-button>
|
|
29
|
+
componentPrefix: 'ui',
|
|
45
30
|
});
|
|
46
31
|
```
|
|
47
32
|
|
|
48
|
-
###
|
|
33
|
+
### 2. 配置 `src/pages.js` 文件
|
|
49
34
|
|
|
50
35
|
```javascript
|
|
51
36
|
// src/pages.js
|
|
52
37
|
|
|
53
38
|
const mergeWith = require('lodash/mergeWith');
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
module.exports =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (Array.isArray(objValue)) {
|
|
67
|
-
return objValue.concat(srcValue);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
);
|
|
71
|
-
});
|
|
39
|
+
const componentEasyCom = require('@ecolovo/uniapp-components/easyCom').default;
|
|
40
|
+
const pageJson = require('./pages-config/index');
|
|
41
|
+
|
|
42
|
+
module.exports = mergeWith(
|
|
43
|
+
pageJson,
|
|
44
|
+
componentEasyCom('ui'), // 填入和步骤 2 中同样的前缀
|
|
45
|
+
function (objValue, srcValue) {
|
|
46
|
+
if (Array.isArray(objValue)) {
|
|
47
|
+
return objValue.concat(srcValue);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
);
|
|
72
51
|
```
|
|
73
52
|
|
|
74
|
-
|
|
53
|
+
> `uni-pages-hot-modules` 库在 Vue3.x 版本中无法正常使用,可使用以下脚本进行 `pages.js` 的动态配置
|
|
54
|
+
>
|
|
55
|
+
> ```javascript
|
|
56
|
+
> // scripts/build.js
|
|
57
|
+
>
|
|
58
|
+
> /* eslint-disable no-console, @typescript-eslint/no-require-imports */
|
|
59
|
+
>
|
|
60
|
+
> const fs = require('fs');
|
|
61
|
+
> const path = require('path');
|
|
62
|
+
> const srcDir = path.resolve(__dirname, '../src');
|
|
63
|
+
> const pagesJsPath = path.join(srcDir, 'pages.js');
|
|
64
|
+
> const pagesConfigDir = path.join(srcDir, 'pages-config');
|
|
65
|
+
> const mainTsPath = path.join(srcDir, 'main.ts');
|
|
66
|
+
>
|
|
67
|
+
> // 1. Inject environment variables before pages.js is evaluated
|
|
68
|
+
> const platformArgIndex = process.argv.indexOf('-p');
|
|
69
|
+
> const platform = platformArgIndex !== -1 ? process.argv[platformArgIndex + 1] : 'h5';
|
|
70
|
+
> process.env.UNI_PLATFORM = platform;
|
|
71
|
+
>
|
|
72
|
+
> const envPath = path.resolve(__dirname, '../.env');
|
|
73
|
+
> if (fs.existsSync(envPath)) {
|
|
74
|
+
> const envContent = fs.readFileSync(envPath, 'utf-8');
|
|
75
|
+
> for (const line of envContent.split(/\r?\n/)) {
|
|
76
|
+
> const trimmed = line.trim();
|
|
77
|
+
> if (!trimmed || trimmed.startsWith('#')) continue;
|
|
78
|
+
> const eqIndex = trimmed.indexOf('=');
|
|
79
|
+
> if (eqIndex !== -1) {
|
|
80
|
+
> const key = trimmed.slice(0, eqIndex).trim();
|
|
81
|
+
> let value = trimmed.slice(eqIndex + 1).trim();
|
|
82
|
+
> if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
83
|
+
> value = value.slice(1, -1);
|
|
84
|
+
> }
|
|
85
|
+
> process.env[key] = value;
|
|
86
|
+
> }
|
|
87
|
+
> }
|
|
88
|
+
> }
|
|
89
|
+
>
|
|
90
|
+
> // 2. Evaluate pages.js to generate config in memory
|
|
91
|
+
> Object.keys(require.cache).forEach((key) => {
|
|
92
|
+
> if (key.includes('pages-config') || key.endsWith(path.join('src', 'pages.js'))) {
|
|
93
|
+
> delete require.cache[key];
|
|
94
|
+
> }
|
|
95
|
+
> });
|
|
96
|
+
> const pagesConfig = require(pagesJsPath);
|
|
97
|
+
> let pagesJsonStr = JSON.stringify(pagesConfig);
|
|
98
|
+
>
|
|
99
|
+
> // 3. Patch fs.readFileSync to intercept pages.json reads
|
|
100
|
+
> const originalReadFileSync = fs.readFileSync;
|
|
101
|
+
> fs.readFileSync = function (...args) {
|
|
102
|
+
> const filePath = typeof args[0] === 'string' ? path.resolve(args[0]) : '';
|
|
103
|
+
> if (filePath.endsWith('pages.json')) {
|
|
104
|
+
> const options = args[1];
|
|
105
|
+
> const encoding = typeof options === 'string' ? options : options && options.encoding;
|
|
106
|
+
> if (encoding === 'utf8' || encoding === 'utf-8') {
|
|
107
|
+
> return pagesJsonStr;
|
|
108
|
+
> }
|
|
109
|
+
> return Buffer.from(pagesJsonStr, 'utf8');
|
|
110
|
+
> }
|
|
111
|
+
> return originalReadFileSync.apply(this, args);
|
|
112
|
+
> };
|
|
113
|
+
>
|
|
114
|
+
> // 4. Replace parsePagesJsonOnce with non-cached version, so rebuilds pick up new config
|
|
115
|
+
> const pagesModulePath = require.resolve('@dcloudio/uni-cli-shared/dist/json/pages');
|
|
116
|
+
> delete require.cache[pagesModulePath];
|
|
117
|
+
> const pagesModule = require(pagesModulePath);
|
|
118
|
+
> const originalParsePagesJson = pagesModule.parsePagesJson;
|
|
119
|
+
> pagesModule.parsePagesJsonOnce = function (inputDir, platform) {
|
|
120
|
+
> return originalParsePagesJson(inputDir, platform);
|
|
121
|
+
> };
|
|
122
|
+
>
|
|
123
|
+
> // 5. Set up file watcher for HMR (watch mode only)
|
|
124
|
+
> const hasBuildCommand = process.argv.includes('build');
|
|
125
|
+
> const hasWatch = process.argv.includes('-w') || process.argv.includes('--watch');
|
|
126
|
+
> const isDevMode = !hasBuildCommand || hasWatch;
|
|
127
|
+
>
|
|
128
|
+
> if (isDevMode && fs.existsSync(pagesConfigDir)) {
|
|
129
|
+
> try {
|
|
130
|
+
> const chokidar = require('chokidar');
|
|
131
|
+
> const watcher = chokidar.watch(pagesConfigDir, {
|
|
132
|
+
> ignoreInitial: true,
|
|
133
|
+
> awaitWriteFinish: { stabilityThreshold: 300 },
|
|
134
|
+
> });
|
|
135
|
+
> watcher.on('change', (file) => {
|
|
136
|
+
> console.log(`[HMR] Pages config changed: ${path.relative(srcDir, file)}`);
|
|
137
|
+
>
|
|
138
|
+
> // Clear require cache for config modules
|
|
139
|
+
> Object.keys(require.cache).forEach((key) => {
|
|
140
|
+
> if (key.includes('pages-config') || key.endsWith(path.join('src', 'pages.js'))) {
|
|
141
|
+
> delete require.cache[key];
|
|
142
|
+
> }
|
|
143
|
+
> });
|
|
144
|
+
>
|
|
145
|
+
> // Re-evaluate pages.js and update in-memory config
|
|
146
|
+
> const newConfig = require(pagesJsPath);
|
|
147
|
+
> pagesJsonStr = JSON.stringify(newConfig);
|
|
148
|
+
>
|
|
149
|
+
> // Touch main.ts to trigger Rollup rebuild
|
|
150
|
+
> try {
|
|
151
|
+
> const now = new Date();
|
|
152
|
+
> fs.utimesSync(mainTsPath, now, now);
|
|
153
|
+
> } catch (_) {
|
|
154
|
+
> // Fallback: touch any .vue file
|
|
155
|
+
> const fallback = path.join(srcDir, 'App.vue');
|
|
156
|
+
> if (fs.existsSync(fallback)) {
|
|
157
|
+
> const now = new Date();
|
|
158
|
+
> fs.utimesSync(fallback, now, now);
|
|
159
|
+
> }
|
|
160
|
+
> }
|
|
161
|
+
> });
|
|
162
|
+
> } catch {
|
|
163
|
+
> console.warn('[HMR] chokidar not available, pages hot reload disabled');
|
|
164
|
+
> }
|
|
165
|
+
> }
|
|
166
|
+
>
|
|
167
|
+
> // 6. Run the uni CLI
|
|
168
|
+
> require('@dcloudio/vite-plugin-uni/bin/uni');
|
|
169
|
+
> ```
|
|
170
|
+
>
|
|
171
|
+
> package.json 中的脚本需要替换,如 `dev:mp-weixin` 由原来的 `uni -p mp-weixin` 替换为 `node scripts/build.js -p mp-weixin` 。
|
|
172
|
+
|
|
173
|
+
### 3. 配置样式
|
|
75
174
|
|
|
76
175
|
#### 全局样式
|
|
77
176
|
|
|
78
|
-
```
|
|
177
|
+
```vue
|
|
79
178
|
<!-- App.vue -->
|
|
80
179
|
|
|
81
180
|
<style lang="scss">
|
|
181
|
+
// 引入组件库全局样式
|
|
82
182
|
@use '@ecolovo/uniapp-components/styles/global';
|
|
83
183
|
</style>
|
|
84
184
|
```
|
|
85
185
|
|
|
86
|
-
####
|
|
186
|
+
#### 自定义样式
|
|
87
187
|
|
|
88
|
-
```
|
|
188
|
+
```scss
|
|
89
189
|
/* src/styles/prepend.scss */
|
|
90
190
|
|
|
191
|
+
// 修改全局组件前缀与主题等全局样式
|
|
91
192
|
@forward '@ecolovo/uniapp-components/styles/var/theme' with (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
193
|
+
$component-prefix: 'ui',
|
|
194
|
+
// 推荐修改为与组件前缀一致
|
|
195
|
+
$themes:
|
|
196
|
+
(
|
|
197
|
+
primary: #d92e20,
|
|
198
|
+
)
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// 修改组件默认样式
|
|
202
|
+
@forward '@ecolovo/uniapp-components/styles/var/component' with (
|
|
203
|
+
$badge: (
|
|
204
|
+
background: #d92e20,
|
|
205
|
+
)
|
|
96
206
|
);
|
|
97
207
|
|
|
98
208
|
@forward '@ecolovo/uniapp-components/styles';
|
|
99
209
|
```
|
|
100
210
|
|
|
101
211
|
```javascript
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
const sass = require('sass');
|
|
105
|
-
|
|
212
|
+
// vite.config.ts
|
|
106
213
|
module.exports = {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// other configs...
|
|
214
|
+
// other configs...
|
|
215
|
+
css: {
|
|
216
|
+
preprocessorOptions: {
|
|
217
|
+
scss: {
|
|
218
|
+
additionalData: '@use "@/styles/prepend.scss" as *;',
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
},
|
|
116
222
|
};
|
|
117
223
|
```
|
|
224
|
+
|
|
225
|
+
### 4. 全局可用的 css 变量
|
|
226
|
+
|
|
227
|
+
以下变量的访问必须为 `<ui-page>` 的内部元素。
|
|
228
|
+
|
|
229
|
+
```scss
|
|
230
|
+
// 顶部安全区高度
|
|
231
|
+
--safe-area-top: 30px;
|
|
232
|
+
|
|
233
|
+
// 底部安全区高度
|
|
234
|
+
--safe-area-bottom: 30px;
|
|
235
|
+
|
|
236
|
+
// 页面头部上边缘相较于顶部的距离,原则上等于 `--safe-area-top`
|
|
237
|
+
--page-header-top: 30px;
|
|
238
|
+
|
|
239
|
+
// 页面头部高度
|
|
240
|
+
--page-header-height: 44px;
|
|
241
|
+
|
|
242
|
+
// 页面头部下边缘相较于顶部的距离,原则上等于 `--page-header-top` + `--page-header-height`
|
|
243
|
+
--page-header-bottom: 74px;
|
|
244
|
+
|
|
245
|
+
// 小程序胶囊按钮宽度(实际为胶囊按钮最左侧到页面右边的距离)
|
|
246
|
+
--menu-button-width: calc(100vw - 280px);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
> 上述变量后的值仅供参考,以实际值为准
|
|
250
|
+
|
|
251
|
+
## 使用
|
|
252
|
+
|
|
253
|
+
请阅读 [**使用文档**](./docs/index.md) 。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view :class="
|
|
3
|
-
<view :class="$style['Aspect--content-wrapper']" :style="
|
|
2
|
+
<view :class="[...classNames, $style['Aspect']]">
|
|
3
|
+
<view :class="$style['Aspect--content-wrapper']" :style="inlineStyle">
|
|
4
4
|
<view :class="$style['Aspect--content']" @click="$emit('click')">
|
|
5
5
|
<slot></slot>
|
|
6
6
|
</view>
|
|
@@ -8,24 +8,33 @@
|
|
|
8
8
|
</view>
|
|
9
9
|
</template>
|
|
10
10
|
|
|
11
|
-
<script>
|
|
12
|
-
import
|
|
11
|
+
<script lang="ts" setup>
|
|
12
|
+
import { computed } from 'vue';
|
|
13
|
+
import useClassNames from '../../composable/component-name';
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
name: 'Aspect',
|
|
15
|
+
defineOptions({
|
|
16
16
|
options: {
|
|
17
|
-
virtualHost: true,
|
|
18
17
|
styleIsolation: 'shared',
|
|
18
|
+
virtualHost: true,
|
|
19
19
|
},
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const classNames = useClassNames('aspect');
|
|
23
|
+
|
|
24
|
+
type _Props = {
|
|
25
|
+
/** 图标名 */
|
|
26
|
+
ratio?: string | number;
|
|
28
27
|
};
|
|
28
|
+
|
|
29
|
+
const props = withDefaults(defineProps<_Props>(), {
|
|
30
|
+
ratio: 1,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
defineEmits<{
|
|
34
|
+
(event: 'click'): void;
|
|
35
|
+
}>();
|
|
36
|
+
|
|
37
|
+
const inlineStyle = computed(() => `padding-top: ${100 * Number(props.ratio)}%;`);
|
|
29
38
|
</script>
|
|
30
39
|
|
|
31
40
|
<style lang="css" module>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
@use 'sass:map';
|
|
2
|
+
@use '../../styles/utils' as *;
|
|
3
|
+
|
|
4
|
+
$badge: () !default;
|
|
5
|
+
// 可配置的变量
|
|
6
|
+
$badge-default: (
|
|
7
|
+
// 徽章相对于挂载元素右上角的偏移量
|
|
8
|
+
translate: 40% -40%,
|
|
9
|
+
// 文字字号
|
|
10
|
+
font-size: UTILS__GLOBAL_VAR(font-size, small),
|
|
11
|
+
// 文字颜色
|
|
12
|
+
color: #fff,
|
|
13
|
+
// 背景色
|
|
14
|
+
background: #ff0000,
|
|
15
|
+
// 边框样式
|
|
16
|
+
border: none,
|
|
17
|
+
// 徽章高度
|
|
18
|
+
height: calc(#{UTILS__LOCAL_VAR(font-size)} + 12rpx)
|
|
19
|
+
);
|
|
20
|
+
$badge: map.merge($badge-default, $badge);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view :class="
|
|
2
|
+
<view :class="[...classNames, $style['Badge']]">
|
|
3
3
|
<slot></slot>
|
|
4
4
|
<template v-if="$slots['badge'] || $slots['badge-value']">
|
|
5
5
|
<slot name="badge">
|
|
@@ -15,48 +15,57 @@
|
|
|
15
15
|
</view>
|
|
16
16
|
</template>
|
|
17
17
|
|
|
18
|
-
<script>
|
|
19
|
-
import
|
|
18
|
+
<script lang="ts" setup>
|
|
19
|
+
import { computed } from 'vue';
|
|
20
|
+
import useClassNames from '../../composable/component-name';
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
name: 'Badge',
|
|
22
|
+
defineOptions({
|
|
23
23
|
options: {
|
|
24
|
-
virtualHost: true,
|
|
25
24
|
styleIsolation: 'shared',
|
|
25
|
+
virtualHost: true,
|
|
26
26
|
},
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
type: Number,
|
|
37
|
-
default: 99,
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
computed: {
|
|
41
|
-
/** 显示值 */
|
|
42
|
-
showValue() {
|
|
43
|
-
const numberValue = Number(this.value);
|
|
44
|
-
return numberValue && numberValue > 0 ? (numberValue > this.max ? `${this.max}+` : numberValue) : '';
|
|
45
|
-
},
|
|
46
|
-
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const classNames = useClassNames('badge');
|
|
30
|
+
|
|
31
|
+
type _Props = {
|
|
32
|
+
/** 显示在右上角的内容 */
|
|
33
|
+
value?: string | number;
|
|
34
|
+
/** 最大显示值,超出时会在后面添加一个“+” */
|
|
35
|
+
max?: number;
|
|
47
36
|
};
|
|
37
|
+
|
|
38
|
+
const props = withDefaults(defineProps<_Props>(), {
|
|
39
|
+
value: 0,
|
|
40
|
+
max: 99,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
defineEmits<{
|
|
44
|
+
(event: 'click'): void;
|
|
45
|
+
}>();
|
|
46
|
+
|
|
47
|
+
const showValue = computed(() => {
|
|
48
|
+
const numberValue = Number(props.value);
|
|
49
|
+
return numberValue && numberValue > 0 ? (numberValue > props.max ? `${props.max}+` : numberValue) : '';
|
|
50
|
+
});
|
|
48
51
|
</script>
|
|
49
52
|
|
|
50
53
|
<style lang="scss" module>
|
|
51
|
-
@use '../../styles/
|
|
54
|
+
@use '../../styles/utils' as *;
|
|
55
|
+
@use './badge' as *;
|
|
52
56
|
|
|
53
57
|
// 定义外部变量
|
|
54
|
-
$component-name: 'badge';
|
|
55
|
-
$component-vars: $badge;
|
|
56
58
|
%external-vars {
|
|
57
|
-
@include UTILS__DEFINE_COMPONENT_VARS();
|
|
59
|
+
@include UTILS__DEFINE_COMPONENT_VARS($badge, 'badge');
|
|
58
60
|
}
|
|
59
61
|
|
|
62
|
+
$__translate: UTILS__LOCAL_VAR(translate);
|
|
63
|
+
$__font-size: UTILS__LOCAL_VAR(font-size);
|
|
64
|
+
$__height: UTILS__LOCAL_VAR(height);
|
|
65
|
+
$__border: UTILS__LOCAL_VAR(border);
|
|
66
|
+
$__color: UTILS__LOCAL_VAR(color);
|
|
67
|
+
$__background: UTILS__LOCAL_VAR(background);
|
|
68
|
+
|
|
60
69
|
.Badge {
|
|
61
70
|
@extend %external-vars;
|
|
62
71
|
|
|
@@ -65,7 +74,7 @@ $component-vars: $badge;
|
|
|
65
74
|
width: fit-content;
|
|
66
75
|
|
|
67
76
|
.Badge--box {
|
|
68
|
-
--padding-x: calc(#{
|
|
77
|
+
--padding-x: calc(#{$__font-size} / 2);
|
|
69
78
|
|
|
70
79
|
position: absolute;
|
|
71
80
|
top: 0;
|
|
@@ -74,15 +83,15 @@ $component-vars: $badge;
|
|
|
74
83
|
padding: 0 var(--padding-x);
|
|
75
84
|
box-sizing: content-box;
|
|
76
85
|
text-align: center;
|
|
77
|
-
min-width: calc(#{
|
|
78
|
-
height:
|
|
79
|
-
line-height:
|
|
80
|
-
font-size:
|
|
81
|
-
border:
|
|
82
|
-
border-radius:
|
|
83
|
-
translate:
|
|
84
|
-
color:
|
|
85
|
-
background:
|
|
86
|
+
min-width: calc(#{$__height} - 2 * var(--padding-x));
|
|
87
|
+
height: $__height;
|
|
88
|
+
line-height: $__height;
|
|
89
|
+
font-size: $__font-size;
|
|
90
|
+
border: $__border;
|
|
91
|
+
border-radius: $__height;
|
|
92
|
+
translate: $__translate;
|
|
93
|
+
color: $__color;
|
|
94
|
+
background: $__background;
|
|
86
95
|
}
|
|
87
96
|
}
|
|
88
97
|
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@use 'sass:map';
|
|
2
|
+
|
|
3
|
+
// 可配置的变量
|
|
4
|
+
$button: () !default;
|
|
5
|
+
$button-default: (
|
|
6
|
+
// 按钮主题颜色,默认取值组件 props 中的 type
|
|
7
|
+
theme: var(--theme-from-prop),
|
|
8
|
+
// 按钮文本颜色
|
|
9
|
+
text-color: #fff,
|
|
10
|
+
// 按钮激活态遮罩颜色
|
|
11
|
+
active-mask: #ffffff,
|
|
12
|
+
// plain 按钮的边框宽度
|
|
13
|
+
border-width: 3rpx
|
|
14
|
+
);
|
|
15
|
+
$button: map.merge($button-default, $button);
|