| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- import { useAjax } from "@/Hook/useAjax"
- import { txtLength } from "@/utils/utils";
- import { Button, Input, InputRef, List, Popover } from "antd";
- import React, { useEffect, useRef } from "react"
- import { useState } from "react";
- import './index.less'
- import { getTextApi } from "@/services/adqV3/global";
- import { SmileOutlined } from "@ant-design/icons";
- import { emojiList } from "./const";
- interface Props {
- value?: any,
- onChange?: (value: any) => void;
- style?: React.CSSProperties;
- placeholder?: string;
- maxTextLength?: number;
- isShowAjax?: boolean
- isSelectEmoji?: boolean
- }
- /**
- * 文案助手输入框
- * @param props
- * @returns
- */
- const TextAideInput: React.FC<Props> = (props) => {
- /************************/
- const { value, onChange, style, placeholder, maxTextLength = 10, isShowAjax = true, isSelectEmoji = true } = props
- const [text, setText] = useState<any>(value)
- const [descriptionShow, setDescriptionshow] = useState(false)
- const [cursorPosition, setCursorPosition] = useState<number | null>(null);
- const inputRef = useRef<InputRef>(null); // 获取 input DOM 元素
- const [emojiOpen, setEmojiOpen] = useState<boolean>(false)
- const getTextLsit = useAjax((params) => getTextApi(params))
- /************************/
- useEffect(() => {
- setText(value)
- }, [value])
- // 文案助手
- const textList = (keyword?: any) => {
- getTextLsit.run({ keyword, maxTextLength })
- }
- const insertTextAtCursor = (emoji: string) => {
- const inputElement = inputRef.current;
- if (inputElement) {
- if (cursorPosition !== null) {
- const newValue = text.slice(0, cursorPosition) + emoji + text.slice(cursorPosition);
- setText(newValue);
- onChange?.(newValue)
- } else {
- const newValue = text + emoji
- setText(newValue);
- onChange?.(newValue)
- }
- const newCursorPosition = (cursorPosition || text.length) + emoji.length;
- setCursorPosition(newCursorPosition);
- // 等待状态更新后再设置光标位置
- setTimeout(() => {
- inputElement.setSelectionRange(newCursorPosition, newCursorPosition);
- inputElement.focus();
- }, 0);
- }
- };
- return <div style={{ display: 'inline-flex', alignItems: 'center', columnGap: 5 }}>
- <Popover
- placement="topLeft"
- overlayClassName="textAideInputPopover"
- style={{ minWidth: 600 }}
- open={descriptionShow}
- content={<List
- loading={getTextLsit?.loading}
- size="small"
- style={{ maxHeight: 300, overflowX: 'auto', minWidth: 600 }}
- dataSource={getTextLsit?.data?.returnTexts}
- renderItem={(item: any) => <List.Item onClick={() => {
- setText(item.text)
- onChange && onChange(item.text)
- setTimeout(() => { setDescriptionshow(false) }, 50)
- }}><span >{item.text}{item.tag && <span className="crt">{'CTR 高'}</span>}</span></List.Item>}
- />}
- >
- <Input.Group compact>
- <Input
- ref={inputRef}
- placeholder={placeholder}
- style={style}
- value={text}
- onFocus={() => {
- if (isShowAjax) {
- setDescriptionshow(true)
- textList(value)
- }
- }}
- onBlur={(e) => {
- setCursorPosition(e.target.selectionStart)
- if (!emojiOpen) {
- setTimeout(() => { setDescriptionshow(false) }, 0)
- }
- }}
- onChange={(e) => {
- let value = e.target.value
- setText(value)
- if (isShowAjax) {
- textList(value)
- }
- onChange && onChange(value)
- }}
- allowClear
- />
- {isSelectEmoji && <Popover
- placement="bottomRight"
- overlayClassName="emoji"
- content={<div className="emoji-list-scroll">
- <ul className="emoji-list">{emojiList.map(item => <li key={item.text} onClick={() => insertTextAtCursor(item.text)}><img src={item.url} alt={item.text} /></li>)}</ul>
- </div>}
- trigger="click"
- onOpenChange={(e) => {
- setEmojiOpen(e)
- }}
- >
- <Button><SmileOutlined /></Button>
- </Popover>}
- </Input.Group>
- </Popover>
- <span>{`${txtLength(text)}/${maxTextLength}`}</span>
- </div>
- }
- export default React.memo(TextAideInput)
|