Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
P
poc-fe
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
poc
poc-fe
Commits
092f2b8d
Commit
092f2b8d
authored
May 09, 2025
by
tyyin lan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore(智能表单): 出差表单功能完善
parent
b9488cdb
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
160 additions
and
36 deletions
+160
-36
en.yaml
src/locales/langs/en.yaml
+2
-1
zh-cn.yaml
src/locales/langs/zh-cn.yaml
+2
-1
zh-hk.yaml
src/locales/langs/zh-hk.yaml
+2
-1
date-formatter.ts
src/utils/date-formatter.ts
+7
-1
message-item.vue
src/views/home/components/message-item.vue
+1
-1
business-trip-form.vue
src/views/home/components/smart-forms/business-trip-form.vue
+43
-13
types.d.ts
src/views/home/components/smart-forms/types.d.ts
+26
-0
home.vue
src/views/home/home.vue
+43
-17
smart-forms.ts
src/views/home/utils/smart-forms.ts
+32
-0
locales.d.ts
types/locales.d.ts
+2
-1
No files found.
src/locales/langs/en.yaml
View file @
092f2b8d
...
@@ -859,6 +859,7 @@ editor_module:
...
@@ -859,6 +859,7 @@ editor_module:
smart_forms_module
:
smart_forms_module
:
business_trip_form
:
business_trip_form
:
result_doc
:
'
Ok.
I
will
automatically
generate
a
business
trip
form
for
you.
The
form
is
as
follows'
title
:
'
Business
trip
form'
title
:
'
Business
trip
form'
objective
:
'
Objective'
objective
:
'
Objective'
travel_location
:
'
Travel
location'
travel_location
:
'
Travel
location'
...
@@ -867,7 +868,7 @@ smart_forms_module:
...
@@ -867,7 +868,7 @@ smart_forms_module:
vehicle
:
'
Vehicle'
vehicle
:
'
Vehicle'
estimated_cost
:
'
Estimated
cost'
estimated_cost
:
'
Estimated
cost'
residence
:
'
Residence'
residence
:
'
Residence'
estimated_amount
:
'
Estimated
amount'
advance_payment_amount
:
'
Advance
payment
amount'
general_budget
:
'
General
budget'
general_budget
:
'
General
budget'
email
:
'
Email'
email
:
'
Email'
confirm_submission
:
'
Confirm
submission'
confirm_submission
:
'
Confirm
submission'
...
...
src/locales/langs/zh-cn.yaml
View file @
092f2b8d
...
@@ -857,6 +857,7 @@ editor_module:
...
@@ -857,6 +857,7 @@ editor_module:
smart_forms_module
:
smart_forms_module
:
business_trip_form
:
business_trip_form
:
result_doc
:
'
好的,我将为您自动生成出差表单,表单如下'
title
:
'
出差表单'
title
:
'
出差表单'
objective
:
'
出差目的'
objective
:
'
出差目的'
travel_location
:
'
出差地点'
travel_location
:
'
出差地点'
...
@@ -865,7 +866,7 @@ smart_forms_module:
...
@@ -865,7 +866,7 @@ smart_forms_module:
vehicle
:
'
交通工具'
vehicle
:
'
交通工具'
estimated_cost
:
'
预计费用'
estimated_cost
:
'
预计费用'
residence
:
'
住宿地点'
residence
:
'
住宿地点'
estimated_amount
:
'
预计
金额'
advance_payment_amount
:
'
预支
金额'
general_budget
:
'
总预算'
general_budget
:
'
总预算'
email
:
'
邮箱信息'
email
:
'
邮箱信息'
confirm_submission
:
'
确认提交'
confirm_submission
:
'
确认提交'
...
...
src/locales/langs/zh-hk.yaml
View file @
092f2b8d
...
@@ -857,6 +857,7 @@ editor_module:
...
@@ -857,6 +857,7 @@ editor_module:
smart_forms_module
:
smart_forms_module
:
business_trip_form
:
business_trip_form
:
result_doc
:
'
好的,我將為您自動生成出差表單,表單如下'
title
:
'
出差表單'
title
:
'
出差表單'
objective
:
'
出差目的'
objective
:
'
出差目的'
travel_location
:
'
出差地點'
travel_location
:
'
出差地點'
...
@@ -865,7 +866,7 @@ smart_forms_module:
...
@@ -865,7 +866,7 @@ smart_forms_module:
vehicle
:
'
交通工具'
vehicle
:
'
交通工具'
estimated_cost
:
'
預計費用'
estimated_cost
:
'
預計費用'
residence
:
'
住宿地點'
residence
:
'
住宿地點'
estimated_amount
:
'
預計
金額'
advance_payment_amount
:
'
預支
金額'
general_budget
:
'
總預算'
general_budget
:
'
總預算'
email
:
'
郵箱信息'
email
:
'
郵箱信息'
confirm_submission
:
'
確認提交'
confirm_submission
:
'
確認提交'
...
...
src/utils/date-formatter.ts
View file @
092f2b8d
...
@@ -6,6 +6,12 @@ import 'dayjs/locale/zh-cn'
...
@@ -6,6 +6,12 @@ import 'dayjs/locale/zh-cn'
dayjs
.
extend
(
utc
)
dayjs
.
extend
(
utc
)
dayjs
.
extend
(
timezone
)
dayjs
.
extend
(
timezone
)
export
function
formatDateTime
(
date
:
string
|
number
|
Date
,
format
:
string
=
'YYYY-MM-DD HH:mm:ss'
):
string
{
type
DateType
=
string
|
number
|
Date
export
function
formatDateTime
(
date
:
DateType
,
format
:
string
=
'YYYY-MM-DD HH:mm:ss'
):
string
{
return
dayjs
(
date
).
format
(
format
)
return
dayjs
(
date
).
format
(
format
)
}
}
export
function
getDayInst
(
date
:
DateType
)
{
return
dayjs
(
date
)
}
src/views/home/components/message-item.vue
View file @
092f2b8d
...
@@ -75,7 +75,7 @@ const handleContentEdit = throttle(
...
@@ -75,7 +75,7 @@ const handleContentEdit = throttle(
<div
class=
"flex"
>
<div
class=
"flex"
>
<img
class=
"h-[36px] w-[36px] rounded-[6px] object-cover"
:src=
"avatarUrl"
alt=
"Avatar"
/>
<img
class=
"h-[36px] w-[36px] rounded-[6px] object-cover"
:src=
"avatarUrl"
alt=
"Avatar"
/>
<div
v-if=
"
tru
e"
class=
"ml-[11px] overflow-hidden"
>
<div
v-if=
"
fals
e"
class=
"ml-[11px] overflow-hidden"
>
<AuthorInfo
:is-agent-message=
"isAgentMessage"
:message-item=
"messageItem"
:message-author=
"messageAuthor"
/>
<AuthorInfo
:is-agent-message=
"isAgentMessage"
:message-item=
"messageItem"
:message-author=
"messageAuthor"
/>
<div
<div
...
...
src/views/home/components/smart-forms/business-trip-form.vue
View file @
092f2b8d
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
computed
,
inject
,
readonly
,
ref
,
useTemplateRef
}
from
'vue'
import
{
computed
,
inject
,
readonly
,
ref
,
useTemplateRef
,
watch
}
from
'vue'
import
type
{
MessageItemInterface
}
from
'../../types'
import
type
{
MessageItemInterface
}
from
'../../types'
import
MarkdownRender
from
'@/components/markdown-render/markdown-render.vue'
import
MarkdownRender
from
'@/components/markdown-render/markdown-render.vue'
import
type
{
FormInst
,
FormRules
,
FormItemRule
}
from
'naive-ui'
import
type
{
FormInst
,
FormRules
,
FormItemRule
}
from
'naive-ui'
...
@@ -7,6 +7,8 @@ import { useI18n } from 'vue-i18n'
...
@@ -7,6 +7,8 @@ import { useI18n } from 'vue-i18n'
import
{
useSystemLanguageStore
}
from
'@/store/modules/system-language'
import
{
useSystemLanguageStore
}
from
'@/store/modules/system-language'
import
MessageBubbleLoading
from
'../message-bubble-loading.vue'
import
MessageBubbleLoading
from
'../message-bubble-loading.vue'
import
isEmail
from
'validator/es/lib/isEmail'
import
isEmail
from
'validator/es/lib/isEmail'
import
type
{
BusinessTripForm
,
ResponseBusinessTripForm
}
from
'./types'
import
{
businessTripFormParser
}
from
'../../utils/smart-forms'
interface
Props
{
interface
Props
{
messageItem
:
MessageItemInterface
messageItem
:
MessageItemInterface
...
@@ -67,16 +69,16 @@ const formRules = readonly<FormRules>({
...
@@ -67,16 +69,16 @@ const formRules = readonly<FormRules>({
},
},
})
})
const
formModel
=
ref
({
const
formModel
=
ref
<
BusinessTripForm
>
({
objective
:
'CustomerVisits'
,
objective
:
'CustomerVisits'
,
travelLocation
:
''
,
travelLocation
:
''
,
departureTime
:
null
,
departureTime
:
null
,
returnTime
:
null
,
returnTime
:
null
,
vehicle
:
''
,
vehicle
:
''
,
vehicleEstimatedCost
:
''
,
vehicleEstimatedCost
:
null
,
residence
:
''
,
residence
:
''
,
residenceEstimatedCost
:
''
,
residenceEstimatedCost
:
null
,
estimatedAmount
:
''
,
advancePaymentAmount
:
null
,
generalBudget
:
''
,
generalBudget
:
''
,
email
:
''
,
email
:
''
,
})
})
...
@@ -100,6 +102,30 @@ const isDisabledForm = computed(() => {
...
@@ -100,6 +102,30 @@ const isDisabledForm = computed(() => {
return
!!
props
.
messageItem
.
smartFormInfo
&&
props
.
messageItem
.
smartFormInfo
.
isDisabled
return
!!
props
.
messageItem
.
smartFormInfo
&&
props
.
messageItem
.
smartFormInfo
.
isDisabled
})
})
watch
(
()
=>
props
.
messageItem
.
smartFormInfo
,
(
smartFormInfo
)
=>
{
if
(
smartFormInfo
&&
smartFormInfo
.
params
)
{
let
config
:
Partial
<
ResponseBusinessTripForm
>
=
{}
try
{
config
=
JSON
.
parse
(
smartFormInfo
.
params
)
}
catch
(
err
)
{
throw
new
Error
(
'Invalid JSON'
)
}
formModel
.
value
=
{
...
formModel
.
value
,
...
businessTripFormParser
(
config
),
}
}
},
{
once
:
true
,
immediate
:
true
,
},
)
function
handleSubmitForm
()
{
function
handleSubmitForm
()
{
businessTripFormRef
.
value
?.
validate
((
errors
)
=>
{
businessTripFormRef
.
value
?.
validate
((
errors
)
=>
{
if
(
!
errors
)
{
if
(
!
errors
)
{
...
@@ -149,7 +175,7 @@ function handleSubmitForm() {
...
@@ -149,7 +175,7 @@ function handleSubmitForm() {
<MarkdownRender
<MarkdownRender
ref=
"markdownRenderRef"
ref=
"markdownRenderRef"
raw-text-content=
"好的,我将为您自动生成出差表单,表单如下
"
:raw-text-content=
"t('smart_forms_module.business_trip_form.result_doc')
"
:color=
"currentBubbleTextColor"
:color=
"currentBubbleTextColor"
/>
/>
...
@@ -225,9 +251,10 @@ function handleSubmitForm() {
...
@@ -225,9 +251,10 @@ function handleSubmitForm() {
</n-form-item>
</n-form-item>
<n-form-item
:label=
"t('smart_forms_module.business_trip_form.estimated_cost')"
path=
"vehicleEstimatedCost"
>
<n-form-item
:label=
"t('smart_forms_module.business_trip_form.estimated_cost')"
path=
"vehicleEstimatedCost"
>
<n-input
<n-input
-number
v-model:value=
"formModel.vehicleEstimatedCost"
v-model:value=
"formModel.vehicleEstimatedCost"
:placeholder=
"`${t('smart_forms_module.business_trip_form.please_enter_the')} ${t('smart_forms_module.business_trip_form.estimated_cost').toLocaleLowerCase()}`"
:placeholder=
"`${t('smart_forms_module.business_trip_form.please_enter_the')} ${t('smart_forms_module.business_trip_form.estimated_cost').toLocaleLowerCase()}`"
clearable
/>
/>
</n-form-item>
</n-form-item>
...
@@ -250,9 +277,10 @@ function handleSubmitForm() {
...
@@ -250,9 +277,10 @@ function handleSubmitForm() {
:label=
"t('smart_forms_module.business_trip_form.estimated_cost')"
:label=
"t('smart_forms_module.business_trip_form.estimated_cost')"
path=
"residenceEstimatedCost"
path=
"residenceEstimatedCost"
>
>
<n-input
<n-input
-number
v-model:value=
"formModel.residenceEstimatedCost"
v-model:value=
"formModel.residenceEstimatedCost"
:placeholder=
"`${t('smart_forms_module.business_trip_form.please_enter_the')} ${t('smart_forms_module.business_trip_form.estimated_cost').toLocaleLowerCase()}`"
:placeholder=
"`${t('smart_forms_module.business_trip_form.please_enter_the')} ${t('smart_forms_module.business_trip_form.estimated_cost').toLocaleLowerCase()}`"
clearable
/>
/>
</n-form-item>
</n-form-item>
...
@@ -262,12 +290,13 @@ function handleSubmitForm() {
...
@@ -262,12 +290,13 @@ function handleSubmitForm() {
<n-form-item
<n-form-item
class=
"mb-[10px]"
class=
"mb-[10px]"
:label=
"t('smart_forms_module.business_trip_form.
estimated
_amount')"
:label=
"t('smart_forms_module.business_trip_form.
advance_payment
_amount')"
path=
"
estimated
Amount"
path=
"
advancePayment
Amount"
>
>
<n-input
<n-input-number
v-model:value=
"formModel.estimatedAmount"
v-model:value=
"formModel.advancePaymentAmount"
:placeholder=
"`${t('smart_forms_module.business_trip_form.please_enter_the')} ${t('smart_forms_module.business_trip_form.estimated_amount').toLocaleLowerCase()}`"
:placeholder=
"`${t('smart_forms_module.business_trip_form.please_enter_the')} ${t('smart_forms_module.business_trip_form.advance_payment_amount').toLocaleLowerCase()}`"
clearable
/>
/>
</n-form-item>
</n-form-item>
...
@@ -275,6 +304,7 @@ function handleSubmitForm() {
...
@@ -275,6 +304,7 @@ function handleSubmitForm() {
<n-input
<n-input
v-model:value=
"formModel.generalBudget"
v-model:value=
"formModel.generalBudget"
:placeholder=
"`${t('smart_forms_module.business_trip_form.please_enter_the')} ${t('smart_forms_module.business_trip_form.general_budget').toLocaleLowerCase()}`"
:placeholder=
"`${t('smart_forms_module.business_trip_form.please_enter_the')} ${t('smart_forms_module.business_trip_form.general_budget').toLocaleLowerCase()}`"
disabled
/>
/>
</n-form-item>
</n-form-item>
...
...
src/views/home/components/smart-forms/types.d.ts
0 → 100644
View file @
092f2b8d
export
interface
ResponseBusinessTripForm
{
purpose
:
string
place
:
string
departureDate
:
string
returnDate
:
string
vehicle
:
string
transportationFee
:
string
accommodation
:
string
accommodationCost
:
string
advancePaymentAmount
:
string
totalBudget
:
string
}
export
interface
BusinessTripForm
{
objective
:
string
travelLocation
:
string
departureTime
:
number
|
null
returnTime
:
number
|
null
vehicle
:
string
vehicleEstimatedCost
:
number
|
null
residence
:
string
residenceEstimatedCost
:
number
|
null
advancePaymentAmount
:
number
|
null
generalBudget
:
string
email
:
string
}
src/views/home/home.vue
View file @
092f2b8d
...
@@ -44,20 +44,20 @@ const isShowMessageList = ref(false)
...
@@ -44,20 +44,20 @@ const isShowMessageList = ref(false)
const
isAgentInitLoading
=
ref
(
true
)
const
isAgentInitLoading
=
ref
(
true
)
const
currentFetchEventSourceController
=
ref
<
AbortController
|
null
>
(
null
)
const
currentFetchEventSourceController
=
ref
<
AbortController
|
null
>
(
null
)
/*
setTimeout(() => {
setTimeout
(()
=>
{
messageList.value.set('1', {
//
messageList.value.set('1', {
role: 'assistant',
//
role: 'assistant',
agentId: 'b058f1baedd04af983ca00775368bb8c',
//
agentId: 'b058f1baedd04af983ca00775368bb8c',
content: '请推荐一些适合初学者的编程学习资源。',
//
content: '请推荐一些适合初学者的编程学习资源。',
timestamp: 1726654820427,
//
timestamp: 1726654820427,
isAnswerLoading: false,
//
isAnswerLoading: false,
avatar: 'http://localhost:8848/fe/src/assets/images/home/agent-avatar.png',
//
avatar: 'http://localhost:8848/fe/src/assets/images/home/agent-avatar.png',
name: '我是作者',
//
name: '我是作者',
reasoningContent: '1324',
//
reasoningContent: '1324',
imageUrl: '',
//
imageUrl: '',
pluginName: '',
//
pluginName: '',
smartFormInfo: { type: 'BusinessTripForm', isDisabled: true, params: '' },
//
smartFormInfo: { type: 'BusinessTripForm', isDisabled: true, params: '' },
})
//
})
messageList
.
value
.
set
(
'2'
,
{
messageList
.
value
.
set
(
'2'
,
{
role
:
'assistant'
,
role
:
'assistant'
,
...
@@ -70,9 +70,35 @@ const currentFetchEventSourceController = ref<AbortController | null>(null)
...
@@ -70,9 +70,35 @@ const currentFetchEventSourceController = ref<AbortController | null>(null)
reasoningContent
:
'1324'
,
reasoningContent
:
'1324'
,
imageUrl
:
''
,
imageUrl
:
''
,
pluginName
:
''
,
pluginName
:
''
,
smartFormInfo: { type: 'BusinessTripForm', isDisabled: false, params: '' },
smartFormInfo
:
{
type
:
'BusinessTripForm'
,
isDisabled
:
false
,
params
:
'{"purpose":"Training","place":"香港","departureDate":"returnDate","accommodationCost":"11","departureDate":"2025-05-10 15:00:00","advancePaymentAmount":"11","totalBudget":"11"}'
,
},
})
})
}, 60) */
},
60
)
// setTimeout(() => {
// onAddMessageItem('3', {
// 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:
// '{"purpose":"Training","place":"香港","departureDate":"returnDate","accommodationCost":"11","departureDate":"2025-05-10 15:00:00","advancePaymentAmount":"11","totalBudget":"11"}',
// },
// })
// }, 2000)
const
homeContainerWidthWatchDebounce
=
debounce
((
newWidth
)
=>
{
const
homeContainerWidthWatchDebounce
=
debounce
((
newWidth
)
=>
{
if
(
newWidth
<=
1120
)
{
if
(
newWidth
<=
1120
)
{
...
@@ -131,7 +157,7 @@ function onAddMessageItem(messageId: string, messageItem: MessageItemInterface)
...
@@ -131,7 +157,7 @@ function onAddMessageItem(messageId: string, messageItem: MessageItemInterface)
if
(
messageItem
.
smartFormInfo
&&
messageItem
.
smartFormInfo
.
type
)
{
if
(
messageItem
.
smartFormInfo
&&
messageItem
.
smartFormInfo
.
type
)
{
messageList
.
value
.
forEach
((
messageInfo
)
=>
{
messageList
.
value
.
forEach
((
messageInfo
)
=>
{
if
(
messageInfo
.
smartFormInfo
&&
messageInfo
.
smartFormInfo
.
type
===
messageItem
.
smartFormInfo
?.
type
)
{
if
(
messageInfo
.
smartFormInfo
&&
messageInfo
.
smartFormInfo
.
type
===
messageItem
.
smartFormInfo
?.
type
)
{
messageInfo
.
smartFormInfo
.
isDisabled
=
fals
e
messageInfo
.
smartFormInfo
.
isDisabled
=
tru
e
}
}
})
})
}
}
...
...
src/views/home/utils/smart-forms.ts
View file @
092f2b8d
import
type
{
SmartFormTypes
}
from
'../types'
import
type
{
SmartFormTypes
}
from
'../types'
import
{
ResponseBusinessTripForm
,
BusinessTripForm
}
from
'@/views/home/components/smart-forms/types'
export
function
smartFormTypeConverter
(
type
:
'travelForm'
):
SmartFormTypes
{
export
function
smartFormTypeConverter
(
type
:
'travelForm'
):
SmartFormTypes
{
switch
(
type
)
{
switch
(
type
)
{
...
@@ -6,3 +7,34 @@ export function smartFormTypeConverter(type: 'travelForm'): SmartFormTypes {
...
@@ -6,3 +7,34 @@ export function smartFormTypeConverter(type: 'travelForm'): SmartFormTypes {
return
'BusinessTripForm'
return
'BusinessTripForm'
}
}
}
}
export
function
businessTripFormParser
(
resForm
:
Partial
<
ResponseBusinessTripForm
>
)
{
return
{
objective
:
resForm
.
purpose
||
'CustomerVisits'
,
travelLocation
:
resForm
.
place
||
''
,
departureTime
:
resForm
.
departureDate
?
Date
.
parse
(
resForm
.
departureDate
)
:
null
,
returnTime
:
resForm
.
returnDate
?
Date
.
parse
(
resForm
.
returnDate
)
:
null
,
vehicle
:
resForm
.
vehicle
||
''
,
vehicleEstimatedCost
:
resForm
.
transportationFee
?
Number
.
parseInt
(
resForm
.
transportationFee
)
:
null
,
residence
:
resForm
.
accommodation
||
''
,
residenceEstimatedCost
:
resForm
.
accommodationCost
?
Number
.
parseInt
(
resForm
.
accommodationCost
)
:
null
,
advancePaymentAmount
:
resForm
.
advancePaymentAmount
?
Number
.
parseInt
(
resForm
.
advancePaymentAmount
)
:
null
,
generalBudget
:
resForm
.
totalBudget
||
''
,
email
:
''
,
}
}
export
function
businessTripFormReturner
(
form
:
BusinessTripForm
)
{
return
{
purpose
:
form
.
objective
,
place
:
form
.
travelLocation
,
departureDate
:
form
.
departureTime
,
returnDate
:
form
.
returnTime
,
vehicle
:
form
.
vehicle
,
transportationFee
:
form
.
vehicleEstimatedCost
,
accommodation
:
form
.
residence
,
accommodationCost
:
form
.
residenceEstimatedCost
,
advancePaymentAmount
:
form
.
advancePaymentAmount
,
totalBudget
:
form
.
generalBudget
,
}
}
types/locales.d.ts
View file @
092f2b8d
...
@@ -879,6 +879,7 @@ declare namespace I18n {
...
@@ -879,6 +879,7 @@ declare namespace I18n {
smart_forms_module
:
{
smart_forms_module
:
{
business_trip_form
:
{
business_trip_form
:
{
result_doc
:
string
title
:
string
title
:
string
objective
:
string
objective
:
string
travel_location
:
string
travel_location
:
string
...
@@ -887,7 +888,7 @@ declare namespace I18n {
...
@@ -887,7 +888,7 @@ declare namespace I18n {
vehicle
:
string
vehicle
:
string
estimated_cost
:
string
estimated_cost
:
string
residence
:
string
residence
:
string
estimated
_amount
:
string
advance_payment
_amount
:
string
general_budget
:
string
general_budget
:
string
email
:
string
email
:
string
confirm_submission
:
string
confirm_submission
:
string
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment