rrj-astra-ui 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 (38) hide show
  1. package/README.en.md +36 -0
  2. package/README.md +37 -0
  3. package/components/AuiBadge.vue +50 -0
  4. package/components/AuiBlockBox.vue +85 -0
  5. package/components/AuiButton.vue +210 -0
  6. package/components/AuiCustomerForm.vue +304 -0
  7. package/components/AuiDivider.vue +66 -0
  8. package/components/AuiFold.vue +40 -0
  9. package/components/AuiFoldItem.vue +173 -0
  10. package/components/AuiForm.vue +76 -0
  11. package/components/AuiFormItem.vue +88 -0
  12. package/components/AuiGrid.vue +26 -0
  13. package/components/AuiGridItem.vue +20 -0
  14. package/components/AuiIcon.vue +145 -0
  15. package/components/AuiImage.vue +152 -0
  16. package/components/AuiInput.vue +176 -0
  17. package/components/AuiLamp.vue +254 -0
  18. package/components/AuiLineProgress.vue +169 -0
  19. package/components/AuiList.vue +18 -0
  20. package/components/AuiListItem.vue +142 -0
  21. package/components/AuiMultiSelect.vue +303 -0
  22. package/components/AuiNoticeBar.vue +62 -0
  23. package/components/AuiNumberBox.vue +282 -0
  24. package/components/AuiPicker.vue +619 -0
  25. package/components/AuiPopup.vue +57 -0
  26. package/components/AuiSelectGroup.vue +312 -0
  27. package/components/AuiTab.vue +173 -0
  28. package/components/AuiTabItem.vue +43 -0
  29. package/components/AuiTable.vue +357 -0
  30. package/components/AuiTag.vue +112 -0
  31. package/components/AuiText.vue +81 -0
  32. package/components/AuiTextarea.vue +203 -0
  33. package/components/AuiToast.vue +96 -0
  34. package/components/AuiUpdate.vue +271 -0
  35. package/components/AuiUpload.vue +524 -0
  36. package/index.js +93 -0
  37. package/package.json +36 -0
  38. package/style.scss +30 -0
@@ -0,0 +1,304 @@
1
+ <template>
2
+ <view class="aui-customer-form">
3
+ <!-- 上部:标题和添加按钮 -->
4
+ <view class="aui-form-header">
5
+ <view class="aui-form-title">{{ title }}</view>
6
+ <view class="aui-add-btn" @click="openAddModal">添加</view>
7
+ </view>
8
+
9
+ <!-- 下部:使用 AuiTable 显示数据 -->
10
+ <AuiTable
11
+ :columns="tableColumns"
12
+ :data="formItems"
13
+ theme="simple"
14
+ @row-click="editItemHandler"
15
+ @delete="deleteItemHandler"
16
+ :showSort="showSort"
17
+ :allowDelete="allowDelete"
18
+ >
19
+ <template #operation="{ row, rowIndex }">
20
+ <button class="aui-edit-btn" @click="editItemHandler(rowIndex, row)">编辑</button>
21
+ <button class="aui-delete-btn" @click="deleteItemHandler(rowIndex, row)">删除</button>
22
+ </template>
23
+ </AuiTable>
24
+
25
+ <!-- 添加/编辑弹窗 -->
26
+ <view v-if="showModal" class="aui-modal">
27
+ <view class="aui-modal-content">
28
+ <view class="aui-modal-header">{{ modalTitle }}</view>
29
+ <view class="aui-modal-body">
30
+ <AuiInput
31
+ v-for="field in propForm"
32
+ :key="field.field"
33
+ :type="field.type || 'text'"
34
+ :placeholder="field.text"
35
+ v-model="currentItem[field.field]"
36
+ :style="{ marginBottom: '10px' }"
37
+ />
38
+ </view>
39
+ <view class="aui-modal-footer">
40
+ <AuiButton type="danger" @click="closeModal">取消</AuiButton>
41
+ <AuiButton @click="handleConfirm">确认</AuiButton>
42
+ </view>
43
+ </view>
44
+ </view>
45
+
46
+ <!-- 删除确认弹窗 -->
47
+ <view v-if="showDeleteConfirm" class="aui-delete-confirm">
48
+ <view class="aui-confirm-content">
49
+ <view style="padding: 20px 0;">
50
+ 确认删除该项目吗?
51
+ </view>
52
+ <div style="margin-top: 15px; display: flex; justify-content: flex-end; gap: 10px;">
53
+ <AuiButton @click="closeDeleteConfirm">取消</AuiButton>
54
+ <AuiButton type="danger" @click="handleDelete">确认删除</AuiButton>
55
+ </div>
56
+ </view>
57
+ </view>
58
+ </view>
59
+ </template>
60
+
61
+ <script setup>
62
+ import { defineProps, defineEmits, ref, watch } from 'vue';
63
+ import AuiInput from './AuiInput.vue';
64
+ import AuiTable from './AuiTable.vue';
65
+ import AuiButton from './AuiButton.vue';
66
+
67
+ const __name = 'AuiCustomerForm';
68
+ defineOptions({ name: __name });
69
+ const props = defineProps({
70
+ title: { type: String, default: '动态表单' },
71
+ propForm: {
72
+ type: Array,
73
+ required: true,
74
+ validator: val => val.every(item => item.field && item.text)
75
+ },
76
+ modelValue: { type: Array, default: () => [] },
77
+ showSort: {
78
+ type: Boolean,
79
+ default: false
80
+ },
81
+ allowDelete :{
82
+ type: Boolean,
83
+ default: false
84
+ }
85
+ });
86
+
87
+ const emits = defineEmits(['update:modelValue']);
88
+
89
+ // 表单数据(响应式)
90
+ const formItems = ref([...props.modelValue]);
91
+
92
+ // 表格列配置(根据 propForm 生成)
93
+ const tableColumns = ref([
94
+ ...props.propForm.map(field => ({
95
+ label: field.text,
96
+ prop: field.field,
97
+ type: field.type,
98
+ editable: false
99
+ }))
100
+ ]);
101
+
102
+ // 弹窗状态
103
+ const showModal = ref(false);
104
+ const showDeleteConfirm = ref(false);
105
+ const currentItem = ref({});
106
+ const modalTitle = ref('');
107
+ const currentIndex = ref(-1);
108
+
109
+ // 添加带 sort 属性的数据处理函数
110
+ const addSortProperty = (data, showSort) => {
111
+ return showSort ? data.map((item, index) => ({ ...item, sort: index + 1 })) : data;
112
+ };
113
+
114
+ // 监听外部数据变化
115
+ watch(() => props.modelValue, (newVal) => {
116
+ formItems.value = newVal.map(item => ({ ...item }));
117
+ formItems.value = addSortProperty(formItems.value, props.showSort);
118
+ }, { deep: true });
119
+
120
+ // 监听 showSort 变化
121
+ watch(() => props.showSort, (newShowSort) => {
122
+ formItems.value = addSortProperty(formItems.value, newShowSort);
123
+ });
124
+
125
+ // 打开添加弹窗
126
+ const openAddModal = () => {
127
+ currentItem.value = {};
128
+ modalTitle.value = '添加新项目';
129
+ showModal.value = true;
130
+ };
131
+
132
+ // 打开编辑弹窗
133
+ const editItemHandler = (index, item) => {
134
+ currentIndex.value = index;
135
+ currentItem.value = { ...item };
136
+ modalTitle.value = '修改项目信息';
137
+ showModal.value = true;
138
+ };
139
+
140
+ // 确认提交(添加/编辑)
141
+ const handleConfirm = () => {
142
+ if (currentIndex.value >= 0) {
143
+ // 编辑操作:更新指定行
144
+ formItems.value[currentIndex.value] = { ...currentItem.value };
145
+ } else {
146
+ // 添加操作:生成唯一 ID 并添加到列表
147
+ const newItem = { ...currentItem.value, id: Date.now() };
148
+ formItems.value.push(newItem);
149
+ }
150
+ // 添加 sort 属性
151
+ const dataWithSort = addSortProperty(formItems.value, props.showSort);
152
+ emits('update:modelValue', dataWithSort.map(item => ({ ...item })));
153
+ closeModal();
154
+ };
155
+
156
+ // 触发删除确认
157
+ const deleteItemHandler = (rowIndex, item) => {
158
+ currentIndex.value = rowIndex;
159
+ showDeleteConfirm.value = true;
160
+ };
161
+
162
+ // 确认删除
163
+ const handleDelete = () => {
164
+ if (currentIndex.value >= 0) {
165
+ formItems.value.splice(currentIndex.value, 1);
166
+ // 添加 sort 属性
167
+ const dataWithSort = addSortProperty(formItems.value, props.showSort);
168
+ emits('update:modelValue', dataWithSort.map(item => ({ ...item })));
169
+ closeDeleteConfirm();
170
+ }
171
+ };
172
+
173
+ // 关闭弹窗
174
+ const closeModal = () => {
175
+ showModal.value = false;
176
+ currentIndex.value = -1;
177
+ currentItem.value = {};
178
+ };
179
+
180
+ const closeDeleteConfirm = () => {
181
+ showDeleteConfirm.value = false;
182
+ currentIndex.value = -1;
183
+ };
184
+ </script>
185
+
186
+ <style scoped lang="scss">
187
+ .aui-customer-form {
188
+ padding: 15px;
189
+ }
190
+
191
+ .aui-form-header {
192
+ display: flex;
193
+ justify-content: space-between;
194
+ align-items: center;
195
+ margin-bottom: 15px;
196
+
197
+ .aui-form-title {
198
+ font-size: 16px;
199
+ font-weight: 500;
200
+ color: #1A1A1A;
201
+ }
202
+
203
+ .aui-add-btn {
204
+ color: #3B82F6;
205
+ font-size: 14px;
206
+ cursor: pointer;
207
+ border: 1px solid #EFF6FF;
208
+ background-color: #EFF6FF;
209
+ padding: 5px 15px;
210
+ border-radius: 2px;
211
+ transition: all 0.2s;
212
+
213
+ &:hover {
214
+ background-color: #EFF6FF;
215
+ }
216
+ }
217
+ }
218
+
219
+ .aui-modal {
220
+ position: fixed;
221
+ top: 0;
222
+ left: 0;
223
+ width: 100%;
224
+ height: 100%;
225
+ background-color: rgba(0, 0, 0, 0.5);
226
+ display: flex;
227
+ justify-content: center;
228
+ align-items: center;
229
+ z-index: 1000;
230
+ }
231
+
232
+ .aui-modal-content {
233
+ background-color: white;
234
+ border-radius: 8px;
235
+ width: 90%;
236
+ max-width: 500px;
237
+ padding: 20px;
238
+
239
+ .aui-modal-header {
240
+ font-size: 18px;
241
+ font-weight: 500;
242
+ margin-bottom: 15px;
243
+ text-align: center;
244
+ }
245
+
246
+ .aui-modal-body {
247
+ margin-bottom: 20px;
248
+
249
+ .aui-input-item {
250
+ margin-bottom: 10px;
251
+ }
252
+ }
253
+
254
+ .aui-modal-footer {
255
+ display: flex;
256
+ justify-content: flex-end;
257
+ gap: 10px;
258
+ }
259
+ }
260
+
261
+ .aui-delete-confirm {
262
+ position: fixed;
263
+ top: 0px;
264
+ left: 0px;
265
+ background-color: rgba(0, 0, 0, 0.5); /* 修改为半透明背景 */
266
+ border-radius: 8px;
267
+ z-index: 1001;
268
+ width: 100%;
269
+ height: 100%;
270
+ display: flex; /* 添加 Flexbox 布局 */
271
+ justify-content: center; /* 水平居中 */
272
+ align-items: center; /* 垂直居中 */
273
+
274
+ .aui-confirm-content {
275
+ text-align: center;
276
+ font-size: 16px;
277
+ color: #333;
278
+ background-color: white; /* 添加白色背景 */
279
+ padding: 20px;
280
+ box-sizing: border-box;
281
+ border-radius: 8px;
282
+ width:80%; /* 限制最大宽度 */
283
+ }
284
+ }
285
+
286
+ .aui-edit-btn, .aui-delete-btn {
287
+ padding: 4px 8px;
288
+ border: none;
289
+ border-radius: 4px;
290
+ cursor: pointer;
291
+ font-size: 12px;
292
+ margin: 0 2px;
293
+ }
294
+
295
+ .aui-edit-btn {
296
+ background-color: #3B82F6;
297
+ color: white;
298
+ }
299
+
300
+ .aui-delete-btn {
301
+ background-color: #F5222D;
302
+ color: white;
303
+ }
304
+ </style>
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <view class="aui-viewider" :class="['aui-viewider--' + type, { 'aui-viewider--dashed': dashed }]">
3
+ <view class="aui-viewider__text">{{ text }}</view>
4
+ </view>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { defineProps } from 'vue';
9
+ const __name = 'AuiDivider';
10
+
11
+
12
+ defineOptions({
13
+ name: __name
14
+ })
15
+ const props = defineProps({
16
+ type: {
17
+ type: String,
18
+ default: 'horizontal',
19
+ validator: (value) => ['horizontal', 'vertical'].includes(value)
20
+ },
21
+ text: {
22
+ type: String,
23
+ default: ''
24
+ },
25
+ dashed: {
26
+ type: Boolean,
27
+ default: false
28
+ }
29
+ });
30
+ </script>
31
+
32
+ <style scoped lang="scss">
33
+ @import '../style.scss';
34
+
35
+ .aui-viewider {
36
+ display: flex;
37
+ align-items: center;
38
+ gap: 10px;
39
+ }
40
+ .aui-viewider--horizontal {
41
+ flex-direction: row;
42
+ height: 1px;
43
+ background-color: $aui-border-color;
44
+ justify-content: center; // 新增:让文字在水平分割线中水平居中
45
+ }
46
+ .aui-viewider--vertical {
47
+ flex-direction: column;
48
+ width: 1px;
49
+ background-color: $aui-border-color;
50
+ align-items: center; // 新增:让文字在垂直分割线中垂直居中
51
+ }
52
+ .aui-viewider__text {
53
+ font-size: $aui-font-size;
54
+ color: $aui-text-color;
55
+ padding: 0 10px;
56
+ background-color: #fff;
57
+ z-index: 1;
58
+ white-space: nowrap;
59
+
60
+ }
61
+ .aui-viewider--dashed {
62
+ background-color: transparent;
63
+ background-image: linear-gradient(90deg, $aui-border-color 50%, transparent 50%);
64
+ background-size: 10px 1px;
65
+ }
66
+ </style>
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <view :class="[`aui-fold`,`aui-fold-theme__${theme}`]">
3
+ <slot></slot>
4
+ </view>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { ref, computed, defineProps, defineEmits } from 'vue';
9
+
10
+ const _name="AuiFold";
11
+ defineOptions({name:_name})
12
+ const props = defineProps({
13
+ theme: {
14
+ type: String,
15
+ default: 'default',
16
+ validator: (value) => ['default'].includes(value)
17
+ },
18
+ showDelete: {
19
+ type: Boolean,
20
+ default: false
21
+ }
22
+ });
23
+
24
+ </script>
25
+
26
+ <style scoped>
27
+ .aui-fold {
28
+ display: flex;
29
+ flex-direction: column;
30
+ gap: 10px;
31
+ width: 100%;
32
+ margin-top: 10px;
33
+ }
34
+
35
+ /* 主题样式 */
36
+ .aui-fold-theme__default .aui-fold-head {
37
+ background-color: #f5f5f5;
38
+ color: #333;
39
+ }
40
+ </style>
@@ -0,0 +1,173 @@
1
+ <template>
2
+ <view class="aui-fold-item">
3
+ <view
4
+ class="aui-fold-head"
5
+ @click="toggleFold"
6
+ >
7
+ <view class="aui-fold-head__left" v-if="imageUrl">
8
+ <aui-image :src="imageUrl" :width="imageWidth"></aui-image>
9
+ </view>
10
+ <view class="aui-fold-head__center">
11
+ <view class="aui-fold-head__title">
12
+ {{ title }}
13
+ </view>
14
+ <view class="aui-fold-head__desc">
15
+ {{ desc }}
16
+ </view>
17
+ </view>
18
+ <view class="aui-fold-head__right">
19
+ <view class="aui-fold-head_tip" v-if="tip">{{ tip }}</view>
20
+ <view class="aui-fold-head__delete" @click.stop="handleDelete" v-if="showDelete">
21
+ ×
22
+ </view>
23
+ <view class="aui-fold-head__arrow">
24
+ <aui-icon name="direction" size="20px" :rotate="isOpen?180:0" />
25
+ </view>
26
+ </view>
27
+ </view>
28
+ <view
29
+ class="aui-fold-item__content"
30
+ :style="{ height: isOpen ? 'auto' : '0px', overflow: isOpen ? 'visible' : 'hidden' }"
31
+ ref="contentRef"
32
+ >
33
+ <slot></slot>
34
+ </view>
35
+ </view>
36
+ </template>
37
+
38
+ <script setup>
39
+ import { ref, defineProps, defineEmits, onMounted, nextTick, watch } from 'vue';
40
+
41
+ import AuiIcon from './AuiIcon.vue'
42
+ import AuiImage from './AuiImage.vue';
43
+
44
+ const _name="AuiFoldItem";
45
+ defineOptions({name:_name})
46
+ const props = defineProps({
47
+ title:{
48
+ type: String,
49
+ default: ''
50
+ },
51
+ desc:{
52
+ type: String,
53
+ default: ''
54
+ },
55
+ showDelete: {
56
+ type: Boolean,
57
+ default: false
58
+ },
59
+ defaultOpen: {
60
+ type: Boolean,
61
+ default: false
62
+ },
63
+ tip:{
64
+ type: String,
65
+ default: ''
66
+ },
67
+ imageUrl:{
68
+ type: String,
69
+ default: ''
70
+ },
71
+ imageWidth:{
72
+ type: Number,
73
+ default: 50
74
+ }
75
+ });
76
+
77
+ const emits = defineEmits(['delete', 'toggle']);
78
+
79
+ const isOpen = ref(props.defaultOpen);
80
+ const contentRef = ref(null);
81
+
82
+ // 切换折叠状态
83
+ const toggleFold = () => {
84
+ isOpen.value = !isOpen.value;
85
+ emits('toggle', isOpen.value);
86
+ };
87
+
88
+ // 删除项
89
+ const handleDelete = () => {
90
+ emits('delete');
91
+ };
92
+ </script>
93
+
94
+ <style scoped>
95
+ .aui-fold-item {
96
+ border-radius: 8px;
97
+ overflow: hidden;
98
+ border: 1px solid #E5E7EB;
99
+ transition: all 0.3s ease;
100
+ padding:10px
101
+ }
102
+
103
+ .aui-fold-head {
104
+ display: flex;
105
+ align-items: center;
106
+ cursor: pointer;
107
+ transition: all 0.3s ease;
108
+ }
109
+
110
+ .aui-fold-head:hover {
111
+ opacity: 0.9;
112
+ }
113
+
114
+ .aui-fold-head__left {
115
+ align-items: center;
116
+ margin-right: 10px;
117
+ }
118
+
119
+ .aui-fold-head__center {
120
+ flex: 1;
121
+ min-width: 0;
122
+ }
123
+
124
+ .aui-fold-head__title {
125
+ font-size: 14px;
126
+ font-weight: 500;
127
+ white-space: nowrap;
128
+ overflow: hidden;
129
+ text-overflow: ellipsis;
130
+ color: #111827;
131
+ }
132
+
133
+ .aui-fold-head__desc {
134
+ font-size: 14px;
135
+ color: #4B5563;
136
+ white-space: nowrap;
137
+ overflow: hidden;
138
+ text-overflow: ellipsis;
139
+ margin-top: 5px;
140
+ }
141
+
142
+ .aui-fold-head__right {
143
+ display: flex;
144
+ align-items: center;
145
+ margin-left: 10px;
146
+ }
147
+
148
+
149
+ .aui-fold-head__arrow {
150
+ width: 16px;
151
+ text-align: center;
152
+ transition: transform 0.3s ease;
153
+ }
154
+
155
+ /** .aui-fold-head__arrow--open {
156
+ transform: rotate(90deg);
157
+ }
158
+ */
159
+
160
+
161
+ .aui-fold-head__delete:hover {
162
+ background-color: #ff4d4f;
163
+ color: white;
164
+ }
165
+
166
+ .aui-fold-item__content {
167
+ overflow: hidden;
168
+ transition: height 0.3s ease;
169
+ background-color: white;
170
+ box-sizing: border-box;
171
+ }
172
+ .aui-fold-head_tip{font-size: 12px;color:#9CA3AF;margin-right: 10px;}
173
+ </style>
@@ -0,0 +1,76 @@
1
+ <template>
2
+ <form :class="['aui-form', `aui-form-${layout}`]" @submit.prevent="handleSubmit">
3
+ <slot></slot>
4
+ </form>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { provide,defineProps, defineEmits,computed } from 'vue';
9
+ const __name = 'AuiForm';
10
+
11
+ defineOptions({
12
+ name: __name
13
+ })
14
+ const props = defineProps({
15
+ layout: {
16
+ type: String,
17
+ default: 'vertical',
18
+ validator: (value) => ['vertical', 'horizontal'].includes(value)
19
+ },
20
+ showSubmitButton: {
21
+ type: Boolean,
22
+ default: true
23
+ },
24
+ buttonText: {
25
+ type: String,
26
+ default: '提交'
27
+ },
28
+ buttonSize: {
29
+ type: String,
30
+ default: 'normal',
31
+ validator: (value) => ['normal', 'small', 'large'].includes(value)
32
+ },
33
+ buttonType: {
34
+ type: String,
35
+ default: 'primary',
36
+ validator: (value) => ['primary', 'success', 'warning', 'danger'].includes(value)
37
+ },
38
+ lineSpacing:{
39
+ type: [String,Number],
40
+ default: '5'
41
+ }
42
+ });
43
+ const emits = defineEmits(['submit']);
44
+
45
+ const formItemStyle = computed(() => ({
46
+ marginBottom: `${props.lineSpacing}px`
47
+ }));
48
+
49
+ const handleSubmit = () => {
50
+ emits('submit');
51
+ };
52
+ // 提供样式对象给子组件
53
+ console.log(formItemStyle.value)
54
+ provide('formItemStyle', formItemStyle.value);
55
+ </script>
56
+
57
+ <style scoped lang="scss">
58
+ @import '../style.scss';
59
+
60
+ .aui-form {
61
+ display: flex;
62
+ flex-direction: column;
63
+ gap: 15px;
64
+ }
65
+
66
+ .aui-form--horizontal {
67
+ flex-direction: row;
68
+ flex-wrap: wrap;
69
+ align-items: flex-start;
70
+ }
71
+
72
+ .aui-form__submit-wrapper {
73
+ margin-top: 15px;
74
+ }
75
+ </style>
76
+