mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-30 17:52:48 +00:00
feat: paragraph
This commit is contained in:
parent
1390ddb36e
commit
003b9115a3
|
|
@ -16,17 +16,24 @@
|
|||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@vavt/cm-extension": "^1.9.1",
|
||||
"@wecom/jssdk": "^2.3.1",
|
||||
"axios": "^1.8.4",
|
||||
"cropperjs": "^2.0.0-rc.2",
|
||||
"dingtalk-jsapi": "^3.1.0",
|
||||
"element-plus": "^2.9.10",
|
||||
"highlight.js": "^11.11.1",
|
||||
"katex": "^0.16.22",
|
||||
"md-editor-v3": "^5.6.1",
|
||||
"mermaid": "^11.6.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^3.0.1",
|
||||
"screenfull": "^6.0.2",
|
||||
"use-element-plus-theme": "^0.0.5",
|
||||
"vue": "^3.5.13",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-codemirror": "^6.1.1",
|
||||
"vue-draggable-plus": "^0.6.0",
|
||||
"vue-i18n": "^11.1.3",
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1744092984968" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1250" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M384 768a64 64 0 1 0 0 128 64 64 0 0 0 0-128z m0-320a64 64 0 1 0 0 128 64 64 0 0 0 0-128z m0-320a64 64 0 1 0 0 128 64 64 0 0 0 0-128z m256 640a64 64 0 1 0 0 128 64 64 0 0 0 0-128z m0-320a64 64 0 1 0 0 128 64 64 0 0 0 0-128z m0-320a64 64 0 1 0 0 128 64 64 0 0 0 0-128z" p-id="1251"></path></svg>
|
||||
|
After Width: | Height: | Size: 627 B |
|
|
@ -19,6 +19,7 @@ import AutoTooltip from './auto-tooltip/index.vue'
|
|||
import MdEditor from './markdown/MdEditor.vue'
|
||||
import MdPreview from './markdown/MdPreview.vue'
|
||||
import MdEditorMagnify from './markdown/MdEditorMagnify.vue'
|
||||
import TagEllipsis from './tag-ellipsis/index.vue'
|
||||
export default {
|
||||
install(app: App) {
|
||||
app.component('LogoFull', LogoFull)
|
||||
|
|
@ -41,5 +42,6 @@ export default {
|
|||
app.component('MdPreview', MdPreview)
|
||||
app.component('MdEditor', MdEditor)
|
||||
app.component('MdEditorMagnify', MdEditorMagnify)
|
||||
app.component('TagEllipsis', TagEllipsis)
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
<template>
|
||||
<el-tag class="tag-ellipsis flex-between mb-8" effect="plain" v-bind="$attrs">
|
||||
<slot></slot>
|
||||
</el-tag>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: 'TagEllipsis' })
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/* tag超出省略号 */
|
||||
.tag-ellipsis {
|
||||
border: 1px solid var(--el-border-color);
|
||||
color: var(--app-text-color);
|
||||
border-radius: 4px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0 9px;
|
||||
box-sizing: border-box;
|
||||
|
||||
:deep(.el-tag__content) {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -19,7 +19,6 @@ import katex from 'katex'
|
|||
import 'katex/dist/katex.min.css'
|
||||
|
||||
import Cropper from 'cropperjs'
|
||||
import 'cropperjs/dist/cropper.css'
|
||||
|
||||
import mermaid from 'mermaid'
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import useKnowledgeStore from './modules/knowledge'
|
|||
import useModelStore from './modules/model'
|
||||
import usePromptStore from './modules/prompt'
|
||||
import useProblemStore from './modules/problem'
|
||||
import useParagraphStore from './modules/paragraph'
|
||||
|
||||
const useStore = () => ({
|
||||
common: useCommonStore(),
|
||||
|
|
@ -18,6 +19,7 @@ const useStore = () => ({
|
|||
model: useModelStore(),
|
||||
prompt: usePromptStore(),
|
||||
problem: useProblemStore(),
|
||||
paragraph: useParagraphStore(),
|
||||
})
|
||||
|
||||
export default useStore
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import paragraphApi from '@/api/knowledge/paragraph'
|
||||
import type { Ref } from 'vue'
|
||||
|
||||
const useParagraphStore = defineStore('paragraph', {
|
||||
state: () => ({}),
|
||||
actions: {
|
||||
async asyncPutParagraph(
|
||||
datasetId: string,
|
||||
documentId: string,
|
||||
paragraphId: string,
|
||||
data: any,
|
||||
loading?: Ref<boolean>,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
paragraphApi
|
||||
.putParagraph(datasetId, documentId, paragraphId, data, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
async asyncDelParagraph(
|
||||
datasetId: string,
|
||||
documentId: string,
|
||||
paragraphId: string,
|
||||
loading?: Ref<boolean>,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
paragraphApi
|
||||
.delParagraph(datasetId, documentId, paragraphId, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default useParagraphStore
|
||||
|
|
@ -99,3 +99,25 @@
|
|||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 分段 dialog
|
||||
.paragraph-dialog {
|
||||
padding: 0 !important;
|
||||
.el-scrollbar {
|
||||
height: auto !important;
|
||||
}
|
||||
.el-dialog__header {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
.el-dialog__body {
|
||||
border-top: 1px solid var(--el-border-color);
|
||||
}
|
||||
.el-dialog__footer {
|
||||
padding: 16px 24px;
|
||||
border-top: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--app-text-color);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
@use './variables.scss';
|
||||
@use './app.scss';
|
||||
@use './component.scss';
|
||||
@use './md-editor.scss';
|
||||
@import 'nprogress/nprogress.css';
|
||||
@import 'md-editor-v3/lib/style.css';
|
||||
@import './md-editor.scss';
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
<AppIcon
|
||||
:iconName="'app-magnify'"
|
||||
:style="{
|
||||
color: xpackForm.custom_theme?.header_font_color
|
||||
color: xpackForm.custom_theme?.header_font_color,
|
||||
}"
|
||||
style="font-size: 20px"
|
||||
></AppIcon>
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
:size="20"
|
||||
class="color-secondary"
|
||||
:style="{
|
||||
color: xpackForm.custom_theme?.header_font_color
|
||||
color: xpackForm.custom_theme?.header_font_color,
|
||||
}"
|
||||
>
|
||||
<Close/>
|
||||
|
|
@ -305,7 +305,7 @@
|
|||
<el-option
|
||||
:label="
|
||||
$t(
|
||||
'views.applicationOverview.appInfo.SettingDisplayDialog.iconPosition.left'
|
||||
'views.applicationOverview.appInfo.SettingDisplayDialog.iconPosition.left',
|
||||
)
|
||||
"
|
||||
value="left"
|
||||
|
|
@ -313,7 +313,7 @@
|
|||
<el-option
|
||||
:label="
|
||||
$t(
|
||||
'views.applicationOverview.appInfo.SettingDisplayDialog.iconPosition.right'
|
||||
'views.applicationOverview.appInfo.SettingDisplayDialog.iconPosition.right',
|
||||
)
|
||||
"
|
||||
value="right"
|
||||
|
|
@ -337,7 +337,7 @@
|
|||
<el-option
|
||||
:label="
|
||||
$t(
|
||||
'views.applicationOverview.appInfo.SettingDisplayDialog.iconPosition.top'
|
||||
'views.applicationOverview.appInfo.SettingDisplayDialog.iconPosition.top',
|
||||
)
|
||||
"
|
||||
value="top"
|
||||
|
|
@ -345,7 +345,7 @@
|
|||
<el-option
|
||||
:label="
|
||||
$t(
|
||||
'views.applicationOverview.appInfo.SettingDisplayDialog.iconPosition.bottom'
|
||||
'views.applicationOverview.appInfo.SettingDisplayDialog.iconPosition.bottom',
|
||||
)
|
||||
"
|
||||
value="bottom"
|
||||
|
|
@ -453,14 +453,14 @@ const defaultSetting = {
|
|||
disclaimer_value: t('views.applicationOverview.appInfo.SettingDisplayDialog.disclaimerValue'),
|
||||
custom_theme: {
|
||||
theme_color: '',
|
||||
header_font_color: '#1f2329'
|
||||
header_font_color: '#1f2329',
|
||||
},
|
||||
float_location: {
|
||||
y: {type: 'bottom', value: 30},
|
||||
x: {type: 'right', value: 0}
|
||||
},
|
||||
show_avatar: true,
|
||||
show_user_avatar: false
|
||||
show_user_avatar: false,
|
||||
}
|
||||
|
||||
const displayFormRef = ref()
|
||||
|
|
@ -486,14 +486,14 @@ const xpackForm = ref<any>({
|
|||
disclaimer_value: t('views.applicationOverview.appInfo.SettingDisplayDialog.disclaimerValue'),
|
||||
custom_theme: {
|
||||
theme_color: '',
|
||||
header_font_color: '#1f2329'
|
||||
header_font_color: '#1f2329',
|
||||
},
|
||||
float_location: {
|
||||
y: {type: 'bottom', value: 30},
|
||||
x: {type: 'right', value: 0}
|
||||
},
|
||||
show_avatar: true,
|
||||
show_user_avatar: false
|
||||
show_user_avatar: false,
|
||||
})
|
||||
|
||||
const imgUrl = ref<any>({
|
||||
|
|
@ -512,7 +512,7 @@ const detail = ref<any>(null)
|
|||
const customStyle = computed(() => {
|
||||
return {
|
||||
background: xpackForm.value.custom_theme?.theme_color,
|
||||
color: xpackForm.value.custom_theme?.header_font_color
|
||||
color: xpackForm.value.custom_theme?.header_font_color,
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -561,7 +561,7 @@ const open = (data: any, content: any) => {
|
|||
t('views.applicationOverview.appInfo.SettingDisplayDialog.disclaimerValue')
|
||||
) {
|
||||
xpackForm.value.disclaimer_value = t(
|
||||
'views.applicationOverview.appInfo.SettingDisplayDialog.disclaimerValue'
|
||||
'views.applicationOverview.appInfo.SettingDisplayDialog.disclaimerValue',
|
||||
)
|
||||
}
|
||||
xpackForm.value.avatar_url = data.avatar
|
||||
|
|
@ -573,7 +573,7 @@ const open = (data: any, content: any) => {
|
|||
xpackForm.value.show_user_avatar = data.show_user_avatar
|
||||
xpackForm.value.custom_theme = {
|
||||
theme_color: data.custom_theme?.theme_color || '',
|
||||
header_font_color: data.custom_theme?.header_font_color || '#1f2329'
|
||||
header_font_color: data.custom_theme?.header_font_color || '#1f2329',
|
||||
}
|
||||
xpackForm.value.float_location = data.float_location
|
||||
dialogVisible.value = true
|
||||
|
|
@ -613,7 +613,7 @@ defineExpose({open})
|
|||
</script>
|
||||
<style lang="scss">
|
||||
.setting-preview {
|
||||
background: #f5f6f7;
|
||||
background: var(--app-layout-bg-color);
|
||||
height: 570px;
|
||||
position: relative;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
<template>
|
||||
<el-card shadow="hover" class="paragraph-box" @mouseenter="cardEnter()" @mouseleave="cardLeave()">
|
||||
<div class="card-header">
|
||||
<h2>{{ 1111 }}</h2>
|
||||
</div>
|
||||
<el-card
|
||||
shadow="hover"
|
||||
class="paragraph-box cursor"
|
||||
@mouseenter="cardEnter()"
|
||||
@mouseleave="cardLeave()"
|
||||
>
|
||||
<h2 class="mb-16">{{ data.title || '-' }}</h2>
|
||||
<MdPreview
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="form.content"
|
||||
:modelValue="data.content"
|
||||
class="maxkb-md"
|
||||
/>
|
||||
</el-card>
|
||||
|
|
@ -14,24 +17,9 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, useSlots } from 'vue'
|
||||
import { t } from '@/locales'
|
||||
defineOptions({ name: 'CardBox' })
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
title?: string
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
description?: string
|
||||
/**
|
||||
* 是否展示icon
|
||||
*/
|
||||
showIcon?: boolean
|
||||
}>(),
|
||||
{ title: t('common.title'), description: '', showIcon: true, border: true },
|
||||
)
|
||||
const props = defineProps<{
|
||||
data: any
|
||||
}>()
|
||||
|
||||
const show = ref(false)
|
||||
// card上面存在dropdown菜单
|
||||
|
|
@ -50,36 +38,13 @@ function subHoveredEnter() {
|
|||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.card-box {
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
min-height: var(--card-min-height);
|
||||
min-width: var(--card-min-width);
|
||||
.card-header {
|
||||
margin-top: -5px;
|
||||
}
|
||||
.description {
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
min-height: 70px;
|
||||
.content {
|
||||
display: -webkit-box;
|
||||
height: var(--app-card-box-description-height, 40px);
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
left: 0;
|
||||
min-height: 30px;
|
||||
font-weight: 400;
|
||||
padding: 0 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
.paragraph-box {
|
||||
background: var(--app-layout-bg-color);
|
||||
border: 1px solid #ffffff;
|
||||
box-shadow: none !important;
|
||||
&:hover {
|
||||
background: rgba(31, 35, 41, 0.1);
|
||||
border: 1px solid #dee0e3;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
</div>
|
||||
<el-card
|
||||
style="--el-card-padding: 0"
|
||||
class="paragraph-detail__main mt-16"
|
||||
class="paragraph__main mt-16"
|
||||
v-loading="(paginationConfig.current_page === 1 && loading) || changeStateloading"
|
||||
>
|
||||
<div class="flex-between p-12-16 border-b">
|
||||
|
|
@ -46,22 +46,58 @@
|
|||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<el-empty v-if="paragraphDetail.length == 0" :description="$t('common.noData')" />
|
||||
<div v-else>
|
||||
<el-scrollbar>
|
||||
<div class="paragraph-detail-height">
|
||||
<InfiniteScroll
|
||||
:size="paragraphDetail.length"
|
||||
:total="paginationConfig.total"
|
||||
:page_size="paginationConfig.page_size"
|
||||
v-model:current_page="paginationConfig.current_page"
|
||||
@load="getParagraphList"
|
||||
:loading="loading"
|
||||
>
|
||||
|
||||
</InfiniteScroll>
|
||||
<div class="flex">
|
||||
<div class="paragraph-sidebar p-16 border-r">
|
||||
<el-anchor
|
||||
direction="vertical"
|
||||
type="default"
|
||||
:offset="130"
|
||||
container=".paragraph-scollbar"
|
||||
@click="handleClick"
|
||||
>
|
||||
<template v-for="(item, index) in paragraphDetail" :key="item.id">
|
||||
<el-anchor-link :href="`#${item.id}`" :title="item.title" v-if="item.title" />
|
||||
</template>
|
||||
</el-anchor>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<el-empty v-if="paragraphDetail.length == 0" :description="$t('common.noData')" />
|
||||
<div v-else>
|
||||
<el-scrollbar class="paragraph-scollbar">
|
||||
<div class="paragraph-detail">
|
||||
<InfiniteScroll
|
||||
:size="paragraphDetail.length"
|
||||
:total="paginationConfig.total"
|
||||
:page_size="paginationConfig.page_size"
|
||||
v-model:current_page="paginationConfig.current_page"
|
||||
@load="getParagraphList"
|
||||
:loading="loading"
|
||||
>
|
||||
<VueDraggable
|
||||
ref="el"
|
||||
v-bind:modelValue="paragraphDetail"
|
||||
handle=".handle"
|
||||
:animation="150"
|
||||
ghostClass="ghost"
|
||||
@end="onEnd"
|
||||
>
|
||||
<template v-for="(item, index) in paragraphDetail" :key="item.id">
|
||||
<div class="handle paragraph-card flex" :id="item.id">
|
||||
<img
|
||||
src="@/assets/sort.svg"
|
||||
alt=""
|
||||
height="15"
|
||||
class="handle-img mr-8 mt-24 cursor"
|
||||
/>
|
||||
<ParagraphCard :data="item" class="mb-8 w-full" />
|
||||
</div>
|
||||
</template>
|
||||
</VueDraggable>
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mul-operation border-t w-full" v-if="isBatch === true">
|
||||
|
|
@ -89,12 +125,15 @@
|
|||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import documentApi from '@/api/knowledge/document'
|
||||
import paragraphApi from '@/api/knowledge/paragraph'
|
||||
import ParagraphDialog from './component/ParagraphDialog.vue'
|
||||
import ParagraphCard from './component/ParagraphCard.vue'
|
||||
import SelectDocumentDialog from './component/SelectDocumentDialog.vue'
|
||||
import GenerateRelatedDialog from '@/components/generate-related-dialog/index.vue'
|
||||
import { numberFormat } from '@/utils/utils'
|
||||
import { numberFormat } from '@/utils/common'
|
||||
import { VueDraggable } from 'vue-draggable-plus'
|
||||
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||
import useStore from '@/stores'
|
||||
import { t } from '@/locales'
|
||||
|
|
@ -104,6 +143,7 @@ const {
|
|||
params: { id, documentId },
|
||||
} = route as any
|
||||
|
||||
const containerRef = ref<HTMLElement | null>(null)
|
||||
const SelectDocumentDialogRef = ref()
|
||||
const ParagraphDialogRef = ref()
|
||||
const loading = ref(false)
|
||||
|
|
@ -114,6 +154,10 @@ const title = ref('')
|
|||
const search = ref('')
|
||||
const searchType = ref('title')
|
||||
|
||||
const handleClick = (e: MouseEvent) => {
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
// 批量操作
|
||||
const isBatch = ref(false)
|
||||
const multipleSelection = ref<any[]>([])
|
||||
|
|
@ -279,6 +323,20 @@ function openGenerateDialog(row?: any) {
|
|||
GenerateRelatedDialogRef.value.open(arr, 'paragraph')
|
||||
}
|
||||
|
||||
function onEnd(event?: any) {
|
||||
const { oldIndex, newIndex } = event
|
||||
if (oldIndex === undefined || newIndex === undefined) return
|
||||
const list = cloneDeep(paragraphDetail.value)
|
||||
if (oldIndex === list.length - 1 || newIndex === list.length - 1) {
|
||||
return
|
||||
}
|
||||
const newInstance = { ...list[oldIndex], type: list[newIndex].type, id: list[newIndex].id }
|
||||
const oldInstance = { ...list[newIndex], type: list[oldIndex].type, id: list[oldIndex].id }
|
||||
list[newIndex] = newInstance
|
||||
list[oldIndex] = oldInstance
|
||||
paragraphDetail.value = list
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDetail()
|
||||
getParagraphList()
|
||||
|
|
@ -292,43 +350,14 @@ onMounted(() => {
|
|||
right: calc(var(--app-base-px) * 3);
|
||||
top: calc(var(--app-base-px) + 4px);
|
||||
}
|
||||
|
||||
.paragraph-detail-height {
|
||||
height: calc(var(--app-main-height) - 75px);
|
||||
.paragraph-sidebar {
|
||||
width: 240px;
|
||||
}
|
||||
.paragraph-card {
|
||||
height: 210px;
|
||||
background: var(--app-layout-bg-color);
|
||||
border: 1px solid var(--app-layout-bg-color);
|
||||
&.selected {
|
||||
background: #ffffff;
|
||||
&:hover {
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
&: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(.content) {
|
||||
-webkit-line-clamp: 5 !important;
|
||||
height: 110px !important;
|
||||
}
|
||||
.active-button {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 16px;
|
||||
}
|
||||
|
||||
.paragraph-detail {
|
||||
height: calc(100vh - 215px);
|
||||
max-width: 1000px;
|
||||
margin: 16px auto;
|
||||
}
|
||||
|
||||
&__main {
|
||||
|
|
@ -343,5 +372,17 @@ onMounted(() => {
|
|||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
.paragraph-card {
|
||||
&.handle {
|
||||
.handle-img {
|
||||
visibility: hidden;
|
||||
}
|
||||
&:hover {
|
||||
.handle-img {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue