提交 d18d0158 authored 作者: songchuancai's avatar songchuancai

修改版本v1.5.1

上级 f3d64c0a
...@@ -43,8 +43,7 @@ ...@@ -43,8 +43,7 @@
"vue-clipboard3": "^2.0.0", "vue-clipboard3": "^2.0.0",
"vue-codemirror": "^6.1.1", "vue-codemirror": "^6.1.1",
"vue-i18n": "^9.13.1", "vue-i18n": "^9.13.1",
"vue-router": "^4.2.4", "vue-router": "^4.2.4"
"recorder-core": "^1.3.24040900"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.3.2", "@rushstack/eslint-patch": "^1.3.2",
......
import { Result } from '@/request/Result' import { Result } from '@/request/Result'
import { get, post, postStream, del, put, request, download } from '@/request/index' import { get, post, postStream, del, put } from '@/request/index'
import type { pageRequest } from '@/api/type/common' import type { pageRequest } from '@/api/type/common'
import type { ApplicationFormType } from '@/api/type/application' import type { ApplicationFormType } from '@/api/type/application'
import { type Ref } from 'vue' import { type Ref } from 'vue'
import type { FormField } from '@/components/dynamics-form/type' import type { FormField } from '@/components/dynamics-form/type'
const prefix = '/application' const prefix = '/application'
/** /**
...@@ -239,48 +238,6 @@ const getApplicationModel: ( ...@@ -239,48 +238,6 @@ const getApplicationModel: (
} }
/** /**
* 获取当前用户可使用的模型列表
* @param application_id
* @param loading
* @query { query_text: string, top_number: number, similarity: number }
* @returns
*/
const getApplicationRerankerModel: (
application_id: string,
loading?: Ref<boolean>
) => Promise<Result<Array<any>>> = (application_id, loading) => {
return get(`${prefix}/${application_id}/model`, { model_type: 'RERANKER' }, loading)
}
/**
* 获取当前用户可使用的模型列表
* @param application_id
* @param loading
* @query { query_text: string, top_number: number, similarity: number }
* @returns
*/
const getApplicationSTTModel: (
application_id: string,
loading?: Ref<boolean>
) => Promise<Result<Array<any>>> = (application_id, loading) => {
return get(`${prefix}/${application_id}/model`, { model_type: 'STT' }, loading)
}
/**
* 获取当前用户可使用的模型列表
* @param application_id
* @param loading
* @query { query_text: string, top_number: number, similarity: number }
* @returns
*/
const getApplicationTTSModel: (
application_id: string,
loading?: Ref<boolean>
) => Promise<Result<Array<any>>> = (application_id, loading) => {
return get(`${prefix}/${application_id}/model`, { model_type: 'TTS' }, loading)
}
/**
* 发布应用 * 发布应用
* @param 参数 * @param 参数
*/ */
...@@ -331,63 +288,6 @@ const getModelParamsForm: ( ...@@ -331,63 +288,6 @@ const getModelParamsForm: (
) => Promise<Result<Array<FormField>>> = (application_id, model_id, loading) => { ) => Promise<Result<Array<FormField>>> = (application_id, model_id, loading) => {
return get(`${prefix}/${application_id}/model_params_form/${model_id}`, undefined, loading) return get(`${prefix}/${application_id}/model_params_form/${model_id}`, undefined, loading)
} }
/**
* 语音转文本
*/
const postSpeechToText: (
application_id: String,
data: any,
loading?: Ref<boolean>
) => Promise<Result<any>> = (application_id, data, loading) => {
return post(`${prefix}/${application_id}/speech_to_text`, data, undefined, loading)
}
/**
* 语音转文本
*/
const postTextToSpeech: (
application_id: String,
data: any,
loading?: Ref<boolean>
) => Promise<Result<any>> = (application_id, data, loading) => {
return download(`${prefix}/${application_id}/text_to_speech`, 'post', data, undefined, loading)
}
/**
* 获取平台状态
*/
const getPlatformStatus: (application_id: string) => Promise<Result<any>> = (application_id) => {
return get(`/platform/${application_id}/status`)
}
/**
* 获取平台配置
*/
const getPlatformConfig: (application_id: string, type: string) => Promise<Result<any>> = (
application_id,
type
) => {
return get(`/platform/${application_id}/${type}`)
}
/**
* 更新平台配置
*/
const updatePlatformConfig: (
application_id: string,
type: string,
data: any
) => Promise<Result<any>> = (application_id, type, data) => {
return post(`/platform/${application_id}/${type}`, data)
}
/**
* 更新平台状态
*/
const updatePlatformStatus: (application_id: string, data: any) => Promise<Result<any>> = (
application_id,
data
) => {
return post(`/platform/${application_id}/status`, data)
}
export default { export default {
getAllAppilcation, getAllAppilcation,
getApplication, getApplication,
...@@ -410,14 +310,5 @@ export default { ...@@ -410,14 +310,5 @@ export default {
postWorkflowChatOpen, postWorkflowChatOpen,
listFunctionLib, listFunctionLib,
getFunctionLib, getFunctionLib,
getModelParamsForm, getModelParamsForm
getApplicationRerankerModel,
getApplicationSTTModel,
getApplicationTTSModel,
postSpeechToText,
postTextToSpeech,
getPlatformStatus,
getPlatformConfig,
updatePlatformConfig,
updatePlatformStatus
} }
...@@ -212,19 +212,6 @@ const postQADocument: ( ...@@ -212,19 +212,6 @@ const postQADocument: (
} }
/** /**
* 导入表格
* @param 参数
* file
*/
const postTableDocument: (
dataset_id: string,
data: any,
loading?: Ref<boolean>
) => Promise<Result<any>> = (dataset_id, data, loading) => {
return post(`${prefix}/${dataset_id}/document/table`, data, undefined, loading)
}
/**
* 批量迁移文档 * 批量迁移文档
* @param 参数 dataset_id,target_dataset_id, * @param 参数 dataset_id,target_dataset_id,
*/ */
...@@ -270,18 +257,6 @@ const exportQATemplate: (fileName: string, type: string, loading?: Ref<boolean>) ...@@ -270,18 +257,6 @@ const exportQATemplate: (fileName: string, type: string, loading?: Ref<boolean>)
} }
/** /**
* 获得table模版
* @param 参数 fileName,type,
*/
const exportTableTemplate: (fileName: string, type: string, loading?: Ref<boolean>) => void = (
fileName,
type,
loading
) => {
return exportExcel(fileName, `${prefix}/document/table_template/export`, { type }, loading)
}
/**
* 导出文档 * 导出文档
* @param document_name 文档名称 * @param document_name 文档名称
* @param dataset_id 数据集id * @param dataset_id 数据集id
...@@ -320,8 +295,6 @@ export default { ...@@ -320,8 +295,6 @@ export default {
putMigrateMulDocument, putMigrateMulDocument,
batchEditHitHandling, batchEditHitHandling,
exportQATemplate, exportQATemplate,
exportTableTemplate,
postQADocument, postQADocument,
postTableDocument,
exportDocument exportDocument
} }
...@@ -14,11 +14,6 @@ interface ApplicationFormType { ...@@ -14,11 +14,6 @@ interface ApplicationFormType {
type?: string type?: string
work_flow?: any work_flow?: any
model_params_setting?: any model_params_setting?: any
stt_model_id?: string
tts_model_id?: string
stt_model_enable?: boolean
tts_model_enable?: boolean
tts_type?: string
} }
interface chatType { interface chatType {
id: string id: string
......
...@@ -39,12 +39,7 @@ ...@@ -39,12 +39,7 @@
<template v-if="item.type === WorkflowType.Start"> <template v-if="item.type === WorkflowType.Start">
<div class="card-never border-r-4"> <div class="card-never border-r-4">
<h5 class="p-8-12">参数输入</h5> <h5 class="p-8-12">参数输入</h5>
<div class="p-8-12 border-t-dashed lighter"> <div class="p-8-12 border-t-dashed lighter">{{ item.question || '-' }}</div>
<div>用户问题: {{ item.question || '-' }}</div>
<div v-for="(f, i) in item.global_fields" :key="i">
{{ f.label }}: {{ f.value }}
</div>
</div>
</div> </div>
</template> </template>
<!-- 知识库检索 --> <!-- 知识库检索 -->
...@@ -167,67 +162,6 @@ ...@@ -167,67 +162,6 @@
</div> </div>
</div> </div>
</template> </template>
<!-- 多路召回 -->
<template v-if="item.type == WorkflowType.RrerankerNode">
<div class="card-never border-r-4">
<h5 class="p-8-12">检索内容</h5>
<div class="p-8-12 border-t-dashed lighter">
<template v-if="item.document_list?.length > 0">
<template
v-for="(paragraph, paragraphIndex) in item.document_list"
:key="paragraphIndex"
>
<CardBox shadow="never" title="" class="cursor mb-8" :showIcon="false">
<template #description>
<el-scrollbar max-height="150">
<MdPreview
ref="editorRef"
editorId="preview-only"
:modelValue="paragraph"
/>
</el-scrollbar>
</template>
</CardBox>
</template>
</template>
<template v-else> - </template>
</div>
</div>
<div class="card-never border-r-4 mt-8">
<h5 class="p-8-12">检索结果</h5>
<div class="p-8-12 border-t-dashed lighter">
<template v-if="item.result_list?.length > 0">
<template
v-for="(paragraph, paragraphIndex) in item.result_list"
:key="paragraphIndex"
>
<CardBox
shadow="never"
:title="''"
class="paragraph-source-card cursor mb-8 paragraph-source-card-height"
:showIcon="false"
>
<div class="active-button primary">
{{ paragraph.metadata.relevance_score?.toFixed(3) }}
</div>
<template #description>
<div class="mt-8">
<el-scrollbar height="150">
<MdPreview
ref="editorRef"
editorId="preview-only"
:modelValue="paragraph.page_content"
/>
</el-scrollbar>
</div>
</template>
</CardBox>
</template>
</template>
<template v-else> - </template>
</div>
</div>
</template>
</template> </template>
<template v-else> <template v-else>
<div class="card-never border-r-4"> <div class="card-never border-r-4">
......
...@@ -66,9 +66,6 @@ function cardLeave() { ...@@ -66,9 +66,6 @@ function cardLeave() {
min-height: var(--card-min-height); min-height: var(--card-min-height);
min-width: var(--card-min-width); min-width: var(--card-min-width);
border-radius: 8px; border-radius: 8px;
.title {
height: 20px;
}
.description { .description {
color: var(--app-text-color-secondary); color: var(--app-text-color-secondary);
line-height: 22px; line-height: 22px;
......
...@@ -551,27 +551,6 @@ export const iconMap: any = { ...@@ -551,27 +551,6 @@ export const iconMap: any = {
]) ])
} }
}, },
'app-warning-colorful': {
iconReader: () => {
return h('i', [
h(
'svg',
{
style: { height: '100%', width: '100%' },
viewBox: '0 0 1024 1024',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg'
},
[
h('path', {
d: 'M42.666667 512c0 259.2 210.133333 469.333333 469.333333 469.333333s469.333333-210.133333 469.333333-469.333333S771.2 42.666667 512 42.666667 42.666667 252.8 42.666667 512z m469.333333-277.333333A53.333333 53.333333 0 1 1 512 341.333333a53.333333 53.333333 0 0 1 0-106.666666zM458.666667 384h64a42.666667 42.666667 0 0 1 42.666666 42.666667v256h53.333334a21.333333 21.333333 0 0 1 21.333333 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333333 21.333333H426.666667a21.333333 21.333333 0 0 1-21.333334-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333334-21.333333h53.333333v-213.333334h-21.333333a21.333333 21.333333 0 0 1-21.333334-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333334-21.333333z',
fill: '#3370FF'
})
]
)
])
}
},
'app-operation': { 'app-operation': {
iconReader: () => { iconReader: () => {
return h('i', [ return h('i', [
...@@ -927,7 +906,23 @@ export const iconMap: any = { ...@@ -927,7 +906,23 @@ export const iconMap: any = {
}, },
[ [
h('path', { h('path', {
d: 'M512 170.666667a85.333333 85.333333 0 0 1 85.333333-85.333334h256a85.333333 85.333333 0 0 1 85.333334 85.333334v256a85.333333 85.333333 0 0 1-85.333334 85.333333h-256a85.333333 85.333333 0 0 1-85.333333-85.333333V170.666667z m85.333333 0v256h256V170.666667h-256zM85.333333 597.333333a85.333333 85.333333 0 0 1 85.333334-85.333333h256a85.333333 85.333333 0 0 1 85.333333 85.333333v256a85.333333 85.333333 0 0 1-85.333333 85.333334H170.666667a85.333333 85.333333 0 0 1-85.333334-85.333334v-256z m85.333334 0v256h256v-256H170.666667zM128 298.666667a213.333333 213.333333 0 0 1 213.333333-213.333334h85.333334v85.333334H341.333333a128 128 0 0 0-128 128h57.514667a12.8 12.8 0 0 1 9.728 21.12l-100.181333 116.906666a12.8 12.8 0 0 1-19.456 0l-100.181334-116.906666A12.8 12.8 0 0 1 70.485333 298.666667H128zM896 725.333333a213.333333 213.333333 0 0 1-213.333333 213.333334h-85.333334v-85.333334h85.333334a128 128 0 0 0 128-128v-21.333333h-57.514667a12.8 12.8 0 0 1-9.728-21.12l100.181333-116.906667a12.8 12.8 0 0 1 19.456 0l100.181334 116.906667a12.8 12.8 0 0 1-9.728 21.12H896v21.333333z', d: 'M494.592 165.12l-320 208a32 32 0 0 0-14.592 26.88v224a32 32 0 0 0 14.592 26.88l320 208a32 32 0 0 0 34.88 0l320-208a32 32 0 0 0 14.528-26.88v-224a32 32 0 0 0-14.528-26.88l-320-208a32 32 0 0 0-34.88 0zM224 417.408L512 230.144l288 187.2V606.72L512 793.856 224 606.656V417.28z',
fill: 'currentColor'
}),
h('path', {
d: 'M512 592a32 32 0 0 0-32 32V832a32 32 0 0 0 64 0V624a32 32 0 0 0-32-32z',
fill: 'currentColor'
}),
h('path', {
d: 'M165.76 381.632a32 32 0 0 0 7.872 44.608l320 224a32 32 0 0 0 36.736 0l320-224a32 32 0 0 0-36.736-52.48L512 584.96l-301.632-211.2a32 32 0 0 0-44.608 7.872z',
fill: 'currentColor'
}),
h('path', {
d: 'M493.632 373.76a32 32 0 0 1 36.736 0l320 224a32 32 0 0 1-36.736 52.48L512 439.04l-301.632 211.2a32 32 0 1 1-36.736-52.48l320-224z',
fill: 'currentColor'
}),
h('path', {
d: 'M512 160a32 32 0 0 0-32 32v208a32 32 0 0 0 64 0V192a32 32 0 0 0-32-32z',
fill: 'currentColor' fill: 'currentColor'
}) })
] ]
...@@ -1101,51 +1096,5 @@ export const iconMap: any = { ...@@ -1101,51 +1096,5 @@ export const iconMap: any = {
) )
]) ])
} }
},
'app-access': {
iconReader: () => {
return h('i', [
h(
'svg',
{
style: { height: '100%', width: '100%' },
viewBox: '0 0 1024 1024',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg'
},
[
h('path', {
d: 'M490.368 48.554667a42.666667 42.666667 0 0 1 43.264 0l362.666667 213.333333A42.666667 42.666667 0 0 1 917.333333 298.666667v426.666666a42.666667 42.666667 0 0 1-21.034666 36.778667l-362.666667 213.333333a42.666667 42.666667 0 0 1-43.264 0l-362.666667-213.333333A42.666667 42.666667 0 0 1 106.666667 725.333333V298.666667a42.666667 42.666667 0 0 1 21.034666-36.778667l362.666667-213.333333zM192 323.072v377.856L512 889.173333l320-188.245333V323.072L512 134.826667 192 323.072z',
fill: 'currentColor'
}),
h('path', {
d: 'M705.194667 441.472a42.666667 42.666667 0 1 0-45.226667-72.362667l-148.096 92.586667L363.946667 369.066667a42.666667 42.666667 0 1 0-45.312 72.362666L469.333333 535.722667V704a42.666667 42.666667 0 1 0 85.333334 0v-168.448l150.528-94.08z',
fill: 'currentColor'
})
]
)
])
}
},
'app-access-active': {
iconReader: () => {
return h('i', [
h(
'svg',
{
style: { height: '100%', width: '100%' },
viewBox: '0 0 1024 1024',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg'
},
[
h('path', {
d: 'M533.632 48.554667a42.666667 42.666667 0 0 0-43.264 0l-362.666667 213.333333A42.666667 42.666667 0 0 0 106.666667 298.666667v426.666666a42.666667 42.666667 0 0 0 21.034666 36.778667l362.666667 213.333333a42.666667 42.666667 0 0 0 43.264 0l362.666667-213.333333A42.666667 42.666667 0 0 0 917.333333 725.333333V298.666667a42.666667 42.666667 0 0 0-21.034666-36.778667l-362.666667-213.333333z m185.130667 334.08a42.666667 42.666667 0 0 1-13.568 58.837333L554.666667 535.552V704a42.666667 42.666667 0 1 1-85.333334 0v-168.277333l-150.613333-94.293334a42.666667 42.666667 0 0 1 45.226667-72.32l147.925333 92.586667 148.053333-92.586667a42.666667 42.666667 0 0 1 58.837334 13.568z',
fill: 'currentColor'
})
]
)
])
}
} }
} }
...@@ -9,8 +9,6 @@ ...@@ -9,8 +9,6 @@
<el-icon><EditPen /></el-icon> <el-icon><EditPen /></el-icon>
{{ item.content }} {{ item.content }}
</div> </div>
<HtmlRander v-else-if="item.type === 'html_rander'" :source="item.content"></HtmlRander>
<MdPreview <MdPreview
v-else v-else
noIconfont noIconfont
...@@ -25,14 +23,12 @@ ...@@ -25,14 +23,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { config } from 'md-editor-v3' import { config } from 'md-editor-v3'
import HtmlRander from './HtmlRander.vue'
config({ config({
markdownItConfig(md) { markdownItConfig(md) {
md.renderer.rules.link_open = (tokens, idx, options, env, self) => { md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
tokens[idx].attrSet('target', '_blank') tokens[idx].attrSet('target', '_blank')
return md.renderer.renderToken(tokens, idx, options) return md.renderer.renderToken(tokens, idx, options)
} }
document.appendChild
} }
}) })
const props = withDefaults( const props = withDefaults(
...@@ -64,7 +60,7 @@ const md_view_list = computed(() => { ...@@ -64,7 +60,7 @@ const md_view_list = computed(() => {
return md_img_list[Math.floor(index / 2)] return md_img_list[Math.floor(index / 2)]
} }
}) })
return split_html_rander(split_quick_question(result)) return split_quick_question(result)
}) })
const split_quick_question = (result: Array<string>) => { const split_quick_question = (result: Array<string>) => {
return result return result
...@@ -99,40 +95,6 @@ const split_quick_question_ = (source: string) => { ...@@ -99,40 +95,6 @@ const split_quick_question_ = (source: string) => {
}) })
return result return result
} }
const split_html_rander = (result: Array<any>) => {
return result
.map((item) => split_html_rander_(item.content, item.type))
.reduce((x: any, y: any) => {
return [...x, ...y]
}, [])
}
const split_html_rander_ = (source: string, type: string) => {
const temp_md_quick_question_list = source.match(/<html_rander>[\d\D]*?<\/html_rander>/g)
const md_quick_question_list = temp_md_quick_question_list
? temp_md_quick_question_list.filter((i) => i)
: []
const split_quick_question_value = source
.split(/<html_rander>[\d\D]*?<\/html_rander>/g)
.filter((item) => item !== undefined)
.filter((item) => !md_quick_question_list?.includes(item))
const result = Array.from(
{ length: md_quick_question_list.length + split_quick_question_value.length },
(v, i) => i
).map((index) => {
if (index % 2 == 0) {
return { type: type, content: split_quick_question_value[Math.floor(index / 2)] }
} else {
return {
type: 'html_rander',
content: md_quick_question_list[Math.floor(index / 2)]
.replace('<html_rander>', '')
.replace('</html_rander>', '')
}
}
})
return result
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.problem-button { .problem-button {
......
...@@ -2,15 +2,3 @@ export enum hitHandlingMethod { ...@@ -2,15 +2,3 @@ export enum hitHandlingMethod {
optimization = '模型优化', optimization = '模型优化',
directly_return = '直接回答' directly_return = '直接回答'
} }
export enum hitStatus {
waiting = '等待中',
processing = '处理中',
completed = '已完成',
failed = '失败'
}
export enum isActivated {
true = '启用',
false = '禁用'
}
...@@ -9,9 +9,7 @@ export enum PermissionDesc { ...@@ -9,9 +9,7 @@ export enum PermissionDesc {
export enum modelType { export enum modelType {
EMBEDDING = '向量模型', EMBEDDING = '向量模型',
LLM = '大语言模型', LLM = '大语言模型'
STT = '语音识别',
TTS = '语音合成',
} }
...@@ -7,6 +7,5 @@ export enum WorkflowType { ...@@ -7,6 +7,5 @@ export enum WorkflowType {
Condition = 'condition-node', Condition = 'condition-node',
Reply = 'reply-node', Reply = 'reply-node',
FunctionLib = 'function-lib-node', FunctionLib = 'function-lib-node',
FunctionLibCustom = 'function-node', FunctionLibCustom = 'function-node'
RrerankerNode = 'reranker-node'
} }
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
<span class="label">授权给</span><span>{{ licenseInfo?.corporation || '-' }}</span> <span class="label">授权给</span><span>{{ licenseInfo?.corporation || '-' }}</span>
</div> </div>
<div class="flex"> <div class="flex">
<span class="label">ISV</span><span>{{ licenseInfo?.isv || '-' }}</span>
</div>
<div class="flex">
<span class="label">到期时间</span> <span class="label">到期时间</span>
<span <span
>{{ licenseInfo?.expired || '-' }} >{{ licenseInfo?.expired || '-' }}
...@@ -49,9 +52,6 @@ ...@@ -49,9 +52,6 @@
<el-button class="border-primary" @click="toSupport">获取技术支持</el-button> <el-button class="border-primary" @click="toSupport">获取技术支持</el-button>
</div> </div>
</div> </div>
<div class="border-t text-center mt-16 p-16 pb-0">
<el-text type="info">2014-2025 版权所有 © 杭州飞致云信息科技有限公司</el-text>
</div>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
......
...@@ -20,43 +20,28 @@ ...@@ -20,43 +20,28 @@
<AppIcon iconName="app-pricing" class="mr-8" style="font-size: 20px"></AppIcon> <AppIcon iconName="app-pricing" class="mr-8" style="font-size: 20px"></AppIcon>
购买专业版 购买专业版
</el-button> </el-button>
<el-tooltip <el-tooltip effect="dark" :content="$t('layout.topbar.github')" placement="top">
effect="dark"
:content="$t('layout.topbar.github')"
placement="top"
v-if="user.themeInfo?.showProject"
>
<AppIcon <AppIcon
iconName="app-github" iconName="app-github"
class="cursor color-secondary mr-8 ml-8" class="cursor color-secondary mr-8 ml-8"
style="font-size: 20px" style="font-size: 20px"
@click="toUrl(user.themeInfo?.projectUrl)" @click="toUrl('https://github.com/1Panel-dev/MaxKB')"
></AppIcon> ></AppIcon>
</el-tooltip> </el-tooltip>
<el-tooltip <el-tooltip effect="dark" :content="$t('layout.topbar.wiki')" placement="top">
effect="dark"
:content="$t('layout.topbar.wiki')"
placement="top"
v-if="user.themeInfo?.showUserManual"
>
<AppIcon <AppIcon
iconName="app-reading" iconName="app-reading"
class="cursor color-secondary mr-8 ml-8" class="cursor color-secondary mr-8 ml-8"
style="font-size: 20px" style="font-size: 20px"
@click="toUrl(user.themeInfo?.userManualUrl)" @click="toUrl('https://maxkb.cn/docs/')"
></AppIcon> ></AppIcon>
</el-tooltip> </el-tooltip>
<el-tooltip <el-tooltip effect="dark" :content="$t('layout.topbar.forum')" placement="top">
effect="dark"
:content="$t('layout.topbar.forum')"
placement="top"
v-if="user.themeInfo?.showForum"
>
<AppIcon <AppIcon
iconName="app-help" iconName="app-help"
class="cursor color-secondary mr-16 ml-8" class="cursor color-secondary mr-16 ml-8"
style="font-size: 20px" style="font-size: 20px"
@click="toUrl(user.themeInfo?.forumUrl)" @click="toUrl('https://bbs.fit2cloud.com/c/mk/11')"
></AppIcon> ></AppIcon>
</el-tooltip> </el-tooltip>
<el-dropdown v-if="false" trigger="click" type="primary"> <el-dropdown v-if="false" trigger="click" type="primary">
......
...@@ -240,23 +240,6 @@ export const exportExcel: ( ...@@ -240,23 +240,6 @@ export const exportExcel: (
.catch((e) => {}) .catch((e) => {})
} }
export const download: (
url: string,
method: string,
data?: any,
params?: any,
loading?: NProgress | Ref<boolean>
) => Promise<any> = (
url: string,
method: string,
data?: any,
params?: any,
loading?: NProgress | Ref<boolean>
) => {
return promise(request({ url: url, method: method, data, params, responseType: 'blob' }), loading)
}
/** /**
* 与服务器建立ws链接 * 与服务器建立ws链接
* @param url websocket路径 * @param url websocket路径
......
import Layout from '@/layout/layout-template/DetailLayout.vue' import Layout from '@/layout/layout-template/DetailLayout.vue'
import { ComplexPermission } from '@/utils/permission/type'
const applicationRouter = { const applicationRouter = {
path: '/application', path: '/application',
name: 'application', name: 'application',
...@@ -53,20 +52,6 @@ const applicationRouter = { ...@@ -53,20 +52,6 @@ const applicationRouter = {
component: () => import('@/views/application/ApplicationSetting.vue') component: () => import('@/views/application/ApplicationSetting.vue')
}, },
{ {
path: 'access',
name: 'AppAccess',
meta: {
icon: 'app-access',
iconActive: 'app-access-active',
title: '应用接入',
active: 'access',
parentPath: '/application/:id/:type',
parentName: 'ApplicationDetail',
permission: new ComplexPermission([], ['x-pack'], 'OR')
},
component: () => import('@/views/application/ApplicationAccess.vue')
},
{
path: 'hit-test', path: 'hit-test',
name: 'AppHitTest', name: 'AppHitTest',
meta: { meta: {
......
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { type Ref } from 'vue' import { type Ref } from 'vue'
import type { User } from '@/api/type/user' import type { User } from '@/api/type/user'
import { cloneDeep } from 'lodash'
import UserApi from '@/api/user' import UserApi from '@/api/user'
import ThemeApi from '@/api/theme' import ThemeApi from '@/api/theme'
import { useElementPlusTheme } from 'use-element-plus-theme' import { useElementPlusTheme } from 'use-element-plus-theme'
...@@ -38,7 +38,7 @@ const useUserStore = defineStore({ ...@@ -38,7 +38,7 @@ const useUserStore = defineStore({
setTheme(data: any) { setTheme(data: any) {
const { changeTheme } = useElementPlusTheme(this.themeInfo?.theme) const { changeTheme } = useElementPlusTheme(this.themeInfo?.theme)
changeTheme(data?.['theme']) changeTheme(data?.['theme'])
this.themeInfo = cloneDeep(data) this.themeInfo = data
}, },
isExpire() { isExpire() {
return this.isXPack && !this.XPACK_LICENSE_IS_VALID return this.isXPack && !this.XPACK_LICENSE_IS_VALID
......
...@@ -304,10 +304,6 @@ h5 { ...@@ -304,10 +304,6 @@ h5 {
color: var(--el-color-primary); color: var(--el-color-primary);
} }
.border-none {
border: none;
}
.cursor { .cursor {
cursor: pointer; cursor: pointer;
} }
...@@ -703,11 +699,10 @@ h5 { ...@@ -703,11 +699,10 @@ h5 {
font-weight: 400; font-weight: 400;
} }
.el-radio-button__original-radio:checked + .el-radio-button__inner { .el-radio-button__original-radio:checked + .el-radio-button__inner {
color: var(--el-color-primary) !important; color: var(--el-color-primary);
background: var(--el-color-primary-light-9) !important; background: var(--el-color-primary-light-9);
border: none !important; border: none;
box-shadow: none !important; box-shadow: none;
font-weight: 500;
} }
} }
......
...@@ -35,14 +35,5 @@ export const defaultSetting = { ...@@ -35,14 +35,5 @@ export const defaultSetting = {
loginLogo: '', loginLogo: '',
loginImage: '', loginImage: '',
title: 'MaxKB', title: 'MaxKB',
slogan: '欢迎使用 MaxKB 智能知识库问答系统' slogan: '欢迎使用 MaxKB 智能知识库'
}
export const defaultPlatformSetting = {
showUserManual: true,
userManualUrl: 'https://maxkb.cn/docs/',
showForum: true,
forumUrl: 'https://bbs.fit2cloud.com/c/mk/11',
showProject: true,
projectUrl: 'https://github.com/1Panel-dev/MaxKB'
} }
...@@ -38,20 +38,19 @@ export function fileType(name: string) { ...@@ -38,20 +38,19 @@ export function fileType(name: string) {
获得文件对应图片 获得文件对应图片
*/ */
const typeList: any = { const typeList: any = {
txt: ['txt', 'pdf', 'docx', 'csv', 'md', 'html'], txt: ['txt', 'pdf', 'docx', 'csv', 'md', 'html', 'PDF'],
table: ['xlsx', 'xls', 'csv'],
QA: ['xlsx', 'csv', 'xls'] QA: ['xlsx', 'csv', 'xls']
} }
export function getImgUrl(name: string) { export function getImgUrl(name: string) {
const list = Object.values(typeList).flat() const list = Object.values(typeList).flat()
const type = list.includes(fileType(name).toLowerCase()) ? fileType(name).toLowerCase() : 'unknow' const type = list.includes(fileType(name.toLowerCase())) ? fileType(name.toLowerCase()) : 'unknow'
return new URL(`../assets/${type}-icon.svg`, import.meta.url).href return new URL(`../assets/${type}-icon.svg`, import.meta.url).href
} }
// 是否是白名单后缀 // 是否是白名单后缀
export function isRightType(name: string, type: string) { export function isRightType(name: string, type: string) {
return typeList[type].includes(fileType(name).toLowerCase()) return typeList[type].includes(fileType(name))
} }
/* /*
......
...@@ -218,7 +218,6 @@ const clickShowDebug = () => { ...@@ -218,7 +218,6 @@ const clickShowDebug = () => {
try { try {
workflow.is_valid() workflow.is_valid()
detail.value = { detail.value = {
...detail.value,
type: 'WORK_FLOW', type: 'WORK_FLOW',
...workflow.get_base_node()?.properties.node_data, ...workflow.get_base_node()?.properties.node_data,
work_flow: getGraphData() work_flow: getGraphData()
...@@ -286,9 +285,6 @@ function getDetail() { ...@@ -286,9 +285,6 @@ function getDetail() {
v['properties']['noRender'] = true v['properties']['noRender'] = true
}) })
detail.value = res.data detail.value = res.data
detail.value.stt_model_id = res.data.stt_model
detail.value.tts_model_id = res.data.tts_model
detail.value.tts_type = res.data.tts_type
saveTime.value = res.data?.update_time saveTime.value = res.data?.update_time
}) })
} }
......
...@@ -288,152 +288,6 @@ ...@@ -288,152 +288,6 @@
</template> </template>
<el-switch size="small" v-model="applicationForm.problem_optimization"></el-switch> <el-switch size="small" v-model="applicationForm.problem_optimization"></el-switch>
</el-form-item> </el-form-item>
<el-form-item>
<template #label>
<div class="flex align-center">
<span class="mr-4">语音输入</span>
<el-tooltip
effect="dark"
content="开启后,需要设定语音转文本模型,语音输入完成后会转化为文字直接发送提问"
placement="right"
>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
<el-switch v-model="applicationForm.stt_model_enable"/>
</div>
</template>
<el-select
v-model="applicationForm.stt_model_id"
class="w-full"
popper-class="select-model"
>
<el-option-group
v-for="(value, label) in sttModelOptions"
:key="value"
:label="relatedObject(providerOptions, label, 'provider')?.name"
>
<el-option
v-for="item in value.filter((v: any) => v.status === 'SUCCESS')"
:key="item.id"
:label="item.name"
:value="item.id"
class="flex-between"
>
<div class="flex align-center">
<span
v-html="relatedObject(providerOptions, label, 'provider')?.icon"
class="model-icon mr-8"
></span>
<span>{{ item.name }}</span>
<el-tag
v-if="item.permission_type === 'PUBLIC'"
type="info"
class="info-tag ml-8"
>公用
</el-tag>
</div>
<el-icon class="check-icon" v-if="item.id === applicationForm.stt_model_id">
<Check />
</el-icon>
</el-option>
<!-- 不可用 -->
<el-option
v-for="item in value.filter((v: any) => v.status !== 'SUCCESS')"
:key="item.id"
:label="item.name"
:value="item.id"
class="flex-between"
disabled
>
<div class="flex">
<span
v-html="relatedObject(providerOptions, label, 'provider')?.icon"
class="model-icon mr-8"
></span>
<span>{{ item.name }}</span>
<span class="danger">{{
$t('views.application.applicationForm.form.aiModel.unavailable')
}}</span>
</div>
<el-icon class="check-icon" v-if="item.id === applicationForm.stt_model_id">
<Check />
</el-icon>
</el-option>
</el-option-group>
</el-select>
</el-form-item>
<el-form-item>
<template #label>
<div class="flex align-center">
<span class="mr-4">语音播放</span>
<el-switch v-model="applicationForm.tts_model_enable"/>
</div>
</template>
<el-radio-group v-model="applicationForm.tts_type">
<el-radio label="浏览器播放(免费)" value="BROWSER"/>
<el-radio label="TTS模型" value="TTS"/>
</el-radio-group>
<el-select
v-if="applicationForm.tts_type === 'TTS'"
v-model="applicationForm.tts_model_id"
class="w-full"
popper-class="select-model"
>
<el-option-group
v-for="(value, label) in ttsModelOptions"
:key="value"
:label="relatedObject(providerOptions, label, 'provider')?.name"
>
<el-option
v-for="item in value.filter((v: any) => v.status === 'SUCCESS')"
:key="item.id"
:label="item.name"
:value="item.id"
class="flex-between"
>
<div class="flex align-center">
<span
v-html="relatedObject(providerOptions, label, 'provider')?.icon"
class="model-icon mr-8"
></span>
<span>{{ item.name }}</span>
<el-tag
v-if="item.permission_type === 'PUBLIC'"
type="info"
class="info-tag ml-8"
>公用
</el-tag>
</div>
<el-icon class="check-icon" v-if="item.id === applicationForm.tts_model_id">
<Check />
</el-icon>
</el-option>
<!-- 不可用 -->
<el-option
v-for="item in value.filter((v: any) => v.status !== 'SUCCESS')"
:key="item.id"
:label="item.name"
:value="item.id"
class="flex-between"
disabled
>
<div class="flex">
<span
v-html="relatedObject(providerOptions, label, 'provider')?.icon"
class="model-icon mr-8"
></span>
<span>{{ item.name }}</span>
<span class="danger">{{
$t('views.application.applicationForm.form.aiModel.unavailable')
}}</span>
</div>
<el-icon class="check-icon" v-if="item.id === applicationForm.tts_model_id">
<Check />
</el-icon>
</el-option>
</el-option-group>
</el-select>
</el-form-item>
</el-form> </el-form>
</el-scrollbar> </el-scrollbar>
</div> </div>
...@@ -557,11 +411,6 @@ const applicationForm = ref<ApplicationFormType>({ ...@@ -557,11 +411,6 @@ const applicationForm = ref<ApplicationFormType>({
}, },
model_params_setting: {}, model_params_setting: {},
problem_optimization: false, problem_optimization: false,
stt_model_id: '',
tts_model_id: '',
stt_model_enable: false,
tts_model_enable: false,
tts_type: 'BROWSER',
type: 'SIMPLE' type: 'SIMPLE'
}) })
...@@ -591,8 +440,6 @@ const rules = reactive<FormRules<ApplicationFormType>>({ ...@@ -591,8 +440,6 @@ const rules = reactive<FormRules<ApplicationFormType>>({
const modelOptions = ref<any>(null) const modelOptions = ref<any>(null)
const providerOptions = ref<Array<Provider>>([]) const providerOptions = ref<Array<Provider>>([])
const datasetList = ref([]) const datasetList = ref([])
const sttModelOptions = ref<any>(null)
const ttsModelOptions = ref<any>(null)
const submit = async (formEl: FormInstance | undefined) => { const submit = async (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
...@@ -661,9 +508,6 @@ function getDetail() { ...@@ -661,9 +508,6 @@ function getDetail() {
application.asyncGetApplicationDetail(id, loading).then((res: any) => { application.asyncGetApplicationDetail(id, loading).then((res: any) => {
applicationForm.value = res.data applicationForm.value = res.data
applicationForm.value.model_id = res.data.model applicationForm.value.model_id = res.data.model
applicationForm.value.stt_model_id = res.data.stt_model
applicationForm.value.tts_model_id = res.data.tts_model
applicationForm.value.tts_type = res.data.tts_type
}) })
} }
...@@ -686,32 +530,6 @@ function getModel() { ...@@ -686,32 +530,6 @@ function getModel() {
}) })
} }
function getSTTModel() {
loading.value = true
applicationApi
.getApplicationSTTModel(id)
.then((res: any) => {
sttModelOptions.value = groupBy(res?.data, 'provider')
loading.value = false
})
.catch(() => {
loading.value = false
})
}
function getTTSModel() {
loading.value = true
applicationApi
.getApplicationTTSModel(id)
.then((res: any) => {
ttsModelOptions.value = groupBy(res?.data, 'provider')
loading.value = false
})
.catch(() => {
loading.value = false
})
}
function getProvider() { function getProvider() {
loading.value = true loading.value = true
model model
...@@ -734,8 +552,6 @@ onMounted(() => { ...@@ -734,8 +552,6 @@ onMounted(() => {
getModel() getModel()
getDataset() getDataset()
getDetail() getDetail()
getSTTModel()
getTTSModel()
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
...@@ -36,11 +36,9 @@ ...@@ -36,11 +36,9 @@
class="AiChat-embed" class="AiChat-embed"
> >
<template #operateBefore> <template #operateBefore>
<div class="chat-width"> <el-button type="primary" link class="new-chat-button mb-8" @click="newChat">
<el-button type="primary" link class="new-chat-button mb-8" @click="newChat"> <el-icon><Plus /></el-icon><span class="ml-4">新建对话</span>
<el-icon><Plus /></el-icon><span class="ml-4">新建对话</span> </el-button>
</el-button>
</div>
</template> </template>
</AiChat> </AiChat>
</div> </div>
...@@ -336,9 +334,5 @@ onMounted(() => { ...@@ -336,9 +334,5 @@ onMounted(() => {
padding-top: 12px; padding-top: 12px;
} }
} }
.chat-width {
max-width: var(--app-chat-width, 860px);
margin: 0 auto;
}
} }
</style> </style>
...@@ -78,21 +78,6 @@ async function next() { ...@@ -78,21 +78,6 @@ async function next() {
router.push({ path: `/dataset/${id}/document` }) router.push({ path: `/dataset/${id}/document` })
}) })
} }
} else if (documentsType.value === 'table') {
let fd = new FormData()
documentsFiles.value.forEach((item: any) => {
if (item?.raw) {
fd.append('file', item?.raw)
}
})
if (id) {
// table文档上传
documentApi.postTableDocument(id as string, fd, loading).then((res) => {
MsgSuccess('提交成功')
clearStore()
router.push({ path: `/dataset/${id}/document` })
})
}
} else { } else {
if (active.value++ > 2) active.value = 0 if (active.value++ > 2) active.value = 0
} }
......
...@@ -7,81 +7,13 @@ ...@@ -7,81 +7,13 @@
label-position="top" label-position="top"
require-asterisk-position="right" require-asterisk-position="right"
> >
<div class="mt-16 mb-16"> <el-form-item>
<el-radio-group v-model="form.fileType" @change="radioChange" class="app-radio-button-group"> <el-radio-group v-model="form.fileType" @change="radioChange">
<el-radio-button value="txt">文本文件</el-radio-button> <el-radio value="txt">文本文件</el-radio>
<el-radio-button value="table">表格</el-radio-button> <el-radio value="QA">QA 问答对</el-radio>
<el-radio-button value="QA">QA 问答对</el-radio-button>
</el-radio-group> </el-radio-group>
</div>
<el-form-item prop="fileList" v-if="form.fileType === 'QA'">
<div class="update-info flex p-8-12 border-r-4 mb-16 w-full">
<div class="mt-4">
<AppIcon iconName="app-warning-colorful" style="font-size: 16px"></AppIcon>
</div>
<div class="ml-16 lighter">
<p>
1、点击下载对应模版并完善信息:
<el-button type="primary" link @click="downloadTemplate('excel')">
下载 Excel 模版
</el-button>
<el-button type="primary" link @click="downloadTemplate('csv')">
下载 CSV 模版
</el-button>
</p>
<p>2、上传的表格文件中每个 sheet 会作为一个文档,sheet名称为文档名称</p>
<p>3、每次最多上传 50 个文件,每个文件不超过 100MB</p>
</div>
</div>
<el-upload
:webkitdirectory="false"
class="w-full mb-4"
drag
multiple
v-model:file-list="form.fileList"
action="#"
:auto-upload="false"
:show-file-list="false"
accept=".xlsx, .xls, .csv"
:limit="50"
:on-exceed="onExceed"
:on-change="fileHandleChange"
@click.prevent="handlePreview(false)"
>
<img src="@/assets/upload-icon.svg" alt="" />
<div class="el-upload__text">
<p>
拖拽文件至此上传或
<em class="hover" @click.prevent="handlePreview(false)"> 选择文件 </em>
<em class="hover" @click.prevent="handlePreview(true)"> 选择文件夹 </em>
</p>
<div class="upload__decoration">
<p>支持格式:EXCEL、CSV</p>
</div>
</div>
</el-upload>
</el-form-item> </el-form-item>
<el-form-item prop="fileList" v-else-if="form.fileType === 'table'"> <el-form-item prop="fileList" v-if="form.fileType === 'QA'">
<div class="update-info flex p-8-12 border-r-4 mb-16 w-full">
<div class="mt-4">
<AppIcon iconName="app-warning-colorful" style="font-size: 16px"></AppIcon>
</div>
<div class="ml-16 lighter">
<p>
1、点击下载对应模版并完善信息:
<el-button type="primary" link @click="downloadTableTemplate('excel')">
下载 Excel 模版
</el-button>
<el-button type="primary" link @click="downloadTableTemplate('csv')">
下载 CSV 模版
</el-button>
</p>
<p>2、第一行必须是列标题,且列标题必须是有意义的术语,表中每条记录将作为一个分段</p>
<p>3、上传的表格文件中每个 sheet 会作为一个文档,sheet名称为文档名称</p>
<p>4、每次最多上传 50 个文件,每个文件不超过 100MB</p>
</div>
</div>
<el-upload <el-upload
:webkitdirectory="false" :webkitdirectory="false"
class="w-full mb-4" class="w-full mb-4"
...@@ -105,21 +37,18 @@ ...@@ -105,21 +37,18 @@
<em class="hover" @click.prevent="handlePreview(true)"> 选择文件夹 </em> <em class="hover" @click.prevent="handlePreview(true)"> 选择文件夹 </em>
</p> </p>
<div class="upload__decoration"> <div class="upload__decoration">
<p>支持格式:EXCEL 和 CSV</p> <p>当前支持 XLSX / XLS / CSV 格式的文档</p>
<p>每次最多上传50个文件,每个文件不超过 100MB</p>
</div> </div>
</div> </div>
</el-upload> </el-upload>
<el-button type="primary" link @click="downloadTemplate('excel')">
下载 Excel 模板
</el-button>
<el-divider direction="vertical" />
<el-button type="primary" link @click="downloadTemplate('csv')"> 下载 CSV 模板 </el-button>
</el-form-item> </el-form-item>
<el-form-item prop="fileList" v-else> <el-form-item prop="fileList" v-else>
<div class="update-info flex p-8-12 border-r-4 mb-16 w-full">
<div class="mt-4">
<AppIcon iconName="app-warning-colorful" style="font-size: 16px"></AppIcon>
</div>
<div class="ml-16 lighter">
<p>1、文件上传前,建议规范文件的分段标识</p>
<p>2、每次最多上传 50 个文件,每个文件不超过 100MB</p>
</div>
</div>
<el-upload <el-upload
:webkitdirectory="false" :webkitdirectory="false"
class="w-full" class="w-full"
...@@ -129,7 +58,7 @@ ...@@ -129,7 +58,7 @@
action="#" action="#"
:auto-upload="false" :auto-upload="false"
:show-file-list="false" :show-file-list="false"
accept=".txt, .md, .csv, .log, .docx, .pdf, .html" accept=".txt, .md, .csv, .log, .docx, .pdf, .html, .PDF"
:limit="50" :limit="50"
:on-exceed="onExceed" :on-exceed="onExceed"
:on-change="fileHandleChange" :on-change="fileHandleChange"
...@@ -143,7 +72,10 @@ ...@@ -143,7 +72,10 @@
<em class="hover" @click.prevent="handlePreview(true)"> 选择文件夹 </em> <em class="hover" @click.prevent="handlePreview(true)"> 选择文件夹 </em>
</p> </p>
<div class="upload__decoration"> <div class="upload__decoration">
<p>支持格式:TXT、Markdown、PDF、DOCX、HTML</p> <p>
支持格式:TXT、Markdown、PDF、DOCX、HTML 每次最多上传50个文件,每个文件不超过 100MB
</p>
<p>若使用【高级分段】建议上传前规范文件的分段标识</p>
</div> </div>
</div> </div>
</el-upload> </el-upload>
...@@ -201,10 +133,6 @@ function downloadTemplate(type: string) { ...@@ -201,10 +133,6 @@ function downloadTemplate(type: string) {
documentApi.exportQATemplate(`${type}模版.${type == 'csv' ? type : 'xlsx'}`, type) documentApi.exportQATemplate(`${type}模版.${type == 'csv' ? type : 'xlsx'}`, type)
} }
function downloadTableTemplate(type: string) {
documentApi.exportTableTemplate(`${type}模版.${type == 'csv' ? type : 'xlsx'}`, type)
}
function radioChange() { function radioChange() {
form.value.fileList = [] form.value.fileList = []
} }
...@@ -284,8 +212,4 @@ defineExpose({ ...@@ -284,8 +212,4 @@ defineExpose({
color: var(--el-color-primary-light-5); color: var(--el-color-primary-light-5);
} }
} }
.update-info {
background: #d6e2ff;
line-height: 25px;
}
</style> </style>
<template> <template>
<el-drawer v-model="debugVisible" size="60%" :append-to-body="true"> <el-drawer v-model="dubugVisible" size="60%" :append-to-body="true">
<template #header> <template #header>
<div class="flex align-center" style="margin-left: -8px"> <div class="flex align-center" style="margin-left: -8px">
<el-button class="cursor mr-4" link @click.prevent="debugVisible = false"> <el-button class="cursor mr-4" link @click.prevent="dubugVisible = false">
<el-icon :size="20"> <el-icon :size="20">
<Back /> <Back />
</el-icon> </el-icon>
...@@ -72,7 +72,7 @@ import type { FormInstance } from 'element-plus' ...@@ -72,7 +72,7 @@ import type { FormInstance } from 'element-plus'
const FormRef = ref() const FormRef = ref()
const loading = ref(false) const loading = ref(false)
const debugVisible = ref(false) const dubugVisible = ref(false)
const showResult = ref(false) const showResult = ref(false)
const isSuccess = ref(false) const isSuccess = ref(false)
const result = ref('') const result = ref('')
...@@ -83,7 +83,7 @@ const form = ref<any>({ ...@@ -83,7 +83,7 @@ const form = ref<any>({
input_field_list: [] input_field_list: []
}) })
watch(debugVisible, (bool) => { watch(dubugVisible, (bool) => {
if (!bool) { if (!bool) {
showResult.value = false showResult.value = false
isSuccess.value = false isSuccess.value = false
...@@ -140,7 +140,7 @@ const open = (data: any) => { ...@@ -140,7 +140,7 @@ const open = (data: any) => {
} }
form.value.code = data.code form.value.code = data.code
form.value.input_field_list = data.input_field_list form.value.input_field_list = data.input_field_list
debugVisible.value = true dubugVisible.value = true
} }
defineExpose({ defineExpose({
......
<template> <template>
<login-layout> <login-layout>
<LoginContainer subTitle="欢迎使用 MaxKB 智能知识库问答系统"> <LoginContainer subTitle="欢迎使用 MaxKB 智能知识库">
<h2 class="mb-24">忘记密码</h2> <h2 class="mb-24">忘记密码</h2>
<el-form <el-form
class="register-form" class="register-form"
......
<template> <template>
<login-layout v-if="user.isEnterprise() ? user.themeInfo : true" v-loading="loading"> <login-layout v-if="user.isEnterprise() ? user.themeInfo : true" v-loading="loading">
<LoginContainer :subTitle="user.themeInfo?.slogan || '欢迎使用 MaxKB 智能知识库问答系统'"> <LoginContainer :subTitle="user.themeInfo?.slogan || '欢迎使用 MaxKB 智能知识库'">
<h2 class="mb-24">{{ loginMode || '普通登录' }}</h2> <h2 class="mb-24">{{ loginMode || '普通登录' }}</h2>
<el-form <el-form
class="login-form" class="login-form"
......
<template> <template>
<login-layout> <login-layout>
<LoginContainer subTitle="欢迎使用 MaxKB 智能知识库问答系统"> <LoginContainer subTitle="欢迎使用 MaxKB 智能知识库">
<h2 class="mb-24">用户注册</h2> <h2 class="mb-24">用户注册</h2>
<el-form class="register-form" :model="registerForm" :rules="rules" ref="registerFormRef"> <el-form class="register-form" :model="registerForm" :rules="rules" ref="registerFormRef">
<div class="mb-24"> <div class="mb-24">
......
<template> <template>
<login-layout> <login-layout>
<LoginContainer subTitle="欢迎使用 MaxKB 智能知识库问答系统"> <LoginContainer subTitle="欢迎使用 MaxKB 智能知识库">
<h2 class="mb-24">修改密码</h2> <h2 class="mb-24">修改密码</h2>
<el-form <el-form
class="reset-password-form" class="reset-password-form"
......
...@@ -6,26 +6,21 @@ ...@@ -6,26 +6,21 @@
<div class="app-card p-24"> <div class="app-card p-24">
<h5 class="mb-16">平台显示主题</h5> <h5 class="mb-16">平台显示主题</h5>
<el-radio-group <el-radio-group
v-model="themeRadio" v-model="themeForm.theme"
class="app-radio-button-group" class="app-radio-button-group"
@change="changeThemeHandle" @change="changeThemeHandle"
> >
<template v-for="(item, index) in themeList" :key="index"> <template v-for="(item, index) in themeList" :key="index">
<el-radio-button :label="item.label" :value="item.value" /> <el-radio-button :label="item.label" :value="item.value" />
</template> </template>
<el-radio-button label="自定义" value="custom" />
</el-radio-group> </el-radio-group>
<div v-if="themeRadio === 'custom'">
<h5 class="mt-16 mb-8">平台显示主题</h5>
<el-color-picker v-model="customColor" @change="customColorHandle" />
</div>
</div> </div>
<div class="app-card p-24 mt-16"> <div class="app-card p-24 mt-16">
<h5 class="mb-16">平台登陆设置</h5> <h5 class="mb-16">平台登陆设置</h5>
<el-card shadow="never" class="layout-bg"> <el-card shadow="never" class="layout-bg">
<div class="flex-between"> <div class="flex-between">
<h5 class="mb-16">页面预览</h5> <h5 class="mb-16">页面预览</h5>
<el-button type="primary" link @click="resetForm('login')"> 恢复默认 </el-button> <el-button type="primary" link @click="resetForm"> 恢复默认 </el-button>
</div> </div>
<el-scrollbar> <el-scrollbar>
<div class="theme-preview"> <div class="theme-preview">
...@@ -133,85 +128,6 @@ ...@@ -133,85 +128,6 @@
</div> </div>
</el-card> </el-card>
</div> </div>
<div class="app-card p-24 mt-16">
<h5 class="mb-16">平台设置</h5>
<el-card shadow="never" class="layout-bg">
<div class="flex-between">
<h5 class="mb-16">页面预览</h5>
<el-button type="primary" link @click="resetForm('platform')"> 恢复默认 </el-button>
</div>
<el-scrollbar>
<div class="theme-preview">
<el-row :gutter="8">
<el-col :span="16">
<div class="theme-platform mr-16">
<div
class="theme-platform-header border-b flex-between"
:class="!isDefaultTheme ? 'custom-header' : ''"
>
<div class="flex-center h-full">
<div class="app-title-container cursor">
<div class="logo flex-center">
<LogoFull height="25px" />
</div>
</div>
</div>
<div class="flex-center">
<AppIcon
iconName="app-github"
class="cursor color-secondary mr-8 ml-8"
style="font-size: 20px"
v-if="themeForm.showProject"
></AppIcon>
<AppIcon
iconName="app-reading"
class="cursor color-secondary mr-8 ml-8"
style="font-size: 20px"
v-if="themeForm.showUserManual"
></AppIcon>
<AppIcon
iconName="app-help"
class="cursor color-secondary ml-8"
style="font-size: 20px"
v-if="themeForm.showForum"
></AppIcon>
</div>
</div>
</div>
</el-col>
<el-col :span="8">
<div class="theme-form">
<div>
<el-checkbox v-model="themeForm.showUserManual" label="显示用户手册" />
<div class="ml-16">
<el-input
v-model="themeForm.userManualUrl"
placeholder="请输入 URL 地址"
/>
</div>
</div>
<div class="my-2">
<el-checkbox v-model="themeForm.showForum" label="显示论坛求助" />
<div class="ml-16">
<el-input v-model="themeForm.forumUrl" placeholder="请输入 URL 地址" />
</div>
</div>
<div class="mt-2">
<el-checkbox v-model="themeForm.showProject" label="显示项目地址" />
<div class="ml-16">
<el-input v-model="themeForm.projectUrl" placeholder="请输入 URL 地址" />
</div>
</div>
</div>
</el-col>
</el-row>
</div>
</el-scrollbar>
<div class="mt-16">
<el-text type="info">默认为 MaxKB 登录界面,支持自定义设置</el-text>
</div>
</el-card>
</div>
</div> </div>
</el-scrollbar> </el-scrollbar>
<div class="theme-setting__operate w-full p-16-24"> <div class="theme-setting__operate w-full p-16-24">
...@@ -222,12 +138,12 @@ ...@@ -222,12 +138,12 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, onMounted, computed } from 'vue' import { ref, reactive, onMounted, computed, watch, nextTick } from 'vue'
import { useRouter, onBeforeRouteLeave } from 'vue-router' import { useRouter, onBeforeRouteLeave } from 'vue-router'
import type { FormInstance, FormRules, UploadFiles } from 'element-plus' import type { FormInstance, FormRules, UploadFiles } from 'element-plus'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import LoginPreview from './LoginPreview.vue' import LoginPreview from './LoginPreview.vue'
import { themeList, defaultSetting, defaultPlatformSetting } from '@/utils/theme' import { themeList, defaultSetting } from '@/utils/theme'
import ThemeApi from '@/api/theme' import ThemeApi from '@/api/theme'
import { MsgSuccess, MsgError } from '@/utils/message' import { MsgSuccess, MsgError } from '@/utils/message'
import useStore from '@/stores' import useStore from '@/stores'
...@@ -240,9 +156,6 @@ onBeforeRouteLeave((to, from) => { ...@@ -240,9 +156,6 @@ onBeforeRouteLeave((to, from) => {
}) })
const themeInfo = computed(() => user.themeInfo) const themeInfo = computed(() => user.themeInfo)
const isDefaultTheme = computed(() => {
return user.isDefaultTheme()
})
const themeFormRef = ref<FormInstance>() const themeFormRef = ref<FormInstance>()
const loading = ref(false) const loading = ref(false)
...@@ -253,16 +166,8 @@ const themeForm = ref<any>({ ...@@ -253,16 +166,8 @@ const themeForm = ref<any>({
loginLogo: '', loginLogo: '',
loginImage: '', loginImage: '',
title: 'MaxKB', title: 'MaxKB',
slogan: '欢迎使用 MaxKB 智能知识库问答系统', slogan: '欢迎使用 MaxKB 智能知识库'
showUserManual: false,
userManualUrl: '',
showForum: false,
forumUrl: '',
showProject: false,
projectUrl: ''
}) })
const themeRadio = ref('')
const customColor = ref('')
const rules = reactive<FormRules>({ const rules = reactive<FormRules>({
title: [{ required: true, message: '请输入网站标题', trigger: 'blur' }], title: [{ required: true, message: '请输入网站标题', trigger: 'blur' }],
...@@ -289,16 +194,9 @@ const onChange = (file: any, fileList: UploadFiles, attr: string) => { ...@@ -289,16 +194,9 @@ const onChange = (file: any, fileList: UploadFiles, attr: string) => {
themeForm.value[attr] = file.raw themeForm.value[attr] = file.raw
} }
} }
user.setTheme(themeForm.value)
} }
function changeThemeHandle(val: string) { function changeThemeHandle(val: string) {
if (val !== 'custom') {
themeForm.value.theme = val
user.setTheme(themeForm.value)
}
}
function customColorHandle(val: string) {
themeForm.value.theme = val themeForm.value.theme = val
user.setTheme(themeForm.value) user.setTheme(themeForm.value)
} }
...@@ -308,20 +206,11 @@ function resetTheme() { ...@@ -308,20 +206,11 @@ function resetTheme() {
themeForm.value = cloneDeep(themeInfo.value) themeForm.value = cloneDeep(themeInfo.value)
} }
function resetForm(val: string) { function resetForm() {
themeForm.value = themeForm.value = {
val === 'base' theme: themeForm.value.theme,
? { ...defaultSetting
...themeForm.value, }
theme: themeForm.value.theme,
...defaultSetting
}
: {
...themeForm.value,
theme: themeForm.value.theme,
...defaultPlatformSetting
}
user.setTheme(themeForm.value) user.setTheme(themeForm.value)
} }
...@@ -347,11 +236,7 @@ onMounted(() => { ...@@ -347,11 +236,7 @@ onMounted(() => {
router.push({ path: `/application` }) router.push({ path: `/application` })
} }
if (themeInfo.value) { if (themeInfo.value) {
themeRadio.value = themeList.some((v) => v.value === themeInfo.value.theme) themeForm.value = themeInfo.value
? themeInfo.value.theme
: 'custom'
customColor.value = themeInfo.value.theme
themeForm.value = cloneDeep(themeInfo.value)
cloneTheme.value = cloneDeep(themeInfo.value) cloneTheme.value = cloneDeep(themeInfo.value)
} }
}) })
...@@ -379,13 +264,5 @@ onMounted(() => { ...@@ -379,13 +264,5 @@ onMounted(() => {
.theme-preview { .theme-preview {
min-width: 1000px; min-width: 1000px;
} }
.theme-platform {
background: #ffffff;
height: 220px;
.theme-platform-header {
padding: 10px 20px;
background: var(--app-header-bg-color);
}
}
} }
</style> </style>
...@@ -139,30 +139,7 @@ export const replyNode = { ...@@ -139,30 +139,7 @@ export const replyNode = {
} }
} }
} }
export const rerankerNode = { export const menuNodes = [aiChatNode, searchDatasetNode, questionNode, conditionNode, replyNode]
type: WorkflowType.RrerankerNode,
text: '使用重排模型对多个知识库的检索结果进行二次召回',
label: '多路召回',
properties: {
stepName: '多路召回',
config: {
fields: [
{
label: '结果',
value: 'result'
}
]
}
}
}
export const menuNodes = [
aiChatNode,
searchDatasetNode,
questionNode,
conditionNode,
replyNode,
rerankerNode
]
/** /**
* 自定义函数配置数据 * 自定义函数配置数据
...@@ -226,8 +203,7 @@ export const nodeDict: any = { ...@@ -226,8 +203,7 @@ export const nodeDict: any = {
[WorkflowType.Start]: startNode, [WorkflowType.Start]: startNode,
[WorkflowType.Reply]: replyNode, [WorkflowType.Reply]: replyNode,
[WorkflowType.FunctionLib]: functionLibNode, [WorkflowType.FunctionLib]: functionLibNode,
[WorkflowType.FunctionLibCustom]: functionNode, [WorkflowType.FunctionLibCustom]: functionNode
[WorkflowType.RrerankerNode]: rerankerNode
} }
export function isWorkFlow(type: string | undefined) { export function isWorkFlow(type: string | undefined) {
return type === 'WORK_FLOW' return type === 'WORK_FLOW'
......
...@@ -73,6 +73,7 @@ export function initDefaultShortcut(lf: LogicFlow, graph: GraphModel) { ...@@ -73,6 +73,7 @@ export function initDefaultShortcut(lf: LogicFlow, graph: GraphModel) {
if (graph.textEditElement) return true if (graph.textEditElement) return true
if (selected && (selected.nodes || selected.edges)) { if (selected && (selected.nodes || selected.edges)) {
lf.clearSelectElements() lf.clearSelectElements()
console.log(selected)
const addElements = lf.addElements(selected, CHILDREN_TRANSLATION_DISTANCE) const addElements = lf.addElements(selected, CHILDREN_TRANSLATION_DISTANCE)
if (!addElements) return true if (!addElements) return true
addElements.nodes.forEach((node) => lf.selectElementById(node.id, true)) addElements.nodes.forEach((node) => lf.selectElementById(node.id, true))
......
...@@ -89,7 +89,6 @@ onMounted(() => { ...@@ -89,7 +89,6 @@ onMounted(() => {
lf.value.deleteEdge(id) lf.value.deleteEdge(id)
}) })
}) })
setTimeout(() => { setTimeout(() => {
lf.value?.fitView() lf.value?.fitView()
}, 500) }, 500)
......
...@@ -13,18 +13,6 @@ ...@@ -13,18 +13,6 @@
</el-button> </el-button>
</el-tooltip> </el-tooltip>
</div> </div>
<div v-for="(item, index) in inputFieldList" :key="index"
class="flex-between border-r-4 p-8-12 mb-8 layout-bg lighter"
@mouseenter="showicon = true"
@mouseleave="showicon = false"
>
<span>{{ item.name }} {{ '{' + item.variable + '}' }}</span>
<el-tooltip effect="dark" content="复制参数" placement="top" v-if="showicon === true">
<el-button link @click="copyClick('{{' + '全局变量.' + item.variable + '}}')" style="padding: 0">
<AppIcon iconName="app-copy"></AppIcon>
</el-button>
</el-tooltip>
</div>
</NodeContainer> </NodeContainer>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
...@@ -39,23 +27,8 @@ const globeLabel = '{{全局变量.time}}' ...@@ -39,23 +27,8 @@ const globeLabel = '{{全局变量.time}}'
const showicon = ref(false) const showicon = ref(false)
const inputFieldList = ref<any[]>([]) // onMounted(() => {
// set(props.nodeModel, 'validate', validate)
onMounted(() => { // })
props.nodeModel.graphModel.nodes
.filter((v: any) => v.id === 'base-node')
.map((v: any) => {
// eslint-disable-next-line vue/no-mutating-props
props.nodeModel.properties.config.globalFields = [
{
label: '当前时间',
value: 'time'
}, ...v.properties.input_field_list.map((i: any) => {
return { label: i.name, value: i.variable }
})
]
inputFieldList.value = v.properties.input_field_list
})
})
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论