Sfoglia il codice sorgente

后台管理页面添加

canghailong 7 mesi fa
parent
commit
fd4a335dec

+ 14 - 10
src/api/forum/forumApi.js

@@ -1,6 +1,6 @@
 import { baseRequest } from '@/utils/request'
 
-const request = (url, ...arg) => baseRequest(`/api/webapp/forum/${url}`, ...arg)
+const request = (url, ...arg) => baseRequest(`/api/webapp/${url}`, ...arg)
 /**
  * 菜单
  *
@@ -10,38 +10,42 @@ const request = (url, ...arg) => baseRequest(`/api/webapp/forum/${url}`, ...arg)
 export default {
 	// 查询帖子列表接口
 	forumList(data) {
-		return request('postinfo/page', data, 'get')
+		return request('forum/postinfo/page', data, 'get')
 	},
 	// 查询分类列表接口
 	forumTypeList(data) {
-		return request('posttype/list', data, 'get')
+		return request('forum/posttype/list', data, 'get')
 	},
 	// 发帖接口 // 编辑帖子接口
 	submitForm(data, edit = false) {
-		return request(`postinfo/${edit ? 'edit' : 'add'}`, data)
+		return request(`forum/postinfo/${edit ? 'edit' : 'add'}`, data)
 	},
 	// 帖子详情接口
 	forumTypeDetail(data) {
-		return request('postinfo/detail', data, 'get')
+		return request('forum/postinfo/detail', data, 'get')
 	},
 	// 点赞接口 // 取消点赞接口
 	postlikeSubmit(data, isLike = 0) {
-		return request(`postlike/${isLike == 0 ? 'add' : 'cancel'}`, data)
+		return request(`forum/postlike/${isLike == 0 ? 'add' : 'cancel'}`, data)
 	},
 	// 回复帖子接口 //编辑回复
 	submitPostreply(data, edit = false) {
-		return request(`postreply/${edit ? 'edit' : 'add'}`, data)
+		return request(`forum/postreply/${edit ? 'edit' : 'add'}`, data)
 	},
 	// 举报帖子接口
 	reportinfoAdd(data) {
-		return request('reportinfo/add', data)
+		return request('forum/reportinfo/add', data)
 	},
 	// 删除自己回复接口
 	postreplyDel(data) {
-		return request('postreply/delete', data)
+		return request('forum/postreply/delete', data)
 	},
 	// 扩展帖子列表,1.查询我发布的 2.查询我回复的 3.查询关于我的 4.查询我点赞的
 	moreList(data) {
-		return request('postinfo/moreList', data, 'get')
+		return request('forum/postinfo/moreList', data, 'get')
+	},
+	// 扩展帖子列表,1.查询我发布的 2.查询我回复的 3.查询关于我的 4.查询我点赞的
+	allUserList(data) {
+		return request('sys/user/allList', data, 'get')
 	}
 }

+ 27 - 0
src/api/forum/forumPostInfoApi.js

@@ -0,0 +1,27 @@
+import { baseRequest } from '@/utils/request'
+
+const request = (url, ...arg) => baseRequest(`/api/forumapp/forum/postinfo/` + url, ...arg)
+
+/**
+ * 帖子信息表Api接口管理器
+ *
+ * @author 金吉龙
+ * @date  2025/07/16 08:46
+ **/
+export default {
+	// 获取帖子信息表分页
+	forumPostInfoPage(data) {
+		return request('page', data, 'get')
+	},
+	// 提交帖子信息表表单 edit为true时为编辑,默认为新增
+	forumPostInfoSubmitForm(data, edit = false) {
+		return request(edit ? 'edit' : 'add', data)
+	},
+	// 删除帖子信息表
+	forumPostInfoDelete(data) {
+		return request('delete', data)
+	},
+	// 获取帖子信息表详情
+	forumPostInfoDetail(data) {
+		return request('detail', data, 'get')
+	}}

+ 27 - 0
src/api/forum/forumPostTypeApi.js

@@ -0,0 +1,27 @@
+import { baseRequest } from '@/utils/request'
+
+const request = (url, ...arg) => baseRequest(`/api/forumapp/forum/posttype/` + url, ...arg)
+
+/**
+ * 帖子分类表Api接口管理器
+ *
+ * @author 金吉龙
+ * @date  2025/07/16 08:43
+ **/
+export default {
+	// 获取帖子分类表分页
+	forumPostTypePage(data) {
+		return request('page', data, 'get')
+	},
+	// 提交帖子分类表表单 edit为true时为编辑,默认为新增
+	forumPostTypeSubmitForm(data, edit = false) {
+		return request(edit ? 'edit' : 'add', data)
+	},
+	// 删除帖子分类表
+	forumPostTypeDelete(data) {
+		return request('delete', data)
+	},
+	// 获取帖子分类表详情
+	forumPostTypeDetail(data) {
+		return request('detail', data, 'get')
+	}}

+ 27 - 0
src/api/forum/forumReportInfoApi.js

@@ -0,0 +1,27 @@
+import { baseRequest } from '@/utils/request'
+
+const request = (url, ...arg) => baseRequest(`/api/forumapp/forum/reportinfo/` + url, ...arg)
+
+/**
+ * 论坛-帖子举报信息表Api接口管理器
+ *
+ * @author 金吉龙
+ * @date  2025/07/17 16:39
+ **/
+export default {
+	// 获取论坛-帖子举报信息表分页
+	forumReportInfoPage(data) {
+		return request('page', data, 'get')
+	},
+	// 提交论坛-帖子举报信息表表单 edit为true时为编辑,默认为新增
+	forumReportInfoSubmitForm(data, edit = false) {
+		return request(edit ? 'edit' : 'add', data)
+	},
+	// 删除论坛-帖子举报信息表
+	forumReportInfoDelete(data) {
+		return request('delete', data)
+	},
+	// 获取论坛-帖子举报信息表详情
+	forumReportInfoDetail(data) {
+		return request('detail', data, 'get')
+	}}

+ 27 - 0
src/api/forum/forumSensitivityApi.js

@@ -0,0 +1,27 @@
+import { baseRequest } from '@/utils/request'
+
+const request = (url, ...arg) => baseRequest(`/api/forumapp/forum/sensitivity/` + url, ...arg)
+
+/**
+ * 论坛-敏感词Api接口管理器
+ *
+ * @author 金吉龙
+ * @date  2025/07/15 11:07
+ **/
+export default {
+	// 获取论坛-敏感词分页
+	forumSensitivityPage(data) {
+		return request('page', data, 'get')
+	},
+	// 提交论坛-敏感词表单 edit为true时为编辑,默认为新增
+	forumSensitivitySubmitForm(data, edit = false) {
+		return request(edit ? 'edit' : 'add', data)
+	},
+	// 删除论坛-敏感词
+	forumSensitivityDelete(data) {
+		return request('delete', data)
+	},
+	// 获取论坛-敏感词详情
+	forumSensitivityDetail(data) {
+		return request('detail', data, 'get')
+	}}

+ 27 - 0
src/api/forum/forumSensitivityRecordApi.js

@@ -0,0 +1,27 @@
+import { baseRequest } from '@/utils/request'
+
+const request = (url, ...arg) => baseRequest(`/api/forumapp/forum/sensitivityrecord/` + url, ...arg)
+
+/**
+ * 敏感词过滤记录Api接口管理器
+ *
+ * @author 金吉龙
+ * @date  2025/07/16 08:41
+ **/
+export default {
+	// 获取敏感词过滤记录分页
+	forumSensitivityRecordPage(data) {
+		return request('page', data, 'get')
+	},
+	// 提交敏感词过滤记录表单 edit为true时为编辑,默认为新增
+	forumSensitivityRecordSubmitForm(data, edit = false) {
+		return request(edit ? 'edit' : 'add', data)
+	},
+	// 删除敏感词过滤记录
+	forumSensitivityRecordDelete(data) {
+		return request('delete', data)
+	},
+	// 获取敏感词过滤记录详情
+	forumSensitivityRecordDetail(data) {
+		return request('detail', data, 'get')
+	}}

+ 28 - 4
src/views/forum/form.vue

@@ -21,7 +21,7 @@
 			<a-row :gutter="16">
 				<a-col :span="12">
 					<a-form-item label="标题:" name="postTitle">
-						<a-input v-model:value="formData.postTitle" placeholder="请输入显示名称" allow-clear />
+						<a-input v-model:value="formData.postTitle" placeholder="请输入标题" allow-clear />
 					</a-form-item>
 				</a-col>
 				<a-col :span="12">
@@ -29,16 +29,29 @@
 						<a-select
 							v-model:value="formData.typeId"
 							show-search
-							placeholder="所有分类"
+							placeholder="请选择分类"
 							style="width: 200px"
 							:options="typeOptions"
 							:filter-option="filterOption"
 						></a-select>
 					</a-form-item>
 				</a-col>
+				<a-col :span="12">
+					<a-form-item label="指向:" name="appointUserArr">
+						<a-select
+							v-model:value="formData.appointUserArr"
+							mode="multiple"
+							show-search
+							placeholder="请选择"
+							style="width: 200px"
+							:options="usertypeOptions"
+							:filter-option="filterOption"
+						></a-select>
+					</a-form-item>
+				</a-col>
 				<a-col :span="24">
 					<a-form-item label="内容:" name="postContent">
-						<xn-editor v-model="formData.postContent" placeholder="请输入" :height="400"></xn-editor>
+						<xn-editor v-model="formData.postContent" placeholder="请输入内容" :height="400"></xn-editor>
 					</a-form-item>
 				</a-col>
 			</a-row>
@@ -72,7 +85,7 @@
 	const submitLoading = ref(false)
 	// 模块ID
 	const moduleId = ref('')
-
+	const usertypeOptions = ref([])
 	const filterOption = (input, option) => {
 		return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
 	}
@@ -90,7 +103,17 @@
 				}
 			})
 		})
+		forumApi.allUserList().then((data)=>{
+			usertypeOptions.value = data.map(r=>{
+				return{
+					label:r.name,
+					value:r.id,
+					...r
+				}
+			})
+		})
 		if (module) {
+			record.appointUserArr = record.appointUser.split(',')
 			formData.value = Object.assign(formData.value, record)
 		}
 	}
@@ -115,6 +138,7 @@
 			.validate()
 			.then(() => {
 				submitLoading.value = true
+				formData.value.appointUser = formData.value.appointUserArr.join(',')
 				forumApi.submitForm(formData.value, formData.value.postId).then(() => {
 					onClose()
 					emit('successful')

+ 1 - 1
src/views/forum/index.vue

@@ -163,7 +163,7 @@
 	}
 	getTypeList()
 
-	const typeValueEx = ref('')
+	const typeValueEx = ref('请选择')
 	const exType = ref(false)
 	const typeOptionsEx = ref([
 		{

+ 103 - 0
src/views/forum/postinfo/form.vue

@@ -0,0 +1,103 @@
+<template>
+    <xn-form-container
+        :title="formData.postId ? '编辑帖子信息表' : '增加帖子信息表'"
+        :width="700"
+        :visible="visible"
+        :destroy-on-close="true"
+        @close="onClose"
+    >
+        <a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
+            <a-form-item label="分类id:" name="typeId">
+                <a-input v-model:value="formData.typeId" placeholder="请输入分类id" allow-clear />
+            </a-form-item>
+            <a-form-item label="用户id:" name="userId">
+                <a-input v-model:value="formData.userId" placeholder="请输入用户id" allow-clear />
+            </a-form-item>
+            <a-form-item label="帖子标题:" name="postTitle">
+                <a-input v-model:value="formData.postTitle" placeholder="请输入帖子标题" allow-clear />
+            </a-form-item>
+            <a-form-item label="帖子内容:" name="postContent">
+                <a-input v-model:value="formData.postContent" placeholder="请输入帖子内容" allow-clear />
+            </a-form-item>
+            <a-form-item label="是否置顶 0普通 1置顶:" name="isTop">
+                <a-input v-model:value="formData.isTop" placeholder="请输入是否置顶 0普通 1置顶" allow-clear />
+            </a-form-item>
+            <a-form-item label="浏览次数:" name="viewCount">
+                <a-input v-model:value="formData.viewCount" placeholder="请输入浏览次数" allow-clear />
+            </a-form-item>
+            <a-form-item label="回复次数:" name="replyCount">
+                <a-input v-model:value="formData.replyCount" placeholder="请输入回复次数" allow-clear />
+            </a-form-item>
+            <a-form-item label="点赞次数:" name="likeCount">
+                <a-input v-model:value="formData.likeCount" placeholder="请输入点赞次数" allow-clear />
+            </a-form-item>
+            <a-form-item label="最后回复用户id:" name="lastReplyUserId">
+                <a-input v-model:value="formData.lastReplyUserId" placeholder="请输入最后回复用户id" allow-clear />
+            </a-form-item>
+            <a-form-item label="最后回复时间:" name="lastReplyTime">
+                <a-date-picker v-model:value="formData.lastReplyTime" value-format="YYYY-MM-DD HH:mm:ss" show-time placeholder="请选择最后回复时间" style="width: 100%" />
+            </a-form-item>
+            <a-form-item label="帖子类型 0普通帖子 1技术支持 2内容纠错:" name="postType">
+                <a-input v-model:value="formData.postType" placeholder="请输入帖子类型 0普通帖子 1技术支持 2内容纠错" allow-clear />
+            </a-form-item>
+            <a-form-item label="定向用户:" name="appointUser">
+                <a-input v-model:value="formData.appointUser" placeholder="请输入定向用户" allow-clear />
+            </a-form-item>
+        </a-form>
+        <template #footer>
+            <a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
+            <a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
+        </template>
+    </xn-form-container>
+</template>
+
+<script setup name="forumPostInfoForm">
+    import { cloneDeep } from 'lodash-es'
+    import { required } from '@/utils/formRules'
+    import forumPostInfoApi from '@/api/forum/forumPostInfoApi'
+    // 抽屉状态
+    const visible = ref(false)
+    const emit = defineEmits({ successful: null })
+    const formRef = ref()
+    // 表单数据
+    const formData = ref({})
+    const submitLoading = ref(false)
+
+    // 打开抽屉
+    const onOpen = (record) => {
+        visible.value = true
+        if (record) {
+            let recordData = cloneDeep(record)
+            formData.value = Object.assign({}, recordData)
+        }
+    }
+    // 关闭抽屉
+    const onClose = () => {
+        formRef.value.resetFields()
+        formData.value = {}
+        visible.value = false
+    }
+    // 默认要校验的
+    const formRules = {
+    }
+    // 验证并提交数据
+    const onSubmit = () => {
+        formRef.value.validate().then(() => {
+            submitLoading.value = true
+            const formDataParam = cloneDeep(formData.value)
+            forumPostInfoApi
+                .forumPostInfoSubmitForm(formDataParam, formDataParam.postId)
+                .then(() => {
+                    onClose()
+                    emit('successful')
+                })
+                .finally(() => {
+                    submitLoading.value = false
+                })
+        })
+    }
+    // 抛出函数
+    defineExpose({
+        onOpen
+    })
+</script>

+ 150 - 0
src/views/forum/postinfo/index.vue

@@ -0,0 +1,150 @@
+<template>
+    <a-card :bordered="false">
+        <s-table
+            ref="table"
+            :columns="columns"
+            :data="loadData"
+            :alert="options.alert.show"
+            bordered
+            :row-key="(record) => record.postId"
+            :tool-config="toolConfig"
+            :row-selection="options.rowSelection"
+        >
+            <template #operator class="table-operator">
+                <a-space>
+                    <a-button type="primary" @click="formRef.onOpen()" v-if="hasPerm('forumPostInfoAdd')">
+                        <template #icon><plus-outlined /></template>
+                        新增
+                    </a-button>
+                    <xn-batch-delete
+                        v-if="hasPerm('forumPostInfoBatchDelete')"
+                        :selectedRowKeys="selectedRowKeys"
+                        @batchDelete="deleteBatchForumPostInfo"
+                    />
+                </a-space>
+            </template>
+            <template #bodyCell="{ column, record }">
+                <template v-if="column.dataIndex === 'action'">
+                    <a-space>
+                        <a @click="formRef.onOpen(record)" v-if="hasPerm('forumPostInfoEdit')">编辑</a>
+                        <a-divider type="vertical" v-if="hasPerm(['forumPostInfoEdit', 'forumPostInfoDelete'], 'and')" />
+                        <a-popconfirm title="确定要删除吗?" @confirm="deleteForumPostInfo(record)">
+                            <a-button type="link" danger size="small" v-if="hasPerm('forumPostInfoDelete')">删除</a-button>
+                        </a-popconfirm>
+                    </a-space>
+                </template>
+            </template>
+        </s-table>
+    </a-card>
+    <Form ref="formRef" @successful="table.refresh(true)" />
+</template>
+
+<script setup name="postinfo">
+    import Form from './form.vue'
+    import forumPostInfoApi from '@/api/forum/forumPostInfoApi'
+    const table = ref()
+    const formRef = ref()
+    const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
+    const columns = [
+        {
+            title: '分类id',
+            dataIndex: 'typeId'
+        },
+        {
+            title: '用户id',
+            dataIndex: 'userId'
+        },
+        {
+            title: '帖子标题',
+            dataIndex: 'postTitle'
+        },
+        {
+            title: '帖子内容',
+            dataIndex: 'postContent'
+        },
+        {
+            title: '是否置顶 0普通 1置顶',
+            dataIndex: 'isTop'
+        },
+        {
+            title: '浏览次数',
+            dataIndex: 'viewCount'
+        },
+        {
+            title: '回复次数',
+            dataIndex: 'replyCount'
+        },
+        {
+            title: '点赞次数',
+            dataIndex: 'likeCount'
+        },
+        {
+            title: '最后回复用户id',
+            dataIndex: 'lastReplyUserId'
+        },
+        {
+            title: '最后回复时间',
+            dataIndex: 'lastReplyTime'
+        },
+        {
+            title: '帖子类型 0普通帖子 1技术支持 2内容纠错',
+            dataIndex: 'postType'
+        },
+        {
+            title: '定向用户',
+            dataIndex: 'appointUser'
+        },
+    ]
+    // 操作栏通过权限判断是否显示
+    if (hasPerm(['forumPostInfoEdit', 'forumPostInfoDelete'])) {
+        columns.push({
+            title: '操作',
+            dataIndex: 'action',
+            align: 'center',
+            width: '150px'
+        })
+    }
+    const selectedRowKeys = ref([])
+    // 列表选择配置
+    const options = {
+        // columns数字类型字段加入 needTotal: true 可以勾选自动算账
+        alert: {
+            show: true,
+            clear: () => {
+                selectedRowKeys.value = ref([])
+            }
+        },
+        rowSelection: {
+            onChange: (selectedRowKey, selectedRows) => {
+                selectedRowKeys.value = selectedRowKey
+            }
+        }
+    }
+    const loadData = (parameter) => {
+        return forumPostInfoApi.forumPostInfoPage(parameter).then((data) => {
+            return data
+        })
+    }
+    // 重置
+    const reset = () => {
+        searchFormRef.value.resetFields()
+        table.value.refresh(true)
+    }
+    // 删除
+    const deleteForumPostInfo = (record) => {
+        let params = [
+            {
+                postId: record.postId
+            }
+        ]
+        forumPostInfoApi.forumPostInfoDelete(params).then(() => {
+            table.value.refresh(true)
+        })
+    }
+    // 批量删除
+    const deleteBatchForumPostInfo = (params) => {
+        forumPostInfoApi.forumPostInfoDelete(params).then(() => {
+            table.value.clearRefreshSelected()
+        })
+    }
+</script>

+ 73 - 0
src/views/forum/posttype/form.vue

@@ -0,0 +1,73 @@
+<template>
+    <xn-form-container
+        :title="formData.typeId ? '编辑帖子分类表' : '增加帖子分类表'"
+        :width="700"
+        :visible="visible"
+        :destroy-on-close="true"
+        @close="onClose"
+    >
+        <a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
+            <a-form-item label="分类名称:" name="typeName">
+                <a-input v-model:value="formData.typeName" placeholder="请输入分类名称" allow-clear />
+            </a-form-item>
+            <a-form-item label="分类描述:" name="typeDesc">
+                <a-input v-model:value="formData.typeDesc" placeholder="请输入分类描述" allow-clear />
+            </a-form-item>
+        </a-form>
+        <template #footer>
+            <a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
+            <a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
+        </template>
+    </xn-form-container>
+</template>
+
+<script setup name="forumPostTypeForm">
+    import { cloneDeep } from 'lodash-es'
+    import { required } from '@/utils/formRules'
+    import forumPostTypeApi from '@/api/forum/forumPostTypeApi'
+    // 抽屉状态
+    const visible = ref(false)
+    const emit = defineEmits({ successful: null })
+    const formRef = ref()
+    // 表单数据
+    const formData = ref({})
+    const submitLoading = ref(false)
+
+    // 打开抽屉
+    const onOpen = (record) => {
+        visible.value = true
+        if (record) {
+            let recordData = cloneDeep(record)
+            formData.value = Object.assign({}, recordData)
+        }
+    }
+    // 关闭抽屉
+    const onClose = () => {
+        formRef.value.resetFields()
+        formData.value = {}
+        visible.value = false
+    }
+    // 默认要校验的
+    const formRules = {
+    }
+    // 验证并提交数据
+    const onSubmit = () => {
+        formRef.value.validate().then(() => {
+            submitLoading.value = true
+            const formDataParam = cloneDeep(formData.value)
+            forumPostTypeApi
+                .forumPostTypeSubmitForm(formDataParam, formDataParam.typeId)
+                .then(() => {
+                    onClose()
+                    emit('successful')
+                })
+                .finally(() => {
+                    submitLoading.value = false
+                })
+        })
+    }
+    // 抛出函数
+    defineExpose({
+        onOpen
+    })
+</script>

+ 110 - 0
src/views/forum/posttype/index.vue

@@ -0,0 +1,110 @@
+<template>
+    <a-card :bordered="false">
+        <s-table
+            ref="table"
+            :columns="columns"
+            :data="loadData"
+            :alert="options.alert.show"
+            bordered
+            :row-key="(record) => record.typeId"
+            :tool-config="toolConfig"
+            :row-selection="options.rowSelection"
+        >
+            <template #operator class="table-operator">
+                <a-space>
+                    <a-button type="primary" @click="formRef.onOpen()" v-if="hasPerm('forumPostTypeAdd')">
+                        <template #icon><plus-outlined /></template>
+                        新增
+                    </a-button>
+                    <xn-batch-delete
+                        v-if="hasPerm('forumPostTypeBatchDelete')"
+                        :selectedRowKeys="selectedRowKeys"
+                        @batchDelete="deleteBatchForumPostType"
+                    />
+                </a-space>
+            </template>
+            <template #bodyCell="{ column, record }">
+                <template v-if="column.dataIndex === 'action'">
+                    <a-space>
+                        <a @click="formRef.onOpen(record)" v-if="hasPerm('forumPostTypeEdit')">编辑</a>
+                        <a-divider type="vertical" v-if="hasPerm(['forumPostTypeEdit', 'forumPostTypeDelete'], 'and')" />
+                        <a-popconfirm title="确定要删除吗?" @confirm="deleteForumPostType(record)">
+                            <a-button type="link" danger size="small" v-if="hasPerm('forumPostTypeDelete')">删除</a-button>
+                        </a-popconfirm>
+                    </a-space>
+                </template>
+            </template>
+        </s-table>
+    </a-card>
+    <Form ref="formRef" @successful="table.refresh(true)" />
+</template>
+
+<script setup name="posttype">
+    import Form from './form.vue'
+    import forumPostTypeApi from '@/api/forum/forumPostTypeApi'
+    const table = ref()
+    const formRef = ref()
+    const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
+    const columns = [
+        {
+            title: '分类名称',
+            dataIndex: 'typeName'
+        },
+        {
+            title: '分类描述',
+            dataIndex: 'typeDesc'
+        },
+    ]
+    // 操作栏通过权限判断是否显示
+    if (hasPerm(['forumPostTypeEdit', 'forumPostTypeDelete'])) {
+        columns.push({
+            title: '操作',
+            dataIndex: 'action',
+            align: 'center',
+            width: '150px'
+        })
+    }
+    const selectedRowKeys = ref([])
+    // 列表选择配置
+    const options = {
+        // columns数字类型字段加入 needTotal: true 可以勾选自动算账
+        alert: {
+            show: true,
+            clear: () => {
+                selectedRowKeys.value = ref([])
+            }
+        },
+        rowSelection: {
+            onChange: (selectedRowKey, selectedRows) => {
+                selectedRowKeys.value = selectedRowKey
+            }
+        }
+    }
+    const loadData = (parameter) => {
+        return forumPostTypeApi.forumPostTypePage(parameter).then((data) => {
+            return data
+        })
+    }
+    // 重置
+    const reset = () => {
+        searchFormRef.value.resetFields()
+        table.value.refresh(true)
+    }
+    // 删除
+    const deleteForumPostType = (record) => {
+        let params = [
+            {
+                typeId: record.typeId
+            }
+        ]
+        forumPostTypeApi.forumPostTypeDelete(params).then(() => {
+            table.value.refresh(true)
+        })
+    }
+    // 批量删除
+    const deleteBatchForumPostType = (params) => {
+        forumPostTypeApi.forumPostTypeDelete(params).then(() => {
+            table.value.clearRefreshSelected()
+        })
+    }
+</script>

+ 85 - 0
src/views/forum/reportinfo/form.vue

@@ -0,0 +1,85 @@
+<template>
+    <xn-form-container
+        :title="formData.reportId ? '编辑论坛-帖子举报信息表' : '增加论坛-帖子举报信息表'"
+        :width="700"
+        :visible="visible"
+        :destroy-on-close="true"
+        @close="onClose"
+    >
+        <a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
+            <a-form-item label="帖子主键id:" name="postId">
+                <a-input v-model:value="formData.postId" placeholder="请输入帖子主键id" allow-clear />
+            </a-form-item>
+            <a-form-item label="举报人用户id:" name="userId">
+                <a-input v-model:value="formData.userId" placeholder="请输入举报人用户id" allow-clear />
+            </a-form-item>
+            <a-form-item label="举报原因类型 0垃圾广告 1色情内容 2人身攻击 3政治敏感 4其他:" name="reportReasonType">
+                <a-input v-model:value="formData.reportReasonType" placeholder="请输入举报原因类型 0垃圾广告 1色情内容 2人身攻击 3政治敏感 4其他" allow-clear />
+            </a-form-item>
+            <a-form-item label="举报信息描述:" name="reportDetail">
+                <a-input v-model:value="formData.reportDetail" placeholder="请输入举报信息描述" allow-clear />
+            </a-form-item>
+            <a-form-item label="证据图片:" name="evidenceScreenshot">
+                <a-input v-model:value="formData.evidenceScreenshot" placeholder="请输入证据图片" allow-clear />
+            </a-form-item>
+            <a-form-item label="举报处理状态 0待处理 1已关闭帖子 2已驳回:" name="reportStatus">
+                <a-input v-model:value="formData.reportStatus" placeholder="请输入举报处理状态 0待处理 1已关闭帖子 2已驳回" allow-clear />
+            </a-form-item>
+        </a-form>
+        <template #footer>
+            <a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
+            <a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
+        </template>
+    </xn-form-container>
+</template>
+
+<script setup name="forumReportInfoForm">
+    import { cloneDeep } from 'lodash-es'
+    import { required } from '@/utils/formRules'
+    import forumReportInfoApi from '@/api/forum/forumReportInfoApi'
+    // 抽屉状态
+    const visible = ref(false)
+    const emit = defineEmits({ successful: null })
+    const formRef = ref()
+    // 表单数据
+    const formData = ref({})
+    const submitLoading = ref(false)
+
+    // 打开抽屉
+    const onOpen = (record) => {
+        visible.value = true
+        if (record) {
+            let recordData = cloneDeep(record)
+            formData.value = Object.assign({}, recordData)
+        }
+    }
+    // 关闭抽屉
+    const onClose = () => {
+        formRef.value.resetFields()
+        formData.value = {}
+        visible.value = false
+    }
+    // 默认要校验的
+    const formRules = {
+    }
+    // 验证并提交数据
+    const onSubmit = () => {
+        formRef.value.validate().then(() => {
+            submitLoading.value = true
+            const formDataParam = cloneDeep(formData.value)
+            forumReportInfoApi
+                .forumReportInfoSubmitForm(formDataParam, formDataParam.reportId)
+                .then(() => {
+                    onClose()
+                    emit('successful')
+                })
+                .finally(() => {
+                    submitLoading.value = false
+                })
+        })
+    }
+    // 抛出函数
+    defineExpose({
+        onOpen
+    })
+</script>

+ 126 - 0
src/views/forum/reportinfo/index.vue

@@ -0,0 +1,126 @@
+<template>
+    <a-card :bordered="false">
+        <s-table
+            ref="table"
+            :columns="columns"
+            :data="loadData"
+            :alert="options.alert.show"
+            bordered
+            :row-key="(record) => record.reportId"
+            :tool-config="toolConfig"
+            :row-selection="options.rowSelection"
+        >
+            <template #operator class="table-operator">
+                <a-space>
+                    <a-button type="primary" @click="formRef.onOpen()" v-if="hasPerm('forumReportInfoAdd')">
+                        <template #icon><plus-outlined /></template>
+                        新增
+                    </a-button>
+                    <xn-batch-delete
+                        v-if="hasPerm('forumReportInfoBatchDelete')"
+                        :selectedRowKeys="selectedRowKeys"
+                        @batchDelete="deleteBatchForumReportInfo"
+                    />
+                </a-space>
+            </template>
+            <template #bodyCell="{ column, record }">
+                <template v-if="column.dataIndex === 'action'">
+                    <a-space>
+                        <a @click="formRef.onOpen(record)" v-if="hasPerm('forumReportInfoEdit')">编辑</a>
+                        <a-divider type="vertical" v-if="hasPerm(['forumReportInfoEdit', 'forumReportInfoDelete'], 'and')" />
+                        <a-popconfirm title="确定要删除吗?" @confirm="deleteForumReportInfo(record)">
+                            <a-button type="link" danger size="small" v-if="hasPerm('forumReportInfoDelete')">删除</a-button>
+                        </a-popconfirm>
+                    </a-space>
+                </template>
+            </template>
+        </s-table>
+    </a-card>
+    <Form ref="formRef" @successful="table.refresh(true)" />
+</template>
+
+<script setup name="reportinfo">
+    import Form from './form.vue'
+    import forumReportInfoApi from '@/api/forum/forumReportInfoApi'
+    const table = ref()
+    const formRef = ref()
+    const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
+    const columns = [
+        {
+            title: '帖子主键id',
+            dataIndex: 'postId'
+        },
+        {
+            title: '举报人用户id',
+            dataIndex: 'userId'
+        },
+        {
+            title: '举报原因类型 0垃圾广告 1色情内容 2人身攻击 3政治敏感 4其他',
+            dataIndex: 'reportReasonType'
+        },
+        {
+            title: '举报信息描述',
+            dataIndex: 'reportDetail'
+        },
+        {
+            title: '证据图片',
+            dataIndex: 'evidenceScreenshot'
+        },
+        {
+            title: '举报处理状态 0待处理 1已关闭帖子 2已驳回',
+            dataIndex: 'reportStatus'
+        },
+    ]
+    // 操作栏通过权限判断是否显示
+    if (hasPerm(['forumReportInfoEdit', 'forumReportInfoDelete'])) {
+        columns.push({
+            title: '操作',
+            dataIndex: 'action',
+            align: 'center',
+            width: '150px'
+        })
+    }
+    const selectedRowKeys = ref([])
+    // 列表选择配置
+    const options = {
+        // columns数字类型字段加入 needTotal: true 可以勾选自动算账
+        alert: {
+            show: true,
+            clear: () => {
+                selectedRowKeys.value = ref([])
+            }
+        },
+        rowSelection: {
+            onChange: (selectedRowKey, selectedRows) => {
+                selectedRowKeys.value = selectedRowKey
+            }
+        }
+    }
+    const loadData = (parameter) => {
+        return forumReportInfoApi.forumReportInfoPage(parameter).then((data) => {
+            return data
+        })
+    }
+    // 重置
+    const reset = () => {
+        searchFormRef.value.resetFields()
+        table.value.refresh(true)
+    }
+    // 删除
+    const deleteForumReportInfo = (record) => {
+        let params = [
+            {
+                reportId: record.reportId
+            }
+        ]
+        forumReportInfoApi.forumReportInfoDelete(params).then(() => {
+            table.value.refresh(true)
+        })
+    }
+    // 批量删除
+    const deleteBatchForumReportInfo = (params) => {
+        forumReportInfoApi.forumReportInfoDelete(params).then(() => {
+            table.value.clearRefreshSelected()
+        })
+    }
+</script>

+ 70 - 0
src/views/forum/sensitivity/form.vue

@@ -0,0 +1,70 @@
+<template>
+    <xn-form-container
+        :title="formData.sensitivityId ? '编辑论坛-敏感词' : '增加论坛-敏感词'"
+        :width="700"
+        :visible="visible"
+        :destroy-on-close="true"
+        @close="onClose"
+    >
+        <a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
+            <a-form-item label="敏感词:" name="sensitivityWord">
+                <a-input v-model:value="formData.sensitivityWord" placeholder="请输入敏感词" allow-clear />
+            </a-form-item>
+        </a-form>
+        <template #footer>
+            <a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
+            <a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
+        </template>
+    </xn-form-container>
+</template>
+
+<script setup name="forumSensitivityForm">
+    import { cloneDeep } from 'lodash-es'
+    import { required } from '@/utils/formRules'
+    import forumSensitivityApi from '@/api/forum/forumSensitivityApi'
+    // 抽屉状态
+    const visible = ref(false)
+    const emit = defineEmits({ successful: null })
+    const formRef = ref()
+    // 表单数据
+    const formData = ref({})
+    const submitLoading = ref(false)
+
+    // 打开抽屉
+    const onOpen = (record) => {
+        visible.value = true
+        if (record) {
+            let recordData = cloneDeep(record)
+            formData.value = Object.assign({}, recordData)
+        }
+    }
+    // 关闭抽屉
+    const onClose = () => {
+        formRef.value.resetFields()
+        formData.value = {}
+        visible.value = false
+    }
+    // 默认要校验的
+    const formRules = {
+    }
+    // 验证并提交数据
+    const onSubmit = () => {
+        formRef.value.validate().then(() => {
+            submitLoading.value = true
+            const formDataParam = cloneDeep(formData.value)
+            forumSensitivityApi
+                .forumSensitivitySubmitForm(formDataParam, formDataParam.sensitivityId)
+                .then(() => {
+                    onClose()
+                    emit('successful')
+                })
+                .finally(() => {
+                    submitLoading.value = false
+                })
+        })
+    }
+    // 抛出函数
+    defineExpose({
+        onOpen
+    })
+</script>

+ 122 - 0
src/views/forum/sensitivity/index.vue

@@ -0,0 +1,122 @@
+<template>
+    <a-card :bordered="false">
+        <a-form ref="searchFormRef" name="advanced_search" :model="searchFormState" class="ant-advanced-search-form">
+            <a-row :gutter="24">
+                <a-col :span="6">
+                    <a-form-item label="敏感词" name="sensitivityWord">
+                        <a-input v-model:value="searchFormState.sensitivityWord" placeholder="请输入敏感词" />
+                    </a-form-item>
+                </a-col>
+                <a-col :span="6">
+                    <a-button type="primary" @click="table.refresh(true)">查询</a-button>
+                    <a-button style="margin: 0 8px" @click="reset">重置</a-button>
+                </a-col>
+            </a-row>
+        </a-form>
+        <s-table
+            ref="table"
+            :columns="columns"
+            :data="loadData"
+            :alert="options.alert.show"
+            bordered
+            :row-key="(record) => record.sensitivityId"
+            :tool-config="toolConfig"
+            :row-selection="options.rowSelection"
+        >
+            <template #operator class="table-operator">
+                <a-space>
+                    <a-button type="primary" @click="formRef.onOpen()" v-if="hasPerm('forumSensitivityAdd')">
+                        <template #icon><plus-outlined /></template>
+                        新增
+                    </a-button>
+                    <xn-batch-delete
+                        v-if="hasPerm('forumSensitivityBatchDelete')"
+                        :selectedRowKeys="selectedRowKeys"
+                        @batchDelete="deleteBatchForumSensitivity"
+                    />
+                </a-space>
+            </template>
+            <template #bodyCell="{ column, record }">
+                <template v-if="column.dataIndex === 'action'">
+                    <a-space>
+                        <a @click="formRef.onOpen(record)" v-if="hasPerm('forumSensitivityEdit')">编辑</a>
+                        <a-divider type="vertical" v-if="hasPerm(['forumSensitivityEdit', 'forumSensitivityDelete'], 'and')" />
+                        <a-popconfirm title="确定要删除吗?" @confirm="deleteForumSensitivity(record)">
+                            <a-button type="link" danger size="small" v-if="hasPerm('forumSensitivityDelete')">删除</a-button>
+                        </a-popconfirm>
+                    </a-space>
+                </template>
+            </template>
+        </s-table>
+    </a-card>
+    <Form ref="formRef" @successful="table.refresh(true)" />
+</template>
+
+<script setup name="sensitivity">
+    import Form from './form.vue'
+    import forumSensitivityApi from '@/api/forum/forumSensitivityApi'
+    let searchFormState = reactive({})
+    const searchFormRef = ref()
+    const table = ref()
+    const formRef = ref()
+    const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
+    const columns = [
+        {
+            title: '敏感词',
+            dataIndex: 'sensitivityWord'
+        },
+    ]
+    // 操作栏通过权限判断是否显示
+    if (hasPerm(['forumSensitivityEdit', 'forumSensitivityDelete'])) {
+        columns.push({
+            title: '操作',
+            dataIndex: 'action',
+            align: 'center',
+            width: '150px'
+        })
+    }
+    const selectedRowKeys = ref([])
+    // 列表选择配置
+    const options = {
+        // columns数字类型字段加入 needTotal: true 可以勾选自动算账
+        alert: {
+            show: true,
+            clear: () => {
+                selectedRowKeys.value = ref([])
+            }
+        },
+        rowSelection: {
+            onChange: (selectedRowKey, selectedRows) => {
+                selectedRowKeys.value = selectedRowKey
+            }
+        }
+    }
+    const loadData = (parameter) => {
+        const searchFormParam = JSON.parse(JSON.stringify(searchFormState))
+        return forumSensitivityApi.forumSensitivityPage(Object.assign(parameter, searchFormParam)).then((data) => {
+            return data
+        })
+    }
+    // 重置
+    const reset = () => {
+        searchFormRef.value.resetFields()
+        table.value.refresh(true)
+    }
+    // 删除
+    const deleteForumSensitivity = (record) => {
+        let params = [
+            {
+                sensitivityId: record.sensitivityId
+            }
+        ]
+        forumSensitivityApi.forumSensitivityDelete(params).then(() => {
+            table.value.refresh(true)
+        })
+    }
+    // 批量删除
+    const deleteBatchForumSensitivity = (params) => {
+        forumSensitivityApi.forumSensitivityDelete(params).then(() => {
+            table.value.clearRefreshSelected()
+        })
+    }
+</script>

+ 79 - 0
src/views/forum/sensitivityrecord/form.vue

@@ -0,0 +1,79 @@
+<template>
+    <xn-form-container
+        :title="formData.recordId ? '编辑敏感词过滤记录' : '增加敏感词过滤记录'"
+        :width="700"
+        :visible="visible"
+        :destroy-on-close="true"
+        @close="onClose"
+    >
+        <a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
+            <a-form-item label="过滤词语:" name="sensitivityWord">
+                <a-input v-model:value="formData.sensitivityWord" placeholder="请输入过滤词语" allow-clear />
+            </a-form-item>
+            <a-form-item label="帖子id:" name="postId">
+                <a-input v-model:value="formData.postId" placeholder="请输入帖子id" allow-clear />
+            </a-form-item>
+            <a-form-item label="过滤类型 0发帖 1回复:" name="recordType">
+                <a-input v-model:value="formData.recordType" placeholder="请输入过滤类型 0发帖 1回复" allow-clear />
+            </a-form-item>
+            <a-form-item label="用户id:" name="userId">
+                <a-input v-model:value="formData.userId" placeholder="请输入用户id" allow-clear />
+            </a-form-item>
+        </a-form>
+        <template #footer>
+            <a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
+            <a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
+        </template>
+    </xn-form-container>
+</template>
+
+<script setup name="forumSensitivityRecordForm">
+    import { cloneDeep } from 'lodash-es'
+    import { required } from '@/utils/formRules'
+    import forumSensitivityRecordApi from '@/api/forum/forumSensitivityRecordApi'
+    // 抽屉状态
+    const visible = ref(false)
+    const emit = defineEmits({ successful: null })
+    const formRef = ref()
+    // 表单数据
+    const formData = ref({})
+    const submitLoading = ref(false)
+
+    // 打开抽屉
+    const onOpen = (record) => {
+        visible.value = true
+        if (record) {
+            let recordData = cloneDeep(record)
+            formData.value = Object.assign({}, recordData)
+        }
+    }
+    // 关闭抽屉
+    const onClose = () => {
+        formRef.value.resetFields()
+        formData.value = {}
+        visible.value = false
+    }
+    // 默认要校验的
+    const formRules = {
+    }
+    // 验证并提交数据
+    const onSubmit = () => {
+        formRef.value.validate().then(() => {
+            submitLoading.value = true
+            const formDataParam = cloneDeep(formData.value)
+            forumSensitivityRecordApi
+                .forumSensitivityRecordSubmitForm(formDataParam, formDataParam.recordId)
+                .then(() => {
+                    onClose()
+                    emit('successful')
+                })
+                .finally(() => {
+                    submitLoading.value = false
+                })
+        })
+    }
+    // 抛出函数
+    defineExpose({
+        onOpen
+    })
+</script>

+ 118 - 0
src/views/forum/sensitivityrecord/index.vue

@@ -0,0 +1,118 @@
+<template>
+    <a-card :bordered="false">
+        <s-table
+            ref="table"
+            :columns="columns"
+            :data="loadData"
+            :alert="options.alert.show"
+            bordered
+            :row-key="(record) => record.recordId"
+            :tool-config="toolConfig"
+            :row-selection="options.rowSelection"
+        >
+            <template #operator class="table-operator">
+                <a-space>
+                    <a-button type="primary" @click="formRef.onOpen()" v-if="hasPerm('forumSensitivityRecordAdd')">
+                        <template #icon><plus-outlined /></template>
+                        新增
+                    </a-button>
+                    <xn-batch-delete
+                        v-if="hasPerm('forumSensitivityRecordBatchDelete')"
+                        :selectedRowKeys="selectedRowKeys"
+                        @batchDelete="deleteBatchForumSensitivityRecord"
+                    />
+                </a-space>
+            </template>
+            <template #bodyCell="{ column, record }">
+                <template v-if="column.dataIndex === 'action'">
+                    <a-space>
+                        <a @click="formRef.onOpen(record)" v-if="hasPerm('forumSensitivityRecordEdit')">编辑</a>
+                        <a-divider type="vertical" v-if="hasPerm(['forumSensitivityRecordEdit', 'forumSensitivityRecordDelete'], 'and')" />
+                        <a-popconfirm title="确定要删除吗?" @confirm="deleteForumSensitivityRecord(record)">
+                            <a-button type="link" danger size="small" v-if="hasPerm('forumSensitivityRecordDelete')">删除</a-button>
+                        </a-popconfirm>
+                    </a-space>
+                </template>
+            </template>
+        </s-table>
+    </a-card>
+    <Form ref="formRef" @successful="table.refresh(true)" />
+</template>
+
+<script setup name="sensitivityrecord">
+    import Form from './form.vue'
+    import forumSensitivityRecordApi from '@/api/forum/forumSensitivityRecordApi'
+    const table = ref()
+    const formRef = ref()
+    const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
+    const columns = [
+        {
+            title: '过滤词语',
+            dataIndex: 'sensitivityWord'
+        },
+        {
+            title: '帖子id',
+            dataIndex: 'postId'
+        },
+        {
+            title: '过滤类型 0发帖 1回复',
+            dataIndex: 'recordType'
+        },
+        {
+            title: '用户id',
+            dataIndex: 'userId'
+        },
+    ]
+    // 操作栏通过权限判断是否显示
+    if (hasPerm(['forumSensitivityRecordEdit', 'forumSensitivityRecordDelete'])) {
+        columns.push({
+            title: '操作',
+            dataIndex: 'action',
+            align: 'center',
+            width: '150px'
+        })
+    }
+    const selectedRowKeys = ref([])
+    // 列表选择配置
+    const options = {
+        // columns数字类型字段加入 needTotal: true 可以勾选自动算账
+        alert: {
+            show: true,
+            clear: () => {
+                selectedRowKeys.value = ref([])
+            }
+        },
+        rowSelection: {
+            onChange: (selectedRowKey, selectedRows) => {
+                selectedRowKeys.value = selectedRowKey
+            }
+        }
+    }
+    const loadData = (parameter) => {
+        return forumSensitivityRecordApi.forumSensitivityRecordPage(parameter).then((data) => {
+            return data
+        })
+    }
+    // 重置
+    const reset = () => {
+        searchFormRef.value.resetFields()
+        table.value.refresh(true)
+    }
+    // 删除
+    const deleteForumSensitivityRecord = (record) => {
+        let params = [
+            {
+                recordId: record.recordId
+            }
+        ]
+        forumSensitivityRecordApi.forumSensitivityRecordDelete(params).then(() => {
+            table.value.refresh(true)
+        })
+    }
+    // 批量删除
+    const deleteBatchForumSensitivityRecord = (params) => {
+        forumSensitivityRecordApi.forumSensitivityRecordDelete(params).then(() => {
+            table.value.clearRefreshSelected()
+        })
+    }
+</script>