@opentiny/vue-docs 3.24.1 → 3.24.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.
@@ -1,211 +1,211 @@
1
- <template>
2
- <div class="products-page">
3
- <div class="page-header">
4
- <h3>商品管理</h3>
5
- </div>
6
- <div class="page-content">
7
- <div class="button-box">
8
- <tiny-button type="info" @click="addProductToEdit"> 添加商品 </tiny-button>
9
- <tiny-button type="danger" @click="removeProduct"> 删除商品 </tiny-button>
10
- <tiny-button type="success" @click="saveProduct"> 保存 </tiny-button>
11
- </div>
12
- <tiny-grid
13
- auto-resize
14
- ref="gridRef"
15
- :data="products"
16
- :height="500"
17
- :edit-config="{ trigger: 'click', mode: 'cell', showStatus: true }"
18
- :tiny_mcp_config="{
19
- server,
20
- business: {
21
- id: 'product-list',
22
- description: '商品列表'
23
- }
24
- }"
25
- >
26
- <tiny-grid-column type="index" width="50" />
27
- <tiny-grid-column type="selection" width="50" />
28
- <tiny-grid-column title="商品图片" width="100">
29
- <template #default="{ row }">
30
- <tiny-image :src="row.image" :preview-src-list="[row.image]" class="product-image" />
31
- </template>
32
- </tiny-grid-column>
33
-
34
- <tiny-grid-column field="name" title="商品名称" :editor="{ component: 'input' }" />
35
- <tiny-grid-column
36
- field="price"
37
- :editor="{
38
- component: 'input',
39
- attrs: { type: 'number' }
40
- }"
41
- title="价格"
42
- >
43
- <template #default="{ row }"> ¥{{ row.price }} </template>
44
- </tiny-grid-column>
45
- <tiny-grid-column
46
- field="stock"
47
- :editor="{
48
- component: 'input',
49
- attrs: { type: 'number' }
50
- }"
51
- title="库存"
52
- />
53
- <tiny-grid-column
54
- field="category"
55
- :editor="{
56
- component: 'select',
57
- options: [
58
- { label: '手机', value: 'phones' },
59
- { label: '笔记本', value: 'laptops' },
60
- { label: '平板', value: 'tablets' }
61
- ]
62
- }"
63
- title="分类"
64
- >
65
- <template #default="{ row }">
66
- {{ categoryLabels[row.category] }}
67
- </template>
68
- </tiny-grid-column>
69
- <tiny-grid-column
70
- field="status"
71
- :editor="{
72
- component: 'select',
73
- options: [
74
- { label: '上架', value: 'on' },
75
- { label: '下架', value: 'off' }
76
- ]
77
- }"
78
- title="状态"
79
- >
80
- <template #default="{ row }">
81
- <tiny-tag :type="row.status === 'on' ? 'success' : 'warning'">
82
- {{ row.status === 'on' ? '上架' : '下架' }}
83
- </tiny-tag>
84
- </template>
85
- </tiny-grid-column>
86
- </tiny-grid>
87
- </div>
88
- </div>
89
- </template>
90
-
91
- <script setup lang="ts">
92
- import { ref } from 'vue'
93
- import productsData from './products.json'
94
- import { $local } from '../../composable/utils'
95
- import { useNextServer } from '@opentiny/next-vue'
96
- import { TinyGrid, TinyGridColumn, TinyButton, TinyTag, TinyModal, TinyImage } from '@opentiny/vue'
97
-
98
- if (!$local.products) {
99
- $local.products = productsData
100
- }
101
-
102
- const products = ref($local.products)
103
- const gridRef = ref(null)
104
-
105
- const categoryLabels: Record<string, string> = {
106
- phones: '手机',
107
- laptops: '笔记本',
108
- tablets: '平板'
109
- }
110
-
111
- // 新增商品到编辑弹窗
112
- const addProductToEdit = async () => {
113
- gridRef?.value?.insert({
114
- 'image': 'https://img1.baidu.com/it/u=1559062020,1043707656&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
115
- price: 10000,
116
- stock: 100,
117
- category: 'phones',
118
- status: 'on'
119
- })
120
- }
121
-
122
- const removeProduct = () => {
123
- const selectedRows = gridRef?.value?.getSelectRecords()
124
- if (selectedRows.length === 0) {
125
- TinyModal.confirm({
126
- message: '请选择要删除的商品',
127
- title: '删除商品',
128
- status: 'warning'
129
- })
130
- return
131
- }
132
- if (selectedRows.length > 0) {
133
- gridRef?.value?.removeSelecteds()
134
- }
135
- }
136
-
137
- const saveProduct = () => {
138
- setTimeout(() => {
139
- const data = gridRef?.value?.getTableData()
140
- $local.products = data.tableData
141
- TinyModal.message({
142
- message: '保存成功',
143
- status: 'success'
144
- })
145
- }, 1000)
146
- }
147
-
148
- const { server } = useNextServer({
149
- serverInfo: { name: 'commodity-config', version: '1.0.0' }
150
- })
151
- </script>
152
-
153
- <style scoped lang="less">
154
- .products-page {
155
- .page-header {
156
- display: flex;
157
- justify-content: space-between;
158
- align-items: center;
159
- margin-bottom: 20px;
160
- padding: 16px 20px;
161
- background-color: #ffffff;
162
- border-radius: 8px;
163
- position: relative;
164
- border: 1px solid #edf2f7;
165
-
166
- &::before {
167
- content: '';
168
- position: absolute;
169
- top: 50%;
170
- left: 0;
171
- width: 4px;
172
- height: 24px;
173
- background: #1677ff;
174
- border-radius: 2px;
175
- transform: translateY(-50%);
176
- }
177
-
178
- h3 {
179
- margin: 0;
180
- font-size: 20px;
181
- font-weight: 600;
182
- color: #1f2937;
183
- position: relative;
184
- padding-left: 20px;
185
- letter-spacing: 0.3px;
186
- }
187
- }
188
- }
189
-
190
- .button-box {
191
- display: flex;
192
- gap: 16px;
193
- margin-bottom: 20px;
194
- justify-content: flex-end;
195
- }
196
- .loading-state {
197
- padding: 20px;
198
- }
199
-
200
- .product-image {
201
- width: 40px;
202
- height: 40px;
203
- border-radius: 4px;
204
- }
205
- .page-content {
206
- padding: 20px;
207
- background: #fff;
208
- border-radius: 8px;
209
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.03);
210
- }
211
- </style>
1
+ <template>
2
+ <div class="products-page">
3
+ <div class="page-header">
4
+ <h3>商品管理</h3>
5
+ </div>
6
+ <div class="page-content">
7
+ <div class="button-box">
8
+ <tiny-button type="info" @click="addProductToEdit"> 添加商品 </tiny-button>
9
+ <tiny-button type="danger" @click="removeProduct"> 删除商品 </tiny-button>
10
+ <tiny-button type="success" @click="saveProduct"> 保存 </tiny-button>
11
+ </div>
12
+ <tiny-grid
13
+ auto-resize
14
+ ref="gridRef"
15
+ :data="products"
16
+ :height="500"
17
+ :edit-config="{ trigger: 'click', mode: 'cell', showStatus: true }"
18
+ :tiny_mcp_config="{
19
+ server,
20
+ business: {
21
+ id: 'product-list',
22
+ description: '商品列表'
23
+ }
24
+ }"
25
+ >
26
+ <tiny-grid-column type="index" width="50" />
27
+ <tiny-grid-column type="selection" width="50" />
28
+ <tiny-grid-column title="商品图片" width="100">
29
+ <template #default="{ row }">
30
+ <tiny-image :src="row.image" :preview-src-list="[row.image]" class="product-image" />
31
+ </template>
32
+ </tiny-grid-column>
33
+
34
+ <tiny-grid-column field="name" title="商品名称" :editor="{ component: 'input' }" />
35
+ <tiny-grid-column
36
+ field="price"
37
+ :editor="{
38
+ component: 'input',
39
+ attrs: { type: 'number' }
40
+ }"
41
+ title="价格"
42
+ >
43
+ <template #default="{ row }"> ¥{{ row.price }} </template>
44
+ </tiny-grid-column>
45
+ <tiny-grid-column
46
+ field="stock"
47
+ :editor="{
48
+ component: 'input',
49
+ attrs: { type: 'number' }
50
+ }"
51
+ title="库存"
52
+ />
53
+ <tiny-grid-column
54
+ field="category"
55
+ :editor="{
56
+ component: 'select',
57
+ options: [
58
+ { label: '手机', value: 'phones' },
59
+ { label: '笔记本', value: 'laptops' },
60
+ { label: '平板', value: 'tablets' }
61
+ ]
62
+ }"
63
+ title="分类"
64
+ >
65
+ <template #default="{ row }">
66
+ {{ categoryLabels[row.category] }}
67
+ </template>
68
+ </tiny-grid-column>
69
+ <tiny-grid-column
70
+ field="status"
71
+ :editor="{
72
+ component: 'select',
73
+ options: [
74
+ { label: '上架', value: 'on' },
75
+ { label: '下架', value: 'off' }
76
+ ]
77
+ }"
78
+ title="状态"
79
+ >
80
+ <template #default="{ row }">
81
+ <tiny-tag :type="row.status === 'on' ? 'success' : 'warning'">
82
+ {{ row.status === 'on' ? '上架' : '下架' }}
83
+ </tiny-tag>
84
+ </template>
85
+ </tiny-grid-column>
86
+ </tiny-grid>
87
+ </div>
88
+ </div>
89
+ </template>
90
+
91
+ <script setup lang="ts">
92
+ import { ref } from 'vue'
93
+ import productsData from './products.json'
94
+ import { $local } from '../../composable/utils'
95
+ import { useNextServer } from '@opentiny/next-vue'
96
+ import { TinyGrid, TinyGridColumn, TinyButton, TinyTag, TinyModal, TinyImage } from '@opentiny/vue'
97
+
98
+ if (!$local.products) {
99
+ $local.products = productsData
100
+ }
101
+
102
+ const products = ref($local.products)
103
+ const gridRef = ref(null)
104
+
105
+ const categoryLabels: Record<string, string> = {
106
+ phones: '手机',
107
+ laptops: '笔记本',
108
+ tablets: '平板'
109
+ }
110
+
111
+ // 新增商品到编辑弹窗
112
+ const addProductToEdit = async () => {
113
+ gridRef?.value?.insert({
114
+ 'image': 'https://img1.baidu.com/it/u=1559062020,1043707656&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
115
+ price: 10000,
116
+ stock: 100,
117
+ category: 'phones',
118
+ status: 'on'
119
+ })
120
+ }
121
+
122
+ const removeProduct = () => {
123
+ const selectedRows = gridRef?.value?.getSelectRecords()
124
+ if (selectedRows.length === 0) {
125
+ TinyModal.confirm({
126
+ message: '请选择要删除的商品',
127
+ title: '删除商品',
128
+ status: 'warning'
129
+ })
130
+ return
131
+ }
132
+ if (selectedRows.length > 0) {
133
+ gridRef?.value?.removeSelecteds()
134
+ }
135
+ }
136
+
137
+ const saveProduct = () => {
138
+ setTimeout(() => {
139
+ const data = gridRef?.value?.getTableData()
140
+ $local.products = data.tableData
141
+ TinyModal.message({
142
+ message: '保存成功',
143
+ status: 'success'
144
+ })
145
+ }, 1000)
146
+ }
147
+
148
+ const { server } = useNextServer({
149
+ serverInfo: { name: 'commodity-config', version: '1.0.0' }
150
+ })
151
+ </script>
152
+
153
+ <style scoped lang="less">
154
+ .products-page {
155
+ .page-header {
156
+ display: flex;
157
+ justify-content: space-between;
158
+ align-items: center;
159
+ margin-bottom: 20px;
160
+ padding: 16px 20px;
161
+ background-color: #ffffff;
162
+ border-radius: 8px;
163
+ position: relative;
164
+ border: 1px solid #edf2f7;
165
+
166
+ &::before {
167
+ content: '';
168
+ position: absolute;
169
+ top: 50%;
170
+ left: 0;
171
+ width: 4px;
172
+ height: 24px;
173
+ background: #1677ff;
174
+ border-radius: 2px;
175
+ transform: translateY(-50%);
176
+ }
177
+
178
+ h3 {
179
+ margin: 0;
180
+ font-size: 20px;
181
+ font-weight: 600;
182
+ color: #1f2937;
183
+ position: relative;
184
+ padding-left: 20px;
185
+ letter-spacing: 0.3px;
186
+ }
187
+ }
188
+ }
189
+
190
+ .button-box {
191
+ display: flex;
192
+ gap: 16px;
193
+ margin-bottom: 20px;
194
+ justify-content: flex-end;
195
+ }
196
+ .loading-state {
197
+ padding: 20px;
198
+ }
199
+
200
+ .product-image {
201
+ width: 40px;
202
+ height: 40px;
203
+ border-radius: 4px;
204
+ }
205
+ .page-content {
206
+ padding: 20px;
207
+ background: #fff;
208
+ border-radius: 8px;
209
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.03);
210
+ }
211
+ </style>