index.vue 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  1. <template>
  2. <!-- 订单中心 -->
  3. <div class="orderPage flex-col">
  4. <s-header :name="$t('orderCenter.orderCenter')" :noback="false"></s-header>
  5. <div class="orderBox">
  6. <van-list v-model:loading="loading" v-model:error="error" :error-text="$t('public.requestFailed')"
  7. :finished="finished" :finished-text="$t('public.noMore')" offset="300" :immediate-check="false" @load="onLoad">
  8. <div class="main3 flex-col justify-center">
  9. <div class="outer1 flex-col justify-between">
  10. <div class="group4 flex-row justify-between">
  11. <div class="ImageText1 flex-col">
  12. <div class="outer2 flex-row justify-between">
  13. <div class="block1 flex-col"></div>
  14. <div class="TextGroup1 flex-col">
  15. <span class="txt1">{{ $t('orderCenter.dataOverview') }}</span>
  16. </div>
  17. </div>
  18. </div>
  19. <div class="ImageText2 flex-col" @click="searchClick()">
  20. <div class="group5 flex-row justify-between">
  21. <img class="icon2" src="../../assets/order/search.png" />
  22. <div class="TextGroup2 flex-col">
  23. <span class="txt2">{{ $t("common.search") }}</span>
  24. </div>
  25. </div>
  26. </div>
  27. </div>
  28. </div>
  29. </div>
  30. <dateSelectList @update="update($event)"></dateSelectList>
  31. <typeSelectList @upselectdata="upselectdata($event)"></typeSelectList>
  32. <div v-if="!noData(salesVolume, salesNumber, orderNumber)" class="o-plr-8 o-pt-15">
  33. <div class="outer5 flex-col">
  34. <div class="block5 flex-col">
  35. <div class="outerBox flex-row">
  36. <div class="main4 flex-col justify-between">
  37. <div class="main5 flex-row justify-center">
  38. <!-- <span class="word8">&yen;</span> -->
  39. <span class="word8">{{ currencySymbol }}</span>
  40. <span class="word9">{{ salesVolume.toFixed(0) }}</span>
  41. </div>
  42. <span class="info5">{{ $t("home.totalIncome") }}</span>
  43. </div>
  44. <div class="TextGroup7 flex-col">
  45. <div class="mod3 flex-col justify-between">
  46. <span class="txt8">{{ salesNumber }}</span>
  47. <span class="info6">{{ $t("home.productNum") }}</span>
  48. </div>
  49. </div>
  50. <div class="TextGroup8 flex-col">
  51. <div class="outer6 flex-col justify-between">
  52. <span class="txt9">{{ orderNumber }}</span>
  53. <span class="word10">{{ $t("home.numberOfOrders") }}</span>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. </div>
  59. </div>
  60. <kNoData v-else></kNoData>
  61. <div class="o-mt-5" style="height: 10px; background: #f5f5f5"></div>
  62. <!-- 时间 -->
  63. <div class="c-text-c c-text-18">
  64. {{ Format_time(searchParams.startDate, 'YYYY-MM-DD') }}--{{ Format_time(searchParams.endDate, 'YYYY-MM-DD') }}
  65. </div>
  66. <div class="group7 flex-col justify-center">
  67. <div class="main9 flex-col justify-between">
  68. <div class="wrap1 flex-row justify-between">
  69. <div class="ImageText7 flex-col">
  70. <div class="mod5 flex-row justify-between">
  71. <div class="block3 flex-col"></div>
  72. <div class="TextGroup7 flex-col">
  73. <span class="info3">{{ $t('orderCenter.orderDetails') }}</span>
  74. </div>
  75. </div>
  76. </div>
  77. <div class="ImageText8 flex-col" @click="gotoOrderExcel()">
  78. <div class="bd3 flex-row justify-between">
  79. <span class="info4 flex-col">{{ $t('orderCenter.exportToExcel') }}</span>
  80. <div class="outer3 flex-col"></div>
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. </div>
  86. <div class="section1 flex-col">
  87. <div class="group8 flex-col">
  88. <div class="section4 flex-col">
  89. <div v-for="(item, index) in orderList" :key="index">
  90. <div class="section5 flex-col" @click="orderClick(item)">
  91. <van-card :thumb="showSugerPhoto(item)">
  92. <template #title>
  93. <span class="word13">{{ $t('orderCenter.tradeName') }}:{{ item.productName }}</span>
  94. </template>
  95. <template #desc>
  96. <span class="word11">{{ $t('orderCenter.equipmentName') }}:{{ item.es }}</span>
  97. </template>
  98. <template #price>
  99. <div class="pricBox flex-row align-end" :class="{ orderError: item.status === 0 }">
  100. <span class="txt9">{{ item.statusText }}:
  101. <span v-if="user.ifForeign === '0'" class="word14 o-ptb-8">
  102. {{ $t('orderCenter.dividingDomesticService') }} :{{ currencySymbol }}{{ showSubcom(item) }}
  103. </span>
  104. </span>
  105. <!-- 订单明细 - 线下支付 ¥ -->
  106. <span class="info5">{{ currencySymbol }}</span>
  107. <span class="word12" v-if="item.status === 3">{{ item.price.toFixed(2) }}</span>
  108. <span class="word12" v-else>{{ item.refundAmount == null ? item.price.toFixed(2) : (item.price -
  109. item.refundAmount).toFixed(2) }}</span>
  110. </div>
  111. </template>
  112. <template #price-top>
  113. <span class="time_01" :style="user.ifForeign == '0' ? 'margin-top: 20px;' : 'margin-top: 40px;'">{{
  114. $t('orderCenter.paymentTime') }}:{{ showOrderTime(item, 1) }}</span>
  115. </template>
  116. <template #footer>
  117. <span v-if="item.status === 3">x{{ item.refundQuantity }}</span>
  118. <span v-else>x{{ item.refundQuantity == null ? item.productNumber : (item.productNumber -
  119. item.refundQuantity) }}</span>
  120. </template>
  121. </van-card>
  122. <div v-if="typeof item.status === 'undefined'" class="main11 flex-col orderSuccess"></div>
  123. <div v-else class="main11 flex-col" :class="{
  124. orderSuccess: item.status === 1,
  125. orderError: item.status === 0,
  126. refunding: item.status === 2,
  127. refunded: item.status === 3,
  128. }"></div>
  129. </div>
  130. <!-- <div class="section6 flex-col"></div> -->
  131. </div>
  132. <van-back-top style="background-color: #2d87c8;" />
  133. </div>
  134. </div>
  135. </div>
  136. </van-list>
  137. </div>
  138. <!-- 搜索弹出框 -->
  139. <orderSearch ref="searchRef" @search="search($event)"></orderSearch>
  140. <!-- 退款弹窗 -->
  141. <van-popup v-model:show="refundType" position="bottom" round>
  142. <div class="refundBox flex-col">
  143. <div class="section1 flex-col">
  144. <div class="group3 flex-col">
  145. <div class="TextGroup1 l-flex-center">
  146. <div class="outer1 flex-col">
  147. <!-- <span class="txt4">这里是设备名称</span> -->
  148. <span class="info1">{{ $t('orderCenter.business') }}</span>
  149. <span class="txt5">+ {{ refundObject.refundAmount == null ? refundObject.price.toFixed(2) :
  150. (refundObject.price - refundObject.refundAmount).toFixed(2) }}</span>
  151. </div>
  152. </div>
  153. <div class="layer1 flex-col"></div>
  154. <!-- <div class="layer2 flex-row justify-between">
  155. <span class="info2">{{ $t('orderCenter.accountBalance') }}</span>
  156. <span class="txt6">{{ accountDetail.altAvilBalance }}</span>
  157. </div> -->
  158. <div class="layer3 flex-row justify-between">
  159. <span class="word2">{{ $t('orderCenter.orderNo') }}</span>
  160. <span class="info3">{{ refundObject.sn }}</span>
  161. </div>
  162. <div class="layer3 flex-row justify-between">
  163. <span class="word2">{{ $t('orderCenter.commodity') }}</span>
  164. <span class="info3">{{ refundObject.productName }}</span>
  165. </div>
  166. <div class="layer4 flex-row justify-between">
  167. <span class="word3">{{ $t('orderCenter.distribution') }}</span>
  168. <span class="word4">{{ showSubcom(refundObject) }}</span>
  169. </div>
  170. <div class="layer4 flex-row justify-between">
  171. <span class="word3">{{ $t('orderCenter.equipmentNo') }}</span>
  172. <span class="word4">{{ refundObject.clientId }}</span>
  173. </div>
  174. <div class="layer5 flex-row justify-between">
  175. <span class="txt7">{{ $t('orderCenter.state') }}</span>
  176. <span class="word5">{{ showStatus(refundObject) }}</span>
  177. </div>
  178. <div class="layer6 flex-row justify-between">
  179. <span class="word6">{{ $t('orderCenter.paymentMethod') }}</span>
  180. <span class="word7">{{ showPayType(refundObject) }}</span>
  181. </div>
  182. <div class="layer6 flex-row justify-between">
  183. <span class="word6">{{ $t('orderCenter.creationTime') }}</span>
  184. <span class="word7">{{ showOrderTime(refundObject, 2) }}</span>
  185. </div>
  186. <div v-if="refundObject.status === 3" class="layer7 flex-row justify-between">
  187. <span class="word8">{{ $t('orderCenter.refunded') }}</span>
  188. <span class="info4">{{ refundObject.refundAmount }}</span>
  189. </div>
  190. <!-- 发起退款 -->
  191. <!-- 非已付款订单,线下订单要隐藏按钮 -->
  192. <van-button size="small"
  193. v-if="(refundObject.status === 1 && user.ifForeign === '0') || (refundObject.status === 1 && user.ifForeign === '1' && refundObject.isAir === '1')"
  194. @click="noticeClk(refundObject)" round type="primary" style="margin-top: 20px;">
  195. {{ $t('orderCenter.initiateRefund') }}
  196. </van-button>
  197. </div>
  198. </div>
  199. </div>
  200. </van-popup>
  201. <!-- 退款弹窗 -->
  202. <kDialog :isCloseForConfirm="false" :dialogTitle="$t('orderCenter.refundTip')"
  203. :confirmBtnTxt="$t('orderCenter.refundSubmit')" ref="kDialogRef" @confirmclk="confirmClk">
  204. <template #content>
  205. <div class="cust_vantBorder l-flex-RC">
  206. <div v-for="(item, index) in orderDetails" :key="index" class="card01">
  207. <van-checkbox v-model="isChecked[index]" @change="checkGood(index)" icon-size="20px"></van-checkbox>
  208. <van-card :price="item.price.toFixed(2)" :title="item.productName" :thumb="showSugarPic(item.productNo)">
  209. <template #footer>
  210. <van-stepper v-model="refundNum[index]" @plus="plusRefundGood(index)" @minus="minusRefundGood(index)"
  211. theme="round" button-size="22" disable-input
  212. :max="item.refundQuantity == null ? item.productNumber : (item.productNumber - item.refundQuantity)" />
  213. </template>
  214. </van-card>
  215. </div>
  216. </div>
  217. <div class="o-mt-5" style="height: 1px; background: #d7d7e2"></div>
  218. <div class="btnFooter">
  219. <van-checkbox class="checkAllBtn o-mt-5" v-model="checkedAll" @click="checkAll">全选</van-checkbox>
  220. <div class="o-mt-5">
  221. <span class="">{{ $t('orderCenter.totalRefund') }}:</span>
  222. <!-- <span class="totalRefund o-pr-15">&yen; {{ totalRefund.toFixed(2) }}</span> -->
  223. <span class="totalRefund o-pr-15">{{ currencySymbol }} {{ totalRefund.toFixed(2) }}</span>
  224. </div>
  225. </div>
  226. </template>
  227. </kDialog>
  228. </div>
  229. </template>
  230. <script>
  231. import { Api_getOnlineExport } from "../../service/order";
  232. // 导入接口
  233. import { getAdminMch } from "../../service/merchantManage";
  234. // 导入弹窗
  235. import kDialog from "../../components/commom/kDialog/index.vue";
  236. // 导入无数据组件
  237. import { showDialog, showConfirmDialog } from 'vant';
  238. import kNoData from "../../components/commom/kNoData/index.vue";
  239. import { onMounted, reactive, ref } from "vue";
  240. import sHeader from "../../components/SimpleHeader";
  241. import orderSearch from "./orderSearch.vue";
  242. import { getOrderList, refundOrder } from "../../service/order/index";
  243. import { showFailToast, showToast, showLoadingToast } from "vant";
  244. import { getLoginUser, $M_IsDate, Format_time, $M_ExportFile, styleUrl } from "../../common/js/utils";
  245. import { getHuifuId } from "../../service/huifuMch/index";
  246. import dateUtil from "../../utils/dateUtil";
  247. import dateSelectList from "../../components/dateSelectList";
  248. import typeSelectList from "../../components/typeSelectList";
  249. import { getStatistics } from "../../service/home";
  250. import { useI18n } from "vue-i18n";
  251. export default {
  252. name: "order",
  253. components: { sHeader, orderSearch, dateSelectList, typeSelectList, kNoData, kDialog },
  254. setup() {
  255. // 批量修改弹窗
  256. const kDialogRef = ref(null);
  257. // 订单明细
  258. const orderDetails = ref([]);
  259. // 退款商品选择状态
  260. const isChecked = ref([]);
  261. // 全选状态
  262. const checkedAll = ref(false);
  263. // 退款总额
  264. const totalRefund = ref(0);
  265. // 退款商户数量
  266. const refundNum = ref([]);
  267. // 加载状态
  268. // const isLoading = ref(false);
  269. // 监控退款选择框状态
  270. const checkGood = (index) => {
  271. if (isChecked.value[index]) {
  272. totalRefund.value = parseFloat((totalRefund.value + (refundNum.value[index] * orderDetails.value[index].price)).toFixed(2));
  273. } else {
  274. if (totalRefund.value > 0) {
  275. totalRefund.value = parseFloat((totalRefund.value - (refundNum.value[index] * orderDetails.value[index].price)).toFixed(2));
  276. }
  277. }
  278. // 如果都为true,都为全选
  279. if (isChecked.value.every((value) => value === true)) {
  280. checkedAll.value = true;
  281. } else {
  282. checkedAll.value = false;
  283. }
  284. }
  285. // 点击增加按钮
  286. const plusRefundGood = (index) => {
  287. if (isChecked.value[index]) {
  288. totalRefund.value = parseFloat((totalRefund.value + orderDetails.value[index].price).toFixed(2));
  289. }
  290. }
  291. // 点击减少按钮
  292. const minusRefundGood = (index) => {
  293. if (isChecked.value[index]) {
  294. totalRefund.value = parseFloat((totalRefund.value - orderDetails.value[index].price).toFixed(2));
  295. }
  296. }
  297. // 点击弹出退款弹窗
  298. const noticeClk = (row) => {
  299. if (row.orderDetails.length > 0) {
  300. isChecked.value = [];
  301. orderDetails.value = [];
  302. refundNum.value = [];
  303. checkedAll.value = false;
  304. totalRefund.value = 0;
  305. // cofficentForm.price = row.price;
  306. // cofficentForm.maxPrice = row.price;
  307. cofficentForm.id = row.id;
  308. // cofficentForm.maxNumber = row.productNumber;
  309. // cofficentForm.productNumber = row.productNumber;
  310. row.orderDetails.forEach(item => {
  311. if (item.refundStatus == '1' || item.refundStatus == '2') {
  312. orderDetails.value.push(item);
  313. if (item.refundQuantity != null) {
  314. refundNum.value.push(item.productNumber - item.refundQuantity);
  315. } else {
  316. refundNum.value.push(item.productNumber);
  317. }
  318. }
  319. });
  320. // 根据orderDetails的长度,向isChecked添加相应数量的false
  321. isChecked.value = Array.from({ length: orderDetails.value.length }, () => false);
  322. kDialogRef.value.openDialog();
  323. } else {
  324. showToast("请联系管理员");
  325. return;
  326. }
  327. };
  328. // 点击全选按钮
  329. const checkAll = () => {
  330. isChecked.value.forEach((item, index) => {
  331. if (isChecked.value[index]) {
  332. isChecked.value[index] = !isChecked.value[index]
  333. checkedAll.value = false;
  334. } else {
  335. isChecked.value[index] = !isChecked.value[index]
  336. checkedAll.value = true;
  337. }
  338. })
  339. }
  340. // 点击确定按钮
  341. const confirmClk = () => {
  342. cofficentForm.note = "";
  343. cofficentForm.productNumber = 0;
  344. cofficentForm.price = 0;
  345. isChecked.value.forEach((isCheckedValue, index) => {
  346. if (isCheckedValue) {
  347. cofficentForm.note = cofficentForm.note + orderDetails.value[index].productNo + "-" + refundNum.value[index] + ","
  348. cofficentForm.productNumber = cofficentForm.productNumber + refundNum.value[index];
  349. }
  350. })
  351. cofficentForm.price = totalRefund.value;
  352. if (cofficentForm.note === "" || cofficentForm.price === 0 || cofficentForm.price === "") {
  353. showToast(t('orderCenter.refundPlace'));
  354. return;
  355. } else {
  356. showConfirmDialog({
  357. // title: "提示",
  358. message: t('orderCenter.refundCheck'),
  359. }).then(() => {
  360. // isLoading.value = true; // 开始加载
  361. refundAjax();
  362. // isLoading.value = false; // 加载完成
  363. kDialogRef.value.closeDialog();
  364. }).catch(() => {
  365. return;
  366. });
  367. }
  368. }
  369. // 退款操作
  370. const refundAjax = async () => {
  371. try {
  372. const { data } = await refundOrder(cofficentForm);
  373. if (data.code && data.code !== 'B0001') {
  374. showDialog({
  375. message: t('orderCenter.refundSucceeded'),
  376. }).then(() => {
  377. refundType.value = false;
  378. // on close
  379. orderList.value = [];
  380. search({});
  381. });
  382. } else {
  383. showFailToast(data.message);
  384. }
  385. } catch (error) {
  386. showFailToast(t('orderCenter.requestFailed'));
  387. }
  388. };
  389. // 修改的价格
  390. const cofficentForm = reactive({
  391. price: 0,
  392. id: "",
  393. productNumber: 0,
  394. note: 0
  395. });
  396. // 引入语言
  397. const { t } = useI18n();
  398. // 订单商品图片路径处理
  399. const showSugerPhoto = (row) => {
  400. if (row.orderDetails != null) {
  401. if (row.orderDetails.length > 0) {
  402. if (row.orderDetails[0].productNo == 'A99') {
  403. return require(`../../assets/order/spunSugar/goods/A30.png`);
  404. }
  405. return require(`../../assets/order/spunSugar/goods/${row.orderDetails[0].productNo}.png`);
  406. } else {
  407. if (row.productNo != null) {
  408. if (row.productNo == 'A99') {
  409. return require(`../../assets/order/spunSugar/goods/A30.png`);
  410. }
  411. return require(`../../assets/order/spunSugar/goods/${row.productNo}.png`);
  412. }
  413. if (row.machineType == null || row.machineType == '0') {
  414. return require(`../../assets/order/spunSugar/goods/A01.png`);
  415. } else {
  416. return require(`../../assets/order/spunSugar/goods/B01.png`);
  417. }
  418. }
  419. } else {
  420. if (row.machineType == null || row.machineType == '0') {
  421. return require(`../../assets/order/spunSugar/goods/A01.png`);
  422. } else {
  423. return require(`../../assets/order/spunSugar/goods/B01.png`);
  424. }
  425. }
  426. };
  427. // 订单明细商品图片路径处理
  428. const showSugarPic = (row) => {
  429. if (row == 'A99') {
  430. return require(`../../assets/order/spunSugar/goods/A30.png`);
  431. }
  432. return require(`../../assets/order/spunSugar/goods/${row}.png`);
  433. };
  434. // 如果是空数据
  435. const noData = (volumes, nums) => {
  436. if (!volumes && !nums) {
  437. return true;
  438. }
  439. return false;
  440. };
  441. const user = getLoginUser();
  442. const searchRef = ref(null);
  443. const huifuId = ref(null);
  444. const orderList = ref([]);
  445. const orderTotal = ref(0);
  446. const loading = ref(true);
  447. const error = ref(false);
  448. const finished = ref(false);
  449. // 滚动加载
  450. const onLoad = () => {
  451. if (!finished.value) {
  452. loading.value = true;
  453. searchParams.current = searchParams.current + 1;
  454. getList();
  455. }
  456. };
  457. // 自定义货币符号
  458. const currencySymbol = ref("¥");
  459. if (user.currencySymbol) {
  460. currencySymbol.value = user.currencySymbol;
  461. } else {
  462. currencySymbol.value = "¥";
  463. }
  464. // 页面列表查询参数
  465. let searchParams = reactive({
  466. adminId: "", // 用户账户id
  467. userName: "", // 用户名 String 没有值时传null
  468. adminType: "", // 判断是否查全部商户 当用户为商家时,“本商户”这个选项为“所有下级用户”传入一个“all”的值,其他情况传null
  469. type: user.ifForeign, // 订单类型 用来区分是国内、海外订单,0:国内,1:海外。默认值一般要根据当前登录用户的类型去选择。区分的参数是admin里ifForeign的值。ifForeign=0则type=0.
  470. // ifForeign现在用于区分国内0,海外1
  471. // isAir海外又分为两种情况,0/null为线下,1是线上
  472. payType: "", // 支付方式 全部时传null 0:无需支付 1:硬币 2:纸币 3:硬币+纸币 4:信用卡 5:电子支付 ALIPAY_NATIVE:支付宝主扫 WEIXIN_NATIVE:微信主扫 ALIPAY_CARD:支付宝反扫 WEIXIN_CARD:微信反扫
  473. productNo: "", // 商品的标识 全部时传null。 Tproductd对象的属性no的值。
  474. clientId: "", // 设备编号 String
  475. dateType: "0", // 所选时间类型 String 0:创建时间 1:退款时间
  476. startDate: "", // 开始时间 Date
  477. endDate: "", // 结束时间 Date
  478. current: 0, // 页数
  479. size: 15, // 页大小
  480. status: 1,//支付状态
  481. companyType: "", // 公司平台
  482. machineType: "", // 设备类型
  483. ifForeign: "",
  484. });
  485. let chartType = "day";
  486. // 获取订单列表数据
  487. const getList = async () => {
  488. finished.value = false;
  489. getStatisticsFun();
  490. // 因为订单的时间格式不一样
  491. const params = Object.assign({}, searchParams);
  492. if ($M_IsDate(params.startDate)) {
  493. params.startDate = dateUtil.formateDate(
  494. new Date(params.startDate),
  495. "yyyy-MM-dd hh:mm:ss"
  496. );
  497. } else {
  498. params.startDate = "";
  499. }
  500. if ($M_IsDate(params.endDate)) {
  501. params.endDate = dateUtil.formateDate(
  502. new Date(params.endDate),
  503. "yyyy-MM-dd hh:mm:ss"
  504. );
  505. } else {
  506. params.endDate = "";
  507. }
  508. // 获取订单列表
  509. const { data } = await getOrderList(Object.assign({}, params));
  510. if (data.code === "00000") {
  511. if (data.data.total === 0) {
  512. finished.value = true;
  513. } else {
  514. // orderTotal.value = data.data.total;
  515. if (params.current === 1) {
  516. orderList.value = [];
  517. orderTotal.value = 0;
  518. }
  519. // 列表值叠加
  520. if (data.data.records.length > 0) {
  521. orderList.value = orderList.value.concat(
  522. data.data.records.map((item) => {
  523. return {
  524. ...item,
  525. statusText:
  526. item.altInfo != null
  527. ? t('orderCenter.onlinePayment')
  528. : t('orderCenter.offlinePayment'),
  529. };
  530. })
  531. );
  532. orderTotal.value = data.data.records.length + orderTotal.value;
  533. if (orderTotal.value === data.data.total) {
  534. finished.value = true;
  535. }
  536. } else {
  537. finished.value = true;
  538. }
  539. }
  540. loading.value = false;
  541. } else {
  542. // error.value = true;
  543. showFailToast("数据加载失败");
  544. }
  545. };
  546. // 搜索表单点击
  547. const searchClick = () => {
  548. searchRef.value.showSearch();
  549. };
  550. // 搜索表单初始化页面及状态查询列表
  551. const search = (data) => {
  552. searchParams = Object.assign(searchParams, data);
  553. // 这个会导致请求两次接口
  554. // finished.value = false;
  555. orderList.value = [];
  556. loading.value = true;
  557. searchParams.current = 1;
  558. getList();
  559. };
  560. // 今日、明日、本周、本月、其他时间选择回调
  561. const update = (uDate) => {
  562. chartType = uDate.chartType;
  563. searchParams = Object.assign(searchParams, uDate);
  564. searchParams.type = searchParams.ifForeign;
  565. search();
  566. };
  567. // 商户、支付方式、设备、商品选择回调
  568. const upselectdata = (uSData) => {
  569. // console.log('uSData', uSData)
  570. searchParams = Object.assign(searchParams, uSData);
  571. // console.log('searchParams', searchParams)
  572. searchParams.type = searchParams.ifForeign;
  573. search();
  574. };
  575. // 初始化页面获取列表
  576. onMounted(async () => {
  577. // 加载样式
  578. styleUrl('orderCenter');
  579. // orderList.value = [];
  580. // searchParams.current = 1;
  581. if (user) {
  582. searchParams.adminId = user.id;
  583. searchParams.userName = user.username;
  584. const { data } = await getHuifuId({
  585. adminId: user.id,
  586. });
  587. if (data.code === '00000') {
  588. if (data.data != null) {
  589. huifuId.value = data.data.huifuId;
  590. }
  591. }
  592. // 获取当天
  593. let now = new Date();
  594. let startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);
  595. searchParams.startDate = dateUtil.formateDate(startDate, "yyyy-MM-dd hh:mm:ss");
  596. let endDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59);
  597. searchParams.endDate = dateUtil.formateDate(endDate, "yyyy-MM-dd hh:mm:ss");
  598. // finished.value = false;
  599. // loading.value = true;
  600. // getList();
  601. onLoad();
  602. addEventListener('load', onLoad);
  603. // 获取账户详情
  604. if (user.ifForeign === '0') {
  605. getAccountDetail(user.id);
  606. }
  607. }
  608. });
  609. // 查询是否有退款权限
  610. const isRefund = user.menuCodeList.some((item) => {
  611. return item === "M16";
  612. });
  613. // 跳转订单导出
  614. const gotoOrderExcel = async () => {
  615. if (searchParams.type == null || searchParams.type == '') {
  616. searchParams.type = user.ifForeign;
  617. }
  618. // 显示加载框
  619. const downloadOrder = showLoadingToast({
  620. forbidClick: true,
  621. duration: 0,
  622. });
  623. try {
  624. const { headers, data } = await Api_getOnlineExport(searchParams);
  625. // 请求完成后隐藏加载框
  626. downloadOrder.close();
  627. $M_ExportFile(data, headers);
  628. // 处理返回的数据
  629. } catch (error) {
  630. // 请求发生错误时隐藏加载框
  631. downloadOrder.close();
  632. // 处理错误情况
  633. console.error(error);
  634. } finally {
  635. downloadOrder.close();
  636. }
  637. };
  638. // 订单详情-退款弹窗
  639. const refundType = ref(false);
  640. const refundObject = ref({});
  641. const orderClick = (item) => {
  642. //查询商户余额,要用admin的type去区分 TODO
  643. refundObject.value = item;
  644. refundType.value = true;
  645. };
  646. const accountDetail = ref({});
  647. // 获取账户详情
  648. const getAccountDetail = (id) => {
  649. getAdminMch({ id }).then(res => {
  650. accountDetail.value = res.data.data;
  651. })
  652. };
  653. // 订单时间格式转换
  654. const showOrderTime = (item, idx) => {
  655. if (idx === 1) {
  656. switch (item.status) {
  657. case 1:
  658. return dateUtil.timeZoneDate(new Date(dateUtil.formateDate(new Date(item.payDate), "yyyy-MM-dd hh:mm:ss")));
  659. case 3:
  660. return dateUtil.timeZoneDate(new Date(dateUtil.formateDate(new Date(item.refundDate), "yyyy-MM-dd hh:mm:ss")));
  661. default:
  662. return dateUtil.timeZoneDate(new Date(dateUtil.formateDate(new Date(item.createDate), "yyyy-MM-dd hh:mm:ss")));
  663. }
  664. } else {
  665. return item && item.createDate
  666. ? dateUtil.timeZoneDate(new Date(dateUtil.formateDate(new Date(item.createDate), "yyyy-MM-dd hh:mm:ss")))
  667. : "";
  668. }
  669. };
  670. // 设备编号格式转换
  671. const showClientId = (item) => {
  672. return item && item.clientId
  673. ? item.clientId.substring(item.clientId.length - 6)
  674. : "";
  675. };
  676. // 计算分佣
  677. const showSubcom = (item) => {
  678. let subcom = "0";
  679. if (item.altInfo) {
  680. const altInfo = JSON.parse(item.altInfo);
  681. if (altInfo && altInfo.length > 0) {
  682. // altInfo这个属性里,最后一个实体的altAmount的值就是他的分佣。
  683. subcom = altInfo[altInfo.length - 1]['altAmount'];
  684. }
  685. }
  686. if (item.acctSplitBunch) {
  687. const data = JSON.parse(item.acctSplitBunch);
  688. const targetObj = data.acct_infos.find(obj => obj.huifu_id === huifuId.value);
  689. if (targetObj) {
  690. subcom = targetObj.div_amt;
  691. }
  692. }
  693. return subcom;
  694. };
  695. // 弹窗订单状态
  696. const showStatus = (item) => {
  697. if (typeof item.status === "undefined") {
  698. return t('orderCenter.paymentSucceeded');
  699. } else {
  700. if (item.status === 0) {
  701. return t('orderCenter.unpaid');
  702. }
  703. if (item.status === 1) {
  704. return t('orderCenter.paid');
  705. }
  706. if (item.status === 2) {
  707. return t('orderCenter.refundInProgress');
  708. }
  709. if (item.status === 3) {
  710. return t('orderCenter.refunded');
  711. }
  712. }
  713. return item;
  714. };
  715. const paySouerList = [
  716. { text: t('orderCenter.whole'), values: null },
  717. { text: t('orderCenter.noPaymentRequired'), values: 0 },
  718. { text: t('orderCenter.coin'), values: 1 },
  719. { text: t('orderCenter.notes'), values: 2 },
  720. { text: t('orderCenter.coinsNotes'), values: 3 },
  721. { text: t('orderCenter.creditCard'), values: 4 },
  722. { text: t('orderCenter.electronicPayment'), values: 5 },
  723. { text: t('orderCenter.mainSweepOfAlipay'), values: "ALIPAY_NATIVE" },
  724. { text: t('orderCenter.weChatScanning'), values: "WEIXIN_NATIVE" },
  725. { text: t('orderCenter.antiScanningOfAlipay'), values: "ALIPAY_CARD" },
  726. { text: t('orderCenter.weChatBackScanning'), values: "WEIXIN_CARD" },
  727. ];
  728. // 弹窗支付上述
  729. const showPayType = (item) => {
  730. const payType = user.ifForeign === "0" ? item.frpCode : item.payType;
  731. const paySoure = paySouerList.filter((i) => i.values === payType);
  732. if (paySoure.length > 0) {
  733. return paySoure[0].text;
  734. } else {
  735. return "";
  736. }
  737. };
  738. const salesVolume = ref(0);
  739. const salesNumber = ref(0);
  740. const orderNumber = ref(0);
  741. // 查询图表
  742. const getStatisticsFun = async () => {
  743. // console.log('searchParams', searchParams)
  744. const params = {
  745. adminId: user.id,
  746. chartType: chartType,
  747. endDate: searchParams.endDate,
  748. ifForeign: searchParams.ifForeign == '' ? user.ifForeign : searchParams.ifForeign,
  749. startDate: searchParams.startDate,
  750. userName: searchParams.userName,
  751. clientId:
  752. searchParams.clientId === "" ? null : searchParams.clientId,
  753. equipmentId:
  754. searchParams.equipmentId === "" ? null : searchParams.equipmentId,
  755. payType:
  756. searchParams.payType === "" ? null : searchParams.payType,
  757. companyType: searchParams.companyType,
  758. machineType: searchParams.machineType,
  759. isAir: searchParams.isAir === "" ? null : searchParams.isAir,
  760. };
  761. const { data } = await getStatistics(params);
  762. if (data.code && data.data) {
  763. salesVolume.value = 0;
  764. salesNumber.value = 0;
  765. orderNumber.value = 0;
  766. data.data.series[0].data.forEach((item) => {
  767. salesNumber.value = parseInt(salesNumber.value + item);
  768. });
  769. data.data.series[1].data.forEach((item) => {
  770. salesVolume.value = parseFloat(salesVolume.value) + parseFloat(item);
  771. });
  772. data.data.series[2].data.forEach((item) => {
  773. orderNumber.value = parseInt(orderNumber.value + item);
  774. });
  775. }
  776. };
  777. return {
  778. user,
  779. loading,
  780. error,
  781. finished,
  782. onLoad,
  783. orderList,
  784. orderTotal,
  785. searchRef,
  786. searchClick,
  787. search,
  788. update,
  789. upselectdata,
  790. gotoOrderExcel,
  791. refundType,
  792. refundObject,
  793. orderClick,
  794. showSugerPhoto,
  795. showOrderTime,
  796. showClientId,
  797. showSubcom,
  798. showStatus,
  799. showPayType,
  800. salesVolume,
  801. salesNumber,
  802. orderNumber,
  803. noData,
  804. kDialogRef,
  805. noticeClk,
  806. confirmClk,
  807. cofficentForm,
  808. accountDetail,
  809. Format_time,
  810. searchParams,
  811. orderDetails,
  812. huifuId,
  813. showSugarPic,
  814. isChecked,
  815. refundNum,
  816. checkAll,
  817. checkedAll,
  818. totalRefund,
  819. checkGood,
  820. plusRefundGood,
  821. minusRefundGood,
  822. // isLoading,
  823. isRefund,
  824. currencySymbol,
  825. };
  826. },
  827. };
  828. </script>
  829. <style lang="less" scoped>
  830. @import "../../common/style/common.less";
  831. @import "../../styles/orderCenter/index.less";
  832. </style>