huangyinfeng
6 天以前 a9a03d64cf190188d3db04d14970fc0908b03491
提交 | 用户 | age
00fe0e 1 <template>
H 2   <a-drawer
3     v-model:open="drawerOpen"
4     :placement="placement"
a9a03d 5     width="68%"
00fe0e 6     :body-style="{ paddingBottom: '80px' }"
H 7     :footer-style="{ textAlign: 'right' }"
8     @after-open-change="afterOpenChange"
74a35f 9     @close="drawerClose"
00fe0e 10   >
H 11     <template #title>
a9a03d 12       <div>
cb21a5 13         <pageHeadLeft
H 14           :checked="true"
15           :selectAllRow="[{ docCode }]"
16           @nextNum="drawerClose"
17         ></pageHeadLeft>
a9a03d 18       </div>
63d608 19     </template>
H 20     <template #extra>
21       <div style="font-size: 16px">
22         共<span class="m-1">{{ props.allList.length }}</span
23         >封
24         <LeftOutlined style="padding: 0 20px" @click="fnPrev" />
25         <RightOutlined @click="fnNext" />
26       </div>
27     </template>
28     <template #footer>
29       <div style="display: flex">
30         <a-textarea autoSize size="large" v-model:value="content" placeholder="快速回复">
31           <template #prefix>
32             <RollbackOutlined style="color: #999" />
33           </template>
34         </a-textarea>
35         <a-button size="large" type="primary" style="margin-left: 10px" @click="fnQuickReply"
36           >发送
37         </a-button>
38       </div>
39     </template>
a9a03d 40     <div class="ct-top" :class="isOpen ? 'isOpenTop' : 'onOpenTop'">
H 41       <div class="title">
42         <div class="left">
43           <span style="margin-right: 20px; font-size: 24px; font-weight: 700">
44             <a-tooltip placement="bottom">
45               <template #title>
46                 <span>{{ tableRowData.subject }}</span>
47               </template>
48               <div :style="{ maxWidth: isOpen ? '300px' : '600px' }" class="text-ellipsis">{{
49                 tableRowData.subject
50               }}</div>
51             </a-tooltip>
52           </span>
53           <span style="margin-right: 10px; font-size: 16px">
54             <PushpinOutlined />
55           </span>
56         </div>
57         <div class="right">
58           <div class="tate">{{ formatToDateDay(tableRowData.receiveTime || tableRowData.updateTime) }}</div>
59           <div>
60             <a-dropdown-button>
61               <div v-if="!isDrafts">
62                 <span>
63                   <a-tooltip placement="bottom">
64                     <template #title>
65                       <span>回复</span>
66                     </template>
67                     <LeftOutlined @click="replyEmail(tableRowData, 'reply')" />
68                   </a-tooltip>
69                 </span>
70                 <a-divider type="vertical" />
71                 <span>
72                   <a-tooltip placement="bottom">
73                     <template #title>
74                       <span>快速回复</span>
75                     </template>
76                     <DoubleLeftOutlined />
77                   </a-tooltip>
78                 </span>
79               </div>
80               <div v-else>
81                 <span @click="replyEmail(tableRowData, 'edit')">再次编辑</span>
82               </div>
83
84               <template #overlay>
85                 <a-menu>
86                   <a-menu-item key="1">
87                     <UserOutlined />
88                     1st menu item
89                   </a-menu-item>
90                   <a-menu-item key="2">
91                     <UserOutlined />
92                     2nd menu item
93                   </a-menu-item>
94                   <a-menu-item key="3">
95                     <UserOutlined />
96                     3rd item
97                   </a-menu-item>
98                 </a-menu>
99               </template>
100             </a-dropdown-button>
101           </div>
102         </div>
103       </div>
104     </div>
105
63d608 106     <div>
cb21a5 107       <div class="flex-between">
H 108         <div class="ct-left p-2" :class="isOpen ? 'isOpen' : 'onOpen'">
a9a03d 109           <div class="user p-1 f-z-14" style="margin-top: 40px">
cb21a5 110             <div style="display: flex; align-items: center">
ccfd07 111               <a-avatar size="small" style="margin-right: 8px" src="#" />
a9a03d 112               <div>
H 113                 <span>{{ tableRowData.senderName }} {{ `<${tableRowData.sender}>` }}</span>
114               </div>
cb21a5 115               <span style="margin: 0 10px">发送</span>
H 116               <a-popover placement="bottom">
117                 <template #content>
118                   <div
119                     class="p-2"
120                     style="
121                       display: flex;
122                       align-items: center;
123                       border-bottom: 1px solid rgb(5 5 5 / 6%);
124                     "
125                   >
126                     <a-avatar size="small" style="margin-right: 8px" src="#" />
127                     <span style="color: #000; font-weight: 700">
128                       {{ `${tableRowData.receiver}` }}</span
129                     >
130                     <CopyOutlined />
131                   </div>
132                   <div class="display-flex p-2">
133                     <a-button type="link" size="small">往来邮件</a-button>
134                   </div>
135                 </template>
136                 <a-avatar size="small" style="margin-right: 8px" src="#" />
137                 {{ `${tableRowData.receiver}` }}<span>{{ `<${tableRowData.receiver}>` }}</span>
138               </a-popover>
139             </div>
a9a03d 140             <div type="info" class="p-2 f-z-14" style="margin-top: 10px; background-color: #e4f1ff">
cb21a5 141               <span>{{ `<${tableRowData.sender}>` }}</span>
H 142               <span>暂未查询到该客户的当地时间</span>
143               <!-- <span>2024-06-08 22:22</span> -->
144             </div>
a9a03d 145             <div class="ct">
H 146               <div v-if="tableRowData.content">
147                 <TinymcePw ref="TinymcePwRef" v-model="tableRowData.content" />
148               </div>
cb21a5 149             </div>
ccfd07 150           </div>
H 151         </div>
a9a03d 152         <div v-show="isOpen" class="ct-right">
H 153           <div style="position: relative">
154             <div style="position: absolute; top: 0; left: 10px">
155               <UserTips></UserTips>
156             </div>
157           </div>
158         </div>
ccfd07 159       </div>
cb21a5 160       <div @click="fuToggleContent" class="toggle-btn" :class="isOpen ? 'onIconOpen' : 'iconOpen'">
H 161         <LeftOutlined v-if="!isOpen" />
162         <RightOutlined v-else />
163       </div>
00fe0e 164     </div>
H 165   </a-drawer>
166 </template>
167
ccfd07 168 <script lang="ts" setup>
74a35f 169   name: 'drawerDetail';
ccfd07 170
74a35f 171   import { ref, watch, defineProps, defineEmits, computed } from 'vue';
H 172   import {
173     LeftOutlined,
174     RightOutlined,
175     DoubleLeftOutlined,
176     PushpinOutlined,
177     CopyOutlined,
178     UserOutlined,
179     RollbackOutlined,
180   } from '@ant-design/icons-vue';
181   import pageHeadLeft from './pageHeadLeft.vue';
a9a03d 182   import UserTips from '@/views/email/components/userTips/index.vue';
74a35f 183   import { TinymcePw } from '@/components/Tinymce';
H 184   import { getMailInfoApi, setQuickReplyAPi } from '@/api/email/userList';
185   import { useCollapseStore } from '@/store/modules/useCollapseStore';
186   import { nextTick } from 'vue';
187   import { formatToDateDay } from '@/utils/dateUtil';
188   import { useLoading } from '@/components/Loading';
00fe0e 189
74a35f 190   // const [open, close, setTip] = useLoading();
H 191   // 定义属性
192   interface Props {
193     modelValue: boolean;
194     title?: string;
195     placement?: 'left' | 'right' | 'top' | 'bottom';
196     idName?: string;
197     selectIds?: number[];
198     mailId?: string;
199     selectAllRow: Array<any>;
200     allList;
a9a03d 201     isDrafts?: boolean;
74a35f 202   }
ccfd07 203
74a35f 204   const props = defineProps<Props>();
ccfd07 205
74a35f 206   const tableRowData = ref<Record<string, any>>({});
H 207   const emit = defineEmits(['update:modelValue', 'updateData']);
208   const drawerOpen = ref(props.modelValue);
209   const TinymcePwRef = ref();
210   const docCode = ref(props.mailId);
211   watch(
212     () => props.mailId,
213     (newVal) => {
214       docCode.value = newVal;
215     },
216   );
217   // 监听属性变化
218   watch(
219     () => props.modelValue,
220     (newValue) => {
221       nextTick(() => {
a9a03d 222         drawerOpen.value = newValue;
H 223         setTimeout(() => {
224           console.log(newValue, '---------4', TinymcePwRef.value);
225           tableRowData.value.content = tableRowData.value.content;
226         }, 500);
74a35f 227       });
H 228       if (newValue) {
229         fnGetMailInfo(props.mailId);
230       }
231     },
232   );
233
234   function fnGetMailInfo(id) {
235     getMailInfoApi({ docCode: id })
236       .then((res) => {
a9a03d 237         nextTick(() => {
H 238           docCode.value = id;
239           tableRowData.value = res.data;
240         });
74a35f 241       })
H 242       .catch(() => {});
243   }
244   // 更新外部属性
245   watch(drawerOpen, (newValue) => {
246     emit('update:modelValue', newValue);
247   });
248
249   // 方法
250   const collapseStore = useCollapseStore();
251   const afterOpenChange = (bool: boolean) => {
252     if (bool) {
253       fnGetUserList({ page: 1, pageSize: 30 });
254     }
255     collapseStore.toggle(false);
256   };
257   const drawerClose = (e) => {
258     drawerOpen.value = false;
259   };
260
261   const fnGetUserList = (params) => {
262     // 调用接口逻辑
263   };
264
265   // 计算属性
266   const placement = computed(() => props.placement || 'right');
267
268   const content = ref('');
269   const isOpen = ref(false);
270
271   function fuToggleContent() {
272     isOpen.value = !isOpen.value;
273   }
274
275   function fnPrev() {
276     const id = getPrevId(props.allList, docCode.value);
277     fnGetMailInfo(id);
278   }
279   function fnNext() {
280     const id = getNextId(props.allList, docCode.value);
281     fnGetMailInfo(id);
282   }
283   function getNextId(list, id) {
284     const index = list.findIndex((item) => item.docCode === id);
285     if (index < list.length - 1) {
286       return list[index + 1].docCode;
287     } else {
288       return list[0].docCode;
289     }
290   }
291   function getPrevId(list, id) {
292     const index = list.findIndex((item) => item.docCode === id);
293     if (index > 0) {
294       return list[index - 1].docCode;
295     } else {
296       return list[list.length - 1].docCode;
297     }
298   }
299
300   import { useMessage } from '@/hooks/web/useMessage';
301
302   const { createMessage } = useMessage();
303   function fnQuickReply() {
304     if (!content.value) {
305       createMessage.warning('请输入回复内容');
306       return;
307     }
308     const data = {
309       docCode: docCode.value,
310       content: content.value,
311     };
312     setQuickReplyAPi(data).then((res) => {
313       if (res.code == 0) {
314         createMessage.success(res.msg);
315
316         fnGetMailInfo(props.mailId);
317       }
ccfd07 318     });
00fe0e 319   }
cb21a5 320   import { useRouter } from 'vue-router';
63d608 321   const router = useRouter();
a9a03d 322   function replyEmail(row, type) {
H 323     router.push({ path: '/email/edit', query: { docCode: row.docCode, type: type } });
63d608 324   }
00fe0e 325 </script>
H 326
327 <style scoped lang="less">
74a35f 328   .table-content {
00fe0e 329     display: flex;
74a35f 330     justify-content: space-between;
H 331     border-top: 1px solid #f0f0f0;
332
333     .left {
334       width: 80%;
335       height: 100%;
336       border-right: 1px solid #f0f0f0;
337     }
338
339     .right {
340       height: 100%;
341     }
00fe0e 342   }
H 343
74a35f 344   ::v-deep(.ant-table) {
H 345     min-height: 355px !important;
346   }
347
348   .title {
00fe0e 349     display: flex;
H 350     align-items: center;
351     justify-content: space-between;
352
74a35f 353     & .left {
H 354       display: flex;
355       align-items: center;
356       width: 50%;
357     }
358
359     & .right {
360       display: flex;
a9a03d 361       flex: 1;
74a35f 362       align-items: center;
a9a03d 363       justify-content: flex-end;
74a35f 364
H 365       & .tate {
a9a03d 366         margin-right: 10px;
74a35f 367       }
00fe0e 368     }
H 369   }
370
74a35f 371   .ct {
H 372     margin: 20px 0;
373   }
00fe0e 374
74a35f 375   .flex-between {
H 376     display: flex;
377   }
00fe0e 378
74a35f 379   .ct-left {
H 380     padding-right: 20px;
381   }
00fe0e 382
74a35f 383   .ct-right {
a9a03d 384     flex: 1;
74a35f 385   }
00fe0e 386
74a35f 387   .toggle-btn {
H 388     display: flex;
389     position: absolute;
390     z-index: 99;
391     top: 50%;
392     width: 20px;
393     height: 54px;
394     padding-left: 5px;
395     transform: translateY(-50%);
396     border: 1px solid #f0f0f0;
397     border-right: none;
398     border-radius: 10px 0 0 10px;
399     background: #fafafa;
400   }
00fe0e 401
74a35f 402   .onOpen {
H 403     width: 100%;
404   }
00fe0e 405
74a35f 406   .isOpen {
a9a03d 407     width: calc(100% - 420px);
H 408   }
409
410   .onOpenTop {
411     width: 98%;
412   }
413
414   .isOpenTop {
415     width: calc(98% - 460px);
74a35f 416   }
00fe0e 417
74a35f 418   .iconOpen {
H 419     right: 0%;
420   }
00fe0e 421
74a35f 422   .onIconOpen {
a9a03d 423     right: 425px;
74a35f 424   }
cb21a5 425
H 426   .ctb {
427     position: relative;
428   }
429
a9a03d 430   .ct-top {
cb21a5 431     position: absolute;
H 432     z-index: 99;
a9a03d 433     top: 57px;
H 434     left: 10px;
cb21a5 435     padding: 10px;
H 436     background: #fff;
437   }
a9a03d 438
H 439   .text-ellipsis {
440     overflow: hidden;
441     text-overflow: ellipsis;
442     white-space: nowrap;
443   }
444
445   .f-z-14 {
446     font-size: 12px;
447   }
00fe0e 448 </style>