<!-- 笔记管理 --> <template> <div class="p-2"> <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> <div v-show="showSearch" class="mb-[10px]"> <el-card shadow="hover"> <el-form ref="queryFormRef" :model="queryParams" :inline="true"> <el-form-item label="笔记标题" prop="id"> <el-input v-model="queryParams.title" placeholder="请输入笔记标题" clearable @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="发布人" prop="title"> <el-input v-model="queryParams.title" placeholder="请输入发布人" clearable @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="标记地点" prop="cover"> <!-- <el-input v-model="queryParams.cover" placeholder="请输入标记地点" clearable @keyup.enter="handleQuery" />--> <el-select v-model="queryParams.cover" placeholder="请选择标记地点" style="width: 240px"> <el-option v-for="item in sys_user_contentOptions" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> <el-form-item label="发布状态" prop="tagId"> <!-- <el-input v-model="queryParams.tagId" placeholder="请输入标签" clearable @keyup.enter="handleQuery" /> --> <el-select v-model="queryParams.status" placeholder="请选择发布状态" style="width: 240px" @keyup.enter="handleQuery"> <el-option v-for="item in statusoptions" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button> <el-button icon="Refresh" @click="resetQuery">重置</el-button> <el-button v-hasPermi="['manage:notebook:add']" type="primary" plain icon="Plus" @click="handleAdd">新增 </el-button> </el-form-item> </el-form> </el-card> </div> </transition> <el-card shadow="never"> <el-table v-loading="loading" :data="notebookList" @selection-change="handleSelectionChange"> <!-- <el-table-column type="selection" width="55" align="center" />--> <el-table-column v-if="true" label="ID" align="center" prop="id" /> <el-table-column label="笔记标题" align="center" prop="title" /> <el-table-column label="笔记封面" align="center" prop="cover"> <template #default="scope"> <image-preview :src="scope.row.cover" :width="50" :height="50" /> <!-- <image-preview :src="scope.row.productImageUrl" /> --> </template> </el-table-column> <el-table-column label="标记地点" align="center" prop="location"> <template #default="scope"> <span>{{ formatlocation(scope.row.location) }}</span> </template> </el-table-column> <el-table-column label="标签" align="center" prop="tagId"> <template #default="scope"> <span>{{ formatTag(scope.row.tagId) }}</span> </template> </el-table-column> <el-table-column label="笔记详情" align="center" prop="tagId"> <template #default="scope"> <el-button type="text" @click="contenttext(scope.row)">查看详情</el-button> <!-- <image-preview :src="scope.row.productImageUrl" /> --> </template> </el-table-column> <el-table-column label="笔记评论数" align="center" prop="commentCount"> <template #default="scope"> <el-button type="text" @click="handleComment(scope.row)">{{ scope.row.commentCount }}</el-button> <!-- <image-preview :src="scope.row.productImageUrl" /> --> </template> </el-table-column> <el-table-column label="笔记点赞数" align="center" prop="agreeCount" /> <el-table-column label="发布状态" align="center" prop="status"> <template #default="scope"> <el-tag v-if="scope.row.status == 0" type="info">未发布</el-tag> <el-tag v-if="scope.row.status == 1" type="warning">草稿</el-tag> <el-tag v-if="scope.row.status == 2" type="success">审核中</el-tag> <el-tag v-if="scope.row.status == 3" type="primary">已发布</el-tag> <!-- <image-preview :src="scope.row.productImageUrl" /> --> </template> </el-table-column> <el-table-column label="操作人" align="center" prop="updateByName" show-overflow-tooltip /> <el-table-column label="操作时间" align="center" prop="updateTime" width="200px" /> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150px"> <template #default="scope"> <el-button v-if="scope.row.status == 0 || scope.row.status == 1" v-hasPermi="['manage:notebook:edit']" link type="primary" @click="handleUpdate(scope.row)" >编辑</el-button > <el-button v-if="scope.row.status == 0" v-hasPermi="['manage:notebook:edit']" link type="primary" @click="fabudata(scope.row)" >发布</el-button > <el-button v-if="scope.row.status == 3" v-hasPermi="['manage:notebook:edit']" link type="primary" @click="fabudata(scope.row)" >撤销发布</el-button > <!-- <el-tooltip content="发布" placement="top">--> <!-- <el-button v-hasPermi="['manage:notebook:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>--> <!-- </el-tooltip>--> <el-button v-if="scope.row.status == 0 || scope.row.status == 1" v-hasPermi="['manage:notebook:remove']" link type="primary" @click="handleDelete(scope.row)" >删除</el-button > </template> </el-table-column> </el-table> <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> </el-card> <!-- 添加或修改笔记对话框 --> <el-dialog v-model="dialog.visible" :title="dialog.title" width="60%" append-to-body> <el-form ref="notebookFormRef" :model="form" :rules="rules" label-width="80px"> <el-form-item label="笔记标题" prop="title"> <el-input v-model="form.title" placeholder="请输入笔记标题" style="width: 300px" /> </el-form-item> <el-form-item label="笔记标签" prop="tagId"> <el-select v-model="tagvalue" placeholder="请选择标签" size="large" style="width: 240px" multiple> <el-option v-for="item in sys_user_tagOptions" :key="item.id" :label="item.title" :value="item.id" /> </el-select> </el-form-item> <el-form-item label="标记地点" prop="location"> <el-select v-model="addressvalue" placeholder="请选择标记地点" size="large" style="width: 240px" multiple> <el-option v-for="item in sys_user_contentOptions" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> <el-form-item label="笔记照片" prop="cover"> <imageUpload :model-value="form.cover" :file-size="20" /> </el-form-item> <el-form-item label="笔记内容" prop="content"> <editor v-model="form.content" :min-height="192" /> </el-form-item> </el-form> <template #footer> <div style="display: flex; justify-content: space-between"> <div> <el-button :loading="buttonLoading" type="primary" @click="yulansave">预 览</el-button> <el-button @click="submitForm('1')">存草稿</el-button> </div> <div> <el-button @click="cancel">取 消</el-button> <el-button :loading="buttonLoading" type="primary" @click="submitForm('0')">提 交</el-button> </div> </div> </template> </el-dialog> <!-- 笔记详情--> <el-dialog v-model="concentdialog.visible" title="笔记详情" width="500px" append-to-body> <note :form="form"></note> </el-dialog> <!-- 评论详情 --> <el-dialog v-model="comment.visible" title="评论详情" width="600px" append-to-body> <div class="commentList"> <commentRows :biz-id="comment.bizId"></commentRows> </div> <template #footer> <div class="dialog-footer noTopPadding"> <el-button @click="cancel">关 闭</el-button> </div> </template> </el-dialog> </div> </template> <script setup name="Notebook" lang="ts"> import { listNotebook, getNotebook, delNotebook, addNotebook, updateNotebook, tagall, contentall } from '@/api/manage/notebook'; import { NotebookVO, NotebookQuery, NotebookForm } from '@/api/manage/notebook/types'; import { hotelall } from '@/api/manage/route'; import { reactive } from 'vue'; import { string } from 'vue-types'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; const notebookList = ref<NotebookVO[]>([]); const buttonLoading = ref(false); const loading = ref(true); const showSearch = ref(true); const ids = ref<Array<string | number>>([]); const single = ref(true); const multiple = ref(true); const total = ref(0); const sys_user_tagOptions = ref([]); //标签库 const sys_user_contentOptions = ref([]); //标签库 const queryFormRef = ref<ElFormInstance>(); const notebookFormRef = ref<ElFormInstance>(); const value = ref(''); const tagvalue = ref(''); const comment = reactive({ visible: false, bizId: null }); //导入父组件传递的值 const props = defineProps({ noteBookTagIds: { type: string, default: () => '' }, autoTableHeight: { type: Number, default: 0 }, parentName: { type: String, default: () => '' }, sys_user_tagOptions: { type: Array, default: () => [] } }); const addressvalue = ref(''); const statusoptions = ref([ { label: '已发布', value: 3 }, { label: '审核中', value: 2 }, { label: '未发布', value: 0 }, { label: '草稿', value: 1 } ]); const dialog = reactive<DialogOption>({ visible: false, title: '' }); const concentdialog = reactive<DialogOption>({ visible: false }); const initFormData: NotebookForm = { id: undefined, userid: undefined, title: undefined, content: undefined, cover: undefined, status: undefined, tagId: undefined }; const data = reactive<PageData<NotebookForm, NotebookQuery>>({ form: { ...initFormData }, queryParams: { pageNum: 1, pageSize: 10, id: undefined, userid: undefined, title: undefined, content: undefined, cover: undefined, status: undefined, tagId: undefined, params: {} }, rules: { id: [{ required: true, message: '笔记ID不能为空', trigger: 'blur' }], title: [{ required: true, message: '笔记标题不能为空', trigger: 'blur' }], // content: [{ required: true, message: '攻略内容不能为空', trigger: 'blur' }], // cover: [{ required: true, message: '笔记照片不能为空', trigger: 'blur' }], status: [{ required: true, message: '帐号状态不能为空', trigger: 'change' }], tagId: [{ required: true, message: '标签不能为空', trigger: 'blur' }], location: [{ required: true, message: '标记地点不能为空', trigger: 'blur' }], content: [{ required: true, message: '笔记内容不能为空', trigger: 'blur' }] } }); const { queryParams, form, rules } = toRefs(data); // 查看评论详情 const handleComment = async (row: any) => { comment.bizId = row.id; comment.visible = true; }; // 监听父组件传递的tagIds,当tagIds发生变化时,重新获取数据 watch( () => props.noteBookTagIds, (newVal, oldVal) => { console.log(newVal); queryParams.value.tagIds = newVal; if (newVal) { //获取数据 nextTick(() => { getTableList(); }); } }, { immediate: true } ); /** * 标签格式化 */ const formatTag = (tagId: string | null) => { let tagString = ''; // for (let i = 0; i < sys_user_tagOptions.value.length; i++) { // const element = sys_user_tagOptions.value[i]; // if (tagId?.includes(element.id)) { // tagString += ',' + element.title; // } // } for (let i = 0; i < sys_user_tagOptions.value.length; i++) { const element = sys_user_tagOptions.value[i]; if (tagId != null) { let filteredArray = tagId.split(',').filter((item) => item == element.id); if (filteredArray.length > 0) { tagString += ',' + element.title; } } } return tagString.substring(1); }; /** * 标记地点格式化 */ const formatlocation = (tagId: string | null) => { let tagString = ''; let arrlist = tagId?.split(',').map(Number); for (let i = 0; i < sys_user_contentOptions.value.length; i++) { const element = sys_user_contentOptions.value[i]; for (let j = 0; j < arrlist.length; j++) { const conten = arrlist[j]; if (conten == element.id) { tagString += ',' + element.name; } } } return tagString.substring(1); }; /** 查询笔记列表 */ const getList = async () => { loading.value = true; const res = await listNotebook(queryParams.value); notebookList.value = res.rows; total.value = res.total; loading.value = false; }; const getTag = async () => { const res = await tagall(); sys_user_tagOptions.value = res; //标签库 }; const getContent = async () => { const res = await contentall({ status: 2 }); const arr = await hotelall({ status: 1 }); sys_user_contentOptions.value = res.concat(arr); //地点 }; /** 取消按钮 */ const cancel = () => { reset(); dialog.visible = false; comment.visible = false; }; /** 表单重置 */ const reset = () => { form.value = { ...initFormData }; notebookFormRef.value?.resetFields(); }; /** 搜索按钮操作 */ const handleQuery = () => { queryParams.value.pageNum = 1; getList(); }; /** 重置按钮操作 */ const resetQuery = () => { queryParams.value.status = ''; queryFormRef.value?.resetFields(); handleQuery(); }; /** 多选框选中数据 */ const handleSelectionChange = (selection: NotebookVO[]) => { ids.value = selection.map((item) => item.id); single.value = selection.length != 1; multiple.value = !selection.length; }; /** 新增按钮操作 */ const handleAdd = () => { reset(); dialog.visible = true; tagvalue.value = ''; addressvalue.value = ''; dialog.title = '添加笔记'; }; /** 修改按钮操作 */ const handleUpdate = async (row?: NotebookVO) => { reset(); const _id = row?.id || ids.value[0]; const res = await getNotebook(_id); Object.assign(form.value, res.data); tagvalue.value = form.value.tagId && form.value.tagId.split(','); addressvalue.value = form.value.tagId && form.value.location.split(','); dialog.visible = true; dialog.title = '修改笔记'; }; //撤销发布 const fabudata = async (row?: NotebookVO) => { const _id = row?.id || ids.value[0]; const _idtitle = row?.title; const res = await getNotebook(_id); Object.assign(form.value, res.data); form.value.status = row.status == 3 ? 0 : 2; const text = row.status == 3 ? '撤销发布' : '确认发布'; const textmessage = row.status == 3 ? '撤销发布成功' : '发布成功'; await proxy?.$modal.confirm('是否' + text + '笔记标题为' + _idtitle + '"的数据项?').finally(() => (loading.value = false)); await updateNotebook(form.value).finally(() => (buttonLoading.value = false)); proxy?.$modal.msgSuccess(`${textmessage}`); await getList(); }; const contenttext = async (row?: NotebookVO) => { const _id = row?.id; const res = await getNotebook(_id); Object.assign(form.value, res.data); concentdialog.visible = true; }; /** 提交按钮 */ const submitForm = async (type) => { form.value.tagId = tagvalue.value.join(','); form.value.location = addressvalue.value.join(','); form.value.cover = ''; form.value.status = Number(type); form.value.content = form.value.content == '<p><br></p>' ? '' : form.value.content; if (type == 1) { buttonLoading.value = true; if (form.value.id) { await updateNotebook(form.value).finally(() => (buttonLoading.value = false)); } else { await addNotebook(form.value).finally(() => (buttonLoading.value = false)); } console.log(form.value.cover); proxy?.$modal.msgSuccess('操作成功'); await getList(); } else { notebookFormRef.value?.validate(async (valid: boolean) => { if (valid) { buttonLoading.value = true; if (form.value.id) { await updateNotebook(form.value).finally(() => (buttonLoading.value = false)); } else { await addNotebook(form.value).finally(() => (buttonLoading.value = false)); } console.log(form.value.cover); proxy?.$modal.msgSuccess('操作成功'); dialog.visible = false; await getList(); } }); } }; /** 删除按钮操作 */ const handleDelete = async (row?: NotebookVO) => { const _ids = row?.id || ids.value; const _idsname = row?.title; await proxy?.$modal.confirm('是否确认删除笔记标题为"' + _idsname + '"的数据项?').finally(() => (loading.value = false)); await delNotebook(_ids); proxy?.$modal.msgSuccess('删除成功'); await getList(); }; // 预览 const yulansave = () => { form.value.tagId = tagvalue.value.join(','); form.value.location = addressvalue.value.join(','); concentdialog.visible = true; }; /** 导出按钮操作 */ const handleExport = () => { proxy?.download( 'manage/notebook/export', { ...queryParams.value }, `notebook_${new Date().getTime()}.xlsx` ); }; // 监听父组件传递的tagIds,当tagIds发生变化时,重新获取数据 watch( () => props.noteBookTagIds, (newVal, oldVal) => { console.log(newVal); queryParams.value.tagIds = newVal; if (newVal) { //获取数据 nextTick(() => { getTableList(); }); } }, { immediate: true } ); onMounted(() => { getList(); getTag(); //标签库 getContent(); }); </script>