mailDetail.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. <template>
  2. <div v-loading="loading" class="box">
  3. <div style="margin-bottom: 10px">
  4. <el-button
  5. :disabled="currentMailIndex === 0"
  6. @click="handleChangeEail('10')"
  7. >上一封</el-button
  8. >
  9. <el-button
  10. :disabled="currentMailIndex === allLength - 1"
  11. @click="handleChangeEail('20')"
  12. >下一封</el-button
  13. >
  14. <el-button type="primary" @click="handleReply('10')">回复</el-button>
  15. <el-button type="primary" @click="handleReply('30')">全部回复</el-button>
  16. <el-button type="warning" @click="handleReply('20')">转发</el-button>
  17. <el-button @click="handleReply('40')">再次编辑</el-button>
  18. <el-button @click="handleMove">移动</el-button>
  19. <el-button @click="handleRemove">删除</el-button>
  20. </div>
  21. <div class="top">
  22. <div class="top-row">
  23. <div class="label">发 件 人:</div>
  24. <div class="value">
  25. <span
  26. v-for="item in replyTo"
  27. :key="item.id"
  28. style="margin-right: 10px"
  29. >
  30. {{ item.email || item.personalName }}</span
  31. >
  32. </div>
  33. </div>
  34. <div class="top-row">
  35. <div class="label">收 件 人:</div>
  36. <div class="value">
  37. <span v-for="item in to" :key="item.id" style="margin-right: 10px">{{
  38. item.email || item.personalName
  39. }}</span>
  40. </div>
  41. </div>
  42. <div class="top-row" v-if="cc && cc.length > 0">
  43. <div class="label">抄 送 人:</div>
  44. <div class="value">
  45. <span v-for="item in cc" :key="item.id" style="margin-right: 10px">
  46. {{ item.email || item.personalName }}</span
  47. >
  48. </div>
  49. </div>
  50. <div class="top-row" v-if="bcc && bcc.length > 0">
  51. <div class="label">密 送 人:</div>
  52. <div class="value">
  53. <span v-for="item in bcc" :key="item.id" style="margin-right: 10px">
  54. {{ item.email || item.personalName }}</span
  55. >
  56. </div>
  57. </div>
  58. <div class="top-row">
  59. <div class="label">时 间:</div>
  60. <div class="value">
  61. {{ time }}
  62. </div>
  63. </div>
  64. <div class="top-row" v-if="fileList && fileList.length > 0">
  65. <div class="label">附 件:</div>
  66. <div class="value">
  67. <div
  68. v-for="(item, index) in fileList"
  69. style="margin-right: 20px; display: flex; align-items: center"
  70. :key="index"
  71. >
  72. <span style="cursor: pointer" @click="handleClickFile(item)">{{
  73. item.name
  74. }}</span>
  75. <span
  76. style="margin-left: 8px; cursor: pointer"
  77. @click="handleClickDownload(item)"
  78. ><el-icon color="#0084FF"><Download /></el-icon
  79. ></span>
  80. </div>
  81. </div>
  82. </div>
  83. </div>
  84. <div class="body">
  85. <iframe
  86. frameborder="0"
  87. allowTransparency="true"
  88. style="
  89. width: 99% !important;
  90. overflow-x: scroll;
  91. padding-top: 10px;
  92. height: 500px;
  93. "
  94. :srcdoc="showBodyText(detailsData.data.content)"
  95. :ref="'iframeText_' + mailStore.currentId"
  96. :id="'iframeText_' + mailStore.currentId"
  97. >
  98. </iframe>
  99. </div>
  100. <el-dialog
  101. title="移动邮件"
  102. v-model="myFolderDialog"
  103. width="300px"
  104. destroy-on-close
  105. v-loading="submitLoading"
  106. >
  107. <byForm
  108. :formConfig="myFolderFormConfig"
  109. :formOption="formOption"
  110. v-model="formData.myFolderData"
  111. :rules="rules"
  112. ref="myFolderForm"
  113. >
  114. </byForm>
  115. <template #footer>
  116. <el-button @click="myFolderDialog = false" size="large"
  117. >取 消</el-button
  118. >
  119. <el-button
  120. type="primary"
  121. @click="submitMyFolderForm()"
  122. size="large"
  123. :loading="submitLoading"
  124. >
  125. 确 定
  126. </el-button>
  127. </template>
  128. </el-dialog>
  129. </div>
  130. </template>
  131. <script setup>
  132. import useMailStore from "@/store/modules/mail";
  133. import byForm from "@/components/byForm/index";
  134. import { ElMessage, ElMessageBox } from "element-plus";
  135. const { proxy } = getCurrentInstance();
  136. const mailStore = useMailStore();
  137. let loading = ref(false);
  138. const detailsData = reactive({
  139. data: {},
  140. });
  141. const currentMailIndex = computed(() => mailStore.currentMailIndex);
  142. const allLength = computed(() => mailStore.mailDataList.length);
  143. const to = ref([]);
  144. const cc = ref([]);
  145. const bcc = ref([]);
  146. const replyTo = ref([]);
  147. const fileList = ref([]);
  148. const requestData = ref({});
  149. const time = ref("");
  150. // 移动文件夹
  151. const formOption = reactive({
  152. inline: true,
  153. labelWidth: 100,
  154. itemWidth: 100,
  155. });
  156. const myFolderForm = ref(null);
  157. const myFolderTreeData = ref([]);
  158. const myFolderDialog = ref(false);
  159. const submitLoading = ref(false);
  160. const editType = ref("add");
  161. const myFolderFormConfig = computed(() => [
  162. {
  163. type: "treeSelect",
  164. prop: "myFolderId",
  165. label: "文件夹",
  166. disabled: false,
  167. itemWidth: 100,
  168. data: myFolderTreeData.value,
  169. style: {
  170. width: "100%",
  171. },
  172. },
  173. ]);
  174. const formData = reactive({
  175. myFolderData: {},
  176. });
  177. const rules = ref({
  178. myFolderId: [{ required: true, message: "请选择文件夹", trigger: "change" }],
  179. });
  180. const getMyFolderTree = (flag) => {
  181. if (flag) {
  182. setTimeout(() => {
  183. proxy
  184. .post("/myFolder/tree", { mailboxId: mailStore.selectMail.id })
  185. .then((res) => {
  186. myFolderTreeData.value = res.map((x) => ({ ...x, value: x.id }));
  187. });
  188. }, 1000);
  189. } else {
  190. proxy
  191. .post("/myFolder/tree", { mailboxId: mailStore.selectMail.id })
  192. .then((res) => {
  193. myFolderTreeData.value = res.map((x) => ({ ...x, value: x.id }));
  194. });
  195. }
  196. };
  197. const handleMove = () => {
  198. formData.myFolderData.messageId = mailStore.currentMenu.messageId;
  199. myFolderDialog.value = true;
  200. };
  201. const handleRemove = () => {
  202. ElMessageBox.confirm(`此操作将删除该邮件, 是否继续?`, "提示", {
  203. confirmButtonText: "确定",
  204. cancelButtonText: "取消",
  205. type: "warning",
  206. }).then(() => {
  207. // 删除
  208. proxy
  209. .post("/mailService/deleteMail", {
  210. id: mailStore.currentMenu.messageId,
  211. type: mailStore.currentMenu.type,
  212. })
  213. .then((res) => {
  214. ElMessage({
  215. message: `操作成功!`,
  216. type: "success",
  217. });
  218. });
  219. });
  220. };
  221. const submitMyFolderForm = () => {
  222. myFolderForm.value.handleSubmit(() => {
  223. submitLoading.value = true;
  224. proxy.post("/myFolderMessage/add", formData.myFolderData).then(
  225. (res) => {
  226. ElMessage({
  227. message: `操作成功!`,
  228. type: "success",
  229. });
  230. myFolderDialog.value = false;
  231. submitLoading.value = false;
  232. getMyFolderTree(false);
  233. },
  234. (err) => {
  235. submitLoading.value = false;
  236. }
  237. );
  238. });
  239. };
  240. const getMailTag = () => {
  241. // proxy
  242. // .post("/myTagMessage/getListByMessageId", {
  243. // id: mailStore.currentMenu.messageId,
  244. // })
  245. // .then((res) => {
  246. // console.log(res, "ada");
  247. // });
  248. };
  249. const getDetails = (messageId) => {
  250. loading.value = true;
  251. proxy
  252. .post("/mailService/getMessageDetail", {
  253. type: mailStore.currentMenu.type,
  254. messageId,
  255. })
  256. .then((res) => {
  257. if (mailStore.currentMenu.time) {
  258. time.value = mailStore.currentMenu.time;
  259. }
  260. detailsData.data = res;
  261. to.value = res.messageAddressList.filter((x) => x.type === 1);
  262. cc.value = res.messageAddressList.filter((x) => x.type === 2);
  263. bcc.value = res.messageAddressList.filter((x) => x.type === 3);
  264. replyTo.value = res.messageAddressList.filter((x) => x.type === 4);
  265. fileList.value = res.messageAttachmentList;
  266. loading.value = false;
  267. });
  268. };
  269. const showBodyText = (text) => {
  270. if (text) {
  271. let val = JSON.parse(JSON.stringify(text));
  272. val = val.replace("body {", "tbody {");
  273. val = val.replace(
  274. "td, p, li, th {",
  275. "tbody td, tbody p, tbody li, tbody th {"
  276. );
  277. val = val.replace(
  278. /<p>/g,
  279. '<p style="margin-block-start: 0; margin-block-end: 0;">'
  280. );
  281. return val;
  282. } else {
  283. return text;
  284. }
  285. };
  286. const init = () => {
  287. //实时更换索引
  288. if (mailStore.currentMenu.messageId) {
  289. mailStore.currentMailIndex = mailStore.mailDataList.findIndex(
  290. (x) => x.id === mailStore.currentMenu.messageId
  291. );
  292. }
  293. getDetails(mailStore.currentMenu.messageId);
  294. };
  295. onMounted(() => {
  296. // init();
  297. });
  298. const handleReply = (pageType) => {
  299. // pageType 10为回复 20为转发 30为全部回复 40为再次编辑 0为写信
  300. let title = "";
  301. if (pageType === "10") {
  302. title = "回复";
  303. } else if (pageType === "20") {
  304. title = "转发";
  305. } else if (pageType === "30") {
  306. title = "全部回复";
  307. } else if (pageType === "40") {
  308. title = "再次编辑";
  309. }
  310. const menu = {
  311. title: title,
  312. type: mailStore.currentMenu.type,
  313. id: "write",
  314. pageType: pageType,
  315. details: {
  316. ...detailsData.data,
  317. ...mailStore.currentMenu.row,
  318. },
  319. };
  320. const index = mailStore.mailMenuList.findIndex((x) => x.id === menu.id);
  321. if (index >= 0) {
  322. mailStore.mailMenuList[index] = menu;
  323. } else {
  324. mailStore.mailMenuList.push(menu);
  325. }
  326. mailStore.currentMenu = menu;
  327. mailStore.currentId = menu.id;
  328. };
  329. const handleChangeEail = (type) => {
  330. if (type === "10") {
  331. mailStore.currentMailIndex = currentMailIndex.value - 1;
  332. } else if (type === "20") {
  333. mailStore.currentMailIndex = currentMailIndex.value + 1;
  334. }
  335. // 拿到更变索引之后的行数据
  336. const row = mailStore.mailDataList[mailStore.currentMailIndex];
  337. // 查当前菜单的数据
  338. const arr = mailStore.currentMenu.id.split(",");
  339. if (arr.length > 1) {
  340. const index = mailStore.mailMenuList.findIndex(
  341. (x) => x.messageId === arr[1]
  342. );
  343. const menu = {
  344. title: row.subject.slice(0, 4) + "...",
  345. type: mailStore.selectMail.type,
  346. messageId: row.id,
  347. id: "detail" + "," + row.id,
  348. time: row.sendDate,
  349. row: { ...row },
  350. };
  351. const menuItem = mailStore.mailMenuList.find((x) => x.id === menu.id);
  352. if (menuItem === undefined) {
  353. mailStore.mailMenuList[index] = menu;
  354. }
  355. mailStore.currentMenu = menu;
  356. mailStore.currentId = menu.id;
  357. }
  358. };
  359. const handleClickFile = (file) => {
  360. const path = file.path ? file.path : file.url ? file.url : "";
  361. if (path) {
  362. window.open(path, "_blank");
  363. }
  364. };
  365. const handleClickDownload = (file) => {
  366. let xhr = new XMLHttpRequest();
  367. //域名是华为云的
  368. xhr.open("GET", `${file.url}`, true);
  369. xhr.responseType = "blob";
  370. xhr.send();
  371. xhr.onreadystatechange = function () {
  372. if (xhr.readyState === 4 && xhr.status === 200) {
  373. let url = window.URL.createObjectURL(xhr.response);
  374. const a = document.createElement("a");
  375. a.href = url;
  376. a.download = file.name; // 下载后文件名
  377. a.style.display = "none";
  378. document.body.appendChild(a);
  379. a.click(); // 点击下载
  380. window.URL.revokeObjectURL(a.href);
  381. document.body.removeChild(a); // 下载完成移除元素
  382. }
  383. };
  384. };
  385. getMyFolderTree(true);
  386. getMailTag();
  387. defineExpose({
  388. initFn: init,
  389. });
  390. </script>
  391. <style lang="scss" scoped>
  392. .box {
  393. padding: 0 10px;
  394. font-size: 12px;
  395. .top {
  396. padding: 10px;
  397. background: #f1f1f1;
  398. .top-row {
  399. display: flex;
  400. margin-bottom: 10px;
  401. .label {
  402. min-width: 60px;
  403. color: #999999;
  404. text-align: right;
  405. }
  406. .value {
  407. flex: 1;
  408. color: #333333;
  409. font-weight: 700;
  410. margin-right: 10px;
  411. display: flex;
  412. }
  413. }
  414. }
  415. }
  416. </style>