Merge branch 'main' of github.com:maxkb-dev/maxkb

This commit is contained in:
shaohuzhang1 2023-12-15 14:22:31 +08:00
commit 40dfe39294
18 changed files with 255 additions and 58 deletions

View File

@ -98,9 +98,28 @@ const putChatRecordLog: (
) )
} }
/**
*
* @param
* application_id, chart_id, chart_record_id
*/
const getMarkRecord: (
applicaiton_id: String,
chart_id: String,
chart_record_id: String,
loading?: Ref<boolean>
) => Promise<Result<any>> = (applicaiton_id, chart_id, chart_record_id, loading) => {
return get(
`${prefix}/${applicaiton_id}/chat/${chart_id}/chat_record/${chart_record_id}/improve`,
undefined,
loading
)
}
export default { export default {
getChatLog, getChatLog,
delChatLog, delChatLog,
getChatRecordLog, getChatRecordLog,
putChatRecordLog putChatRecordLog,
getMarkRecord
} }

View File

@ -67,9 +67,10 @@ const delParagraph: (
const postParagraph: ( const postParagraph: (
dataset_id: string, dataset_id: string,
document_id: string, document_id: string,
data: any data: any,
) => Promise<Result<any>> = (dataset_id, document_id, data: any) => { loading?: Ref<boolean>
return post(`${prefix}/${dataset_id}/document/${document_id}/paragraph`, data) ) => Promise<Result<any>> = (dataset_id, document_id, data, loading) => {
return post(`${prefix}/${dataset_id}/document/${document_id}/paragraph`, data, undefined, loading)
} }
/** /**
@ -92,9 +93,15 @@ const putParagraph: (
dataset_id: string, dataset_id: string,
document_id: string, document_id: string,
paragraph_id: string, paragraph_id: string,
data: any data: any,
) => Promise<Result<any>> = (dataset_id, document_id, paragraph_id, data: any) => { loading?: Ref<boolean>
return put(`${prefix}/${dataset_id}/document/${document_id}/paragraph/${paragraph_id}`, data) ) => Promise<Result<any>> = (dataset_id, document_id, paragraph_id, data, loading) => {
return put(
`${prefix}/${dataset_id}/document/${document_id}/paragraph/${paragraph_id}`,
data,
undefined,
loading
)
} }
/** /**

View File

@ -11,34 +11,41 @@
<AppIcon iconName="app-copy"></AppIcon> <AppIcon iconName="app-copy"></AppIcon>
</el-button> </el-button>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical" /> <el-divider direction="vertical" />
<el-tooltip effect="dark" content="修改内容" placement="top"> <el-tooltip
v-if="data.improve_paragraph_id_list.length === 0"
effect="dark"
content="修改内容"
placement="top"
>
<el-button text @click="editContent(data)"> <el-button text @click="editContent(data)">
<el-icon><EditPen /></el-icon> <el-icon><EditPen /></el-icon>
</el-button> </el-button>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical" />
<el-tooltip effect="dark" content="修改历史" placement="top"> <el-tooltip v-else effect="dark" content="修改标注" placement="top">
<el-button text @click="editContent(data)"> <el-button text @click="editMark(data)">
<el-icon><Document /></el-icon> <AppIcon iconName="app-document-active" class="primary"></AppIcon>
</el-button> </el-button>
</el-tooltip> </el-tooltip>
<el-divider direction="vertical" v-if="buttonData?.vote_status !== '-1'" /> <el-divider direction="vertical" v-if="buttonData?.vote_status !== '-1'" />
<el-button text disabled v-if="buttonData?.vote_status === '0'"> <el-button text disabled v-if="buttonData?.vote_status === '0'">
<AppIcon iconName="app-like-color" class="primary"></AppIcon> <AppIcon iconName="app-like-color"></AppIcon>
</el-button> </el-button>
<el-button text disabled v-if="buttonData?.vote_status === '1'"> <el-button text disabled v-if="buttonData?.vote_status === '1'">
<AppIcon iconName="app-oppose-color"></AppIcon> <AppIcon iconName="app-oppose-color"></AppIcon>
</el-button> </el-button>
<EditContentDialog ref="EditContentDialogRef" /> <EditContentDialog ref="EditContentDialogRef" />
<EditMarkDialog ref="EditMarkDialogRef" @refresh="refresh" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, watch, onMounted } from 'vue' import { reactive, ref, watch, onMounted } from 'vue'
import { copyClick } from '@/utils/clipboard' import { copyClick } from '@/utils/clipboard'
import EditContentDialog from '@/views/log/component/EditContentDialog.vue' import EditContentDialog from '@/views/log/component/EditContentDialog.vue'
import EditMarkDialog from '@/views/log/component/EditMarkDialog.vue'
import { datetimeFormat } from '@/utils/time' import { datetimeFormat } from '@/utils/time'
const props = defineProps({ const props = defineProps({
@ -56,6 +63,7 @@ const props = defineProps({
const emit = defineEmits(['update:data']) const emit = defineEmits(['update:data'])
const EditContentDialogRef = ref() const EditContentDialogRef = ref()
const EditMarkDialogRef = ref()
const buttonData = ref(props.data) const buttonData = ref(props.data)
const loading = ref(false) const loading = ref(false)
@ -64,8 +72,13 @@ function editContent(data: any) {
EditContentDialogRef.value.open(data) EditContentDialogRef.value.open(data)
} }
// function updateContent(data: any) { function editMark(data: any) {
// emit('update:data', data) EditMarkDialogRef.value.open(data)
// } }
function refresh() {
buttonData.value.improve_paragraph_id_list = []
emit('update:data', buttonData.value)
}
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="ai-chat"> <div class="ai-chat" :class="log ? 'chart-log' : ''">
<el-scrollbar ref="scrollDiv"> <el-scrollbar ref="scrollDiv">
<div ref="dialogScrollbar" class="ai-chat__content p-24"> <div ref="dialogScrollbar" class="ai-chat__content p-24">
<div class="item-content mb-16"> <div class="item-content mb-16">
@ -324,6 +324,11 @@ onUpdated(() => {
box-sizing: border-box; box-sizing: border-box;
position: relative; position: relative;
color: var(--app-text-color); color: var(--app-text-color);
&.chart-log {
.ai-chat__content {
padding-bottom: 0;
}
}
&__content { &__content {
padding-top: 0; padding-top: 0;
padding-bottom: 96px; padding-bottom: 96px;

View File

@ -245,7 +245,7 @@ export const iconMap: any = {
}), }),
h('path', { h('path', {
d: 'M12.5 1.2666C12.568 1.28633 12.6306 1.32327 12.6812 1.37472L16.5472 5.30797C16.5788 5.34017 16.6047 5.37698 16.6242 5.4168H13.4459C12.9235 5.4168 12.5 4.99328 12.5 4.47085V1.2666Z', d: 'M12.5 1.2666C12.568 1.28633 12.6306 1.32327 12.6812 1.37472L16.5472 5.30797C16.5788 5.34017 16.6047 5.37698 16.6242 5.4168H13.4459C12.9235 5.4168 12.5 4.99328 12.5 4.47085V1.2666Z',
fill: 'currentColor' fill: '#2B5FD9'
}), }),
h('path', { h('path', {
d: 'M6.71305 7.72705C6.48293 7.72705 6.29639 7.9136 6.29639 8.14372V8.82554C6.29639 9.05565 6.48294 9.2422 6.71305 9.2422H13.2871C13.5172 9.2422 13.7038 9.05565 13.7038 8.82554V8.14372C13.7038 7.9136 13.5172 7.72705 13.2871 7.72705H6.71305Z', d: 'M6.71305 7.72705C6.48293 7.72705 6.29639 7.9136 6.29639 8.14372V8.82554C6.29639 9.05565 6.48294 9.2422 6.71305 9.2422H13.2871C13.5172 9.2422 13.7038 9.05565 13.7038 8.82554V8.14372C13.7038 7.9136 13.5172 7.72705 13.2871 7.72705H6.71305Z',
@ -427,11 +427,11 @@ export const iconMap: any = {
[ [
h('path', { h('path', {
d: 'M2.00497 14.6608H2.00518C2.00511 14.6609 2.00504 14.6609 2.00497 14.6608H0.666612C0.666097 14.6874 0.666707 5.33317 0.666612 5.29087H2.00518C2.00006 5.33305 1.98026 14.6344 2.00497 14.6608Z', d: 'M2.00497 14.6608H2.00518C2.00511 14.6609 2.00504 14.6609 2.00497 14.6608H0.666612C0.666097 14.6874 0.666707 5.33317 0.666612 5.29087H2.00518C2.00006 5.33305 1.98026 14.6344 2.00497 14.6608Z',
fill: 'currentColor' fill: '#FFC60A'
}), }),
h('path', { h('path', {
d: 'M12.5717 5.28984H9.70096C10.1486 4.45673 10.3724 3.78809 10.3724 3.28394C10.3724 1.94718 9.40089 1.14037 8.5893 0.770777C8.04824 0.52438 7.5406 0.753754 7.35254 1.05296L4.5741 5.00545C4.44877 5.18374 4.24449 5.28984 4.02656 5.28984H3.33882C3.154 5.28984 3.00418 5.43966 3.00418 5.62448V14.3319C3.00418 14.5167 3.154 14.6665 3.33882 14.6665H11.1995C11.8409 14.6665 12.4029 14.2423 12.5717 13.6308L14.5687 8.37353C15.0274 7.05264 14.5687 5.28984 12.5717 5.28984Z', d: 'M12.5717 5.28984H9.70096C10.1486 4.45673 10.3724 3.78809 10.3724 3.28394C10.3724 1.94718 9.40089 1.14037 8.5893 0.770777C8.04824 0.52438 7.5406 0.753754 7.35254 1.05296L4.5741 5.00545C4.44877 5.18374 4.24449 5.28984 4.02656 5.28984H3.33882C3.154 5.28984 3.00418 5.43966 3.00418 5.62448V14.3319C3.00418 14.5167 3.154 14.6665 3.33882 14.6665H11.1995C11.8409 14.6665 12.4029 14.2423 12.5717 13.6308L14.5687 8.37353C15.0274 7.05264 14.5687 5.28984 12.5717 5.28984Z',
fill: 'currentColor' fill: '#FFC60A'
}) })
] ]
) )

View File

@ -1,14 +1,40 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import paragraphApi from '@/api/paragraph' import paragraphApi from '@/api/paragraph'
import type { Ref } from 'vue'
const useParagraphStore = defineStore({ const useParagraphStore = defineStore({
id: 'paragraph', id: 'paragraph',
state: () => ({}), state: () => ({}),
actions: { actions: {
async asyncPutParagraph(datasetId: string, documentId: string, paragraphId: string, data: any) { async asyncPutParagraph(
datasetId: string,
documentId: string,
paragraphId: string,
data: any,
loading?: Ref<boolean>
) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
paragraphApi paragraphApi
.putParagraph(datasetId, documentId, paragraphId, data) .putParagraph(datasetId, documentId, paragraphId, data, loading)
.then((data) => {
resolve(data)
})
.catch((error) => {
reject(error)
})
})
},
async asyncDelParagraph(
datasetId: string,
documentId: string,
paragraphId: string,
data: any,
loading?: Ref<boolean>
) {
return new Promise((resolve, reject) => {
paragraphApi
.delParagraph(datasetId, documentId, paragraphId, loading)
.then((data) => { .then((data) => {
resolve(data) resolve(data)
}) })

View File

@ -254,6 +254,10 @@ h4 {
word-break: break-all; word-break: break-all;
} }
.pre-line {
white-space: pre-line;
}
/* /*
内容部分 自适应高度 内容部分 自适应高度
*/ */

View File

@ -127,7 +127,7 @@ const paginationConfig = reactive({
watch(documentData, (list) => { watch(documentData, (list) => {
let interval let interval
if (list.every((item) => item.status === '0')) { if (list.length > 0 && list.every((item) => item.status === '0')) {
interval = setInterval(() => { interval = setInterval(() => {
getList(true) getList(true)
}, 6000) }, 6000)

View File

@ -1,5 +1,5 @@
<template> <template>
<el-drawer v-model="visible" size="50%" @close="closeHandel" class="chat-record-drawer"> <el-drawer v-model="visible" size="600" @close="closeHandel" class="chat-record-drawer">
<template #header> <template #header>
<h4>{{ application?.name }}</h4> <h4>{{ application?.name }}</h4>
</template> </template>
@ -72,7 +72,7 @@ const recordList = ref<chatType[]>([])
const paginationConfig = reactive({ const paginationConfig = reactive({
current_page: 1, current_page: 1,
page_size: 10, page_size: 20,
total: 0 total: 0
}) })

View File

@ -27,7 +27,7 @@
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="保存至文档" prop="document"> <el-form-item label="保存至文档" prop="document">
<el-cascader v-model="form.document" :props="LoadDocument" placeholder="请选择文档"> <el-cascader v-model="form.document" :props="LoadDocument" placeholder="请选择文档" class="w-full">
<template #default="{ node, data }"> <template #default="{ node, data }">
<span class="flex align-center"> <span class="flex align-center">
<AppAvatar v-if="!node.isLeaf" class="mr-12" shape="square" :size="24"> <AppAvatar v-if="!node.isLeaf" class="mr-12" shape="square" :size="24">

View File

@ -0,0 +1,135 @@
<template>
<el-dialog title="修改标注" v-model="dialogVisible" width="600" class="edit-mark-dialog">
<template #header="{ titleId, titleClass }">
<div class="flex-between">
<h4 :id="titleId" :class="titleClass">修改标注</h4>
<div class="text-right">
<el-button text @click="isEdit = true" v-if="!isEdit">
<el-icon><EditPen /></el-icon>
</el-button>
<el-button text style="margin-left: 4px" @click="deleteParagraph">
<el-icon><Delete /></el-icon>
</el-button>
<el-divider direction="vertical" />
</div>
</div>
</template>
<el-scrollbar>
<div style="min-height: 250px; max-height: 350px" v-loading="loading">
<el-form
v-if="isEdit"
ref="formRef"
:model="form"
label-position="top"
require-asterisk-position="right"
:rules="rules"
@submit.prevent
>
<el-form-item prop="content">
<el-input
v-model="form.content"
placeholder="请输入分段内容"
maxlength="1024"
show-word-limit
:rows="15"
type="textarea"
>
</el-input>
</el-form-item>
</el-form>
<span v-else class="pre-line">{{ form?.content }}</span>
</div>
</el-scrollbar>
<template #footer>
<span class="dialog-footer" v-if="isEdit">
<el-button @click.prevent="isEdit = false"> 取消 </el-button>
<el-button type="primary" @click="submit(formRef)" :loading="loading"> 保存 </el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, watch, reactive } from 'vue'
import { useRoute } from 'vue-router'
import type { FormInstance, FormRules } from 'element-plus'
import logApi from '@/api/log'
import useStore from '@/stores'
import { MsgSuccess, MsgConfirm } from '@/utils/message'
const isEdit = ref(false)
const route = useRoute()
const {
params: { id }
} = route as any
const { paragraph } = useStore()
const emit = defineEmits(['refresh'])
const formRef = ref()
const dialogVisible = ref<boolean>(false)
const loading = ref(false)
const form = ref<any>({})
const rules = reactive<FormRules>({
content: [{ required: true, message: '请输入内容', trigger: 'blur' }]
})
watch(dialogVisible, (bool) => {
if (!bool) {
form.value = {}
}
})
function deleteParagraph() {
paragraph
.asyncDelParagraph(form.value.dataset, form.value.document, form.value.id, loading)
.then(() => {
emit('refresh')
MsgSuccess('删除成功')
dialogVisible.value = false
})
}
function getMark(data: any) {
logApi.getMarkRecord(id as string, data.chat, data.id, loading).then((res: any) => {
if (res.data.length > 0) {
form.value = res.data[0]
}
})
}
const open = (data: any) => {
getMark(data)
dialogVisible.value = true
}
const submit = async (formEl: FormInstance) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
paragraph
.asyncPutParagraph(
form.value.dataset,
form.value.document,
form.value.id,
{
content: form.value.content
},
loading
)
.then((res) => {
dialogVisible.value = false
})
} else {
console.log('error submit!')
}
})
}
defineExpose({ open })
</script>
<style lang="scss" scope></style>

View File

@ -1,6 +1,6 @@
<template> <template>
<login-layout> <login-layout>
<LoginContainer subTitle="欢迎使用 MaxKB 管理平台"> <LoginContainer subTitle="欢迎使用 MaxKB 智能知识库">
<h4 class="mb-24">忘记密码</h4> <h4 class="mb-24">忘记密码</h4>
<el-form <el-form
class="register-form" class="register-form"

View File

@ -1,8 +1,14 @@
<template> <template>
<login-layout v-loading="loading"> <login-layout v-loading="loading">
<LoginContainer subTitle="欢迎使用 MaxKB 管理平台"> <LoginContainer subTitle="欢迎使用 MaxKB 智能知识库">
<h2 class="mb-24">普通登录</h2> <h2 class="mb-24">普通登录</h2>
<el-form class="login-form" :rules="rules" :model="loginForm" ref="loginFormRef"> <el-form
class="login-form"
:rules="rules"
:model="loginForm"
ref="loginFormRef"
@keyup.enter="login"
>
<el-form-item prop="username"> <el-form-item prop="username">
<el-input <el-input
size="large" size="large"

View File

@ -1,6 +1,6 @@
<template> <template>
<login-layout> <login-layout>
<LoginContainer subTitle="欢迎使用 MaxKB 管理平台"> <LoginContainer subTitle="欢迎使用 MaxKB 智能知识库">
<h4 class="mb-24">用户注册</h4> <h4 class="mb-24">用户注册</h4>
<el-form class="register-form" :model="registerForm" :rules="rules" ref="registerFormRef"> <el-form class="register-form" :model="registerForm" :rules="rules" ref="registerFormRef">
<el-form-item prop="username"> <el-form-item prop="username">

View File

@ -1,6 +1,6 @@
<template> <template>
<login-layout> <login-layout>
<LoginContainer subTitle="欢迎使用 MaxKB 管理平台"> <LoginContainer subTitle="欢迎使用 MaxKB 智能知识库">
<h4 class="mb-24">修改密码</h4> <h4 class="mb-24">修改密码</h4>
<el-form <el-form
class="reset-password-form" class="reset-password-form"

View File

@ -90,18 +90,13 @@ const open = (data: any) => {
} }
const submitHandle = async () => { const submitHandle = async () => {
if (await paragraphFormRef.value?.validate()) { if (await paragraphFormRef.value?.validate()) {
loading.value = true
if (problemId.value) { if (problemId.value) {
paragraph paragraph
.asyncPutParagraph(id, documentId, problemId.value, paragraphFormRef.value?.form) .asyncPutParagraph(id, documentId, problemId.value, paragraphFormRef.value?.form, loading)
.then((res: any) => { .then((res: any) => {
emit('refresh', res.data) emit('refresh', res.data)
loading.value = false
isEdit.value = false isEdit.value = false
}) })
.catch(() => {
loading.value = false
})
} else { } else {
const obj = const obj =
ProblemRef.value.problemList.length > 0 ProblemRef.value.problemList.length > 0
@ -110,16 +105,10 @@ const submitHandle = async () => {
...paragraphFormRef.value?.form ...paragraphFormRef.value?.form
} }
: paragraphFormRef.value?.form : paragraphFormRef.value?.form
paragraphApi paragraphApi.postParagraph(id, documentId, obj, loading).then((res) => {
.postParagraph(id, documentId, obj) emit('refresh')
.then((res) => { dialogVisible.value = false
emit('refresh') })
loading.value = false
dialogVisible.value = false
})
.catch(() => {
loading.value = false
})
} }
} }
} }

View File

@ -127,14 +127,7 @@ function changeState(bool: Boolean, row: any) {
is_active: bool is_active: bool
} }
loading.value = true loading.value = true
paragraph paragraph.asyncPutParagraph(id, documentId, row.id, obj, loading).then((res) => {})
.asyncPutParagraph(id, documentId, row.id, obj)
.then((res) => {
loading.value = false
})
.catch(() => {
loading.value = false
})
} }
function deleteParagraph(row: any) { function deleteParagraph(row: any) {
@ -143,7 +136,7 @@ function deleteParagraph(row: any) {
confirmButtonClass: 'danger' confirmButtonClass: 'danger'
}) })
.then(() => { .then(() => {
paragraphApi.delParagraph(id, documentId, row.id, loading).then(() => { paragraph.asyncDelParagraph(id, documentId, row.id, loading).then(() => {
const index = paragraphDetail.value.findIndex((v) => v.id === row.id) const index = paragraphDetail.value.findIndex((v) => v.id === row.id)
paragraphDetail.value.splice(index, 1) paragraphDetail.value.splice(index, 1)
MsgSuccess('删除成功') MsgSuccess('删除成功')

View File

@ -24,7 +24,7 @@
<div class="p-24 pb-0"> <div class="p-24 pb-0">
<h4>{{ active_provider?.name }}</h4> <h4>{{ active_provider?.name }}</h4>
<div class="flex-between mt-16 mb-16"> <div class="flex-between mt-16 mb-16">
<el-button type="primary" @click="openCreateModel(active_provider)">创建模型</el-button> <el-button type="primary" @click="openCreateModel(active_provider)">添加模型</el-button>
<el-input <el-input
v-model="model_search_form.name" v-model="model_search_form.name"
@change="list_model" @change="list_model"