From 16567c73dda0cefb9b1176bf29dff2f23871413e Mon Sep 17 00:00:00 2001
From: linwe <872216996@qq.com>
Date: Thu, 23 Nov 2023 17:54:35 +0800
Subject: [PATCH] 议题议事+公益报名

---
 src/views/article/publicSignUp.vue     |  211 +++++
 src/views/article/article.vue          |  527 ++++++++++---
 src/views/article/discussionManage.vue |  321 ++++++++
 src/api/discuss/topics.js              |   50 +
 src/views/discuss/topics.vue           |  188 +++++
 src/api/discuss/publicDiscuss.js       |   50 +
 src/option/discuss/userPublicEnroll.js |   14 
 src/api/discuss/userPublicEnroll.js    |   50 +
 src/option/discuss/userTopics.js       |   14 
 src/views/discuss/userPublicEnroll.vue |  178 ++++
 src/option/discuss/publicDiscuss.js    |   36 
 src/views/discuss/userTopics.vue       |  188 +++++
 src/api/discuss/userTopics.js          |   50 +
 src/option/discuss/topics.js           |   14 
 src/views/discuss/publicDiscuss.vue    |  270 +++++++
 15 files changed, 2,029 insertions(+), 132 deletions(-)

diff --git a/src/api/discuss/publicDiscuss.js b/src/api/discuss/publicDiscuss.js
new file mode 100644
index 0000000..f3f03f8
--- /dev/null
+++ b/src/api/discuss/publicDiscuss.js
@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getListPd = (current, size, params) => {
+  return request({
+    url: '/api/public_discuss/publicDiscuss/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetailPd = (id) => {
+  return request({
+    url: '/api/public_discuss/publicDiscuss/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const removePd = (ids) => {
+  return request({
+    url: '/api/public_discuss/publicDiscuss/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const addPd = (row) => {
+  return request({
+    url: '/api/public_discuss/publicDiscuss/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const updatePd = (row) => {
+  return request({
+    url: '/api/public_discuss/publicDiscuss/submit',
+    method: 'post',
+    data: row
+  })
+}
+
diff --git a/src/api/discuss/topics.js b/src/api/discuss/topics.js
new file mode 100644
index 0000000..9e2d146
--- /dev/null
+++ b/src/api/discuss/topics.js
@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/blade-topics/topics/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/blade-topics/topics/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/blade-topics/topics/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/blade-topics/topics/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/blade-topics/topics/submit',
+    method: 'post',
+    data: row
+  })
+}
+
diff --git a/src/api/discuss/userPublicEnroll.js b/src/api/discuss/userPublicEnroll.js
new file mode 100644
index 0000000..9839076
--- /dev/null
+++ b/src/api/discuss/userPublicEnroll.js
@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/blade-userPublicEnroll/userPublicEnroll/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/blade-userPublicEnroll/userPublicEnroll/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/blade-userPublicEnroll/userPublicEnroll/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/blade-userPublicEnroll/userPublicEnroll/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/blade-userPublicEnroll/userPublicEnroll/submit',
+    method: 'post',
+    data: row
+  })
+}
+
diff --git a/src/api/discuss/userTopics.js b/src/api/discuss/userTopics.js
new file mode 100644
index 0000000..40b1899
--- /dev/null
+++ b/src/api/discuss/userTopics.js
@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/blade-userTopics/userTopics/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/blade-userTopics/userTopics/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/blade-userTopics/userTopics/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/blade-userTopics/userTopics/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/blade-userTopics/userTopics/submit',
+    method: 'post',
+    data: row
+  })
+}
+
diff --git a/src/option/discuss/publicDiscuss.js b/src/option/discuss/publicDiscuss.js
new file mode 100644
index 0000000..a9feeb7
--- /dev/null
+++ b/src/option/discuss/publicDiscuss.js
@@ -0,0 +1,36 @@
+export default {
+  selection: true,
+  height: "auto",
+  calcHeight: 54,
+  align: 'center',
+  menuAlign: 'center',
+  addBtn: false,
+  // editBtn: false,
+  searchMenuSpan: 3,
+  searchBtn: true,
+  column: [{
+      label: 'ID',
+      prop: 'id',
+      searchSpan: 4,
+      // search: true,
+    },
+    {
+      label: '标题',
+      prop: 'title',
+      searchSpan: 4,
+      search: true,
+    },
+    {
+      label: '参与人数',
+      prop: 'number',
+      searchSpan: 4,
+      search: true,
+    },
+    {
+      label: '截止时间',
+      prop: 'endTime',
+      searchSpan: 4,
+      search: true,
+    }
+  ]
+}
diff --git a/src/option/discuss/topics.js b/src/option/discuss/topics.js
new file mode 100644
index 0000000..a4c563b
--- /dev/null
+++ b/src/option/discuss/topics.js
@@ -0,0 +1,14 @@
+export default {
+  height:'auto',
+  calcHeight: 30,
+  tip: false,
+  searchShow: true,
+  searchMenuSpan: 6,
+  border: true,
+  index: true,
+  viewBtn: true,
+  selection: true,
+  dialogClickModal: false,
+  column: [
+  ]
+}
diff --git a/src/option/discuss/userPublicEnroll.js b/src/option/discuss/userPublicEnroll.js
new file mode 100644
index 0000000..a4c563b
--- /dev/null
+++ b/src/option/discuss/userPublicEnroll.js
@@ -0,0 +1,14 @@
+export default {
+  height:'auto',
+  calcHeight: 30,
+  tip: false,
+  searchShow: true,
+  searchMenuSpan: 6,
+  border: true,
+  index: true,
+  viewBtn: true,
+  selection: true,
+  dialogClickModal: false,
+  column: [
+  ]
+}
diff --git a/src/option/discuss/userTopics.js b/src/option/discuss/userTopics.js
new file mode 100644
index 0000000..a4c563b
--- /dev/null
+++ b/src/option/discuss/userTopics.js
@@ -0,0 +1,14 @@
+export default {
+  height:'auto',
+  calcHeight: 30,
+  tip: false,
+  searchShow: true,
+  searchMenuSpan: 6,
+  border: true,
+  index: true,
+  viewBtn: true,
+  selection: true,
+  dialogClickModal: false,
+  column: [
+  ]
+}
diff --git a/src/views/article/article.vue b/src/views/article/article.vue
index 679dade..247ac47 100644
--- a/src/views/article/article.vue
+++ b/src/views/article/article.vue
@@ -1,56 +1,25 @@
 <template>
   <basic-container>
-    <avue-crud
-      :option="option"
-      :table-loading="loading"
-      :data="data"
-      :page.sync="page"
-      ref="crud"
-      @row-del="rowDel"
-      v-model="form"
-      :permission="permissionList"
-      @row-update="rowUpdate"
-      @row-save="rowSave"
-      :before-open="beforeOpen"
-      @search-change="searchChange"
-      @search-reset="searchReset"
-      @selection-change="selectionChange"
-      @current-change="currentChange"
-      @size-change="sizeChange"
-      @refresh-change="refreshChange"
-      @on-load="onLoad"
-    >
+    <avue-crud :option="option" :table-loading="loading" :data="data" :page.sync="page" ref="crud" @row-del="rowDel"
+      v-model="form" :permission="permissionList" @row-update="rowUpdate" @row-save="rowSave" :before-open="beforeOpen"
+      @search-change="searchChange" @search-reset="searchReset" @selection-change="selectionChange"
+      @current-change="currentChange" @size-change="sizeChange" @refresh-change="refreshChange" @on-load="onLoad">
       <template slot="menuLeft">
-        <el-button
-
-          size="small"
-          icon="el-icon-delete"
-          plain
-          v-if="permission.article_delete"
-          @click="handleDelete"
-        >删 除
+        <el-button size="small" icon="el-icon-delete" plain v-if="permission.article_delete" @click="handleDelete">删 除
         </el-button>
-        <el-button
-
-          size="small"
-          icon="el-icon-s-order"
-          plain
-          @click="kqcomment"
-        >开启评论
+        <el-button size="small" icon="el-icon-s-order" plain @click="kqcomment">开启评论
         </el-button>
-        <el-button
-
-          size="small"
-          icon="el-icon-s-release"
-          plain
-          @click="gbcomment"
-        >关闭评论
+        <el-button size="small" icon="el-icon-s-release" plain @click="gbcomment">关闭评论
         </el-button>
-
-
       </template>
 
       <template slot-scope="{type,size,row }" slot="menu">
+        <el-button icon="el-icon-circle-plus-outline" :size="size" :type="type" @click.stop="openDilog(row,0)">
+          公益报名
+        </el-button>
+        <el-button icon="el-icon-circle-plus-outline" :size="size" :type="type" @click.stop="openDilog(row,1)">
+          创建议题
+        </el-button>
         <el-button v-if="row.publish == '1'" icon="el-icon-close" :size="size" :type="type" @click.stop="updateFb(row)">
           撤销
         </el-button>
@@ -60,32 +29,96 @@
       </template>
 
       <template slot-scope="{ row }" slot="publish">
-        <el-tag
-        >{{
+        <el-tag>{{
           row.publish == "1" ? "已发布" : row.publish == "0" ? "未发布" : "未发布"
           }}
         </el-tag>
       </template>
 
       <template slot-scope="{ row }" slot="iscomment">
-        <el-tag
-        >{{
+        <el-tag>{{
           row.iscomment == "1" ? "开启" : row.iscomment == "0" ? "关闭" : "关闭"
           }}
         </el-tag>
       </template>
-
     </avue-crud>
+
+
+
+    <el-dialog title="" append-to-body :visible.sync="dialogVisibles" width="50%" :before-close="handleClose">
+      <span slot="title" class="dialog-footer">
+        {{discussForm.ontitle}}
+      </span>
+      <div id="" v-if="discussForm.eventType == 2">
+        <avue-form @submit="handleSubmit" :option="optionDiscuss" v-model="discussForm"></avue-form>
+      </div>
+
+      <div id="" v-else>
+        <avue-form @submit="handleSubmit" :option="optionEnroll" v-model="discussForm">
+        </avue-form>
+      </div>
+
+    </el-dialog>
+
+    <!-- <el-dialog title="用户数据导入" append-to-body :visible.sync="dialogVisibles" width="555px">
+      <avue-form :option="excelOption" v-model="excelForm" :upload-after="uploadAfter">
+        <template slot="excelTemplate">
+          <el-button type="primary" @click="handleTemplate">
+            点击下载<i class="el-icon-download el-icon--right"></i>
+          </el-button>
+        </template>
+      </avue-form>
+    </el-dialog> -->
+
+
+
   </basic-container>
 </template>
 
 <script>
-  import {getList, remove, update, add, getNotice, upcomment} from "@/api/article/article";
-  import {mapGetters} from "vuex";
+  import {
+    getList,
+    remove,
+    update,
+    add,
+    getNotice,
+    upcomment
+  } from "@/api/article/article";
+
+  import {
+    getListPd,
+    removePd,
+    updatePd,
+    addPd,
+    getNoticePd,
+    upcommentPd
+  } from "@/api/discuss/publicDiscuss";
+  import {
+    mapGetters
+  } from "vuex";
 
   export default {
     data() {
       return {
+        discussForm: {
+          ontitle: '',
+          title: '',
+          openFlag: 0,
+          numberRestrictions: 0,
+          voteRestrictions: 0,
+          userRestrictions: 0,
+          endTime: '',
+          articleId: '',
+          createTime: '',
+          updateTime: '',
+          deleteFlag: '',
+          repeatVote: 0,
+          voteNumberPublic: 0,
+          appointUser: '',
+          userIds: '',
+          eventType: 1,
+        },
+        dialogVisibles: false,
         form: {},
         query: {},
         loading: true,
@@ -103,7 +136,7 @@
           tip: false,
           searchShow: true,
           searchMenuSpan: 3,
-          menuWidth: 350,
+          menuWidth: 450,
           border: false,
           //stripe:true,
           index: true,
@@ -111,21 +144,18 @@
           selection: true,
           excelBtn: true,
           dialogClickModal: false,
-          column: [
-            {
+          column: [{
               label: "资讯标题",
               prop: "title",
               span: 24,
               row: true,
               searchSpan: 4,
               search: true,
-              rules: [
-                {
-                  required: true,
-                  message: "请输入资讯标题",
-                  trigger: "blur",
-                },
-              ],
+              rules: [{
+                required: true,
+                message: "请输入资讯标题",
+                trigger: "blur",
+              }, ],
             },
             {
               label: "资讯封面",
@@ -148,13 +178,11 @@
               search: true,
               searchSpan: 4,
               span: 24,
-              rules: [
-                {
-                  required: true,
-                  message: "请输入资讯类型",
-                  trigger: "blur",
-                },
-              ],
+              rules: [{
+                required: true,
+                message: "请输入资讯类型",
+                trigger: "blur",
+              }, ],
             },
             {
               label: "资讯类型",
@@ -171,13 +199,11 @@
               },
               search: true,
               type: "tree",
-              rules: [
-                {
-                  required: true,
-                  message: "请选择资讯类型",
-                  trigger: "blur",
-                },
-              ],
+              rules: [{
+                required: true,
+                message: "请选择资讯类型",
+                trigger: "blur",
+              }, ],
             },
             {
               label: "发布时间",
@@ -192,13 +218,11 @@
               editDisplay: false,
               viewDisplay: false,
               search: true,
-              rules: [
-                {
-                  required: true,
-                  message: "请选择发布时间",
-                  trigger: "blur",
-                },
-              ],
+              rules: [{
+                required: true,
+                message: "请选择发布时间",
+                trigger: "blur",
+              }, ],
             },
             {
               label: "发布时间",
@@ -216,15 +240,12 @@
               slot: true,
               search: true,
               type: "select",
-              rules: [
-                {
-                  required: true,
-                  message: "请选择发布状态",
-                  trigger: "blur",
-                },
-              ],
-              dicData: [
-                {
+              rules: [{
+                required: true,
+                message: "请选择发布状态",
+                trigger: "blur",
+              }, ],
+              dicData: [{
                   label: "未发布",
                   value: "0",
                 },
@@ -240,8 +261,7 @@
               width: 80,
               slot: true,
               type: "select",
-              dicData: [
-                {
+              dicData: [{
                   label: "关闭",
                   value: "0",
                 },
@@ -286,6 +306,228 @@
           ],
         },
         data: [],
+        optionEnroll: {
+          column: [{
+              label: "",
+              type: 'title',
+              prop: "title",
+              span: 24,
+              row: true,
+              offset: 2,
+              styles: {
+                fontSize: '24px'
+              }
+            }, {
+              labelWidth: 100,
+              label: '开启投票',
+              prop: 'openFlag',
+              type: 'radio',
+              button: true,
+              row: true,
+              offset: 6,
+              dicData: [{
+                label: '开启',
+                value: 0
+              }, {
+                label: '不开启',
+                value: 1
+              }]
+            },
+            {
+              labelWidth: 100,
+              label: '人数限制',
+              prop: 'numberRestrictions',
+              type: 'number',
+              button: true,
+              row: true,
+              min: 0,
+              max: 99999999,
+              controlsPosition: '',
+              step: 10,
+              offset: 6,
+            }, {
+              labelWidth: 100,
+              label: '投票限制',
+              prop: 'voteRestrictions',
+              type: 'radio',
+              button: true,
+              row: true,
+              offset: 6,
+              dicData: [{
+                label: '一人一票',
+                value: 0
+              }, {
+                label: '一户一票',
+                value: 1
+              }]
+            }, {
+              labelWidth: 100,
+              label: '用户限制',
+              prop: 'userRestrictions',
+              type: 'radio',
+              button: true,
+              row: true,
+              offset: 6,
+              dicData: [{
+                label: '不限制',
+                value: 0
+              }, {
+                label: '必须绑定手机',
+                value: 1
+              }, {
+                label: '必须绑定房屋',
+                value: 2
+              }]
+            },
+            {
+              label: "截止时间",
+              row: true,
+              offset: 6,
+              prop: "endTime",
+              type: "datetime",
+              format: "yyyy-MM-dd hh:mm:ss",
+              valueFormat: "timestamp",
+            },
+          ]
+        },
+        optionDiscuss: {
+          column: [{
+              label: "",
+              // labelWidth: 20,
+              type: 'title',
+              prop: "title",
+              span: 24,
+              row: true,
+              offset: 2,
+              styles: {
+                // color: 'red',
+                fontSize: '24px'
+              }
+            }, {
+              labelWidth: 100,
+              label: '开启投票',
+              prop: 'openFlag',
+              type: 'radio',
+              button: true,
+              row: true,
+              offset: 6,
+              dicData: [{
+                label: '开启',
+                value: 0
+              }, {
+                label: '不开启',
+                value: 1
+              }]
+            }, {
+              labelWidth: 100,
+              label: '多房屋可重复',
+              prop: 'repeatVote',
+              type: 'radio',
+              button: true,
+              row: true,
+              offset: 6,
+              dicData: [{
+                label: '不可以',
+                value: 0
+              }, {
+                label: '可以',
+                value: 1
+              }]
+            }, {
+              labelWidth: 100,
+              label: '投票限制',
+              prop: 'voteRestrictions',
+              type: 'radio',
+              button: true,
+              row: true,
+              offset: 6,
+              dicData: [{
+                label: '一人一票',
+                value: 0
+              }, {
+                label: '一户一票',
+                value: 1
+              }]
+            }, {
+              labelWidth: 100,
+              label: '用户限制',
+              prop: 'userRestrictions',
+              type: 'radio',
+              button: true,
+              row: true,
+              offset: 6,
+              dicData: [{
+                label: '不限制',
+                value: 0
+              }, {
+                label: '必须绑定手机',
+                value: 1
+              }, {
+                label: '必须绑定房屋',
+                value: 2
+              }]
+            }, {
+              labelWidth: 100,
+              label: '票数公开',
+              prop: 'voteNumberPublic',
+              type: 'radio',
+              button: true,
+              row: true,
+              offset: 6,
+              dicData: [{
+                label: '全程公开',
+                value: 0
+              }, {
+                label: '投票后公开',
+                value: 1
+              }, {
+                label: '投票结束后公开',
+                value: 2
+              }, {
+                label: '不公开',
+                value: 3
+              }]
+            },
+            {
+              label: "截止时间",
+              row: true,
+              offset: 6,
+              prop: "endTime",
+              type: "datetime",
+              format: "yyyy-MM-dd hh:mm:ss",
+              valueFormat: "timestamp",
+            },
+            // {
+            //   labelWidth: 100,
+            //   label: '人数限制',
+            //   prop: 'numberRestrictions',
+            //   type: 'number',
+            //   button: true,
+            //   row: true,
+            //   min: 0,
+            //   max: 99999999,
+            //   controlsPosition: '',
+            //   step: 10,
+            //   offset: 6,
+            // },
+            // {
+            //   labelWidth: 100,
+            //   label: '指定用户',
+            //   prop: 'appointUser',
+            //   type: 'radio',
+            //   button: true,
+            //   row: true,
+            //   offset: 6,
+            //   dicData: [{
+            //     label: '不限制',
+            //     value: 0
+            //   }, {
+            //     label: '指定用户可见',
+            //     value: 1
+            //   }]
+            // },
+          ]
+        },
       };
     },
     watch: {
@@ -297,13 +539,11 @@
             if (val.indexOf('ksp') != -1) {
               videoUrl.display = true;
               content.display = false;
-              videoUrl.rules = [
-                {
-                  required: false,
-                  message: "请选择视频",
-                  trigger: "blur",
-                },
-              ];
+              videoUrl.rules = [{
+                required: false,
+                message: "请选择视频",
+                trigger: "blur",
+              }, ];
             } else {
               videoUrl.display = false;
               content.display = true;
@@ -315,7 +555,7 @@
       }
     },
     computed: {
-      ...mapGetters(["permission","userInfo"]),
+      ...mapGetters(["permission", "userInfo"]),
       permissionList() {
         return {
           addBtn: this.vaildData(this.permission.article_add, true),
@@ -333,11 +573,50 @@
       },
     },
     methods: {
+
+      openDilog(row, type) {
+        this.dialogVisibles = true
+        this.discussForm.eventType = type
+        this.discussForm.articleId = row.id
+        this.discussForm.title = row.title
+        if (type == 0) {
+          this.discussForm.ontitle = '公益报名'
+        } else {
+          this.discussForm.ontitle = '创建议题'
+        }
+      },
+
+      handleSubmit(form, done) {
+        done();
+        addPd(form).then(
+          () => {
+            this.$message({
+              type: "success",
+              message: "操作成功!",
+            });
+            this.dialogVisibles = false
+            done();
+          },
+          (error) => {
+            window.console.log(error);
+            // loading();
+          }
+        );
+      },
+
+      handleClose(done) {
+        done();
+        // this.$confirm('确认关闭?')
+        //   .then(_ => {
+        //     done();
+        //   })
+        //   .catch(_ => {});
+      },
       rowSave(row, done, loading) {
         if (row.videoUrl.length == 0) {
           row.videoUrl = "";
         }
-        row.userid=this.userInfo.user_id;
+        row.userid = this.userInfo.user_id;
         add(row).then(
           () => {
             this.onLoad(this.page);
@@ -371,10 +650,10 @@
       },
       rowDel(row) {
         this.$confirm("确定将选择数据删除?", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning",
-        })
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning",
+          })
           .then(() => {
             return remove(row.id);
           })
@@ -409,10 +688,10 @@
           return;
         }
         this.$confirm("确定将选择数据删除?", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning",
-        })
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning",
+          })
           .then(() => {
             return remove(this.ids);
           })
@@ -444,7 +723,9 @@
         this.onLoad(this.page, this.query);
       },
       onLoad(page, params = {}) {
-        const {dateTime} = this.query;
+        const {
+          dateTime
+        } = this.query;
         let values = {
           ...params,
         };
@@ -493,12 +774,12 @@
           return;
         }
         this.$confirm("确定将选择数据开启评论?", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning",
-        }).then(() => {
-          return upcomment(this.ids, "1");
-        })
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning",
+          }).then(() => {
+            return upcomment(this.ids, "1");
+          })
           .then(() => {
             this.onLoad(this.page);
             this.$message({
@@ -514,12 +795,12 @@
           return;
         }
         this.$confirm("确定将选择数据开启评论?", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning",
-        }).then(() => {
-          return upcomment(this.ids, "0");
-        })
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning",
+          }).then(() => {
+            return upcomment(this.ids, "0");
+          })
           .then(() => {
             this.onLoad(this.page);
             this.$message({
diff --git a/src/views/article/discussionManage.vue b/src/views/article/discussionManage.vue
index 22bd8c4..35191ec 100644
--- a/src/views/article/discussionManage.vue
+++ b/src/views/article/discussionManage.vue
@@ -1,11 +1,324 @@
 <template>
-  <div id="">
-    议事
-  </div>
+  <basicContainer>
+    <avue-crud :data="data" ref="crud" :table-loading="loading" @current-change="currentChange"
+      @search-change="searchChange" @search-reset="searchReset" @size-change="sizeChange" :option="option"
+      v-model="data" :page="page" @selection-change="selectionChange" @row-del="rowDel" @refresh-change="refreshChange"
+      @on-load="onLoad">
+      <template slot="menuLeft">
+        <el-button type="danger" size="small" plain icon="el-icon-delete" v-if="permission.user_delete"
+          @click="handleDelete">批量删除
+        </el-button>
+      </template>
+
+      <template slot-scope="scope" slot="menu">
+        <el-button type="text" icon="el-icon-circle-plus-outline" size="small"
+          @click.stop="openDilog(scope.row,scope.index)">编辑议题
+        </el-button>
+      </template>
+    </avue-crud>
+
+    <el-dialog title="" append-to-body :visible.sync="dialogVisibles" width="50%" :before-close="handleClose">
+      <span slot="title" class="dialog-footer">
+        {{ontitle}}
+      </span>
+      <avue-form @submit="handleSubmit" :option="optionDiscuss" v-model="disCussFrom">
+      </avue-form>
+    </el-dialog>
+  </basicContainer>
 </template>
 
 <script>
+  import {
+    getListPd,
+    getDetailPd,
+    addPd,
+    updatePd,
+    removePd
+  } from "@/api/discuss/publicDiscuss";
+
+  import {
+    getList,
+    getDetail,
+    add,
+    update,
+    remove
+  } from "@/api/discuss/topics";
+
+  import option from "@/option/discuss/publicDiscuss";
+  import {
+    mapGetters
+  } from "vuex";
+  import {
+    getDictionary
+  } from '@/api/system/dict'
+
+  export default {
+    data() {
+      return {
+        optionDiscuss: {
+          column: [{
+              label: '议题',
+              prop: 'discussContent',
+              type: 'input',
+              row: true,
+            }, {
+              label: '选项范围',
+              prop: 'option',
+              type: 'radio',
+              button: true,
+              row: true,
+              dicData: [{
+                label: '多选',
+                value: 0
+              }, {
+                label: '单选',
+                value: 1
+              }]
+            }, {
+              label: '排序',
+              prop: 'sort',
+              controlsPosition: '',
+              type: 'number'
+            },
+            {
+              label: '选项内容',
+              prop: 'children',
+              type: 'dynamic',
+              span: 24,
+              children: {
+                column: [{
+                  label: '选项标题',
+                  prop: 'optionContent',
+                  type: 'input',
+                  rules: [{
+                    required: true,
+                    message: '请输入选项标题',
+                    trigger: 'blur'
+                  }]
+                }, {
+                  label: '选项说明',
+                  prop: 'optionDetail',
+                  type: 'input',
+                }]
+              }
+            },
+          ]
+
+        },
+        disCussFrom: {
+          discussContent: '',
+          option: 0,
+          sort: 1,
+          optionContent: '',
+          optionDetail: '',
+          number: '',
+          createTime: '',
+          updateTime: '',
+          deleteFlag: '',
+          publicDiscussId: '',
+          parentId: '',
+          level: '',
+          children: [{
+            optionContent: '',
+            optionDetail: '',
+            number: '',
+            createTime: '',
+            updateTime: '',
+            deleteFlag: '',
+            publicDiscussId: '',
+            parentId: '',
+            level: '',
+          }]
+
+        },
+        ontitle: '编辑议题',
+        // 弹框标题
+        title: '',
+        // 是否展示弹框
+        box: false,
+        // 是否显示查询
+        search: true,
+        // 加载中
+        loading: true,
+        // 是否为查看模式
+        view: false,
+        // 查询信息
+        query: {},
+        // 分页信息
+        page: {
+          pageSize: 10,
+          pageSizes: [10, 20, 30, 50, 100],
+          currentPage: 1,
+          total: 0
+        },
+        // 表单数据
+        form: {},
+        // 选择行
+        selectionList: [],
+        // 表单配置
+        option: option,
+        // 表单列表
+        data: [],
+        dataTop: [],
+        dialogVisibles: false,
+      }
+    },
+    mounted() {
+      // this.init();
+      // this.onLoad(this.page);
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+
+      openDilog(row, type) {
+        this.dialogVisibles = true
+        this.loading = true;
+        let params = {}
+        getList(1, 100, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.dataTop = data.records;
+          this.loading = false;
+          this.selectionClear();
+        })
+      },
+
+      handleSubmit(form, done) {
+        done();
+        add(form).then(
+          () => {
+            this.$message({
+              type: "success",
+              message: "操作成功!",
+            });
+            this.dialogVisibles = false
+            done();
+          },
+          (error) => {
+            window.console.log(error);
+            // loading();
+          }
+        );
+      },
+
+      init() {},
+      searchHide() {
+        this.search = !this.search;
+      },
+      searchChange() {
+        this.onLoad(this.page);
+      },
+      searchReset() {
+        this.query = {};
+        this.page.currentPage = 1;
+        this.onLoad(this.page);
+      },
+
+      handleAdd() {
+        this.title = '新增'
+        this.form = {}
+        this.box = true
+      },
+      handleEdit(row) {
+        this.title = '编辑'
+        this.box = true
+        getDetailPd(row.id).then(res => {
+          this.form = res.data.data;
+        });
+      },
+      handleView(row) {
+        this.title = '查看'
+        this.view = true;
+        this.box = true;
+        getDetailPd(row.id).then(res => {
+          this.form = res.data.data;
+        });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+          .then(() => {
+            return removePd(this.ids);
+          })
+          .then(() => {
+            this.selectionClear();
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      beforeClose(done) {
+        done()
+        this.form = {};
+        this.view = false;
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        // this.$refs.table.clearSelection();
+      },
+      currentChange(currentPage) {
+        this.page.currentPage = currentPage;
+        this.onLoad(this.page);
+      },
+      sizeChange(pageSize) {
+        this.page.pageSize = pageSize;
+        this.onLoad(this.page);
+      },
+      onLoad(page, params = {
+        eventType: 1
+      }) {
+        this.loading = true;
+        getListPd(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
 </script>
 
-<style>
+<style lang="scss" scoped>
+  .el-pagination {
+    margin-top: 20px;
+  }
 </style>
diff --git a/src/views/article/publicSignUp.vue b/src/views/article/publicSignUp.vue
index cda76fb..6db76ec 100644
--- a/src/views/article/publicSignUp.vue
+++ b/src/views/article/publicSignUp.vue
@@ -1,12 +1,213 @@
 <template>
-  <div id="">
-    公益报名
-    
-  </div>
+  <basicContainer>
+    <avue-crud :data="data" ref="crud" :table-loading="loading" @current-change="currentChange"
+      @search-change="searchChange" @search-reset="searchReset" @size-change="sizeChange" :option="option"
+      v-model="data" :page="page" @selection-change="selectionChange" @row-del="rowDel" @refresh-change="refreshChange"
+      @on-load="onLoad">
+      <template slot="menuLeft">
+        <!-- <el-button size="small" icon="el-icon-delete" plain v-if="permission.article_delete" @click="handleDelete">删 除
+        </el-button> -->
+        <el-button type="danger" size="small" plain icon="el-icon-delete" v-if="permission.user_delete"
+          @click="handleDelete">批量删除
+        </el-button>
+      </template>
+    </avue-crud>
+  </basicContainer>
 </template>
 
 <script>
+  import {
+    getListPd,
+    getDetailPd,
+    addPd,
+    updatePd,
+    removePd
+  } from "@/api/discuss/publicDiscuss";
+  import option from "@/option/discuss/publicDiscuss";
+  import {
+    mapGetters
+  } from "vuex";
+  import {
+    getDictionary
+  } from '@/api/system/dict'
+
+  export default {
+    data() {
+      return {
+        // 弹框标题
+        title: '',
+        // 是否展示弹框
+        box: false,
+        // 是否显示查询
+        search: true,
+        // 加载中
+        loading: true,
+        // 是否为查看模式
+        view: false,
+        // 查询信息
+        query: {},
+        // 分页信息
+        page: {
+          pageSize: 10,
+          pageSizes: [10, 20, 30, 50, 100],
+          currentPage: 1,
+          total: 0
+        },
+        // 表单数据
+        form: {},
+        // 选择行
+        selectionList: [],
+        // 表单配置
+        option: option,
+        // 表单列表
+        data: [],
+      }
+    },
+    mounted() {
+      // this.init();
+      // this.onLoad(this.page);
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+      init() {},
+      searchHide() {
+        this.search = !this.search;
+      },
+      searchChange() {
+        this.onLoad(this.page);
+      },
+      searchReset() {
+        this.query = {};
+        this.page.currentPage = 1;
+        this.onLoad(this.page);
+      },
+      handleSubmit() {
+        if (!this.form.id) {
+          addPd(this.form).then(() => {
+            this.box = false;
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+        } else {
+          updatePd(this.form).then(() => {
+            this.box = false;
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          })
+        }
+      },
+      handleAdd() {
+        this.title = '新增'
+        this.form = {}
+        this.box = true
+      },
+      handleEdit(row) {
+        this.title = '编辑'
+        this.box = true
+        getDetailPd(row.id).then(res => {
+          this.form = res.data.data;
+        });
+      },
+      handleView(row) {
+        this.title = '查看'
+        this.view = true;
+        this.box = true;
+        getDetailPd(row.id).then(res => {
+          this.form = res.data.data;
+        });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+          .then(() => {
+            return removePd(this.ids);
+          })
+          .then(() => {
+            this.selectionClear();
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      beforeClose(done) {
+        done()
+        this.form = {};
+        this.view = false;
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        // this.$refs.table.clearSelection();
+      },
+      currentChange(currentPage) {
+        this.page.currentPage = currentPage;
+        this.onLoad(this.page);
+      },
+      sizeChange(pageSize) {
+        this.page.pageSize = pageSize;
+        this.onLoad(this.page);
+      },
+      onLoad(page, params = {
+        eventType: 0
+      }) {
+        this.loading = true;
+        getListPd(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
 </script>
 
-<style>
+<style lang="scss" scoped>
+  .el-pagination {
+    margin-top: 20px;
+  }
 </style>
diff --git a/src/views/discuss/publicDiscuss.vue b/src/views/discuss/publicDiscuss.vue
new file mode 100644
index 0000000..6e8fa27
--- /dev/null
+++ b/src/views/discuss/publicDiscuss.vue
@@ -0,0 +1,270 @@
+<template>
+  <basic-container>
+    <div class="avue-crud">
+      <el-row :hidden="!search" style="padding:5px">
+        <!-- 查询模块 -->
+        <el-form :inline="true" :size="option.size" :model="query">
+          <template>
+          </template>
+          <!-- 查询按钮 -->
+          <el-form-item>
+            <el-button type="primary" icon="el-icon-search" @click="searchChange">搜索</el-button>
+            <el-button icon="el-icon-delete" @click="searchReset()">清空</el-button>
+          </el-form-item>
+        </el-form>
+      </el-row>
+      <el-row>
+        <div class="avue-crud__menu">
+          <!-- 头部左侧按钮模块 -->
+          <div class="avue-crud__left">
+            <el-button :size="option.size" type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
+            <el-button :size="option.size" type="danger" icon="el-icon-delete" @click="handleDelete" plain>删除
+            </el-button>
+          </div>
+          <!-- 头部右侧按钮模块 -->
+          <div class="avue-crud__right">
+            <el-button :size="option.size" icon="el-icon-refresh" @click="searchChange" circle></el-button>
+            <el-button :size="option.size" icon="el-icon-search" @click="searchHide" circle></el-button>
+          </div>
+        </div>
+      </el-row>
+      <el-row>
+        <!-- 列表模块 -->
+        <el-table ref="table" v-loading="loading" :size="option.size" @selection-change="selectionChange" :data="data"
+                  style="width: 100%"
+                  :border="option.border">
+          <el-table-column type="selection" v-if="option.selection" width="55" align="center"></el-table-column>
+          <el-table-column type="expand" v-if="option.expand" align="center"></el-table-column>
+          <el-table-column v-if="option.index" label="#" type="index" width="50" align="center">
+          </el-table-column>
+          <template v-for="(item,index) in option.column">
+            <!-- table字段 -->
+            <el-table-column v-if="item.hide!==true"
+                             :prop="item.prop"
+                             :label="item.label"
+                             :width="item.width"
+                             :key="index">
+            </el-table-column>
+          </template>
+          <!-- 操作栏模块 -->
+          <el-table-column prop="menu" label="操作" :width="180" align="center">
+            <template slot-scope="{row}">
+              <el-button :size="option.size" type="text" icon="el-icon-view" @click="handleView(row)">查看</el-button>
+              <el-button :size="option.size" type="text" icon="el-icon-edit" @click="handleEdit(row)">编辑</el-button>
+              <el-button :size="option.size" type="text" icon="el-icon-delete" @click="rowDel(row)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-row>
+      <el-row>
+        <!-- 分页模块 -->
+        <el-pagination
+          align="right" background
+          @size-change="sizeChange"
+          @current-change="currentChange"
+          :current-page="page.currentPage"
+          :page-sizes="[10, 20, 30, 40, 50, 100]"
+          :page-size="page.pageSize"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="page.total">
+        </el-pagination>
+      </el-row>
+      <!-- 表单模块 -->
+      <el-dialog :title="title" :visible.sync="box" width="50%" :before-close="beforeClose" append-to-body>
+        <el-form :disabled="view" :size="option.size" ref="form" :model="form" label-width="80px">
+          <!-- 表单字段 -->
+        </el-form>
+        <!-- 表单按钮 -->
+        <span v-if="!view" slot="footer" class="dialog-footer">
+          <el-button type="primary" icon="el-icon-circle-check" :size="option.size" @click="handleSubmit">提 交</el-button>
+          <el-button icon="el-icon-circle-close" :size="option.size" @click="box = false">取 消</el-button>
+        </span>
+      </el-dialog>
+    </div>
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove} from "@/api/discuss/publicDiscuss";
+  import option from "@/option/discuss/publicDiscuss";
+  import {mapGetters} from "vuex";
+  import {getDictionary} from '@/api/system/dict'
+
+export default {
+  data() {
+    return {
+      // 弹框标题
+      title: '',
+      // 是否展示弹框
+      box: false,
+      // 是否显示查询
+      search: true,
+      // 加载中
+      loading: true,
+      // 是否为查看模式
+      view: false,
+      // 查询信息
+      query: {},
+      // 分页信息
+      page: {
+        currentPage: 1,
+        pageSize: 10,
+        total: 40
+      },
+      // 表单数据
+      form: {},
+      // 选择行
+      selectionList: [],
+      // 表单配置
+      option: option,
+      // 表单列表
+      data: [],
+    }
+  },
+  mounted() {
+    this.init();
+    this.onLoad(this.page);
+  },
+  computed: {
+    ...mapGetters(["permission"]),
+    ids() {
+      let ids = [];
+      this.selectionList.forEach(ele => {
+        ids.push(ele.id);
+      });
+      return ids.join(",");
+    }
+  },
+  methods: {
+    init() {
+    },
+    searchHide() {
+      this.search = !this.search;
+    },
+    searchChange() {
+      this.onLoad(this.page);
+    },
+    searchReset() {
+      this.query = {};
+      this.page.currentPage = 1;
+      this.onLoad(this.page);
+    },
+    handleSubmit() {
+      if (!this.form.id) {
+        add(this.form).then(() => {
+          this.box = false;
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+        });
+      } else {
+        update(this.form).then(() => {
+          this.box = false;
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+        })
+      }
+    },
+    handleAdd() {
+      this.title = '新增'
+      this.form = {}
+      this.box = true
+    },
+    handleEdit(row) {
+      this.title = '编辑'
+      this.box = true
+      getDetail(row.id).then(res => {
+        this.form = res.data.data;
+      });
+    },
+    handleView(row) {
+      this.title = '查看'
+      this.view = true;
+      this.box = true;
+      getDetail(row.id).then(res => {
+        this.form = res.data.data;
+      });
+    },
+    handleDelete() {
+      if (this.selectionList.length === 0) {
+        this.$message.warning("请选择至少一条数据");
+        return;
+      }
+      this.$confirm("确定将选择数据删除?", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(() => {
+          return remove(this.ids);
+        })
+        .then(() => {
+          this.selectionClear();
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+        });
+    },
+    rowDel(row) {
+      this.$confirm("确定将选择数据删除?", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(() => {
+          return remove(row.id);
+        })
+        .then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+        });
+    },
+    beforeClose(done) {
+      done()
+      this.form = {};
+      this.view = false;
+    },
+    selectionChange(list) {
+      this.selectionList = list;
+    },
+    selectionClear() {
+      this.selectionList = [];
+      this.$refs.table.clearSelection();
+    },
+    currentChange(currentPage) {
+      this.page.currentPage = currentPage;
+      this.onLoad(this.page);
+    },
+    sizeChange(pageSize) {
+      this.page.pageSize = pageSize;
+      this.onLoad(this.page);
+    },
+    onLoad(page, params = {}) {
+      this.loading = true;
+      getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+        const data = res.data.data;
+        this.page.total = data.total;
+        this.data = data.records;
+        this.loading = false;
+        this.selectionClear();
+      });
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.el-pagination {
+  margin-top: 20px;
+}
+</style>
diff --git a/src/views/discuss/topics.vue b/src/views/discuss/topics.vue
new file mode 100644
index 0000000..d0e3979
--- /dev/null
+++ b/src/views/discuss/topics.vue
@@ -0,0 +1,188 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option"
+               :table-loading="loading"
+               :data="data"
+               :page.sync="page"
+               :permission="permissionList"
+               :before-open="beforeOpen"
+               v-model="form"
+               ref="crud"
+               @row-update="rowUpdate"
+               @row-save="rowSave"
+               @row-del="rowDel"
+               @search-change="searchChange"
+               @search-reset="searchReset"
+               @selection-change="selectionChange"
+               @current-change="currentChange"
+               @size-change="sizeChange"
+               @refresh-change="refreshChange"
+               @on-load="onLoad">
+      <template slot="menuLeft">
+        <el-button type="danger"
+                   size="small"
+                   icon="el-icon-delete"
+                   plain
+                   v-if="permission.topics_delete"
+                   @click="handleDelete">删 除
+        </el-button>
+      </template>
+    </avue-crud>
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove} from "@/api/discuss/topics";
+  import option from "@/option/discuss/topics";
+  import {mapGetters} from "vuex";
+
+  export default {
+    data() {
+      return {
+        form: {},
+        query: {},
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: option,
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.topics_add, false),
+          viewBtn: this.vaildData(this.permission.topics_view, false),
+          delBtn: this.vaildData(this.permission.topics_delete, false),
+          editBtn: this.vaildData(this.permission.topics_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage){
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize){
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>
diff --git a/src/views/discuss/userPublicEnroll.vue b/src/views/discuss/userPublicEnroll.vue
new file mode 100644
index 0000000..2e2f462
--- /dev/null
+++ b/src/views/discuss/userPublicEnroll.vue
@@ -0,0 +1,178 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option" :table-loading="loading" :data="data" :page.sync="page" :permission="permissionList"
+      :before-open="beforeOpen" v-model="form" ref="crud" @row-update="rowUpdate" @row-save="rowSave" @row-del="rowDel"
+      @search-change="searchChange" @search-reset="searchReset" @selection-change="selectionChange"
+      @current-change="currentChange" @size-change="sizeChange" @refresh-change="refreshChange" @on-load="onLoad">
+      <template slot="menuLeft">
+        <el-button type="danger" size="small" icon="el-icon-delete" plain v-if="permission.userPublicEnroll_delete"
+          @click="handleDelete">删 除
+        </el-button>
+      </template>
+    </avue-crud>
+  </basic-container>
+</template>
+
+<script>
+  import {
+    getList,
+    getDetail,
+    add,
+    update,
+    remove
+  } from "@/api/discuss/userPublicEnroll";
+  import option from "@/option/discuss/userPublicEnroll";
+  import {
+    mapGetters
+  } from "vuex";
+
+  export default {
+    data() {
+      return {
+        form: {},
+        query: {},
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: option,
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.userPublicEnroll_add, false),
+          viewBtn: this.vaildData(this.permission.userPublicEnroll_view, false),
+          delBtn: this.vaildData(this.permission.userPublicEnroll_delete, false),
+          editBtn: this.vaildData(this.permission.userPublicEnroll_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage) {
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize) {
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>
diff --git a/src/views/discuss/userTopics.vue b/src/views/discuss/userTopics.vue
new file mode 100644
index 0000000..739f093
--- /dev/null
+++ b/src/views/discuss/userTopics.vue
@@ -0,0 +1,188 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option"
+               :table-loading="loading"
+               :data="data"
+               :page.sync="page"
+               :permission="permissionList"
+               :before-open="beforeOpen"
+               v-model="form"
+               ref="crud"
+               @row-update="rowUpdate"
+               @row-save="rowSave"
+               @row-del="rowDel"
+               @search-change="searchChange"
+               @search-reset="searchReset"
+               @selection-change="selectionChange"
+               @current-change="currentChange"
+               @size-change="sizeChange"
+               @refresh-change="refreshChange"
+               @on-load="onLoad">
+      <template slot="menuLeft">
+        <el-button type="danger"
+                   size="small"
+                   icon="el-icon-delete"
+                   plain
+                   v-if="permission.userTopics_delete"
+                   @click="handleDelete">删 除
+        </el-button>
+      </template>
+    </avue-crud>
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove} from "@/api/discuss/userTopics";
+  import option from "@/option/discuss/userTopics";
+  import {mapGetters} from "vuex";
+
+  export default {
+    data() {
+      return {
+        form: {},
+        query: {},
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: option,
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.userTopics_add, false),
+          viewBtn: this.vaildData(this.permission.userTopics_view, false),
+          delBtn: this.vaildData(this.permission.userTopics_delete, false),
+          editBtn: this.vaildData(this.permission.userTopics_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage){
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize){
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

--
Gitblit v1.9.3