mailList.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. <template>
  2. <div>
  3. <div
  4. style="padding-left: 20px; display: flex; align-items: center"
  5. v-loading="btnLoading"
  6. >
  7. <el-icon @click="handleRefresh" style="cursor: pointer">
  8. <Refresh />
  9. </el-icon>
  10. <div class="vertical-line"></div>
  11. <div>
  12. <el-checkbox
  13. v-model="isCheckAll"
  14. label="全选"
  15. size="default"
  16. @change="handleChangeCheckAll"
  17. />
  18. </div>
  19. <div style="color: #666666">
  20. <span
  21. >(共 {{ tableData.pagination.total }} 封,其中<span
  22. style="color: #39c55a"
  23. >
  24. 未读邮件 </span
  25. >{{ unReadCount }} 封)</span
  26. >
  27. </div>
  28. <el-button
  29. @click="handleSetAllRead"
  30. :disabled="selectData.length === 0"
  31. style="margin-left: 10px"
  32. >全部标为已读</el-button
  33. >
  34. <el-select
  35. v-model="selectTag"
  36. placeholder="标记为"
  37. style="margin: 0 10px; width: 120px"
  38. :disabled="selectData.length === 0"
  39. @change="handleSetTag"
  40. >
  41. <el-option
  42. v-for="item in tagData"
  43. :key="item.id"
  44. :label="item.name"
  45. :value="item.id"
  46. />
  47. </el-select>
  48. <el-tree-select
  49. v-model="selectFolder"
  50. :data="myFolderTreeData"
  51. :disabled="selectData.length === 0"
  52. placeholder="移动到"
  53. style="margin-right: 10px; width: 120px"
  54. check-strictly
  55. :render-after-expand="false"
  56. @change="handleSetFolder"
  57. />
  58. <el-button @click="handleDeleteAll" :disabled="selectData.length === 0"
  59. >删除</el-button
  60. >
  61. </div>
  62. <div style="padding: 10px 15px; width: 100%">
  63. <el-table
  64. :data="tableData.data"
  65. style="width: 100%"
  66. :height="tableHeight"
  67. @selection-change="handleSelectionChange"
  68. v-loading="loading"
  69. >
  70. <el-table-column label=" " width="40" align="center">
  71. <template #default="{ row, $index }">
  72. <div>
  73. <el-checkbox
  74. v-model="row.isCheck"
  75. label=""
  76. size="default"
  77. @change="handleChangeCheck"
  78. />
  79. </div>
  80. </template>
  81. </el-table-column>
  82. <el-table-column label="状态" width="70">
  83. <template #default="{ row, $index }">
  84. <div style="cursor: pointer" @click="handleRowClick(row, $index)">
  85. <span v-if="row.flags && !row.flags.includes('6')">
  86. <img
  87. src="@/assets/images/mail/message.png"
  88. alt=""
  89. title="未读"
  90. class="messageImg"
  91. />
  92. </span>
  93. <span
  94. v-if="
  95. row.flags !== undefined &&
  96. row.flags !== null &&
  97. row.flags === ''
  98. "
  99. >
  100. <img
  101. src="@/assets/images/mail/message.png"
  102. alt=""
  103. title="未读"
  104. class="messageImg"
  105. />
  106. </span>
  107. <span
  108. v-if="
  109. row.flags &&
  110. row.flags.includes('6') &&
  111. row.flags.includes('1')
  112. "
  113. >
  114. <img
  115. src="@/assets/images/mail/replied.png"
  116. alt=""
  117. title="已回复"
  118. class="messageImg"
  119. />
  120. </span>
  121. <span v-if="row.flags && row.flags.includes('6')">
  122. <img
  123. src="@/assets/images/mail/message-open.png"
  124. alt=""
  125. title="已读"
  126. class="messageImg"
  127. />
  128. </span>
  129. </div>
  130. </template>
  131. </el-table-column>
  132. <el-table-column prop="fromPersonalName" label="发件人" width="150">
  133. <template #default="{ row, $index }">
  134. <div class="contentClass" @click="handleRowClick(row, $index)">
  135. {{ row.fromPersonalName }}
  136. </div>
  137. </template>
  138. </el-table-column>
  139. <el-table-column prop="fromEmail" label="发件人地址" width="210">
  140. <template #default="{ row, $index }">
  141. <el-tooltip
  142. class="box-item"
  143. effect="dark"
  144. :content="row.fromEmail"
  145. placement="top"
  146. >
  147. <div class="contentClass" @click="handleRowClick(row, $index)">
  148. {{ row.fromEmail }}
  149. </div>
  150. </el-tooltip>
  151. </template>
  152. </el-table-column>
  153. <el-table-column prop="subject" label="主题">
  154. <template #default="{ row, $index }">
  155. <div
  156. class="contentClass"
  157. @click="handleRowClick(row, $index)"
  158. :style="{
  159. 'font-weight':
  160. (row.flags && !row.flags.includes('6')) ||
  161. (row.flags !== undefined &&
  162. row.flags !== null &&
  163. row.flags === '')
  164. ? 700
  165. : '',
  166. }"
  167. >
  168. {{ row.subject }}
  169. </div>
  170. </template>
  171. </el-table-column>
  172. <el-table-column prop="sendDate" label="时间" width="160">
  173. <template #default="{ row, $index }">
  174. <div style="cursor: pointer" @click="handleRowClick(row, $index)">
  175. {{ row.sendDate }}
  176. </div>
  177. </template>
  178. </el-table-column>
  179. </el-table>
  180. <el-pagination
  181. style="margin-top: 15px"
  182. v-model:current-page="tableData.pagination.pageNum"
  183. v-model:page-size="tableData.pagination.pageSize"
  184. :page-sizes="[15, 30, 50, 100]"
  185. layout="sizes, prev, pager, next"
  186. :total="tableData.pagination.total"
  187. prev-text="上一页"
  188. next-text="下一页"
  189. @current-change="handleCurrentChange"
  190. @size-change="handleSizeChange"
  191. />
  192. </div>
  193. </div>
  194. </template>
  195. <script setup>
  196. import byTable from "@/components/byTable/index";
  197. import useMailStore from "@/store/modules/mail";
  198. import useUserStore from "@/store/modules/user";
  199. import { ElMessage, ElMessageBox } from "element-plus";
  200. const { proxy } = getCurrentInstance();
  201. const mailStore = useMailStore();
  202. let loading = ref(false);
  203. const tableHeight = ref(0);
  204. const getTableHeight = () => {
  205. tableHeight.value = window.innerHeight - 280;
  206. };
  207. getTableHeight();
  208. window.addEventListener("resize", () => {
  209. getTableHeight();
  210. });
  211. const tableData = reactive({
  212. data: [],
  213. pagination: {
  214. pageNum: 1,
  215. pageSize: 15,
  216. total: 0,
  217. },
  218. });
  219. const unReadCount = computed(() => mailStore.currentMenu.unReadCount);
  220. const config = computed(() => {
  221. return [
  222. {
  223. attrs: {
  224. label: "状态",
  225. slot: "icon",
  226. width: 70,
  227. },
  228. },
  229. {
  230. attrs: {
  231. label: "发件人",
  232. prop: "fromPersonalName",
  233. },
  234. },
  235. {
  236. attrs: {
  237. label: "发件人地址",
  238. prop: "fromEmail",
  239. },
  240. },
  241. {
  242. attrs: {
  243. label: "主题",
  244. prop: "subject",
  245. },
  246. },
  247. {
  248. attrs: {
  249. label: "时间",
  250. prop: "sendDate",
  251. },
  252. },
  253. ];
  254. });
  255. const getList = () => {
  256. if (mailStore.currentMenu.listPageType === "10") {
  257. loading.value = true;
  258. proxy
  259. .post("/mailService/getMessagePage", {
  260. ...mailStore.currentMenu,
  261. ...tableData.pagination,
  262. })
  263. .then((res) => {
  264. tableData.data = res.rows.map((x) => ({ ...x, isCheck: false }));
  265. mailStore.mailDataList = res.rows.map((x) => ({
  266. ...x,
  267. isCheck: false,
  268. }));
  269. tableData.pagination.total = res.total;
  270. loading.value = false;
  271. });
  272. } else if (mailStore.currentMenu.listPageType === "20") {
  273. loading.value = true;
  274. proxy
  275. .post("/myFolderMessage/page", {
  276. myFolderId: mailStore.currentMenu.folderId,
  277. type: mailStore.selectMail.type,
  278. ...tableData.pagination,
  279. })
  280. .then((res) => {
  281. tableData.data = res.rows.map((x) => ({
  282. ...x,
  283. isCheck: false,
  284. }));
  285. mailStore.mailDataList = res.rows.map((x) => ({
  286. ...x,
  287. isCheck: false,
  288. }));
  289. tableData.pagination.total = res.total;
  290. loading.value = false;
  291. });
  292. } else if (mailStore.currentMenu.listPageType === "30") {
  293. loading.value = true;
  294. proxy
  295. .post("/myTagMessage/page", {
  296. myTagId: mailStore.currentMenu.folderId,
  297. type: mailStore.selectMail.type,
  298. ...tableData.pagination,
  299. })
  300. .then((res) => {
  301. tableData.data = res.rows.map((x) => ({
  302. ...x,
  303. isCheck: false,
  304. }));
  305. mailStore.mailDataList = res.rows.map((x) => ({
  306. ...x,
  307. isCheck: false,
  308. }));
  309. tableData.pagination.total = res.total;
  310. loading.value = false;
  311. });
  312. }
  313. };
  314. const handleRefresh = () => {
  315. tableData.pagination = {
  316. pageNum: 1,
  317. pageSize: 15,
  318. };
  319. // getList();
  320. };
  321. const handleRowClick = (row, index) => {
  322. mailStore.currentMailIndex = index;
  323. const menu = {
  324. title: row.subject.slice(0, 4) + "...",
  325. type: mailStore.selectMail.type,
  326. messageId: row.id,
  327. id: "detail" + "," + row.id,
  328. time: row.sendDate,
  329. subject: row.subject,
  330. row: { ...row },
  331. };
  332. const menuItem = mailStore.mailMenuList.find((x) => x.id === menu.id);
  333. if (menuItem === undefined) {
  334. mailStore.mailMenuList.push(menu);
  335. }
  336. mailStore.currentMenu = menu;
  337. mailStore.currentId = menu.id;
  338. };
  339. const init = () => {
  340. getList();
  341. };
  342. const handleCurrentChange = (val) => {
  343. tableData.pagination.pageNum = val;
  344. getList();
  345. };
  346. const handleSizeChange = (val) => {
  347. tableData.pagination.pageSize = val;
  348. getList();
  349. };
  350. const myFolderTreeData = ref([]);
  351. const tagData = ref([]);
  352. const handleTreeData = (arr) => {
  353. for (let i = 0; i < arr.length; i++) {
  354. const e = arr[i];
  355. e.value = e.id;
  356. if (e.children && e.children.length > 0) {
  357. e.children = handleTreeData(e.children);
  358. }
  359. }
  360. return arr;
  361. };
  362. const getOtherData = () => {
  363. setTimeout(() => {
  364. proxy
  365. .post("/myFolder/tree", { mailboxId: mailStore.selectMail.id })
  366. .then((res) => {
  367. myFolderTreeData.value = handleTreeData(res);
  368. });
  369. }, 1000);
  370. setTimeout(() => {
  371. proxy
  372. .post("/myTag/page", {
  373. pageNum: 1,
  374. pageSize: 9999,
  375. id: useUserStore().user.userId,
  376. })
  377. .then((res) => {
  378. tagData.value = res.rows;
  379. });
  380. }, 1000);
  381. };
  382. getOtherData();
  383. const isCheckAll = ref(false);
  384. const selectTag = ref("");
  385. const selectFolder = ref("");
  386. const selectData = ref([]);
  387. const handleChangeCheck = () => {
  388. selectData.value = tableData.data.filter((x) => x.isCheck === true);
  389. if (selectData.value.length === tableData.data.length) {
  390. isCheckAll.value = true;
  391. }
  392. };
  393. const handleChangeCheckAll = () => {
  394. tableData.data.forEach((x) => {
  395. x.isCheck = isCheckAll.value;
  396. });
  397. if (isCheckAll.value) {
  398. selectData.value = tableData.data;
  399. } else {
  400. selectData.value = [];
  401. }
  402. };
  403. const btnLoading = ref(false);
  404. const handleSetAllRead = () => {
  405. btnLoading.value = true;
  406. const uidList = selectData.value.map((x) => x.id);
  407. const data = {
  408. folderName: mailStore.currentMenu.oldName,
  409. uidList,
  410. mailboxId: mailStore.selectMail.id,
  411. type: mailStore.selectMail.type,
  412. };
  413. proxy.post("/mailService/setSeen", data).then(
  414. (res) => {
  415. ElMessage({
  416. message: `操作成功!`,
  417. type: "success",
  418. });
  419. btnLoading.value = false;
  420. },
  421. (err) => {
  422. btnLoading.value = false;
  423. }
  424. );
  425. };
  426. const handleSetTag = (val) => {
  427. if (!val) return;
  428. btnLoading.value = true;
  429. const messageIdList = selectData.value.map((x) => x.id);
  430. const data = {
  431. myTagId: val,
  432. messageIdList,
  433. };
  434. proxy.post("/myTagMessage/addBath", data).then(
  435. (res) => {
  436. ElMessage({
  437. message: `操作成功!`,
  438. type: "success",
  439. });
  440. selectTag.value = "";
  441. btnLoading.value = false;
  442. },
  443. (err) => {
  444. btnLoading.value = false;
  445. }
  446. );
  447. };
  448. const handleSetFolder = (val) => {
  449. if (!val) return;
  450. btnLoading.value = true;
  451. const messageIdList = selectData.value.map((x) => x.id);
  452. const data = {
  453. myFolderId: val,
  454. messageIdList,
  455. };
  456. proxy.post("/myFolderMessage/addBath", data).then(
  457. (res) => {
  458. ElMessage({
  459. message: `操作成功!`,
  460. type: "success",
  461. });
  462. selectFolder.value = "";
  463. btnLoading.value = false;
  464. },
  465. (err) => {
  466. btnLoading.value = false;
  467. }
  468. );
  469. };
  470. const handleDeleteAll = () => {
  471. ElMessageBox.confirm(`此操作将删除选中的邮件, 是否继续?`, "提示", {
  472. confirmButtonText: "确定",
  473. cancelButtonText: "取消",
  474. type: "warning",
  475. }).then(() => {
  476. btnLoading.value = true;
  477. const idList = selectData.value.map((x) => x.id);
  478. const data = {
  479. type: mailStore.selectMail.type,
  480. idList,
  481. };
  482. proxy.post("/mailService/deleteBatchMail", data).then(
  483. (res) => {
  484. ElMessage({
  485. message: `操作成功!`,
  486. type: "success",
  487. });
  488. btnLoading.value = false;
  489. selectData.value = [];
  490. getList();
  491. },
  492. (err) => {
  493. btnLoading.value = false;
  494. }
  495. );
  496. });
  497. };
  498. defineExpose({
  499. initFn: init,
  500. });
  501. </script>
  502. <style lang="scss" scoped>
  503. // * {
  504. // font-size: 12px;
  505. // }
  506. .messageImg {
  507. width: 18px;
  508. height: 18px;
  509. transform: translateY(5px);
  510. }
  511. .el-pagination {
  512. padding-left: 30vw;
  513. }
  514. .contentClass {
  515. cursor: pointer;
  516. overflow: hidden;
  517. white-space: nowrap;
  518. text-overflow: ellipsis;
  519. }
  520. .vertical-line {
  521. width: 2px;
  522. height: 14px;
  523. background: #dddddd;
  524. margin: 0 10px;
  525. }
  526. </style>