diff --git a/config/env.ts b/config/env.ts index aefa726..0a5c838 100644 --- a/config/env.ts +++ b/config/env.ts @@ -2,8 +2,8 @@ export const ENV_CONFIG = { // 开发环境 development: { - // API_BASE_URL: 'http://127.0.0.1:9200/api', - API_BASE_URL: 'https://ysb-api.websoft.top/api', + API_BASE_URL: 'http://127.0.0.1:9200/api', + // API_BASE_URL: 'https://ysb-api.websoft.top/api', APP_NAME: '开发环境', DEBUG: 'true', }, diff --git a/src/api/system/payment/index.ts b/src/api/system/payment/index.ts deleted file mode 100644 index 7ec67a7..0000000 --- a/src/api/system/payment/index.ts +++ /dev/null @@ -1,145 +0,0 @@ -import request from '@/utils/request'; -import type {ApiResult, PageResult} from '@/api/index'; -import type {Payment, PaymentParam} from './model'; -import type {ShopOrder} from '@/api/shop/shopOrder/model'; -import {SERVER_API_URL} from "@/utils/server"; - -/** - * 分页查询支付方式 - */ -export async function pagePayment(params: PaymentParam) { - const res = await request.get>>( - SERVER_API_URL + '/system/payment/page', - params - ); - if (res.code === 0) { - return res.data; - } - return Promise.reject(new Error(res.message)); -} - -/** - * 查询支付方式列表 - */ -export async function listPayment(params?: PaymentParam) { - const res = await request.get>( - SERVER_API_URL + '/system/payment', - params - ); - if (res.code === 0 && res.data) { - return res.data; - } - return Promise.reject(new Error(res.message)); -} - -/** - * 添加支付方式 - */ -export async function addPayment(data: Payment) { - const res = await request.post>( - SERVER_API_URL + '/system/payment', - data - ); - if (res.code === 0) { - return res.message; - } - return Promise.reject(new Error(res.message)); -} - -/** - * 修改支付方式 - */ -export async function updatePayment(data: Payment) { - const res = await request.put>( - SERVER_API_URL + '/system/payment', - data - ); - if (res.code === 0) { - return res.message; - } - return Promise.reject(new Error(res.message)); -} - -/** - * 删除支付方式 - */ -export async function removePayment(id?: number) { - const res = await request.del>( - SERVER_API_URL + '/system/payment/' + id - ); - if (res.code === 0) { - return res.message; - } - return Promise.reject(new Error(res.message)); -} - -/** - * 批量删除支付方式 - */ -export async function removeBatchPayment(data: (number | undefined)[]) { - const res = await request.del>( - SERVER_API_URL + '/system/payment/batch', - { - data - } - ); - if (res.code === 0) { - return res.message; - } - return Promise.reject(new Error(res.message)); -} - -/** - * 根据id查询支付方式 - */ -export async function getPayment(id: number) { - const res = await request.get>( - SERVER_API_URL + '/system/payment/' + id - ); - if (res.code === 0 && res.data) { - return res.data; - } - return Promise.reject(new Error(res.message)); -} - -/** - * 生成支付二维码(微信native) - */ -export async function getNativeCode(data: ShopOrder) { - const res = await request.post>( - SERVER_API_URL + '/system/wx-native-pay/codeUrl', - data - ); - if (res.code === 0) { - return res.data; - } - return Promise.reject(new Error(res.message)); -} - -/** - * 使用余额支付 - */ -export async function payByBalance(data: ShopOrder) { - const res = await request.post>( - SERVER_API_URL + '/system/payment/balancePay', - data - ); - if (res.code === 0) { - return res.message; - } - return Promise.reject(new Error(res.message)); -} - -/** - * 选择支付方式 - */ -export async function selectPayment(params?: PaymentParam) { - const res = await request.get>( - SERVER_API_URL + '/system/payment/select', - params - ); - if (res.code === 0) { - return res.data; - } - return Promise.reject(new Error(res.message)); -} diff --git a/src/api/system/payment/model/index.ts b/src/api/system/payment/model/index.ts deleted file mode 100644 index 6a4ecfe..0000000 --- a/src/api/system/payment/model/index.ts +++ /dev/null @@ -1,55 +0,0 @@ -import type { PageParam } from '@/api/index'; - -/** - * 支付方式 - */ -export interface Payment { - // ID - id?: number; - // 支付方式 - name?: string; - // 支付类型 - type?: number; - // 标识 - code?: string; - // 支付图标 - image?: string; - // 微信商户号类型 1普通商户2子商户 - wechatType?: number; - // 应用ID - appId?: string; - // 商户号 - mchId?: string; - // 设置APIv3密钥 - apiKey?: string; - // 证书文件 (CERT) - apiclientCert?: string; - // 证书文件 (KEY) - apiclientKey?: string; - // 商户证书序列号 - merchantSerialNumber?: string; - // 支付结果通过 - notifyUrl?: string; - // 备注 - comments?: string; - // 文章排序(数字越小越靠前) - sortNumber?: number; - // 状态, 0启用, 1禁用 - status?: boolean; - // 是否删除, 0否, 1是 - deleted?: number; - // 租户id - tenantId?: number; - // 注册时间 - createTime?: string; - // 修改时间 - updateTime?: string; -} - -/** - * 支付方式搜索条件 - */ -export interface PaymentParam extends PageParam { - id?: number; - keywords?: string; -} diff --git a/src/components/GoodsList.tsx b/src/components/GoodsList.tsx deleted file mode 100644 index 3777b6a..0000000 --- a/src/components/GoodsList.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import {Avatar, Cell, Space, Tabs, Button, TabPane, Swiper} from '@nutui/nutui-react-taro' -import {useEffect, useState, CSSProperties, useRef} from "react"; -import {BszxPay} from "@/api/bszx/bszxPay/model"; -import {InfiniteLoading} from '@nutui/nutui-react-taro' -import dayjs from "dayjs"; -import {pageShopOrder} from "@/api/shop/shopOrder"; -import {ShopOrder} from "@/api/shop/shopOrder/model"; -import {copyText} from "@/utils/common"; - -const InfiniteUlStyle: CSSProperties = { - marginTop: '84px', - height: '82vh', - width: '100%', - padding: '0', - overflowY: 'auto', - overflowX: 'hidden', -} -const tabs = [ - { - index: 0, - key: '全部', - title: '全部' - }, - { - index: 1, - key: '已上架', - title: '已上架' - }, - { - index: 2, - key: '已下架', - title: '已下架' - }, - { - index: 3, - key: '已售罄', - title: '已售罄' - }, - { - index: 4, - key: '警戒库存', - title: '警戒库存' - }, - { - index: 5, - key: '回收站', - title: '回收站' - }, -] - -function GoodsList(props: any) { - const [list, setList] = useState([]) - const [page, setPage] = useState(1) - const [hasMore, setHasMore] = useState(true) - const swiperRef = useRef | null>(null) - const [tabIndex, setTabIndex] = useState(0) - - console.log(props.statusBarHeight, 'ppp') - const reload = async () => { - pageShopOrder({page}).then(res => { - let newList: BszxPay[] | undefined = [] - if (res?.list && res?.list.length > 0) { - newList = list?.concat(res.list) - setHasMore(true) - } else { - newList = res?.list - setHasMore(false) - } - setList(newList || []); - }) - } - - const reloadMore = async () => { - setPage(page + 1) - reload().then(); - } - - useEffect(() => { - setPage(2) - reload().then() - }, []) - - return ( - <> - { - swiperRef.current?.to(page) - setTabIndex(page) - }} - > - { - tabs?.map((item, index) => { - return - }) - } - -
- { - - }} - onScrollToUpper={() => { - - }} - loadingText={ - <> - 加载中 - - } - loadMoreText={ - <> - 没有更多了 - - } - > - {list?.map(item => { - return ( - - -
- copyText(`${item.orderNo}`)}>{item.orderNo} - 待付款 -
-
{dayjs(item.createTime).format('YYYY年MM月DD日 HH:mm:ss')}
-
-
-
- -
{item.realName}
-
-
{item.totalNum}件商品
-
-
-
实付金额:¥{item.payPrice}
- - - - -
-
- ) - })} -
-
- - ) -} - -export default GoodsList diff --git a/src/components/OrderList.tsx b/src/components/OrderList.tsx deleted file mode 100644 index de058a7..0000000 --- a/src/components/OrderList.tsx +++ /dev/null @@ -1,181 +0,0 @@ -import {Avatar, Cell, Space, Tabs, Button, TabPane} from '@nutui/nutui-react-taro' -import {useEffect, useState, CSSProperties} from "react"; -import Taro from '@tarojs/taro'; -import {InfiniteLoading} from '@nutui/nutui-react-taro' -import dayjs from "dayjs"; -import {pageShopOrder} from "@/api/shop/shopOrder"; -import {ShopOrder} from "@/api/shop/shopOrder/model"; -import {copyText} from "@/utils/common"; - -const InfiniteUlStyle: CSSProperties = { - marginTop: '84px', - height: '82vh', - width: '100%', - padding: '0', - overflowY: 'auto', - overflowX: 'hidden', -} -const tabs = [ - { - index: 0, - key: '全部', - title: '全部' - }, - { - index: 1, - key: '待付款', - title: '待付款' - }, - { - index: 2, - key: '待发货', - title: '待发货' - }, - { - index: 3, - key: '已收货', - title: '已收货' - }, - { - index: 4, - key: '已完成', - title: '已完成' - } -] - -function OrderList(props: any) { - const [list, setList] = useState([]) - const [page, setPage] = useState(1) - const [hasMore, setHasMore] = useState(true) - const [tapIndex, setTapIndex] = useState('0') - - console.log(props.statusBarHeight, 'ppp') - - const getOrderStatusParams = (index: string | number) => { - let params: { payStatus?: number; deliveryStatus?: number; orderStatus?: number } = {}; - switch (index) { - case '1': // 待付款 - params.payStatus = 0; - break; - case '2': // 待发货 - params.payStatus = 1; - params.deliveryStatus = 10; - break; - case '3': // 已收货 - params.deliveryStatus = 30; - break; - case '4': // 已完成 - params.orderStatus = 1; - break; - case '0': // 全部 - default: - break; - } - return params; - }; - - const reload = async (resetPage = false) => { - const currentPage = resetPage ? 1 : page; - const params = getOrderStatusParams(tapIndex); - pageShopOrder({ page: currentPage, ...params }).then(res => { - let newList: ShopOrder[] | undefined = []; - if (res?.list && res?.list.length > 0) { - newList = resetPage ? res.list : list?.concat(res.list); - setHasMore(true); - } else { - newList = res?.list; - setHasMore(false); - } - setList(newList || []); - setPage(currentPage); - }); - }; - - const reloadMore = async () => { - setPage(page + 1); - reload(); - }; - - useEffect(() => { - reload(true); // 首次加载或tab切换时重置页码 - }, [tapIndex]); // 监听tapIndex变化 - - return ( - <> - { - setTapIndex(paneKey) - }} - > - { - tabs?.map((item, index) => { - return - }) - } - -
- { - - }} - onScrollToUpper={() => { - - }} - loadingText={ - <> - 加载中 - - } - loadMoreText={ - <> - 没有更多了 - - } - > - {list?.map(item => { - return ( - Taro.navigateTo({url: `/shop/orderDetail/index?orderId=${item.orderId}`})}> - -
- {e.stopPropagation(); copyText(`${item.orderNo}`)}}>{item.orderNo} - 待付款 {/* 这里可以根据item.orderStatus显示不同的状态 */} -
-
{dayjs(item.createTime).format('YYYY年MM月DD日 HH:mm:ss')}
-
-
-
- -
{item.realName}
-
-
{item.totalNum}件商品
-
-
-
实付金额:¥{item.payPrice}
- - - -
-
- ) - })} -
-
- - ) -} - -export default OrderList diff --git a/src/components/SpecSelector/index.scss b/src/components/SpecSelector/index.scss deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/SpecSelector/index.tsx b/src/components/SpecSelector/index.tsx deleted file mode 100644 index ee6cf3c..0000000 --- a/src/components/SpecSelector/index.tsx +++ /dev/null @@ -1,176 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { View } from '@tarojs/components'; -import { Popup, Button, Radio, Image, Space, Cell, CellGroup } from '@nutui/nutui-react-taro'; -import { ShopGoodsSku } from '@/api/shop/shopGoodsSku/model'; -import { ShopGoodsSpec } from '@/api/shop/shopGoodsSpec/model'; -import { ShopGoods } from '@/api/shop/shopGoods/model'; -import './index.scss'; - -interface SpecSelectorProps { - visible?: boolean; - onClose: () => void; - goods: ShopGoods; - specs: ShopGoodsSpec[]; - skus: ShopGoodsSku[]; - onConfirm: (selectedSku: ShopGoodsSku, quantity: number, action?: 'cart' | 'buy') => void; - action?: 'cart' | 'buy'; -} - -interface SpecGroup { - specName: string; - values: string[]; -} - -const SpecSelector: React.FC = ({ - visible = true, - onClose, - goods, - specs, - skus, - onConfirm, - action = 'cart' -}) => { - const [selectedSpecs, setSelectedSpecs] = useState>({}); - const [selectedSku, setSelectedSku] = useState(null); - const [quantity, setQuantity] = useState(1); - const [specGroups, setSpecGroups] = useState([]); - - // 组织规格数据 - useEffect(() => { - if (specs.length > 0) { - const groups: Record> = {}; - - specs.forEach(spec => { - if (spec.specName && spec.specValue) { - if (!groups[spec.specName]) { - groups[spec.specName] = new Set(); - } - groups[spec.specName].add(spec.specValue); - } - }); - - const groupsArray = Object.entries(groups).map(([specName, values]) => ({ - specName, - values: Array.from(values) - })); - - setSpecGroups(groupsArray); - } - }, [specs]); - - // 根据选中规格找到对应SKU - useEffect(() => { - if (Object.keys(selectedSpecs).length === specGroups.length && skus.length > 0) { - // 构建规格值字符串,按照规格名称排序确保一致性 - const sortedSpecNames = specGroups.map(g => g.specName).sort(); - const specValues = sortedSpecNames.map(name => selectedSpecs[name]).join('|'); - - const sku = skus.find(s => s.sku === specValues); - setSelectedSku(sku || null); - } else { - setSelectedSku(null); - } - }, [selectedSpecs, skus, specGroups]); - - // 选择规格值 - // const handleSpecSelect = (specName: string, specValue: string) => { - // setSelectedSpecs(prev => ({ - // ...prev, - // [specName]: specValue - // })); - // }; - - // 确认选择 - const handleConfirm = () => { - if (!selectedSku) { - return; - } - onConfirm(selectedSku, quantity, action); - }; - - // 检查规格值是否可选(是否有对应的SKU且有库存) - // const isSpecValueAvailable = (specName: string, specValue: string) => { - // const testSpecs = { ...selectedSpecs, [specName]: specValue }; - // - // // 如果还有其他规格未选择,则认为可选 - // if (Object.keys(testSpecs).length < specGroups.length) { - // return true; - // } - // - // // 构建规格值字符串 - // const sortedSpecNames = specGroups.map(g => g.specName).sort(); - // const specValues = sortedSpecNames.map(name => testSpecs[name]).join('|'); - // - // const sku = skus.find(s => s.sku === specValues); - // return sku && sku.stock && sku.stock > 0 && sku.status === 0; - // }; - - return ( - - - {/* 商品信息 */} - - - - - {goods.name} - - ¥{selectedSku?.price || goods.price} - - - 库存:{selectedSku?.stock || goods.stock} - - - - - - {/* 规格选择 */} - - - - 套餐 - - - 选项1 - - - 选项2 - - - 选项3 - - - - - - {/* 底部按钮 */} - - - - - - - - ); -}; - -export default SpecSelector; diff --git a/src/components/UnifiedQRButton.tsx b/src/components/UnifiedQRButton.tsx index 6519ec9..ede3c6d 100644 --- a/src/components/UnifiedQRButton.tsx +++ b/src/components/UnifiedQRButton.tsx @@ -3,7 +3,7 @@ import { Button } from '@nutui/nutui-react-taro'; import { View } from '@tarojs/components'; import { Scan } from '@nutui/icons-react-taro'; import Taro from '@tarojs/taro'; -import { useUnifiedQRScan, ScanType, type UnifiedScanResult } from '@/hooks/useUnifiedQRScan'; +import { useUnifiedQRScan, type UnifiedScanResult } from '@/hooks/useUnifiedQRScan'; export interface UnifiedQRButtonProps { /** 按钮类型 */ @@ -26,7 +26,7 @@ export interface UnifiedQRButtonProps { /** * 统一扫码按钮组件 - * 支持登录和核销两种类型的二维码扫描 + * 支持登录二维码扫描 */ const UnifiedQRButton: React.FC = ({ type = 'danger', @@ -61,22 +61,6 @@ const UnifiedQRButton: React.FC = ({ const scanResult = await startScan(); if (scanResult) { onSuccess?.(scanResult); - - // 根据扫码类型给出不同的后续提示 - if (scanResult.type === ScanType.VERIFICATION) { - // 核销成功后可以继续扫码 - setTimeout(() => { - Taro.showModal({ - title: '核销成功', - content: '是否继续扫码核销其他水票/礼品卡?', - success: (res) => { - if (res.confirm) { - handleClick(); // 递归调用继续扫码 - } - } - }); - }, 2000); - } } } catch (error: any) { onError?.(error.message || '扫码失败'); diff --git a/src/hooks/useDealerApply.ts b/src/hooks/useDealerApply.ts deleted file mode 100644 index be0c7c5..0000000 --- a/src/hooks/useDealerApply.ts +++ /dev/null @@ -1,81 +0,0 @@ -import {useState, useEffect, useCallback} from 'react' -import Taro from '@tarojs/taro' -import {getShopDealerApply} from '@/api/shop/shopDealerApply' -import type {ShopDealerApply} from '@/api/shop/shopDealerApply/model' - -// Hook 返回值接口 -export interface UseDealerApplyReturn { - // 经销商用户信息 - dealerApply: ShopDealerApply | null - // 加载状态 - loading: boolean - // 错误信息 - error: string | null - // 刷新数据 - refresh: () => Promise -} - - -/** - * 经销商用户 Hook - 简化版本 - * 只查询经销商用户信息和判断是否存在 - */ -export const useDealerApply = (): UseDealerApplyReturn => { - const [dealerApply, setDealerApply] = useState(null) - const [loading, setLoading] = useState(false) - const [error, setError] = useState(null) - - const userId = Taro.getStorageSync('UserId'); - - // 获取经销商用户数据 - const fetchDealerData = useCallback(async () => { - - if (!userId) { - console.log('🔍 用户未登录,提前返回') - setDealerApply(null) - return - } - - try { - setLoading(true) - setError(null) - - // 查询当前用户的经销商信息 - const dealer = await getShopDealerApply(userId) - - if (dealer) { - setDealerApply(dealer) - } else { - setDealerApply(null) - } - } catch (err) { - const errorMessage = err instanceof Error ? err.message : '获取经销商信息失败' - setError(errorMessage) - setDealerApply(null) - } finally { - setLoading(false) - } - }, [userId]) - - // 刷新数据 - const refresh = useCallback(async () => { - await fetchDealerData() - }, [fetchDealerData]) - - // 初始化加载数据 - useEffect(() => { - if (userId) { - console.log('🔍 调用 fetchDealerData') - fetchDealerData() - } else { - console.log('🔍 用户ID不存在,不调用 fetchDealerData') - } - }, [fetchDealerData, userId]) - - return { - dealerApply, - loading, - error, - refresh - } -} diff --git a/src/hooks/useDealerUser.ts b/src/hooks/useDealerUser.ts deleted file mode 100644 index 3195eb6..0000000 --- a/src/hooks/useDealerUser.ts +++ /dev/null @@ -1,102 +0,0 @@ -import {useState, useEffect, useCallback} from 'react' -import Taro, { useDidShow } from '@tarojs/taro' -import {getShopDealerUser} from '@/api/shop/shopDealerUser' -import type {ShopDealerUser} from '@/api/shop/shopDealerUser/model' - -// Hook 返回值接口 -export interface UseDealerUserReturn { - // 经销商用户信息 - dealerUser: ShopDealerUser | null - // 加载状态 - loading: boolean - // 错误信息 - error: string | null - // 刷新数据 - refresh: () => Promise -} - - -/** - * 经销商用户 Hook - 简化版本 - * 只查询经销商用户信息和判断是否存在 - */ -export const useDealerUser = (): UseDealerUserReturn => { - const [dealerUser, setDealerUser] = useState(null) - const rawUserId = Taro.getStorageSync('UserId') - const userId = Number(rawUserId) - const hasUser = Number.isFinite(userId) && userId > 0 - - // If user is logged in, start in loading state to avoid "click too fast" mis-routing. - const [loading, setLoading] = useState(hasUser) - const [error, setError] = useState(null) - - // 获取经销商用户数据 - const fetchDealerData = useCallback(async () => { - - if (!hasUser) { - setDealerUser(null) - setLoading(false) - return - } - - try { - setLoading(true) - setError(null) - - // 查询当前用户的经销商信息 - const dealer = await getShopDealerUser(userId) - - if (dealer) { - setDealerUser(dealer) - } else { - setDealerUser(null) - } - } catch (err) { - const errorMessage = err instanceof Error ? err.message : '获取经销商信息失败' - setError(errorMessage) - setDealerUser(null) - } finally { - setLoading(false) - } - }, [hasUser, userId]) - - // 刷新数据 - const refresh = useCallback(async () => { - await fetchDealerData() - }, [fetchDealerData]) - - // 初始化加载数据 - useEffect(() => { - if (hasUser) { - fetchDealerData() - } else { - setDealerUser(null) - setError(null) - setLoading(false) - } - }, [fetchDealerData, hasUser]) - - // 页面返回/切换到前台时刷新一次,避免“注册成为经销商后,页面不更新” - useDidShow(() => { - fetchDealerData() - }) - - // 允许业务侧通过事件主动触发刷新(例如:注册成功后触发) - useEffect(() => { - const handler = () => { - fetchDealerData() - } - // 事件名尽量语义化;后续可在注册成功处 trigger - Taro.eventCenter.on('dealerUser:changed', handler) - return () => { - Taro.eventCenter.off('dealerUser:changed', handler) - } - }, [fetchDealerData]) - - return { - dealerUser, - loading, - error, - refresh - } -} diff --git a/src/hooks/useUnifiedQRScan.ts b/src/hooks/useUnifiedQRScan.ts index f2a2b8d..e5d43e6 100644 --- a/src/hooks/useUnifiedQRScan.ts +++ b/src/hooks/useUnifiedQRScan.ts @@ -4,11 +4,6 @@ import { confirmWechatQRLogin, parseQRContent } from '@/api/passport/qr-login'; -import { getShopGiftByCode, updateShopGift, decryptQrData } from "@/api/shop/shopGift"; -import { getGltUserTicket, updateGltUserTicket } from '@/api/glt/gltUserTicket'; -import { useUser } from "@/hooks/useUser"; -import { isValidJSON } from "@/utils/jsonUtils"; -import dayjs from 'dayjs'; /** * 统一扫码状态 @@ -26,19 +21,9 @@ export enum UnifiedScanState { */ export enum ScanType { LOGIN = 'login', // 登录二维码 - VERIFICATION = 'verification', // 核销二维码 UNKNOWN = 'unknown' // 未知类型 } -type VerificationBusinessType = 'gift' | 'ticket'; - -interface TicketVerificationPayload { - userTicketId: number; - qty?: number; - userId?: number; - t?: number; -} - /** * 统一扫码结果 */ @@ -50,10 +35,9 @@ export interface UnifiedScanResult { /** * 统一扫码Hook - * 可以处理登录和核销两种类型的二维码 + * 用于处理登录二维码 */ export function useUnifiedQRScan() { - const { isAdmin } = useUser(); const [state, setState] = useState(UnifiedScanState.IDLE); const [error, setError] = useState(''); const [result, setResult] = useState(null); @@ -80,29 +64,12 @@ export function useUnifiedQRScan() { */ const detectScanType = useCallback((scanResult: string): ScanType => { try { - // 1. 检查是否为JSON格式(核销二维码) - if (isValidJSON(scanResult)) { - const json = JSON.parse(scanResult); - if ((json.businessType === 'gift' || json.businessType === 'ticket') && json.token && json.data) { - return ScanType.VERIFICATION; - } - // Allow plaintext (non-encrypted) ticket verification payload for debugging/internal use. - if (json.userTicketId) { - return ScanType.VERIFICATION; - } - } - - // 2. 检查是否为登录二维码 + // 检查是否为登录二维码 const loginToken = parseQRContent(scanResult); if (loginToken) { return ScanType.LOGIN; } - // 3. 检查是否为纯文本核销码(6位数字) - if (/^\d{6}$/.test(scanResult.trim())) { - return ScanType.VERIFICATION; - } - return ScanType.UNKNOWN; } catch (error) { console.error('检测二维码类型失败:', error); @@ -136,120 +103,6 @@ export function useUnifiedQRScan() { } }, []); - /** - * 处理核销二维码 - */ - const handleVerificationQR = useCallback(async (scanResult: string): Promise => { - if (!isAdmin()) { - throw new Error('您没有核销权限'); - } - - let businessType: VerificationBusinessType = 'gift'; - let decryptedOrRaw = ''; - - // 判断是否为加密的JSON格式 - if (isValidJSON(scanResult)) { - const json = JSON.parse(scanResult); - if ((json.businessType === 'gift' || json.businessType === 'ticket') && json.token && json.data) { - businessType = json.businessType; - // 解密获取核销内容 - const decryptedData = await decryptQrData({ - token: json.token, - encryptedData: json.data - }); - - if (decryptedData) { - decryptedOrRaw = decryptedData.toString(); - } else { - throw new Error('解密失败'); - } - } else if (json.userTicketId) { - businessType = 'ticket'; - decryptedOrRaw = scanResult.trim(); - } - } else { - // 直接使用扫码结果作为核销内容 - decryptedOrRaw = scanResult.trim(); - } - - if (!decryptedOrRaw) { - throw new Error('无法获取有效的核销码'); - } - - if (businessType === 'ticket') { - if (!isValidJSON(decryptedOrRaw)) { - throw new Error('水票核销信息格式错误'); - } - const payload = JSON.parse(decryptedOrRaw) as TicketVerificationPayload; - const userTicketId = Number(payload.userTicketId); - const qty = Math.max(1, Number(payload.qty || 1)); - if (!Number.isFinite(userTicketId) || userTicketId <= 0) { - throw new Error('水票核销信息无效'); - } - - const ticket = await getGltUserTicket(userTicketId); - if (!ticket) throw new Error('水票不存在'); - if (ticket.status === 1) throw new Error('该水票已冻结'); - const available = Number(ticket.availableQty || 0); - const used = Number(ticket.usedQty || 0); - if (available < qty) throw new Error('水票可用次数不足'); - - await updateGltUserTicket({ - ...ticket, - availableQty: available - qty, - usedQty: used + qty - }); - - return { - type: ScanType.VERIFICATION, - data: { - businessType: 'ticket', - ticket: { - ...ticket, - availableQty: available - qty, - usedQty: used + qty - }, - qty - }, - message: `核销成功(已使用${qty}次)` - }; - } - - // 验证礼品卡核销码 - const gift = await getShopGiftByCode(decryptedOrRaw); - - if (!gift) { - throw new Error('核销码无效'); - } - - if (gift.status === 1) { - throw new Error('此礼品码已使用'); - } - - if (gift.status === 2) { - throw new Error('此礼品码已失效'); - } - - if (gift.userId === 0) { - throw new Error('此礼品码未认领'); - } - - // 执行核销 - await updateShopGift({ - ...gift, - status: 1, - operatorUserId: Number(Taro.getStorageSync('UserId')) || 0, - takeTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), - verificationTime: dayjs().format('YYYY-MM-DD HH:mm:ss') - }); - - return { - type: ScanType.VERIFICATION, - data: { businessType: 'gift', gift }, - message: '核销成功' - }; - }, [isAdmin]); - /** * 开始扫码 */ @@ -306,9 +159,6 @@ export function useUnifiedQRScan() { case ScanType.LOGIN: result = await handleLoginQR(scanResult); break; - case ScanType.VERIFICATION: - result = await handleVerificationQR(scanResult); - break; default: throw new Error('未知的扫码类型'); } @@ -351,7 +201,7 @@ export function useUnifiedQRScan() { } finally { setIsLoading(false); } - }, [reset, detectScanType, handleLoginQR, handleVerificationQR]); + }, [reset, detectScanType, handleLoginQR]); /** * 取消扫码 diff --git a/src/pages/user/components/UserCard.tsx b/src/pages/user/components/UserCard.tsx index bf60c54..c1dc705 100644 --- a/src/pages/user/components/UserCard.tsx +++ b/src/pages/user/components/UserCard.tsx @@ -2,6 +2,7 @@ import {Avatar, Tag, Space, Button} from '@nutui/nutui-react-taro' import {View, Text} from '@tarojs/components' import {getUserInfo, getWxOpenId} from '@/api/layout'; import Taro from '@tarojs/taro'; +import {SERVER_API_URL} from "@/utils/server"; import {useEffect, useState, forwardRef, useImperativeHandle} from "react"; import {User} from "@/api/system/user/model"; import navTo from "@/utils/common"; @@ -177,7 +178,7 @@ const UserCard = forwardRef((_, ref) => { success: function () { if (code) { Taro.request({ - url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone', + url: SERVER_API_URL + '/wx-login/loginByMpWxPhone', method: 'POST', data: { code, diff --git a/src/passport/register.tsx b/src/passport/register.tsx index 027b07a..0da98c7 100644 --- a/src/passport/register.tsx +++ b/src/passport/register.tsx @@ -3,7 +3,7 @@ import Taro from '@tarojs/taro' import { Button, Radio } from '@nutui/nutui-react-taro' import { TenantId } from '@/config/app' import { getUserInfo, getWxOpenId } from '@/api/layout' -import { saveStorageByLoginUser } from '@/utils/server' +import {saveStorageByLoginUser, SERVER_API_URL} from '@/utils/server' import { getStoredInviteParams, parseInviteParams, @@ -171,7 +171,7 @@ const Register = () => { const wxLoginCode = await getWeappLoginCode() const res = (await Taro.request({ - url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone', + url: SERVER_API_URL + '/wx-login/loginByMpWxPhone', method: 'POST', data: { code: phoneCode, diff --git a/src/passport/unified-qr/index.tsx b/src/passport/unified-qr/index.tsx index be5cda1..b3dca15 100644 --- a/src/passport/unified-qr/index.tsx +++ b/src/passport/unified-qr/index.tsx @@ -7,7 +7,7 @@ import { useUnifiedQRScan, ScanType, type UnifiedScanResult } from '@/hooks/useU /** * 统一扫码页面 - * 支持登录和核销两种类型的二维码扫描 + * 支持登录二维码扫描 */ const UnifiedQRPage: React.FC = () => { const [scanHistory, setScanHistory] = useState([]); @@ -36,22 +36,6 @@ const UnifiedQRPage: React.FC = () => { success: true }; setScanHistory(prev => [newRecord, ...prev.slice(0, 4)]); // 只保留最近5条记录 - - // 根据类型给出不同提示 - if (result.type === ScanType.VERIFICATION) { - // 核销成功后询问是否继续扫码 - setTimeout(() => { - Taro.showModal({ - title: '核销成功', - content: '是否继续扫码核销其他水票/礼品卡?', - success: (res) => { - if (res.confirm) { - handleStartScan(); - } - } - }); - }, 2000); - } }; // 处理扫码失败 @@ -100,8 +84,6 @@ const UnifiedQRPage: React.FC = () => { switch (type) { case ScanType.LOGIN: return 登录; - case ScanType.VERIFICATION: - return 核销; default: return 未知; } @@ -119,7 +101,7 @@ const UnifiedQRPage: React.FC = () => { 统一扫码 - 支持登录和核销功能 + 支持扫码登录确认 @@ -135,7 +117,7 @@ const UnifiedQRPage: React.FC = () => { 智能扫码 - 自动识别登录和核销二维码 + 自动识别登录二维码