left.vue 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216
  1. <template>
  2. <div class="left">
  3. <div class="top">
  4. <el-dropdown>
  5. <span class="mail">
  6. <el-badge
  7. :value="selectMail.allUnreadMessageCount"
  8. :max="99"
  9. class="item"
  10. >
  11. {{ selectMail.mailUser }}
  12. <el-icon class="el-icon--right" style="margin-right: 15px">
  13. <arrow-down />
  14. </el-icon>
  15. </el-badge>
  16. </span>
  17. <template #dropdown>
  18. <el-dropdown-menu>
  19. <el-dropdown-item
  20. v-for="item in mailList"
  21. :key="item.id"
  22. @click="handleClickMail(item)"
  23. >{{ item.mailUser }}</el-dropdown-item
  24. >
  25. </el-dropdown-menu>
  26. </template>
  27. </el-dropdown>
  28. <el-tabs v-model="activeName" class="demo-tabs" stretch>
  29. <el-tab-pane label="邮箱" name="first">
  30. <template #label>
  31. <div>
  32. <i
  33. class="iconfont icon-iconm_dianzyx"
  34. style="margin-right: 5px"
  35. ></i>
  36. <span>邮箱</span>
  37. </div>
  38. </template>
  39. </el-tab-pane>
  40. <el-tab-pane label="联系人" name="second">
  41. <template #label>
  42. <div>
  43. <i
  44. class="iconfont icon-icomm_contact"
  45. style="margin-right: 5px"
  46. ></i>
  47. <span>联系人</span>
  48. </div>
  49. </template>
  50. </el-tab-pane>
  51. <el-tab-pane label="客户" name="third">
  52. <template #label>
  53. <div>
  54. <i class="iconfont icon-icon_kh" style="margin-right: 5px"></i>
  55. <span>客户</span>
  56. </div>
  57. </template>
  58. </el-tab-pane>
  59. </el-tabs>
  60. <div>
  61. <el-button
  62. type="primary"
  63. style="width: 100%; font-size: 12px"
  64. @click="handleGoWrite()"
  65. >写信</el-button
  66. >
  67. </div>
  68. </div>
  69. <div class="body">
  70. <div v-if="activeName === 'first'">
  71. <ul class="mail-menu">
  72. <li
  73. class="menu-item"
  74. v-bind:class="{ 'select-menu': item.id === selectFloderId }"
  75. v-for="item in selectMail.mailFolderInfoListCopy"
  76. :key="item.id"
  77. @click="handleOpenMenu(item, '10')"
  78. >
  79. <i
  80. class="iconfont icon-iconm_inbox leftIcon"
  81. v-if="item.sort === 1"
  82. ></i>
  83. <i
  84. class="iconfont icon-iconm_unread leftIcon"
  85. v-else-if="item.sort === 2"
  86. ></i>
  87. <i
  88. class="iconfont icon-icomm_draftbox leftIcon"
  89. v-else-if="item.sort === 3"
  90. ></i>
  91. <i
  92. class="iconfont icon-iconm_sent leftIcon"
  93. v-else-if="item.sort === 4"
  94. ></i>
  95. <i
  96. class="iconfont icon-icomm_delete leftIcon"
  97. v-else-if="item.sort === 5"
  98. ></i>
  99. <i
  100. class="iconfont icon-iconm_ljyx leftIcon"
  101. v-else-if="item.sort === 6"
  102. ></i>
  103. <span style="margin-left: 5px">{{ item.name }}</span>
  104. <div v-if="item.sort === 1" class="badge">
  105. <span> {{ item.unreadMessageCount }} </span>
  106. </div>
  107. </li>
  108. </ul>
  109. <!-- 员工邮箱 -->
  110. <div
  111. class="tree"
  112. v-if="staffMailData[0] && staffMailData[0].children.length > 0"
  113. >
  114. <el-tree
  115. :data="staffMailData"
  116. node-key="id"
  117. :expand-on-click-node="false"
  118. default-expand-all
  119. @node-click="(data, node) => handleTreeNodeNewClick(data, node)"
  120. v-loading="staffLoading"
  121. >
  122. <template #default="{ node, data }">
  123. <span class="tree-content">
  124. <i
  125. class="iconfont icon-icomm_ygyx iconColor"
  126. v-if="data.id == '0'"
  127. style="margin-right: 5px"
  128. ></i>
  129. <span
  130. >{{ data.name }}
  131. <span v-if="data.userId && data.children.length === 0">
  132. (点击获取员工邮箱)</span
  133. ></span
  134. >
  135. <div v-if="data.isMailUser" class="badge">
  136. <span> {{ data.allUnreadMessageCount }} </span>
  137. </div>
  138. </span>
  139. </template>
  140. </el-tree>
  141. </div>
  142. <!-- 官方文件夹 -->
  143. <div
  144. class="tree"
  145. v-if="selectMail.otherFolder && selectMail.otherFolder.length > 0"
  146. >
  147. <el-tree
  148. :data="selectMail.otherFolder"
  149. node-key="id"
  150. default-expand-all
  151. :expand-on-click-node="false"
  152. @node-click="(data) => handleTreeNodeClick(data, 'official')"
  153. >
  154. <template #default="{ node, data }">
  155. <span class="tree-content">
  156. <i
  157. class="iconfont icon-iconm_gfwjj iconColor"
  158. v-if="data.id == '0'"
  159. style="margin-right: 5px"
  160. ></i>
  161. <span>{{ data.name }}</span>
  162. </span>
  163. </template></el-tree
  164. >
  165. </div>
  166. <!-- 我的文件夹 -->
  167. <div
  168. class="tree"
  169. v-if="myFolderTreeData && myFolderTreeData.length > 0"
  170. >
  171. <el-tree
  172. :data="myFolderTreeData"
  173. node-key="id"
  174. default-expand-all
  175. :expand-on-click-node="false"
  176. @node-click="(data) => handleTreeNodeClick(data, 'folder')"
  177. >
  178. <template #default="{ node, data }">
  179. <span class="tree-content">
  180. <i
  181. class="iconfont icon-icomm_wdwjj iconColor"
  182. v-if="data.id == '0'"
  183. style="margin-right: 5px"
  184. ></i>
  185. <span>{{ data.label }}</span>
  186. <el-popover
  187. placement="bottom-start"
  188. title=""
  189. :width="200"
  190. trigger="click"
  191. >
  192. <div default style="display: flex">
  193. <el-button
  194. size="small"
  195. @click.stop="handleEditFolder(data, 'add')"
  196. >添加</el-button
  197. >
  198. <el-button
  199. size="small"
  200. v-if="data.id != '0'"
  201. @click.stop="handleEditFolder(data, 'edit')"
  202. >编辑</el-button
  203. >
  204. <el-button
  205. size="small"
  206. v-if="data.id != '0'"
  207. @click.stop="handleDelFolder(data)"
  208. >删除</el-button
  209. >
  210. </div>
  211. <template #reference>
  212. <span
  213. class="iconfont icon_more iconColor"
  214. style="padding-bottom: 5px; margin-left: auto"
  215. >...</span
  216. >
  217. </template>
  218. </el-popover>
  219. </span>
  220. </template>
  221. </el-tree>
  222. </div>
  223. <!-- 我的标签 -->
  224. <div class="tree" v-if="tagsTreeData && tagsTreeData.length > 0">
  225. <el-tree
  226. :data="tagsTreeData"
  227. node-key="id"
  228. default-expand-all
  229. :expand-on-click-node="false"
  230. @node-click="(data) => handleTreeNodeClick(data, 'tag')"
  231. >
  232. <template #default="{ node, data }">
  233. <span class="tree-content">
  234. <i
  235. class="iconfont icon-icomm_label iconColor"
  236. v-if="data.id == '0'"
  237. style="margin-right: 5px"
  238. ></i>
  239. <span>{{ data.name }}</span>
  240. <el-popover
  241. placement="bottom-start"
  242. title=""
  243. :width="150"
  244. trigger="click"
  245. >
  246. <div default style="display: flex">
  247. <el-button
  248. size="small"
  249. v-if="data.id == '0'"
  250. @click.stop="handleEditTag(data, 'add')"
  251. >添加</el-button
  252. >
  253. <el-button
  254. size="small"
  255. v-if="data.id != '0'"
  256. @click.stop="handleEditTag(data, 'edit')"
  257. >编辑</el-button
  258. >
  259. <el-button
  260. size="small"
  261. v-if="data.id != '0'"
  262. @click.stop="handleDelTag(data)"
  263. >删除</el-button
  264. >
  265. </div>
  266. <template #reference>
  267. <span
  268. class="iconfont icon_more iconColor"
  269. style="padding-bottom: 5px; margin-left: auto"
  270. >...</span
  271. >
  272. </template>
  273. </el-popover>
  274. </span>
  275. </template>
  276. </el-tree>
  277. </div>
  278. </div>
  279. <div v-if="activeName === 'second'">
  280. <div
  281. class="tree"
  282. v-if="contactsTreeData && contactsTreeData.length > 0"
  283. style="border-top: none; margin-top: 0px"
  284. >
  285. <el-tree
  286. :data="contactsTreeData"
  287. node-key="id"
  288. default-expand-all
  289. :expand-on-click-node="false"
  290. @node-click="
  291. (data, node) => handleCustomerTreeClick(data, node, 'contacts')
  292. "
  293. v-loading="contactsTreeLoading"
  294. >
  295. <template #default="{ node, data }">
  296. <span class="tree-content">
  297. <span>{{ data.name }}</span>
  298. <el-popover
  299. placement="bottom-start"
  300. title=""
  301. :width="150"
  302. trigger="click"
  303. v-if="data.parentId === '0'"
  304. >
  305. <div default style="display: flex">
  306. <el-button
  307. size="small"
  308. @click.stop="handleEditContacts(data)"
  309. >编辑</el-button
  310. >
  311. <el-button
  312. size="small"
  313. @click.stop="handleDelContacts(data)"
  314. >删除</el-button
  315. >
  316. </div>
  317. <template #reference>
  318. <span
  319. class="iconfont icon_more iconColor"
  320. style="padding-bottom: 5px; margin-left: auto"
  321. >...</span
  322. >
  323. </template>
  324. </el-popover>
  325. </span>
  326. </template>
  327. </el-tree>
  328. </div>
  329. <div style="padding: 0 10px; margin-top: 15px">
  330. <el-button
  331. type="primary"
  332. plain
  333. :icon="Plus"
  334. style="width: 100%; font-size: 12px"
  335. @click="handleAddContact"
  336. >添加联系人</el-button
  337. >
  338. </div>
  339. </div>
  340. <div v-if="activeName === 'third'">
  341. <div
  342. class="tree"
  343. v-if="customerList && customerList.length > 0"
  344. style="border-top: none; margin-top: 0px"
  345. >
  346. <el-tree
  347. :data="customerList"
  348. node-key="id"
  349. :expand-on-click-node="false"
  350. default-expand-all
  351. @node-click="
  352. (data, node) => handleCustomerTreeClick(data, node, 'customer')
  353. "
  354. v-loading="customerLoading"
  355. >
  356. <template #default="{ node, data }">
  357. <span class="tree-content">
  358. <span v-if="data.parentId === '0'"
  359. >{{ data.name }}
  360. <span
  361. v-if="data.parentId === '0' && data.children.length === 0"
  362. >
  363. (点击获取客户邮箱)</span
  364. ></span
  365. >
  366. <span v-else> {{ data.name }} {{ data.email }} </span>
  367. </span>
  368. </template>
  369. </el-tree>
  370. </div>
  371. </div>
  372. </div>
  373. <el-dialog
  374. :title="editType === 'add' ? '添加文件夹' : '编辑文件夹'"
  375. v-model="myFolderDialog"
  376. width="300px"
  377. destroy-on-close
  378. v-loading="submitLoading"
  379. >
  380. <byForm
  381. :formConfig="myFolderFormConfig"
  382. :formOption="formOption"
  383. v-model="formData.myFolderData"
  384. :rules="rules"
  385. ref="myFolderForm"
  386. >
  387. </byForm>
  388. <template #footer>
  389. <el-button @click="myFolderDialog = false" size="large"
  390. >取 消</el-button
  391. >
  392. <el-button
  393. type="primary"
  394. @click="submitMyFolderForm()"
  395. size="large"
  396. :loading="submitLoading"
  397. >
  398. 确 定
  399. </el-button>
  400. </template>
  401. </el-dialog>
  402. <el-dialog
  403. :title="editType === 'add' ? '添加标签' : '编辑标签'"
  404. v-model="tagDialog"
  405. width="300px"
  406. destroy-on-close
  407. v-loading="submitLoading"
  408. >
  409. <byForm
  410. :formConfig="tagFormConfig"
  411. :formOption="formOption"
  412. v-model="formData.tagData"
  413. :rules="tagRules"
  414. ref="tagForm"
  415. >
  416. </byForm>
  417. <template #footer>
  418. <el-button @click="tagDialog = false" size="large">取 消</el-button>
  419. <el-button
  420. type="primary"
  421. @click="submitTagForm()"
  422. size="large"
  423. :loading="submitLoading"
  424. >
  425. 确 定
  426. </el-button>
  427. </template>
  428. </el-dialog>
  429. <el-dialog
  430. :title="editType === 'add' ? '添加联系人' : '编辑联系人'"
  431. v-model="contactsDialog"
  432. width="400px"
  433. destroy-on-close
  434. v-loading="submitLoading"
  435. >
  436. <byForm
  437. :formConfig="contactsFormConfig"
  438. :formOption="formOption"
  439. v-model="formData.contactsData"
  440. :rules="contactsRules"
  441. ref="contactsForm"
  442. >
  443. <template #mailSet>
  444. <div style="width: 100%">
  445. <el-button type="primary" @click="clickAddRow">添 加</el-button>
  446. <el-table
  447. :data="formData.contactsData.mailSet"
  448. style="width: 100%; margin-top: 16px"
  449. >
  450. <el-table-column label="电子邮箱">
  451. <template #default="{ row, $index }">
  452. <div style="width: 100%">
  453. <el-form-item
  454. :prop="'mailSet.' + $index + '.email'"
  455. :rules="contactsRules.email"
  456. :inline-message="true"
  457. >
  458. <el-input
  459. v-model="row.email"
  460. placeholder="请输入电子邮箱"
  461. />
  462. </el-form-item>
  463. </div>
  464. </template>
  465. </el-table-column>
  466. <el-table-column
  467. align="center"
  468. label="操作"
  469. width="80"
  470. fixed="right"
  471. >
  472. <template #default="{ row, $index }">
  473. <el-button
  474. type="primary"
  475. link
  476. @click="handleRemoveRow($index)"
  477. >删除</el-button
  478. >
  479. </template>
  480. </el-table-column>
  481. </el-table>
  482. </div>
  483. </template>
  484. </byForm>
  485. <template #footer>
  486. <el-button @click="contactsDialog = false" size="large"
  487. >取 消</el-button
  488. >
  489. <el-button
  490. type="primary"
  491. @click="submitContactsForm()"
  492. size="large"
  493. :loading="submitLoading"
  494. >
  495. 确 定
  496. </el-button>
  497. </template>
  498. </el-dialog>
  499. </div>
  500. </template>
  501. <script setup>
  502. import { Plus } from "@element-plus/icons-vue";
  503. import useMailStore from "@/store/modules/mail";
  504. import useUserStore from "@/store/modules/user";
  505. import byForm from "@/components/byForm/index";
  506. import { ElMessage, ElMessageBox } from "element-plus";
  507. const mailStore = useMailStore();
  508. const { proxy } = getCurrentInstance();
  509. let selectMail = ref({});
  510. let activeName = ref("first");
  511. const mailMapData = {
  512. inbox: ["INBOX"],
  513. unread: ["UNREAD"],
  514. draft: ["草稿箱", "Drafts", "[Gmail]/草稿"],
  515. sent: ["已发送", "Sent Messages", "[Gmail]/已发邮件"],
  516. delete: ["已删除", "Deleted Messages", "[Gmail]/已删除邮件"],
  517. waste: ["垃圾邮件", "Junk", "[Gmail]/垃圾邮件"],
  518. };
  519. let selectFloderId = ref("");
  520. const mailList = ref([]);
  521. const staffMailData = ref([
  522. {
  523. name: "员工邮箱",
  524. id: "0",
  525. children: [],
  526. },
  527. ]);
  528. const staffLoading = ref(false);
  529. const userList = ref([]);
  530. const formOption = reactive({
  531. inline: true,
  532. labelWidth: 100,
  533. itemWidth: 100,
  534. });
  535. const myFolderForm = ref(null);
  536. const myFolderTreeData = ref([]);
  537. const myFolderDialog = ref(false);
  538. const submitLoading = ref(false);
  539. const editType = ref("add");
  540. const myFolderFormConfig = computed(() => [
  541. {
  542. type: "input",
  543. prop: "name",
  544. label: "文件夹名称",
  545. disabled: false,
  546. itemWidth: 100,
  547. },
  548. ]);
  549. const formData = reactive({
  550. myFolderData: {},
  551. tagData: {},
  552. contactsData: {},
  553. });
  554. const rules = ref({
  555. name: [{ required: true, message: "请输入文件夹名称", trigger: "blur" }],
  556. });
  557. const tagForm = ref(null);
  558. const tagsTreeData = ref([]);
  559. const tagDialog = ref(false);
  560. const tagFormConfig = computed(() => [
  561. {
  562. type: "input",
  563. prop: "name",
  564. label: "标签名称",
  565. disabled: false,
  566. itemWidth: 100,
  567. },
  568. ]);
  569. const tagRules = ref({
  570. name: [{ required: true, message: "请输入标签名称", trigger: "blur" }],
  571. });
  572. const customerList = ref([]);
  573. const customerLoading = ref([]);
  574. const getCustomerList = () => {
  575. customerLoading.value = true;
  576. proxy.post("/myCustomer/list").then((res) => {
  577. customerList.value = res.map((x) => ({
  578. ...x,
  579. parentId: "0",
  580. children: [],
  581. }));
  582. customerLoading.value = false;
  583. });
  584. };
  585. const contactsTreeData = ref([]);
  586. const contactsTreeLoading = ref([]);
  587. const contactsForm = ref(null);
  588. const contactsDialog = ref(false);
  589. const contactsFormConfig = computed(() => [
  590. {
  591. type: "input",
  592. prop: "name",
  593. label: "联系人名称",
  594. disabled: false,
  595. itemWidth: 100,
  596. },
  597. {
  598. type: "slot",
  599. prop: "mailSet",
  600. slotName: "mailSet",
  601. },
  602. ]);
  603. const contactsRules = ref({
  604. name: [{ required: true, message: "请输入联系人名称", trigger: "blur" }],
  605. email: [{ required: true, message: "请输入电子邮箱", trigger: "blur" }],
  606. });
  607. const submitContactsForm = () => {
  608. contactsForm.value.handleSubmit(() => {
  609. if (formData.contactsData.mailSet.length > 0) {
  610. submitLoading.value = true;
  611. formData.contactsData.mailSet = formData.contactsData.mailSet
  612. .map((x) => x.email)
  613. .join();
  614. proxy
  615. .post("/myContactPerson/" + editType.value, formData.contactsData)
  616. .then(
  617. (res) => {
  618. ElMessage({
  619. message: `操作成功!`,
  620. type: "success",
  621. });
  622. contactsDialog.value = false;
  623. submitLoading.value = false;
  624. getContactsTreeData();
  625. },
  626. (err) => {
  627. submitLoading.value = false;
  628. }
  629. );
  630. } else {
  631. ElMessage({
  632. message: "请添加邮箱",
  633. type: "info",
  634. });
  635. }
  636. });
  637. };
  638. const clickAddRow = () => {
  639. formData.contactsData.mailSet.push({
  640. email: "",
  641. });
  642. };
  643. const handleRemoveRow = (index) => {
  644. formData.contactsData.mailSet.splice(index, 1);
  645. };
  646. const getContactsTreeData = () => {
  647. contactsTreeLoading.value = true;
  648. proxy.post("/myContactPerson/page").then((res) => {
  649. contactsTreeData.value = res.rows.map((x) => ({
  650. ...x,
  651. parentId: "0",
  652. children: x.mailSet.split(",").map((y) => ({ name: y })),
  653. }));
  654. contactsTreeLoading.value = false;
  655. });
  656. };
  657. const handleAddContact = () => {
  658. formData.contactsData = {
  659. name: "",
  660. mailSet: [],
  661. };
  662. editType.value = "add";
  663. contactsDialog.value = true;
  664. };
  665. const handleEditContacts = (data) => {
  666. editType.value = "edit";
  667. proxy.post("/myContactPerson/detail", { id: data.id }).then((res) => {
  668. res.mailSet = res.mailSet.split(",").map((x) => ({ email: x }));
  669. formData.contactsData = res;
  670. contactsDialog.value = true;
  671. });
  672. };
  673. const handleDelContacts = (data) => {
  674. ElMessageBox.confirm(`此操作将删除该联系人, 是否继续?`, "提示", {
  675. confirmButtonText: "确定",
  676. cancelButtonText: "取消",
  677. type: "warning",
  678. }).then(() => {
  679. // 删除
  680. proxy.post("/myContactPerson/delete", { id: data.id }).then((res) => {
  681. ElMessage({
  682. message: `操作成功!`,
  683. type: "success",
  684. });
  685. getContactsTreeData();
  686. });
  687. });
  688. };
  689. const getTagsList = () => {
  690. proxy
  691. .post("/myTag/page", {
  692. pageNum: 1,
  693. pageSize: 9999,
  694. id: useUserStore().user.userId,
  695. })
  696. .then((res) => {
  697. tagsTreeData.value = [
  698. {
  699. name: "我的标签",
  700. id: "0",
  701. children: res.rows,
  702. },
  703. ];
  704. });
  705. };
  706. const submitTagForm = () => {
  707. tagForm.value.handleSubmit(() => {
  708. submitLoading.value = true;
  709. proxy.post("/myTag/" + editType.value, formData.tagData).then(
  710. (res) => {
  711. ElMessage({
  712. message: `操作成功!`,
  713. type: "success",
  714. });
  715. tagDialog.value = false;
  716. submitLoading.value = false;
  717. getTagsList(selectMail.value);
  718. },
  719. (err) => {
  720. submitLoading.value = false;
  721. }
  722. );
  723. });
  724. };
  725. const handleEditTag = (data, type) => {
  726. editType.value = type;
  727. if (type === "add") {
  728. formData.tagData.name = "";
  729. formData.tagData.type = selectMail.value.type;
  730. formData.tagData.mailboxId = selectMail.value.id;
  731. } else {
  732. formData.tagData = data;
  733. }
  734. tagDialog.value = true;
  735. };
  736. const handleDelTag = (data) => {
  737. ElMessageBox.confirm(`此操作将删除该标签, 是否继续?`, "提示", {
  738. confirmButtonText: "确定",
  739. cancelButtonText: "取消",
  740. type: "warning",
  741. }).then(() => {
  742. // 删除
  743. proxy.post("/myTag/delete", { id: data.id }).then((res) => {
  744. ElMessage({
  745. message: `操作成功!`,
  746. type: "success",
  747. });
  748. getTagsList();
  749. });
  750. });
  751. };
  752. const getMyFolderTree = (data) => {
  753. proxy.post("/myFolder/tree", { mailboxId: data.id }).then((res) => {
  754. myFolderTreeData.value = [
  755. {
  756. label: "我的文件夹",
  757. id: "0",
  758. children: res,
  759. },
  760. ];
  761. });
  762. };
  763. const submitMyFolderForm = () => {
  764. myFolderForm.value.handleSubmit(() => {
  765. submitLoading.value = true;
  766. proxy.post("/myFolder/" + editType.value, formData.myFolderData).then(
  767. (res) => {
  768. ElMessage({
  769. message: `操作成功!`,
  770. type: "success",
  771. });
  772. myFolderDialog.value = false;
  773. submitLoading.value = false;
  774. getMyFolderTree(selectMail.value);
  775. },
  776. (err) => {
  777. submitLoading.value = false;
  778. }
  779. );
  780. });
  781. };
  782. const handleEditFolder = (data, type) => {
  783. formData.myFolderData = {};
  784. editType.value = type;
  785. if (type === "add") {
  786. formData.myFolderData.parentId = data.id;
  787. } else {
  788. formData.myFolderData = data;
  789. formData.myFolderData.name = data.label;
  790. }
  791. formData.myFolderData.type = selectMail.value.type;
  792. formData.myFolderData.mailboxId = selectMail.value.id;
  793. myFolderDialog.value = true;
  794. };
  795. const handleDelFolder = (data) => {
  796. ElMessageBox.confirm(`此操作将删除该文件夹, 是否继续?`, "提示", {
  797. confirmButtonText: "确定",
  798. cancelButtonText: "取消",
  799. type: "warning",
  800. }).then(() => {
  801. // 删除
  802. proxy.post("/myFolder/delete", { id: data.id }).then((res) => {
  803. ElMessage({
  804. message: `操作成功!`,
  805. type: "success",
  806. });
  807. getMyFolderTree(selectMail.value);
  808. });
  809. });
  810. };
  811. const handleMapMailListData = (arr) => {
  812. for (let i = 0; i < arr.length; i++) {
  813. const iele = arr[i];
  814. iele.mailFolderInfoListCopy = [];
  815. iele.otherFolder = [];
  816. iele.allUnreadMessageCount = 0;
  817. for (let j = 0; j < iele.mailFolderInfoList.length; j++) {
  818. const jele = iele.mailFolderInfoList[j];
  819. iele.allUnreadMessageCount += jele.unreadMessageCount;
  820. if (mailMapData["inbox"].includes(jele.name)) {
  821. iele.mailFolderInfoListCopy.push({
  822. ...jele,
  823. oldName: jele.name,
  824. name: "收件箱",
  825. sort: 1,
  826. });
  827. } else if (mailMapData["unread"].includes(jele.name)) {
  828. iele.mailFolderInfoListCopy.push({
  829. ...jele,
  830. oldName: jele.name,
  831. name: "未读邮件",
  832. sort: 2,
  833. });
  834. } else if (mailMapData["draft"].includes(jele.name)) {
  835. iele.mailFolderInfoListCopy.push({
  836. ...jele,
  837. oldName: jele.name,
  838. name: "草稿箱",
  839. sort: 3,
  840. });
  841. } else if (mailMapData["sent"].includes(jele.name)) {
  842. iele.mailFolderInfoListCopy.push({
  843. ...jele,
  844. oldName: jele.name,
  845. name: "已发送",
  846. sort: 4,
  847. });
  848. } else if (mailMapData["delete"].includes(jele.name)) {
  849. iele.mailFolderInfoListCopy.push({
  850. ...jele,
  851. oldName: jele.name,
  852. name: "已删除",
  853. sort: 5,
  854. });
  855. } else if (mailMapData["waste"].includes(jele.name)) {
  856. iele.mailFolderInfoListCopy.push({
  857. ...jele,
  858. oldName: jele.name,
  859. name: "垃圾邮件",
  860. sort: 6,
  861. });
  862. } else {
  863. iele.otherFolder.push(jele);
  864. }
  865. }
  866. if (iele.otherFolder.length > 0) {
  867. iele.otherFolder = [
  868. {
  869. name: "官方文件夹",
  870. id: "0",
  871. children: iele.otherFolder,
  872. },
  873. ];
  874. }
  875. iele.mailFolderInfoListCopy.sort((a, b) => a.sort - b.sort);
  876. }
  877. return arr;
  878. };
  879. const getMialList = () => {
  880. proxy.get("/mailService/getUserEmailList").then((res) => {
  881. const arr = handleMapMailListData(res.data);
  882. mailList.value = arr;
  883. mailStore.userMailList = arr;
  884. if (mailList.value.length) {
  885. // 默认赋值第一邮箱
  886. selectMail.value = mailList.value[0];
  887. mailStore.selectMail = mailList.value[0];
  888. // 获取我的文件夹树形
  889. getMyFolderTree(selectMail.value);
  890. // 默认打开第一邮箱文件夹
  891. if (selectMail.value.mailFolderInfoListCopy.length > 0) {
  892. if (mailStore.mailMenuList.length === 0) {
  893. handleOpenMenu(selectMail.value.mailFolderInfoListCopy[0], "10");
  894. }
  895. }
  896. }
  897. });
  898. proxy.post("/mailInfo/getUserList").then((res) => {
  899. if (res && res.length > 0) {
  900. res = res.map((x) => ({
  901. ...x,
  902. name: x.nickName,
  903. children: [],
  904. }));
  905. }
  906. staffMailData.value[0].children = res;
  907. });
  908. };
  909. const handleClickMail = (item, flag = true) => {
  910. mailStore.mailMenuList = [];
  911. selectMail.value = item;
  912. mailStore.selectMail = item;
  913. // 默认打开第一邮箱文件夹
  914. if (selectMail.value.mailFolderInfoListCopy.length > 0 && flag) {
  915. handleOpenMenu(selectMail.value.mailFolderInfoListCopy[0], "10");
  916. }
  917. };
  918. const changeFloderId = (val) => {
  919. selectFloderId.value = val;
  920. };
  921. const handleOpenMenu = (item, listPageType = "10") => {
  922. // 10为官方文件夹以及六个外侧文件夹 20为我的文件夹 30为标签文件夹
  923. selectFloderId.value = item.id;
  924. const menu = {
  925. oldName: item.oldName,
  926. unReadCount: item.unreadMessageCount || 0,
  927. title: item.name,
  928. type: selectMail.value.type,
  929. folderId: item.id,
  930. id: "folder" + "," + item.id,
  931. listPageType,
  932. };
  933. // 如没有这个菜单则push
  934. const menuItem = mailStore.mailMenuList.find((x) => x.id === menu.id);
  935. if (menuItem === undefined) {
  936. mailStore.mailMenuList.push(menu);
  937. }
  938. // 更新当前选择的tab数据和tab的Id值
  939. mailStore.currentMenu = menu;
  940. mailStore.currentId = menu.id;
  941. };
  942. const handleGoWrite = (mail = {}, pageType = "0") => {
  943. const menu = {
  944. title: "写信",
  945. type: selectMail.value.type,
  946. id: "write",
  947. pageType,
  948. };
  949. if (mail) {
  950. menu.reMail = mail;
  951. }
  952. const index = mailStore.mailMenuList.findIndex((x) => x.id === menu.id);
  953. if (index >= 0) {
  954. mailStore.mailMenuList[index] = menu;
  955. } else {
  956. mailStore.mailMenuList.push(menu);
  957. }
  958. mailStore.currentMenu = menu;
  959. mailStore.currentId = menu.id;
  960. };
  961. const handleTreeNodeClick = (data, type) => {
  962. if (data.id != "0") {
  963. let menuData = {
  964. id: data.id,
  965. };
  966. let listPageType = "10";
  967. if (type === "official") {
  968. menuData.name = data.name;
  969. } else if (type === "folder") {
  970. menuData.name = data.label;
  971. listPageType = "20";
  972. } else if (type === "tag") {
  973. menuData.name = data.name;
  974. listPageType = "30";
  975. }
  976. handleOpenMenu(menuData, listPageType);
  977. }
  978. };
  979. const clickTreeMail = (data, node) => {
  980. let mailData = node.parent.data;
  981. if (mailStore.selectMail.id === mailData.id) {
  982. const menuData = {
  983. id: data.id,
  984. name: data.name,
  985. };
  986. handleOpenMenu(menuData, "10");
  987. } else {
  988. handleClickMail(mailData, false);
  989. handleOpenMenu(data, "10");
  990. }
  991. };
  992. const handleTreeNodeNewClick = (data, node) => {
  993. if (data.id == "0") {
  994. return;
  995. } else if (data.userId) {
  996. const index = staffMailData.value[0].children.findIndex(
  997. (x) => x.userId === data.userId
  998. );
  999. if (index >= 0) {
  1000. if (
  1001. staffMailData.value[0].children[index].children &&
  1002. staffMailData.value[0].children[index].children.length > 0
  1003. ) {
  1004. return;
  1005. } else {
  1006. staffLoading.value = true;
  1007. proxy.post("/mailInfo/getUserEmailList", { id: data.userId }).then(
  1008. (res) => {
  1009. let arr = handleMapMailListData(res);
  1010. arr = arr.map((x) => ({
  1011. ...x,
  1012. name: x.mailUser,
  1013. isMailUser: true,
  1014. children: x.mailFolderInfoList.map((x) => ({
  1015. ...x,
  1016. isFolder: true,
  1017. })),
  1018. }));
  1019. staffMailData.value[0].children[index].children = arr;
  1020. setTimeout(() => {
  1021. staffLoading.value = false;
  1022. }, 200);
  1023. },
  1024. (err) => {
  1025. staffLoading.value = false;
  1026. return ElMessage({
  1027. message: `获取员工邮箱失败,请联系管理员`,
  1028. type: "info",
  1029. });
  1030. }
  1031. );
  1032. }
  1033. }
  1034. } else if (data.isFolder) {
  1035. clickTreeMail(data, node);
  1036. }
  1037. };
  1038. const handleCustomerTreeClick = (data, node, type) => {
  1039. if (type === "customer") {
  1040. if (data.parentId === "0") {
  1041. const index = customerList.value.findIndex((x) => x.id === data.id);
  1042. if (index !== -1 && customerList.value[index].children.length === 0) {
  1043. customerLoading.value = true;
  1044. proxy.post("/customer/detail", { id: data.id }).then((res) => {
  1045. if (res.customerUserList && res.customerUserList.length > 0) {
  1046. customerList.value[index].children = res.customerUserList;
  1047. }
  1048. customerLoading.value = false;
  1049. });
  1050. }
  1051. } else {
  1052. handleGoWrite({ email: data.email, personal: data.name }, "0");
  1053. }
  1054. } else if (type === "contacts") {
  1055. if (data.parentId === "0") {
  1056. return;
  1057. } else {
  1058. handleGoWrite({ email: data.name, personal: node.parent.data.name }, "0");
  1059. }
  1060. }
  1061. };
  1062. onMounted(() => {
  1063. getMialList();
  1064. getCustomerList();
  1065. getTagsList();
  1066. getContactsTreeData();
  1067. });
  1068. defineExpose({
  1069. handleGoWrite,
  1070. changeFloderId,
  1071. });
  1072. </script>
  1073. <style lang="scss" scoped>
  1074. .left {
  1075. font-size: 12px;
  1076. .top {
  1077. padding: 10px;
  1078. text-align: center;
  1079. border-bottom: 1px solid #ddd;
  1080. .mail {
  1081. color: #333333;
  1082. font-weight: 700;
  1083. font-size: 14px;
  1084. }
  1085. }
  1086. .body {
  1087. height: calc(100vh - 260px);
  1088. overflow: auto;
  1089. // padding: 10px;
  1090. .mail-menu {
  1091. list-style: none;
  1092. margin-block-start: 0;
  1093. margin-block-end: 0;
  1094. padding: 0px;
  1095. padding: 10px 10px 0 10px;
  1096. .menu-item {
  1097. display: flex;
  1098. align-items: center;
  1099. font-weight: 700;
  1100. padding-left: 10px;
  1101. font-size: 12px;
  1102. width: 100%;
  1103. height: 40px;
  1104. line-height: 40px;
  1105. border-radius: 3px;
  1106. color: #333333;
  1107. cursor: pointer;
  1108. &:hover {
  1109. background: #ddedfe;
  1110. }
  1111. .leftIcon {
  1112. font-size: 16px;
  1113. color: #999999;
  1114. }
  1115. }
  1116. }
  1117. }
  1118. }
  1119. .select-menu {
  1120. // background: #ddedfe;
  1121. color: #0084ff !important;
  1122. .leftIcon {
  1123. color: #0084ff !important;
  1124. }
  1125. }
  1126. .tree {
  1127. margin-top: 10px;
  1128. border-top: 1px solid #ddd;
  1129. padding: 10px 10px 0 10px;
  1130. .tree-content {
  1131. width: 100%;
  1132. display: flex;
  1133. // justify-content: space-between;
  1134. padding-right: 10px;
  1135. align-items: center;
  1136. .iconColor {
  1137. color: #666 !important;
  1138. }
  1139. }
  1140. }
  1141. .badge {
  1142. background: #eeeeee;
  1143. height: 20px;
  1144. width: 30px;
  1145. border-radius: 10px;
  1146. line-height: 20px;
  1147. text-align: center;
  1148. font-weight: normal;
  1149. margin-left: auto;
  1150. margin-right: 10px;
  1151. span {
  1152. color: #666666;
  1153. }
  1154. }
  1155. </style>
  1156. <style lang="scss">
  1157. .body {
  1158. .el-tree-node__content {
  1159. font-weight: 700;
  1160. color: #333333 !important;
  1161. font-size: 12px !important;
  1162. }
  1163. }
  1164. .top {
  1165. .el-badge__content.is-fixed {
  1166. top: 8px;
  1167. }
  1168. .el-tabs__item {
  1169. color: #616161;
  1170. font-size: 12px;
  1171. }
  1172. .el-tabs__item:hover {
  1173. color: #409eff;
  1174. }
  1175. .el-tabs__item.is-active {
  1176. color: #409eff;
  1177. }
  1178. }
  1179. </style>