index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <template>
  2. <doc-alert title="支付功能开启" url="https://doc.iocoder.cn/pay/build/" />
  3. <!-- 搜索 -->
  4. <ContentWrap>
  5. <el-form
  6. class="-mb-15px"
  7. :model="queryParams"
  8. ref="queryFormRef"
  9. :inline="true"
  10. label-width="68px"
  11. >
  12. <el-form-item label="应用名" prop="name">
  13. <el-input
  14. v-model="queryParams.name"
  15. placeholder="请输入应用名"
  16. clearable
  17. @keyup.enter="handleQuery"
  18. class="!w-240px"
  19. />
  20. </el-form-item>
  21. <el-form-item label="开启状态" prop="status">
  22. <el-select
  23. v-model="queryParams.status"
  24. placeholder="请选择开启状态"
  25. clearable
  26. class="!w-240px"
  27. >
  28. <el-option
  29. v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
  30. :key="dict.value"
  31. :label="dict.label"
  32. :value="dict.value"
  33. />
  34. </el-select>
  35. </el-form-item>
  36. <el-form-item label="创建时间" prop="createTime">
  37. <el-date-picker
  38. v-model="queryParams.createTime"
  39. value-format="YYYY-MM-DD HH:mm:ss"
  40. type="daterange"
  41. start-placeholder="开始日期"
  42. end-placeholder="结束日期"
  43. :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
  44. class="!w-240px"
  45. />
  46. </el-form-item>
  47. <el-form-item>
  48. <el-button @click="handleQuery">
  49. <Icon icon="ep:search" class="mr-5px" />
  50. 搜索
  51. </el-button>
  52. <el-button @click="resetQuery">
  53. <Icon icon="ep:refresh" class="mr-5px" />
  54. 重置
  55. </el-button>
  56. <el-button type="primary" plain @click="openForm('create')" v-hasPermi="['pay:app:create']">
  57. <Icon icon="ep:plus" class="mr-5px" />
  58. 新增
  59. </el-button>
  60. </el-form-item>
  61. </el-form>
  62. </ContentWrap>
  63. <!-- 列表 -->
  64. <ContentWrap>
  65. <el-table v-loading="loading" :data="list">
  66. <el-table-column label="应用编号" align="center" prop="id" />
  67. <el-table-column label="应用名" align="center" prop="name" />
  68. <el-table-column label="开启状态" align="center" prop="status">
  69. <template #default="scope">
  70. <el-switch
  71. v-model="scope.row.status"
  72. :active-value="0"
  73. :inactive-value="1"
  74. @change="handleStatusChange(scope.row)"
  75. />
  76. </template>
  77. </el-table-column>
  78. <el-table-column label="支付宝配置" align="center">
  79. <el-table-column
  80. :label="channel.name"
  81. align="center"
  82. v-for="channel in alipayChannels"
  83. :key="channel.code"
  84. >
  85. <template #default="scope">
  86. <el-button
  87. type="success"
  88. v-if="isChannelExists(scope.row.channelCodes, channel.code)"
  89. @click="openChannelForm(scope.row, channel.code)"
  90. circle
  91. >
  92. <Icon icon="ep:check" />
  93. </el-button>
  94. <el-button
  95. v-else
  96. type="danger"
  97. circle
  98. @click="openChannelForm(scope.row, channel.code)"
  99. >
  100. <Icon icon="ep:close" />
  101. </el-button>
  102. </template>
  103. </el-table-column>
  104. </el-table-column>
  105. <el-table-column label="微信配置" align="center">
  106. <el-table-column
  107. :label="channel.name"
  108. align="center"
  109. v-for="channel in wxChannels"
  110. :key="channel.code"
  111. >
  112. <template #default="scope">
  113. <el-button
  114. type="success"
  115. v-if="isChannelExists(scope.row.channelCodes, channel.code)"
  116. @click="openChannelForm(scope.row, channel.code)"
  117. circle
  118. >
  119. <Icon icon="ep:check" />
  120. </el-button>
  121. <el-button
  122. v-else
  123. type="danger"
  124. circle
  125. @click="openChannelForm(scope.row, channel.code)"
  126. >
  127. <Icon icon="ep:close" />
  128. </el-button>
  129. </template>
  130. </el-table-column>
  131. </el-table-column>
  132. <el-table-column label="钱包支付配置" align="center">
  133. <el-table-column :label="PayChannelEnum.WALLET.name" align="center">
  134. <template #default="scope">
  135. <el-button
  136. type="success"
  137. circle
  138. v-if="isChannelExists(scope.row.channelCodes, PayChannelEnum.WALLET.code)"
  139. @click="openChannelForm(scope.row, PayChannelEnum.WALLET.code)"
  140. >
  141. <Icon icon="ep:check" />
  142. </el-button>
  143. <el-button
  144. v-else
  145. type="danger"
  146. circle
  147. @click="openChannelForm(scope.row, PayChannelEnum.WALLET.code)"
  148. >
  149. <Icon icon="ep:close" />
  150. </el-button>
  151. </template>
  152. </el-table-column>
  153. </el-table-column>
  154. <el-table-column label="模拟支付配置" align="center">
  155. <el-table-column :label="PayChannelEnum.MOCK.name" align="center">
  156. <template #default="scope">
  157. <el-button
  158. type="success"
  159. circle
  160. v-if="isChannelExists(scope.row.channelCodes, PayChannelEnum.MOCK.code)"
  161. @click="openChannelForm(scope.row, PayChannelEnum.MOCK.code)"
  162. >
  163. <Icon icon="ep:check" />
  164. </el-button>
  165. <el-button
  166. v-else
  167. type="danger"
  168. circle
  169. @click="openChannelForm(scope.row, PayChannelEnum.MOCK.code)"
  170. >
  171. <Icon icon="ep:close" />
  172. </el-button>
  173. </template>
  174. </el-table-column>
  175. </el-table-column>
  176. <el-table-column label="操作" align="center" min-width="110" fixed="right">
  177. <template #default="scope">
  178. <el-button
  179. link
  180. type="primary"
  181. @click="openForm('update', scope.row.id)"
  182. v-hasPermi="['pay:app:update']"
  183. >
  184. 编辑
  185. </el-button>
  186. <el-button
  187. link
  188. type="danger"
  189. @click="handleDelete(scope.row.id)"
  190. v-hasPermi="['pay:app:delete']"
  191. >
  192. 删除
  193. </el-button>
  194. </template>
  195. </el-table-column>
  196. </el-table>
  197. <!-- 分页 -->
  198. <Pagination
  199. :total="total"
  200. v-model:page="queryParams.pageNo"
  201. v-model:limit="queryParams.pageSize"
  202. @pagination="getList"
  203. />
  204. </ContentWrap>
  205. <!-- 表单弹窗:添加/修改 -->
  206. <AppForm ref="formRef" @success="getList" />
  207. <AlipayChannelForm ref="alipayFormRef" @success="getList" />
  208. <WeixinChannelForm ref="weixinFormRef" @success="getList" />
  209. <MockChannelForm ref="mockFormRef" @success="getList" />
  210. <WalletChannelForm ref="walletFormRef" @success="getList" />
  211. </template>
  212. <script lang="ts" setup>
  213. import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
  214. import * as AppApi from '@/api/pay/app'
  215. import AppForm from './components/AppForm.vue'
  216. import { CommonStatusEnum, PayChannelEnum } from '@/utils/constants'
  217. import AlipayChannelForm from './components/channel/AlipayChannelForm.vue'
  218. import WeixinChannelForm from './components/channel/WeixinChannelForm.vue'
  219. import MockChannelForm from './components/channel/MockChannelForm.vue'
  220. import WalletChannelForm from './components/channel/WalletChannelForm.vue'
  221. defineOptions({ name: 'PayApp' })
  222. const message = useMessage() // 消息弹窗
  223. const { t } = useI18n() // 国际化
  224. const loading = ref(true) // 列表的加载中
  225. const total = ref(0) // 列表的总页数
  226. const list = ref([]) // 列表的数据
  227. const queryParams = reactive({
  228. pageNo: 1,
  229. pageSize: 10,
  230. name: undefined,
  231. status: undefined,
  232. remark: undefined,
  233. payNotifyUrl: undefined,
  234. refundNotifyUrl: undefined,
  235. createTime: []
  236. })
  237. const queryFormRef = ref() // 搜索的表单
  238. const alipayChannels = [
  239. PayChannelEnum.ALIPAY_APP,
  240. PayChannelEnum.ALIPAY_PC,
  241. PayChannelEnum.ALIPAY_WAP,
  242. PayChannelEnum.ALIPAY_QR,
  243. PayChannelEnum.ALIPAY_BAR
  244. ]
  245. const wxChannels = [
  246. PayChannelEnum.WX_LITE,
  247. PayChannelEnum.WX_PUB,
  248. PayChannelEnum.WX_APP,
  249. PayChannelEnum.WX_NATIVE,
  250. PayChannelEnum.WX_WAP,
  251. PayChannelEnum.WX_BAR,
  252. ]
  253. /** 查询列表 */
  254. const getList = async () => {
  255. loading.value = true
  256. try {
  257. const data = await AppApi.getAppPage(queryParams)
  258. list.value = data.list
  259. total.value = data.total
  260. } finally {
  261. loading.value = false
  262. }
  263. }
  264. /** 搜索按钮操作 */
  265. const handleQuery = () => {
  266. queryParams.pageNo = 1
  267. getList()
  268. }
  269. /** 重置按钮操作 */
  270. const resetQuery = () => {
  271. queryFormRef.value.resetFields()
  272. handleQuery()
  273. }
  274. /** 应用状态修改 */
  275. const handleStatusChange = async (row: any) => {
  276. let text = row.status === CommonStatusEnum.ENABLE ? '启用' : '停用'
  277. try {
  278. await message.confirm('确认要"' + text + '""' + row.name + '"应用吗?')
  279. await AppApi.changeAppStatus({ id: row.id, status: row.status })
  280. message.success(text + '成功')
  281. } catch {
  282. row.status =
  283. row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE
  284. }
  285. }
  286. /** 添加/修改操作 */
  287. const formRef = ref()
  288. const openForm = (type: string, id?: number) => {
  289. formRef.value.open(type, id)
  290. }
  291. /** 删除按钮操作 */
  292. const handleDelete = async (id: number) => {
  293. try {
  294. // 删除的二次确认
  295. await message.delConfirm()
  296. // 发起删除
  297. await AppApi.deleteApp(id)
  298. message.success(t('common.delSuccess'))
  299. // 刷新列表
  300. await getList()
  301. } catch {}
  302. }
  303. /**
  304. * 根据渠道编码判断渠道列表中是否存在
  305. *
  306. * @param channels 渠道列表
  307. * @param channelCode 渠道编码
  308. */
  309. const isChannelExists = (channels, channelCode) => {
  310. if (!channels) {
  311. return false
  312. }
  313. return channels.indexOf(channelCode) !== -1
  314. }
  315. /**
  316. * 新增支付渠道信息
  317. */
  318. const alipayFormRef = ref()
  319. const weixinFormRef = ref()
  320. const mockFormRef = ref()
  321. const walletFormRef = ref()
  322. const channelParam = reactive({
  323. appId: null, // 应用 ID
  324. payCode: null // 渠道编码
  325. })
  326. const openChannelForm = async (row, payCode) => {
  327. channelParam.appId = row.id
  328. channelParam.payCode = payCode
  329. if (payCode.indexOf('alipay_') === 0) {
  330. alipayFormRef.value.open(row.id, payCode)
  331. return
  332. }
  333. if (payCode.indexOf('wx_') === 0) {
  334. weixinFormRef.value.open(row.id, payCode)
  335. return
  336. }
  337. if (payCode.indexOf('mock') === 0) {
  338. mockFormRef.value.open(row.id, payCode)
  339. }
  340. if (payCode.indexOf('wallet') === 0) {
  341. mockFormRef.value.open(row.id, payCode)
  342. }
  343. }
  344. /** 初始化 **/
  345. onMounted(async () => {
  346. await getList()
  347. })
  348. </script>