diff --git a/src/components/PublishMenu/PublishMenu.tsx b/src/components/PublishMenu/PublishMenu.tsx index e4a1cb0..0339bb4 100644 --- a/src/components/PublishMenu/PublishMenu.tsx +++ b/src/components/PublishMenu/PublishMenu.tsx @@ -3,6 +3,7 @@ import { View, Text, Image } from '@tarojs/components' import Taro from '@tarojs/taro' import styles from './index.module.scss' import images from '@/config/images' +import AiImportPopup from '@/publish_pages/publishBall/components/AiImportPopup' export interface PublishMenuProps { onPersonalPublish?: () => void @@ -11,25 +12,53 @@ export interface PublishMenuProps { const PublishMenu: React.FC = () => { const [isVisible, setIsVisible] = useState(false) - + const [aiImportVisible, setAiImportVisible] = useState(false) + const handleIconClick = () => { setIsVisible(!isVisible) } - - const handleMenuItemClick = (type: 'individual' | 'group') => { + const handleOverlayClick = () => { + setIsVisible(false) + } + const handleMenuItemClick = (type: 'individual' | 'group' | 'ai') => { // 跳转到publishBall页面并传递type参数 console.log(type, 'type'); + if (type === 'ai') { + setAiImportVisible(true) + setIsVisible(false) + return + } Taro.navigateTo({ url: `/publish_pages/publishBall/index?type=${type}` }) setIsVisible(false) } + const handleAiImportClose = () => { + setAiImportVisible(false) + } + const handleManualPublish = () => { + Taro.navigateTo({ + url: '/publish_pages/publishBall/index?type=individual' + }) + } + + const handlePasteAndRecognize = (text: string) => { + console.log('识别的文本:', text) + // TODO: 实现文本识别逻辑 + Taro.showToast({ + title: '文本识别功能开发中', + icon: 'none' + }) + } return ( - + {/* 蒙层 */} + {isVisible && ( + + )} {/* 菜单选项 */} {isVisible && ( @@ -37,15 +66,16 @@ const PublishMenu: React.FC = () => { className={styles.menuItem} onClick={() => handleMenuItemClick('individual')} > - - - - 发布个人约球 + 发布个人约球 + + + + 已订场,找球友;未订场,找搭子 - - + + @@ -53,15 +83,34 @@ const PublishMenu: React.FC = () => { className={styles.menuItem} onClick={() => handleMenuItemClick('group')} > - - - + - 发布畅打活动 + 发布畅打活动 + + + + 认证球场官方组织 - - + + + + + handleMenuItemClick('ai')} + > + + 智能导入球局信息 + + + + + 识别文本,快速导入球局信息 + + + + @@ -74,6 +123,14 @@ const PublishMenu: React.FC = () => { > + + {/* AI导入弹窗 */} + ) } diff --git a/src/components/PublishMenu/index.module.scss b/src/components/PublishMenu/index.module.scss index f09ec51..6a1f9a9 100644 --- a/src/components/PublishMenu/index.module.scss +++ b/src/components/PublishMenu/index.module.scss @@ -3,48 +3,53 @@ z-index: 1000; } - +.overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 999; +} .menuCard { position: absolute; bottom: 80px; right: 0; - width: 302px; - background: white; - border-radius: 16px; - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); - padding: 12px; + width: 278px; animation: slideIn 0.3s ease-out; box-sizing: border-box; display: flex; flex-direction: column; gap: 8px; - /* 小三角指示器 */ - &::after { - content: ''; - position: absolute; - bottom: -8px; - right: 20px; - width: 0; - height: 0; - border-left: 8px solid transparent; - border-right: 8px solid transparent; - border-top: 8px solid white; - /* 移除阴影,避免连接处的黑色 */ - } + z-index: 1001; + // /* 小三角指示器 */ + // &::after { + // content: ''; + // position: absolute; + // bottom: -8px; + // right: 20px; + // width: 0; + // height: 0; + // border-left: 8px solid transparent; + // border-right: 8px solid transparent; + // border-top: 8px solid white; + // /* 移除阴影,避免连接处的黑色 */ + // } - /* 为小三角添加单独的阴影效果 */ - &::before { - content: ''; - position: absolute; - bottom: -9px; - right: 20px; - width: 0; - height: 0; - border-left: 8px solid transparent; - border-right: 8px solid transparent; - border-top: 8px solid rgba(0, 0, 0, 0.1); - z-index: -1; - } + // /* 为小三角添加单独的阴影效果 */ + // &::before { + // content: ''; + // position: absolute; + // bottom: -9px; + // right: 20px; + // width: 0; + // height: 0; + // border-left: 8px solid transparent; + // border-right: 8px solid transparent; + // border-top: 8px solid rgba(0, 0, 0, 0.1); + // z-index: -1; + // } } @keyframes slideIn { @@ -71,12 +76,20 @@ } .menuIcon { - width: 40px; - height: 40px; display: flex; - align-items: center; + width: 48px; + height: 48px; + padding: 10px; justify-content: center; - margin-right: 12px; + align-items: center; + border-radius: 12px; +border: 1px solid rgba(0, 0, 0, 0.06); +background: rgba(0, 0, 0, 0.03); +box-sizing: border-box; + image{ + width: 28px; + height: 28px; + } } .ballIcon { @@ -143,6 +156,7 @@ flex: 1; display: flex; flex-direction: column; + padding-left: 8px; } .menuTitle { @@ -151,6 +165,8 @@ color: #000; margin-bottom: 2px; line-height: 24px; /* 150% */ + display: flex; + align-items: center; } .menuDesc { @@ -162,7 +178,7 @@ .menuArrow { font-size: 16px; color: #ccc; - margin-left: 8px; + margin-left: 4px; .img{ width: 16px; height: 16px; @@ -180,6 +196,8 @@ justify-content: center; flex-shrink: 0; overflow: hidden; + z-index: 1001; + position: relative; &.rotated { transform: rotate(-90deg); } @@ -193,3 +211,20 @@ font-weight: bold; line-height: 1; } + +.aiItem{ + border-radius: 20px; + border: 0.5px solid rgba(0, 0, 0, 0.08); + background: #000; + .menuTitle{ + color: #FFF; + } + .menuDesc{ + color: rgba(255, 255, 255, 0.60); + } + .menuIcon{ + border-radius: 12px; + border: 1px solid rgba(0, 0, 0, 0.06); + background: rgba(255, 255, 255, 0.20); + } +} \ No newline at end of file diff --git a/src/config/images.js b/src/config/images.js index 8009e5f..f9ae115 100644 --- a/src/config/images.js +++ b/src/config/images.js @@ -56,4 +56,7 @@ export default { ICON_LIST_SEARCH_CLEAR_HISTORY: require('@/static/search/icon-clear-history.svg'), ICON_LIST_SEARCH_SUGGESTION: require('@/static/search/icon-search-suggestion.svg'), ICON_LIST_INPUT_LOGO: require('@/static/list/icon-input-logo.svg'), + ICON_IMPORTANT_BTN: require('@/static/publishBall/icon-important-btn.svg'), + ICON_ARROW_RIGHT_WHITE: require('@/static/publishBall/icon-arrow-right-white.svg'), + ICON_ARROW_RIGHT_BLACK: require('@/static/publishBall/icon-arrow-right-black.svg'), } \ No newline at end of file diff --git a/src/publish_pages/publishBall/components/AiImportPopup/AiImportPopup.tsx b/src/publish_pages/publishBall/components/AiImportPopup/AiImportPopup.tsx new file mode 100644 index 0000000..68b54a0 --- /dev/null +++ b/src/publish_pages/publishBall/components/AiImportPopup/AiImportPopup.tsx @@ -0,0 +1,184 @@ +import React, { useState, useEffect } from 'react' +import { View, Text, Textarea, Image } from '@tarojs/components' +import Taro from '@tarojs/taro' +import { Popup, Toast } from '@nutui/nutui-react-taro' +import styles from './index.module.scss' +import images from '@/config/images' + +export interface AiImportPopupProps { + visible: boolean + onClose: () => void + onManualPublish?: () => void + onPasteAndRecognize?: (text: string) => void +} + +const AiImportPopup: React.FC = ({ + visible, + onClose, + onManualPublish, + onPasteAndRecognize +}) => { + const [text, setText] = useState('') + const [uploadFailCount, setUploadFailCount] = useState(0) + const maxFailCount = 3 + + // 当弹窗显示时,尝试获取剪切板内容 + useEffect(() => { + if (visible) { + getClipboardData() + } + }, [visible]) + + const getClipboardData = async () => { + try { + const res = await Taro.getClipboardData() + if (res.data && res.data.trim()) { + setText(res.data) + Toast.show('toast', { + content: '有场读取了你的剪切板信息', + duration: 90, + wordBreak:'break-word' + }) + // Taro.showToast({ + // title: '已读取你的剪切板信息', + // icon: 'success', + // duration: 2000 + // }) + } else { + Taro.showToast({ + title: '剪切板为空,请手动输入', + icon: 'none', + duration: 2000 + }) + } + } catch (error) { + console.error('获取剪切板失败:', error) + Taro.showToast({ + title: '读取剪切板失败,请手动输入', + icon: 'error', + duration: 2000 + }) + } + } + + const handleTextChange = (e: any) => { + setText(e.detail.value) + } + + const handleImageRecognition = async () => { + try { + const res = await Taro.chooseMedia({ + count: 1, + mediaType: ['image'], + sourceType: ['album', 'camera'], + camera: 'back' + }) + + if (res.tempFiles && res.tempFiles.length > 0) { + // 这里可以调用图片识别API + console.log('选择的图片:', res.tempFiles[0]) + // TODO: 实现图片识别逻辑 + Taro.showToast({ + title: '图片识别功能开发中', + icon: 'none' + }) + } + } catch (error) { + console.error('选择图片失败:', error) + setUploadFailCount(prev => prev + 1) + Taro.showToast({ + title: '上传失败', + icon: 'error' + }) + } + } + + const handlePasteAndRecognize = () => { + if (!text.trim()) { + Taro.showToast({ + title: '请输入球局信息', + icon: 'none' + }) + return + } + + if (onPasteAndRecognize) { + onPasteAndRecognize(text) + } + onClose() + } + + const handleManualPublish = () => { + if (onManualPublish) { + onManualPublish() + } + onClose() + } + + const showManualButton = uploadFailCount >= maxFailCount + + return ( + + + {/* 头部 */} + + + + 智能导入球局信息 + + + × + + + + {/* 文本域 */} + +