Parcourir la source

教育学习模块,新增专业类别;

修改系统名字为CMC智联云枢办公系统
余思翰 il y a 3 semaines
Parent
révision
8f7a9f08c0

+ 2
- 2
oa-back/ruoyi-system/src/main/resources/mapper/oa/CmcResourceMapper.xml Voir le fichier

@@ -56,12 +56,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
56 56
     </select>
57 57
 
58 58
     <select id="selectCmcResourceListBelow" parameterType="CmcResource" resultMap="CmcResourceResult">
59
-        SELECT r.resource_id, r.uploader, r.upload_dept, r.title, r.source_path, r.type, r.field_id, r.upload_time, r.hours
59
+        SELECT r.resource_id, r.uploader, r.upload_dept, r.title, r.source_path, r.type, r.field_id, tree.field, r.upload_time, r.hours
60 60
         FROM cmc_resource AS r
61 61
         LEFT JOIN sys_user AS u ON u.user_id = r.uploader
62 62
         LEFT JOIN sys_dept AS d ON d.dept_id = r.upload_dept
63 63
         RIGHT JOIN (
64
-        SELECT rf2.field_id FROM
64
+        SELECT rf2.field_id, rf2.field FROM
65 65
         ( SELECT rf1.field_id AS sub_field_id, rf1.parent_id AS sub_parent_id, rf0.field_id, rf0.parent_id
66 66
         FROM cmc_resource_field AS rf0
67 67
         LEFT JOIN cmc_resource_field AS rf1 ON rf1.parent_id = rf0.field_id

+ 8
- 2
oa-ui/.env.development Voir le fichier

@@ -1,10 +1,16 @@
1
+###
2
+ # @Author: ysh
3
+ # @Date: 2024-06-21 18:51:04
4
+ # @LastEditors: 
5
+ # @LastEditTime: 2025-03-25 17:00:43
6
+### 
1 7
 # 页面标题
2
-VUE_APP_TITLE = CMC综合办公系统
8
+VUE_APP_TITLE = CMC智联云枢办公系统
3 9
 
4 10
 # 开发环境配置
5 11
 ENV = 'development'
6 12
 
7
-# CMC综合办公系统/开发环境
13
+# CMC智联云枢办公系统/开发环境
8 14
 VUE_APP_BASE_API = '/dev-api'
9 15
 
10 16
 # 路由懒加载

+ 2
- 2
oa-ui/.env.production Voir le fichier

@@ -1,8 +1,8 @@
1 1
 # 页面标题
2
-VUE_APP_TITLE = CMC综合办公系统
2
+VUE_APP_TITLE = CMC智联云枢办公系统
3 3
 
4 4
 # 生产环境配置
5 5
 ENV = 'production'
6 6
 
7
-# CMC综合办公系统/生产环境
7
+# CMC智联云枢办公系统/生产环境
8 8
 VUE_APP_BASE_API = '/prod-api'

+ 2
- 2
oa-ui/.env.staging Voir le fichier

@@ -1,10 +1,10 @@
1 1
 # 页面标题
2
-VUE_APP_TITLE = CMC综合办公系统
2
+VUE_APP_TITLE = CMC智联云枢办公系统
3 3
 
4 4
 NODE_ENV = production
5 5
 
6 6
 # 测试环境配置
7 7
 ENV = 'staging'
8 8
 
9
-# CMC综合办公系统/测试环境
9
+# CMC智联云枢办公系统/测试环境
10 10
 VUE_APP_BASE_API = '/stage-api'

+ 8
- 1
oa-ui/src/api/oa/study/resource.js Voir le fichier

@@ -8,7 +8,14 @@ export function listResource(query) {
8 8
     params: query
9 9
   })
10 10
 }
11
-
11
+// 查询cmc学习资料列表根据类名
12
+export function getListBelow(query) {
13
+  return request({
14
+    url: '/oa/resource/getListBelow',
15
+    method: 'get',
16
+    params: query
17
+  })
18
+}
12 19
 // 查询cmc学习资料详细
13 20
 export function getResource(resourceId) {
14 21
   return request({

+ 50
- 0
oa-ui/src/api/oa/study/resourceField.js Voir le fichier

@@ -0,0 +1,50 @@
1
+/*
2
+ * @Author: ysh
3
+ * @Date: 2025-03-24 10:15:00
4
+ * @LastEditors: 
5
+ * @LastEditTime: 2025-03-24 10:15:15
6
+ */
7
+import request from '@/utils/request'
8
+
9
+// 查询cmc专业领域列表
10
+export function listField(query) {
11
+  return request({
12
+    url: '/oa/field/list',
13
+    method: 'get',
14
+    params: query
15
+  })
16
+}
17
+
18
+// 查询cmc专业领域详细
19
+export function getField(fieldId) {
20
+  return request({
21
+    url: '/oa/field/' + fieldId,
22
+    method: 'get'
23
+  })
24
+}
25
+
26
+// 新增cmc专业领域
27
+export function addField(data) {
28
+  return request({
29
+    url: '/oa/field',
30
+    method: 'post',
31
+    data: data
32
+  })
33
+}
34
+
35
+// 修改cmc专业领域
36
+export function updateField(data) {
37
+  return request({
38
+    url: '/oa/field',
39
+    method: 'put',
40
+    data: data
41
+  })
42
+}
43
+
44
+// 删除cmc专业领域
45
+export function delField(fieldId) {
46
+  return request({
47
+    url: '/oa/field/' + fieldId,
48
+    method: 'delete'
49
+  })
50
+}

+ 3
- 3
oa-ui/src/views/login.vue Voir le fichier

@@ -2,7 +2,7 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2024-01-03 09:23:11
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2024-06-12 17:34:58
5
+ * @LastEditTime: 2025-03-25 16:52:11
6 6
 -->
7 7
 <template>
8 8
   <el-row class="login-wrapper">
@@ -14,7 +14,7 @@
14 14
     </el-col>
15 15
     <el-col :xs="18" class="login-box">
16 16
       <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
17
-        <h3 class="title">CMC综合办公系统</h3>
17
+        <h3 class="title">CMC智联云枢办公系统</h3>
18 18
         <el-form-item prop="username">
19 19
           <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
20 20
             <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
@@ -207,7 +207,7 @@ export default {
207 207
   padding: 0 20px;
208 208
 
209 209
   .title {
210
-    font-size: 40px;
210
+    font-size: 30px;
211 211
     margin-bottom: 40px;
212 212
     color: #504d4d;
213 213
     font-family: 'CMCTitle';

+ 245
- 0
oa-ui/src/views/oa/study/components/resourceTree.vue Voir le fichier

@@ -0,0 +1,245 @@
1
+<template>
2
+  <div>
3
+    <el-row :gutter="10" class="mb8">
4
+      <el-col :span="1.5">
5
+        <el-button type="primary" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">展开/折叠</el-button>
6
+      </el-col>
7
+    </el-row>
8
+    <el-input v-model="filterText" placeholder="输入关键字过滤" />
9
+    <el-tree v-if="refreshTable" ref="tree" :data="treeData" :props="defaultProps" node-key="fieldId"
10
+      :default-expanded-keys="[1, 2, 3, 4]" @node-click="handleNodeClick" :highlight-current="true"
11
+      :filter-node-method="filterNode" :default-expand-all="isExpandAll" :expand-on-click-node="false">
12
+      <!-- 自定义节点样式 -->
13
+      <span class="custom-tree-node" slot-scope="{ node, data }">
14
+        <span>{{ node.label }}</span>
15
+        <span v-if="isModify">
16
+          <el-button v-hasPermi="['oa:resource:edit']" type="text" icon="el-icon-plus" size="mini" @click="() => append(data)">
17
+            新增
18
+          </el-button>
19
+          <el-button v-hasPermi="['oa:resource:remove']" type="text" icon="el-icon-delete" size="mini" @click="() => remove(node, data)">
20
+            删除
21
+          </el-button>
22
+        </span>
23
+      </span>
24
+    </el-tree>
25
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
26
+      <el-form ref="formRef" :model="form" :rules="rules">
27
+        <el-form-item label="父级专业" prop="parentId">
28
+          <treeselect v-model="form.parentId" :options="treeData" :normalizer="normalizer" :show-count="true"
29
+            placeholder="选择上级专业" />
30
+        </el-form-item>
31
+        <el-form-item label="专业名称" prop="field">
32
+          <el-input v-model="form.field" placeholder="请输入专业名称" />
33
+        </el-form-item>
34
+      </el-form>
35
+      <div slot="footer" class="dialog-footer">
36
+        <el-button @click="open = false">取 消</el-button>
37
+        <el-button type="primary" @click="submitForm">确 定</el-button>
38
+      </div>
39
+    </el-dialog>
40
+  </div>
41
+</template>
42
+
43
+<script>
44
+import { listField, getField, delField, addField, updateField } from "@/api/oa/study/resourceField";
45
+import { listResource, getResource, delResource, addResource, updateResource } from "@/api/oa/study/resource";
46
+import Treeselect from "@riophae/vue-treeselect";
47
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
48
+export default {
49
+  components: { Treeselect },
50
+  props: {
51
+    isModify: Boolean,
52
+    default: true
53
+  },
54
+  data() {
55
+    return {
56
+      treeData: [],       // 树形结构数据
57
+      defaultProps: {     // 树形组件配置
58
+        children: 'children',
59
+        label: 'field'
60
+      },
61
+      filterText: '',
62
+      isExpandAll: false,
63
+      refreshTable: true,
64
+      title: '',
65
+      open: false,
66
+      form: {
67
+        fieldId: undefined,
68
+        field: "",
69
+        parentId: undefined,
70
+      },
71
+      rules: {
72
+        field: [
73
+          { required: true, message: "专业名称不能为空", trigger: "blur" }
74
+        ],
75
+        parentId: [
76
+          { required: true, message: "父级专业不能为空", trigger: "change" }
77
+        ]
78
+      },
79
+      // 菜单树选项
80
+      menuOptions: [],
81
+    }
82
+  },
83
+  watch: {
84
+    filterText(val) {
85
+      this.$refs.tree.filter(val);
86
+    }
87
+  },
88
+  created() {
89
+    this.initTree();
90
+  },
91
+  methods: {
92
+    async initTree() {
93
+      const response = await listField({ pageSize: 9999 });
94
+      this.treeData = [{
95
+        fieldId: 0,
96
+        field: '全部专业',
97
+        children: []
98
+      }]
99
+      this.treeData[0].children = this.buildTree(response.rows);
100
+      this.$emit('getTreeData', this.buildTree(response.rows))
101
+    },
102
+    buildTree(items) {
103
+      const map = {};      // 哈希表存储所有节点
104
+      const roots = [];     // 存储根节点
105
+      // 先遍历所有项,存入哈希表
106
+      items.forEach(item => {
107
+        map[item.fieldId] = { ...item, children: [] };
108
+      });
109
+      // 再次遍历建立父子关系
110
+      items.forEach(item => {
111
+        const node = map[item.fieldId];
112
+        if (item.parentId === 0) {
113
+          roots.push(node);
114
+        } else {
115
+          const parent = map[item.parentId];
116
+          if (parent) {
117
+            parent.children.push(node);
118
+          }
119
+        }
120
+      });
121
+      return roots;
122
+    },
123
+    filterNode(value, data) {
124
+      if (!value) return true;
125
+      return data.field.indexOf(value) !== -1;
126
+    },
127
+    async loadNode(node, resolve) {
128
+      if (node.level === 0) {
129
+        // 加载根节点
130
+        return resolve(await this.fetchRootNodes());
131
+      }
132
+      // 加载子节点
133
+      resolve(await this.fetchChildNodes(node.key));
134
+    },
135
+    handleNodeClick(data) {
136
+      if (data.fieldId == 0) {
137
+        this.$emit('clickNode', {})
138
+      } else {
139
+        this.$emit('clickNode', data)
140
+      }
141
+    },
142
+    append(data) {
143
+      this.resetForm();
144
+      this.title = "新增专业";
145
+      this.open = true;
146
+      this.form.parentId = data.fieldId; // 设置父节点为当前节点
147
+    },
148
+    async remove(node, data) {
149
+      if (!data.children) {
150
+        data.children = []
151
+      }
152
+      let list = await listResource({ fieldId: data.fieldId });
153
+      this.$confirm('确定删除该专业吗?', "警告", {
154
+        confirmButtonText: "确定",
155
+        cancelButtonText: "取消",
156
+        type: "warning"
157
+      }).then(() => {
158
+        if (data.children.length > 0) {
159
+          this.$message.error("删除失败,存在子专业,无法删除!");
160
+          return
161
+        }
162
+        if (list.total > 0) {
163
+          this.$message.error("删除失败,存在资料数据,无法删除!");
164
+          return
165
+        }
166
+        delField(data.fieldId).then(() => {
167
+          this.$message.success("删除成功");
168
+          this.initTree();
169
+          // 如果删除的是当前选中节点,清空选择
170
+          if (this.$refs.tree.getCurrentKey() === data.fieldId) {
171
+            this.$emit("clickNode", {});
172
+          }
173
+        });
174
+      });
175
+    },
176
+    /** 展开/折叠操作 */
177
+    toggleExpandAll() {
178
+      this.refreshTable = false;
179
+      this.isExpandAll = !this.isExpandAll;
180
+      this.$nextTick(() => {
181
+        this.refreshTable = true;
182
+      });
183
+    },
184
+    // 表单提交
185
+    submitForm() {
186
+      this.$refs.formRef.validate(valid => {
187
+        if (valid) {
188
+          if (this.form.fieldId) {
189
+            updateField(this.form).then(() => {
190
+              this.$message.success("修改成功");
191
+              this.open = false;
192
+              this.initTree();
193
+            });
194
+          } else {
195
+            addField(this.form).then(() => {
196
+              this.$message.success("新增成功");
197
+              this.open = false;
198
+              this.initTree();
199
+            });
200
+          }
201
+        }
202
+      });
203
+    },
204
+    // 重置表单
205
+    resetForm() {
206
+      this.form = {
207
+        fieldId: undefined,
208
+        field: "",
209
+        parentId: undefined
210
+      };
211
+      if (this.$refs.formRef) {
212
+        this.$refs.formRef.resetFields();
213
+      }
214
+    },
215
+
216
+    /** 转换菜单数据结构 */
217
+    normalizer(node) {
218
+      if (node.children && !node.children.length) {
219
+        delete node.children;
220
+      }
221
+      return {
222
+        id: node.fieldId,
223
+        label: node.field,
224
+        children: node.children
225
+      };
226
+    },
227
+  },
228
+}
229
+</script>
230
+
231
+<style lang="scss" scoped>
232
+.tree-container {
233
+  width: 300px;
234
+  padding: 20px;
235
+}
236
+
237
+.custom-tree-node {
238
+  flex: 1;
239
+  display: flex;
240
+  align-items: center;
241
+  justify-content: space-between;
242
+  font-size: 14px;
243
+  padding: 8px 0;
244
+}
245
+</style>

+ 71
- 17
oa-ui/src/views/oa/study/components/studyRight.vue Voir le fichier

@@ -2,11 +2,42 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2025-03-05 15:36:17
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-03-13 16:13:05
5
+ * @LastEditTime: 2025-03-25 16:50:59
6 6
 -->
7 7
 <template>
8
-  <div class="right-box">
9
-    <div class="video">
8
+  <div>
9
+    <el-row :gutter="20">
10
+      <el-col :span="8">
11
+        <resource-tree :isModify="false" @clickNode="queryField"></resource-tree>
12
+      </el-col>
13
+      <el-col :span="16">
14
+        <el-form :model="videoParams" size="small" :inline="true" label-width="68px" @submit.native.prevent>
15
+          <el-form-item label="资料名称" prop="title">
16
+            <el-input v-model="videoParams.title" placeholder="请输入资料名称" clearable
17
+              @keyup.enter.native="handleVideoQuery" />
18
+          </el-form-item>
19
+          <el-form-item>
20
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleVideoQuery">搜索</el-button>
21
+          </el-form-item>
22
+        </el-form>
23
+        <el-table :data="videoList" style="width: 100%">
24
+          <el-table-column align="center" label="序号" type="index" />
25
+          <el-table-column align="center" label="名称" prop="title" />
26
+          <el-table-column align="center" label="学时" prop="hours" />
27
+          <el-table-column align="center" label="操作">
28
+            <template slot-scope="{row}">
29
+              <el-button type="text" @click="addToStudy(row)">
30
+                添加课程
31
+              </el-button>
32
+            </template>
33
+          </el-table-column>
34
+        </el-table>
35
+        <pagination v-show="videoTotal > 0" :total="videoTotal" :page.sync="videoParams.pageNum"
36
+          :layout="'total, prev, pager, next,jumper'" :limit.sync="videoParams.pageSize" :autoScroll="false"
37
+          @pagination="getVideoList" />
38
+      </el-col>
39
+    </el-row>
40
+    <!-- <div class="video">
10 41
       <el-tabs v-model="videoTab" type="card">
11 42
         <el-form :model="videoParams" size="small" :inline="true" label-width="68px" @submit.native.prevent>
12 43
           <el-form-item label="视频名称" prop="title">
@@ -28,12 +59,12 @@
28 59
                   添加课程
29 60
                 </el-button>
30 61
               </template>
31
-            </el-table-column>
32
-          </el-table>
33
-          <pagination v-show="videoTotal > 0" :total="videoTotal" :page.sync="videoParams.pageNum"
34
-            :layout="'total, prev, pager, next,jumper'" :limit.sync="videoParams.pageSize" :autoScroll="false"
35
-            @pagination="getVideoList" />
36
-        </el-tab-pane>
62
+      </el-table-column>
63
+      </el-table>
64
+      <pagination v-show="videoTotal > 0" :total="videoTotal" :page.sync="videoParams.pageNum"
65
+        :layout="'total, prev, pager, next,jumper'" :limit.sync="videoParams.pageSize" :autoScroll="false"
66
+        @pagination="getVideoList" />
67
+      </el-tab-pane>
37 68
       </el-tabs>
38 69
     </div>
39 70
     <div class="pdf">
@@ -53,10 +84,10 @@
53 84
             <el-table-column align="center" label="学时" prop="hours" />
54 85
             <el-table-column align="center" label="操作">
55 86
               <template slot-scope="{row}">
56
-                <el-button type="text" @click="addToStudy(row)">
57
-                  添加课程
58
-                </el-button>
59
-              </template>
87
+                    <el-button type="text" @click="addToStudy(row)">
88
+                      添加课程
89
+                    </el-button>
90
+                  </template>
60 91
             </el-table-column>
61 92
           </el-table>
62 93
           <pagination v-show="pdfTotal > 0" :total="pdfTotal" :page.sync="pdfParams.pageNum"
@@ -64,15 +95,17 @@
64 95
             @pagination="getPdfList" />
65 96
         </el-tab-pane>
66 97
       </el-tabs>
67
-    </div>
98
+    </div> -->
68 99
   </div>
69 100
 </template>
70 101
 
71 102
 <script>
72
-import { listResource, getResource, delResource, addResource, updateResource } from "@/api/oa/study/resource";
103
+import { listResource, getResource, delResource, addResource, updateResource, getListBelow } from "@/api/oa/study/resource";
73 104
 import { listStudy, getStudy, delStudy, addStudy, updateStudy } from "@/api/oa/study/myStudy";
105
+import resourceTree from './resourceTree.vue';
74 106
 
75 107
 export default {
108
+  components: { resourceTree },
76 109
   data() {
77 110
     return {
78 111
       videoList: [],
@@ -91,12 +124,25 @@ export default {
91 124
   },
92 125
   methods: {
93 126
     getVideoList() {
94
-      this.videoParams.type = '视频'
127
+      // this.videoParams.type = '视频'
128
+      listResource(this.videoParams).then(response => {
129
+        this.videoList = response.rows;
130
+        this.videoTotal = response.total;
131
+      });
132
+    },
133
+    getList() {
95 134
       listResource(this.videoParams).then(response => {
96 135
         this.videoList = response.rows;
97 136
         this.videoTotal = response.total;
98 137
       });
99 138
     },
139
+    getAllListByFiedldId() {
140
+      this.loading = true;
141
+      getListBelow(this.videoParams).then(response => {
142
+        this.videoList = response.rows;
143
+        this.videoTotal = response.total;
144
+      })
145
+    },
100 146
     getPdfList() {
101 147
       this.pdfParams.type = '文档'
102 148
       listResource(this.pdfParams).then(response => {
@@ -131,7 +177,15 @@ export default {
131 177
           this.$emit('refreshList');
132 178
         });
133 179
       })
134
-
180
+    },
181
+    queryField(data) {
182
+      if (data.fieldId) {
183
+        this.videoParams.fieldId = data.fieldId
184
+        this.getAllListByFiedldId();
185
+      } else {
186
+        this.videoParams.fieldId = null
187
+        this.getList();
188
+      }
135 189
     }
136 190
   },
137 191
 }

+ 1
- 17
oa-ui/src/views/oa/study/myStudy.vue Voir le fichier

@@ -2,27 +2,11 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2025-03-05 14:00:18
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-03-12 10:43:08
5
+ * @LastEditTime: 2025-03-25 14:12:17
6 6
 -->
7 7
 <template>
8 8
   <div>
9 9
     <study-head></study-head>
10
-    <!-- <div class="main app-contrainer">
11
-      <div class="left">
12
-        <div class="title">
13
-          我的学习记录
14
-          <div class="line"></div>
15
-        </div>
16
-        <study-left ref="studyLeft"></study-left>
17
-      </div>
18
-      <div class="right">
19
-        <div class="title">
20
-          学习资料库
21
-          <div class="line"></div>
22
-        </div>
23
-        <study-right ref="studyRight" @refreshList="getStudyList"></study-right>
24
-      </div>
25
-    </div> -->
26 10
     <div class="main app-container">
27 11
       <el-row>
28 12
         <el-col :md="12" :sm="24" class="left">

+ 262
- 140
oa-ui/src/views/oa/study/resource.vue Voir le fichier

@@ -2,154 +2,187 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2025-03-05 09:15:54
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-03-12 10:02:46
5
+ * @LastEditTime: 2025-03-25 13:59:38
6 6
 -->
7 7
 <template>
8 8
   <div class="app-container">
9
-    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
10
-      <el-form-item label="资料名称" prop="title">
11
-        <el-input v-model="queryParams.title" placeholder="请输入资料名称" clearable @keyup.enter.native="handleQuery" />
12
-      </el-form-item>
13
-      <el-form-item label="上传人" prop="uploader">
14
-        <el-input v-model="queryParams.uploader" placeholder="请输入上传人" clearable @keyup.enter.native="handleQuery" />
15
-      </el-form-item>
16
-      <el-form-item label="上传部门" prop="uploadDept">
17
-        <el-input v-model="queryParams.uploadDept" placeholder="请输入上传部门" clearable @keyup.enter.native="handleQuery" />
18
-      </el-form-item>
19
-      <el-form-item label="专业领域" prop="field">
20
-        <el-input v-model="queryParams.field" placeholder="请输入专业领域" clearable @keyup.enter.native="handleQuery" />
21
-      </el-form-item>
22
-      <el-form-item label="上传时间" prop="uploadTime">
23
-        <el-date-picker clearable v-model="queryParams.uploadTime" type="date" value-format="yyyy-MM-dd"
24
-          placeholder="请选择上传时间">
25
-        </el-date-picker>
26
-      </el-form-item>
27
-      <el-form-item>
28
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
29
-        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
30
-      </el-form-item>
31
-    </el-form>
32
-
33
-    <el-row :gutter="10" class="mb8">
34
-      <el-col :span="1.5">
35
-        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
36
-          v-hasPermi="['oa:resource:add']">新增</el-button>
37
-      </el-col>
38
-      <el-col :span="1.5">
39
-        <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
40
-          v-hasPermi="['oa:resource:edit']">修改</el-button>
41
-      </el-col>
42
-      <el-col :span="1.5">
43
-        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
44
-          v-hasPermi="['oa:resource:remove']">删除</el-button>
45
-      </el-col>
46
-      <el-col :span="1.5">
47
-        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
48
-          v-hasPermi="['oa:resource:export']">导出</el-button>
9
+    <el-row :gutter="20">
10
+      <el-col :span="6">
11
+        <el-row>
12
+          <div class="title">
13
+            专业领域
14
+            <div class="line"></div>
15
+          </div>
16
+          <resource-tree @getTreeData="getTreeDataFn" @clickNode="queryField">
17
+          </resource-tree>
18
+        </el-row>
49 19
       </el-col>
50
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
51
-    </el-row>
20
+      <el-col :span="18">
21
+        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
22
+          label-width="68px">
23
+          <el-form-item label="资料名称" prop="title">
24
+            <el-input v-model="queryParams.title" placeholder="请输入资料名称" clearable @keyup.enter.native="handleQuery" />
25
+          </el-form-item>
26
+          <el-form-item label="上传人" prop="uploader">
27
+            <el-select v-model="queryParams.uploader" filterable clearable @change="handleQuery">
28
+              <el-option v-for="item in $store.state.user.userList" :key="item.userId" :label="item.nickName"
29
+                :value="item.userId">
30
+              </el-option>
31
+            </el-select>
32
+          </el-form-item>
33
+          <el-form-item label="上传部门" prop="uploadDept">
34
+            <el-select v-model="queryParams.uploadDept" filterable clearable @change="handleQuery">
35
+              <el-option v-for="item in $store.state.user.deptList" :key="item.deptId" :label="item.deptName"
36
+                :value="item.deptId">
37
+              </el-option>
38
+            </el-select>
39
+          </el-form-item>
40
+          <el-form-item label="上传时间" prop="uploadTime">
41
+            <el-date-picker clearable v-model="queryParams.uploadTime" type="date" value-format="yyyy-MM-dd"
42
+              placeholder="请选择上传时间">
43
+            </el-date-picker>
44
+          </el-form-item>
45
+          <el-form-item>
46
+            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
47
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
48
+          </el-form-item>
49
+        </el-form>
50
+
51
+        <el-row :gutter="10" class="mb8">
52
+          <el-col :span="1.5">
53
+            <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
54
+              v-hasPermi="['oa:resource:add']">新增</el-button>
55
+          </el-col>
56
+          <el-col :span="1.5">
57
+            <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
58
+              v-hasPermi="['oa:resource:edit']">修改</el-button>
59
+          </el-col>
60
+          <el-col :span="1.5">
61
+            <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
62
+              v-hasPermi="['oa:resource:remove']">删除</el-button>
63
+          </el-col>
64
+          <el-col :span="1.5">
65
+            <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
66
+              v-hasPermi="['oa:resource:export']">导出</el-button>
67
+          </el-col>
68
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
69
+        </el-row>
52 70
 
53
-    <el-table v-loading="loading" :data="resourceList" @selection-change="handleSelectionChange">
54
-      <el-table-column type="selection" width="55" align="center" />
55
-      <el-table-column label="资料id" align="center" prop="resourceId" />
56
-      <el-table-column label="上传人" align="center" prop="uploader">
57
-        <template slot-scope="scope">
58
-          {{ getUserName(scope.row.uploader) }}
59
-        </template>
60
-      </el-table-column>
61
-      <el-table-column label="上传部门" align="center" prop="uploadDept">
62
-        <template slot-scope="scope">
63
-          {{ getDeptName(scope.row.uploadDept) }}
64
-        </template>
65
-      </el-table-column>
66
-      <el-table-column label="标题" align="center" prop="title" />
67
-      <el-table-column label="上传附件" align="center" prop="sourcePath" :formatter="formatterPath" />
68
-      <el-table-column label="专业领域" align="center" prop="field" />
69
-      <el-table-column label="类型" align="center" prop="type" />
70
-      <el-table-column label="上传时间" align="center" prop="uploadTime" width="180">
71
-        <template slot-scope="scope">
72
-          <span>{{ parseTime(scope.row.uploadTime, '{y}-{m}-{d}') }}</span>
73
-        </template>
74
-      </el-table-column>
75
-      <el-table-column label="学时" align="center" prop="hours" />
76
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
77
-        <template slot-scope="scope">
78
-          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
79
-            v-hasPermi="['oa:resource:edit']">修改</el-button>
80
-          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
81
-            v-hasPermi="['oa:resource:remove']">删除</el-button>
82
-        </template>
83
-      </el-table-column>
84
-    </el-table>
71
+        <el-table v-loading="loading" :data="resourceList" @selection-change="handleSelectionChange">
72
+          <el-table-column type="selection" width="55" align="center" />
73
+          <el-table-column label="资料id" align="center" prop="resourceId" />
74
+          <el-table-column label="上传人" align="center" prop="uploader">
75
+            <template slot-scope="scope">
76
+              {{ getUserName(scope.row.uploader) }}
77
+            </template>
78
+          </el-table-column>
79
+          <el-table-column label="上传部门" align="center" prop="uploadDept">
80
+            <template slot-scope="scope">
81
+              {{ getDeptName(scope.row.uploadDept) }}
82
+            </template>
83
+          </el-table-column>
84
+          <el-table-column label="资料名称" align="center" prop="title" />
85
+          <el-table-column label="上传附件" align="center" prop="sourcePath" :formatter="formatterPath" />
86
+          <el-table-column label="专业领域" align="center" prop="field" />
87
+          <el-table-column label="类型" align="center" prop="type" />
88
+          <el-table-column label="上传时间" align="center" prop="uploadTime" width="180">
89
+            <template slot-scope="scope">
90
+              <span>{{ parseTime(scope.row.uploadTime, '{y}-{m}-{d}') }}</span>
91
+            </template>
92
+          </el-table-column>
93
+          <el-table-column label="学时" align="center" prop="hours" />
94
+          <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
95
+            <template slot-scope="scope">
96
+              <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
97
+                v-hasPermi="['oa:resource:edit']">修改</el-button>
98
+              <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
99
+                v-hasPermi="['oa:resource:remove']">删除</el-button>
100
+            </template>
101
+          </el-table-column>
102
+        </el-table>
85 103
 
86
-    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
87
-      @pagination="getList" />
104
+        <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
105
+          :limit.sync="queryParams.pageSize" @pagination="getList" />
88 106
 
89
-    <!-- 添加或修改cmc学习资料对话框 -->
90
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
91
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
92
-        <el-form-item label="资料名称" prop="title">
93
-          <el-input v-model="form.title" placeholder="请输入资料名称" />
94
-        </el-form-item>
95
-        <el-form-item label="上传附件" prop="sourcePath">
96
-          <FileUpload v-if="form.sourcePath == null || form.sourcePath == ''" :isShowTip="false" :limit="1"
97
-            :filePathName="'教育学习/学习资料'" :fileType="['pdf', 'mp4']" :fileSize="10240" @input="getDocumentPath">
98
-          </FileUpload>
99
-          <div v-if="form.sourcePath">
100
-            <el-link type="primary" @click="reviewWord(`${baseUrl}${'/profile/upload' + form.sourcePath}`)">
101
-              {{ getFileName(form.sourcePath) }}
102
-            </el-link>
103
-            <el-link class="ml20" type="warning" :href="`${baseUrl}${'/profile/upload' + form.sourcePath}`"
104
-              :underline="false" target="_blank">
105
-              <span class="el-icon-download">下载文件</span>
106
-            </el-link>
107
-            <el-link class="ml20" type="danger" @click="handleDeleteDocument" :underline="false"
108
-              v-hasPermi="['oa:resource:edit']">
109
-              <span class="el-icon-delete">删除文件</span>
110
-            </el-link>
111
-            <!-- <FileUpload v-if="taskName == '参培申请'" :limit="1" :filePathName="'参培/佐证附件'"
107
+        <!-- 添加或修改cmc学习资料对话框 -->
108
+        <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
109
+          <el-form ref="form" :model="form" :rules="rules" label-width="80px">
110
+            <el-form-item label="资料名称" prop="title">
111
+              <el-input v-model="form.title" placeholder="请输入资料名称" />
112
+            </el-form-item>
113
+            <el-form-item label="上传附件" prop="sourcePath">
114
+              <FileUpload v-if="form.sourcePath == null || form.sourcePath == ''" :isShowTip="false" :limit="1"
115
+                :filePathName="'教育学习/学习资料'" :fileType="['pdf', 'mp4']" :fileSize="10240" @input="getDocumentPath">
116
+              </FileUpload>
117
+              <div v-if="form.sourcePath">
118
+                <el-link type="primary" @click="reviewWord(`${baseUrl}${'/profile/upload' + form.sourcePath}`)">
119
+                  {{ getFileName(form.sourcePath) }}
120
+                </el-link>
121
+                <el-link class="ml20" type="warning" :href="`${baseUrl}${'/profile/upload' + form.sourcePath}`"
122
+                  :underline="false" target="_blank">
123
+                  <span class="el-icon-download">下载文件</span>
124
+                </el-link>
125
+                <el-link class="ml20" type="danger" @click="handleDeleteDocument" :underline="false"
126
+                  v-hasPermi="['oa:resource:edit']">
127
+                  <span class="el-icon-delete">删除文件</span>
128
+                </el-link>
129
+                <!-- <FileUpload v-if="taskName == '参培申请'" :limit="1" :filePathName="'参培/佐证附件'"
112 130
               :fileType="['doc', 'docx', 'xls', 'xlsx', 'pdf', 'rar', 'zip']" @input="getDocumentPath"></FileUpload> -->
131
+              </div>
132
+              <div style="font-size:12px;color:#e45656">
133
+                tips:文档仅支持pdf格式,视频仅支持mp4格式
134
+              </div>
135
+            </el-form-item>
136
+            <el-form-item label="资料类型" prop="type">
137
+              <el-select v-model="form.type" clearable>
138
+                <el-option label="视频" value="视频"></el-option>
139
+                <el-option label="文档" value="文档"></el-option>
140
+              </el-select>
141
+            </el-form-item>
142
+            <el-form-item label="专业领域" prop="fieldId">
143
+              <!-- <el-input v-model="form.fieldId" placeholder="请输入专业领域" /> -->
144
+              <!-- <el-cascader :options="fieldOptions" v-model="form.fieldId" :show-all-levels="false"
145
+                :props="{ children: 'children', label: 'field', value: 'fieldId' }">
146
+                <template slot-scope="{ node, data }">
147
+                  <span>{{ data.field }}</span>
148
+                </template>
149
+              </el-cascader> -->
150
+              <el-tag>{{ form.field }}</el-tag>
151
+              <el-tree ref="fieldIdTree" class="tree-border" :data="fieldOptions" show-checkbox
152
+                :default-expanded-keys="this.form.fieldId ? [this.form.fieldId] : []" node-key="fieldId"
153
+                empty-text="加载中,请稍候" :check-strictly="true" @check="handleChechChange"
154
+                :props="{ children: 'children', label: 'field', value: 'fieldId' }">
155
+              </el-tree>
156
+            </el-form-item>
157
+            <el-form-item label="学时" prop="hours">
158
+              <el-input-number v-model="form.hours" :min="0" :precision="1" />
159
+            </el-form-item>
160
+            <el-form-item label="上传人" prop="uploader">
161
+              {{ getUserName(form.uploader) }}
162
+            </el-form-item>
163
+            <el-form-item label="上传部门" prop="uploadDept">
164
+              {{ getDeptName(form.uploadDept) }}
165
+            </el-form-item>
166
+            <el-form-item label="上传时间" prop="uploadTime">
167
+              {{ form.uploadTime }}
168
+            </el-form-item>
169
+          </el-form>
170
+          <div slot="footer" class="dialog-footer">
171
+            <el-button type="primary" @click="submitForm">确 定</el-button>
172
+            <el-button @click="cancel">取 消</el-button>
113 173
           </div>
114
-          <div style="font-size:12px;color:#e45656">
115
-            tips:文档仅支持pdf格式,视频仅支持mp4格式
116
-          </div>
117
-        </el-form-item>
118
-        <el-form-item label="资料类型" prop="type">
119
-          <el-select v-model="form.type" clearable>
120
-            <el-option label="视频" value="视频"></el-option>
121
-            <el-option label="文档" value="文档"></el-option>
122
-          </el-select>
123
-        </el-form-item>
124
-        <el-form-item label="专业领域" prop="field">
125
-          <el-input v-model="form.field" placeholder="请输入专业领域" />
126
-        </el-form-item>
127
-        <el-form-item label="学时" prop="hours">
128
-          <el-input-number v-model="form.hours" :min="0" :precision="1" />
129
-        </el-form-item>
130
-        <el-form-item label="上传人" prop="uploader">
131
-          {{ getUserName(form.uploader) }}
132
-        </el-form-item>
133
-        <el-form-item label="上传部门" prop="uploadDept">
134
-          {{ getDeptName(form.uploadDept) }}
135
-        </el-form-item>
136
-        <el-form-item label="上传时间" prop="uploadTime">
137
-          {{ form.uploadTime }}
138
-        </el-form-item>
139
-      </el-form>
140
-      <div slot="footer" class="dialog-footer">
141
-        <el-button type="primary" @click="submitForm">确 定</el-button>
142
-        <el-button @click="cancel">取 消</el-button>
143
-      </div>
144
-    </el-dialog>
174
+        </el-dialog>
175
+      </el-col>
176
+    </el-row>
145 177
   </div>
146 178
 </template>
147 179
 
148 180
 <script>
149
-import { listResource, getResource, delResource, addResource, updateResource } from "@/api/oa/study/resource";
181
+import { listResource, getResource, delResource, addResource, updateResource, getListBelow } from "@/api/oa/study/resource";
150 182
 import { parseTime } from "@/utils/ruoyi";
151
-
183
+import resourceTree from './components/resourceTree.vue';
152 184
 export default {
185
+  components: { resourceTree },
153 186
   name: "Resource",
154 187
   data() {
155 188
     return {
@@ -180,7 +213,7 @@ export default {
180 213
         uploadDept: null,
181 214
         title: null,
182 215
         sourcePath: null,
183
-        field: null,
216
+        fieldId: null,
184 217
         type: null,
185 218
         uploadTime: null,
186 219
         hours: null
@@ -188,8 +221,10 @@ export default {
188 221
       // 表单参数
189 222
       form: {},
190 223
       // 表单校验
191
-      rules: {
192
-      }
224
+      rules: {},
225
+      treeData: [],
226
+      fieldOptions: [],
227
+      currentCheckedKey: null,
193 228
     };
194 229
   },
195 230
   watch: {
@@ -205,7 +240,7 @@ export default {
205 240
       } else {
206 241
         this.form.type = ''
207 242
       }
208
-    }
243
+    },
209 244
   },
210 245
   created() {
211 246
     this.getList();
@@ -220,6 +255,14 @@ export default {
220 255
         this.loading = false;
221 256
       });
222 257
     },
258
+    getAllListByFiedldId() {
259
+      this.loading = true;
260
+      getListBelow(this.queryParams).then(response => {
261
+        this.resourceList = response.rows;
262
+        this.total = response.total;
263
+        this.loading = false;
264
+      })
265
+    },
223 266
     // 取消按钮
224 267
     cancel() {
225 268
       this.open = false;
@@ -233,7 +276,7 @@ export default {
233 276
         uploadDept: null,
234 277
         title: null,
235 278
         sourcePath: null,
236
-        field: null,
279
+        fieldId: null,
237 280
         type: null,
238 281
         uploadTime: null,
239 282
         hours: null
@@ -264,6 +307,9 @@ export default {
264 307
       this.form.uploadDept = this.$store.getters.deptId;
265 308
       this.form.uploadTime = parseTime(new Date(), '{y}-{m}-{d}');
266 309
       this.title = "新增学习资料";
310
+      this.$nextTick(() => {
311
+        this.$refs.fieldIdTree.setCheckedKeys([]);
312
+      });
267 313
     },
268 314
     /** 修改按钮操作 */
269 315
     handleUpdate(row) {
@@ -272,11 +318,16 @@ export default {
272 318
       getResource(resourceId).then(response => {
273 319
         this.form = response.data;
274 320
         this.open = true;
275
-        this.title = "修改cmc学习资料";
321
+        this.title = "修改学习资料";
322
+        console.log(this.$refs.fieldIdTree);
323
+        this.$nextTick(() => {
324
+          this.$refs.fieldIdTree.setCheckedKeys([this.form.fieldId]);
325
+        });
276 326
       });
277 327
     },
278 328
     /** 提交按钮 */
279 329
     submitForm() {
330
+      console.log(this.form);
280 331
       this.$refs["form"].validate(valid => {
281 332
         if (valid) {
282 333
           if (this.form.resourceId != null) {
@@ -326,7 +377,78 @@ export default {
326 377
     formatterPath(row) {
327 378
       let name = this.getFileName(row.sourcePath)
328 379
       return name
380
+    },
381
+    queryField(data) {
382
+      if (data.fieldId) {
383
+        this.queryParams.fieldId = data.fieldId
384
+        this.getAllListByFiedldId();
385
+      } else {
386
+        this.queryParams.fieldId = null
387
+        this.getList();
388
+      }
389
+    },
390
+    getTreeDataFn(data) {
391
+      this.fieldOptions = this.removeEmptyChildren(data);
392
+    },
393
+    removeEmptyChildren(arr) {
394
+      return arr.map(item => {
395
+        // 创建新对象(不修改原对象)
396
+        const newItem = { ...item };
397
+        // 递归处理子节点
398
+        if (newItem.children && Array.isArray(newItem.children)) {
399
+          if (newItem.children.length === 0) {
400
+            delete newItem.children; // 删除空数组属性
401
+          } else {
402
+            newItem.children = this.removeEmptyChildren(newItem.children); // 递归处理子节点
403
+          }
404
+        }
405
+
406
+        return newItem;
407
+      });
408
+    },
409
+    handleChechChange(currentNode, checkedStatus) {
410
+      const checkedKeys = checkedStatus.checkedKeys;
411
+      let currentId = currentNode.fieldId;
412
+      // 如果选中超过1个节点
413
+      if (checkedKeys.length > 1) {
414
+        // 保留最后一个选中的节点
415
+        const lastKey = checkedKeys.filter(item => item == currentId);
416
+        this.$refs.fieldIdTree.setCheckedKeys([lastKey]);
417
+        this.form.fieldId = currentId
418
+        this.form.field = currentNode.field;
419
+        return;
420
+      }
421
+      // 如果取消选中当前节点
422
+      if (checkedKeys.length === 0) {
423
+        this.currentCheckedKey = null;
424
+        this.form.fieldId = null;
425
+        this.form.field = null;
426
+      } else {
427
+        this.currentCheckedKey = checkedKeys[0];
428
+        this.form.fieldId = currentId;
429
+        this.form.field = currentNode.field;
430
+      }
329 431
     }
330 432
   }
331
-};
433
+}
332 434
 </script>
435
+
436
+<style lang="scss" scoped>
437
+.title {
438
+  position: relative;
439
+  font-weight: bold;
440
+  font-size: 18px;
441
+  padding-left: 40px;
442
+  padding-bottom: 20px;
443
+
444
+  .line {
445
+    position: absolute;
446
+    left: 22px;
447
+    top: 3px;
448
+    width: 5px;
449
+    height: 20px;
450
+    border-radius: 10px;
451
+    background-color: #2893e5;
452
+  }
453
+}
454
+</style>

+ 1
- 1
oa-ui/src/views/register.vue Voir le fichier

@@ -1,7 +1,7 @@
1 1
 <template>
2 2
   <div class="register">
3 3
     <el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form">
4
-      <h3 class="title">CMC综合办公系统</h3>
4
+      <h3 class="title">CMC智联云枢办公系统</h3>
5 5
       <el-form-item prop="username">
6 6
         <el-input v-model="registerForm.username" type="text" auto-complete="off" placeholder="账号">
7 7
           <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />

+ 1
- 1
oa-ui/vue.config.js Voir le fichier

@@ -7,7 +7,7 @@ function resolve(dir) {
7 7
 
8 8
 const CompressionPlugin = require('compression-webpack-plugin')
9 9
 
10
-const name = process.env.VUE_APP_TITLE || 'CMC综合办公系统' // 网页标题
10
+const name = process.env.VUE_APP_TITLE || 'CMC智联云枢办公系统' // 网页标题
11 11
 
12 12
 const port = process.env.port || process.env.npm_config_port || 80 // 端口
13 13
 

Loading…
Annuler
Enregistrer