This commit is contained in:
qsh
2024-06-05 17:08:27 +08:00
parent a557255b4a
commit 94943df4f9
30 changed files with 1069 additions and 846 deletions

View File

@@ -1,11 +1,11 @@
<template>
<Dialog :title="title" v-model="dialogVisible" width="800px">
<el-form :model="form" ref="addForm" :rules="rules" label-width="100px">
<el-form-item label="知识库名称" prop="name">
<el-input v-model="form.name" placeholder="请输入" />
<el-form v-loading="formLoading" :model="form" ref="formRef" :rules="rules" label-width="100px">
<el-form-item label="知识库名称" prop="libName">
<el-input v-model="form.libName" placeholder="请输入" />
</el-form-item>
<el-form-item label="资源类型" prop="type">
<el-radio-group v-model="form.type">
<el-form-item label="资源类型" prop="libType">
<el-radio-group v-model="form.libType">
<el-radio :label="1"> 文件 </el-radio>
<el-radio :label="2"> 纯图片 </el-radio>
<el-radio :label="3"> 自主编辑 </el-radio>
@@ -18,49 +18,71 @@
<template #footer>
<span>
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="handleSave"> </el-button>
<el-button type="primary" :disabled="formLoading" @click="handleSave"> </el-button>
</span>
</template>
</Dialog>
</template>
<script setup>
import * as LibraryApi from '@/api/system/library'
const emit = defineEmits(['success'])
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const form = ref()
const rules = ref({
name: { required: true, message: '名称不可为空', trigger: 'blur' }
libName: { required: true, message: '名称不可为空', trigger: 'blur' }
})
const title = ref('')
const addForm = ref()
const formRef = ref()
const formLoading = ref(false)
const formType = ref('create')
const emit = defineEmits(['update'])
const open = (val) => {
const open = (type, val) => {
dialogVisible.value = true
formType.value = type
if (val) {
title.value = '修改知识库'
form.value = { ...val }
} else {
title.value = '新增知识库'
form.value = {
name: '',
type: 1,
remark: undefined
libName: '',
libType: 1,
remark: undefined,
isDefault: false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
function handleSave() {
addForm.value.validate((valid) => {
if (valid) {
emit('update', form.value)
dialogVisible.value = false
async function handleSave() {
// 校验表单
if (!formRef.value) return
const valid = await formRef.value.validate()
if (!valid) return
// 提交请求
formLoading.value = true
try {
if (formType.value === 'create') {
await LibraryApi.createLibrary(form.value)
message.success(t('common.createSuccess'))
} else {
await LibraryApi.updateLibrary(form.value)
message.success(t('common.updateSuccess'))
}
})
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
</script>

View File

@@ -1,6 +1,6 @@
<template>
<Dialog :title="title" v-model="show" width="800px">
<el-form :model="form" ref="resourceForm" :rules="rules" label-width="60px">
<el-form v-loading="formLoading" :model="form" ref="formRef" :rules="rules" label-width="60px">
<el-row :gutter="20">
<el-col :span="12" :offset="0">
<el-form-item label="标题" prop="title">
@@ -8,16 +8,19 @@
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="标签" prop="tipList">
<el-form-item label="标签" prop="tags">
<el-select
v-model="form.tipList"
v-model="form.tags"
multiple
filterable
collapse-tags
collapse-tags-tooltip
allow-create
default-first-option
:reserve-keyword="false"
placeholder="请选择标签或输入"
clearable
@change="tipChange"
style="width: 100%"
>
<el-option
@@ -33,15 +36,10 @@
<el-row :gutter="20">
<el-col :span="24" :offset="0">
<el-form-item label="内容" prop="content">
<UploadFile
v-if="form.type == 1"
v-model="form.sliderPicUrls"
:isShowTip="false"
:fileType="[]"
/>
<UploadImgs
v-else-if="form.type == 2"
v-model:modelValue="form.sliderPicUrls"
<UploadFile v-if="libType == 1" v-model="form.files" :limit="1" :isShowTip="false" />
<UploadImg
v-else-if="libType == 2"
v-model:modelValue="form.files"
width="100px"
height="100px"
/>
@@ -60,41 +58,107 @@
<template #footer>
<span>
<el-button @click="show = false"> </el-button>
<el-button type="primary" @click="handleSave"> </el-button>
<el-button type="primary" :disabled="formLoading" @click="handleSave"> </el-button>
</span>
</template>
</Dialog>
</template>
<script setup>
<script setup name="DialogResource">
import * as ResourceApi from '@/api/system/library/resource'
import { getDictOptions } from '@/utils/dict'
import * as dictApi from '@/api/system/dict/dict.data'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const show = ref(false)
const title = ref('')
const formType = ref('create')
const libType = ref(1)
const form = ref({})
const rules = ref({})
const formLoading = ref(false)
const rules = ref({
title: { required: true, message: '标题不可为空', trigger: 'blur' }
})
const tipOptions = ref([{ label: '绿色', value: '绿色' }])
const tipOptions = ref([])
function open(type, val) {
function getOptions() {
tipOptions.value = getDictOptions('knowledge_tags')
}
async function open(type, info, id) {
show.value = true
if (val) {
title.value = '修改资源'
form.value = { ...val, type }
} else {
title.value = '新增资源'
form.value = {
type,
title: '',
tipList: [],
sliderPicUrls: [],
content: '',
remark: null
title.value = type == 'update' ? '修改资源' : '新增资源'
formType.value = type
libType.value = info.libType
resetForm(info.libId)
getOptions()
if (id) {
formLoading.value = true
try {
form.value = await ResourceApi.getResource(id)
} finally {
formLoading.value = false
}
}
}
function resetForm(libId) {
form.value = {
libId,
title: '',
tags: [],
files: '',
content: '',
remark: null,
isDefault: false
}
}
async function tipChange(val) {
const valStr = val.at(-1)
if (!tipOptions.value.some((it) => it.value == valStr)) {
await dictApi.createDictData({
label: valStr,
value: valStr,
sort: 1,
status: 0,
dictType: 'knowledge_tags'
})
tipOptions.value.push({ label: valStr, value: valStr })
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
function handleSave() {
console.log('保存成功')
const formRef = ref()
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
async function handleSave() {
// 校验表单
if (!formRef.value) return
const valid = await formRef.value.validate()
if (!valid) return
// 提交请求
formLoading.value = true
try {
if (formType.value === 'create') {
await ResourceApi.createResource(form.value)
message.success(t('common.createSuccess'))
} else {
await ResourceApi.updateResource(form.value)
message.success(t('common.updateSuccess'))
}
show.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
</script>

View File

@@ -1,7 +1,6 @@
<template>
<teleport v-if="show" to="#app">
<div class="container">
<!-- <Icon class="ep:circle-close close-icon" /> -->
<el-icon class="close-icon" @click="show = false"><CircleClose /></el-icon>
<el-drawer
v-model="showDrawer"
@@ -16,22 +15,30 @@
<template #header>
<span style="color: #fff">资源详情</span>
</template>
<el-form style="flex: 1" :model="info" label-width="80px" label-position="left">
<el-form-item label="标题:">
{{ info.title }}
</el-form-item>
<el-form-item label="文件名称:">
{{ info.fileName }}
</el-form-item>
<el-form-item label="标签:">
<el-tag class="mr-5px mb-5px" v-for="(item, index) in info.tipList" :key="index">{{
item
}}</el-tag>
</el-form-item>
<el-form-item label="备注:">
{{ info.remark }}
</el-form-item>
</el-form>
<div>
<div class="flex mb-18px">
<div class="w-80px text-light-50">标题</div>
<div class="flex-1 ml-10px text-light-50">{{ info.title }}</div>
</div>
<div class="flex mb-18px">
<div class="w-80px text-light-50">文件名称</div>
<div class="flex-1 ml-10px text-light-50 w-80px" style="word-wrap: break-word">{{
info.files
}}</div>
</div>
<div class="flex mb-18px">
<div class="w-80px text-light-50">标签</div>
<div class="flex-1 ml-10px w-80px">
<el-tag class="mr-5px" v-for="(item, index) in info.tags" :key="index">
{{ getDictLabel('knowledge_tags', item) }}
</el-tag>
</div>
</div>
<div class="flex mb-18px">
<div class="w-80px text-light-50">备注</div>
<div class="flex-1 ml-10px text-light-50">{{ info.remark }}</div>
</div>
</div>
<template #footer>
<div class="flex justify-between">
<el-button plain :disabled="imgIndex <= 0" @click="imgIndex--">上一张</el-button>
@@ -42,13 +49,14 @@
</template>
</el-drawer>
<img :src="info.fileUrl" :alt="info.fileName" srcset="" class="width-fit img" />
<img :src="info.files" :alt="info.files" srcset="" class="width-fit img" />
<div class="img-idx">{{ imgIndex + 1 }} / {{ imgList.length }}</div>
</div>
</teleport>
</template>
<script setup>
import { getDictLabel } from '@/utils/dict'
import { ElIcon } from 'element-plus'
import { CircleClose } from '@element-plus/icons-vue'

View File

@@ -3,7 +3,9 @@
<el-card shadow="always" :body-style="{ padding: '10px' }">
<div class="flex justify-between items-center" style="width: 400px">
<div class="text-16px font-bold">知识库名称</div>
<el-button type="primary" style="padding: 0px" text @click="handleAdd">新增</el-button>
<el-button type="primary" style="padding: 0px" text @click="openForm('create', null)"
>新增</el-button
>
</div>
<div class="border-top-1px mt-10px pt-10px">
<div
@@ -11,24 +13,27 @@
v-for="(item, index) in libraryList"
:key="index"
:class="{ actived: libraryIndex == index }"
@click="libraryIndex = index"
@click="handleClickLib(index)"
>
<div class="flex-1 text-14px">{{ item.name }}</div>
<div class="flex-1 text-14px">{{ item.libName }}</div>
<div class="ml-10px">
<el-button type="primary" style="padding: 0px" text @click="handleUpdate(item)"
>修改</el-button
>
<el-button type="primary" style="padding: 0px" text @click="openForm('update', item)">
修改
</el-button>
<el-button
type="primary"
class="ml-10px"
style="padding: 0px"
text
@click="handleRemove(index)"
>删除</el-button
@click="handleRemove(item.libId)"
>
删除
</el-button>
</div>
</div>
<Pagination
small
layout="total, prev, pager, next, jumper"
v-model:limit="pageSize"
v-model:page="currentPage"
:total="total"
@@ -36,44 +41,55 @@
/>
</div>
</el-card>
<el-card class="ml-20px" style="flex: 1" shadow="always" :body-style="{ padding: '10px' }">
<el-card
v-if="libraryList.length"
class="ml-20px"
style="flex: 1"
shadow="always"
:body-style="{ padding: '10px' }"
>
<div class="flex justify-between items-center border-bottom-1px pb-10px mb-20px">
<div>{{ libraryList[libraryIndex].name }}资源详情</div>
<el-button type="primary" @click="handleAddResource">新增资源</el-button>
<div>{{ libraryList[libraryIndex].libName }}资源详情</div>
<el-button type="primary" @click="openResource('create', null)">新增资源</el-button>
</div>
<div v-if="libraryList[libraryIndex].type == 1">
<el-table :data="tableList" border>
<div v-if="libraryList[libraryIndex].libType == 1">
<el-table :data="tableList" border v-loading="loading">
<el-table-column type="index" width="50" />
<el-table-column prop="title" label="标题" width="200" />
<el-table-column label="标签" width="200px">
<template #default="{ row }">
<el-tag v-for="(item, index) in row.tipList" :key="index" class="mr-5px">{{
item
}}</el-tag>
<el-tag v-for="(item, index) in row.tags" :key="index" class="mr-5px">
{{ getDictLabel('knowledge_tags', item) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="fileName" label="附件">
<el-table-column prop="files" label="附件">
<template #default="{ row }">
<el-link type="primary" underline :href="row.fileUrl" target="_blank">{{
row.fileName
}}</el-link>
<el-link type="primary" underline :href="row.fileUrl" target="_blank">
{{ row.files }}
</el-link>
</template>
</el-table-column>
<el-table-column label="操作" width="120px">
<template #default="{ row, $index }">
<el-button type="primary" style="padding: 0" text @click="updateResource(row)"
>修改</el-button
>
<el-button type="danger" style="padding: 0" text @click="removeResource($index)"
>删除</el-button
<el-button
type="primary"
style="padding: 0"
text
@click="openResource('update', row.id)"
>
修改
</el-button>
<el-button type="danger" style="padding: 0" text @click="removeResource($index)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div v-else-if="libraryList[libraryIndex].type == 2" class="flex">
<div v-else-if="libraryList[libraryIndex].libType == 2" class="flex">
<div v-for="(item, index) in tableList" :key="index" class="mr-10px">
<el-image :src="item.fileUrl" @click="imagePreview(index)" class="w-150px h-150px" />
<el-image :src="item.files" @click="imagePreview(index)" class="w-150px h-150px" />
<div class="mt-5px text-center">{{ item.title }}</div>
</div>
</div>
@@ -83,19 +99,24 @@
<el-table-column prop="title" label="标题" />
<el-table-column label="标签">
<template #default="{ row }">
<el-tag v-for="(item, index) in row.tipList" :key="index" class="mr-5px">{{
item
}}</el-tag>
<el-tag v-for="(item, index) in row.tags" :key="index" class="mr-5px">
{{ getDictLabel('knowledge_tags', item) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="120px">
<template #default="{ row, $index }">
<el-button type="primary" style="padding: 0" text @click="updateResource(row)"
>修改</el-button
>
<el-button type="danger" style="padding: 0" text @click="removeResource($index)"
>删除</el-button
<el-button
type="primary"
style="padding: 0"
text
@click="openResource('update', row.infoId)"
>
修改
</el-button>
<el-button type="danger" style="padding: 0" text @click="removeResource($index)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
@@ -108,27 +129,31 @@
/>
</el-card>
</div>
<DialogLibrary ref="library" @update="afterSaveLibrary" />
<DialogResource ref="resourceDialog" />
<DialogLibrary ref="library" @success="getList" />
<DialogResource ref="resourceDialog" @success="getResourceList" />
<ImagePreview ref="imgPreview" />
</template>
<script setup>
<script setup name="Library">
import * as LibraryApi from '@/api/system/library/index'
import * as ResourceApi from '@/api/system/library/resource'
import DialogLibrary from './Comp/DialogLibrary.vue'
import DialogResource from './Comp/DialogResource.vue'
import ImagePreview from './Comp/ImagePreview.vue'
import { getDictLabel } from '@/utils/dict'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const libraryIndex = ref(0)
const libraryList = ref([
{ name: '成交案例', id: 1, type: 2 },
{ name: '公司资质材料', id: 2, type: 1 },
{ name: '会议纪要', id: 3, type: 3 }
])
const libraryList = ref([])
const pageSize = ref(20)
const currentPage = ref(1)
const total = ref(0)
const loading = ref(false)
const library = ref()
const resourceDialog = ref()
const imgPreview = ref()
@@ -137,61 +162,70 @@ const resourcePageSize = ref(20)
const resourcePageNum = ref(1)
const resourceTotal = ref(0)
const tableList = ref([
{
fileUrl:
'https://img0.baidu.com/it/u=1033018635,7901815&fm=253&fmt=auto&app=138&f=JPEG?w=750&h=500',
fileName: '测试图片1'
},
{
tipList: ['优质材料', '无污染'],
fileUrl:
'https://img0.baidu.com/it/u=1610680713,975251961&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=750',
fileName: '测试图片2'
}
])
const tableList = ref([])
function handleAdd() {
// 新增知识库
library.value.open(null)
function openForm(type, item) {
library.value.open(type, item)
}
function handleUpdate(item) {
library.value.open(item)
async function handleRemove(id) {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await LibraryApi.deleteLibrary(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
function handleRemove(index) {
libraryList.value.splice(index, 1)
async function getList() {
const data = await LibraryApi.getLibraryPage({
pageNo: currentPage.value,
pageSize: pageSize.value
})
libraryList.value = data.list
total.value = data.total
handleClickLib(0)
}
function afterSaveLibrary(val) {
libraryList.value.push(val)
function handleClickLib(index) {
libraryIndex.value = index
getResourceList()
}
function getList() {
libraryList.value = []
}
function handleAddResource() {
resourceDialog.value.open(libraryList.value[libraryIndex.value].type, null)
}
function updateResource(row) {
resourceDialog.value.open(libraryList.value[libraryIndex.value].type, row)
function openResource(type, id) {
resourceDialog.value.open(type, libraryList.value[libraryIndex.value], id)
}
function removeResource(index) {
tableList.value.splice(index, 1)
}
function getResourceList() {
tableList.value = []
async function getResourceList() {
loading.value = true
try {
const data = await ResourceApi.getResourcePage({
libId: libraryList.value[libraryIndex.value].libId,
pageNo: resourcePageNum.value,
pageSize: resourcePageSize.value
})
tableList.value = data.list
resourceTotal.value = data.total
} finally {
loading.value = false
}
}
/** 商品图预览 */
function imagePreview(index) {
imgPreview.value.open(index, tableList.value)
}
onMounted(() => {
getList()
})
</script>
<style lang="scss" scoped>