feat:商城支付
This commit is contained in:
1 parent
705cd7d47c
commit
8730295312
26 files changed
+1333
-233
No files matched your search
@@ -2,7 +2,7 @@
|
||||
"version" : "1.0",
|
||||
"configurations" : [
|
||||
{
|
||||
"customPlaygroundType" : "local",
|
||||
"customPlaygroundType" : "device",
|
||||
"localRepoPath" : "C:/workcode/vue/biz-mobile-cloud-zax",
|
||||
"openVueDevtools" : true,
|
||||
"packageName" : "z",
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
# Uni-App AI Editor Role
|
||||
|
||||
你是一名专注于 `uni-app` 多端应用开发的高级工程师与 AI 编程助手,负责在当前项目中进行需求理解、页面开发、问题修复、结构优化与文档维护。
|
||||
|
||||
## 1. 角色定位
|
||||
|
||||
- 精通 `uni-app`、`Vue 3`、`TypeScript`、`Vite`、`Pinia`、`UnoCSS`、`Sass`
|
||||
- 熟悉 `uni-app` 多端差异,理解 `H5`、`App`、各类小程序端的兼容性约束
|
||||
- 站在“可维护、可扩展、可交付”的角度完成代码修改
|
||||
- 默认使用中文输出,并以工程协作风格给出清晰结论
|
||||
|
||||
## 2. 工作目标
|
||||
|
||||
- 优先完成用户明确提出的需求
|
||||
- 保持现有业务行为稳定,避免无关改动
|
||||
- 编写结构清晰、命名明确、便于维护的代码
|
||||
- 优先使用最简单可靠的方案,不做过度设计
|
||||
- 所有改动应尽量符合当前项目既有结构与编码习惯
|
||||
|
||||
## 3. 项目技术栈
|
||||
|
||||
当前项目是一个基于 `uni-app` 的多端应用,核心技术栈如下:
|
||||
|
||||
- 框架:`uni-app` + `Vue 3`
|
||||
- 构建:`Vite 5` + `@dcloudio/vite-plugin-uni`
|
||||
- 语言:`TypeScript`
|
||||
- 状态管理:`Pinia`
|
||||
- 样式:`UnoCSS` + `Sass`
|
||||
- 请求层:`luch-request`
|
||||
- 国际化:`vue-i18n`
|
||||
- 图表:`@qiun/uni-ucharts`
|
||||
- UI 组件:`tm-ui`、`z-paging`
|
||||
|
||||
当前项目的主要目标端为:
|
||||
|
||||
- `App`
|
||||
- `H5`
|
||||
|
||||
因此在分析、设计、编码、修复和优化时,应默认优先保障这两个端的兼容性、交互一致性和运行稳定性。
|
||||
|
||||
## 4. 项目结构认知
|
||||
|
||||
请在理解和修改代码时遵循以下目录职责:
|
||||
|
||||
- `src/pages`:业务页面
|
||||
- `src/components`:通用业务组件
|
||||
- `src/sheep/api`:接口封装层
|
||||
- `src/sheep/components`:项目级公共组件
|
||||
- `src/sheep/hooks`:组合式逻辑复用
|
||||
- `src/sheep/stores`:Pinia 状态管理
|
||||
- `src/sheep/utils`:工具函数与基础能力
|
||||
- `src/sheep/constant`:常量定义
|
||||
- `src/pages.json`:页面路由、页面样式、分包与 easycom 配置
|
||||
- `src/manifest.json`:应用平台能力与打包配置
|
||||
- `vite.config.ts`:Vite 与 uni 构建配置
|
||||
- `unocss.config.ts`:原子化样式配置
|
||||
|
||||
## 5. 项目约定
|
||||
|
||||
### 5.1 别名约定
|
||||
|
||||
- `@` 指向 `src`
|
||||
- `@@` 指向 `src/sheep`
|
||||
|
||||
### 5.2 组件约定
|
||||
|
||||
项目启用了 `easycom`,常见规则如下:
|
||||
|
||||
- `base-*` 对应 `src/sheep/components/base`
|
||||
- `crud-*` 对应 `src/sheep/components/crud`
|
||||
- `tm-*` 对应 `src/uni_modules/tm-ui/components`
|
||||
- `z-paging*` 使用 `z-paging` 组件约定
|
||||
|
||||
### 5.3 多端约定
|
||||
|
||||
- 涉及平台差异时,优先使用 `#ifdef`、`#ifndef` 等 uni 条件编译
|
||||
- 不要把仅某一端可用的 API 直接写成全端通用逻辑
|
||||
- 涉及原生能力时,必须明确适用平台和降级策略
|
||||
- 默认优先适配 `App` 与 `H5`,其他端仅在用户明确要求时再做专项兼容
|
||||
|
||||
## 6. 编码原则
|
||||
|
||||
- 优先复用现有模块、组件、hooks、stores,不重复造轮子
|
||||
- 优先保持接口调用风格与项目现有 `api` 层一致
|
||||
- 优先保持状态管理风格与现有 `Pinia store` 一致
|
||||
- 保持函数短小、职责单一
|
||||
- 命名应语义化,避免随意缩写
|
||||
- 新增逻辑要考虑异常处理、空值处理和边界条件
|
||||
- 对用户输入、上传、跳转、支付、权限等敏感流程要有安全意识
|
||||
- 仅在必要时添加注释,注释应解释“为什么”,而不是“这行代码做了什么”
|
||||
|
||||
## 7. 页面开发规范
|
||||
|
||||
- 新页面优先放在 `src/pages` 的对应业务域目录下
|
||||
- 页面标题、导航栏配置、是否禁用滚动等信息,优先在 `pages.json` 中维护
|
||||
- 页面应按“数据、状态、行为、视图”分层组织
|
||||
- 复杂页面应适当拆分为局部组件或组合式函数
|
||||
- 表单页要注意校验、提交态、重复提交保护和错误提示
|
||||
- 列表页要注意分页、空态、加载态、刷新态
|
||||
|
||||
## 8. 样式规范
|
||||
|
||||
- 优先使用 `UnoCSS`
|
||||
- 复杂样式或组件局部样式可使用 `scss`
|
||||
- 保持样式语义清晰,避免无意义的层级嵌套
|
||||
- 兼顾移动端适配,优先考虑 `rpx` 与 uni 场景下的表现
|
||||
- 优先保证 `App` 与 `H5` 的视觉一致性
|
||||
- 避免仅在单一端可用、但在 `App` 或 `H5` 表现异常的 CSS 特性
|
||||
|
||||
## 9. 请求与数据流规范
|
||||
|
||||
- 接口定义优先放在 `src/sheep/api`
|
||||
- 组件或页面中不要直接散落大量请求实现细节
|
||||
- 共享状态放入 `Pinia`
|
||||
- 页面私有状态优先使用页面本地状态
|
||||
- 请求失败必须给出合理反馈,避免静默失败
|
||||
|
||||
## 10. 修改代码前的思考顺序
|
||||
|
||||
每次开始工作前,按以下顺序思考:
|
||||
|
||||
1. 用户要解决的真实问题是什么
|
||||
2. 现有项目中是否已有相似实现可以复用
|
||||
3. 这次改动应该落在哪一层:页面、组件、hooks、store、api、utils、配置
|
||||
4. 是否涉及多端差异、权限、登录态、路由、支付、上传等敏感流程
|
||||
5. 是否需要同步修改 `pages.json`、`manifest.json`、`vite.config.ts` 或类型声明
|
||||
|
||||
## 11. 操作边界
|
||||
|
||||
- 非用户明确要求时,不主动大规模重构
|
||||
- 非必要时,不修改已有稳定业务逻辑
|
||||
- 非必要时,不修改第三方库代码
|
||||
- 非必要时,不引入新的重型依赖
|
||||
- 不要为了“代码更优雅”而改变现有页面交互
|
||||
- 未经用户要求,不默认运行某个平台的打包命令
|
||||
- 若仅需提供方案或文档,优先输出文档而不是直接大改代码
|
||||
|
||||
## 12. 修改 `uni-app` 项目时的特别注意事项
|
||||
|
||||
- 关注 `pages.json` 中的页面路径、分包配置与 `tabBar` 配置
|
||||
- 注意 `uni_modules` 组件的兼容性与版本行为
|
||||
- 涉及 `tm-ui`、`z-paging` 等组件时,优先沿用现有项目写法
|
||||
- 注意 `App.vue`、全局样式、全局 store 对页面行为的影响
|
||||
- 涉及路由、登录态、商户、支付、地址、订单等核心链路时,先理解现有数据流再修改
|
||||
- 涉及 `vite.config.ts` 时,优先使用对 `uni-app` 友好的保守配置
|
||||
- 任何页面、组件或样式调整,都要优先检查 `App` 与 `H5` 是否会出现布局、滚动、事件、导航或原生能力差异
|
||||
|
||||
## 13. 输出要求
|
||||
|
||||
在向用户汇报时:
|
||||
|
||||
- 使用中文
|
||||
- 先给结果,再说明原因
|
||||
- 说明改了哪些文件
|
||||
- 如果存在风险、前提条件或待确认项,要明确指出
|
||||
- 如果没有真正修改代码,不要假装已经完成实现
|
||||
|
||||
## 14. 默认执行策略
|
||||
|
||||
当用户提出需求时,默认采用以下策略:
|
||||
|
||||
1. 先理解问题并定位应修改的层级
|
||||
2. 优先读取相关页面、组件、store、api、配置文件
|
||||
3. 在最小改动范围内完成需求
|
||||
4. 保持与当前项目风格一致
|
||||
5. 交付后说明改动点、影响范围和后续建议
|
||||
|
||||
## 15. 适用场景
|
||||
|
||||
该角色适用于以下任务:
|
||||
|
||||
- `uni-app` 页面开发
|
||||
- `uni-app` 组件封装
|
||||
- `Pinia store` 设计与修复
|
||||
- 接口调用与数据流整理
|
||||
- `pages.json`、`manifest.json`、`vite.config.ts` 配置调整
|
||||
- 样式优化与移动端适配
|
||||
- 多端兼容问题排查
|
||||
- 构建报错、运行报错、路由问题、权限问题修复
|
||||
|
||||
## 16. 一句话工作准则
|
||||
|
||||
在这个项目中,始终以 `uni-app` 多端兼容、最小改动、结构清晰、业务稳定 为最高优先级完成任务。
|
||||
+22
-6
@@ -3,7 +3,6 @@ import { adApi, userApi } from "@@/api"
|
||||
import { storageConstant } from "@@/constant"
|
||||
import pinia from "@@/stores/index"
|
||||
import { useRiderPushBannerStore } from "@@/stores/rider-push-banner"
|
||||
import { useTabbarStore } from "@@/stores/tabbar"
|
||||
import { globalWebSocket } from "@/sheep/utils/global-websocket"
|
||||
import { handleCanteenDeliveryWebSocketFrame } from "@/sheep/utils/canteen-delivery-ws-push"
|
||||
|
||||
@@ -82,12 +81,19 @@ export default {
|
||||
return userData
|
||||
},
|
||||
async _initTabbar() {
|
||||
const tabbarStore = useTabbarStore(pinia)
|
||||
tabbarStore.init()
|
||||
const tabbarStore = await this._getTabbarStore()
|
||||
tabbarStore?.init()
|
||||
},
|
||||
_syncTabbar() {
|
||||
const tabbarStore = useTabbarStore(pinia)
|
||||
tabbarStore.syncByCurrentRoute()
|
||||
async _syncTabbar() {
|
||||
const tabbarStore = await this._getTabbarStore()
|
||||
tabbarStore?.syncByCurrentRoute()
|
||||
},
|
||||
async _getTabbarStore() {
|
||||
// #ifdef APP-NVUE
|
||||
return null
|
||||
// #endif
|
||||
const { useTabbarStore } = await import("@@/stores/tabbar")
|
||||
return useTabbarStore(pinia)
|
||||
},
|
||||
async reportSplashAd() {
|
||||
try {
|
||||
@@ -136,6 +142,16 @@ $theme-gray: #999;
|
||||
padding: 8rpx 15rpx;
|
||||
}
|
||||
|
||||
.primary_btn {
|
||||
border: 1px solid white;
|
||||
background: $theme-blue;
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
border-radius: 10rpx;
|
||||
padding: 8rpx 15rpx;
|
||||
}
|
||||
|
||||
.prefix_title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
"name" : "资安信",
|
||||
"appid" : "__UNI__1BFE88F",
|
||||
"description" : "资安信后勤管理系统",
|
||||
"versionName" : "1.5.02",
|
||||
"versionCode" : 1502,
|
||||
"versionName" : "1.4.02",
|
||||
"versionCode" : 1402,
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { reactive, computed, ref } from "vue"
|
||||
|
||||
import { adApi } from "@@/api/index"
|
||||
import { hooks, router } from "@@/index"
|
||||
import { hooks } from "@@/index"
|
||||
|
||||
const data = {
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick } from "vue"
|
||||
import { onShow, onHide, onBackPress } from "@dcloudio/uni-app"
|
||||
|
||||
import { router } from "@@/index"
|
||||
|
||||
|
||||
const adPageRef = ref()
|
||||
|
||||
onShow(() => {
|
||||
@@ -17,7 +15,7 @@
|
||||
})
|
||||
|
||||
onBackPress(() => {
|
||||
router.jump("/pages/tabbar/my")
|
||||
uni.switchTab({ url: "/pages/tabbar/my" })
|
||||
return true
|
||||
})
|
||||
|
||||
@@ -32,4 +30,4 @@
|
||||
|
||||
<template>
|
||||
<ad-content-page class="size-full" ref="adPageRef" adpid="1696053352" @load="onadload" @error="onaderror" />
|
||||
</template>
|
||||
</template>
|
||||
@@ -2,8 +2,6 @@
|
||||
import { ref, nextTick } from "vue"
|
||||
import { onShow, onHide, onBackPress } from "@dcloudio/uni-app"
|
||||
|
||||
import { router } from "@@/index"
|
||||
|
||||
const adPageRef = ref()
|
||||
|
||||
onShow(() => {
|
||||
@@ -17,7 +15,7 @@
|
||||
})
|
||||
|
||||
onBackPress(() => {
|
||||
router.jump("/pages/tabbar/my")
|
||||
uni.switchTab({ url: "/pages/tabbar/my" })
|
||||
return true
|
||||
})
|
||||
|
||||
@@ -34,4 +32,4 @@
|
||||
<view class="full">
|
||||
<ad-content-page class="size-full" ref="adPageRef" adpid="1696053352" @load="onadload" @error="onaderror" />
|
||||
</view>
|
||||
</template>
|
||||
</template>
|
||||
+171
-38
@@ -1,49 +1,182 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive } from "vue"
|
||||
import { onLoad } from "@dcloudio/uni-app"
|
||||
|
||||
import { hooks, router } from "@@/index"
|
||||
import { orderApi } from "@@/api"
|
||||
import AppLottiePlayer from "@@/components/common/app-lottie-player.vue"
|
||||
import InformationStreamAd from "@@/components/ad/information-stream-ad.vue"
|
||||
|
||||
import loadingAnimation from "@/static/lottie-json/loading.json"
|
||||
import successAnimation from "@/static/lottie-json/success.json"
|
||||
import errorAnimation from "@/static/lottie-json/fail.json"
|
||||
|
||||
type ResultPhase = "loading" | "success" | "error"
|
||||
|
||||
const POLL_INTERVAL_MS = 1000
|
||||
const POLL_TIMEOUT_MS = 10000
|
||||
let orderPollToken = 0
|
||||
|
||||
// backBtnType
|
||||
// 'back' 回退订单列表
|
||||
// 'detail' 查看订单详情
|
||||
const state = reactive<any>({
|
||||
phase: "loading" as ResultPhase,
|
||||
orderId: "",
|
||||
backBtnType: 'back',
|
||||
orderDetail: {},
|
||||
failMessage: "",
|
||||
})
|
||||
|
||||
const titleText = computed(() => {
|
||||
if (state.phase === "loading") return "充值结果确认中"
|
||||
return state.phase === "success" ? "充值成功" : "充值失败"
|
||||
})
|
||||
|
||||
const descText = computed(() => {
|
||||
if (state.phase === "loading") return "正在查询订单状态,请稍候..."
|
||||
if (state.phase === "success") return "充值金额已到账,可前往钱包查看最新余额"
|
||||
return state.failMessage || "未查询到本次充值结果,请稍后在充值记录中确认"
|
||||
})
|
||||
|
||||
const currentAnimation = computed(() => {
|
||||
if (state.phase === "loading") return loadingAnimation
|
||||
return state.phase === "success" ? successAnimation : errorAnimation
|
||||
})
|
||||
|
||||
const currentLoop = computed(() => state.phase === "loading")
|
||||
|
||||
const currentAnimationSize = computed(() => {
|
||||
if (state.phase === "loading") {
|
||||
return { width: "140rpx", height: "140rpx" }
|
||||
}
|
||||
if (state.phase === "success") {
|
||||
return { width: "280rpx", height: "280rpx" }
|
||||
}
|
||||
return { width: "280rpx", height: "280rpx" }
|
||||
})
|
||||
|
||||
const payOrderAmount = computed(() => Number(state.orderDetail?.payPrice || 0))
|
||||
|
||||
const mchNameText = computed(() => state.orderDetail?.merchantName || "--")
|
||||
|
||||
const payTypeText = computed(() => {
|
||||
const text = hooks.useEnum('hardwarePayTypeEnum', state.orderDetail?.payType)
|
||||
return text ? `${text}支付` : "--"
|
||||
})
|
||||
|
||||
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
|
||||
|
||||
const isPaySuccess = (orderStatus?: string | number) => ["5", "200"].includes(String(orderStatus ?? ""))
|
||||
|
||||
// 查询订单详情
|
||||
const getOrder = async (polling = false) => {
|
||||
const currentToken = ++orderPollToken
|
||||
try {
|
||||
state.phase = "loading"
|
||||
state.failMessage = ""
|
||||
const startTime = Date.now()
|
||||
while (true) {
|
||||
const res: any = await orderApi.detail({ id: state.orderId })
|
||||
if (currentToken !== orderPollToken) return
|
||||
const orderDetail = res?.data
|
||||
state.orderDetail = orderDetail || {}
|
||||
if (!orderDetail) {
|
||||
state.failMessage = "未查询到本次订单"
|
||||
state.phase = "error"
|
||||
return
|
||||
}
|
||||
if (isPaySuccess(orderDetail.orderStatus)) {
|
||||
state.phase = "success"
|
||||
return
|
||||
}
|
||||
if (!polling || Date.now() - startTime >= POLL_TIMEOUT_MS) {
|
||||
state.phase = "error"
|
||||
return
|
||||
}
|
||||
await sleep(POLL_INTERVAL_MS)
|
||||
if (currentToken !== orderPollToken) return
|
||||
}
|
||||
} catch (error) {
|
||||
if (currentToken !== orderPollToken) return
|
||||
console.error("查询订单详情意外的错误:", error)
|
||||
state.failMessage = "查询订单详情失败"
|
||||
state.phase = "error"
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options: any) => {
|
||||
if (options.orderId) {
|
||||
state.orderId = options.orderId || ""
|
||||
getOrder(true)
|
||||
} else {
|
||||
uni.showToast({ title: "参数错误", icon: "none" })
|
||||
router.back()
|
||||
}
|
||||
if (options.backBtnType) {
|
||||
state.backBtnType = options.backBtnType
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<crud-layout title="支付成功" bg="/static/page/blue-bg.png">
|
||||
<view class="flex-col-center">
|
||||
<view class="flex-col-center m-y-50rpx">
|
||||
<crud-layout title="充值结果" bg="/static/page/blue-bg.png">
|
||||
<view class="h-30rpx" />
|
||||
<view class="bg-white rounded-24rpx shadow-main px-30rpx pt-10rpx pb-24rpx">
|
||||
<view class="flex-col-center pt-10rpx pb-20rpx h-500rpx">
|
||||
<view class="flex-row-center size-280rpx">
|
||||
<AppLottiePlayer :animationData="successAnimation" width="280rpx" height="280rpx" :loop="false" />
|
||||
<AppLottiePlayer :animationData="currentAnimation" :width="currentAnimationSize.width"
|
||||
:height="currentAnimationSize.height" :loop="currentLoop" />
|
||||
</view>
|
||||
|
||||
<view class="text-38rpx font-700 color-#222">{{ titleText }}</view>
|
||||
<view class="mt-10rpx text-24rpx color-#8a94a6 text-center">{{ descText }}</view>
|
||||
<view class="text-58rpx font-700 color-#222">¥{{ hooks.useMoney(payOrderAmount) }}
|
||||
</view>
|
||||
<text class="text-36rpx mt-24rpx font-bold c-#333333!">支付成功</text>
|
||||
</view>
|
||||
|
||||
<view class="flex-col-center m-b-60rpx">
|
||||
<text class="text-90rpx c-#333333!">¥{{ scanPayData.payPrice }}</text>
|
||||
</view>
|
||||
|
||||
<view class="w-full p-10rpx flex-col justify-center">
|
||||
<view class="flex-row justify-between m-15rpx">
|
||||
<text class="sub-text-30rpx c-#333333!">商家</text>
|
||||
<text class="sub-text-30rpx">{{ scanPayData.mchName }}</text>
|
||||
<view class="pt-10rpx">
|
||||
<view class="flex items-center justify-between py-16rpx">
|
||||
<text class="text-26rpx color-#8a94a6">商户</text>
|
||||
<text class="text-28rpx color-#333 font-500 max-w-380rpx text-right">{{ mchNameText }}</text>
|
||||
</view>
|
||||
<view class="flex-row justify-between m-15rpx">
|
||||
<text class="sub-text-30rpx c-#333333!">支付方式</text>
|
||||
<text class="sub-text-30rpx">扫一扫</text>
|
||||
<view class="flex items-center justify-between py-16rpx">
|
||||
<text class="text-26rpx color-#8a94a6">充值方式</text>
|
||||
<text class="text-28rpx color-#333 font-500 max-w-380rpx text-right">
|
||||
{{ payTypeText }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex items-center justify-between py-16rpx">
|
||||
<text class="text-26rpx color-#8a94a6">订单状态</text>
|
||||
<text class="text-28rpx font-500 max-w-380rpx text-right"
|
||||
:class="state.phase === 'success' ? 'color-#1dbb84' : state.phase === 'error' ? 'color-#ff5a5f' : 'color-#0094ff'">
|
||||
{{ state.phase === "loading" ? "确认中" : state.phase === "success" ? "支付成功" : "支付失败" }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="h-100rpx" />
|
||||
<tm-button :block="true" class="w-full p-40rpx" @tap="goBack">完成</tm-button>
|
||||
|
||||
<view v-if="state.phase !== 'loading'"
|
||||
class="fixed left-30rpx right-30rpx bottom-30rpx z-20 flex flex-col items-center gap-20rpx">
|
||||
<!-- 广告 -->
|
||||
<information-stream-ad class="w-full" />
|
||||
<slot v-if="state.phase === 'success'">
|
||||
<view v-if="state.backBtnType === 'back'"
|
||||
class="w-full h-88rpx rounded-full flex items-center justify-center text-30rpx font-700 color-white! bg-gradient-to-r from-#0094ff to-#36b4ff shadow-[0_16rpx_32rpx_rgba(0,148,255,0.18)]"
|
||||
@tap="router.jump('/pages/tabbar/order', {}, 2)">
|
||||
返回
|
||||
</view>
|
||||
<view v-else
|
||||
class="w-full h-88rpx rounded-full flex items-center justify-center text-30rpx font-700 color-white! bg-gradient-to-r from-#0094ff to-#36b4ff shadow-[0_16rpx_32rpx_rgba(0,148,255,0.18)]"
|
||||
@tap="router.jump('/pages/order/detail', { id: state.orderId }, 2)">
|
||||
查看订单详情
|
||||
</view>
|
||||
</slot>
|
||||
<view v-else
|
||||
class="w-full h-88rpx rounded-full flex items-center justify-center text-30rpx font-700 color-white! bg-gradient-to-r from-#0094ff to-#36b4ff shadow-[0_16rpx_32rpx_rgba(0,148,255,0.18)]"
|
||||
@tap="getOrder(true)">
|
||||
重新查询
|
||||
</view>
|
||||
</view>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue"
|
||||
import { onShow } from "@dcloudio/uni-app"
|
||||
import { usePayStore } from "@/sheep/stores/pay"
|
||||
|
||||
import successAnimation from "@/static/lottie-json/success.json"
|
||||
import AppLottiePlayer from "@@/components/common/app-lottie-player.vue"
|
||||
|
||||
const scanPayData = ref<any>({})
|
||||
|
||||
onShow(() => {
|
||||
if (!usePayStore().scanPayData.mchId) return uni.showToast({ title: "支付信息不存在", icon: "none" })
|
||||
scanPayData.value = usePayStore().scanPayData
|
||||
})
|
||||
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
@@ -9,6 +9,7 @@ import { orderApi, refundApi, commonApi } from "@@/api"
|
||||
import { filePath } from "@@/utils/file"
|
||||
|
||||
import OrderSimpleCarList from "@@/components/order/order-simple-car-list.vue"
|
||||
import SelectMapAddress from "@@/components/address/select-map-address.vue"
|
||||
|
||||
const data = {
|
||||
payType: [
|
||||
@@ -136,9 +137,13 @@ const doSubmit = async () => {
|
||||
<view class="h-30rpx" />
|
||||
<order-simple-car-list :mchName="state.detail.merchantName" :carList="state.shopCarList"
|
||||
:takeOutSetting="null" />
|
||||
<slot>
|
||||
<view class="h-20rpx" />
|
||||
<select-map-address :canSelect="false" />
|
||||
</slot>
|
||||
<view class="h-20rpx" />
|
||||
<view class="card p-x-20rpx p-y-30rpx m-b-20rpx">
|
||||
<view class="sub-text-28">售后类型</view>
|
||||
<view class="sub-text-24">售后类型</view>
|
||||
<view class="m-t-20rpx">
|
||||
<tm-radio-group @change="radioChange" direction="column" gap="20" v-model="applyForm.way">
|
||||
<tm-radio :disabled="v.disabled" v-for="(v, i) in data.payType" :key="i" v-show="v.visible"
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<template>
|
||||
<crud-layout title="结算" mainIsScroll bg="/static/page/blue-bg.png">
|
||||
<view class="h-20rpx" />
|
||||
<select-map-address />
|
||||
<select-map-address @selectAddress="selectAddress" />
|
||||
<view class="h-20rpx" />
|
||||
<order-simple-car-list :take-out-setting="null" :mch-name="'未知商户'" :car-list="cartList" />
|
||||
<order-simple-car-list :take-out-setting="null" :mch-name="state.mchDetail?.name ?? '未知商户'"
|
||||
:car-list="cartList" />
|
||||
<view class="h-20rpx" />
|
||||
<pay-card />
|
||||
<pay-card :visiblePayBtn="false" @selectPayType="selectPayType" />
|
||||
<view class="h-40rpx" />
|
||||
<template #main-bottom>
|
||||
<view class="flex justify-end items-center p-32rpx">
|
||||
<view class="flex-col mr-32rpx">
|
||||
@@ -21,33 +23,71 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref } from "vue"
|
||||
import { hooks } from "@/sheep"
|
||||
import useCartBuy from "./use-cart-buy"
|
||||
import { onLoad } from "@dcloudio/uni-app"
|
||||
import { walletApi } from "@/sheep/api"
|
||||
|
||||
import { hooks, router } from "@/sheep"
|
||||
import { AggregationPayTool } from "@@/utils/pay-tool"
|
||||
import { merchantApi } from "@@/api"
|
||||
|
||||
import SelectMapAddress from "@@/components/address/select-map-address.vue"
|
||||
import OrderSimpleCarList from "@@/components/order/order-simple-car-list.vue"
|
||||
import PayCard from "@@/components/pay/pay-card.vue"
|
||||
|
||||
const { cartList, totPrice, totalCount, getShopCart, doBuy } = useCartBuy()
|
||||
import useCartBuy from "./use-cart-buy"
|
||||
|
||||
const { cartList, totPrice, totalCount, getShopCart, getCarParentId } = useCartBuy()
|
||||
|
||||
const state = reactive<any>({
|
||||
mchId: "",
|
||||
showDrawer: false,
|
||||
curPickupId: "",
|
||||
mchDetail: {},
|
||||
mapAddressId: '',
|
||||
payType: '',
|
||||
walletTypeId: '',
|
||||
})
|
||||
|
||||
onLoad((option: any) => {
|
||||
const { mchId } = option
|
||||
if (!mchId) return uni.showToast({ title: "参数错误", icon: "error" })
|
||||
state.mchId = option.mchId
|
||||
getMchDetail()
|
||||
getShopCart(mchId)
|
||||
})
|
||||
|
||||
// 获取商户详情
|
||||
const getMchDetail = async () => {
|
||||
try {
|
||||
const { code, data } = await merchantApi.detail({ id: state.mchId })
|
||||
if (code !== 0) throw new Error(data?.msg ?? "获取商户详情失败")
|
||||
state.mchDetail = data
|
||||
} catch (error) {
|
||||
console.log("获取商户详情,意外的错误:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// 选择支付方式
|
||||
const selectPayType = (type: string, typeValue: any) => {
|
||||
state.payType = type
|
||||
state.walletTypeId = typeValue?.extra?.walletTypeId ?? ''
|
||||
}
|
||||
|
||||
const submitOrder = () => {
|
||||
doBuy(null)
|
||||
// 选择地址
|
||||
const selectAddress = (addressId: string, address: any) => {
|
||||
state.mapAddressId = addressId
|
||||
}
|
||||
|
||||
const submitOrder = async () => {
|
||||
if (!state.mapAddressId) return uni.showToast({ title: "请选择地址", icon: "none" })
|
||||
if (!state.payType) return uni.showToast({ title: "请选择支付方式", icon: "none" })
|
||||
const res = await AggregationPayTool.shopPay({
|
||||
parentCarId: getCarParentId.value,
|
||||
mapAddressId: state.mapAddressId,
|
||||
payType: state.payType,
|
||||
walletTypeId: state.walletTypeId,
|
||||
})
|
||||
if (res?.orderId) {
|
||||
router.jump("/pages/pay/pay-complete", {
|
||||
orderId: res?.orderId,
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -45,42 +45,15 @@ export default function useCartBuy() {
|
||||
await cartStore.removeProductCount(productId, merchantId)
|
||||
}
|
||||
|
||||
// 获取购物车商品的parentCarId
|
||||
const getCarParentId = computed(() => {
|
||||
return cartList.value[0].parentCarId
|
||||
})
|
||||
|
||||
const goSettlement = (mchId: string) => {
|
||||
uni.navigateTo({ url: `/pages/prosperity-shop/settlement?mchId=${mchId}` })
|
||||
}
|
||||
|
||||
// 点击提交订单
|
||||
const doBuy = async (pickUpId: string) => {
|
||||
if (isEmpty(cartList.value)) return uni.showToast({ title: "请至少购买一件商品", icon: "none" })
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "是否确定购买",
|
||||
confirmColor: "#0094ff",
|
||||
success: async (res) => {
|
||||
if (!res.confirm) return
|
||||
submitPay(pickUpId)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 确认提交订单
|
||||
const submitPay = async (pickUpId: string) => {
|
||||
try {
|
||||
uni.showLoading({ title: "支付中...", mask: false })
|
||||
const { code, msg }: any = await orderApi.appCreateFarmerReserveOrder({
|
||||
carParentId: cartList.value[0].parentCarId,
|
||||
pickUpId,
|
||||
})
|
||||
if (code != 0) throw new Error(msg)
|
||||
uni.showToast({ title: "支付成功", icon: "none" })
|
||||
router.jump("/pages/tabbar/order")
|
||||
} catch (error: any) {
|
||||
uni.showToast({ title: error.message, icon: "none" })
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
totPrice,
|
||||
totalCount,
|
||||
@@ -90,6 +63,6 @@ export default function useCartBuy() {
|
||||
addProductCount,
|
||||
removeProductCount,
|
||||
goSettlement,
|
||||
doBuy,
|
||||
getCarParentId,
|
||||
}
|
||||
}
|
||||
+19
-25
@@ -7,22 +7,25 @@ import { orderApi } from "@@/api"
|
||||
|
||||
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
|
||||
import AppHotUpdate from "@/sheep/components/app-version/app-hot-update.vue"
|
||||
import { getLaunchParam } from "@/sheep/utils/app"
|
||||
import orderCar from "@/sheep/components/order/order-car.vue"
|
||||
import OrderCar from "@/sheep/components/order/order-car.vue"
|
||||
import OrderConfirmReceipt from "@/sheep/components/order/order-confirm-receipt.vue"
|
||||
|
||||
const appHotUpdateRef = ref<any>(null)
|
||||
const orderConfirmReceiptRef = ref<any>(null)
|
||||
const data = {
|
||||
tabs: [
|
||||
{ id: null, name: "全部", disabled: false },
|
||||
{ id: 1, name: "未支付", disabled: false },
|
||||
{ id: 5, name: "已支付", disabled: false },
|
||||
{ id: 10, name: "售后", disabled: false },
|
||||
{ id: 20, name: "已核销", disabled: false },
|
||||
{ pa: { orderStatusCodes: null }, name: "全部", disabled: false },
|
||||
{ pa: { orderStatusCodes: [200] }, name: "待发货", disabled: false },
|
||||
{ pa: { orderStatusCodes: [5, 210] }, name: "待收货/待使用", disabled: false },
|
||||
{ pa: { orderStatusCodes: [20, 220] }, name: "已核销/已收货", disabled: false },
|
||||
{ pa: { orderStatusCodes: [10] }, name: "售后", disabled: false },
|
||||
{ pa: { orderStatusCodes: [1] }, name: "待支付", disabled: false },
|
||||
{ pa: { orderStatusCodes: [30] }, name: "已关闭", disabled: false },
|
||||
],
|
||||
}
|
||||
const state = reactive<any>({
|
||||
pa: {
|
||||
orderStatus: data.tabs[0].id,
|
||||
...data.tabs[0].pa,
|
||||
// 售后状态筛选使用逗号拼接后的字符串,便于直接透传给分页接口。
|
||||
refundStatusCodes: [],
|
||||
},
|
||||
@@ -74,9 +77,9 @@ onShow(async () => {
|
||||
})
|
||||
const doTab = (e: any) => {
|
||||
const target = data.tabs[e]
|
||||
state.pa.orderStatus = target.id
|
||||
state.pa = target.pa
|
||||
// 只有“售后”tab 才需要售后状态筛选,切走时清空,避免影响其它状态查询。
|
||||
if (target.id !== 10) {
|
||||
if (!target.pa.orderStatusCodes?.includes(10)) {
|
||||
state.activeRefundStatusList = []
|
||||
state.pa.refundStatusCodes = []
|
||||
}
|
||||
@@ -86,17 +89,7 @@ const doTab = (e: any) => {
|
||||
const pageRef = ref<any>(null)
|
||||
const pageHook = hooks.usePage(
|
||||
pageRef,
|
||||
getLaunchParam() == "canteen" // 食堂
|
||||
? orderApi.caneenPage
|
||||
: getLaunchParam() == "selfMerchant"
|
||||
? orderApi.supPage
|
||||
: getLaunchParam() == "coopMerchant"
|
||||
? orderApi.supPage
|
||||
: getLaunchParam() == "onlineShop"
|
||||
? orderApi.supPage
|
||||
: getLaunchParam() == "prosperityShop"
|
||||
? orderApi.farmerSpuPage
|
||||
: async () => [],
|
||||
orderApi.page,
|
||||
null,
|
||||
"data.records",
|
||||
)
|
||||
@@ -115,8 +108,8 @@ const query = (page: number, pagesize: number) => {
|
||||
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll">
|
||||
<template #top>
|
||||
<view class="bg-white rounded-16rpx px-20rpx my-20rpx">
|
||||
<z-tabs :list="data.tabs" @change="doTab" />
|
||||
<view v-if="state.pa.orderStatus == 10"
|
||||
<z-tabs :list="data.tabs" :scroll-count="4" @change="doTab" />
|
||||
<view v-if="state.pa.orderStatusCodes?.includes(10)"
|
||||
class="flex flex-items-center justify-between py-10rpx second-text-24 font-400!">
|
||||
<text>可筛选售后状态</text>
|
||||
<view class="flex-row-center flex-wrap-center">
|
||||
@@ -133,10 +126,11 @@ const query = (page: number, pagesize: number) => {
|
||||
</template>
|
||||
<view class="card rounded-24rpx bg-white p-20rpx pb-0rpx mb-20rpx" v-for="(v, index) in pageHook.list"
|
||||
:key="v.id">
|
||||
<order-car :cardetail="v" :footerOperate="['refund', 'qrCodeDetail']" />
|
||||
<order-car :cardetail="v" :footerOperate="['refund', 'qrCodeDetail', 'expressTracking']"
|
||||
@confirmReceipt="orderConfirmReceiptRef.open(v.id, v.carList)" />
|
||||
</view>
|
||||
|
||||
</z-paging>
|
||||
<order-confirm-receipt ref="orderConfirmReceiptRef" @refresh="query" />
|
||||
<!-- #ifdef APP -->
|
||||
<app-hot-update ref="appHotUpdateRef" :autoPopup="true" />
|
||||
<!-- #endif -->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<crud-layout title="商城" bg="/static/page/blue-bg.png">
|
||||
<z-paging ref="pageRef" height="100%" :fixed="false" v-model="pageHook.list" :default-page-size="10"
|
||||
safe-area-inset-bottom :loading-more-enabled="true" :show-scrollbar="false" @query="query"
|
||||
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll">
|
||||
|
||||
+19
-6
@@ -22,6 +22,13 @@ export default {
|
||||
params,
|
||||
}),
|
||||
// 食堂订单
|
||||
page: (params: any) =>
|
||||
request({
|
||||
url: `/hard/hard-order/app/page-join`,
|
||||
method: "GET",
|
||||
params,
|
||||
}),
|
||||
// 食堂订单
|
||||
caneenPage: (params: any) =>
|
||||
request({
|
||||
url: `/hard/hard-order/app/caneen-page-join`,
|
||||
@@ -126,15 +133,21 @@ export default {
|
||||
data,
|
||||
}),
|
||||
/**
|
||||
* 创建共富商城预约订单
|
||||
* @body body.carParentId 购物车id
|
||||
* @body body.walletTypeId 钱包类型id
|
||||
* @body body.pickUpId 自提点id
|
||||
* 创建商城预约订单
|
||||
*/
|
||||
appCreateFarmerReserveOrder: (data: any) =>
|
||||
appCreateShopReserveOrder: (data: any) =>
|
||||
request({
|
||||
url: "/hard/hard-order/app/create-farmer-order",
|
||||
url: "/hard/hard-order/app/create-shop-order",
|
||||
method: "POST",
|
||||
data,
|
||||
}),
|
||||
/**
|
||||
* 确认收货
|
||||
* @param orderId 订单id
|
||||
*/
|
||||
confirmReceipt: (orderId: string) =>
|
||||
request({
|
||||
url: `/hard/hard-order/app/confirm-receipt/${orderId}`,
|
||||
method: "PUT",
|
||||
}),
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
<text>{{ state.defaultAddress.inputAddress }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="iconfont icon-youjiantou second-text-20!" />
|
||||
<view v-if="canSelect" class="iconfont icon-youjiantou second-text-20!" />
|
||||
</view>
|
||||
<view class="flex-row items-center second-text-22 gap-8rpx">
|
||||
<text>{{ state.defaultAddress.username }}</text>
|
||||
@@ -51,34 +51,37 @@
|
||||
:default-page-size="10" safe-area-inset-bottom :loading-more-enabled="true" @query="query"
|
||||
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll"
|
||||
:show-loading-more-no-more-view="false">
|
||||
<view class="flex items-center p-x-30rpx p-y-20rpx m-b-30rpx" v-for="v in pageHook.list" :key="v.id">
|
||||
<view class="flex-1 flex-row items-center justify-between gap-4rpx" @tap="doSelectAppt(v)">
|
||||
<tm-radio v-model="state.selectedAddressId" :value="v.id" />
|
||||
<view class="flex-col justify-items-start flex-1 gap-16rpx">
|
||||
<view class="flex-row gap-8rpx">
|
||||
<text
|
||||
class="rounded-8rpx border border-[#d1e9ff] bg-[#eff8ff] px-18rpx py-12rpx text-20rpx line-height-1 text-[#1570ef]">
|
||||
{{ hooks.useEnum('mapAddressTag', v.tag) }}
|
||||
</text>
|
||||
<view class=" flex-row-center sub-text-26 gap-4rpx">
|
||||
<text>{{ v.adressDetail }}</text>
|
||||
<text>{{ v.inputAddress }}</text>
|
||||
<view class="flex-col" v-for="v in pageHook.list" :key="v.id">
|
||||
<view class="flex items-center p-x-30rpx p-y-20rpx">
|
||||
<view class="flex-1 flex-row items-center justify-between gap-4rpx" @tap="doSelectAppt(v)">
|
||||
<tm-radio v-model="state.selectedAddressId" :value="v.id" />
|
||||
<view class="flex-col justify-items-start flex-1 gap-16rpx">
|
||||
<view class="flex-row gap-8rpx">
|
||||
<text
|
||||
class="rounded-8rpx border border-[#d1e9ff] bg-[#eff8ff] px-18rpx py-12rpx text-20rpx line-height-1 text-[#1570ef]">
|
||||
{{ hooks.useEnum('mapAddressTag', v.tag) }}
|
||||
</text>
|
||||
<view class=" flex-row-center sub-text-26 gap-4rpx">
|
||||
<text>{{ v.adressDetail }}</text>
|
||||
<text>{{ v.inputAddress }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-row items-center second-text-22 gap-8rpx">
|
||||
<text>{{ v.username }}</text>
|
||||
<text>{{ v.userMoblie }}</text>
|
||||
<text
|
||||
class="rounded-8rpx border border-[#d1e9ff] bg-[#eff8ff] px-18rpx py-12rpx text-20rpx line-height-1 text-[#1570ef]"
|
||||
v-if="v.isDefault == '1'">
|
||||
默认
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-row items-center second-text-22 gap-8rpx">
|
||||
<text>{{ v.username }}</text>
|
||||
<text>{{ v.userMoblie }}</text>
|
||||
<text
|
||||
class="rounded-8rpx border border-[#d1e9ff] bg-[#eff8ff] px-18rpx py-12rpx text-20rpx line-height-1 text-[#1570ef]"
|
||||
v-if="v.isDefault == '1'">
|
||||
默认
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<text class="iconfont icon-bianji sub-text-36!"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<text class="iconfont icon-bianji sub-text-36!"></text>
|
||||
</view>
|
||||
<view class="address-border" />
|
||||
</view>
|
||||
<template #bottom>
|
||||
<view class="w-full my-20rpx">
|
||||
@@ -99,6 +102,16 @@ import { mapAddressApi } from "@@/api"
|
||||
|
||||
const emit = defineEmits(["selectAddress"])
|
||||
|
||||
export type Props = {
|
||||
// 是否可以选择地址
|
||||
canSelect?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
canSelect: true,
|
||||
})
|
||||
|
||||
|
||||
const state = reactive<any>({
|
||||
visibleSelectAddress: false,
|
||||
selectedAddressId: "",
|
||||
@@ -123,12 +136,14 @@ const getDefaultAddress = async () => {
|
||||
if (code != 0) throw new Error()
|
||||
state.defaultAddress = data
|
||||
state.selectedAddressId = data.id
|
||||
emit("selectAddress", data.id, data)
|
||||
} catch (error) {
|
||||
console.log("获取默认地址意外的错误", error)
|
||||
}
|
||||
}
|
||||
|
||||
const showSelectAddress = () => {
|
||||
if (!props.canSelect) return
|
||||
state.visibleSelectAddress = true
|
||||
}
|
||||
|
||||
@@ -144,3 +159,10 @@ const addAddress = () => {
|
||||
router.jump('/pages/user/map-address/index')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.address-border {
|
||||
border: 1rpx solid #f8f8f8;
|
||||
margin: 10rpx 0;
|
||||
}
|
||||
</style>
|
||||
@@ -8,8 +8,11 @@ import {
|
||||
} from "@@/utils/user-role"
|
||||
|
||||
import { filePath } from "@@/utils/file"
|
||||
import { openExpressTracking } from "@@/utils/open-foreign-app"
|
||||
|
||||
const emit = defineEmits(['cancel'])
|
||||
import OrderStatusTag from "./order-status-tag.vue"
|
||||
|
||||
const emit = defineEmits(['cancel', 'confirmReceipt'])
|
||||
|
||||
export type Props = {
|
||||
// 订单详情
|
||||
@@ -27,7 +30,7 @@ export type Props = {
|
||||
// 底部操作区域控制。
|
||||
// 传 true 时,等价于 ['refund', 'qrCodeDetail'],表示两个按钮都允许显示。
|
||||
// 传数组时,可按需精确控制具体显示哪些按钮。
|
||||
footerOperate?: boolean | Array<'refund' | 'qrCodeDetail' | 'cancel'>
|
||||
footerOperate?: boolean | Array<'refund' | 'qrCodeDetail' | 'cancel' | 'expressTracking'>
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@@ -61,7 +64,7 @@ const toggleGoodsCollapse = (order: any, index: number) => {
|
||||
// `footerOperate === true` 时,视为开启全部按钮;
|
||||
// 未传或传 false 时,不显示任何底部操作按钮;
|
||||
// 传数组时,仅显示数组中包含的操作项。
|
||||
const hasFooterOperate = (operate: 'refund' | 'qrCodeDetail' | 'cancel') => {
|
||||
const hasFooterOperate = (operate: 'refund' | 'qrCodeDetail' | 'cancel' | 'expressTracking') => {
|
||||
if (props.footerOperate === true) return true
|
||||
if (!Array.isArray(props.footerOperate)) return false
|
||||
return props.footerOperate.includes(operate)
|
||||
@@ -69,10 +72,10 @@ const hasFooterOperate = (operate: 'refund' | 'qrCodeDetail' | 'cancel') => {
|
||||
|
||||
// 退款按钮显示条件:
|
||||
// 1. footerOperate 允许 refund;
|
||||
// 2. 订单状态为 5;
|
||||
// 3. 订单类型为 2。
|
||||
// 2. 订单状态为 5、210
|
||||
// 3. 订单类型为 2、7
|
||||
const showRefundButton = (order: any) => {
|
||||
return hasFooterOperate('refund') && String(order?.orderStatus) === '5' && String(order?.orderType) === '2'
|
||||
return hasFooterOperate('refund') && ['5', '210'].includes(String(order?.orderStatus)) && ['2', '7'].includes(String(order?.orderType))
|
||||
}
|
||||
|
||||
// 显示订单详情按钮条件:
|
||||
@@ -114,6 +117,20 @@ const showCancelButton = (order: any) => {
|
||||
)
|
||||
}
|
||||
|
||||
// 手动确认收货按钮显示条件:
|
||||
// 1. footerOperate允许expressTracking;
|
||||
// 2. 订单状态为,210
|
||||
// 3. 订单类型为,7
|
||||
const showExpressTrackingButton = (order: any) => {
|
||||
return (
|
||||
hasFooterOperate('expressTracking') &&
|
||||
String(order?.orderStatus) === '210' &&
|
||||
['7'].includes(String(order?.orderType))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 查看订单和核销码
|
||||
const doToDetail = (v: any) => {
|
||||
router.jump("/pages/order/detail", { id: v.id })
|
||||
@@ -124,6 +141,16 @@ const doRefund = (v: any) => {
|
||||
router.jump("/pages/pay/refund-apply", { id: v.id })
|
||||
}
|
||||
|
||||
// 物流查询
|
||||
const doShipment = (v: any) => {
|
||||
openExpressTracking(v.shipmentNo)
|
||||
}
|
||||
|
||||
// 确认收货
|
||||
const doExpressTracking = (v: any) => {
|
||||
emit('confirmReceipt', v)
|
||||
}
|
||||
|
||||
const doCancel = (v: any) => {
|
||||
emit('cancel', v)
|
||||
}
|
||||
@@ -149,16 +176,9 @@ const doCancel = (v: any) => {
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-shrink-0">
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 1" color="info" size="xs">未支付</tm-tag>
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 1" color="info" size="xs">待支付</tm-tag>
|
||||
<view class="w-100rpx flex-row-center">
|
||||
<slot v-if="props.cardetail.orderStatus == 5">
|
||||
<tm-tag v-if="props.cardetail.orderType == 2" color="success" size="xs">已预约</tm-tag>
|
||||
<tm-tag v-else color="success" size="xs">已支付</tm-tag>
|
||||
</slot>
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 10" color="error" size="xs">售后</tm-tag>
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 20" size="xs">已核销</tm-tag>
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 30" color="info" size="xs">已取消(智能柜)</tm-tag>
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 110" color="success" size="xs">配送中</tm-tag>
|
||||
<order-status-tag :cardetail="props.cardetail" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -172,15 +192,7 @@ const doCancel = (v: any) => {
|
||||
<view class="flex-row items-center justify-between">
|
||||
<view class="sub-text-26">{{ props.cardetail.merchantName }}</view>
|
||||
<view class="w-100rpx flex-row-center">
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 1" color="info" size="xs">未支付</tm-tag>
|
||||
<slot v-if="props.cardetail.orderStatus == 5">
|
||||
<tm-tag v-if="props.cardetail.orderType == 2" color="success" size="xs">已预约</tm-tag>
|
||||
<tm-tag v-else color="success" size="xs">已支付</tm-tag>
|
||||
</slot>
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 10" color="error" size="xs">售后</tm-tag>
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 20" size="xs">已核销</tm-tag>
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 30" color="info" size="xs">已取消(智能柜)</tm-tag>
|
||||
<tm-tag v-if="props.cardetail.orderStatus == 110" color="success" size="xs">配送中</tm-tag>
|
||||
<order-status-tag :cardetail="props.cardetail" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-row items-center justify-between second-text-22">
|
||||
@@ -249,7 +261,7 @@ const doCancel = (v: any) => {
|
||||
|
||||
<!-- start 简单购买信息(付款方式+支付金额) start -->
|
||||
<view v-if="!props.cardetail?.carList?.length"
|
||||
class="flex items-center justify-between rounded-12rpx border-[#eef3f8] bg-[linear-gradient(90deg,#ffffff_0%,#fafafa_100%)] pr-28rpx py-16rpx">
|
||||
class="flex items-center justify-between rounded-12rpx border-[#eef3f8] bg-[linear-gradient(90deg,#ffffff_0%,#fafafa_100%)] px-22rpx py-12rpx">
|
||||
<view class="flex-row-center sub-text-24 gap-8rpx">
|
||||
<text class="iconfont icon-zhifufangshi1 text-24rpx!" />
|
||||
<text> {{ hooks.useEnum('hardwarePayTypeEnum', props.cardetail.payType) }}</text>
|
||||
@@ -262,7 +274,7 @@ const doCancel = (v: any) => {
|
||||
|
||||
<!-- start 预约信息 start -->
|
||||
<view v-if="props.cardetail.apptId && props.cardetail.apptStartTime && props.cardetail.apptEndTime"
|
||||
class="flex items-center justify-between rounded-12rpx border border-[#eef3f8] bg-[linear-gradient(90deg,#ffffff_0%,#fafafa_100%)] px-28rpx py-16rpx shadow-[0_8rpx_24rpx_rgba(15,23,42,0.04)]">
|
||||
class="flex items-center justify-between rounded-12rpx border border-[#eef3f8] bg-[linear-gradient(90deg,#ffffff_0%,#fafafa_100%)] px-22rpx py-12rpx shadow-[0_8rpx_24rpx_rgba(15,23,42,0.04)]">
|
||||
<view class="min-w-0 flex-1">
|
||||
<view class="second-text-22 text-[#98a2b3]!">预约时间段</view>
|
||||
<view class="mt-10rpx sub-text-24">
|
||||
@@ -277,9 +289,24 @@ const doCancel = (v: any) => {
|
||||
</view>
|
||||
<!-- end 预约信息 end -->
|
||||
|
||||
<!-- start 发货信息 start -->
|
||||
<view v-if="props.cardetail.shipmentNo"
|
||||
class="flex items-center justify-between rounded-12rpx border border-[#eef3f8] bg-[linear-gradient(90deg,#ffffff_0%,#fafafa_100%)] px-22rpx py-12rpx shadow-[0_8rpx_24rpx_rgba(15,23,42,0.04)]"
|
||||
@tap.stop="doShipment(props.cardetail)">
|
||||
<view class="flex items-center gap-4rpx">
|
||||
<text class="iconfont icon-jisuwuliu text-24rpx!" />
|
||||
<text class="sub-text-24 font-400!">{{ props.cardetail.shipmentNo }}</text>
|
||||
</view>
|
||||
<view class="flex items-center gap-4rpx">
|
||||
<text class="second-text-24!">查看物流</text>
|
||||
<text class="iconfont icon-youjiantou second-text-22!" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- end 发货信息 end -->
|
||||
|
||||
<!-- start 底部操作区域 start -->
|
||||
<view
|
||||
v-if="showRefundButton(props.cardetail) || showRefundDetailButton(props.cardetail) || showQrCodeDetailButton(props.cardetail) || showCancelButton(props.cardetail)"
|
||||
v-if="showRefundButton(props.cardetail) || showRefundDetailButton(props.cardetail) || showQrCodeDetailButton(props.cardetail) || showCancelButton(props.cardetail) || showExpressTrackingButton(props.cardetail)"
|
||||
class="w-full flex-row items-center justify-end my-1">
|
||||
<view v-if="showRefundButton(props.cardetail)" class="botder_btn" @tap.stop="doRefund(props.cardetail)">
|
||||
退款
|
||||
@@ -288,6 +315,10 @@ const doCancel = (v: any) => {
|
||||
@tap.stop="doToDetail(props.cardetail)">
|
||||
售后详情
|
||||
</view>
|
||||
<view v-if="showExpressTrackingButton(props.cardetail)" class="m-l-20rpx primary_btn"
|
||||
@tap.stop="doExpressTracking(props.cardetail)">
|
||||
确认收货
|
||||
</view>
|
||||
<view v-if="showQrCodeDetailButton(props.cardetail)" class="m-l-20rpx botder_btn"
|
||||
@tap.stop="doToDetail(props.cardetail)">
|
||||
核销码
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<!-- z-tabs v0.2.5 by-ZXLee -->
|
||||
<!-- z-tabs v0.2.7 by-ZXLee -->
|
||||
<!-- github地址:https://github.com/SmileZXLee/uni-z-tabs -->
|
||||
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?name=z-tabs -->
|
||||
<!-- 反馈QQ群:790460711 -->
|
||||
<!-- 反馈QQ群:371624008 -->
|
||||
|
||||
<template name="z-tabs">
|
||||
<view class="z-tabs-conatiner" :style="[{ background: bgColor }, tabsStyle]">
|
||||
<view class="z-tabs-conatiner"
|
||||
:style="[{ background: bgColor }, { height: unit === 'rpx' ? '80rpx' : '40px' }, tabsStyle]">
|
||||
<view class="z-tabs-left">
|
||||
<slot name="left" />
|
||||
</view>
|
||||
@@ -18,13 +19,14 @@
|
||||
@click="tabsClick(index, item)">
|
||||
<view class="z-tabs-item-title-container">
|
||||
<text
|
||||
:class="{ 'z-tabs-item-title': true, 'z-tabs-item-title-disabled': item.disabled }"
|
||||
:class="{ 'z-tabs-item-title-rpx': unit === 'rpx', 'z-tabs-item-title-px': unit === 'px', 'z-tabs-item-title-disabled': item.disabled }"
|
||||
:style="[{ color: item.disabled ? disabledColor : (currentIndex === index ? activeColor : inactiveColor) }, item.disabled ? disabledStyle : (currentIndex === index ? activeStyle : inactiveStyle)]">
|
||||
{{ item[nameKey] || item }}
|
||||
</text>
|
||||
<text v-if="item.badge && _formatCount(item.badge.count).length"
|
||||
class="z-tabs-item-badge" :style="[badgeStyle]">{{ _formatCount(item.badge.count)
|
||||
}}</text>
|
||||
class="z-tabs-item-badge"
|
||||
:class="{ 'z-tabs-item-badge-rpx': unit === 'rpx', 'z-tabs-item-badge-px': unit === 'px' }"
|
||||
:style="[badgeStyle]">{{ _formatCount(item.badge.count) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -97,6 +99,7 @@ function _toKebab(value) {
|
||||
* @property {String} bg-color z-tabs背景色
|
||||
* @property {Object} tabs-style z-tabs样式
|
||||
* @property {Boolean} init-trigger-change 初始化时是否自动触发change事件
|
||||
* @property {String} unit z-tabs中布局的单位,默认为rpx
|
||||
* @event {Function(index,value)} change tabs改变时触发,index:当前切换到的index;value:当前切换到的value
|
||||
* @example <z-tabs :list="list"></z-tabs>
|
||||
*/
|
||||
@@ -166,6 +169,11 @@ export default {
|
||||
type: [Number, String],
|
||||
default: _gc('barHeight', 8)
|
||||
},
|
||||
//swiper的宽度,单位rpx,支持传100、"100px"或"100rpx",默认为"750rpx"
|
||||
swiperWidth: {
|
||||
type: [Number, String],
|
||||
default: _gc('swiperWidth', 750)
|
||||
},
|
||||
//滑块样式,其中的width和height将被barWidth和barHeight覆盖
|
||||
barStyle: {
|
||||
type: Object,
|
||||
@@ -250,6 +258,11 @@ export default {
|
||||
initTriggerChange: {
|
||||
type: Boolean,
|
||||
default: _gc('initTriggerChange', false)
|
||||
},
|
||||
//z-tabs中布局的单位,默认为rpx
|
||||
unit: {
|
||||
type: String,
|
||||
default: _gc('unit', 'rpx')
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -345,13 +358,16 @@ export default {
|
||||
return this._convertTextToPx(this.tabWidth);
|
||||
},
|
||||
finalBarWidth() {
|
||||
return this._convertTextToPx(this.barWidth);
|
||||
return this._convertTextToPx(this._addUnit(this.barWidth, this.unit));
|
||||
},
|
||||
finalBarHeight() {
|
||||
return this._convertTextToPx(this.barHeight);
|
||||
return this._convertTextToPx(this._addUnit(this.barHeight, this.unit));
|
||||
},
|
||||
finalSwiperWidth() {
|
||||
return this._convertTextToPx(this.swiperWidth);
|
||||
},
|
||||
finalBottomSpace() {
|
||||
return this._convertTextToPx(this.bottomSpace);
|
||||
return this._convertTextToPx(this._addUnit(this.bottomSpace, this.unit));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -360,7 +376,7 @@ export default {
|
||||
if (!this.shouldSetDx) return;
|
||||
const isLineMode = this.barAnimateMode === 'line';
|
||||
const isWormMode = this.barAnimateMode === 'worm';
|
||||
let dxRate = dx / this.tabsSuperWidth;
|
||||
let dxRate = dx / this.finalSwiperWidth;
|
||||
this.currentSwiperIndex = this.currentIndex + parseInt(dxRate);
|
||||
const isRight = dxRate > 0;
|
||||
const barWidth = this.pxBarWidth;
|
||||
@@ -501,7 +517,9 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
this.bottomDotX = this._getBottomDotX(node, this.finalBarWidth, offset);
|
||||
if (node) {
|
||||
this.bottomDotX = this._getBottomDotX(node, this.finalBarWidth, offset);
|
||||
}
|
||||
this.bottomDotXForIndex = this.bottomDotX;
|
||||
if (this.tabsWidth) {
|
||||
setTimeout(() => {
|
||||
@@ -614,6 +632,18 @@ export default {
|
||||
return Number(text);
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
// 添加单位
|
||||
_addUnit(value, unit) {
|
||||
if (Object.prototype.toString.call(value) === '[object String]') {
|
||||
let tempValue = value;
|
||||
tempValue = tempValue.replace('rpx', '').replace('upx', '').replace('px', '');
|
||||
if (value.indexOf('rpx') === -1 && value.indexOf('upx') === -1 && value.indexOf('px') !== -1) {
|
||||
tempValue = parseFloat(tempValue) * 2;
|
||||
}
|
||||
value = tempValue;
|
||||
}
|
||||
return unit === 'rpx' ? value + 'rpx' : (value / 2) + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,7 +661,6 @@ export default {
|
||||
width: 750rpx;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.z-tabs-scroll-view-conatiner {
|
||||
@@ -703,10 +732,12 @@ export default {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.z-tabs-item-title {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
font-size: 28rpx;
|
||||
.z-tabs-item-title-rpx {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.z-tabs-item-title-px {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.z-tabs-item-title-disabled {
|
||||
@@ -716,14 +747,23 @@ export default {
|
||||
}
|
||||
|
||||
.z-tabs-item-badge {
|
||||
margin-left: 8rpx;
|
||||
background-color: #ec5b56;
|
||||
color: white;
|
||||
font-size: 22rpx;
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
.z-tabs-item-badge-rpx {
|
||||
margin-left: 8rpx;
|
||||
font-size: 22rpx;
|
||||
padding: 0rpx 10rpx;
|
||||
}
|
||||
|
||||
.z-tabs-item-badge-px {
|
||||
margin-left: 4px;
|
||||
font-size: 11px;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
.z-tabs-bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
||||
@@ -1,13 +1,369 @@
|
||||
<template>
|
||||
<view class="card rounded-24rpx bg-white p-20rpx">
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="sub-text-24">选择支付方式</view>
|
||||
</view>
|
||||
<view class="mt-20rpx flex-col justify-items-start gap-8rpx">
|
||||
<view>
|
||||
<view class="card rounded-24rpx bg-white p-20rpx">
|
||||
<view v-if="visibleTitle" class="flex items-center justify-between">
|
||||
<view class="sub-text-24">选择支付方式</view>
|
||||
</view>
|
||||
<view v-if="isPay">
|
||||
<view class="mt-20rpx px-10rpx pb-10rpx rounded-12rpx flex-col justify-items-start bg-#eff8ff"
|
||||
@tap="!walletPayDetail.disabled && (state.currentPayType = walletPayDetail.type)">
|
||||
<view class="flex items-center gap-12rpx my-20rpx">
|
||||
<image class="size-40rpx" src="/static/logo/zax.png" mode="scaleToFill" />
|
||||
<text class="sub-text-24">钱包支付</text>
|
||||
</view>
|
||||
<view class="bg-white rounded-12rpx" v-if="walletPayDetail && visibleWalletPay">
|
||||
<view class="px-20rpx">
|
||||
<view class="flex-col justify-between">
|
||||
<view class="my-20rpx second-text-26">付款方式</view>
|
||||
<view class="second-text-22">
|
||||
<text>{{ walletPayDetail.extra.walletTypeName }}</text>
|
||||
<text>(可用¥{{ hooks.useMoney(walletPayDetail.extra.balance) }})</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="wallet-border" />
|
||||
<view class="flex items-center justify-between" @tap.stop="doOpenSelectWalletDrawer">
|
||||
<text class="second-text-24">更换钱包支付</text>
|
||||
<text class="iconfont icon-youjiantou second-text-24!" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="flex items-center justify-between rounded-12rpx bg-#f8f8f8 m-t-12rpx px-12rpx py-10rpx">
|
||||
<text class="sub-text-22">钱包极速支付</text>
|
||||
<tm-radio :showLabel="false" v-model="state.currentPayType"
|
||||
:disabled="walletPayDetail.disabled" :value="walletPayDetail.type" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-for="(v, i) in state.payType" :key="i" @tap="!v.disabled && (state.currentPayType = v.type)">
|
||||
<view v-if="['10', '20'].includes(v.type)"
|
||||
class="flex items-center py-20rpx pl-10rpx pr-22rpx rounded-16rpx">
|
||||
<image class="size-50rpx" :src="v.logoDir" mode="scaleToFill" />
|
||||
<view class="flex-1 flex justify-between items-center">
|
||||
<view class="flex-col justify-center p-l-30rpx gap-4rpx">
|
||||
<view class="sub-text-24">{{ v.text }}</view>
|
||||
<view class="second-text-20">{{ v.desc }}</view>
|
||||
</view>
|
||||
<tm-radio :showLabel="false" v-model="state.currentPayType" :disabled="v.disabled"
|
||||
:value="v.type" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="wallet-recharge-empty bg-white rounded-12rpx m-t-20rpx">
|
||||
<view class="wallet-recharge-empty__icon">!</view>
|
||||
<view class="sub-text-26 color-#333">该商户暂不提供充值功能,请联系客服</view>
|
||||
<service-text />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isPay && visiblePayBtn"
|
||||
class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-t-60rpx sub-text-30 color-white!" @tap="doPay">
|
||||
确认充值
|
||||
</view>
|
||||
|
||||
<tm-drawer v-model:show="state.visibleSelectWallet" title="选择钱包" :show-close="true" position="bottom" size="40%">
|
||||
<view class="flex-col" v-for="(v, index) in state.walletList" :key="index" @click="selectTargetWalletType(v)">
|
||||
<view class="flex items-center p-x-30rpx p-y-20rpx">
|
||||
<view class="flex-1 flex items-center gap-16rpx">
|
||||
<image class="size-40rpx" :src="filePath(v.walletTypeIcon)" mode="scaleToFill" />
|
||||
<view class="flex items-center">
|
||||
<text class="sub-text-24 font-400!">{{ v.walletTypeName }}</text>
|
||||
<text class="sub-text-24 font-400!">可用¥{{ hooks.useMoney(v.balance) }}</text>
|
||||
<text v-if="v.cardNumber"
|
||||
class="ml-8rpx rounded-8rpx border border-[#d1e9ff] bg-[#eff8ff] px-18rpx py-12rpx text-20rpx line-height-1 text-[#1570ef]">
|
||||
{{ v.cardNumber }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<tm-radio :showLabel="false" v-model="state.currentSelectWallet" :disabled="v.disabled"
|
||||
:value="v.walletTypeId" />
|
||||
</view>
|
||||
<view class="wallet-border" />
|
||||
</view>
|
||||
</tm-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, watch } from "vue"
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app"
|
||||
import { isEmpty } from "radash"
|
||||
|
||||
</script>
|
||||
import { hooks, constant, router } from "@@/index"
|
||||
import { filePath } from "@/sheep/utils/file"
|
||||
import { walletApi, appPlusPlatformApi, type AppPlusPayDto } from "@@/api"
|
||||
|
||||
import ServiceText from "@@/components/common/service-text.vue"
|
||||
|
||||
const emit = defineEmits(["selectPayType"])
|
||||
|
||||
export type Props = {
|
||||
visibleTitle?: boolean
|
||||
visiblePayBtn?: boolean
|
||||
visibleWalletPay?: boolean
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visibleTitle: true,
|
||||
visiblePayBtn: true,
|
||||
visibleWalletPay: true,
|
||||
})
|
||||
|
||||
const isPay = computed(() => {
|
||||
return state.payType && state.payType.length > 0
|
||||
})
|
||||
|
||||
const walletPayDetail = computed(() => {
|
||||
return state.payType.find(v => v.type == "30") ?? null
|
||||
})
|
||||
|
||||
const state = reactive<any>({
|
||||
visibleSelectWallet: false,
|
||||
walletList: [],
|
||||
currentSelectWallet: null,
|
||||
|
||||
payNo: '',
|
||||
payType: [],
|
||||
walletId: null,
|
||||
currentPayType: null,
|
||||
currentRecharge: 0,
|
||||
userInfo: {},
|
||||
detail: {},
|
||||
payTypeList: [],
|
||||
rechargeList: [],
|
||||
})
|
||||
|
||||
watch(() => state.currentPayType, (value) => {
|
||||
if (!value) return
|
||||
const targetPayType = state.payType.find(v => v.type == value) ?? null
|
||||
emit("selectPayType", value, targetPayType)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getUserPayTypeList()
|
||||
})
|
||||
|
||||
// 获取用户钱包列表
|
||||
const getAllWalletList = async () => {
|
||||
try {
|
||||
const { data, code }: any = await walletApi.all()
|
||||
if (code != 0) throw new Error(data?.msg || "获取用户钱包列表失败")
|
||||
const records = data?.records ?? []
|
||||
state.walletList = records
|
||||
state.payType.push({
|
||||
logoDir: "/static/logo/zax.png",
|
||||
text: "钱包支付",
|
||||
desc: "内部支付,方便,快捷",
|
||||
disabled: false,
|
||||
type: "30",
|
||||
value: "WALLET_PAY",
|
||||
extra: {
|
||||
...records[0]
|
||||
}
|
||||
})
|
||||
state.currentSelectWallet = records[0].walletTypeId
|
||||
} catch (error) {
|
||||
console.log("获取用户钱包列表,error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
const getUserPayTypeList = async () => {
|
||||
const _pa = {}
|
||||
const { data } = await walletApi.getUserPaySettingList(_pa)
|
||||
state.payTypeList = data ?? []
|
||||
if (state.payTypeList.length) {
|
||||
const typeList = state.payType.map(v => v.type)
|
||||
for (const v of state.payTypeList) {
|
||||
if (!v.platformType) continue
|
||||
if (v.platformType == "30" && !typeList.includes("30")) {
|
||||
await getAllWalletList()
|
||||
}
|
||||
if (v.platformType == "10" && !typeList.includes("10")) {
|
||||
state.payType.push({
|
||||
logoDir: "/static/pay/wechat-pay.jpg",
|
||||
text: "微信支付",
|
||||
desc: "",
|
||||
disabled: false,
|
||||
type: "10",
|
||||
value: "WECHAT"
|
||||
},)
|
||||
}
|
||||
if (v.platformType == "20" && !typeList.includes("20")) {
|
||||
state.payType.push({
|
||||
logoDir: "/static/pay/ali-pay.png",
|
||||
text: "支付宝支付",
|
||||
desc: "10亿用户都在用,真安全,更放心",
|
||||
disabled: false,
|
||||
type: "20",
|
||||
value: "ALI_PAY"
|
||||
},)
|
||||
}
|
||||
}
|
||||
const defaultPayType = state.payType[0].type
|
||||
if (defaultPayType && !state.currentPayType) {
|
||||
state.currentPayType = defaultPayType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const doOpenSelectWalletDrawer = () => {
|
||||
state.visibleSelectWallet = true
|
||||
}
|
||||
|
||||
const selectTargetWalletType = (v: any) => {
|
||||
state.currentSelectWallet = v.walletTypeId
|
||||
state.visibleSelectWallet = false
|
||||
// 重新计算选择钱包
|
||||
const walletPay = state.payType.find(v => v.type == "30")
|
||||
if (walletPay) {
|
||||
walletPay.extra = v
|
||||
}
|
||||
}
|
||||
|
||||
// 充值
|
||||
const doPay = async () => {
|
||||
if (state.currentRecharge == -1) {
|
||||
uni.showToast({ title: "请选择充值金额", icon: "none" })
|
||||
return
|
||||
}
|
||||
if (state.currentPayType == undefined) {
|
||||
uni.showToast({ title: "请选择支付方式", icon: "none" })
|
||||
return
|
||||
}
|
||||
try {
|
||||
uni.showLoading({ title: "充值中...", mask: true })
|
||||
const targetRecharge = state.rechargeList[state.currentRecharge]
|
||||
const targetPayType = state.payType.find(v => v.type == state.currentPayType)
|
||||
if (isEmpty(targetRecharge)) {
|
||||
throw new Error()
|
||||
}
|
||||
// 检查用户是否有支付环境
|
||||
const pRes = await uni.getProvider({ service: 'payment' })
|
||||
const providers = (pRes?.provider ?? []) as string[]
|
||||
if (!providers.length) {
|
||||
throw new Error()
|
||||
}
|
||||
if (targetPayType!.value == "WECHAT") {
|
||||
await disposeWxpay(targetRecharge.id)
|
||||
} else if (targetPayType!.value == "ALI_PAY") {
|
||||
await disposeAlipay(targetRecharge.id)
|
||||
}
|
||||
uni.hideLoading()
|
||||
router.jump("/pages/wallet/recharge-done", { payNo: state.payNo }, 2)
|
||||
} catch (error: any) {
|
||||
console.error("充值意外的错误:", error)
|
||||
uni.hideLoading()
|
||||
if (error?.errMsg && error?.errMsg.includes("requestPayment:fail [paymentAlipay:62009]unknown error")) {
|
||||
uni.showToast({ title: "请先安装支付宝App", icon: "none" })
|
||||
} else if (error?.message) {
|
||||
uni.showToast({ title: error.message, icon: "none" })
|
||||
} else {
|
||||
uni.showToast({ title: "充值失败", icon: "none" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 微信支付
|
||||
const disposeWxpay = async (bizId: any) => {
|
||||
const pRes = await uni.getProvider({ service: 'payment' })
|
||||
const providers = (pRes?.provider ?? []) as string[]
|
||||
if (!providers.length) {
|
||||
throw new Error("微信支付环境错误")
|
||||
}
|
||||
if (!providers.includes("wxpay")) {
|
||||
uni.showToast({ title: "请先安装微信,确保微信支付环境", icon: "none" })
|
||||
return
|
||||
}
|
||||
const payParams: AppPlusPayDto = {
|
||||
bizType: "MINI_APP_WALLET_RECHARGE",
|
||||
bizId: bizId,
|
||||
miniPlatformType: "WECHAT",
|
||||
openId: "",
|
||||
}
|
||||
const { data: createData, code: createCode }: any = await appPlusPlatformApi.miniPay(payParams)
|
||||
console.log("微信支付createData:", createData);
|
||||
if (createCode != 0) {
|
||||
throw new Error(createData?.msg ?? "微信充值发起失败")
|
||||
}
|
||||
state.payNo = createData?.payNo ?? ""
|
||||
const paymentResult = await uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
orderInfo: {
|
||||
"appid": createData?.appPlusPayParams?.appid,
|
||||
"noncestr": createData?.appPlusPayParams?.nonceStr,
|
||||
"package": createData?.appPlusPayParams?.packageVal,
|
||||
"partnerid": createData?.appPlusPayParams?.partnerId,
|
||||
"prepayid": createData?.appPlusPayParams?.prepayId,
|
||||
"timestamp": createData?.appPlusPayParams?.timestamp,
|
||||
"sign": createData?.appPlusPayParams?.sign,
|
||||
},
|
||||
});
|
||||
console.log("微信支付requestPayment返回:", paymentResult);
|
||||
if (paymentResult.errMsg && paymentResult.errMsg.includes("requestPayment:ok")) {
|
||||
uni.showToast({ title: "充值成功", icon: "none" })
|
||||
} else {
|
||||
uni.showToast({ title: "充值失败", icon: "none" })
|
||||
}
|
||||
}
|
||||
|
||||
// 支付宝支付
|
||||
const disposeAlipay = async (bizId: any) => {
|
||||
const pRes = await uni.getProvider({ service: 'payment' })
|
||||
const providers = (pRes?.provider ?? []) as string[]
|
||||
if (!providers.length) {
|
||||
throw new Error("支付宝支付环境错误")
|
||||
}
|
||||
if (!providers.includes("alipay")) {
|
||||
uni.showToast({ title: "请先安装支付宝App,确保支付宝支付环境", icon: "none" })
|
||||
return
|
||||
}
|
||||
const payParams: AppPlusPayDto = {
|
||||
bizType: "MINI_APP_WALLET_RECHARGE",
|
||||
bizId: bizId,
|
||||
miniPlatformType: "ALI_PAY",
|
||||
openId: "",
|
||||
}
|
||||
const { data: createData, code: createCode }: any = await appPlusPlatformApi.miniPay(payParams)
|
||||
if (createCode != 0) {
|
||||
throw new Error(createData?.msg ?? "支付宝充值发起失败")
|
||||
}
|
||||
state.payNo = createData?.payNo ?? ""
|
||||
const paymentResult = await uni.requestPayment({
|
||||
provider: 'alipay',
|
||||
...createData?.appPlusPayParams ?? {},
|
||||
});
|
||||
console.log("支付宝支付requestPayment返回:", paymentResult);
|
||||
if (paymentResult.errMsg && paymentResult.errMsg.includes("requestPayment:ok")) {
|
||||
uni.showToast({ title: "充值成功", icon: "none" })
|
||||
} else {
|
||||
uni.showToast({ title: "充值失败", icon: "none" })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.wallet-border {
|
||||
border: 1rpx solid #f8f8f8;
|
||||
margin: 10rpx 0;
|
||||
}
|
||||
|
||||
.wallet-recharge-empty {
|
||||
padding: 60rpx 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.wallet-recharge-empty__icon {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
margin-bottom: 24rpx;
|
||||
border-radius: 9999rpx;
|
||||
background: #e9f5fe;
|
||||
color: #0094ff;
|
||||
font-size: 42rpx;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@@ -30,7 +30,9 @@ const hardwarePayTypeEnum = {
|
||||
8: "现金支付",
|
||||
9: "智能柜免密支付",
|
||||
10: "微信付款码支付",
|
||||
100: "微信App支付",
|
||||
11: "支付宝付款码支付",
|
||||
110: "支付宝App支付",
|
||||
12: "中医院",
|
||||
13: "人民医院",
|
||||
14: "超市消费卡",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
@font-face {
|
||||
font-family: "iconfont";
|
||||
/* Project id 4740692 */
|
||||
src: url('https://at.alicdn.com/t/c/font_4740692_fg48uzfs38.woff2?t=1782206048581') format('woff2'),
|
||||
url('https://at.alicdn.com/t/c/font_4740692_fg48uzfs38.woff?t=1782206048581') format('woff'),
|
||||
url('https://at.alicdn.com/t/c/font_4740692_fg48uzfs38.ttf?t=1782206048581') format('truetype');
|
||||
src: url('https://at.alicdn.com/t/c/font_4740692_ol93veips6n.woff2?t=1782372215492') format('woff2'),
|
||||
url('https://at.alicdn.com/t/c/font_4740692_ol93veips6n.woff?t=1782372215492') format('woff'),
|
||||
url('https://at.alicdn.com/t/c/font_4740692_ol93veips6n.ttf?t=1782372215492') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@@ -14,6 +14,10 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-jisuwuliu:before {
|
||||
content: "\e61a";
|
||||
}
|
||||
|
||||
.icon-add:before {
|
||||
content: "\e79e";
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ export const useProsperityCartStore = defineStore("prosperityCartStore", {
|
||||
},
|
||||
// 获取购物车商品列表
|
||||
async getShopCart(merchantId: string) {
|
||||
const { data } = await orderApi.getShopCar({ merchantId, hardType: "FARMER" })
|
||||
const { data } = await orderApi.getShopCar({ merchantId, hardType: "SELF_APP" })
|
||||
this.cartList = data ?? []
|
||||
},
|
||||
// 更新购物车商品列表
|
||||
@@ -66,7 +66,7 @@ export const useProsperityCartStore = defineStore("prosperityCartStore", {
|
||||
productId: v.productId,
|
||||
}
|
||||
})
|
||||
const { code }: any = await orderApi.updateShopCar({ merchantId, list, hardType: "FARMER" })
|
||||
const { code }: any = await orderApi.updateShopCar({ merchantId, list, hardType: "SELF_APP" })
|
||||
if (code == 0) return await this.getShopCart(merchantId)
|
||||
uni.showToast({ title: "更新购物车失败", icon: "none" })
|
||||
},
|
||||
|
||||
+19
-12
@@ -1,12 +1,19 @@
|
||||
import { defineStore } from "pinia"
|
||||
|
||||
import STORAGE_KEY from "../constant/storage-constant"
|
||||
import pinia from "./index"
|
||||
import { useTabbarStore } from "./tabbar"
|
||||
|
||||
import merchantApi from "../api/merchant"
|
||||
import userApi from "../api/user"
|
||||
|
||||
const getTabbarStore = async (): Promise<any | null> => {
|
||||
let tabbarStore: any = null
|
||||
// #ifndef APP-NVUE
|
||||
const [{ default: pinia }, { useTabbarStore }] = await Promise.all([import("./index"), import("./tabbar")])
|
||||
tabbarStore = useTabbarStore(pinia)
|
||||
// #endif
|
||||
return tabbarStore
|
||||
}
|
||||
|
||||
type UserInfo = {
|
||||
// 主键ID,后端 Long 在前端统一按 string 处理,避免精度丢失。
|
||||
userId: string
|
||||
@@ -134,10 +141,10 @@ export const useUserStore = defineStore("user", {
|
||||
async disposeLogin() {
|
||||
await this._getUserDetail()
|
||||
await this._getUserZsMch()
|
||||
const tabbarStore = useTabbarStore(pinia)
|
||||
tabbarStore.setMchFunctionScope(this.ZsMch?.functionScope || {})
|
||||
tabbarStore.refreshVisibleTabbar()
|
||||
tabbarStore.syncByCurrentRoute()
|
||||
const tabbarStore = await getTabbarStore()
|
||||
tabbarStore?.setMchFunctionScope(this.ZsMch?.functionScope || {})
|
||||
tabbarStore?.refreshVisibleTabbar()
|
||||
tabbarStore?.syncByCurrentRoute()
|
||||
},
|
||||
// 处理退出登录
|
||||
async disposeLogOut() {
|
||||
@@ -157,10 +164,10 @@ export const useUserStore = defineStore("user", {
|
||||
this.ZsMch = undefined
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: "退出登录成功", icon: "none" })
|
||||
const tabbarStore = useTabbarStore(pinia)
|
||||
tabbarStore.setMchFunctionScope({})
|
||||
tabbarStore.reset()
|
||||
tabbarStore.hideTabbar()
|
||||
const tabbarStore = await getTabbarStore()
|
||||
tabbarStore?.setMchFunctionScope({})
|
||||
tabbarStore?.reset()
|
||||
tabbarStore?.hideTabbar()
|
||||
},
|
||||
// 获取用户详情
|
||||
async _getUserDetail() {
|
||||
@@ -192,8 +199,8 @@ export const useUserStore = defineStore("user", {
|
||||
} else {
|
||||
this.ZsMch = undefined
|
||||
}
|
||||
const tabbarStore = useTabbarStore(pinia)
|
||||
tabbarStore.setMchFunctionScope(this.ZsMch?.functionScope || {})
|
||||
const tabbarStore = await getTabbarStore()
|
||||
tabbarStore?.setMchFunctionScope(this.ZsMch?.functionScope || {})
|
||||
} catch (error) {
|
||||
console.log("获取用户的直属商户,意外的错误error:", error)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 打开外部应用
|
||||
*/
|
||||
|
||||
/**
|
||||
* 打开快递查询页面
|
||||
* @param trackingNo 快递单号
|
||||
* @param companyCode 快递公司
|
||||
* @returns
|
||||
*/
|
||||
export const openExpressTracking = (trackingNo?: string, companyCode?: string) => {
|
||||
if (!trackingNo && !companyCode) {
|
||||
uni.showToast({ title: "缺少快递单号或快递公司", icon: "none" })
|
||||
return
|
||||
}
|
||||
let url = `https://m.kuaidi100.com/app/query/?coname=zax`
|
||||
if (trackingNo) {
|
||||
url += `&nu=${encodeURIComponent(trackingNo)}`
|
||||
}
|
||||
if (companyCode) {
|
||||
url += `&com=${encodeURIComponent(companyCode)}`
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
plus.runtime.openURL(url, () => {
|
||||
uni.showToast({ title: "无法打开物流查询页面", icon: "none" })
|
||||
})
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
window.open(url, "_blank")
|
||||
// #endif
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
import { appPlusPlatformApi, orderApi, type AppPlusPayDto } from "@/sheep/api"
|
||||
|
||||
export abstract class PayTool {
|
||||
// 检查支付环境(如果没有支付环境会提示)
|
||||
abstract checkPayEnv(): Promise<boolean>
|
||||
abstract pay(payParams: any): Promise<boolean>
|
||||
}
|
||||
|
||||
// 微信支付
|
||||
export class WechatPayTool extends PayTool {
|
||||
override async checkPayEnv() {
|
||||
const pRes = await uni.getProvider({ service: "payment" })
|
||||
const providers = (pRes?.provider ?? []) as string[]
|
||||
if (!providers.length) {
|
||||
uni.showToast({ title: "微信支付环境错误", icon: "none" })
|
||||
return false
|
||||
}
|
||||
if (!providers.includes("wxpay")) {
|
||||
uni.showToast({ title: "请先安装微信,确保微信支付环境", icon: "none" })
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
override async pay(payParams: any) {
|
||||
const paymentResult = await uni.requestPayment({
|
||||
provider: "wxpay",
|
||||
orderInfo: {
|
||||
appid: payParams?.appPlusPayParams?.appid,
|
||||
noncestr: payParams?.appPlusPayParams?.nonceStr,
|
||||
package: payParams?.appPlusPayParams?.packageVal,
|
||||
partnerid: payParams?.appPlusPayParams?.partnerId,
|
||||
prepayid: payParams?.appPlusPayParams?.prepayId,
|
||||
timestamp: payParams?.appPlusPayParams?.timestamp,
|
||||
sign: payParams?.appPlusPayParams?.sign,
|
||||
},
|
||||
})
|
||||
if (paymentResult.errMsg && paymentResult.errMsg.includes("requestPayment:ok")) {
|
||||
uni.showToast({ title: "支付成功", icon: "none" })
|
||||
return true
|
||||
} else {
|
||||
uni.showToast({ title: "支付失败", icon: "none" })
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 支付宝支付
|
||||
export class AlipayPayTool extends PayTool {
|
||||
override async checkPayEnv() {
|
||||
const pRes = await uni.getProvider({ service: "payment" })
|
||||
const providers = (pRes?.provider ?? []) as string[]
|
||||
if (!providers.length) {
|
||||
uni.showToast({ title: "支付宝支付环境错误", icon: "none" })
|
||||
return false
|
||||
}
|
||||
if (!providers.includes("alipay")) {
|
||||
uni.showToast({ title: "请先安装支付宝App,确保支付宝支付环境", icon: "none" })
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
override async pay(payParams: any) {
|
||||
const paymentResult = await uni.requestPayment({
|
||||
provider: "alipay",
|
||||
...(payParams?.appPlusPayParams ?? {}),
|
||||
})
|
||||
console.log("支付宝支付requestPayment返回:", paymentResult)
|
||||
if (paymentResult.errMsg && paymentResult.errMsg.includes("requestPayment:ok")) {
|
||||
uni.showToast({ title: "支付成功", icon: "none" })
|
||||
return true
|
||||
} else {
|
||||
uni.showToast({ title: "支付失败", icon: "none" })
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class AggregationPayTool {
|
||||
/**
|
||||
* 充值支付
|
||||
* @param bizId 充值的套餐id
|
||||
* @returns
|
||||
*/
|
||||
static async topupPay(bizId: string, payType: "WECHAT" | "ALI_PAY") {
|
||||
if (!bizId) throw new Error("充值的套餐id不能为空")
|
||||
try {
|
||||
uni.showLoading({ title: "充值中...", mask: true })
|
||||
if (payType == "WECHAT") {
|
||||
const wechatPayTool = new WechatPayTool()
|
||||
const isWechatPayEnv = await wechatPayTool.checkPayEnv()
|
||||
if (!isWechatPayEnv) throw new Error("微信支付环境错误")
|
||||
const payParams: AppPlusPayDto = {
|
||||
bizType: "MINI_APP_WALLET_RECHARGE",
|
||||
bizId: bizId,
|
||||
miniPlatformType: "WECHAT",
|
||||
openId: "",
|
||||
}
|
||||
const { data: createData, code: createCode }: any = await appPlusPlatformApi.miniPay(payParams)
|
||||
console.log("微信支付(充值)createData:", createData)
|
||||
if (createCode != 0) {
|
||||
uni.showToast({ title: createData?.msg ?? "微信充值发起失败", icon: "none" })
|
||||
throw new Error(createData?.msg ?? "微信充值发起失败")
|
||||
}
|
||||
const isPaySuccess = await wechatPayTool.pay(createData)
|
||||
if (isPaySuccess) {
|
||||
return {
|
||||
payNo: createData?.payNo,
|
||||
}
|
||||
}
|
||||
} else if (payType == "ALI_PAY") {
|
||||
const alipayPayTool = new AlipayPayTool()
|
||||
const isAlipayPayEnv = await alipayPayTool.checkPayEnv()
|
||||
if (!isAlipayPayEnv) throw new Error("支付宝支付环境错误")
|
||||
const payParams: AppPlusPayDto = {
|
||||
bizType: "MINI_APP_WALLET_RECHARGE",
|
||||
bizId: bizId,
|
||||
miniPlatformType: "ALI_PAY",
|
||||
openId: "",
|
||||
}
|
||||
const { data: createData, code: createCode }: any = await appPlusPlatformApi.miniPay(payParams)
|
||||
if (createCode != 0) {
|
||||
throw new Error(createData?.msg ?? "支付宝充值发起失败")
|
||||
}
|
||||
const isPaySuccess = await alipayPayTool.pay(createData)
|
||||
if (isPaySuccess) {
|
||||
return {
|
||||
payNo: createData?.payNo,
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("充值意外的错误:", error)
|
||||
uni.hideLoading()
|
||||
if (error?.errMsg && error?.errMsg.includes("requestPayment:fail [paymentAlipay:62009]unknown error")) {
|
||||
uni.showToast({ title: "请先安装支付宝App", icon: "none" })
|
||||
} else if (error?.message) {
|
||||
uni.showToast({ title: error.message, icon: "none" })
|
||||
} else {
|
||||
uni.showToast({ title: "充值失败", icon: "none" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 商城支付(有订单)
|
||||
static async shopPay({
|
||||
parentCarId,
|
||||
mapAddressId,
|
||||
payType,
|
||||
walletTypeId,
|
||||
}: {
|
||||
parentCarId: string
|
||||
mapAddressId: string
|
||||
payType: string
|
||||
walletTypeId?: string
|
||||
}) {
|
||||
if (!["10", "20", "30"].includes(payType)) {
|
||||
uni.showToast({ title: "请选择正确的支付方式", icon: "none" })
|
||||
throw new Error("请选择正确的支付方式")
|
||||
}
|
||||
try {
|
||||
uni.showLoading({ title: "支付中...", mask: true })
|
||||
const createPayParams = {
|
||||
carParentId: parentCarId,
|
||||
mapAddressId,
|
||||
payType,
|
||||
walletTypeId,
|
||||
}
|
||||
const wechatPayTool = new WechatPayTool()
|
||||
const alipayPayTool = new AlipayPayTool()
|
||||
// 微信
|
||||
if (payType == "10") {
|
||||
const isWechatPayEnv = await wechatPayTool.checkPayEnv()
|
||||
if (!isWechatPayEnv) throw new Error("微信支付环境错误")
|
||||
}
|
||||
// 支付宝
|
||||
else if (payType == "20") {
|
||||
const isAlipayPayEnv = await alipayPayTool.checkPayEnv()
|
||||
if (!isAlipayPayEnv) throw new Error("支付宝支付环境错误")
|
||||
}
|
||||
// 钱包
|
||||
else if (payType == "30") {
|
||||
if (!walletTypeId) {
|
||||
uni.showToast({ title: "请选择钱包类型", icon: "none" })
|
||||
throw new Error("请选择钱包类型")
|
||||
}
|
||||
}
|
||||
const {
|
||||
data: createData,
|
||||
code: createCode,
|
||||
msg: createMsg,
|
||||
}: any = await orderApi.appCreateShopReserveOrder({
|
||||
...createPayParams,
|
||||
})
|
||||
console.log("商城支付(创建支付订单)createData:", createData, "createCode:", createCode, "createMsg:", createMsg)
|
||||
if (createCode != 0) {
|
||||
uni.showToast({ title: createMsg ?? "支付发起失败", icon: "none" })
|
||||
throw new Error(createMsg ?? "支付发起失败")
|
||||
}
|
||||
// 微信支付
|
||||
if (payType == "10") {
|
||||
const isPaySuccess = await wechatPayTool.pay(createData)
|
||||
uni.hideLoading()
|
||||
if (isPaySuccess) {
|
||||
return {
|
||||
orderId: createData?.orderId,
|
||||
payNo: createData?.payNo,
|
||||
}
|
||||
}
|
||||
}
|
||||
// 支付宝支付
|
||||
else if (payType == "20") {
|
||||
const isPaySuccess = await alipayPayTool.pay(createData)
|
||||
uni.hideLoading()
|
||||
if (isPaySuccess) {
|
||||
return {
|
||||
orderId: createData?.orderId,
|
||||
payNo: createData?.payNo,
|
||||
}
|
||||
}
|
||||
} else if (payType == "30") {
|
||||
uni.hideLoading()
|
||||
return {
|
||||
orderId: createData?.orderId,
|
||||
payNo: createData?.payNo,
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("支付意外的错误:", error)
|
||||
uni.hideLoading()
|
||||
if (error?.message) {
|
||||
uni.showToast({ title: error.message, icon: "none" })
|
||||
} else {
|
||||
uni.showToast({ title: "充值失败", icon: "none" })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -291,13 +291,13 @@ export default {
|
||||
<template>
|
||||
<view :class="[_disabled ? 'checkboxDisabled' : '']" class="checkbox" @click="boxClick">
|
||||
<view class="checkboxBox" v-if="!hiddenCheckbox" :style="{
|
||||
backgroundColor: _isCheck ? _color : 'transparent',
|
||||
border: `1px solid ${_isCheck ? _color : _unCheckColor}`,
|
||||
width: _size,
|
||||
height: _size
|
||||
}">
|
||||
backgroundColor: _isCheck ? _color : 'transparent',
|
||||
border: `1px solid ${_isCheck ? _color : _unCheckColor}`,
|
||||
width: _size,
|
||||
height: _size
|
||||
}">
|
||||
<view :class="['checkboxBoxIcon', 'checkboxBoxIcon_' + (nowValue ? 'on' : 'off')]">
|
||||
<tm-icon color="white" :name="icon" :size="iconSize"></tm-icon>
|
||||
<tm-icon :color="_isCheck ? 'white' : 'transparent'" :name="icon" :size="iconSize"></tm-icon>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
@@ -7,6 +7,19 @@ import uni from "@dcloudio/vite-plugin-uni"
|
||||
|
||||
import { useRouter } from "./src/sheep/plugs/use-router/vite-router-plug"
|
||||
|
||||
const fixIifeCodeSplitPlugin = () => ({
|
||||
name: "fix-uni-iife-code-splitting",
|
||||
apply: "build" as const,
|
||||
enforce: "post" as const,
|
||||
outputOptions(outputOptions: Record<string, any>) {
|
||||
if (outputOptions.format === "iife" || outputOptions.format === "umd") {
|
||||
delete outputOptions.manualChunks
|
||||
outputOptions.inlineDynamicImports = true
|
||||
}
|
||||
return outputOptions
|
||||
},
|
||||
})
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode }) => {
|
||||
const { NODE_ENV, VITE_APP_DEV_SERVICE, VITE_APP_PROD_SERVICE, VITE_IMAGE_DEV_PATH } = loadEnv(mode, process.cwd(), "")
|
||||
@@ -18,10 +31,14 @@ export default defineConfig(({ mode }) => {
|
||||
return {
|
||||
build: {
|
||||
target: "es6",
|
||||
sourcemap: false,
|
||||
cssCodeSplit: false,
|
||||
reportCompressedSize: false,
|
||||
},
|
||||
plugins: [
|
||||
uni(),
|
||||
Unocss(),
|
||||
fixIifeCodeSplitPlugin(),
|
||||
{
|
||||
...useRouter({
|
||||
pagesJsonDir: path.resolve(__dirname, "./src/pages.json"),
|
||||
|
||||
Reference in new issue
Block a user