index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. <template>
  2. <div
  3. id="review_Email"
  4. v-loading="pictLoading"
  5. class="view"
  6. element-loading-background="rgba(43, 48, 67, 0.65)"
  7. element-loading-spinner="el-icon-loading"
  8. >
  9. <div class="crm_search">
  10. <el-form ref="formRef" label-position="" :model="search" label-width="">
  11. <el-row>
  12. <el-col :span="24" :md="24" :lg="24">
  13. <el-form-item>
  14. <el-select
  15. v-model="search.tag"
  16. class="crm_search_down crm-border-radius-no"
  17. :placeholder="$t('Placeholder.Choose')"
  18. >
  19. <el-option
  20. v-for="option in searchTagOptions"
  21. :key="option.value"
  22. :label="$t(option.label)"
  23. :value="option.value"
  24. ></el-option>
  25. </el-select>
  26. </el-form-item>
  27. <el-form-item style="margin-right: 10px">
  28. <el-input
  29. v-if="search.tag == 1"
  30. v-model.trim="search.cId"
  31. class="crm-border-left-no crm-border-radius-no"
  32. clearable
  33. :placeholder="$t('Placeholder.Input')"
  34. @keyup.enter="toSearch"
  35. ></el-input>
  36. <el-input
  37. v-if="search.tag == 2"
  38. v-model.trim="search.mobile"
  39. class="crm-border-left-no crm-border-radius-no"
  40. clearable
  41. :placeholder="$t('Placeholder.Input')"
  42. @keyup.enter="toSearch"
  43. ></el-input>
  44. <el-input
  45. v-if="search.tag == 3"
  46. v-model.trim="search.email"
  47. class="crm-border-left-no crm-border-radius-no"
  48. clearable
  49. :placeholder="$t('Placeholder.Input')"
  50. @keyup.enter="toSearch"
  51. ></el-input>
  52. <el-input
  53. v-if="search.tag == 5"
  54. v-model.trim="search.currency"
  55. class="crm-border-left-no crm-border-radius-no"
  56. clearable
  57. :placeholder="$t('Placeholder.Input')"
  58. @keyup.enter="toSearch"
  59. ></el-input>
  60. </el-form-item>
  61. <el-form-item style="margin-right: 10px">
  62. <el-input
  63. v-model.trim="search.cardNumber"
  64. class="crm-border-radius-no"
  65. clearable
  66. :placeholder="$t('Placeholder.Input') + $t('Ucard.Transactions.s1')"
  67. @keyup.enter="toSearch"
  68. ></el-input>
  69. </el-form-item>
  70. <el-form-item style="margin-right: 10px">
  71. <el-select
  72. v-model="search.type"
  73. class="crm-border-radius-no"
  74. clearable
  75. :placeholder="$t('Ucard.Transactions.s3')"
  76. @change="toSearch"
  77. >
  78. <el-option
  79. v-for="option in transactionTypeOptions"
  80. :key="option.value"
  81. :label="$t(option.label)"
  82. :value="option.value"
  83. ></el-option>
  84. </el-select>
  85. </el-form-item>
  86. <el-form-item>
  87. <el-select
  88. v-model="search.status"
  89. class="crm-border-radius-no"
  90. clearable
  91. :placeholder="$t('Ucard.Transactions.s5')"
  92. @change="toSearch"
  93. >
  94. <el-option
  95. v-for="option in statusOptions"
  96. :key="option.value"
  97. :label="$t(option.label)"
  98. :value="option.value"
  99. ></el-option>
  100. </el-select>
  101. </el-form-item>
  102. <el-form-item>
  103. <el-button class="crm-border-radius-no crm-border-left-no" @click="toSearch">
  104. <el-icon><Search /></el-icon>
  105. </el-button>
  106. </el-form-item>
  107. </el-col>
  108. </el-row>
  109. <el-form-item>
  110. <el-button
  111. v-if="display['R-Transactions-Export'] && display['R-Transactions-Export'].show"
  112. type="primary"
  113. style="margin-left: 8px"
  114. @click="exportAgents"
  115. >{{ $t('Btn.Export') }}</el-button
  116. >
  117. </el-form-item>
  118. </el-form>
  119. <div class="card-mock-demo" style="margin: 30px 0">
  120. <el-table :data="mock_tableData" stripe style="margin-top: 20px; width: 100%">
  121. <el-table-column prop="" align="left" :label="$t('Label.CidAccount')">
  122. <template #default="scope">
  123. <span
  124. v-if="scope.row.cId && display['R-Transactions-Btn1'].show"
  125. class="crm-text-underline"
  126. @click="accountOpen(scope.row.cId)"
  127. >{{ scope.row.cId || '--' }}</span
  128. >
  129. <span v-else>{{ scope.row.cId || '--' }}</span>
  130. </template>
  131. </el-table-column>
  132. <el-table-column prop="" align="left" :label="$t('Label.Name')">
  133. <template #default="scope">
  134. <span v-if="scope.row.firstName">{{ scope.row.firstName + ' ' }}</span>
  135. <span v-if="scope.row.middle">{{ scope.row.middle + ' ' }}</span>
  136. <span v-if="scope.row.lastName">{{ scope.row.lastName }}</span>
  137. <span v-if="!scope.row.firstName && !scope.row.lastName && !scope.row.middle">{{
  138. '--'
  139. }}</span>
  140. </template>
  141. </el-table-column>
  142. <el-table-column prop="" align="left" :label="$t('Label.Email')">
  143. <template #default="scope">
  144. {{ scope.row.email || '--' }}
  145. </template>
  146. </el-table-column>
  147. <el-table-column prop="mobile" align="left" :label="$t('Ucard.KycAuth.item2')">
  148. <template #default="scope"> {{ scope.row.areaCode }} {{ scope.row.mobile }} </template>
  149. </el-table-column>
  150. <el-table-column prop="cardNumber" align="left" :label="$t('Ucard.Transactions.item2')">
  151. <template #default="scope">
  152. <span
  153. v-if="scope.row.cardNumber"
  154. class="crm-text-underline"
  155. @click="cardOpen(scope.row.cardNumber)"
  156. >{{ scope.row.cardNumber || '--' }}</span
  157. >
  158. <span v-else>{{ scope.row.cardNumber || '--' }}</span>
  159. </template>
  160. </el-table-column>
  161. <!-- <el-table-column prop="cardTypeId" align="left" :label="$t('Ucard.Transactions.item1')" /> -->
  162. <el-table-column prop="currency" align="left" :label="$t('Ucard.Transactions.item3')" />
  163. <el-table-column prop="amount" align="left" :label="$t('Ucard.Transactions.item4')" />
  164. <el-table-column prop="fee" align="left" :label="$t('Ucard.Transactions.item5')" />
  165. <el-table-column prop="tradeNo" align="left" :label="$t('Ucard.Transactions.item8')" />
  166. <el-table-column prop="type" align="left" :label="$t('Ucard.Transactions.item9')">
  167. <template #default="scope">
  168. <span>
  169. {{ $t(transactionTypeMap[scope.row.type]) }}
  170. </span>
  171. </template>
  172. </el-table-column>
  173. <el-table-column prop="status" align="left" :label="$t('Ucard.Transactions.item11')">
  174. <template #default="scope">
  175. <span
  176. v-if="scope.row.status === 'succeed' || scope.row.status === 'success'"
  177. class="state crm_state_blue"
  178. >{{ $t('Ucard.Transactions.t18') }}</span
  179. >
  180. <span
  181. v-else-if="scope.row.status === 'failed' || scope.row.status === 'fail'"
  182. class="state crm_state_gray"
  183. >{{ $t('Ucard.Transactions.t25') }}</span
  184. >
  185. <span v-else-if="scope.row.status === 'processing'" class="state crm_state_orange">{{
  186. $t('card.Status.t3')
  187. }}</span>
  188. <span
  189. v-else-if="scope.row.status === 'wait_process'"
  190. class="state crm_state_yellow"
  191. >{{ $t('card.Status.t5') }}</span
  192. >
  193. <span v-else class="state crm_state_green">{{ $t('Ucard.Transactions.t24') }}</span>
  194. </template>
  195. </el-table-column>
  196. <el-table-column prop="" align="center" :label="$t('Label.Action')">
  197. <template #default="scope">
  198. <el-dropdown trigger="click" @command="handleCommand">
  199. <span class="el-dropdown-link crm-cursor">
  200. <i style="font-weight: bold; font-size: 20px" class="iconfont iconcaidan"></i>
  201. </span>
  202. <template #dropdown>
  203. <el-dropdown-menu>
  204. <el-dropdown-item
  205. v-if="display['R-Transactions-Btn1'].show"
  206. :command="{ type: 1, row: scope.row }"
  207. >
  208. <el-icon><Operation /></el-icon>
  209. {{ $t('R-Hire-Check') }}
  210. </el-dropdown-item>
  211. </el-dropdown-menu>
  212. </template>
  213. </el-dropdown>
  214. </template>
  215. </el-table-column>
  216. </el-table>
  217. </div>
  218. </div>
  219. <PagePagination
  220. :pager-info="pagerInfo"
  221. @current-change="handleCurrentChange"
  222. @size-change="handleSizeChange"
  223. />
  224. <detailed-info-cid
  225. :dialog-info-cid="dialogInfoCid"
  226. :form-info="formInfo"
  227. :is-trading="true"
  228. @close="close"
  229. >
  230. </detailed-info-cid>
  231. <div v-if="dialogInfoCid" class="crm_verified_info_mask" @click="closeDia"></div>
  232. <ViewCardSingle
  233. :dialog-info-trading-single="dialogInfoTradingSingle"
  234. :form-list="formSingle"
  235. :editor-type="editorType"
  236. @close-single="closeSingle"
  237. >
  238. </ViewCardSingle>
  239. <div v-if="dialogInfoTradingSingle" class="crm_verified_info_mask" @click="closeSingle"></div>
  240. </div>
  241. </template>
  242. <script setup>
  243. import { ref, reactive, computed, watch, onMounted, inject } from 'vue'
  244. import { useRouter } from 'vue-router'
  245. import { ElMessage } from 'element-plus'
  246. import Service from '@/service/ucard'
  247. import Config from '@/config'
  248. import Service1 from '@/service/customer'
  249. import PagePagination from '@/components/pagePagination/index.vue'
  250. import DetailedInfoCid from '@/views/components/DetailedInfoCid/index.vue'
  251. import ViewCardSingle from '@/views/components/ViewCardSingle/index.vue'
  252. import { exportExcel } from '@/utils/export'
  253. import {
  254. searchTagOptions,
  255. statusOptions,
  256. transactionTypeMap,
  257. transactionTypeOptions,
  258. } from '@/views/card/CardTransactions/const'
  259. import { Operation } from '@element-plus/icons-vue'
  260. import { useI18n } from 'vue-i18n'
  261. const { Code } = Config
  262. const { t } = useI18n()
  263. const Session = inject('session')
  264. const router = useRouter()
  265. // 响应式数据
  266. const pictLoading = ref(false)
  267. const dialogInfoTradingSingle = ref(false)
  268. const formSingle = ref({})
  269. const editorType = ref(4)
  270. const search = reactive({
  271. tag: 1,
  272. mobile: '',
  273. cId: '',
  274. email: '',
  275. cardNumber: '',
  276. currency: '',
  277. type: '',
  278. dataType: '',
  279. status: '',
  280. })
  281. const mock_tableData = ref([])
  282. const pagerInfo = reactive({ row: 10, current: 1, pageTotal: 0, rowTotal: 0 })
  283. const dialogInfoCid = ref(false)
  284. const formInfo = ref({})
  285. const formRef = ref()
  286. // 计算属性
  287. const display = computed(() => {
  288. return JSON.parse(Session.Get('display', true))
  289. })
  290. // 方法
  291. // 导出
  292. const exportAgents = async () => {
  293. exportExcel('/wasabi/card/transac/record/export', { ...search }, 'Bank_Card_Transactions')
  294. }
  295. // 银行卡详情
  296. const cardOpen = (cardNumber) => {
  297. router.push({ name: 'R-CardDetail', params: { cardNumber: cardNumber } })
  298. }
  299. // 详细信息cid
  300. const accountOpen = (cId) => {
  301. router.push({ name: 'R-CustomerDetail', params: { cId: cId } })
  302. }
  303. const searchSingleCid = async (cId) => {
  304. const res = await Service1.cidRealSingle({
  305. id: cId,
  306. })
  307. if (res.code == Code.StatusOK) {
  308. // 注意:这里原代码有 editor 变量,但组件中未定义,保持原逻辑
  309. // if (this.editor) {
  310. // this.formList = res.data;
  311. // this.dialogInfoAdd = true;
  312. // } else {
  313. formInfo.value = res.data
  314. searchRealAll(cId)
  315. // }
  316. } else {
  317. ElMessage.error(res.msg)
  318. }
  319. }
  320. // 获取cid下的真实账户信息
  321. const searchRealAll = async (cId) => {
  322. const res = await Service1.realCustomerListAll({
  323. cId: cId,
  324. page: {
  325. current: 1,
  326. row: 1,
  327. },
  328. })
  329. if (res.code == Code.StatusOK) {
  330. formInfo.value.realList = res.data
  331. dialogInfoCid.value = true
  332. } else {
  333. ElMessage.error(res.msg)
  334. }
  335. }
  336. // 详细信息关闭cid/pibno
  337. const closeDia = () => {
  338. dialogInfoCid.value = false
  339. }
  340. const close = (val) => {
  341. dialogInfoCid.value = val
  342. }
  343. const toSearch = () => {
  344. pagerInfo.current = 1
  345. searchFunc()
  346. }
  347. // 更新
  348. const updateCardTypes = async () => {
  349. const res = await Service.updateCardTypes({})
  350. if (res.code == Code.StatusOK) {
  351. ElMessage.success(t('Msg.SearchSuccess'))
  352. searchFunc()
  353. } else {
  354. ElMessage.error(res.msg)
  355. }
  356. }
  357. // 查看
  358. const closeSingle = () => {
  359. dialogInfoTradingSingle.value = false
  360. }
  361. const handleCommand = (command) => {
  362. switch (command.type) {
  363. case 1:
  364. dialogInfoTradingSingle.value = true
  365. formSingle.value = command.row
  366. break
  367. }
  368. }
  369. // 列表
  370. const searchFunc = async () => {
  371. pictLoading.value = true
  372. if (!display.value['R-Transactions-Search']?.show) {
  373. ElMessage.warning(t('Msg.NotDisplay'))
  374. pictLoading.value = false
  375. return
  376. }
  377. try {
  378. const res = await Service.transactionsList({
  379. ...search,
  380. page: {
  381. current: pagerInfo.current,
  382. row: pagerInfo.row,
  383. },
  384. })
  385. if (res.code == Code.StatusOK) {
  386. mock_tableData.value = res.data
  387. if (res.page != null) {
  388. pagerInfo.rowTotal = res.page.rowTotal
  389. pagerInfo.pageTotal = res.page.pageTotal
  390. } else {
  391. pagerInfo.rowTotal = 0
  392. }
  393. ElMessage.success(t('Msg.SearchSuccess'))
  394. } else {
  395. ElMessage.error(res.msg)
  396. }
  397. } catch (error) {
  398. ElMessage.error(res.msg)
  399. }
  400. pictLoading.value = false
  401. }
  402. const handleSizeChange = (val) => {
  403. pagerInfo.row = val
  404. searchFunc()
  405. }
  406. const handleCurrentChange = (val) => {
  407. pagerInfo.current = val
  408. searchFunc()
  409. }
  410. // 生命周期
  411. onMounted(() => {
  412. searchFunc()
  413. })
  414. // 监听器
  415. watch(
  416. () => search.tag,
  417. () => {
  418. search.mobile = ''
  419. search.email = ''
  420. search.cId = ''
  421. search.cardNumber = ''
  422. search.currency = ''
  423. search.type = ''
  424. search.dataType = ''
  425. search.status = ''
  426. }
  427. )
  428. </script>
  429. <style scoped lang="scss">
  430. #review_Email {
  431. .crm_search {
  432. .search_action_btn {
  433. .delete {
  434. background-color: #a1a1a1;
  435. }
  436. .delete.active {
  437. background-color: #368fec;
  438. }
  439. }
  440. }
  441. .el-table .state {
  442. display: inline-block;
  443. min-width: 80px;
  444. max-width: 150px;
  445. box-sizing: border-box;
  446. line-height: 1.5;
  447. border-radius: 2px;
  448. padding: 2px 10px;
  449. color: #ffffff;
  450. }
  451. }
  452. </style>
  453. <style lang="scss">
  454. #review_Email {
  455. .dialog_header_w {
  456. .crm_search_down {
  457. width: 400px;
  458. }
  459. }
  460. }
  461. </style>