初始化

This commit is contained in:
qsh
2024-04-28 16:20:45 +08:00
parent 3f2749b6c4
commit 58929c05ef
687 changed files with 90151 additions and 13 deletions

View File

@@ -0,0 +1,67 @@
<template>
<el-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-item>
<el-form-item label="资源类型" prop="type">
<el-radio-group v-model="form.type">
<el-radio :label="1"> 文件 </el-radio>
<el-radio :label="2"> 纯图片 </el-radio>
<el-radio :label="3"> 自主编辑 </el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<Editor v-model:modelValue="form.remark" />
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="handleSave"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
const dialogVisible = ref(false) // 弹窗的是否展示
const form = ref()
const rules = ref({
name: { required: true, message: '名称不可为空', trigger: 'blur' }
})
const title = ref('')
const addForm = ref()
const emit = defineEmits(['update'])
const open = (val) => {
dialogVisible.value = true
if (val) {
title.value = '修改知识库'
form.value = { ...val }
} else {
title.value = '新增知识库'
form.value = {
name: '',
type: 1,
remark: undefined
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
function handleSave() {
addForm.value.validate((valid) => {
if (valid) {
emit('update', form.value)
dialogVisible.value = false
}
})
}
</script>
<style scoped></style>

View File

@@ -0,0 +1,101 @@
<template>
<el-dialog :title="title" v-model="show" width="800px">
<el-form :model="form" ref="resourceForm" :rules="rules" label-width="60px">
<el-row :gutter="20">
<el-col :span="12" :offset="0">
<el-form-item label="标题" prop="title">
<el-input v-model="form.title" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
<el-form-item label="标签" prop="tipList">
<el-select
v-model="form.tipList"
multiple
filterable
allow-create
default-first-option
:reserve-keyword="false"
placeholder="请选择标签或输入"
clearable
style="width: 100%"
>
<el-option
v-for="item in tipOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<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"
width="100px"
height="100px"
/>
<Editor v-else v-model:modelValue="form.content" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24" :offset="0">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span>
<el-button @click="show = false"> </el-button>
<el-button type="primary" @click="handleSave"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
const show = ref(false)
const title = ref('')
const form = ref({})
const rules = ref({})
const tipOptions = ref([{ label: '绿色', value: '绿色' }])
function open(type, val) {
show.value = true
if (val) {
title.value = '修改资源'
form.value = { ...val, type }
} else {
title.value = '新增资源'
form.value = {
type,
title: '',
tipList: [],
sliderPicUrls: [],
content: '',
remark: null
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
function handleSave() {
console.log('保存成功')
}
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,120 @@
<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"
direction="ltr"
size="20%"
:show-close="false"
:modal="false"
:lock-scroll="false"
:close-on-press-escape="false"
style="background-color: rgba(0, 0, 0, 0.6)"
>
<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>
<template #footer>
<div class="flex justify-between">
<el-button plain :disabled="imgIndex <= 0" @click="imgIndex--">上一张</el-button>
<el-button plain :disabled="imgIndex >= imgList.length - 1" @click="imgIndex++"
>下一张</el-button
>
</div>
</template>
</el-drawer>
<img :src="info.fileUrl" :alt="info.fileName" srcset="" class="width-fit img" />
<div class="img-idx">{{ imgIndex + 1 }} / {{ imgList.length }}</div>
</div>
</teleport>
</template>
<script setup>
import { ElIcon } from 'element-plus'
import { CircleClose } from '@element-plus/icons-vue'
const show = ref(false)
const imgIndex = ref(0)
const imgList = ref([])
const showDrawer = ref(true)
function open(idx = 0, arr = []) {
show.value = true
imgIndex.value = idx
imgList.value = arr
}
const info = computed(() => {
return imgList.value[imgIndex.value]
})
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
</script>
<style lang="scss" scoped>
.container {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba($color: #000000, $alpha: 0.5);
z-index: 9999999;
max-width: 100%;
.close-icon {
position: absolute;
top: 40px;
right: 40px;
font-size: 40px;
color: #fff;
cursor: pointer;
z-index: 9999;
}
:deep(.el-form-item__label) {
color: #fff;
}
.img {
position: absolute;
top: 50%;
left: 60%;
transform: translate3d(-50%, -50%, 0);
width: 30%;
}
.img-idx {
position: absolute;
bottom: 50px;
left: 60%;
transform: translateX(-50%);
width: 100px;
height: 30px;
line-height: 30px;
border-radius: 30px;
color: #fff;
text-align: center;
background-color: rgba($color: #000000, $alpha: 0.6);
}
}
</style>

View File

@@ -0,0 +1,202 @@
<template>
<div class="flex">
<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>
</div>
<div class="border-top-1px mt-10px pt-10px">
<div
class="flex justify-between items-center pl-10px pr-10px cursor-pointer pt-5px pb-5px"
v-for="(item, index) in libraryList"
:key="index"
:class="{ actived: libraryIndex == index }"
@click="libraryIndex = index"
>
<div class="flex-1 text-14px">{{ item.name }}</div>
<div class="ml-10px">
<el-button type="primary" style="padding: 0px" text @click="handleUpdate(item)"
>修改</el-button
>
<el-button
type="primary"
class="ml-10px"
style="padding: 0px"
text
@click="handleRemove(index)"
>删除</el-button
>
</div>
</div>
<Pagination
v-model:limit="pageSize"
v-model:page="currentPage"
:total="total"
@pagination="getList"
/>
</div>
</el-card>
<el-card 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>
<div v-if="libraryList[libraryIndex].type == 1">
<el-table :data="tableList" border>
<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>
</template>
</el-table-column>
<el-table-column prop="fileName" label="附件">
<template #default="{ row }">
<el-link type="primary" underline :href="row.fileUrl" target="_blank">{{
row.fileName
}}</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
>
</template>
</el-table-column>
</el-table>
</div>
<div v-else-if="libraryList[libraryIndex].type == 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" />
<div class="mt-5px text-center">{{ item.title }}</div>
</div>
</div>
<div v-else>
<el-table :data="tableList" border>
<el-table-column type="index" width="50" />
<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>
</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
>
</template>
</el-table-column>
</el-table>
</div>
<Pagination
v-model:limit="resourcePageSize"
v-model:page="resourcePageNum"
:total="resourceTotal"
@pagination="getResourceList"
/>
</el-card>
</div>
<DialogLibrary ref="library" @update="afterSaveLibrary" />
<DialogResource ref="resourceDialog" />
<ImagePreview ref="imgPreview" />
</template>
<script setup>
import DialogLibrary from './Comp/DialogLibrary.vue'
import DialogResource from './Comp/DialogResource.vue'
import ImagePreview from './Comp/ImagePreview.vue'
const libraryIndex = ref(0)
const libraryList = ref([
{ name: '成交案例', id: 1, type: 2 },
{ name: '公司资质材料', id: 2, type: 1 },
{ name: '会议纪要', id: 3, type: 3 }
])
const pageSize = ref(20)
const currentPage = ref(1)
const total = ref(0)
const library = ref()
const resourceDialog = ref()
const imgPreview = ref()
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'
}
])
function handleAdd() {
// 新增知识库
library.value.open(null)
}
function handleUpdate(item) {
library.value.open(item)
}
function handleRemove(index) {
libraryList.value.splice(index, 1)
}
function afterSaveLibrary(val) {
libraryList.value.push(val)
}
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 removeResource(index) {
tableList.value.splice(index, 1)
}
function getResourceList() {
tableList.value = []
}
/** 商品图预览 */
function imagePreview(index) {
imgPreview.value.open(index, tableList.value)
}
</script>
<style lang="scss" scoped>
.actived {
background-color: #f0f7ff;
font-weight: bold;
}
</style>

View File

@@ -0,0 +1,62 @@
// import { CrudSchema } from '@/hooks/web/useCrudSchemas'
import { dateFormatter } from '@/utils/formatTime'
const statusOptions = [
{ label: '发送成功', value: 1 },
{ label: '发送失败', value: 2 },
{ label: '排队中', value: 3 },
{ label: '微信端卡住', value: 4 }
]
// CrudSchemahttps://doc.iocoder.cn/vue3/crud-schema/
const crudSchemas = reactive([
{
label: '发送对象',
field: 'sendUser',
isSearch: true,
isTable: true
},
{
label: '发送内容',
field: 'content',
isSearch: false,
isTable: true
},
{
label: '发送状态',
field: 'status',
isSearch: true,
isTable: true,
search: {
component: 'Select',
api: () => statusOptions,
componentProps: {
optionsAlias: {
labelField: 'label',
valueField: 'value'
}
}
}
},
{
label: '发送时间',
field: 'createTime',
isSearch: true,
isTable: true,
formatter: dateFormatter,
detail: {
dateFormat: 'YYYY-MM-DD'
},
search: {
component: 'DatePicker',
componentProps: {
type: 'daterange',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
startPlaceholder: '发送时间',
endPlaceholder: '发送时间'
}
}
}
])
export const { allSchemas } = useCrudSchemas(crudSchemas)

View File

@@ -0,0 +1,77 @@
<template>
<el-tabs v-model="tabIndex" type="border-card">
<el-tab-pane label="微信消息记录" :name="0">
<!-- 搜索工作栏 -->
<Search
:schema="allSchemas.searchSchema"
labelWidth="0"
@search="setSearchParams"
@reset="setSearchParams"
/>
<!-- 列表 -->
<SSTable
class="mt-20px"
v-model:tableObject="tableObject"
:tableColumns="allSchemas.tableColumns"
@get-list="getTableList"
>
<el-table-column
v-for="item in allSchemas.tableColumns"
:key="item.field"
:prop="item.field"
:label="item.label"
:fixed="item.fixed"
min-width="150px"
showOverflowTooltip
/>
<el-table-column label="操作" width="150px" fixed="right">
<template #default="{ row }">
<el-button type="primary" link @click="sendMsg(row)">再次发送</el-button>
</template>
</el-table-column>
</SSTable>
</el-tab-pane>
</el-tabs>
</template>
<script setup>
import { allSchemas } from './index.data.js'
const tabIndex = ref(0)
const tableObject = ref({
tableList: [],
loading: false,
total: 1,
pageSize: 20,
currentPage: 1
})
function setSearchParams() {
tableObject.value.tableList = [
{
sendUser: '测试',
content: '您今日有10条待跟进的线索',
status: '发送成功',
createTime: '2024-04-25 12:00:00'
}
]
}
function getTableList() {
tableObject.value.tableList = [
{
sendUser: '测试',
content: '您今日有10条待跟进的线索',
status: '发送成功',
createTime: '2024-04-25 12:00:00'
}
]
}
function sendMsg() {
console.log('测试')
}
</script>
<style lang="scss" scoped></style>