@wapri/gutils 0.0.0-stage → 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.
@@ -0,0 +1,172 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref } from 'vue'
3
+ import { currency } from '@wapri/gutils'
4
+
5
+ const amountInput = ref('1234.56')
6
+ const centsInput = ref('123456')
7
+ const symbol = ref('¥')
8
+ const precision = ref(2)
9
+
10
+ function toFiniteNumber(value: string): number {
11
+ const number = Number(value)
12
+ return Number.isFinite(number) ? number : 0
13
+ }
14
+
15
+ const amountValue = computed(() => toFiniteNumber(amountInput.value))
16
+ const amount = computed(() => currency(amountValue.value, { symbol: symbol.value, precision: precision.value }))
17
+ const centsValue = computed(() => amount.value.intValue)
18
+ const restoredAmount = computed(() =>
19
+ currency(centsValue.value, {
20
+ fromCents: true,
21
+ symbol: symbol.value,
22
+ precision: precision.value,
23
+ }).format(),
24
+ )
25
+ const centsAmount = computed(() =>
26
+ currency(toFiniteNumber(centsInput.value), {
27
+ fromCents: true,
28
+ symbol: symbol.value,
29
+ precision: precision.value,
30
+ }),
31
+ )
32
+ const plusAmount = computed(() => amount.value.add('99.90').format())
33
+ const splitAmounts = computed(() =>
34
+ amount.value
35
+ .distribute(3)
36
+ .map((item) => item.format())
37
+ .join('、'),
38
+ )
39
+ </script>
40
+
41
+ <template>
42
+ <div class="currency-demo">
43
+ <div class="currency-demo__fields">
44
+ <label class="currency-demo__field">
45
+ <span>输入金额(元)</span>
46
+ <input
47
+ v-model="amountInput"
48
+ type="number"
49
+ step="0.01"
50
+ inputmode="decimal"
51
+ />
52
+ </label>
53
+ <label class="currency-demo__field">
54
+ <span>货币符号</span>
55
+ <input
56
+ v-model="symbol"
57
+ maxlength="3"
58
+ />
59
+ </label>
60
+ <label class="currency-demo__field">
61
+ <span>小数位数</span>
62
+ <select v-model.number="precision">
63
+ <option :value="0">0</option>
64
+ <option :value="2">2</option>
65
+ <option :value="3">3</option>
66
+ </select>
67
+ </label>
68
+ </div>
69
+
70
+ <div class="currency-demo__result">
71
+ <p>
72
+ 格式化展示:
73
+ <strong>{{ amount.format() }}</strong>
74
+ </p>
75
+ <p>
76
+ 元金额数值:
77
+ <code>{{ amount.value }}</code>
78
+ </p>
79
+ <p>
80
+ 转换为最小货币单位:
81
+ <code>{{ centsValue }}</code>
82
+ </p>
83
+ <p>
84
+ 从最小货币单位还原:
85
+ <strong>{{ restoredAmount }}</strong>
86
+ </p>
87
+ <p>
88
+ 加上 99.90:
89
+ <strong>{{ plusAmount }}</strong>
90
+ </p>
91
+ <p>
92
+ 平均分成 3 份:
93
+ <strong>{{ splitAmounts }}</strong>
94
+ </p>
95
+ </div>
96
+
97
+ <label class="currency-demo__field currency-demo__field--cents">
98
+ <span>输入最小货币单位(分)</span>
99
+ <input
100
+ v-model="centsInput"
101
+ type="number"
102
+ step="1"
103
+ inputmode="numeric"
104
+ />
105
+ <strong>{{ centsAmount.format() }}</strong>
106
+ </label>
107
+ </div>
108
+ </template>
109
+
110
+ <style scoped>
111
+ .currency-demo {
112
+ max-width: 760px;
113
+ padding: 20px;
114
+ border: 1px solid #e5e7eb;
115
+ border-radius: 8px;
116
+ color: #1f2937;
117
+ }
118
+
119
+ .currency-demo__fields {
120
+ display: flex;
121
+ flex-wrap: wrap;
122
+ gap: 16px;
123
+ }
124
+
125
+ .currency-demo__field {
126
+ display: inline-flex;
127
+ min-width: 150px;
128
+ flex: 1;
129
+ flex-direction: column;
130
+ gap: 6px;
131
+ font-size: 14px;
132
+ }
133
+
134
+ .currency-demo__field input,
135
+ .currency-demo__field select {
136
+ box-sizing: border-box;
137
+ height: 34px;
138
+ padding: 0 10px;
139
+ border: 1px solid #d1d5db;
140
+ border-radius: 4px;
141
+ background: #fff;
142
+ color: inherit;
143
+ font: inherit;
144
+ }
145
+
146
+ .currency-demo__result {
147
+ margin: 20px 0;
148
+ padding: 14px 16px;
149
+ border-radius: 6px;
150
+ background: #f8fafc;
151
+ line-height: 1.8;
152
+ }
153
+
154
+ .currency-demo__result p {
155
+ margin: 0;
156
+ }
157
+
158
+ .currency-demo__result strong,
159
+ .currency-demo__field strong {
160
+ color: #1677ff;
161
+ }
162
+
163
+ .currency-demo__field--cents {
164
+ max-width: 300px;
165
+ }
166
+
167
+ code {
168
+ padding: 2px 5px;
169
+ border-radius: 3px;
170
+ background: #eef2f7;
171
+ }
172
+ </style>
@@ -0,0 +1,2 @@
1
+ export * from '@wapri/gbase';
2
+ export * from './vconsole';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from '@wapri/gbase';
2
+ export * from "./vconsole";
@@ -0,0 +1,139 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import { setToken, storage } from '@wapri/gutils'
4
+
5
+ const key = ref('demo-key')
6
+ const value = ref('demo-value')
7
+ const result = ref<string | null>(null)
8
+ const message = ref('等待操作')
9
+
10
+ const getKey = () => key.value.trim()
11
+
12
+ const save = () => {
13
+ const storageKey = getKey()
14
+ if (!storageKey) {
15
+ message.value = '请输入 key 后再存储'
16
+ return
17
+ }
18
+
19
+ storage.setItem(storageKey, value.value)
20
+ setToken(value.value)
21
+ message.value = '已存储'
22
+ }
23
+
24
+ const read = () => {
25
+ const storageKey = getKey()
26
+ if (!storageKey) {
27
+ message.value = '请输入 key 后再读取'
28
+ result.value = null
29
+ return
30
+ }
31
+
32
+ result.value = storage.getItem(storageKey)
33
+ message.value = result.value === null ? '未找到对应数据' : '读取成功'
34
+ }
35
+ </script>
36
+
37
+ <template>
38
+ <div class="storage-demo">
39
+ <label class="storage-demo__field">
40
+ <span>Key</span>
41
+ <input
42
+ v-model="key"
43
+ placeholder="请输入 key"
44
+ />
45
+ </label>
46
+
47
+ <label class="storage-demo__field">
48
+ <span>Value</span>
49
+ <input
50
+ v-model="value"
51
+ placeholder="请输入 value"
52
+ />
53
+ </label>
54
+
55
+ <div class="storage-demo__actions">
56
+ <button
57
+ type="button"
58
+ @click="save"
59
+ >
60
+ 存储
61
+ </button>
62
+ <button
63
+ type="button"
64
+ @click="read"
65
+ >
66
+ 读取
67
+ </button>
68
+ </div>
69
+
70
+ <div
71
+ class="storage-demo__result"
72
+ aria-live="polite"
73
+ >
74
+ <span>{{ message }}</span>
75
+ <code>读取结果:{{ result ?? 'null' }}</code>
76
+ </div>
77
+ </div>
78
+ </template>
79
+
80
+ <style scoped>
81
+ .storage-demo {
82
+ display: grid;
83
+ max-width: 640px;
84
+ gap: 16px;
85
+ padding: 20px;
86
+ border: 1px solid #e5e7eb;
87
+ border-radius: 8px;
88
+ color: #1f2937;
89
+ }
90
+
91
+ .storage-demo__field {
92
+ display: grid;
93
+ gap: 6px;
94
+ font-size: 14px;
95
+ }
96
+
97
+ .storage-demo__field input {
98
+ box-sizing: border-box;
99
+ width: 100%;
100
+ height: 34px;
101
+ padding: 0 10px;
102
+ border: 1px solid #d1d5db;
103
+ border-radius: 4px;
104
+ color: inherit;
105
+ font: inherit;
106
+ }
107
+
108
+ .storage-demo__actions {
109
+ display: flex;
110
+ gap: 10px;
111
+ }
112
+
113
+ .storage-demo__actions button {
114
+ height: 34px;
115
+ padding: 0 16px;
116
+ border: 0;
117
+ border-radius: 4px;
118
+ background: #1677ff;
119
+ color: #fff;
120
+ cursor: pointer;
121
+ }
122
+
123
+ .storage-demo__actions button + button {
124
+ background: #4b5563;
125
+ }
126
+
127
+ .storage-demo__result {
128
+ display: grid;
129
+ gap: 6px;
130
+ padding: 12px;
131
+ border-radius: 6px;
132
+ background: #f8fafc;
133
+ font-size: 14px;
134
+ }
135
+
136
+ .storage-demo__result code {
137
+ color: #1677ff;
138
+ }
139
+ </style>
@@ -0,0 +1,15 @@
1
+ interface Eruda {
2
+ init?: () => void;
3
+ }
4
+ declare global {
5
+ interface Window {
6
+ eruda?: Eruda;
7
+ }
8
+ }
9
+ /**
10
+ * 动态加载并初始化移动端调试面板 Eruda。
11
+ *
12
+ * 同一页面中重复调用只会初始化一次;服务端渲染环境会安全跳过。
13
+ */
14
+ export declare function vconsole(): Promise<void>;
15
+ export {};
@@ -0,0 +1,30 @@
1
+ import { loadResource } from '@wapri/gbase';
2
+ var ERUDA_URL = 'https://cdn.jsdelivr.net/npm/eruda';
3
+ var initializePromise;
4
+ var initialized = false;
5
+
6
+ /**
7
+ * 动态加载并初始化移动端调试面板 Eruda。
8
+ *
9
+ * 同一页面中重复调用只会初始化一次;服务端渲染环境会安全跳过。
10
+ */
11
+ export function vconsole() {
12
+ if (typeof window === 'undefined' || initialized) {
13
+ return Promise.resolve();
14
+ }
15
+ if (initializePromise) {
16
+ return initializePromise;
17
+ }
18
+ initializePromise = (window.eruda ? Promise.resolve() : loadResource(ERUDA_URL)).then(function () {
19
+ var eruda = window.eruda;
20
+ if (!(eruda !== null && eruda !== void 0 && eruda.init)) {
21
+ throw new Error('Eruda 加载失败');
22
+ }
23
+ eruda.init();
24
+ initialized = true;
25
+ }).catch(function (error) {
26
+ initializePromise = undefined;
27
+ throw error;
28
+ });
29
+ return initializePromise;
30
+ }
package/package.json CHANGED
@@ -1,6 +1,28 @@
1
1
  {
2
2
  "name": "@wapri/gutils",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.0.0",
4
+ "description": "前端js函数库",
5
+ "keywords": [],
6
+ "license": "UNLICENSED",
7
+ "author": "wa",
8
+ "sideEffects": false,
9
+ "module": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "dependencies": {
15
+ "console-ban": "^5.0.0",
16
+ "dayjs": "^1.11.9",
17
+ "@wapri/gbase": "^1.0.0"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public",
21
+ "registry": "https://registry.npmjs.org/"
22
+ },
23
+ "peerDependenciesMeta": {},
24
+ "scripts": {
25
+ "build": "father build",
26
+ "dev": "father dev"
27
+ }
6
28
  }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.