huangyinfeng
4 天以前 db42d08c39ae6129e2b95cd24c0d57c6769282e5
提交 | 用户 | age
63d608 1 <template>
H 2   <div class="p-2">
3     <vxe-toolbar>
4       <template #buttons>
5         <div style="display: flex; align-items: flex-end">
6           <span style="font-size: 1.25rem; font-weight: 600">我的标签</span
7           ><span style="margin-left: 5px; padding-bottom: 4px; font-size: 12px"
8             >管理您的所有个人标签</span
9           >
10         </div>
11       </template>
12       <template #tools>
a9a03d 13         <a-button type="primary" @click="showModal('add','')">新建个人标签</a-button>
63d608 14       </template>
H 15     </vxe-toolbar>
16
17     <vxe-table
18       ref="xTable"
19       style="margin: 10px 0"
20       :data="demo.tableData"
21       @mounted="onMounted"
22       height="600"
23     >
24       <vxe-column width="40">
25         <template #default>
26           <span class="drag-btn">
27             <HolderOutlined />
28           </span>
29         </template>
30       </vxe-column>
31       <vxe-column field="TagName" title="文件夹名称" minWidth="250">
32         <template #default="{ row }">
33           <span class="my-d-f">
34             <div
35               v-if="row.systemFlag"
36               class="bookmark"
37               :style="{ backgroundColor: row.tagColor }"
38             ></div>
39             <div v-else>
40               <ColorPicker
41                 v-model="row.tagColor"
42                 :type="2"
43                 @change="fnRowColorChange($event, row)"
44               ></ColorPicker>
45             </div>
46             <a-tag class="ml-5" :color="row.tagColor">{{ row.tagName }}</a-tag>
47           </span>
48         </template>
49       </vxe-column>
50       <vxe-column field="age" title="操作" width="150">
51         <template #default="{ row }">
52           <a style="margin-right: 10px" @click="showModal('edit', row)">编辑</a>
53           <a style="margin-right: 10px" @click="fnDeleteRow(row)">删除</a>
54         </template>
55       </vxe-column>
56     </vxe-table>
57     <a-modal :width="300" v-model:open="open" :title="`${title}个人标签`" @ok="handleOk">
58       <a-form ref="formRef" :model="form" style="margin-top: 20px">
59         <a-form-item label="标签颜色" name="tagColor">
60           <ColorPicker v-model="form.tagColor" :type="2"></ColorPicker>
61         </a-form-item>
62         <a-form-item
63           label="标签名称"
64           name="tagName"
65           :rules="[{ required: true, message: '请输入标签名称', trigger: 'blur' }]"
66         >
67           <a-input v-model:value="form.tagName" placeholder="请输入标签名称" />
68         </a-form-item>
69       </a-form>
70     </a-modal>
71   </div>
72 </template>
73
74 <script lang="ts" setup>
75   import { ref, computed, onMounted, nextTick, onUnmounted, reactive } from 'vue';
76   import ColorPicker from '@/components/ColorPicker/index.vue';
77   import { addTagApi, deleteTagApi, updateTagApi, getTagApi } from '@/api/email/userList';
78
79   // 排序
80   import { HolderOutlined } from '@ant-design/icons-vue';
81   import Sortable from 'sortablejs';
82   let sortable: any;
83   const demo = reactive({
84     showHelpTip: false,
85     tableData: [],
86   });
87   const xTable = ref();
88   const rowDrop = () => {
89     const $table = xTable.value;
90     sortable = Sortable.create($table.$el.querySelector('.body--wrapper>.vxe-table--body tbody'), {
91       handle: '.drag-btn',
92       onEnd: (sortableEvent) => {
93         const newIndex = sortableEvent.newIndex as number;
94         const oldIndex = sortableEvent.oldIndex as number;
95         const currRow: Record<string, any> = demo.tableData.splice(oldIndex, 1)[0];
96         // demo.tableData.splice(newIndex, 0, currRow);
97         updateTagApi({
98           tagColor: currRow.tagColor,
99           tagName: currRow.tagName,
100           sortId: newIndex,
101           tagId: currRow.tagId,
102         })
103           .then(() => {
104             fnGetList();
105           })
106           .catch(() => {});
107       },
108     });
109   };
110
111   let initTime: any;
112   nextTick(() => {
113     // 加载完成之后在绑定拖动事件
114     initTime = setTimeout(() => {
115       rowDrop();
116     }, 500);
117   });
118
119   onUnmounted(() => {
120     clearTimeout(initTime);
121     if (sortable) {
122       sortable.destroy();
123     }
124   });
125
126   function fnGetList() {
127     getTagApi({}).then((res) => {
128       console.log(res);
129       demo.tableData = res.data;
130     });
131   }
132
133   import { useMessage } from '@/hooks/web/useMessage';
134
135   const { createMessage } = useMessage();
136
137   const open = ref(false);
138   const formRef = ref();
139
140   interface formType {
141     tagColor: string;
142     tagName: string;
143     tagType: number;
144     systemFlag: boolean;
145     tagId?: number;
146   }
147
148   const defaultForm: formType = {
149     tagColor: '#000000',
150     tagName: '',
151     tagType: 1,
152     systemFlag: false,
153   };
154
155   const form = ref<formType>({ ...defaultForm });
156
157   const title = ref('新建');
158   const signType = ref('add');
159
160   const showModal = (type: string, row) => {
161     signType.value = type;
162     open.value = true;
163
164     if (type == 'add') {
165       form.value = { ...defaultForm };
166     } else {
167       title.value = '编辑';
168       nextTick(() => {
169         formRef.value.resetFields();
170         form.value = {
171           tagColor: row.tagColor,
172           tagName: row.tagName,
173           tagType: row.tagType,
174           systemFlag: row.systemFlag,
175           tagId: row.tagId,
176         };
177       });
178     }
179   };
180
181   function fnDeleteRow(row) {
182     deleteTagApi({ tagId: row.tagId }).then((res) => {
183       if (res.code === 0) {
184         createMessage.success(res.msg);
185         fnGetList();
186       }
187     });
188   }
189
190   function handleOk() {
191     nextTick(() => {
192       formRef.value
193         .validate()
194         .then(() => {
195           const api = signType.value == 'add' ? addTagApi : updateTagApi;
196           api(form.value).then((res) => {
197             if (res.code === 0) {
198               createMessage.success(res.msg);
199               fnGetList();
200               open.value = false;
201             }
202           });
203         })
204         .catch(() => {});
205     });
206   }
207
208   function fnRowColorChange(color, row) {
209     const data = {
a9a03d 210       tagColor: color,
63d608 211       tagName: row.tagName,
H 212       tagType: row.tagType,
213       systemFlag: row.systemFlag,
214       tagId: row.tagId,
215     };
216     updateTagApi(data).then((res) => {
217       if (res.code === 0) {
218         createMessage.success(res.msg);
219         fnGetList();
220       }
221     });
222   }
223
224   onMounted(() => {
225     fnGetList();
226   });
227 </script>
228
229 <style scoped>
230   .sortable-row-demo .drag-btn {
231     font-size: 12px;
232     cursor: move;
233   }
234
235   .sortable-row-demo .vxe-body--row.sortable-ghost,
236   .sortable-row-demo .vxe-body--row.sortable-chosen {
237     background-color: #dfecfb;
238   }
239
240   .bookmark {
241     display: inline-block;
242     position: relative;
243     width: 14px;
244     height: 18px;
245     margin-right: 5px;
246     border-radius: 2px 2px 0 0; /* Rounded top corners */
247   }
248
249   .bookmark::after {
250     content: '';
251     position: absolute;
252     right: 0;
253     bottom: 0;
254     left: 0;
255     height: 8px;
256     background-color: #fff;
257     clip-path: polygon(50% 60%, 0% 100%, 100% 100%); /* Triangle at the bottom */
258   }
259 </style>