feat: 段落模块

This commit is contained in:
wangdan-fit2cloud 2023-11-13 19:02:13 +08:00
parent 76dd9d2192
commit e452a942be
12 changed files with 341 additions and 65 deletions

View File

@ -184,6 +184,43 @@ const getParagraph: (dataset_id: string, document_id: string) => Promise<Result<
return get(`${prefix}/${dataset_id}/document/${document_id}/paragraph`)
}
/**
*
* @param dataset_id, document_id, document_id
*/
const delParagraph: (
dataset_id: string,
document_id: string,
paragraph_id: string
) => Promise<Result<boolean>> = (dataset_id, document_id, paragraph_id) => {
return del(`${prefix}/${dataset_id}/document/${document_id}/paragraph/${paragraph_id}`)
}
/**
*
* @param
* dataset_id, document_id, paragraph_id
* {
"content": "string",
"title": "string",
"is_active": true,
"problem_list": [
{
"id": "string",
"content": "string"
}
]
}
*/
const putParagraph: (
dataset_id: string,
document_id: string,
paragraph_id: string,
data: any
) => Promise<Result<any>> = (dataset_id, document_id, paragraph_id, data: any) => {
return put(`${prefix}/${dataset_id}/document/${document_id}/paragraph/${paragraph_id}`, data)
}
export default {
getDateset,
getAllDateset,
@ -197,5 +234,7 @@ export default {
putDocument,
delDocument,
getDocumentDetail,
getParagraph
getParagraph,
delParagraph,
putParagraph
}

View File

@ -67,9 +67,13 @@ function cardLeave() {
.card-footer {
position: absolute;
bottom: 8px;
left: 0;
min-height: 30px;
color: var(--app-text-color-secondary);
font-weight: 400;
padding: 0 16px;
width: 100%;
box-sizing: border-box;
}
}
</style>

View File

@ -19,7 +19,7 @@ body {
height: 100%;
margin: 0;
padding: 0;
color: var(--app-text-color-primary);
color: var(--app-text-color);
}
#app {
@ -135,7 +135,7 @@ h4 {
margin-right: calc(var(--app-base-px) + 4px);
}
.mr-16 {
margin-right: calc(var(--app-base-px) * 3);
margin-right: calc(var(--app-base-px) * 2);
}
.p-8 {
@ -212,6 +212,7 @@ h4 {
// 内容部分 自适应高度
.main-calc-height {
height: var(--app-main-height);
box-sizing: border-box;
}
// 标题前带竖线样式

View File

@ -3,7 +3,7 @@
--el-color-primary-light-9: rgba(51, 112, 255, 0.1);
--el-menu-item-height: 45px;
--el-box-shadow-light: 0px 2px 4px 0px rgba(31, 35, 41, 0.12);
--el-border-color: rgba(31, 35, 41, 0.15);
--el-border-color: #DEE0E3;
}
.el-button {
@ -13,7 +13,7 @@
font-size: 16px;
max-height: 24px;
&:not(.is-disabled):hover {
background: var(--app-text-color-primary-light-1);
background: var(--app-text-color-light-1);
}
}
}
@ -48,7 +48,7 @@
.el-message-box__content {
padding: 24px 0;
color: var(--app-text-color-primary);
color: var(--app-text-color);
font-weight: 400;
}
.el-message-box__btns {
@ -62,6 +62,7 @@
button.danger {
background: var(--el-color-danger);
border: var(--el-color-danger);
color: #ffffff;
}
}
.el-message-box__headerbtn {
@ -92,7 +93,7 @@
--el-card-padding: calc(var(--app-base-px) * 2);
}
.el-dropdown {
color: var(--app-text-color-primary);
color: var(--app-text-color);
}
.el-tag {
@ -100,7 +101,7 @@
}
.el-table {
--el-table-header-bg-color: var(--app-layout-bg-color);
--el-table-text-color: var(--app-text-color-primary);
--el-table-text-color: var(--app-text-color);
font-weight: 400;
thead {
color: var(--app-text-color-secondary);
@ -165,3 +166,14 @@
.el-slider__input {
width: 60px;
}
.input-with-select {
.el-input__wrapper {
// border: 1px solid var(--el-border-color);
// box-shadow: none!important;
}
.el-input-group__prepend {
background-color: var(--el-fill-color-blank);
}
}

View File

@ -1,9 +1,10 @@
:root {
--app-base-px: 8px;
--app-layout-bg-color: #f5f6f7;
--app-text-color-primary: #1f2329;
--app-text-color-primary-light-1: rgba(31, 35, 41, 0.1);
--app-text-color: #1f2329;
--app-text-color-light-1: rgba(31, 35, 41, 0.1);
--app-text-color-secondary: #646a73;
--app-text-color-disable: #bbbfc4;
--app-view-padding: 24px;
--app-view-bg-color: #ffffff;
--app-border-color-dark: #bbbfc4;

View File

@ -31,7 +31,7 @@ const router = useRouter()
}
.message-container {
color: var(--app-text-color-primary);
color: var(--app-text-color);
.title {
font-size: 50px;

View File

@ -167,7 +167,6 @@ function submit() {
width: 100%;
margin: 0 auto;
overflow: hidden;
box-sizing: border-box;
}
&__footer {
padding: 16px 24px;

View File

@ -1,61 +1,79 @@
<template>
<LayoutContainer :header="documentDetail?.name" back-to="-1" class="dataset-detail">
<LayoutContainer :header="documentDetail?.name" back-to="-1" class="document-detail">
<template #header>
<!-- <el-steps :active="active" finish-status="success" align-center class="create-dataset__steps">
<el-step v-for="(item, index) in steps" :key="index">
<template #icon>
<div class="app-step flex align-center">
<div class="el-step__icon is-text">
<div class="el-step__icon-inner">
<el-icon v-if="active == index + 1" style="margin-top: 1px"><Select /></el-icon>
<span v-else> {{ index + 1 }}</span>
</div>
</div>
<span class="ml-4">{{ item.name }}</span>
</div>
</template>
</el-step>
</el-steps> -->
<div class="document-detail__header">
<el-button @click="addParagraph" type="primary" :disabled="loading"> 添加分段 </el-button>
</div>
</template>
<div class="dataset-detail__main main-calc-height p-24">
<el-row :gutter="15">
<el-col
:xs="24"
:sm="12"
:md="8"
:lg="6"
:xl="4"
v-for="(item, index) in paragraphDetail"
:key="index"
class="mt-8"
<div class="document-detail__main p-16">
<div class="flex-between p-8">
<span>{{ paragraphDetail.length }} 段落</span>
<el-input
v-model="search"
placeholder="搜索"
class="input-with-select"
style="width: 260px"
>
<CardBox
shadow="hover"
:title="item.title"
:description="item.content"
class="cursor"
:showIcon="false"
>
<!-- <template #footer>
<div class="footer-content">
<span class="bold">{{ item?.document_count || 0 }}</span>
文档<el-divider direction="vertical" />
<span class="bold">{{ numberFormat(item?.char_length) || 0 }}</span>
字符<el-divider direction="vertical" />
<span class="bold">{{ item?.char_length || 0 }}</span>
关联应用
</div>
</template> -->
</CardBox>
</el-col>
</el-row>
<template #prepend>
<el-select v-model="searchType" placeholder="Select" style="width: 80px">
<el-option label="标题" value="title" />
<el-option label="内容" value="content" />
</el-select>
</template>
</el-input>
</div>
<el-scrollbar>
<div class="document-detail-height" v-loading="loading">
<el-row>
<el-col
:xs="24"
:sm="12"
:md="8"
:lg="6"
:xl="4"
v-for="(item, index) in paragraphDetail"
:key="index"
class="p-8"
>
<CardBox
shadow="hover"
:title="item.title"
:description="item.content"
class="document-card cursor"
:class="item.is_active ? '' : 'disabled'"
:showIcon="false"
@click="editParagraph(item)"
>
<div class="active-button">
<el-switch v-model="item.is_active" @change="changeState($event, item)" />
</div>
<template #footer>
<div class="footer-content flex-between">
<span> {{ numberFormat(item?.content.length) || 0 }} 字符 </span>
<el-tooltip effect="dark" content="删除" placement="top">
<el-button text @click.stop="deleteParagraph(item)" class="delete-button">
<el-icon><Delete /></el-icon>
</el-button>
</el-tooltip>
</div>
</template>
</CardBox>
</el-col>
</el-row>
</div>
</el-scrollbar>
</div>
<ParagraphDialog ref="ParagraphDialogRef" :title="title" />
</LayoutContainer>
</template>
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import datasetApi from '@/api/dataset'
import ParagraphDialog from './component/ParagraphDialog.vue'
import { numberFormat } from '@/utils/utils'
import { MsgSuccess, MsgConfirm } from '@/utils/message'
const router = useRouter()
const route = useRoute()
@ -63,9 +81,57 @@ const {
params: { datasetId, documentId }
} = route as any
const ParagraphDialogRef = ref()
const loading = ref(false)
const documentDetail = ref<any>({})
const paragraphDetail = ref<any[]>([])
const title = ref('')
const search = ref('')
const searchType = ref('title')
function changeState(bool: Boolean, row: any) {
const obj = {
is_active: bool
}
loading.value = true
datasetApi
.putParagraph(datasetId, documentId, row.id, obj)
.then((res) => {
loading.value = false
})
.catch(() => {
loading.value = false
})
}
function deleteParagraph(row: any) {
MsgConfirm(`是否删除段落:${row.title} ?`, `删除后无法恢复,请谨慎操作。`, {
confirmButtonText: '删除',
confirmButtonClass: 'danger'
})
.then(() => {
loading.value = true
datasetApi
.delParagraph(datasetId, documentId, row.id)
.then(() => {
MsgSuccess('删除成功')
getParagraphDetail()
})
.catch(() => {
loading.value = false
})
})
.catch(() => {})
}
function addParagraph() {
title.value = '添加分段'
ParagraphDialogRef.value.open()
}
function editParagraph(row: any) {
title.value = '分段详情'
ParagraphDialogRef.value.open(row)
}
function getDetail() {
loading.value = true
@ -99,9 +165,42 @@ onMounted(() => {
})
</script>
<style lang="scss" scoped>
.dataset-detail {
&__main{
box-sizing: border-box;
.document-detail {
&__header {
position: absolute;
right: calc(var(--app-base-px) * 3);
}
.document-detail-height {
height: calc(var(--app-main-height) - 75px);
}
.document-card {
height: 210px;
background: var(--app-layout-bg-color);
border: 1px solid var(--app-layout-bg-color);
&:hover {
background: #ffffff;
border: 1px solid var(--el-border-color);
}
&.disabled {
background: var(--app-layout-bg-color);
border: 1px solid var(--app-layout-bg-color);
:deep(.description) {
color: var(--app-border-color-dark);
}
:deep(.title) {
color: var(--app-border-color-dark);
}
}
:deep(.description) {
-webkit-line-clamp: 5 !important;
height: 110px;
}
.active-button {
position: absolute;
right: 16px;
top: 16px;
}
}
}
</style>

View File

@ -0,0 +1,121 @@
<template>
<el-dialog :title="title" v-model="dialogVisible" width="800" class="paragraph-dialog">
<el-row>
<el-col :span="16" class="p-24">
<div class="flex-between mb-16">
<div class="bold title align-center">分段内容</div>
<el-button text>
<el-icon><EditPen /></el-icon>
</el-button>
</div>
<el-form
ref="segmentFormRef"
:model="segmentForm"
label-position="top"
:rules="rules"
@submit.prevent
>
<el-form-item label="分段标题">
<el-input v-model="segmentForm.title" placeholder="请输入分段标题"> </el-input>
</el-form-item>
<el-form-item label="分段内容" prop="content">
<el-input
v-model="segmentForm.content"
placeholder="请输入分段内容"
maxlength="500"
show-word-limit
:rows="8"
type="textarea"
>
</el-input>
</el-form-item>
</el-form>
<div class="text-right">
<el-button @click.prevent="dialogVisible = false"> 取消 </el-button>
<el-button type="primary" @click="submitHandle(segmentFormRef)"> 保存 </el-button>
</div>
</el-col>
<el-col :span="8" class="border-l p-24">
<p class="bold title mb-16">
关联问题 <el-divider direction="vertical" />
<el-button text>
<el-icon><Plus /></el-icon>
</el-button>
</p>
</el-col>
</el-row>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { cloneDeep } from 'lodash'
const props = defineProps({
title: String
})
const emit = defineEmits(['updateContent'])
const segmentFormRef = ref<FormInstance>()
const dialogVisible = ref<boolean>(false)
const segmentForm = ref({
title: '',
content: ''
})
const rules = ref<FormRules>({
content: [{ required: true, message: '请输入分段内容', trigger: 'blur' }]
})
const isEdit = ref(false)
watch(dialogVisible, (bool) => {
if (!bool) {
segmentForm.value = {
title: '',
content: ''
}
isEdit.value = false
}
})
const open = (data: any) => {
if (data) {
segmentForm.value.title = data.title
segmentForm.value.content = data.content
isEdit.value = true
}
dialogVisible.value = true
}
const submitHandle = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
emit('updateContent', segmentForm.value)
dialogVisible.value = false
} else {
console.log('error submit!')
}
})
}
defineExpose({ open })
</script>
<style lang="scss" scope>
.paragraph-dialog {
.el-dialog__header {
padding-bottom: 16px;
}
.el-dialog__body {
border-top: 1px solid var(--el-border-color);
padding: 0 !important;
}
.title {
color: var(--app-text-color);
}
}
</style>

View File

@ -110,7 +110,7 @@ onMounted(() => {})
<style scoped lang="scss">
.segment-tabs {
:deep(.el-tabs__item) {
background: var(--app-text-color-primary-light-1);
background: var(--app-text-color-light-1);
margin: 4px;
border-radius: 4px;
padding: 5px 10px 5px 8px !important;

View File

@ -135,7 +135,7 @@ onMounted(() => {
}
.footer-content {
.bold {
color: var(--app-text-color-primary);
color: var(--app-text-color);
}
}
}

View File

@ -158,7 +158,7 @@ defineExpose({
height: 100%;
padding: calc(var(--app-base-px) * 2);
line-height: 22px;
color: var(--app-text-color-primary);
color: var(--app-text-color);
}
:deep(.el-radio__label) {
padding-left: 32px;