Sfoglia il codice sorgente

fix: 聊天输入框样式重新修正

王晓东 2 settimane fa
parent
commit
225da75967

+ 9 - 2
project.private.config.json

@@ -8,12 +8,19 @@
   "condition": {
     "miniprogram": {
       "list": [
+        {
+          "name": "pages/chat/index",
+          "pathName": "pages/chat/index",
+          "query": "agentId=p_2e73c9d7efaYfDo2-agent_3111&isVisitor=false",
+          "scene": null,
+          "launchMode": "default"
+        },
         {
           "name": "pages/profile/index",
           "pathName": "pages/profile/index",
           "query": "agentId=p_2e73c9d7efaYfDo2-agent_2747&shareKey=2%241%24AAADJVaNamEqHCG%2FJ8rQloPjNu6BaGv5PqdIw081Yet%2BROuk5MwyAhuwauvV1dt3XgK7JnY2%2BAO6qDCDzQeF2qqhC4YSK%2FkewwevYKd6jPM%2FQO1u",
-          "scene": null,
-          "launchMode": "default"
+          "launchMode": "default",
+          "scene": null
         },
         {
           "name": "pages/chat/index",

+ 23 - 21
src/components/wemeta-textarea/index.tsx

@@ -46,6 +46,7 @@ const index = ({
   onConfirm,
   placeholderStyle,
   adjustPosition,
+  ...rest
 }: Props) => {
   const [focus, setFocus] = useState(false);
   const inputRef = useRef<HTMLInputElement>(null); // 创建一个 ref
@@ -83,27 +84,28 @@ const index = ({
       {prefix && prefix()}
       <View className={styleIndex.textareaContainer}>
         <View className="flex items-end">
-          <Textarea
-            ref={inputRef}
-            value={value}
-            disabled={disabled}
-            adjustPosition={adjustPosition}
-            confirmType={confirmType}
-            style={style}
-            onInput={(e: any) => handleInput(e.target.value)}
-            placeholder={placeholder}
-            placeholderStyle={placeholderStyle ?? 'color: rgba(17,17,17,.25)'}
-            className={`${styleIndex.textInput} ${extraClass}`}
-            onFocus={handleFocus}
-            onBlur={handleBlur}
-            autoHeight={autoHeight}
-            autoFocus={autoFocus}
-            cursorSpacing={cursorSpacing}
-            maxlength={10000}
-            onConfirm={(e: any) => {
-              onConfirm && onConfirm(e.detail.value);
-            }}
-          />
+            <Textarea
+              ref={inputRef}
+              value={value}
+              disabled={disabled}
+              adjustPosition={adjustPosition}
+              confirmType={confirmType}
+              style={style}
+              onInput={(e: any) => handleInput(e.target.value)}
+              placeholder={placeholder}
+              placeholderStyle={placeholderStyle ?? 'color: rgba(17,17,17,.25)'}
+              className={`${styleIndex.textInput} ${extraClass}`}
+              onFocus={handleFocus}
+              onBlur={handleBlur}
+              autoHeight={autoHeight}
+              autoFocus={autoFocus}
+              cursorSpacing={cursorSpacing}
+              maxlength={10000}
+              onConfirm={(e: any) => {
+                onConfirm && onConfirm(e.detail.value);
+              }}
+              {...rest}
+            />
           {suffix && suffix()}
         </View>
         <View className={`${styleIndex.textareaButtons} justify-end gap-8`}>

+ 49 - 23
src/pages/chat/components/InputBar/TextInputBar.tsx

@@ -1,17 +1,19 @@
-import { View } from "@tarojs/components"
+import { View, Textarea } from "@tarojs/components"
 import IconMic from "@/components/icon/IconMic"
 import IconStop from "@/components/icon/IconStop"
 import IconSend from "@/components/icon/IconSend"
 import { useState } from "react";
-// import WemetaInput from '@/components/wemeta-input'
+import TextareaInputAutoHeight from './TextareaInputAutoHeight'
 import WemetaTextarea from '@/components/wemeta-textarea'
 import { useTextChat } from "@/store/textChatStore";
+import { useAppStore } from "@/store/appStore";
 interface Props {
   disabled: boolean,
   onIconClick: () => void
   onSend: (msg: string)=> void
 }
 export default ({disabled, onIconClick, onSend}:Props) => {
+  const isIos = useAppStore( state => state.isIos)
   const [value, setValue] = useState('')
   const {messageStopHandle} = useTextChat()
 
@@ -31,29 +33,53 @@ export default ({disabled, onIconClick, onSend}:Props) => {
   }
 
   const renderExtra = () => {
-    // IOS Textarea 高度最小只能是 34px, 高度无法再缩小,所以添加一个高度 34 在同一行中高度居中显示
-    return <View className="flex items-center gap-12 leading-34 h-34">
-        {!value.length && <View className="flex-center" onClick={onIconClick}><IconMic /></View>}
-        {!messageStopHandle &&  <View className={`flex-center ${!!value.length ? '':'opacity-50'}`} onClick={handleConfirm}><IconSend /></View>}
-        {!!messageStopHandle && <View className="flex-center" onClick={handleStopClick}><IconStop /></View>}
+    return <View className="flex items-center gap-12 leading-24 h-24">
+      {!value.length && <View className="flex-center" onClick={onIconClick}><IconMic /></View>}
+      {!messageStopHandle &&  <View className={`flex-center ${!!value.length ? '':'opacity-50'}`} onClick={handleConfirm}><IconSend /></View>}
+      {!!messageStopHandle && <View className="flex-center" onClick={handleStopClick}><IconStop /></View>}
     </View>
   }
   return <View className="flex flex-col gap-12">
-      <WemetaTextarea
-      	adjustPosition={false}
-        disabled={disabled}
-        className="px-16 py-6"
-        // 必须添加 height 与 maxHeight 否则在初始化时高度会先 maxheight 再跳回到 lineHeight,导致闪烁和 高度计算错误
-        style={{'borderRadius': '10px', maxHeight: '120px', 'lineHeight': '1', 'height': '24px'}}
-        autoHeight
-        placeholder="有问题尽管问我..."
-        value={value}
-        cursorSpacing={400}
-        onConfirm={handleConfirm}
-        confirmType="send"
-        suffix={renderExtra}
-        onInput={(value: any) => handleInput(value)}
-        >
-      </WemetaTextarea>
+        {/* 无法复用 wemeta-textarea 需要特殊处理 */}
+        <TextareaInputAutoHeight
+          adjustPosition={false}
+          disabled={disabled}
+          extraClass="flex-1 w-auto"
+          autoHeight
+          placeholder="有问题尽管问我..."
+          value={value}
+          cursorSpacing={400}
+          onConfirm={handleConfirm}
+          confirmType="send"
+          disable-default-padding
+          onInput={(value) => handleInput(value)}
+          suffix={renderExtra}
+      />
   </View>
+  // return <View className="flex flex-col gap-12">
+  //     <View className="flex items-end px-16 py-14 rounded-10 bg-white">
+  //       <View className="min-h-24 flex items-center flex-1">
+  //         <Textarea
+  //           adjustPosition={false}
+  //           disabled={disabled}
+  //           className="flex-1 w-auto"
+  //           // 必须添加 height 与 maxHeight 否则在初始化时高度会先 maxheight 再跳回到 lineHeight,导致闪烁和 高度计算错误
+  //           style={{'borderRadius': '0px', maxHeight: '120px', 'lineHeight': '24px', 'height': '24px'}}
+  //           autoHeight
+  //           placeholder="有问题尽管问我..."
+  //           value={value}
+  //           cursorSpacing={400}
+  //           onConfirm={handleConfirm}
+  //           confirmType="send"
+  //           disable-default-padding
+  //           onInput={(e: any) => handleInput(e.target.value)}
+  //         />
+  //       </View>
+  //       <View className="flex items-center gap-12 leading-24 h-24">
+  //         {!value.length && <View className="flex-center" onClick={onIconClick}><IconMic /></View>}
+  //         {!messageStopHandle &&  <View className={`flex-center ${!!value.length ? '':'opacity-50'}`} onClick={handleConfirm}><IconSend /></View>}
+  //         {!!messageStopHandle && <View className="flex-center" onClick={handleStopClick}><IconStop /></View>}
+  //       </View>
+  //     </View>
+  // </View>
 }

+ 104 - 0
src/pages/chat/components/InputBar/TextareaInputAutoHeight.tsx

@@ -0,0 +1,104 @@
+import styleIndex from "./index.module.less";
+import { useState, useRef } from "react";
+import { countCharacters, getStrByMaxLength } from "@/utils/index";
+import { View, Textarea, InputProps, type TextareaProps } from "@tarojs/components";
+
+// 定义一个泛型接口来避免重复声明函数类型的返回值类型
+type RenderFunction = () => JSX.Element | JSX.Element[] | null;
+
+interface IProps extends Partial<Omit<TextareaProps, 'onInput' | 'onBlur' | 'onConfirm'>> {
+  placeholder?: string;
+  value: string;
+  cursorSpacing?: number;
+  maxlength?: number;
+  disabled?: boolean;
+  confirmType?: NonNullable<InputProps['confirmType']>; // 使用 NonNullable 防止 confirmType 被设置为 undefined
+  extra?: RenderFunction;
+  suffix?: RenderFunction;
+  onInput?: (value: string) => void;
+  onBlur?: (value: string) => void;
+  bgColor?: string;
+  extraClass?: string;
+  className?: string;
+  onConfirm?: (value: string) => void;
+  placeholderStyle?: string;
+}
+
+let isInbox = false;
+const index = ({
+  value,
+  className,
+  extraClass,
+  disabled,
+  confirmType,
+  suffix,
+  placeholder = "请输入...",
+  onInput,
+  onBlur,
+  cursorSpacing,
+  maxlength,
+  extra,
+  onConfirm,
+  placeholderStyle,
+  ...rest
+}: IProps) => {
+  const [focus, setFocus] = useState(false);
+  const inputRef = useRef<HTMLInputElement>(null); // 创建一个 ref
+
+  const handleFocus = () => {
+    isInbox = false;
+    setFocus(true);
+  };
+  const handleBlur = () => {
+    // console.log("textarea blur");
+    if (!isInbox) {
+      setFocus(false);
+      if (onBlur && inputRef.current) {
+        onBlur(inputRef.current.value);
+      }
+    }
+  };
+  const handleInput = (value: string) => {
+    const len = countCharacters(value);
+    if (maxlength && len > maxlength) {
+      const r = getStrByMaxLength(value, maxlength);
+      onInput && onInput(r);
+      return;
+    }
+    onInput && onInput(value);
+  };
+
+  return (
+    <View
+      className={`${
+        focus ? styleIndex.inputContainerFocused : styleIndex.inputContainer
+      }  flex items-end px-16 py-12 min-h-52 rounded-10 bg-white`}
+    >
+      <View className="flex items-end flex-1 w-full">
+        <View className="min-h-24 flex items-center flex-1">
+          <Textarea
+            ref={inputRef}
+            value={value}
+            disabled={disabled}
+            confirmType={confirmType}
+            style={{'borderRadius': '0px', maxHeight: '120px', 'lineHeight': '24px', 'height': '24px'}}
+            onInput={(e: any) => handleInput(e.target.value)}
+            placeholder={placeholder}
+            placeholderStyle={placeholderStyle ?? 'color: rgba(17,17,17,.25)'}
+            className={`${styleIndex.textInput} ${extraClass}`}
+            onFocus={handleFocus}
+            onBlur={handleBlur}
+            autoHeight
+            maxlength={10000}
+            onConfirm={(e: any) => {
+              onConfirm && onConfirm(e.detail.value);
+            }}
+            {...rest}
+          />
+        </View>
+        {suffix && suffix()}
+      </View>
+    </View>
+  );
+};
+export default index;

+ 1 - 1
src/pages/chat/components/InputBar/VoiceInputBar.tsx

@@ -70,7 +70,7 @@ export default ({agentId,disabled, onIconClick, onSend, beforeSend, onError}:Pro
   return <>
     {/* <TextInputBar onIconClick={handleTextInputBarSwitch}></TextInputBar> */}
 
-      <View className={`flex bg-white gap-6 items-center px-16 py-6 rounded-10 ${style.speechButton} ${ idle ? '': style.speechButtonActive}`}>
+      <View className={`flex bg-white gap-6 items-center px-16 py-8 h-52 rounded-8 ${style.speechButton} ${ idle ? '': style.speechButtonActive}`}>
         <View
           className="flex-1 flex items-center justify-center leading-34 h-34"
           onLongPress={onLongPress}

+ 47 - 0
src/pages/chat/components/InputBar/index.module.less

@@ -16,3 +16,50 @@
   // background-color: var(--color-primary);
   // background-color: var(--color-primary);
 }
+
+
+
+.inputContainer{
+  display: flex;
+  align-items: center;
+  border-radius: 12px;
+  background-color: white;
+  border: 2px solid transparent;
+}
+.textInput{
+  display: block;
+  font-family: "PingFang SC";
+  font-size: 15px;
+  font-style: normal;
+  font-weight: 400;
+  line-height: 30px;
+  width: 100%;
+  text-align: justify;
+  caret-color: var(--color-primary-dark);
+  &::placeholder{
+    color: rgba(#000, .45);
+    line-height: 24px;
+  }
+}
+.inputContainerFocused{
+  .inputContainer();
+  border: 2px solid var(--color-primary-dark);
+}
+.textareaContainer{
+  flex: 1;
+}
+.textarea{
+  .textInput();
+  width: 100%;
+  height: 236px;
+}
+.textareaButtons{
+  display: flex;
+  align-items: center;
+}
+.textareaButtonLeft{
+  display: flex;
+  flex: 1;
+  align-items: center;
+  gap: 8px;
+}

+ 1 - 1
src/pages/chat/index.module.less

@@ -36,4 +36,4 @@
   text-align: center;
   font-size: 10px;
   color: rgba(#000, .4);
-}
+}