You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

778 lines
32 KiB

6 months ago
6 months ago
6 months ago
3 months ago
6 months ago
3 months ago
6 months ago
5 months ago
3 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
5 months ago
6 months ago
3 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
3 months ago
3 months ago
5 months ago
5 months ago
3 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
3 months ago
3 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
3 months ago
6 months ago
6 months ago
6 months ago
6 months ago
3 months ago
3 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
3 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
5 months ago
6 months ago
5 months ago
5 months ago
3 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
3 months ago
5 months ago
3 months ago
5 months ago
3 months ago
5 months ago
5 months ago
3 months ago
5 months ago
5 months ago
3 months ago
5 months ago
6 months ago
5 months ago
5 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
3 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
  1. <!-- 客服 -->
  2. <template>
  3. <el-card style="margin-bottom: 0.5vh;background-color: rgb(243,250,254);">
  4. <div class="condition">
  5. <div class="item1">
  6. <el-text size="large" style="width:4vw;">{{ t('common.jwcode') }}</el-text>
  7. <el-input v-model="searchForm.jwcode" :placeholder="t('common.jwcodePlaceholder')" style="width:9vw;"
  8. clearable />
  9. </div>
  10. <div class="item1">
  11. <el-text size="large" style="width:4vw;">{{ t('common.customerName') }}</el-text>
  12. <el-input v-model="searchForm.name" :placeholder="t('common.customerNamePlaceholder')"
  13. style="width:9vw;" clearable />
  14. </div>
  15. <div class="item1">
  16. <el-text size="large" style="width:4vw;">{{ t('common.productName') }}</el-text>
  17. <el-cascader v-model="searchForm.goodsName" :props="{ multiple: false, emitPath: false }" :show-all-levels="false" :options="productList" style="width: 10vw;" :placeholder="t('common.productNamePlaceholder')" clearable />
  18. </div>
  19. <div class="item1" v-if="isHeadquarters">
  20. <el-text size="large" style="width:4vw;">{{ t('common.market') }}</el-text>
  21. <el-cascader style="width: 9vw;" v-model="searchForm.market" :options="market"
  22. :placeholder="t('common.marketPlaceholder')" clearable @change="handleMarketChange" />
  23. </div>
  24. <div class="item1">
  25. <el-text size="large" style="width:4vw;" multiple>{{ t('common.orderStatus') }}</el-text>
  26. <el-select v-model="searchForm.statuses" style="width:9vw;" clearable>
  27. <el-option v-for="item in statusList" :key="item" :label="item" :value="item" />
  28. </el-select>
  29. </div>
  30. </div>
  31. <div class="condition">
  32. <div class="item2">
  33. <el-text size="large" style="width:4vw;">{{ t('common.payCurrency') }}</el-text>
  34. <el-select v-model="searchForm.paymentCurrency" style="width:9vw;" clearable>
  35. <el-option v-for="item in currencies" :key="item" :label="item" :value="item" />
  36. </el-select>
  37. </div>
  38. <div class="item2">
  39. <el-text size="large" style="width:4vw;">{{ t('common.payModel') }}</el-text>
  40. <el-select v-model="searchForm.payType" style="width:9vw;" clearable>
  41. <el-option v-for="item in channelOptions" :key="item" :label="item" :value="item" />
  42. </el-select>
  43. </div>
  44. <div class="item2" style="width: 28.5vw;">
  45. <el-text size="large" style="width:4vw;">{{ t('common.payTime') }}</el-text>
  46. <el-date-picker v-model="dateRange" type="datetimerange" :range-separator="t('common.to')"
  47. :start-placeholder="t('common.startTime')" :end-placeholder="t('common.endTime')"
  48. style="width:22vw;" :disabled-date="disabledDate" :default-time="defaultTime" clearable />
  49. </div>
  50. <div>
  51. <el-button type="primary" @click="getRefund">{{ t('common.search') }}</el-button>
  52. <!-- <el-button type="warning">导出excel</el-button>
  53. <el-button type="primary">查看导出列表</el-button> -->
  54. <el-button type="success" @click="reset">{{ t('common.reset') }}</el-button>
  55. </div>
  56. </div>
  57. </el-card>
  58. <el-card style="margin-top: 0.5vh;background-color: rgb(231,244,253);">
  59. <el-table ref="tableRef" :data="tableData" style="height:73vh;width:82vw;background-color: rgb(243,250,254);">
  60. <el-table-column type="index" :label="t('common_list.id')" width="60" fixed="left">
  61. <template #default="scope">
  62. {{ scope.$index + 1 + (pagination.pageNum - 1) * pagination.pageSize }}
  63. </template>
  64. </el-table-column>
  65. <el-table-column prop="jwcode" label="Homily ID" width="120" fixed="left" />
  66. <el-table-column prop="name" :label="t('common_list.name')" width="120" fixed="left"
  67. show-overflow-tooltip />
  68. <el-table-column prop="marketName" :label="t('common_list.market')" width="120" />
  69. <el-table-column prop="activity" :label="t('common_list.activity')" width="120px" show-overflow-tooltip />
  70. <el-table-column prop="goodsName" :label="t('common_list.productName')" width="130" show-overflow-tooltip />
  71. <el-table-column prop="goodsNum" :label="t('common_list.productNum')" width="130px">
  72. <template #default="scope">
  73. <span v-if="scope.row.goodsName == t('common_list.goldRecharge')">{{
  74. scope.row.permanentGold }} {{ t('cash.unit') }}</span>
  75. <span v-else>{{ scope.row.goodsNum }} {{ scope.row.numUnit }}</span>
  76. </template>
  77. </el-table-column>
  78. <el-table-column prop="paymentCurrency" :label="t('common_add.payCurrency')" width="120" />
  79. <el-table-column prop="paymentAmount" :label="t('common_add.payAmount')" width="120" />
  80. <el-table-column prop="payType" :label="t('common_add.payMethod')" width="140" />
  81. <el-table-column prop="payTime" :label="t('common_add.payTime')" width="180" />
  82. <el-table-column prop="voucher" :label="t('common_add.transferVoucher')" width="110px">
  83. <template #default="scope">
  84. <div v-if="scope.row.voucher"
  85. style="display: flex; justify-content: center; align-items: center; cursor: pointer;"
  86. @click="previewImage(scope.row.voucher)">
  87. <img :src="scope.row.voucher" alt="转账凭证" style="width: auto; height: 40px;">
  88. </div>
  89. <div v-else style="display: flex; justify-content: center; align-items: center; height: 40px;">{{
  90. t('common_add.noTransferVoucher') }}
  91. </div>
  92. </template>
  93. </el-table-column>
  94. <el-table-column prop="remark" :label="t('common_list.remark')" width="150" show-overflow-tooltip />
  95. <el-table-column prop="status" :label="t('common_list.orderStatus')" width="120">
  96. <template #default="scope">
  97. {{
  98. [10].includes(scope.row.status) ? t('cash.statusList.submitted') :
  99. [20, 30, 40].includes(scope.row.status) ? t('cash.statusList.inProgress') :
  100. [12, 22, 32].includes(scope.row.status) ? t('cash.statusList.rejected') :
  101. [11].includes(scope.row.status) ? t('cash.statusList.recalled') :
  102. scope.row.status === 41 ? t('cash.statusList.refunded') : scope.row.status
  103. }}
  104. </template>
  105. </el-table-column>
  106. <el-table-column prop="operation" :label="t('common_list.operation')" fixed="right" width="140px">
  107. <template #default="scope">
  108. <div class="operation">
  109. <!-- <el-button v-if="scope.row.status === 10" type="primary" text
  110. @click="showBackDialog(scope.row)">
  111. {{ t('common.withdraw') }}
  112. </el-button> -->
  113. <el-button v-if="scope.row.status === 11" type="primary" text
  114. @click="showEditDialog(scope.row)">
  115. {{ t('common.edit') }}
  116. </el-button>
  117. <el-button v-if="[12, 22, 32].includes(scope.row.status)" type="primary" text
  118. @click="showRejectReasonDialog(scope.row)">
  119. {{ t('common.viewRejectReason') }}
  120. </el-button>
  121. </div>
  122. </template>
  123. </el-table-column>
  124. </el-table>
  125. <el-pagination v-model:current-page="pagination.pageNum" v-model:page-size="pagination.pageSize"
  126. layout="total, sizes, prev, pager, next, jumper" :total="pagination.total"
  127. @size-change="handlePageSizeChange" @current-change="handleCurrentChange"
  128. style="margin-top: 1vh;"></el-pagination>
  129. </el-card>
  130. <el-dialog v-model="showEdit" :title="t('common_add.refund')" class="editDialog" overflow draggable
  131. style="width: 40vw; background-color: #F3FAFE !important;">
  132. <div style="display: flex;">
  133. <div class="left">
  134. <div class="add-item">
  135. <el-text style="width:4vw;">{{ t('common_add.jwcode') }}</el-text>
  136. <el-input v-model="editRow.jwcode" style="width:10vw;" disabled />
  137. </div>
  138. <div class="add-item">
  139. <el-text style="width:4vw;">{{ t('common_add.customerName') }}</el-text>
  140. <el-input v-model="editRow.name" style="width:10vw;" disabled />
  141. </div>
  142. <div class="add-item">
  143. <el-text style="width:4vw;">{{ t('common_add.market') }}</el-text>
  144. <el-input v-model="editRow.marketName" style="width:10vw;" disabled />
  145. </div>
  146. <div class="add-item">
  147. <el-text style="width:4vw;">{{ t('common_add.activity') }}</el-text>
  148. <el-input v-model="editRow.activity" style="width:10vw;" disabled />
  149. </div>
  150. <div class="add-item">
  151. <el-text style="width:4vw;">{{ t('common_add.productName') }}</el-text>
  152. <el-input v-model="editRow.goodsName" style="width:10vw;" disabled />
  153. </div>
  154. <div class="add-item" v-if="editRow.goodsName !== t('cash.coinRecharge')">
  155. <el-text style="width:4vw;">{{ t('common_add.productNum') }}</el-text>
  156. <el-input v-model="editRow.goodsNum" style="width:10vw;" disabled />
  157. &nbsp;{{ editRow.numUnit }}
  158. </div>
  159. <div class="add-item" v-if="editRow.goodsName == t('cash.coinRecharge')">
  160. <el-text style="width:4vw;">{{ t('refund.permanentGold') }}</el-text>
  161. <el-input v-model="editRow.gold" style="width:10vw;" disabled />
  162. &nbsp;{{ t('cash.unit') }}
  163. </div>
  164. <div class="add-item" v-if="editRow.goodsName == t('cash.coinRecharge')">
  165. <el-text style="width:4vw;">{{ t('refund.freeGold') }}</el-text>
  166. <el-input v-model="editRow.free" style="width:10vw;" disabled />
  167. &nbsp;{{ t('cash.unit') }}
  168. </div>
  169. <div class="add-item">
  170. <el-text style="width:4vw;">{{ t('common_add.payCurrency') }}</el-text>
  171. <el-input v-model="editRow.paymentCurrency" style="width:10vw;" disabled />
  172. </div>
  173. <div class="add-item">
  174. <el-text style="width:4vw;">{{ t('common_add.payAmount') }}</el-text>
  175. <el-input v-model="editRow.paymentAmount" style="width:10vw;" disabled />
  176. </div>
  177. <div class="add-item">
  178. <el-text style="width:4vw;">{{ t('common_add.payMethod') }}</el-text>
  179. <el-input v-model="editRow.payType" style="width:10vw;" disabled />
  180. </div>
  181. <div class="add-item">
  182. <el-text style="width:4vw;">{{ t('common_add.payTime') }}</el-text>
  183. <el-date-picker v-model="editRow.payTime" type="datetime" style="width:10vw;" disabled />
  184. </div>
  185. <div class="add-item">
  186. <el-text style="width:4vw;">{{ t('common_add.transferVoucher') }}</el-text>
  187. <img v-if="editRow.voucher" :src="editRow.voucher"
  188. style="width: 80px; height: 80px; object-fit: cover;">
  189. <div v-else>
  190. {{ t('common_add.noTransferVoucher') }}
  191. </div>
  192. </div>
  193. <div class="add-item">
  194. <el-text style="width:4vw;">{{ t('common_add.remark') }}</el-text>
  195. <el-input v-model="editRow.remark" style="width:10vw;" :rows="3" type="textarea" maxLength="100"
  196. disabled show-word-limit />
  197. </div>
  198. </div>
  199. <div class="right">
  200. <div class="add-item">
  201. <el-text style="width:4vw;">{{ t('common_add.refundType') }}</el-text>
  202. <el-radio-group v-model="editForm.refundModel">
  203. <el-radio value="0">{{ t('common_add.refundModelAll') }}</el-radio>
  204. <el-radio value="1">{{ t('common_add.refundModelPart') }}</el-radio>
  205. </el-radio-group>
  206. </div>
  207. <div class="add-item" v-show="editRow.goodsName == t('cash.coinRecharge') && editForm.refundModel === '1'">
  208. <el-text style="width:4vw;">{{ t('common_add.permanentGold') }}</el-text>
  209. <el-input v-model="editForm.partRefundGold" style="width:5vw;" />&nbsp;&nbsp;{{ t('cash.unit') }}
  210. </div>
  211. <div class="add-item" v-show="editRow.goodsName == t('cash.coinRecharge') && editForm.refundModel === '1'">
  212. <el-text style="width:4vw;">{{ t('common_add.freeGold') }}</el-text>
  213. <el-input v-model="editForm.partRefundFree" style="width:5vw;" />&nbsp;&nbsp;{{ t('cash.unit') }}
  214. </div>
  215. <div class="add-item">
  216. <el-text style="width:4vw;">{{ t('common_add.refundReason') }}</el-text>
  217. <el-input v-model="editForm.refundReason" style="width:10vw;" :rows="5" maxlength="150"
  218. show-word-limit type="textarea" />
  219. </div>
  220. <div>{{ t('common_add.tip') }}</div>
  221. <div style="display:flex;justify-content: center;margin-top: 5vh;">
  222. <el-button type="default" @click="cancelEdit">{{ t('common.cancel') }}</el-button>
  223. <el-button type="primary" @click="submitEdit">{{ t('common.submit') }}</el-button>
  224. </div>
  225. </div>
  226. </div>
  227. </el-dialog>
  228. <ConfirmDialog v-model="showBack" :message="t('common.willRecallOrder')" @confirm="recall"
  229. @cancel="showBack = false" @close="showBack = false" />
  230. <el-dialog v-model="showError" overflow draggable class="back-dialog" :style="{
  231. backgroundImage: `url(${RefundRecallBackground})`,
  232. backgroundSize: 'cover',
  233. backgroundPosition: 'center'
  234. }">
  235. <div class="back-text">{{ t('elmessage.refundAmountError') }}</div>
  236. <div class="back-btn">
  237. <el-button type="default" @click="showError = false">{{ t('common.cancel') }}</el-button>
  238. <el-button type="primary" @click="" style="margin-left: 2vw;">{{ t('common.confirm') }}</el-button>
  239. </div>
  240. </el-dialog>
  241. <el-dialog v-model="showRejectReason" :title="t('common.viewRejectReason')" width="40%" style="background-color: rgb(243,250,254);">
  242. <div>{{ rejectReason }}</div>
  243. </el-dialog>
  244. </template>
  245. <script setup>
  246. import { ref, onMounted, computed, nextTick } from 'vue'
  247. import { ElMessage } from 'element-plus'
  248. import API from '@/util/http.js'
  249. const uploadUrl = 'https://api.homilychart.com/hljw/api/aws/upload'
  250. import { useAdminStore } from "@/store/index.js"
  251. import { storeToRefs } from "pinia"
  252. import dayjs from 'dayjs'
  253. const adminStore = useAdminStore()
  254. const { adminData, menuTree } = storeToRefs(adminStore)
  255. import { permissionMapping, findMenuById, hasMenuPermission } from "@/utils/menuTreePermission.js"
  256. import ConfirmDialog from '@/components/dialogs/ConfirmDialog.vue'
  257. import { pa } from 'element-plus/es/locales.mjs'
  258. import { productList, CurrencyForId } from '@/views/moneyManage/receiveDetail/utils/staticData.js'
  259. import RefundRecallBackground from '@/assets/images/refund-recall.png'
  260. import { isNumber } from 'lodash'
  261. import { re } from 'mathjs'
  262. import { useI18n } from 'vue-i18n'
  263. const { t } = useI18n()
  264. const isHeadquarters = computed(() => {
  265. const m = adminData.value.markets
  266. return m === t('common.markets.headquarters') || m === '总部' || m === 'Headquarters'
  267. })
  268. const dateRange = ref([])
  269. const searchForm = ref({
  270. jwcode: '',
  271. market: [],
  272. statuses: [],
  273. goodsName: []
  274. })
  275. const market = ref([])
  276. const backRow = ref({})// 撤回存数据
  277. const editRow = ref({})// 编辑存数据
  278. const rejectReason = ref('')// 驳回理由
  279. const showRejectReason = ref(false)
  280. const editForm = ref({
  281. refundModel: '',
  282. refundReason: ''
  283. })
  284. const auditForm = ref({
  285. refundType: ''
  286. })
  287. const pagination = ref({
  288. pageNum: 1,
  289. pageSize: 50,
  290. total: 0
  291. })
  292. const tableData = ref([])
  293. const tableRef = ref(null)
  294. const scrollTableTop = () => {
  295. tableRef.value?.setScrollTop?.(0)
  296. }
  297. const showEdit = ref(false)
  298. const uploadRef = ref(null)
  299. const showBack = ref(false)
  300. const showError = ref(false)
  301. const isKF = adminData.value.adminName.includes('客服')
  302. const statusList = computed(() => [
  303. t('cash.statusList.submitted'),
  304. t('cash.statusList.recalled'),
  305. t('cash.statusList.inProgress'),
  306. t('cash.statusList.refunded'),
  307. t('cash.statusList.rejected')
  308. ])
  309. // 查全部
  310. const getRefund = async function () {
  311. if (!hasMenuPermission(menuTree.value, permissionMapping.view_customer_service_refund_pending)) {
  312. ElMessage.error(t('elmessage.noPermission'))
  313. return
  314. }
  315. try {
  316. const statusParam = ref([])
  317. if (searchForm.value.statuses === t('cash.statusList.submitted')) {
  318. statusParam.value = [10]
  319. } else if (searchForm.value.statuses === t('cash.statusList.recalled')) {
  320. statusParam.value = [11]
  321. } else if (searchForm.value.statuses === t('cash.statusList.inProgress')) {
  322. statusParam.value = [20, 30, 40]
  323. } else if (searchForm.value.statuses === t('cash.statusList.refunded')) {
  324. statusParam.value = [41]
  325. } else if (searchForm.value.statuses === t('cash.statusList.rejected')) {
  326. statusParam.value = [12, 22, 32]
  327. }
  328. console.log('goodsName', searchForm.value.goodsName);
  329. let goodsName = searchForm.value.goodsName && searchForm.value.goodsName.length > 0
  330. ? [searchForm.value.goodsName] : []
  331. if (searchForm.value.jwcode) {
  332. const isPositiveInteger = /^[1-9]\d*$/.test(searchForm.value.jwcode);
  333. if (!isPositiveInteger) {
  334. ElMessage.error(t('elmessage.checkJwcodeFormat'))
  335. return;
  336. }
  337. }
  338. // 增加精网号长度限制,防止后端400错误
  339. if (searchForm.value.jwcode.length > 8) {
  340. ElMessage.error(t('elmessage.limitJwcodeLength'))
  341. return;
  342. }
  343. const params = {
  344. pageNum: pagination.value.pageNum,
  345. pageSize: pagination.value.pageSize,
  346. cashRecordDTO: {
  347. jwcode: searchForm.value.jwcode,//精网号
  348. name: searchForm.value.name,//姓名
  349. markets: searchForm.value.market && searchForm.value.market.length > 0 ? [searchForm.value.market[searchForm.value.market.length - 1]] : [],
  350. goodsNames: goodsName,//商品名
  351. statuses: statusParam.value,//10:地区财务待审核;12:地区财务驳回;
  352. // 20:地区负责人待审核;22:地区负责人驳回;
  353. // 30:总部财务待审核;32:总部财务驳回;
  354. // 40:执行人待处理;41:执行人已处理,退款完成;
  355. paymentCurrency: CurrencyForId(searchForm.value.paymentCurrency),//付款币种
  356. payType: searchForm.value.payType,//支付方式
  357. startTime: dateRange.value && dateRange.value[0] ? dayjs(dateRange.value[0]).format('YYYY-MM-DD HH:mm:ss') : "",
  358. endTime: dateRange.value && dateRange.value[1] ? dayjs(dateRange.value[1]).format('YYYY-MM-DD HH:mm:ss') : "",
  359. submitterId: adminData.value.id
  360. }
  361. }
  362. const result = await API({
  363. url: '/Money/selecta',
  364. method: 'POST',
  365. data: params
  366. })
  367. tableData.value = result.data.list || []
  368. await nextTick()
  369. scrollTableTop()
  370. pagination.value.total = result.data.total || 0
  371. } catch (error) {
  372. ElMessage.error(error.message || t('elmessage.searchFailed'))
  373. }
  374. }
  375. // 撤回
  376. const recall = async function () {
  377. if (!hasMenuPermission(menuTree.value, permissionMapping.withdraw_customer_service_refund)) {
  378. ElMessage.error(t('elmessage.noPermission'))
  379. return
  380. }
  381. try {
  382. console.log(backRow.value)
  383. const params = {
  384. id: backRow.value.id,
  385. status: backRow.value.status,
  386. orderType: backRow.value.orderType
  387. }
  388. const result = await API({
  389. url: '/Money/update',
  390. data: params
  391. })
  392. if (result.code === 200) {
  393. ElMessage.success(result.msg || t('elmessage.withdrawSuccess'))
  394. showBack.value = false
  395. getRefund()
  396. } else {
  397. ElMessage.error(result.msg || t('elmessage.operationFailed'))
  398. }
  399. } catch (error) {
  400. ElMessage.error(error.message || t('elmessage.operationFailed'))
  401. }
  402. }
  403. // 编辑
  404. const submitEdit = async function () {
  405. if (!hasMenuPermission(menuTree.value, permissionMapping.edit_customer_service_refund)) {
  406. ElMessage.error(t('elmessage.noPermission'))
  407. return
  408. }
  409. try {
  410. console.log(editRow.value)
  411. if (!editForm.value.refundModel) {
  412. ElMessage.error(t('elmessage.selectRefundModel'))
  413. return
  414. } else if (!editForm.value.refundReason) {
  415. ElMessage.error(t('elmessage.refundReasonPlaceholder'))
  416. return
  417. } else if (editRow.value.goodsName === t('cash.coinRecharge') && editForm.value.refundModel == 1) {
  418. if (!editForm.value.partRefundGold || !editForm.value.partRefundFree) {
  419. ElMessage.error(t('elmessage.inputRefundBeansBoth'))
  420. return
  421. }
  422. const isPositiveInteger = /^[0-9]\d*$/.test(editForm.value.partRefundGold)
  423. if (!isPositiveInteger) {
  424. ElMessage.error(t('elmessage.checkPermanentFormat'))
  425. return
  426. }
  427. const isPositiveInteger1 = /^[0-9]\d*$/.test(editForm.value.partRefundFree)
  428. if (!isPositiveInteger1) {
  429. ElMessage.error(t('elmessage.checkFreeFormat'))
  430. return
  431. }
  432. if(editForm.value.partRefundFree == 0 && editForm.value.partRefundGold == 0){
  433. ElMessage.error(t('elmessage.checkRefundgolds'))
  434. return
  435. }
  436. }
  437. let params = {
  438. id: editRow.value.id,
  439. status: editRow.value.status,
  440. refundModel: editForm.value.refundModel,
  441. refundReason: editForm.value.refundReason,
  442. jwcode: editRow.value.jwcode,
  443. paymentAmount: editRow.value.paymentAmount,
  444. paymentCurrency: editRow.value.paymentCurrency,
  445. newRefundGold: (editForm.value.partRefundGold * 100),
  446. newRefundFree: (editForm.value.partRefundFree) * 100
  447. }
  448. if(params.refundModel == 0){
  449. params.newRefundGold = (editRow.value.gold)*100
  450. params.newRefundFree = (editRow.value.free)*100
  451. }
  452. console.log('params',params);
  453. if (editRow.value.goodsName != t('cash.coinRecharge')) {
  454. params.newRefundGold = ''
  455. params.newRefundFree = ''
  456. }
  457. if (editRow.value.goodsName == t('cash.coinRecharge')) {
  458. if (editForm.value.partRefundGold > editRow.value.gold) {
  459. ElMessage.error(t('elmessage.limitRefundGoldNotExceedOriginal'))
  460. return
  461. }
  462. if (editForm.value.partRefundFree > editRow.value.free) {
  463. ElMessage.error(t('elmessage.limitRefundFreeNotExceedOriginal'))
  464. return
  465. }
  466. }
  467. const result = await API({
  468. url: '/Money/update',
  469. data: params
  470. })
  471. if (result.code === 200) {
  472. ElMessage.success(result.msg || t('elmessage.editSuccess'))
  473. showEdit.value = false
  474. getRefund()
  475. cancelEdit()
  476. } else {
  477. ElMessage.error(result.msg || t('elmessage.editFailed'))
  478. }
  479. } catch (error) {
  480. ElMessage.error(error.message || t('elmessage.editFailed'))
  481. }
  482. }
  483. const getMarket = async function () {
  484. try {
  485. const result = await API({
  486. url: '/market/selectMarket',
  487. })
  488. console.log('看看地区树', result)
  489. const transformTree = (nodes) => {
  490. const allChildren = nodes.flatMap(node => node.children || []);
  491. return allChildren.map(child => {
  492. const grandchildren = child.children && child.children.length
  493. ? transformTree([child])
  494. : null;
  495. return {
  496. value: child.id,
  497. label: child.name,
  498. children: grandchildren
  499. };
  500. });
  501. };
  502. market.value = transformTree(result.data)
  503. console.log('转换后的地区树==============', market.value)
  504. } catch (error) {
  505. console.log('请求失败', error)
  506. }
  507. }
  508. // 预览图片函数
  509. // const previewImage = (imageUrl) => {
  510. // // 使用 element-plus 的 el-image 组件实现图片预览功能
  511. // const imageElement = document.createElement('img');
  512. // imageElement.src = imageUrl;
  513. // imageElement.style.maxWidth = '80vw';
  514. // imageElement.style.maxHeight = '80vh';
  515. // const viewer = document.createElement('div');
  516. // viewer.style.position = 'fixed';
  517. // viewer.style.top = '0';
  518. // viewer.style.left = '0';
  519. // viewer.style.width = '100vw';
  520. // viewer.style.height = '100vh';
  521. // viewer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
  522. // viewer.style.display = 'flex';
  523. // viewer.style.justifyContent = 'center';
  524. // viewer.style.alignItems = 'center';
  525. // viewer.style.zIndex = '9999';
  526. // viewer.style.overflow = 'auto';
  527. // viewer.appendChild(imageElement);
  528. // document.body.appendChild(viewer);
  529. // viewer.addEventListener('click', () => {
  530. // document.body.removeChild(viewer);
  531. // });
  532. // };
  533. const previewImage = (imageUrl) => {
  534. if (!imageUrl) return;
  535. const imageElement = document.createElement('img');
  536. imageElement.src = imageUrl;
  537. imageElement.style.maxWidth = '90vw';
  538. imageElement.style.maxHeight = '90vh';
  539. imageElement.style.display = 'block';
  540. imageElement.style.transition = 'transform 0.2s ease-out';
  541. imageElement.style.cursor = 'zoom-in';
  542. imageElement.style.transformOrigin = 'center center'; // 缩放中心点
  543. const viewer = document.createElement('div');
  544. viewer.style.position = 'fixed';
  545. viewer.style.top = '0';
  546. viewer.style.left = '0';
  547. viewer.style.width = '100vw';
  548. viewer.style.height = '100vh';
  549. viewer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
  550. viewer.style.display = 'flex';
  551. viewer.style.justifyContent = 'center';
  552. viewer.style.alignItems = 'center';
  553. viewer.style.overflow = 'hidden';
  554. viewer.style.zIndex = '999999';
  555. viewer.appendChild(imageElement);
  556. let currentScale = 1;
  557. const scaleStep = 0.2;
  558. const handleWheel = (e) => {
  559. e.preventDefault();
  560. if (e.deltaY > 0) {
  561. currentScale -= scaleStep;
  562. } else {
  563. currentScale += scaleStep;
  564. }
  565. if (currentScale < 0.5) currentScale = 0.5;
  566. imageElement.style.transform = `scale(${currentScale})`;
  567. imageElement.style.cursor = currentScale > 1 ? 'zoom-out' : 'zoom-in';
  568. };
  569. viewer.addEventListener('wheel', handleWheel, { passive: false });
  570. viewer.addEventListener('click', (e) => {
  571. if (e.target === viewer) {
  572. document.body.removeChild(viewer);
  573. viewer.removeEventListener('wheel', handleWheel);
  574. }
  575. });
  576. document.body.appendChild(viewer);
  577. };
  578. const cancelEdit = function () {
  579. editForm.value = {
  580. refundModel: '',
  581. refundReason: '',
  582. partRefundGold: '',
  583. partRefundFree: ''
  584. }
  585. showEdit.value = false
  586. }
  587. const currencies = computed(() => [
  588. t('cash.currency.usd'),
  589. t('cash.currency.hkd'),
  590. t('cash.currency.sgd'),
  591. t('cash.currency.myr'),
  592. t('cash.currency.thb'),
  593. t('cash.currency.cad'),
  594. t('cash.currency.vnd'),
  595. t('cash.currency.krw'),
  596. t('cash.currency.rmb'),
  597. ])
  598. const channelOptions = computed(() => [
  599. t('cash.payMethods.stripe'), // Stripe
  600. t('cash.payMethods.paymentAsia'), // PaymentAsia
  601. t('cash.payMethods.stripe2'), // Stripe2
  602. t('cash.payMethods.ipay88'), // Ipay88
  603. t('cash.payMethods.grabpay'), // Grabpay
  604. t('cash.payMethods.nets'), // Nets
  605. t('cash.payMethods.transfer'), // E-Transfer
  606. t('cash.payMethods.paypal'), // PayPal
  607. t('cash.payMethods.paysolution'), // Paysolution
  608. t('cash.payMethods.bankTransfer'),// 银行转账
  609. t('cash.payMethods.card'), // 刷卡
  610. t('cash.payMethods.cash'), // 现金
  611. t('cash.payMethods.check'), // 支票
  612. ])
  613. const reset = function () {
  614. searchForm.value = {
  615. jwcode: '',
  616. market: [],
  617. statuses: [],
  618. goodsName: []
  619. }
  620. // 重置页码
  621. pagination.value.pageNum = 1
  622. dateRange.value = []
  623. getRefund()
  624. }
  625. const showBackDialog = function (row) {
  626. backRow.value = row
  627. showBack.value = true
  628. }
  629. const showEditDialog = function (row) {
  630. editRow.value = row
  631. showEdit.value = true
  632. }
  633. const handlePageSizeChange = function (val) {
  634. pagination.value.pageSize = val
  635. getRefund()
  636. }
  637. const handleCurrentChange = function (val) {
  638. pagination.value.pageNum = val
  639. getRefund()
  640. }
  641. const disabledDate = (time) => {
  642. const limitDate = new Date(2025, 0, 1);
  643. return time.getTime() < limitDate.getTime();
  644. }
  645. const handleMarketChange = (value) => {
  646. searchForm.value.market = value || []
  647. }
  648. const defaultTime = [
  649. new Date(2000, 1, 1, 0, 0, 0),
  650. new Date(2000, 2, 1, 23, 59, 59),
  651. ]
  652. const showRejectReasonDialog = function (row) {
  653. rejectReason.value = row.rejectReason
  654. showRejectReason.value = true
  655. }
  656. onMounted(() => {
  657. getRefund()
  658. getMarket()
  659. console.log('???????????????????', adminData.value)
  660. })
  661. </script>
  662. <style scoped lang="scss">
  663. :deep(.el-table__header-wrapper),
  664. :deep(.el-table__body-wrapper),
  665. :deep(.el-table__cell),
  666. :deep(.el-table__body td) {
  667. background-color: #F3FAFE !important;
  668. }
  669. :deep(.el-table__header th) {
  670. background-color: #F3FAFE !important;
  671. }
  672. .condition {
  673. width: 82vw;
  674. display: flex;
  675. align-items: center;
  676. height: 4vh;
  677. .item1 {
  678. width: 18%;
  679. display: flex;
  680. align-items: center;
  681. margin-bottom: 1vh;
  682. margin-right: 0.5vw;
  683. }
  684. .item2 {
  685. width: 18%;
  686. display: flex;
  687. align-items: center;
  688. margin-right: 0.5vw;
  689. }
  690. }
  691. .editDialog {
  692. .left {
  693. width: 50%;
  694. height: 70vh;
  695. padding: 0 2vw;
  696. .add-item {
  697. display: flex;
  698. align-items: center;
  699. margin-bottom: 1vh;
  700. }
  701. .image {
  702. width: 4vw !important;
  703. height: 4vw !important;
  704. }
  705. }
  706. .right {
  707. width: 50%;
  708. height: 50vh;
  709. .add-item {
  710. display: flex;
  711. align-items: center;
  712. margin-bottom: 1vh;
  713. }
  714. }
  715. }
  716. .back-dialog {
  717. width: 700px;
  718. height: auto;
  719. .back-text {
  720. font-size: 60px;
  721. font-weight: bold;
  722. color: #000000;
  723. text-align: center;
  724. justify-content: center;
  725. margin-top: 22vh;
  726. }
  727. .back-btn {
  728. height: 20vh;
  729. display: flex;
  730. justify-content: center;
  731. align-items: center;
  732. }
  733. }
  734. </style>