diff --git a/package.json b/package.json index a04c2520..2cf30fb6 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "nprogress": "^0.2.0", "pinia": "^2.1.6", "qrcode": "^1.5.3", + "qrcode.vue": "^3.4.0", "qs": "^6.11.2", "steady-xml": "^0.1.0", "url": "^0.11.1", diff --git a/src/api/mall/promotion/combination/combinationActivity.ts b/src/api/mall/promotion/combination/combinationActivity.ts index 1e211c86..f89264e4 100644 --- a/src/api/mall/promotion/combination/combinationActivity.ts +++ b/src/api/mall/promotion/combination/combinationActivity.ts @@ -10,8 +10,8 @@ export interface CombinationActivityVO { startTime?: Date endTime?: Date userSize?: number - totalNum?: number - successNum?: number + totalCount?: number + successCount?: number orderUserCount?: number virtualGroup?: number status?: number @@ -23,7 +23,7 @@ export interface CombinationActivityVO { export interface CombinationProductVO { spuId: number skuId: number - activePrice: number // 拼团价格 + combinationPrice: number // 拼团价格 } // 扩展 Sku 配置 diff --git a/src/api/mall/promotion/coupon.ts b/src/api/mall/promotion/coupon/coupon.ts similarity index 100% rename from src/api/mall/promotion/coupon.ts rename to src/api/mall/promotion/coupon/coupon.ts diff --git a/src/api/mall/promotion/couponTemplate.ts b/src/api/mall/promotion/coupon/couponTemplate.ts similarity index 100% rename from src/api/mall/promotion/couponTemplate.ts rename to src/api/mall/promotion/coupon/couponTemplate.ts diff --git a/src/api/mall/promotion/seckill/seckillConfig.ts b/src/api/mall/promotion/seckill/seckillConfig.ts index eee82115..23ad15ca 100644 --- a/src/api/mall/promotion/seckill/seckillConfig.ts +++ b/src/api/mall/promotion/seckill/seckillConfig.ts @@ -20,7 +20,7 @@ export const getSeckillConfig = async (id: number) => { } // 获得所有开启状态的秒杀时段精简列表 -export const getListAllSimple = async () => { +export const getSimpleSeckillConfigList = async () => { return await request.get({ url: '/promotion/seckill-config/list-all-simple' }) } diff --git a/src/api/pay/app/index.ts b/src/api/pay/app/index.ts index c19eb99b..4bb06b36 100644 --- a/src/api/pay/app/index.ts +++ b/src/api/pay/app/index.ts @@ -22,16 +22,6 @@ export interface AppPageReqVO extends PageParam { createTime?: Date[] } -export interface AppExportReqVO { - name?: string - status?: number - remark?: string - payNotifyUrl?: string - refundNotifyUrl?: string - merchantName?: string - createTime?: Date[] -} - export interface AppUpdateStatusReqVO { id: number status: number @@ -67,12 +57,9 @@ export const deleteApp = (id: number) => { return request.delete({ url: '/pay/app/delete?id=' + id }) } -// 导出支付应用 -export const exportApp = (params: AppExportReqVO) => { - return request.download({ url: '/pay/app/export-excel', params }) -} - -// 根据商ID称搜索应用列表 -export const getAppListByMerchantId = (merchantId: number) => { - return request.get({ url: '/pay/app/list-merchant-id', params: { merchantId: merchantId } }) +// 获得支付应用列表 +export const getAppList = () => { + return request.get({ + url: '/pay/app/list' + }) } diff --git a/src/api/pay/demo/index.ts b/src/api/pay/demo/index.ts new file mode 100644 index 00000000..3824a8b2 --- /dev/null +++ b/src/api/pay/demo/index.ts @@ -0,0 +1,36 @@ +import request from '@/config/axios' + +export interface DemoOrderVO { + spuId: number + createTime: Date +} + +// 创建示例订单 +export function createDemoOrder(data: DemoOrderVO) { + return request.post({ + url: '/pay/demo-order/create', + data: data + }) +} + +// 获得示例订单 +export function getDemoOrder(id: number) { + return request.get({ + url: '/pay/demo-order/get?id=' + id + }) +} + +// 获得示例订单分页 +export function getDemoOrderPage(query: PageParam) { + return request.get({ + url: '/pay/demo-order/page', + params: query + }) +} + +// 退款示例订单 +export function refundDemoOrder(id) { + return request.put({ + url: '/pay/demo-order/refund?id=' + id + }) +} diff --git a/src/api/pay/merchant/index.ts b/src/api/pay/merchant/index.ts deleted file mode 100644 index bb630c36..00000000 --- a/src/api/pay/merchant/index.ts +++ /dev/null @@ -1,78 +0,0 @@ -import request from '@/config/axios' - -export interface MerchantVO { - id: number - no: string - name: string - shortName: string - status: number - remark: string - createTime: Date -} - -export interface MerchantPageReqVO extends PageParam { - no?: string - name?: string - shortName?: string - status?: number - remark?: string - createTime?: Date[] -} - -export interface MerchantExportReqVO { - no?: string - name?: string - shortName?: string - status?: number - remark?: string - createTime?: Date[] -} - -// 查询列表支付商户 -export const getMerchantPage = (params: MerchantPageReqVO) => { - return request.get({ url: '/pay/merchant/page', params }) -} - -// 查询详情支付商户 -export const getMerchant = (id: number) => { - return request.get({ url: '/pay/merchant/get?id=' + id }) -} - -// 根据商户名称搜索商户列表 -export const getMerchantListByName = (name?: string) => { - return request.get({ - url: '/pay/merchant/list-by-name', - params: { - name: name - } - }) -} - -// 新增支付商户 -export const createMerchant = (data: MerchantVO) => { - return request.post({ url: '/pay/merchant/create', data }) -} - -// 修改支付商户 -export const updateMerchant = (data: MerchantVO) => { - return request.put({ url: '/pay/merchant/update', data }) -} - -// 删除支付商户 -export const deleteMerchant = (id: number) => { - return request.delete({ url: '/pay/merchant/delete?id=' + id }) -} - -// 导出支付商户 -export const exportMerchant = (params: MerchantExportReqVO) => { - return request.download({ url: '/pay/merchant/export-excel', params }) -} - -// 支付商户状态修改 -export const updateMerchantStatus = (id: number, status: number) => { - const data = { - id, - status - } - return request.put({ url: '/pay/merchant/update-status', data: data }) -} diff --git a/src/api/pay/notify/index.ts b/src/api/pay/notify/index.ts new file mode 100644 index 00000000..dc8bd887 --- /dev/null +++ b/src/api/pay/notify/index.ts @@ -0,0 +1,16 @@ +import request from '@/config/axios' + +// 获得支付通知明细 +export const getNotifyTaskDetail = (id) => { + return request.get({ + url: '/pay/notify/get-detail?id=' + id + }) +} + +// 获得支付通知分页 +export const getNotifyTaskPage = (query) => { + return request.get({ + url: '/pay/notify/page', + params: query + }) +} diff --git a/src/api/pay/order/index.ts b/src/api/pay/order/index.ts index 6621381a..71960a8a 100644 --- a/src/api/pay/order/index.ts +++ b/src/api/pay/order/index.ts @@ -93,19 +93,9 @@ export const getOrderDetail = async (id: number) => { return await request.get({ url: '/pay/order/get-detail?id=' + id }) } -// 新增支付订单 -export const createOrder = async (data: OrderVO) => { - return await request.post({ url: '/pay/order/create', data }) -} - -// 修改支付订单 -export const updateOrder = async (data: OrderVO) => { - return await request.put({ url: '/pay/order/update', data }) -} - -// 删除支付订单 -export const deleteOrder = async (id: number) => { - return await request.delete({ url: '/pay/order/delete?id=' + id }) +// 提交支付订单 +export const submitOrder = async (data: any) => { + return await request.post({ url: '/pay/order/submit', data }) } // 导出支付订单 diff --git a/src/api/system/permission/index.ts b/src/api/system/permission/index.ts index baf2805b..b3c7696b 100644 --- a/src/api/system/permission/index.ts +++ b/src/api/system/permission/index.ts @@ -18,7 +18,7 @@ export interface PermissionAssignRoleDataScopeReqVO { // 查询角色拥有的菜单权限 export const getRoleMenuList = async (roleId: number) => { - return await request.get({ url: '/system/permission/list-role-resources?roleId=' + roleId }) + return await request.get({ url: '/system/permission/list-role-menus?roleId=' + roleId }) } // 赋予角色菜单权限 diff --git a/src/assets/svgs/pay/icon/alipay_app.svg b/src/assets/svgs/pay/icon/alipay_app.svg new file mode 100644 index 00000000..ebf11883 --- /dev/null +++ b/src/assets/svgs/pay/icon/alipay_app.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/alipay_bar.svg b/src/assets/svgs/pay/icon/alipay_bar.svg new file mode 100644 index 00000000..eb1e1e84 --- /dev/null +++ b/src/assets/svgs/pay/icon/alipay_bar.svg @@ -0,0 +1,2 @@ + diff --git a/src/assets/svgs/pay/icon/alipay_pc.svg b/src/assets/svgs/pay/icon/alipay_pc.svg new file mode 100644 index 00000000..2a752770 --- /dev/null +++ b/src/assets/svgs/pay/icon/alipay_pc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/alipay_qr.svg b/src/assets/svgs/pay/icon/alipay_qr.svg new file mode 100644 index 00000000..48337508 --- /dev/null +++ b/src/assets/svgs/pay/icon/alipay_qr.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/alipay_wap.svg b/src/assets/svgs/pay/icon/alipay_wap.svg new file mode 100644 index 00000000..87075dbb --- /dev/null +++ b/src/assets/svgs/pay/icon/alipay_wap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/mock.svg b/src/assets/svgs/pay/icon/mock.svg new file mode 100644 index 00000000..27b09ead --- /dev/null +++ b/src/assets/svgs/pay/icon/mock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/wx_app.svg b/src/assets/svgs/pay/icon/wx_app.svg new file mode 100644 index 00000000..ad40b2a2 --- /dev/null +++ b/src/assets/svgs/pay/icon/wx_app.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/wx_bar.svg b/src/assets/svgs/pay/icon/wx_bar.svg new file mode 100644 index 00000000..11292e6e --- /dev/null +++ b/src/assets/svgs/pay/icon/wx_bar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/wx_lite.svg b/src/assets/svgs/pay/icon/wx_lite.svg new file mode 100644 index 00000000..0c925cf3 --- /dev/null +++ b/src/assets/svgs/pay/icon/wx_lite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/wx_native.svg b/src/assets/svgs/pay/icon/wx_native.svg new file mode 100644 index 00000000..bf3ba2b6 --- /dev/null +++ b/src/assets/svgs/pay/icon/wx_native.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgs/pay/icon/wx_pub.svg b/src/assets/svgs/pay/icon/wx_pub.svg new file mode 100644 index 00000000..3a6d15b7 --- /dev/null +++ b/src/assets/svgs/pay/icon/wx_pub.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/src/config/axios/index.ts b/src/config/axios/index.ts index e6c6af8d..79e558da 100644 --- a/src/config/axios/index.ts +++ b/src/config/axios/index.ts @@ -5,12 +5,13 @@ import { config } from './config' const { default_headers } = config const request = (option: any) => { - const { url, method, params, data, headersType, responseType } = option + const { url, method, params, data, headersType, responseType, ...config } = option return service({ url: url, method, params, data, + ...config, responseType: responseType, headers: { 'Content-Type': headersType || default_headers diff --git a/src/config/axios/service.ts b/src/config/axios/service.ts index 1a4741b6..3a4635f0 100644 --- a/src/config/axios/service.ts +++ b/src/config/axios/service.ts @@ -31,7 +31,7 @@ let requestList: any[] = [] // 是否正在刷新中 let isRefreshToken = false // 请求白名单,无须token的接口 -const whiteList: string[] = ['/login', '/refresh-token'] +const whiteList: string[] = ['/login', '/refresh-token', '/system/tenant/get-id-by-name'] // 创建axios实例 const service: AxiosInstance = axios.create({ @@ -47,8 +47,7 @@ service.interceptors.request.use( let isToken = (config!.headers || {}).isToken === false whiteList.some((v) => { if (config.url) { - config.url.indexOf(v) > -1 - return (isToken = false) + return (isToken = config.url.indexOf(v) > -1) } }) if (getAccessToken() && !isToken) { diff --git a/src/hooks/web/useCrudSchemas.ts b/src/hooks/web/useCrudSchemas.ts index 984e57c5..4cfe1eaf 100644 --- a/src/hooks/web/useCrudSchemas.ts +++ b/src/hooks/web/useCrudSchemas.ts @@ -9,6 +9,7 @@ import { TableColumn } from '@/types/table' import { DescriptionsSchema } from '@/types/descriptions' import { ComponentOptions, ComponentProps } from '@/types/components' import { DictTag } from '@/components/DictTag' +import { cloneDeep } from 'lodash-es' export type CrudSchema = Omit & { isSearch?: boolean // 是否在查询显示 @@ -306,3 +307,12 @@ const filterOptions = (options: Recordable, labelField?: string) => { return v }) } + +// 将 tableColumns 指定 fields 放到最前面 +export const sortTableColumns = (tableColumns: TableColumn[], field: string) => { + const fieldIndex = tableColumns.findIndex((item) => item.field === field) + const fieldColumn = cloneDeep(tableColumns[fieldIndex]) + tableColumns.splice(fieldIndex, 1) + // 添加到开头 + tableColumns.unshift(fieldColumn) +} diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 2a277a10..81f74d55 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -410,6 +410,24 @@ const remainingRouter: AppRouteRecordRaw[] = [ } } ] + }, + { + path: '/pay', + component: Layout, + name: 'pay', + meta: { hidden: true }, + children: [ + { + path: 'cashier', + name: 'PayCashier', + meta: { + title: '收银台', + noCache: true, + hidden: true + }, + component: () => import('@/views/pay/cashier/index.vue') + } + ] } ] diff --git a/src/utils/constants.ts b/src/utils/constants.ts index edde87d5..cd346a5c 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -99,6 +99,10 @@ export const PayChannelEnum = { code: 'wx_app', name: '微信 APP 支付' }, + WX_BAR: { + code: 'wx_bar', + name: '微信条码支付' + }, ALIPAY_PC: { code: 'alipay_pc', name: '支付宝 PC 网站支付' @@ -125,6 +129,36 @@ export const PayChannelEnum = { } } +/** + * 支付的展示模式每局 + */ +export const PayDisplayModeEnum = { + URL: { + mode: 'url' + }, + IFRAME: { + mode: 'iframe' + }, + FORM: { + mode: 'form' + }, + QR_CODE: { + mode: 'qr_code' + }, + APP: { + mode: 'app' + } +} + +/** + * 支付类型枚举 + */ +export const PayType = { + WECHAT: 'WECHAT', + ALIPAY: 'ALIPAY', + MOCK: 'MOCK' +} + /** * 支付订单状态枚举 */ @@ -143,80 +177,6 @@ export const PayOrderStatusEnum = { } } -/** - * 支付订单回调状态枚举 - */ -export const PayOrderNotifyStatusEnum = { - NO: { - status: 0, - name: '未通知' - }, - SUCCESS: { - status: 10, - name: '通知成功' - }, - FAILURE: { - status: 20, - name: '通知失败' - } -} - -/** - * 支付订单退款状态枚举 - */ -export const PayOrderRefundStatusEnum = { - NO: { - status: 0, - name: '未退款' - }, - SOME: { - status: 10, - name: '部分退款' - }, - ALL: { - status: 20, - name: '全部退款' - } -} - -/** - * 支付退款订单状态枚举 - */ -export const PayRefundStatusEnum = { - CREATE: { - status: 0, - name: '退款订单生成' - }, - SUCCESS: { - status: 1, - name: '退款成功' - }, - FAILURE: { - status: 2, - name: '退款失败' - }, - PROCESSING_NOTIFY: { - status: 3, - name: '退款中,渠道通知结果' - }, - PROCESSING_QUERY: { - status: 4, - name: '退款中,系统查询结果' - }, - UNKNOWN_RETRY: { - status: 5, - name: '状态未知,请重试' - }, - UNKNOWN_QUERY: { - status: 6, - name: '状态未知,系统查询结果' - }, - CLOSE: { - status: 99, - name: '退款关闭' - } -} - /** * 商品 SPU 状态 */ diff --git a/src/utils/dict.ts b/src/utils/dict.ts index 67a92ba6..d11d1d33 100644 --- a/src/utils/dict.ts +++ b/src/utils/dict.ts @@ -130,17 +130,16 @@ export enum DICT_TYPE { BPM_OA_LEAVE_TYPE = 'bpm_oa_leave_type', // ========== PAY 模块 ========== - PAY_CHANNEL_WECHAT_VERSION = 'pay_channel_wechat_version', // 微信渠道版本 - PAY_CHANNEL_ALIPAY_SIGN_TYPE = 'pay_channel_alipay_sign_type', // 支付渠道支付宝算法类型 - PAY_CHANNEL_ALIPAY_MODE = 'pay_channel_alipay_mode', // 支付宝公钥类型 - PAY_CHANNEL_ALIPAY_SERVER_TYPE = 'pay_channel_alipay_server_type', // 支付宝网关地址 + PAY_CHANNEL_CODE = 'pay_channel_code', // 支付渠道编码类型 PAY_CHANNEL_CODE_TYPE = 'pay_channel_code_type', // 支付渠道编码类型 - PAY_ORDER_NOTIFY_STATUS = 'pay_order_notify_status', // 商户支付订单回调状态 PAY_ORDER_STATUS = 'pay_order_status', // 商户支付订单状态 PAY_ORDER_REFUND_STATUS = 'pay_order_refund_status', // 商户支付订单退款状态 PAY_REFUND_ORDER_STATUS = 'pay_refund_order_status', // 退款订单状态 PAY_REFUND_ORDER_TYPE = 'pay_refund_order_type', // 退款订单类别 + PAY_NOTIFY_STATUS = 'pay_notify_status', // 商户支付回调状态 + PAY_NOTIFY_TYPE = 'pay_notify_type', // 商户支付回调状态 + // ========== MP 模块 ========== MP_AUTO_REPLY_REQUEST_MATCH = 'mp_auto_reply_request_match', // 自动回复请求匹配类型 MP_MESSAGE_TYPE = 'mp_message_type', // 消息类型 diff --git a/src/views/Login/components/LoginForm.vue b/src/views/Login/components/LoginForm.vue index 82dbe3fc..190c5aa1 100644 --- a/src/views/Login/components/LoginForm.vue +++ b/src/views/Login/components/LoginForm.vue @@ -148,6 +148,8 @@ import { ElLoading } from 'element-plus' import LoginFormTitle from './LoginFormTitle.vue' import type { RouteLocationNormalizedLoaded } from 'vue-router' +import { CACHE_KEY, useCache } from '@/hooks/web/useCache' +const { wsCache } = useCache() import { useIcon } from '@/hooks/web/useIcon' import * as authUtil from '@/utils/auth' @@ -244,6 +246,7 @@ const handleLogin = async (params) => { if (!res) { return } + wsCache.delete(CACHE_KEY.USER) // 清除上次登录用户信息 ElLoading.service({ lock: true, text: '正在加载系统中...', diff --git a/src/views/bpm/group/index.vue b/src/views/bpm/group/index.vue index ee8c2e65..957ffc89 100644 --- a/src/views/bpm/group/index.vue +++ b/src/views/bpm/group/index.vue @@ -30,7 +30,7 @@ diff --git a/src/views/infra/fileConfig/FileConfigForm.vue b/src/views/infra/fileConfig/FileConfigForm.vue index 6332f702..06b80e7d 100644 --- a/src/views/infra/fileConfig/FileConfigForm.vue +++ b/src/views/infra/fileConfig/FileConfigForm.vue @@ -67,7 +67,7 @@ 主动模式 - 主动模式 + 被动模式 diff --git a/src/views/mall/promotion/bargain/BargainActivityForm.vue b/src/views/mall/promotion/bargain/activity/BargainActivityForm.vue similarity index 99% rename from src/views/mall/promotion/bargain/BargainActivityForm.vue rename to src/views/mall/promotion/bargain/activity/BargainActivityForm.vue index 91bb52d0..5384d6a1 100644 --- a/src/views/mall/promotion/bargain/BargainActivityForm.vue +++ b/src/views/mall/promotion/bargain/activity/BargainActivityForm.vue @@ -129,7 +129,6 @@ const getSpuDetails = async ( if (typeof products !== 'undefined') { const product = products.find((item) => item.skuId === sku.id) if (product) { - // 分转元 product.bargainFirstPrice = formatToFraction(product.bargainFirstPrice) product.bargainPrice = formatToFraction(product.bargainPrice) } diff --git a/src/views/mall/promotion/bargain/bargainActivity.data.ts b/src/views/mall/promotion/bargain/activity/bargainActivity.data.ts similarity index 100% rename from src/views/mall/promotion/bargain/bargainActivity.data.ts rename to src/views/mall/promotion/bargain/activity/bargainActivity.data.ts diff --git a/src/views/mall/promotion/bargain/index.vue b/src/views/mall/promotion/bargain/activity/index.vue similarity index 78% rename from src/views/mall/promotion/bargain/index.vue rename to src/views/mall/promotion/bargain/activity/index.vue index 42222f45..abcbcc6b 100644 --- a/src/views/mall/promotion/bargain/index.vue +++ b/src/views/mall/promotion/bargain/activity/index.vue @@ -65,8 +65,8 @@ import { allSchemas } from './bargainActivity.data' import * as BargainActivityApi from '@/api/mall/promotion/bargain/bargainActivity' import BargainActivityForm from './BargainActivityForm.vue' -import { cloneDeep } from 'lodash-es' import { createImageViewer } from '@/components/ImageViewer' +import { sortTableColumns } from '@/hooks/web/useCrudSchemas' defineOptions({ name: 'PromotionBargainActivity' }) @@ -98,20 +98,10 @@ const handleDelete = (id: number) => { tableMethods.delList(id, false) } -// TODO @puhui999:要不还是使用原生的 element plus 做。感觉 crud schema 复杂界面,做起来麻烦 /** 初始化 **/ onMounted(() => { - /** - TODO - 后面准备封装成一个函数来操作 tableColumns 重新排列:比如说需求是表单上商品选择是在后面的而列表展示的时候需要调到位置。 - 封装效果支持批量操作,给出 field 和需要插入的位置,例:[{field:'spuId',index: 1}] 效果为把 field 为 spuId 的 column 移动到第一个位置 - */ - // 处理一下表格列让商品往前 - const index = allSchemas.tableColumns.findIndex((item) => item.field === 'spuId') - const column = cloneDeep(allSchemas.tableColumns[index]) - allSchemas.tableColumns.splice(index, 1) - // 添加到开头 - allSchemas.tableColumns.unshift(column) + // 获得活动列表 + sortTableColumns(allSchemas.tableColumns, 'spuId') getList() }) diff --git a/src/views/mall/promotion/combination/CombinationActivityForm.vue b/src/views/mall/promotion/combination/activity/CombinationActivityForm.vue similarity index 91% rename from src/views/mall/promotion/combination/CombinationActivityForm.vue rename to src/views/mall/promotion/combination/activity/CombinationActivityForm.vue index 265eb98e..3c802ede 100644 --- a/src/views/mall/promotion/combination/CombinationActivityForm.vue +++ b/src/views/mall/promotion/combination/activity/CombinationActivityForm.vue @@ -19,7 +19,7 @@