From 07cf8e884e249d3ce35fd141b3a87b807beed995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Sat, 7 Feb 2026 20:24:45 +0800 Subject: [PATCH 01/12] 1 --- src/config/env.ts | 135 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 src/config/env.ts diff --git a/src/config/env.ts b/src/config/env.ts new file mode 100644 index 0000000..5fd7f75 --- /dev/null +++ b/src/config/env.ts @@ -0,0 +1,135 @@ +import Taro from '@tarojs/taro' + +// 环境类型 +export type EnvType = 'development' | 'production' + +// 环境配置接口 +export interface EnvConfig { + name: string + apiBaseURL: string + ossBaseURL: string + timeout: number + enableLog: boolean + enableMock: boolean + // 客服配置 + customerService: { + corpId: string + serviceUrl: string + phoneNumber?: string + email?: string + } +} + +// 各环境配置 +const envConfigs: Record = { + + + // 开发环境 + development: { + name: '开发环境', + apiBaseURL: 'https://tennis.bimwe.com', + ossBaseURL: 'https://bimwe.oss-cn-shanghai.aliyuncs.com', + //apiBaseURL: 'http://localhost:9098', + timeout: 15000, + enableLog: true, + enableMock: false, + // 客服配置 + customerService: { + corpId: 'ww51fc969e8b76af82', // 企业ID + serviceUrl: 'https://work.weixin.qq.com/kfid/kfc64085b93243c5c91', + + } + }, + + + + + + + + // 生产环境1 + production: { + name: '生产环境1', + apiBaseURL: 'https://tennis.bimwe.com', + ossBaseURL: 'https://bimwe.oss-cn-shanghai.aliyuncs.com', + timeout: 10000, + enableLog: false, + enableMock: false, + // 客服配置 + customerService: { + corpId: 'ww51fc969e8b76af82', // 企业ID + serviceUrl: 'https://work.weixin.qq.com/kfid/kfc64085b93243c5c91', + + } + }, + + //生产环境2 + // production: { + // name: '生产环境2', + // apiBaseURL: 'https://youchang.qiongjingtiyu.com', + // ossBaseURL: 'https://youchang2026.oss-cn-shanghai.aliyuncs.com', + // timeout: 10000, + // enableLog: false, + // enableMock: false, + // // 客服配置 + // customerService: { + // corpId: 'ww9a2d9a5d9410c664', // 企业ID + // serviceUrl: 'https://work.weixin.qq.com/kfid/kfcd355e162e0390684', + // } + // } +} + +// 获取当前环境 +export const getCurrentEnv = (): EnvType => { + // 在小程序环境中,使用默认逻辑判断环境 + // 可以根据实际需要配置不同的判断逻辑 + + // 可以根据实际部署情况添加更多判断逻辑 + // 比如通过 Taro.getEnv() 获取当前平台环境 + + const isProd = process.env.NODE_ENV === 'production' + if (isProd) { + return 'production' + } else { + return 'development' + } +} + +// 获取当前环境配置 +export const getCurrentConfig = (): EnvConfig => { + const env = getCurrentEnv() + return envConfigs[env] +} + +// 获取指定环境配置 +export const getEnvConfig = (env: EnvType): EnvConfig => { + return envConfigs[env] +} + +// 是否为开发环境 +export const isDevelopment = (): boolean => { + return getCurrentEnv() === 'development' +} + +// 是否为生产环境 +export const isProduction = (): boolean => { + return getCurrentEnv() === 'production' +} + + + +// 环境配置调试信息 +export const getEnvInfo = () => { + const config = getCurrentConfig() + return { + env: getCurrentEnv(), + config, + taroEnv: Taro.getEnv(), + platform: Taro.getEnv() === Taro.ENV_TYPE.WEAPP ? '微信小程序' : + Taro.getEnv() === Taro.ENV_TYPE.WEB ? 'Web' : + Taro.getEnv() === Taro.ENV_TYPE.RN ? 'React Native' : '未知' + } +} + +// 导出当前环境配置(方便直接使用) +export default getCurrentConfig() \ No newline at end of file From 5146894d92e1e57887b0f18d8a976a470464a9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=88=90?= Date: Sat, 7 Feb 2026 20:24:49 +0800 Subject: [PATCH 02/12] 1 --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ddaf3df..ebe3e16 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ node_modules/ src/config/env.ts .vscode *.http -env.ts + From 744169fe34cfb3ad9a59e7fa77bb370e6add03f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=91=9E?= Date: Sat, 7 Feb 2026 22:08:30 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=E5=A4=84=E7=90=86=E5=9C=B0=E7=82=B9?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ListCard/index.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ListCard/index.scss b/src/components/ListCard/index.scss index a316a7d..54362cb 100644 --- a/src/components/ListCard/index.scss +++ b/src/components/ListCard/index.scss @@ -53,7 +53,7 @@ } .location-position { - flex: 1; + // flex: 1; min-width: 0; // 允许缩小 white-space: nowrap; overflow: hidden; From bfc6a149f0bf281f8869594d08b0d531d000aabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AD=B1=E9=87=8E?= Date: Sat, 7 Feb 2026 22:15:14 +0800 Subject: [PATCH 04/12] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=97=A5=E6=9C=9F?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=BC=B9=E5=87=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CustomPopup/CustomPopup.tsx | 181 ++++++++++++++++++ src/components/CustomPopup/index.module.scss | 153 +++++++++++++++ src/components/CustomPopup/index.ts | 4 + .../CalendarDialog/DialogCalendarCard.tsx | 8 + src/components/Picker/DayDialog/index.tsx | 8 + src/components/index.ts | 2 + .../AiImportPopup/AiImportPopup.tsx | 160 +++++++++------- .../AiImportPopup/index.module.scss | 34 +++- .../SelectStadium/SelectStadium.tsx | 20 +- .../SelectStadium/StadiumDetail.scss | 2 +- .../SelectStadium/StadiumDetail.tsx | 37 +++- src/publish_pages/publishBall/index.tsx | 1 + 12 files changed, 515 insertions(+), 95 deletions(-) create mode 100644 src/components/CustomPopup/CustomPopup.tsx create mode 100644 src/components/CustomPopup/index.module.scss create mode 100644 src/components/CustomPopup/index.ts diff --git a/src/components/CustomPopup/CustomPopup.tsx b/src/components/CustomPopup/CustomPopup.tsx new file mode 100644 index 0000000..2841d24 --- /dev/null +++ b/src/components/CustomPopup/CustomPopup.tsx @@ -0,0 +1,181 @@ +import React, { useRef, useState } from 'react' +import type { CSSProperties, ReactNode } from 'react' +import { View, Text } from '@tarojs/components' +import { Button } from '@nutui/nutui-react-taro' +import styles from './index.module.scss' + +export interface CustomPopupProps { + visible: boolean + onClose: () => void + title?: ReactNode + showHeader?: boolean + hideFooter?: boolean + cancelText?: string + confirmText?: string + onCancel?: () => void + onConfirm?: () => void + children?: ReactNode + className?: string + style?: CSSProperties + // 与 CommonPopup 保持入参一致 + position?: 'center' | 'bottom' | 'top' | 'left' | 'right' + round?: boolean + zIndex?: number + enableDragToClose?: boolean +} + +const CustomPopup: React.FC = ({ + visible, + onClose, + title, + showHeader = false, + hideFooter = false, + cancelText = '返回', + confirmText = '完成', + onCancel, + onConfirm, + children, + className, + style, + position = 'bottom', + round = true, + zIndex, + enableDragToClose = true, +}) => { + const [dragOffset, setDragOffset] = useState(0) + const [isDragging, setIsDragging] = useState(false) + const touchStartY = useRef(0) + + if (!visible) { + return null + } + + const handleCancel = () => { + if (onCancel) { + onCancel() + } else { + onClose() + } + } + + const handleTouchStart = (e: any) => { + if (!enableDragToClose) return + + touchStartY.current = e.touches[0].clientY + setIsDragging(true) + } + + const handleTouchMove = (e: any) => { + if (!enableDragToClose || !isDragging) return + + const currentY = e.touches[0].clientY + const deltaY = currentY - touchStartY.current + + if (deltaY > 0) { + setDragOffset(Math.min(deltaY, 100)) + } + } + + const handleTouchEnd = () => { + if (!enableDragToClose || !isDragging) return + + setIsDragging(false) + + if (dragOffset > 50) { + onClose() + } + + setDragOffset(0) + } + + const overlayAlignItems = + position === 'center' + ? 'center' + : position === 'top' + ? 'flex-start' + : 'flex-end' + + const handleOverlayClick = () => { + onClose() + } + + + return ( + + + { + e.stopPropagation() + }} + > + {enableDragToClose && ( + + + + )} + + {showHeader && ( + + {typeof title === 'string' ? ( + {title} + ) : ( + title + )} + + + + + + + + )} + + {children} + + {!hideFooter && ( + + + + + )} + + + ) +} + +export default CustomPopup + diff --git a/src/components/CustomPopup/index.module.scss b/src/components/CustomPopup/index.module.scss new file mode 100644 index 0000000..67981fa --- /dev/null +++ b/src/components/CustomPopup/index.module.scss @@ -0,0 +1,153 @@ +@use "~@/scss/themeColor.scss" as theme; + +.custom-popup-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 9999; + display: flex; + align-items: flex-end; + justify-content: center; +} +.custom-popup-move{ + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 9998; +} +.custom-popup { + position: relative; + z-index: 9999; + width: 100%; + padding: 0; + box-sizing: border-box; + max-height: 80vh; + display: flex; + flex-direction: column; + background-color: theme.$page-background-color; + border-radius: 20px 20px 0 0; + overflow: hidden; + .custom-popup__drag-handle-container { + position: relative; + height: 0; + } + + .custom-popup__drag-handle { + position: absolute; + top: 6px; + left: 50%; + width: 90px; + height: 30px; + z-index: 10; + display: flex; + justify-content: center; + align-items: flex-start; + + &::before { + content: ""; + width: 32px; + height: 4px; + background-color: rgba(22, 24, 35, 0.2); + border-radius: 2px; + } + } + + .custom-popup__header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 20px; + + .custom-popup__title { + font-family: "PingFang SC"; + font-weight: 600; + font-size: 22px; + line-height: 1.27em; + color: #000000; + text-align: center; + } + + .close_button { + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background: #ffffff; + border: 1px solid rgba(0, 0, 0, 0.06); + border-radius: 50%; + cursor: pointer; + box-shadow: 0px 4px 36px 0px rgba(0, 0, 0, 0.06); + + .close_icon { + position: relative; + width: 24px; + height: 24px; + + .close_line { + position: absolute; + top: 50%; + left: 50%; + width: 17px; + height: 3px; + border-radius: 3px; + background: #000000; + transform: translate(-50%, -50%) rotate(45deg); + + &:nth-child(2) { + transform: translate(-50%, -50%) rotate(-45deg); + } + } + } + } + } + + .custom-popup__body { + flex: 1 1 auto; + } + + .custom-popup__footer { + padding: 8px 10px 0 10px; + display: flex; + gap: 8px; + background: #fafafa; + padding-bottom: max(10px, env(safe-area-inset-bottom)); + } + + .custom-popup__btn { + flex: 1; + font-feature-settings: "liga" off, "clig" off; + font-family: "PingFang SC"; + font-size: 16px; + font-style: normal; + font-weight: 600; + line-height: normal; + } + + .custom-popup__btn-cancel { + background: #f5f6f7; + color: #1f2329; + border: none; + width: 154px; + height: 44px; + border-radius: 12px !important; + border: 0.5px solid rgba(0, 0, 0, 0.06); + background: #fff; + padding: 4px 10px; + } + + .custom-popup__btn-confirm { + width: 154px; + height: 44px; + border: 0.5px solid rgba(0, 0, 0, 0.06); + background: #000; + border-radius: 12px !important; + padding: 4px 10px; + } +} + diff --git a/src/components/CustomPopup/index.ts b/src/components/CustomPopup/index.ts new file mode 100644 index 0000000..325f791 --- /dev/null +++ b/src/components/CustomPopup/index.ts @@ -0,0 +1,4 @@ +import CustomPopup from './CustomPopup' +export default CustomPopup +export * from './CustomPopup' + diff --git a/src/components/Picker/CalendarDialog/DialogCalendarCard.tsx b/src/components/Picker/CalendarDialog/DialogCalendarCard.tsx index 1156de6..7c8555c 100644 --- a/src/components/Picker/CalendarDialog/DialogCalendarCard.tsx +++ b/src/components/Picker/CalendarDialog/DialogCalendarCard.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect, useRef } from "react"; import CommonPopup from "@/components/CommonPopup"; import { View } from "@tarojs/components"; +import Taro from "@tarojs/taro"; import CalendarUI, { CalendarUIRef, } from "@/components/Picker/CalendarUI/CalendarUI"; @@ -47,6 +48,13 @@ const DialogCalendarCard: React.FC = ({ onClose(); return; } + if (!selected) { + Taro.showToast({ + title: '请选择日期', + icon: "none", + }); + return; + } // 年份选择完成后,进入月份选择 setType("time"); } else if (type === "month") { diff --git a/src/components/Picker/DayDialog/index.tsx b/src/components/Picker/DayDialog/index.tsx index c36237c..3547210 100644 --- a/src/components/Picker/DayDialog/index.tsx +++ b/src/components/Picker/DayDialog/index.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect, useRef } from "react"; import CommonPopup from "@/components/CommonPopup"; +import Taro from "@tarojs/taro"; import { View } from "@tarojs/components"; import CalendarUI, { CalendarUIRef, @@ -32,6 +33,13 @@ const DayDialog: React.FC = ({ } | null>(null); const handleConfirm = () => { console.log(selected, 'selectedselected'); + if (!selected) { + Taro.showToast({ + title: '请选择日期', + icon: "none", + }); + return; + } const finalDate = dayjs(selected as Date).format("YYYY-MM-DD"); if (onChange){ onChange(finalDate) diff --git a/src/components/index.ts b/src/components/index.ts index 3720f2e..a4019f5 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -8,6 +8,7 @@ import NumberInterval from "./NumberInterval"; import TimeSelector from "./TimeSelector"; import TitleTextarea from "./TitleTextarea"; import CommonPopup from "./CommonPopup"; +import CustomPopup from "./CustomPopup"; import { CalendarUI, DialogCalendarCard } from "./Picker"; import CommonDialog from "./CommonDialog"; import PublishMenu from "./PublishMenu/PublishMenu"; @@ -37,6 +38,7 @@ export { TimeSelector, TitleTextarea, CommonPopup, + CustomPopup, DialogCalendarCard, CalendarUI, CommonDialog, diff --git a/src/publish_pages/publishBall/components/AiImportPopup/AiImportPopup.tsx b/src/publish_pages/publishBall/components/AiImportPopup/AiImportPopup.tsx index 0f9f08f..ddd3d44 100644 --- a/src/publish_pages/publishBall/components/AiImportPopup/AiImportPopup.tsx +++ b/src/publish_pages/publishBall/components/AiImportPopup/AiImportPopup.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react' import { View, Text, Textarea, Image } from '@tarojs/components' import Taro from '@tarojs/taro' -import { ConfigProvider, Loading, Popup, Toast } from '@nutui/nutui-react-taro' +import { ConfigProvider, Loading, Toast } from '@nutui/nutui-react-taro' import styles from './index.module.scss' import uploadFiles from '@/services/uploadFiles' import publishService from '@/services/publishService' @@ -109,7 +109,10 @@ const AiImportPopup: React.FC = ({ } const handleTextChange = (e: any) => { - setText(e.detail.value) + const text = e.detail.value; + const maxAllowedLength = 120; + const truncatedVal = text.length > maxAllowedLength ? text.slice(0, maxAllowedLength) : text + setText(truncatedVal) } // 使用全局键盘状态监听 @@ -191,73 +194,90 @@ const AiImportPopup: React.FC = ({ } const showManualButton = uploadFailCount >= maxFailCount + if (!visible) { + return null + } + // 阻止弹窗内的触摸事件冒泡 + const handleTouchMoveInPopup = (e) => { + if (!isKeyboardVisible) { + e.stopPropagation() + } + } + return ( - - - {/* 头部 */} - - - - 智能导入球局信息 - - - - - - - {/* 文本域 */} - -