order.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. <template>
  2. <div class="list-box">
  3. <div class="titleBox">
  4. <div class="titleBox_l">My order</div>
  5. <div class="titleBox_r">
  6. <div class="titleBox_r_l">
  7. <n-input v-model:value="keyword" type="text" class="custom-placeholder" clearable placeholder="Please enter your order number for inquiry" />
  8. </div>
  9. <div class="titleBox_r_r">
  10. Search
  11. </div>
  12. </div>
  13. </div>
  14. <div class="list">
  15. <div class="item" v-for="item in pageData.list" :key="item.id">
  16. <div class="item_title">Order Number:{{ item.orderNumber }}</div>
  17. <div class="item_content">
  18. <img :src="BaseUrl + '/report/' + item.researchReportFileName" alt="">
  19. <div>
  20. <div class="item_content_title">
  21. <img :src="BaseUrl + '/report/' + item.researchReportFileName" alt="">
  22. <div>
  23. {{ item.researchBriefReportTitle ||item.researchReportTitle}}
  24. </div>
  25. </div>
  26. <div class="item_content_time">Order placement time:<span> {{item.createDate}}</span></div>
  27. <div class="item_content_method">Payment method:<span>{{item.payResearchType}} </span></div>
  28. <div class="item_content_amount">Payment amount:<span>${{item.payPrice}}</span></div>
  29. </div>
  30. </div>
  31. <div class="btnBox">
  32. <div class="blue">PDF download</div>
  33. <div class="green">PPT Download</div>
  34. </div>
  35. </div>
  36. </div>
  37. <div class="pageBox" v-if="pageData?.list.length>0">
  38. <n-pagination show-quick-jumper :page-count="pageData?.count" :on-update:page="changePage" :page-slot="6">
  39. <template #prev>
  40. <div class="pageBox_btn">Previous</div>
  41. </template>
  42. <template #next>
  43. <div class="pageBox_btn">Next</div>
  44. </template>
  45. <template #goto>
  46. <div class="pageBox_inp">Go To</div>
  47. </template>
  48. </n-pagination>
  49. </div>
  50. <div class="box-empty" v-if="pageData?.count === 0">
  51. <n-empty description="Data Missed">
  52. <template #extra>
  53. <!-- <n-button @click="handleDemand({ id: '', price: 0 }, '0')" round type="primary">{{ t("report.detail.custom") }}</n-button> -->
  54. </template>
  55. </n-empty>
  56. </div>
  57. </div>
  58. </template>
  59. <script lang="ts" setup>
  60. import { useI18n } from "#imports";
  61. import { ref, reactive, onMounted, watch, onUnmounted } from "vue";
  62. import {
  63. NButton,
  64. NPagination,
  65. createDiscreteApi,
  66. NEmpty,
  67. NModal,
  68. NSpin,
  69. } from "naive-ui";
  70. import QrcodeVue from "qrcode.vue";
  71. import { useUserStore } from "@/store/user";
  72. const config = useRuntimeConfig();
  73. const BaseUrl = ref(config.public.baseUrl);
  74. const { t, locale, setLocale } = useI18n();
  75. const pageSize = 10;
  76. const userStore = useUserStore();
  77. const pcShow = ref(true);
  78. const props = defineProps({
  79. isMobile: {
  80. type: Boolean,
  81. default: false,
  82. },
  83. });
  84. const queryParams = reactive({
  85. pageNo: 1,
  86. pageSize: 5,
  87. orderNumber: "",
  88. });
  89. const pageData = ref({});
  90. const wxQRCode = ref("");
  91. const payVisible = ref<boolean>(false);
  92. const payTitle = ref<string>("");
  93. const count = ref(0);
  94. const timer = ref();
  95. const spinShow = ref(false);
  96. const description = ref(t("myInfo.loading"));
  97. const payShow = ref(false);
  98. const closePayVisible = ref(false);
  99. const closePayId = ref(null);
  100. const emailShow = ref(false);
  101. const activeItem = ref();
  102. // const Message = createDiscreteApi(["message"]);
  103. const model = ref({
  104. email: "",
  105. affirmEmail: "",
  106. });
  107. const openInpEmail = (item) => {
  108. activeItem.value = item;
  109. emailShow.value = true;
  110. };
  111. const getList = async () => {
  112. spinShow.value = true;
  113. description.value = t("myInfo.loading");
  114. let apiFun = getMyOrder_Api;
  115. if (userStore.getLang != "zh-CN") {
  116. apiFun = websiteUserResearchOrderList;
  117. }
  118. const { code, data } = await apiFun(queryParams);
  119. if (code === 200) {
  120. pageData.value = data;
  121. }
  122. spinShow.value = false;
  123. };
  124. // 提交邮箱
  125. const submitEmit = () => {
  126. if (model.value.affirmEmail != model.value.email) {
  127. message.message.error("The email addresses are inconsistent.");
  128. return;
  129. }
  130. let param = {
  131. id: activeItem.value.id,
  132. email: model.value.email,
  133. };
  134. websiteUserResearchOrderUpdateEmail(param).then((res) => {
  135. if (res.code == 200) {
  136. message.message.success(t("report.demand.submitSuccess"));
  137. close();
  138. queryParams.pageNo = 1;
  139. getList();
  140. }
  141. });
  142. };
  143. const close = () => {
  144. emailShow.value = false;
  145. };
  146. // onMounted(() => {
  147. getList();
  148. // });
  149. onBeforeMount(async () => {
  150. pcShow.value = !isMobile();
  151. });
  152. onUnmounted(() => {
  153. payEnd();
  154. });
  155. watch(
  156. () => payVisible.value,
  157. (newVal, oldVal) => {
  158. if (newVal === false) {
  159. payEnd();
  160. }
  161. }
  162. );
  163. const searchData = (val: string | any) => {
  164. queryParams.orderNumber = val;
  165. getList();
  166. };
  167. const goPay = (item) => {
  168. window.open(item.orderPayUrl);
  169. };
  170. const message = createDiscreteApi(["message"]);
  171. // 下载
  172. const handleTools = async (item: Object, fileType: string) => {
  173. if (fileType == "pay") {
  174. if (props.isMobile) {
  175. if (item.payMethod == "zfb" || item.payMethod == "wx") {
  176. return message.message.info("请前往PC端个人中心支付订单");
  177. }
  178. } else {
  179. if (item.payMethod == "zfb_h5" || item.payMethod == "wx_h5") {
  180. return message.message.info("请前往H5端个人中心支付订单");
  181. }
  182. }
  183. toPay(item);
  184. } else {
  185. const { code, data } = await getDownUrl_Api({
  186. researchBriefReportId: item.researchBriefReportId,
  187. fileType: fileType,
  188. });
  189. if (code === 200) {
  190. let url = `${BaseUrl}/fileupload/${data.filePath}${data.fileName}`;
  191. if (typeof window !== "undefined") {
  192. window.open(url);
  193. }
  194. }
  195. }
  196. };
  197. const toPay = (item) => {
  198. if (item.payMethod == "wx") {
  199. payVisible.value = true;
  200. wxQRCode.value = item.orderPayUrl;
  201. setTimeout(() => {
  202. payDetail(item);
  203. }, 500);
  204. } else {
  205. downloadFile(item.orderPayUrl);
  206. }
  207. };
  208. const payDetail = async (item) => {
  209. payShow.value = true;
  210. const { code, data } = await bulletinDetailPay_Api({
  211. researchBriefReportId: item.researchBriefReportId,
  212. orderNumber: item.orderNumber,
  213. });
  214. if (code === 200) {
  215. if (data.payStatus == 1) {
  216. message.message.success("支付成功");
  217. payEnd();
  218. } else if (data.payStatus != 1) {
  219. if (payVisible.value) {
  220. if (count.value >= 5) {
  221. payEnd();
  222. message.message.error("请检查是否支付完成");
  223. } else {
  224. timer.value = setTimeout(() => {
  225. count.value++;
  226. payDetail(item);
  227. }, 10 * 1000);
  228. }
  229. }
  230. }
  231. }
  232. };
  233. const payEnd = () => {
  234. count.value = 0;
  235. payVisible.value = false;
  236. clearTimeout(timer.value);
  237. };
  238. const handleClosePay = async (item) => {
  239. closePayId.value = item.id;
  240. closePayVisible.value = true;
  241. };
  242. const submitClosePayCallback = async () => {
  243. let apiFun = closePay_Api;
  244. if (userStore.getLang == "en-US") {
  245. // 英文 取消订单
  246. apiFun = websiteUserResearchCancelOrder;
  247. }
  248. const { code } = await apiFun({
  249. id: closePayId.value,
  250. });
  251. if (code === 200) {
  252. getList();
  253. message.message.success(t("myInfo.PaymentOrderCancelledSuccessfully"));
  254. }
  255. closePayId.value = null;
  256. closePayVisible.value = false;
  257. };
  258. const cancelClosePayCallback = () => {
  259. closePayId.value = null;
  260. closePayVisible.value = false;
  261. };
  262. // 改变页数
  263. const changePage = (page: number) => {
  264. document.documentElement.scrollTop = 0;
  265. queryParams.pageNo = page;
  266. getList();
  267. };
  268. defineExpose({
  269. searchData,
  270. });
  271. </script>
  272. <style lang="scss" scoped>
  273. @import "~/assets/css/tool.scss";
  274. .list-box {
  275. .titleBox {
  276. display: flex;
  277. justify-content: space-between;
  278. padding-bottom: var(--size-7);
  279. border-bottom: var(--size-1) solid #e6e6e6;
  280. .titleBox_l {
  281. font-size: var(--size-24);
  282. font-family: Arial, Arial-Bold;
  283. font-weight: 700;
  284. color: #1a1a1a;
  285. line-height: var(--size-44);
  286. }
  287. .titleBox_r {
  288. display: flex;
  289. align-items: center;
  290. width: var(--size-500);
  291. height: var(--size-44);
  292. background: #f5f5f5;
  293. border-radius: var(--size-8);
  294. overflow: hidden;
  295. .titleBox_r_l {
  296. flex-grow: 1;
  297. .n-input {
  298. --n-height: var(--size-26) !important;
  299. line-height: var(--size-26) !important;
  300. background: #f5f5f5 !important;
  301. font-size: var(--size-14) !important;
  302. }
  303. }
  304. .titleBox_r_r {
  305. width: var(--size-105);
  306. font-size: var(--size-16);
  307. color: #ffffff;
  308. text-align: center;
  309. height: var(--size-44);
  310. background: linear-gradient(0deg, #7b9c4f 0%, #2da19d 100%), #1a1a1a;
  311. line-height: var(--size-44);
  312. cursor: pointer;
  313. }
  314. }
  315. }
  316. .list {
  317. margin-top: var(--size-45);
  318. .item {
  319. border: var(--size-1) solid #e6e6e6;
  320. position: relative;
  321. margin-bottom: var(--size-30);
  322. &:last-child {
  323. margin-bottom: 0;
  324. }
  325. .item_title {
  326. font-size: var(--size-20);
  327. font-family: Arial, Arial-Bold;
  328. font-weight: 700;
  329. text-align: left;
  330. color: #1a1a1a;
  331. line-height: var(--size-44);
  332. letter-spacing: 0.06px;
  333. padding: var(--size-14) var(--size-25);
  334. background: #f5f5f5;
  335. }
  336. .item_content {
  337. padding: var(--size-20) var(--size-25) var(--size-23);
  338. display: flex;
  339. align-items: center;
  340. > img {
  341. width: var(--size-148);
  342. height: var(--size-216);
  343. object-fit: contain;
  344. }
  345. > div {
  346. margin-left: var(--size-40);
  347. .item_content_title {
  348. font-size: var(--size-21);
  349. font-family: Arial, Arial-Regular;
  350. color: #1a1a1a;
  351. line-height: var(--size-28);
  352. img {
  353. display: none;
  354. }
  355. }
  356. .item_content_time,
  357. .item_content_method {
  358. display: flex;
  359. font-size: var(--size-16);
  360. font-family: Arial, Arial-Regular;
  361. color: #1a1a1a;
  362. letter-spacing: 0.05px;
  363. span {
  364. color: #808080;
  365. }
  366. }
  367. .item_content_time {
  368. margin: var(--size-20) 0 0;
  369. }
  370. .item_content_method {
  371. margin: var(--size-6) 0 var(--size-10);
  372. }
  373. .item_content_amount {
  374. display: flex;
  375. font-size: var(--size-16);
  376. font-family: Arial, Arial-Regular;
  377. color: #1a1a1a;
  378. line-height: var(--size-44);
  379. letter-spacing: 0.05px;
  380. align-items: baseline;
  381. span {
  382. font-size: var(--size-30);
  383. color: #ee001f;
  384. }
  385. }
  386. }
  387. }
  388. .btnBox {
  389. display: flex;
  390. position: absolute;
  391. right: var(--size-20);
  392. bottom: var(--size-45);
  393. > div {
  394. width: var(--size-144);
  395. height: var(--size-48);
  396. border-radius: var(--size-8);
  397. font-size: var(--size-14);
  398. font-family: Arial, Arial-Regular;
  399. text-align: center;
  400. color: #ffffff;
  401. line-height: var(--size-48);
  402. margin-right: var(--size-14);
  403. cursor: pointer;
  404. &:last-child {
  405. margin-right: 0;
  406. }
  407. }
  408. .blue {
  409. background: #60ac92;
  410. }
  411. .green {
  412. background: #84a86c;
  413. }
  414. }
  415. }
  416. }
  417. }
  418. @include responseTo("phone") {
  419. .list-box {
  420. .titleBox {
  421. padding-bottom: var(--size-20);
  422. display: block;
  423. .titleBox_r {
  424. width: 100%;
  425. }
  426. }
  427. .list {
  428. margin-top: var(--size-20);
  429. .item {
  430. .item_title {
  431. padding: var(--size-10) var(--size-15);
  432. font-size: var(--size-18);
  433. line-height: var(--size-24);
  434. }
  435. .item_content {
  436. padding: var(--size-10);
  437. > img {
  438. display: none;
  439. }
  440. > div {
  441. margin: 0;
  442. .item_content_title {
  443. display: flex;
  444. > div {
  445. font-size: var(--size-18);
  446. line-height: var(--size-26);
  447. overflow: hidden;
  448. text-overflow: ellipsis;
  449. display: -webkit-box;
  450. -webkit-line-clamp: 4;
  451. -webkit-box-orient: vertical;
  452. }
  453. > img {
  454. width: var(--size-74);
  455. height: var(--size-108);
  456. object-fit: contain;
  457. margin-right: var(--size-10);
  458. display: block;
  459. }
  460. }
  461. .item_content_time,
  462. .item_content_method {
  463. font-size: var(--size-14);
  464. }
  465. .item_content_amount {
  466. font-size: var(--size-14);
  467. line-height: var(--size-30);
  468. span {
  469. font-size: var(--size-26);
  470. }
  471. }
  472. }
  473. }
  474. .btnBox {
  475. position: static;
  476. width: 100%;
  477. justify-content: center;
  478. padding-bottom: var(--size-20);
  479. }
  480. }
  481. }
  482. }
  483. }
  484. </style>