Commit b9488cdb authored by tyyin lan's avatar tyyin lan

chore(智能表单): 出差表单功能完善

parent 32a99e0e
......@@ -873,3 +873,6 @@ smart_forms_module:
confirm_submission: 'Confirm submission'
please_enter_the: 'Please enter the'
execution_successful_doc: 'Execution successful doc'
customer_visit: 'Customer visit'
meeting: 'Meeting'
training: 'Training'
......@@ -871,3 +871,6 @@ smart_forms_module:
confirm_submission: '确认提交'
please_enter_the: '请输入'
execution_successful_doc: '出差表单插件执行成功'
customer_visit: '客户拜访'
meeting: '会议'
training: '培训'
......@@ -871,3 +871,6 @@ smart_forms_module:
confirm_submission: '確認提交'
please_enter_the: '請輸入'
execution_successful_doc: '出差表單插件執行成功'
customer_visit: '客戶拜訪'
meeting: '會議'
training: '培訓'
<script setup lang="ts">
import { computed, readonly, useTemplateRef } from 'vue'
import { computed, provide, readonly, useTemplateRef } from 'vue'
import { CheckOne } from '@icon-park/vue-next'
import type { MessageItemInterface } from '../types'
import { useUserStore } from '@/store/modules/user'
......@@ -14,6 +14,7 @@ import AuthorInfo from './author-info.vue'
interface Props {
messageItem: MessageItemInterface
messageItemId: string
}
const props = defineProps<Props>()
......@@ -26,6 +27,8 @@ const userStore = useUserStore()
const markdownRenderRef = useTemplateRef<InstanceType<typeof MarkdownRender>>('markdownRenderRef')
provide('messageItemId', props.messageItemId)
const agentDefaultAvatarUrl = readonly({ url: 'https://gsst-poe-sit.gz.bcebos.com/icon/agent-avatar.png' })
const isAgentMessage = computed(() => {
......@@ -150,10 +153,9 @@ const handleContentEdit = throttle(
<SmartForms
v-else
type="BusinessTripForm"
:message-item="messageItem"
:message-author="messageAuthor"
:is-agent-message="isAgentMessage"
:message-item="messageItem"
:current-bubble-text-color="currentBubbleTextColor"
/>
</div>
......
<script setup lang="ts">
import MessageItem from './message-item.vue'
import type { MessageItemInterface } from '../types'
import { ref, useTemplateRef } from 'vue'
import { provide, ref, useTemplateRef } from 'vue'
import { ScrollbarInst } from 'naive-ui'
import EditorDrawer from '@/components/editor-drawer/editor-drawer.vue'
import { useElementVisibility } from '@vueuse/core'
......@@ -12,12 +12,21 @@ interface Props {
}
defineProps<Props>()
const emit = defineEmits<{
updateSpecifyMessageItem: [messageId: string, newMessageItem: Partial<MessageItemInterface>]
}>()
const scrollbarRef = useTemplateRef<ScrollbarInst | null>('scrollbarRef')
const backBottomBtnFlagRef = useTemplateRef<HTMLDivElement | null>('backBottomBtnFlagRef')
const isNotShowBackBottomBtn = useElementVisibility(backBottomBtnFlagRef)
provide('updateSpecifyMessageItem', {
updateSpecifyMessageItem: (messageId: string, newMessageItem: Partial<MessageItemInterface>) => {
emit('updateSpecifyMessageItem', messageId, newMessageItem)
},
})
const isShowEditorDrawer = ref(false)
const contentEdit = ref('')
......@@ -50,6 +59,7 @@ defineExpose({
<MessageItem
v-for="[key, messageItem] in messageList"
:key="key"
:message-item-id="key"
:message-item="messageItem"
@contentedit="onContentedit"
/>
......
<script setup lang="ts">
import { readonly, ref, useTemplateRef } from 'vue'
import { computed, inject, readonly, ref, useTemplateRef } from 'vue'
import type { MessageItemInterface } from '../../types'
import MarkdownRender from '@/components/markdown-render/markdown-render.vue'
import type { FormInst, FormRules } from 'naive-ui'
import type { FormInst, FormRules, FormItemRule } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { useSystemLanguageStore } from '@/store/modules/system-language'
import MessageBubbleLoading from '../message-bubble-loading.vue'
import isEmail from 'validator/es/lib/isEmail'
interface Props {
isAgentMessage: boolean
messageItem: MessageItemInterface
isAgentMessage: boolean
currentBubbleTextColor: string
messageAuthor: string
}
defineProps<Props>()
const props = defineProps<Props>()
const { t } = useI18n()
const systemLanguageStore = useSystemLanguageStore()
const businessTripFormRef = useTemplateRef<FormInst>('businessTripFormRef')
const messageItemId = inject('messageItemId', '')
const { updateSpecifyMessageItem } = inject<{
updateSpecifyMessageItem: (messageId: string, newMessageItem: Partial<MessageItemInterface>) => void
}>('updateSpecifyMessageItem', {
updateSpecifyMessageItem: () => {},
})
const formRules = readonly<FormRules>({
objective: {
required: true,
......@@ -46,12 +55,20 @@ const formRules = readonly<FormRules>({
email: {
required: true,
trigger: ['blur', 'input'],
message: '',
validator: (_rule: FormItemRule, value: string) => {
if (!value) {
return new Error(t('login_module.please_enter_your_email_address'))
} else if (!isEmail(value)) {
return new Error(t('login_module.please_enter_the_correct_email_address'))
}
return
},
},
})
const formModel = ref({
objective: 'khbf',
objective: 'CustomerVisits',
travelLocation: '',
departureTime: null,
returnTime: null,
......@@ -66,36 +83,37 @@ const formModel = ref({
const objectiveOptions = readonly([
{
label: '客户拜访',
value: 'khbf',
label: t('smart_forms_module.business_trip_form.customer_visit'),
value: 'CustomerVisits',
},
{
label: '会议',
value: 'hy',
label: t('smart_forms_module.business_trip_form.meeting'),
value: 'Meetings',
},
{
label: '培训',
value: 'px',
label: t('smart_forms_module.business_trip_form.training'),
value: 'Training',
},
])
const isDisabledForm = ref(false)
function switchFormDisabledStatus() {
isDisabledForm.value = !isDisabledForm.value
}
const isDisabledForm = computed(() => {
return !!props.messageItem.smartFormInfo && props.messageItem.smartFormInfo.isDisabled
})
function handleSubmitForm() {
businessTripFormRef.value?.validate((errors) => {
if (!errors) {
window.$message.success('提交')
updateSpecifyMessageItem(messageItemId, {
smartFormInfo: {
...(props.messageItem.smartFormInfo || { type: 'BusinessTripForm', params: '' }),
isDisabled: true,
},
})
}
})
}
defineExpose({
switchFormDisabledStatus,
})
</script>
<template>
......@@ -271,7 +289,7 @@ defineExpose({
/>
</n-form-item>
<div class="mt-[30px] text-end">
<div class="mt-[46px] text-end">
<n-button type="primary" :disabled="isDisabledForm" @click="handleSubmitForm">
{{ t('smart_forms_module.business_trip_form.confirm_submission') }}
</n-button>
......
<script setup lang="ts">
import { useTemplateRef } from 'vue'
import type { MessageItemInterface, SmartFormTypes } from '../../types'
import type { MessageItemInterface } from '../../types'
import BusinessTripForm from './business-trip-form.vue'
// import BusinessTripReimbursementForm from './business-trip-reimbursement-form.vue'
interface Props {
type: SmartFormTypes
isAgentMessage: boolean
messageAuthor: string
messageItem: MessageItemInterface
......@@ -13,19 +11,12 @@ interface Props {
}
defineProps<Props>()
const businessTripFormRefList = useTemplateRef<InstanceType<typeof BusinessTripForm>>('businessTripFormComRef')
defineExpose({
businessTripFormRefList,
})
</script>
<template>
<BusinessTripForm
ref="businessTripFormComRef"
:is-agent-message="isAgentMessage"
:message-item="messageItem"
:is-agent-message="isAgentMessage"
:message-author="messageAuthor"
:current-bubble-text-color="currentBubbleTextColor"
/>
......
......@@ -44,32 +44,35 @@ const isShowMessageList = ref(false)
const isAgentInitLoading = ref(true)
const currentFetchEventSourceController = ref<AbortController | null>(null)
// setTimeout(() => {
// messageList.value.set('1', {
// role: 'user',
// agentId: 'b058f1baedd04af983ca00775368bb8c',
// content: '请推荐一些适合初学者的编程学习资源。',
// timestamp: 1726654820427,
// isAnswerLoading: false,
// avatar: 'http://localhost:8848/fe/src/assets/images/home/agent-avatar.png',
// name: '1234',
// reasoningContent: '1324',
// imageUrl: '',
// pluginName: '',
// })
// }, 60)
// messageList.value.set('2', {
// role: 'assistant',
// agentId: 'b058f1baedd04af983ca00775368bb8c',
// content:
// '对于初学者的编程学习资源,可以从以下几个方面进行推荐:\n\n### 一、在线教程与网站\n\n1. **w3school**:这是一个非常全面的编程学习网站,提供了从基础到高级的教程,包括HTML、CSS、JavaScript、SQL等,适合初学者逐步深入学习。\n2. **慕课网**:慕课网上有许多免费课程,涵盖了前端、后端开发,移动开发等多个方面,初学者可以根据自己的兴趣选择相应的课程。\n3. **Coursera**:该网站提供世界名校的网络公开课程,其中也包括计算机编程的相关课程,初学者可以接触到国际一流的教学资源。\n\n### 二、书籍推荐\n\n1. **《Python编程快速上手》**:这本书是为零基础读者打造的Python入门书籍,内容系统且详细,每个知识点都深入浅出,非常适合初学者。\n2. **《C++ Primer Plus》**:这本书是C++语言学习的理想图书,通过大量短小精悍的程序详细阐述了C++的基本概念和技术,对初学者极为友好。\n\n### 三、实践项目与刷题网站\n\n1. **Stack Overflow**:这是一个程序设计领域的问答网站,初学者在遇到编程难题时可以在这里寻找解决方案,同时也可以学习到其他技术大牛的经验和技巧。\n2. **GitHub**:作为全球最大的开源代码托管仓库,GitHub上有无穷无尽的开源代码供初学者学习和参考,阅读源码是一个快速提升编程能力的好方法。\n\n### 四、社区与论坛\n\n1. **CSDN软件开发网**:这是国内知名的软件开发社区,提供了大量的编程资源和经验分享,初学者可以在这里交流学习心得,获取最新的技术动态。\n\n综上所述,初学者可以根据自己的学习需求和兴趣选择合适的编程学习资源。从在线教程、书籍阅读到实践项目和社区交流,多方面的学习将有助于初学者快速掌握编程技能并不断提升自己。',
// timestamp: 1726654851735,
// isAnswerLoading: false,
// avatar: 'http://localhost:8848/fe/src/assets/images/home/agent-avatar.png',
// name: 'lisa',
// reasoningContent:
// '对于初学者的编程学习资源,可以从以下几个方面进行推荐:\n\n### 一、在线教程与网站\n\n1. **w3school**:这是一个非常全面的编程学习网站,提供了从基础到高级的教程,包括HTML、CSS、JavaScript、SQL等,适合初学者逐步深入学习。\n2. **慕课网**:慕课网上有许多免费课程,涵盖了前端、后端开发,移动开发等多个方面,初学者可以根据自己的兴趣选择相应的课程。\n3. **Coursera**:该网站提供世界名校的网络公开课程,其中也包括计算机编程的相关课程,初学者可以接触到国际一流的教学资源。\n\n### 二、书籍推荐\n\n1. **《Python编程快速上手》**:这本书是为零基础读者打造的Python入门书籍,内容系统且详细,每个知识点都深入浅出,非常适合初学者。\n2. **《C++ Primer Plus》**:这本书是C++语言学习的理想图书,通过大量短小精悍的程序详细阐述了C++的基本概念和技术,对初学者极为友好。\n\n### 三、实践项目与刷题网站\n\n1. **Stack Overflow**:这是一个程序设计领域的问答网站,初学者在遇到编程难题时可以在这里寻找解决方案,同时也可以学习到其他技术大牛的经验和技巧。\n2. **GitHub**:作为全球最大的开源代码托管仓库,GitHub上有无穷无尽的开源代码供初学者学习和参考,阅读源码是一个快速提升编程能力的好方法。\n\n### 四、社区与论坛\n\n1. **CSDN软件开发网**:这是国内知名的软件开发社区,提供了大量的编程资源和经验分享,初学者可以在这里交流学习心得,获取最新的技术动态。\n\n综上所述,初学者可以根据自己的学习需求和兴趣选择合适的编程学习资源。从在线教程、书籍阅读到实践项目和社区交流,多方面的学习将有助于初学者快速掌握编程技能并不断提升自己',
// })
/* setTimeout(() => {
messageList.value.set('1', {
role: 'assistant',
agentId: 'b058f1baedd04af983ca00775368bb8c',
content: '请推荐一些适合初学者的编程学习资源。',
timestamp: 1726654820427,
isAnswerLoading: false,
avatar: 'http://localhost:8848/fe/src/assets/images/home/agent-avatar.png',
name: '我是作者',
reasoningContent: '1324',
imageUrl: '',
pluginName: '',
smartFormInfo: { type: 'BusinessTripForm', isDisabled: true, params: '' },
})
messageList.value.set('2', {
role: 'assistant',
agentId: 'b058f1baedd04af983ca00775368bb8c',
content: '请推荐一些适合初学者的编程学习资源。',
timestamp: 1726654820427,
isAnswerLoading: false,
avatar: 'http://localhost:8848/fe/src/assets/images/home/agent-avatar.png',
name: '我是作者',
reasoningContent: '1324',
imageUrl: '',
pluginName: '',
smartFormInfo: { type: 'BusinessTripForm', isDisabled: false, params: '' },
})
}, 60) */
const homeContainerWidthWatchDebounce = debounce((newWidth) => {
if (newWidth <= 1120) {
......@@ -124,6 +127,15 @@ function messageListScrollToBottom() {
}
function onAddMessageItem(messageId: string, messageItem: MessageItemInterface) {
/* 重置智能表单项目 */
if (messageItem.smartFormInfo && messageItem.smartFormInfo.type) {
messageList.value.forEach((messageInfo) => {
if (messageInfo.smartFormInfo && messageInfo.smartFormInfo.type === messageItem.smartFormInfo?.type) {
messageInfo.smartFormInfo.isDisabled = false
}
})
}
messageList.value.set(messageId, messageItem)
}
......@@ -221,7 +233,12 @@ function onClearSessionReferenceFile() {
:current-agent-application="currentAgentApplication"
/>
<MessageList v-show="isShowMessageList" ref="messageListRef" :message-list="messageList" />
<MessageList
v-show="isShowMessageList"
ref="messageListRef"
:message-list="messageList"
@update-specify-message-item="onUpdateSpecifyMessageItem"
/>
<FooterOperation
ref="footerOperationRef"
......
......@@ -10,6 +10,8 @@ export interface AgentApplicationRecordItem {
unitIds: string[]
}
export type SmartFormTypes = 'BusinessTripForm'
export interface MessageItemInterface {
role: 'user' | 'assistant'
agentId: string
......@@ -21,6 +23,10 @@ export interface MessageItemInterface {
pluginName?: string
imageUrl?: string
reasoningContent: string
// isDisabledSmartForm?: boolean
smartFormInfo?: {
type: SmartFormTypes
isDisabled: boolean
params: string
}
}
export type SmartFormTypes = 'BusinessTripForm'
import type { SmartFormTypes } from '../types'
export function smartFormTypeConverter(type: 'travelForm'): SmartFormTypes {
switch (type) {
case 'travelForm':
return 'BusinessTripForm'
}
}
......@@ -893,6 +893,9 @@ declare namespace I18n {
confirm_submission: string
please_enter_the: string
execution_successful_doc: string
customer_visit: string
meeting: string
training: string
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment