智能导入
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
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 { ConfigProvider, Loading, Popup, Toast } from '@nutui/nutui-react-taro'
|
||||
import styles from './index.module.scss'
|
||||
import uploadFiles from '@/services/uploadFiles'
|
||||
import publishService from '@/services/publishService'
|
||||
import { usePublishBallActions } from '@/store/publishBallStore'
|
||||
import images from '@/config/images'
|
||||
|
||||
export interface AiImportPopupProps {
|
||||
@@ -20,14 +23,21 @@ const AiImportPopup: React.FC<AiImportPopupProps> = ({
|
||||
}) => {
|
||||
const [text, setText] = useState('')
|
||||
const [uploadFailCount, setUploadFailCount] = useState(0)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [uploadLoading, setUploadLoading] = useState(false)
|
||||
const maxFailCount = 3
|
||||
|
||||
// 当弹窗显示时,尝试获取剪切板内容
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
getClipboardData()
|
||||
}
|
||||
}, [visible])
|
||||
// 获取 actions(在组件顶层调用 Hook)
|
||||
const { setPublishData } = usePublishBallActions()
|
||||
|
||||
const textIdentification = async (text: string) => {
|
||||
setLoading(true)
|
||||
const res = await publishService.extract_tennis_activity({text})
|
||||
console.log(res)
|
||||
const {data} = res
|
||||
navigateToPublishBall(data)
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
const getClipboardData = async () => {
|
||||
try {
|
||||
@@ -36,9 +46,10 @@ const AiImportPopup: React.FC<AiImportPopupProps> = ({
|
||||
setText(res.data)
|
||||
Toast.show('toast', {
|
||||
content: '有场读取了你的剪切板信息',
|
||||
duration: 90,
|
||||
duration: 2,
|
||||
wordBreak:'break-word'
|
||||
})
|
||||
textIdentification(res.data)
|
||||
// Taro.showToast({
|
||||
// title: '已读取你的剪切板信息',
|
||||
// icon: 'success',
|
||||
@@ -48,7 +59,7 @@ const AiImportPopup: React.FC<AiImportPopupProps> = ({
|
||||
Taro.showToast({
|
||||
title: '剪切板为空,请手动输入',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
duration: 2
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -56,11 +67,20 @@ const AiImportPopup: React.FC<AiImportPopupProps> = ({
|
||||
Taro.showToast({
|
||||
title: '读取剪切板失败,请手动输入',
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
duration: 2
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const navigateToPublishBall = (data: any) => {
|
||||
if (Array.isArray(data) && data.length > 0) {
|
||||
setPublishData(data)
|
||||
Taro.navigateTo({
|
||||
url: '/publish_pages/publishBall/pages/publishBall?type=ai'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleTextChange = (e: any) => {
|
||||
setText(e.detail.value)
|
||||
}
|
||||
@@ -76,12 +96,17 @@ const AiImportPopup: React.FC<AiImportPopupProps> = ({
|
||||
|
||||
if (res.tempFiles && res.tempFiles.length > 0) {
|
||||
// 这里可以调用图片识别API
|
||||
console.log('选择的图片:', res.tempFiles[0])
|
||||
// TODO: 实现图片识别逻辑
|
||||
Taro.showToast({
|
||||
title: '图片识别功能开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
setUploadLoading(false)
|
||||
setLoading(true)
|
||||
const res_upload = await uploadFiles.upload_oss_img(res.tempFiles[0].tempFilePath)
|
||||
const {ossPath} = res_upload;
|
||||
if (ossPath) {
|
||||
setUploadLoading(true)
|
||||
const publishData = await publishService.extract_tennis_activity_from_image({image_url: ossPath})
|
||||
const {data} = publishData
|
||||
navigateToPublishBall(data)
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('选择图片失败:', error)
|
||||
@@ -93,20 +118,6 @@ const AiImportPopup: React.FC<AiImportPopupProps> = ({
|
||||
}
|
||||
}
|
||||
|
||||
const handlePasteAndRecognize = () => {
|
||||
if (!text.trim()) {
|
||||
Taro.showToast({
|
||||
title: '请输入球局信息',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (onPasteAndRecognize) {
|
||||
onPasteAndRecognize(text)
|
||||
}
|
||||
onClose()
|
||||
}
|
||||
|
||||
const handleManualPublish = () => {
|
||||
if (onManualPublish) {
|
||||
@@ -144,9 +155,10 @@ const AiImportPopup: React.FC<AiImportPopupProps> = ({
|
||||
className={styles.textArea}
|
||||
value={text}
|
||||
onInput={handleTextChange}
|
||||
placeholder="请输入球局信息..."
|
||||
placeholder="在此「粘贴识别」或输入文本,智能拆分球局时间、费用、地点和其他信息,并帮你智能生成球局标题"
|
||||
maxlength={100}
|
||||
showConfirmBar={false}
|
||||
placeholderClass={styles.textArea_placeholder}
|
||||
autoHeight
|
||||
/>
|
||||
<View className={styles.charCount}>
|
||||
@@ -156,10 +168,12 @@ const AiImportPopup: React.FC<AiImportPopupProps> = ({
|
||||
|
||||
{/* 图片识别按钮 */}
|
||||
<View className={styles.imageRecognitionContainer}>
|
||||
<View className={styles.imageRecognitionButton} onClick={handleImageRecognition}>
|
||||
<Image src={images.ICON_UPLOAD} className={styles.cameraIcon} />
|
||||
<View className={`${styles.imageRecognitionButton} ${uploadLoading ? styles.uploadLoadingContainer : ''}`} onClick={handleImageRecognition}>
|
||||
{
|
||||
uploadLoading ? (<Image src={images.ICON_UPLOAD_SUCCESS} className={styles.cameraIcon} />) : (<Image src={images.ICON_UPLOAD_IMG} className={styles.cameraIcon} />)
|
||||
}
|
||||
<Text className={styles.imageRecognitionText}>图片识别</Text>
|
||||
<Text className={styles.imageRecognitionDesc}>支持订场截图/小红书笔记截图等图片</Text>
|
||||
<Text className={styles.imageRecognitionDesc}>{uploadLoading ? '已上传 1 张图片' : '支持订场截图/小红书笔记截图等图片'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -170,9 +184,22 @@ const AiImportPopup: React.FC<AiImportPopupProps> = ({
|
||||
<Text className={styles.manualButtonText}>手动发布球局</Text>
|
||||
</View>
|
||||
)}
|
||||
<View className={styles.pasteButton} onClick={handlePasteAndRecognize}>
|
||||
<Image src={images.ICON_PLUS} className={styles.clipboardIcon} />
|
||||
<Text className={styles.pasteButtonText}>粘贴并识别</Text>
|
||||
<View className={styles.pasteButton} onClick={getClipboardData}>
|
||||
{
|
||||
loading ? (
|
||||
<View className={styles.loadingContainer}>
|
||||
<ConfigProvider theme={{ nutuiLoadingIconColor: '#fff', nutuiLoadingIconSize: '20px' }}>
|
||||
<Loading type="circular" />
|
||||
</ConfigProvider>
|
||||
<Text className={styles.pasteButtonText}>识别中</Text>
|
||||
</View>
|
||||
) : (
|
||||
<>
|
||||
<Image src={images.ICON_COPY} className={styles.clipboardIcon} />
|
||||
<Text className={styles.pasteButtonText}>粘贴并识别</Text>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
.textArea {
|
||||
width: 100%;
|
||||
min-height: 80px;
|
||||
min-height: 120px;
|
||||
padding: 12px;
|
||||
border: 1px solid #e5e6eb;
|
||||
border-radius: 8px;
|
||||
@@ -67,9 +67,10 @@
|
||||
box-sizing: border-box;
|
||||
resize: none;
|
||||
|
||||
&:focus {
|
||||
border-color: #165dff;
|
||||
outline: none;
|
||||
.textArea_placeholder{
|
||||
color: rgba(60, 60, 67, 0.30);
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,17 +91,15 @@
|
||||
|
||||
.imageRecognitionButton {
|
||||
display: flex;
|
||||
height: 40px;
|
||||
padding: 2px 16px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&:active {
|
||||
background: #e9ecef;
|
||||
}
|
||||
gap: 6px;
|
||||
align-self: stretch;
|
||||
border-radius: 999px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.16);
|
||||
background: #FFF;
|
||||
|
||||
.cameraIcon {
|
||||
width: 16px;
|
||||
@@ -115,10 +114,15 @@
|
||||
|
||||
.imageRecognitionDesc {
|
||||
font-size: 12px;
|
||||
color: #8a8a8a;
|
||||
margin-left: auto;
|
||||
color: rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
}
|
||||
.uploadLoadingContainer{
|
||||
border-radius: 999px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.16);
|
||||
background: rgba(52, 199, 89, 0.10);
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.bottomButtons {
|
||||
@@ -161,21 +165,25 @@
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
|
||||
.loadingContainer{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
}
|
||||
&:active {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.clipboardIcon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
filter: invert(1);
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.pasteButtonText {
|
||||
font-size: 14px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { View, Text, Input, ScrollView, Image } from '@tarojs/components'
|
||||
import Taro from '@tarojs/taro'
|
||||
import { Loading } from '@nutui/nutui-react-taro'
|
||||
import StadiumDetail, { StadiumDetailRef } from './StadiumDetail'
|
||||
import { CommonPopup } from '@/components'
|
||||
import { CommonPopup } from '../../../../components'
|
||||
import { getLocation } from '@/utils/locationUtils'
|
||||
import PublishService from '@/services/publishService'
|
||||
import images from '@/config/images'
|
||||
@@ -135,6 +135,12 @@ const SelectStadium: React.FC<SelectStadiumProps> = ({
|
||||
setSearchValue('')
|
||||
}
|
||||
|
||||
const handleDetailCancel = () => {
|
||||
setShowDetail(false)
|
||||
setSelectedStadium(null)
|
||||
setSearchValue('')
|
||||
}
|
||||
|
||||
const handleItemLocation = (stadium: Stadium) => {
|
||||
if (stadium.latitude && stadium.longitude) {
|
||||
Taro.openLocation({
|
||||
@@ -169,7 +175,7 @@ const SelectStadium: React.FC<SelectStadiumProps> = ({
|
||||
cancelText="返回"
|
||||
confirmText="确认"
|
||||
className="select-stadium-popup"
|
||||
onCancel={handleCancel}
|
||||
onCancel={handleDetailCancel}
|
||||
onConfirm={handleConfirm}
|
||||
position="bottom"
|
||||
round
|
||||
|
||||
Reference in New Issue
Block a user