diff --git a/packages/xgen/actions/Common/emitEvent.ts b/packages/xgen/actions/Common/emitEvent.ts new file mode 100644 index 00000000..0de2d3dd --- /dev/null +++ b/packages/xgen/actions/Common/emitEvent.ts @@ -0,0 +1,9 @@ +import type { Action } from '@/types' + +export default () => { + return async (payload: Action.EmitEvent) => { + const { key, value } = payload + + await window.$app.Event.emit(key, value) + } +} diff --git a/packages/xgen/actions/Common/index.ts b/packages/xgen/actions/Common/index.ts index 43ffecc4..65d27e4f 100644 --- a/packages/xgen/actions/Common/index.ts +++ b/packages/xgen/actions/Common/index.ts @@ -5,3 +5,5 @@ export { default as historyBack } from './historyBack' export { default as confirm } from './confirm' export { default as refetch } from './refetch' export { default as reload } from './reload' +export { default as showMessage } from './showMessage' +export { default as emitEvent } from './emitEvent' diff --git a/packages/xgen/actions/Common/showMessage.ts b/packages/xgen/actions/Common/showMessage.ts new file mode 100644 index 00000000..b3c32439 --- /dev/null +++ b/packages/xgen/actions/Common/showMessage.ts @@ -0,0 +1,25 @@ +import { message } from 'antd' + +import type { Action } from '@/types' + +export default () => { + return (payload: Action.ShowMessage) => { + return new Promise((resolve) => { + const { type, content } = payload + + switch (type) { + case 'success': + message.success(content) + break + case 'warning': + message.warning(content) + break + case 'error': + message.error(content) + break + } + + resolve() + }) + } +} diff --git a/packages/xgen/actions/utils/handleActions.ts b/packages/xgen/actions/utils/handleActions.ts index 52e339a9..9059a5b5 100644 --- a/packages/xgen/actions/utils/handleActions.ts +++ b/packages/xgen/actions/utils/handleActions.ts @@ -1,4 +1,14 @@ -import { closeModal, confirm, historyBack, historyPush, openModal, refetch, reload } from '../Common' +import { + closeModal, + confirm, + historyBack, + historyPush, + openModal, + refetch, + reload, + showMessage, + emitEvent +} from '../Common' import { delete as formDelete, find as formFind, fullscreen as formFullscreen, submit as formSubmit } from '../Form' import { delete as TableDelete, save as tableSave, search as tableSearch } from '../Table' import { Service, Studio } from '../Yao' @@ -34,6 +44,12 @@ export default ({ namespace, primary, data_item, it, extra }: OnAction) => { case 'Common.reload': total.push({ task: reload(), ...flow_info }) break + case 'Common.showMessage': + total.push({ task: showMessage(), ...flow_info }) + break + case 'Common.emitEvent': + total.push({ task: emitEvent(), ...flow_info }) + break case 'Table.search': total.push({ task: tableSearch({ namespace }), ...flow_info }) break diff --git a/packages/xgen/components/base/PureForm/components/FormItem.tsx b/packages/xgen/components/base/PureForm/components/FormItem.tsx index 8a431a2f..4f1bf336 100644 --- a/packages/xgen/components/base/PureForm/components/FormItem.tsx +++ b/packages/xgen/components/base/PureForm/components/FormItem.tsx @@ -1,9 +1,9 @@ import { useMemoizedFn } from 'ahooks' -import { Col, Popover, Input } from 'antd' +import { Col, Popover, Input, Button } from 'antd' import clsx from 'clsx' import { observer } from 'mobx-react-lite' import { PaperPlaneTilt } from 'phosphor-react' -import { useMemo, useState, useRef } from 'react' +import { useMemo, useState, useRef, useEffect } from 'react' import { X } from '@/components' import { useGlobal } from '@/context/app' @@ -19,6 +19,15 @@ const Index = (props: IPropsFormItem) => { const global = useGlobal() const input = useRef(null) const [visible, setVisible] = useState(false) + const [loading, setLoading] = useState(false) + + const unLoading = useMemoizedFn(() => setLoading(false)) + + useEffect(() => { + window.$app.Event.on(`${namespace}/${item.bind}/unloading`, unLoading) + + return () => window.$app.Event.off(`${namespace}/${item.bind}/unloading`, unLoading) + }, [namespace, item]) const show_ai = useMemo( () => global.app_info.optional?.neo?.api && item.edit.props?.ai, @@ -38,19 +47,23 @@ const Index = (props: IPropsFormItem) => { const showAI = useMemoizedFn(() => setVisible(true)) - const askAI = useMemoizedFn(() => { + const askAI = useMemoizedFn((e) => { + e.preventDefault() + const target = input?.current?.resizableTextArea?.textArea - + if (!target) return if (!target.value) return window.$app.Event.emit('app/getField', { title: item.name, bind: item.bind, - text: target.value + text: target.value, + config: item }) setVisible(false) + setLoading(true) }) const Ask = ( @@ -83,6 +96,11 @@ const Index = (props: IPropsFormItem) => { AI )} + {loading && ( + + )} { useLayoutEffect(() => { window.$app.Event.on(`${namespace}/submit`, submit) + window.$app.Event.on(`${namespace}/setFieldsValue`, setFieldsValue) - return () => window.$app.Event.off(`${namespace}/submit`, submit) - }, []) + return () => { + window.$app.Event.off(`${namespace}/submit`, submit) + window.$app.Event.off(`${namespace}/setFieldsValue`, setFieldsValue) + } + }, [namespace]) useLayoutEffect(() => { window.$app.Event.emit('app/getContext', { namespace, primary, data_item: data }) diff --git a/packages/xgen/layouts/components/Neo/components/ChatItem/index.less b/packages/xgen/layouts/components/Neo/components/ChatItem/index.less index 845563ea..ce5f2ed2 100644 --- a/packages/xgen/layouts/components/Neo/components/ChatItem/index.less +++ b/packages/xgen/layouts/components/Neo/components/ChatItem/index.less @@ -40,7 +40,13 @@ .confirm_wrap { padding-top: 12px; + .text{ + width: calc(100% - 60px); + } + .btn_yes { + width: 60px; + &:hover { text-decoration: underline; } diff --git a/packages/xgen/layouts/components/Neo/index.tsx b/packages/xgen/layouts/components/Neo/index.tsx index cdfca3b6..a14f3b65 100644 --- a/packages/xgen/layouts/components/Neo/index.tsx +++ b/packages/xgen/layouts/components/Neo/index.tsx @@ -4,7 +4,7 @@ import clsx from 'clsx' import { AnimatePresence, motion } from 'framer-motion' import { ChatCircleText, PaperPlaneTilt, X, ArrowsOutSimple, ArrowsInSimple, Stop } from 'phosphor-react' import { useLayoutEffect, useEffect, useRef, useState, useMemo } from 'react' -import { Else, If, Then } from 'react-if' +import { Else, If, Then, When } from 'react-if' import { fuzzyQuery } from '@/knife' import { useLocation, getLocale } from '@umijs/max' @@ -15,7 +15,7 @@ import { useEventStream } from './hooks' import styles from './index.less' import type { IPropsNeo } from '../../types' -import type { App } from '@/types' +import type { App, Common } from '@/types' const { TextArea } = Input @@ -36,7 +36,8 @@ const Index = (props: IPropsNeo) => { }) const [field, setField] = useState({ name: '', - bind: '' + bind: '', + config: {} as Common.FieldDetail }) const ref = useRef(null) const [value, { onChange }] = useEventTarget({ initialValue: '' }) @@ -66,7 +67,7 @@ const Index = (props: IPropsNeo) => { }, [commands, value, visible_commands]) const getContext = useMemoizedFn((v: App.Context) => setContext(v)) - const getField = useMemoizedFn((v: App.Field & { text: string }) => { + const getField = useMemoizedFn((v: App.Field & { text: string; config: Common.FieldDetail }) => { if (loading) stop() setField(v) @@ -76,11 +77,18 @@ const Index = (props: IPropsNeo) => { { is_neo: false, text: v.text, - context: { stack, pathname, formdata: context.data_item, field: { name: v.name, bind: v.bind } } + context: { + namespace: context.namespace, + stack, + pathname, + formdata: context.data_item, + field: { name: v.name, bind: v.bind }, + config: v.config + } } ]) }) - const setNeoVisible = useMemoizedFn(() => setVisible(true)) + const setNeoVisible = useMemoizedFn((v) => setVisible(v ?? true)) useLayoutEffect(() => { window.$app.Event.on('app/getContext', getContext) @@ -108,7 +116,18 @@ const Index = (props: IPropsNeo) => { setMessages([ ...messages, - { is_neo: false, text: value, context: { stack, pathname, formdata: context.data_item, field } } + { + is_neo: false, + text: value, + context: { + namespace: context.namespace, + stack, + pathname, + formdata: context.data_item, + field: { name: field.name, bind: field.bind }, + config: field.config + } + } ]) setTimeout(() => { @@ -146,6 +165,18 @@ const Index = (props: IPropsNeo) => { ) }, [commands, max, search_commands]) + const exit = useMemoizedFn(() => { + if (cmd?.name) exitCmd() + + if (field.name) { + setField({ + name: '', + bind: '', + config: {} as Common.FieldDetail + }) + } + }) + return (
@@ -163,18 +194,27 @@ const Index = (props: IPropsNeo) => { >
- + -
- - {is_cn ? '命令模式:' : 'Command mode:'} - - {cmd?.name} -
- + {cmd?.name && ( +
+ + {is_cn ? '命令模式:' : 'Command mode:'} + + {cmd?.name} +
+ )} + {field.name && ( +
+ + {is_cn ? '字段模式:' : 'Field mode:'} + + + {field.name}-{field.bind} + +
+ )} + {is_cn ? '退出' : 'Exit'}
diff --git a/packages/xgen/types/action.ts b/packages/xgen/types/action.ts index 55b72ec9..41c5d8ff 100644 --- a/packages/xgen/types/action.ts +++ b/packages/xgen/types/action.ts @@ -36,6 +36,16 @@ export declare namespace Action { neo?: boolean } + interface ShowMessage { + type: 'success' | 'warning' | 'error' + content: string + } + + type EmitEvent = { key: string; value: any } | EventToggleNeo | EventSetFieldsValue | EventUnLoadingAI + type EventToggleNeo = { key: 'setNeoVisible'; value: boolean } + type EventSetFieldsValue = { key: `$namespace/setFieldsValue`; value: Record } + type EventUnLoadingAI = { key: `$namespace/$item.bind/unloading` } + interface ActionMap { 'Common.openModal': OpenModal 'Common.closeModal': {} @@ -44,6 +54,8 @@ export declare namespace Action { 'Common.confirm': Confirm 'Common.refetch': {} 'Common.reload': Reload + 'Common.showMessage': ShowMessage + 'Common.emitEvent': EmitEvent 'Table.search': {} 'Table.save': Global.StringObject 'Table.delete': {} diff --git a/packages/xgen/types/app.ts b/packages/xgen/types/app.ts index b68c18b1..92fd4cb1 100644 --- a/packages/xgen/types/app.ts +++ b/packages/xgen/types/app.ts @@ -1,4 +1,4 @@ -import type { Action } from '@/types' +import type { Action, Common } from '@/types' export declare namespace App { type Theme = 'light' | 'dark' @@ -27,7 +27,14 @@ export declare namespace App { type ChatHuman = { is_neo: boolean text: string - context?: { stack: string; pathname: string; formdata: any; field?: Field } + context?: { + namespace: string + stack: string + pathname: string + formdata: any + field?: Omit + config?: Common.FieldDetail + } } type ChatInfo = ChatHuman | ChatAI @@ -49,6 +56,7 @@ export declare namespace App { interface Field { name: string bind: string + config: Common.FieldDetail } type Role = { diff --git a/packages/xgen/types/common.ts b/packages/xgen/types/common.ts index d957895a..ad9a7baf 100644 --- a/packages/xgen/types/common.ts +++ b/packages/xgen/types/common.ts @@ -26,6 +26,7 @@ export declare namespace Common { } interface FieldDetail { + id: string bind: string view: { bind?: string