瀏覽代碼

Merge remote-tracking branch 'origin/master'

humingbo 2 年之前
父節點
當前提交
66498010cf

+ 9 - 1
src/api/system/dept.js

@@ -49,4 +49,12 @@ export function delDept(deptId) {
     url: '/system/dept/' + deptId,
     method: 'delete'
   })
-}
+}
+
+
+export function syncDept() {
+  return request({
+    url: '/system/dept/syncDept' ,
+    method: 'get'
+  })
+}

+ 7 - 0
src/api/system/user.js

@@ -91,3 +91,10 @@ export function updateUserPwd(oldPassword, newPassword) {
     params: data
   })
 }
+
+export function syncUser() {
+  return request({
+    url: '/system/user/syncUser' ,
+    method: 'get'
+  })
+}

+ 77 - 0
src/components/RichTextEditor/index.vue

@@ -0,0 +1,77 @@
+<template>
+  <div style="border: 1px solid #ccc;">
+    <Toolbar
+      style="border-bottom: 1px solid #ccc"
+      :editor="editor"
+      :defaultConfig="toolbarConfig"
+      :mode="mode"
+    />
+    <Editor
+      style="height: 300px; overflow-y: hidden;"
+      v-model="html"
+      :defaultConfig="editorConfig"
+      :mode="mode"
+      @onCreated="onCreated"
+      @onChange="onChange"
+    />
+  </div>
+</template>
+
+<script>
+import {Editor, Toolbar} from '@wangeditor/editor-for-vue'
+
+export default {
+  name: "index",
+  components: {Editor, Toolbar},
+  props: {},
+  data() {
+    return {
+      editor: null,
+      html: undefined,
+      toolbarConfig: {
+        toolbarKeys: [
+          "bold",
+          "underline",
+          "italic",
+          "through",
+          "color",
+          "bgColor",
+          "|",
+          "bulletedList",
+          "numberedList",
+          "justifyLeft",
+          "justifyRight",
+          "justifyCenter",
+          "|",
+          "fullScreen"
+
+        ]
+      },
+      editorConfig: {placeholder: '请输入内容...'},
+      mode: 'simple', // or 'simple'
+    }
+  },
+  watch: {},
+  beforeDestroy() {
+    const editor = this.editor
+    if (editor == null) return
+    editor.destroy() // 组件销毁时,及时销毁编辑器
+  },
+  methods: {
+    onCreated(editor) {
+      this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
+    },
+    onChange(editor) {
+      this.$emit('getHtml', this.html)
+    },
+    clear() {
+      this.html = undefined
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>
+<style src="@wangeditor/editor/dist/css/style.css"></style>

+ 1 - 1
src/views/enforceflow/enforceflow.vue

@@ -473,7 +473,7 @@
 </template>
 
 <script>
-import E from 'wangeditor';
+// import E from 'wangeditor';
 let editor;
 let editorEnforce;
 import Pagination from '@/components/Page/Pagination'

+ 41 - 0
src/views/mixins/editor.js

@@ -0,0 +1,41 @@
+export default {
+  data(){
+    return {
+      editor: null,
+      html: undefined,
+      toolbarConfig: {
+        toolbarKeys: [
+          "bold",
+          "underline",
+          "italic",
+          "through",
+          "color",
+          "bgColor",
+          "|",
+          "bulletedList",
+          "numberedList",
+          "justifyLeft",
+          "justifyRight",
+          "justifyCenter",
+          "|",
+          "fullScreen"
+
+        ]
+      },
+      editorConfig: {placeholder: '请输入内容...'},
+      mode: 'simple', // or 'simple'
+    }
+  },
+  beforeDestroy() {
+    const editor = this.editor
+    if (editor == null) return
+    editor.destroy() // 组件销毁时,及时销毁编辑器
+  },
+  methods: {
+    onCreated(editor) {
+      this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
+    },
+
+
+  }
+}

+ 4 - 2
src/views/system/components/dept.vue

@@ -32,7 +32,7 @@
                 <el-button size="mini" type="primary" @click="handleAdd(data)"
                            v-hasPermi="['system:dept:add']">新增</el-button>
                 <el-button size="mini" @click="handleUpdate(data)" v-hasPermi="['system:dept:edit']">修改</el-button>
-                <el-button size="mini" type="danger" v-hasPermi="['system:dept:delete']">删除</el-button>
+                <el-button size="mini" type="danger" @click="handleDelete(data)" v-hasPermi="['system:dept:delete']">删除</el-button>
                 <i class="el-icon-share" slot="reference"></i>
                </el-popover>
             </span>
@@ -98,7 +98,7 @@
 </template>
 
 <script>
-import {listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild} from "@/api/system/dept";
+import {listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild,syncDept} from "@/api/system/dept";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import {deptTreeSelect} from "@/api/system/user";
@@ -162,6 +162,7 @@ export default {
   methods: {
     /** 查询部门下拉树结构 */
     getDeptTree() {
+      // syncDept()
       deptTreeSelect().then(response => {
         this.deptData = response.data;
       });
@@ -264,6 +265,7 @@ export default {
     },
     /** 删除按钮操作 */
     handleDelete(row) {
+      console.log(row);
       this.$confirm('是否确认删除名称为"' + row.deptName + '"的数据项?').then(function () {
         return delDept(row.id);
       }).then(() => {

+ 24 - 6
src/views/system/user.vue

@@ -46,6 +46,17 @@
             >新增用户
             </el-button>
           </el-col>
+          <el-col :span="1.5">
+            <el-button
+              type="primary"
+              plain
+              icon="el-icon-refresh"
+              size="mini"
+              @click="handleSync"
+              v-hasPermi="['system:user:sync']"
+            >同步用户
+            </el-button>
+          </el-col>
         </el-row>
 
         <el-table :data="userList" size="mini">
@@ -128,7 +139,7 @@
 
     <!-- 添加或修改用户配置对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body :close-on-click-modal="false">
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+      <el-form ref="form" :model="form" :rules="rules" size="mini" label-width="80px">
         <el-row>
           <el-col :span="12">
             <el-form-item label="员工名称" prop="userName">
@@ -214,8 +225,8 @@
         </el-row>
       </el-form>
       <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitForm">确 定</el-button>
-        <el-button @click="cancel">取 消</el-button>
+        <el-button type="primary" size="mini" @click="submitForm">确 定</el-button>
+        <el-button size="mini" @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
 
@@ -231,7 +242,8 @@ import {
   updateUser,
   resetUserPwd,
   changeUserStatus,
-  deptTreeSelect
+  deptTreeSelect,
+  syncUser
 } from "@/api/system/user";
 
 import Dept from './components/dept'
@@ -406,6 +418,10 @@ export default {
         this.form.password = this.initPassword;
       });
     },
+    handleSync() {
+      syncUser()
+    },
+
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
@@ -461,8 +477,10 @@ export default {
     },
     /** 删除按钮操作 */
     handleDelete(row) {
-      const ids = row.id || this.ids;
-      this.$confirm('是否确认删除用户编号为"' + ids + '"的数据项?').then(function () {
+      if(row.fuserId){
+
+      }
+      this.$confirm('是否确认删除用户编号为"' + row.id + '"的数据项?').then(function () {
         return delUser(ids);
       }).then(() => {
         this.getList();

+ 1 - 1
src/views/task/components/taskDetail.vue

@@ -49,7 +49,7 @@
       <el-table-column label="反馈备注">
         <template slot-scope="scope">
           <div>
-            <div>{{ scope.row.description }}</div>
+            <div v-html="scope.row.description"></div>
             <span v-for="(file,index) in scope.row.fileList">
               <a :href="file.url" style="color: darkgreen">
                 <span v-html="file.fileName"></span>

+ 8 - 3
src/views/task/projectView.vue

@@ -100,7 +100,7 @@
               <el-table-column label="反馈备注">
                 <template slot-scope="scope">
                   <div>
-                    <span>{{ scope.row.description }}</span>
+                    <span v-html="scope.row.description"></span>
                     <span v-for="(file,index) in scope.row.fileList">
                                 <a :href="file.url" style="color: darkgreen">
                                   <span v-html="file.fileName"></span>
@@ -116,7 +116,7 @@
       </el-table-column>
     </el-table>
 
-    <el-dialog title="添加评论" :visible.sync="open" width="680px" append-to-body :close-on-click-modal="false">
+    <el-dialog title="添加评论" :visible.sync="open" width="680px" class="feed-dialog" append-to-body @close="cancel">
       <el-form ref="form" :model="form" :rules="rules" size="mini" label-width="100px">
         <el-form-item label="任务名称">
           <div>{{ form.taskName }}</div>
@@ -131,7 +131,8 @@
           <file-upload @getFileUrl="getFileUrl" @removeFile="removeFile"></file-upload>
         </el-form-item>
         <el-form-item label="描述" prop="description">
-          <el-input v-model="form.description" type="textarea" autosize/>
+          <!--          <el-input v-model="form.description" type="textarea" autosize/>-->
+          <rich-text-editor ref="rtEditor" @getHtml="(val)=>form.description=val"></rich-text-editor>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -311,6 +312,7 @@ export default {
     },
     // 取消按钮
     cancel() {
+      this.$refs.rtEditor.clear()
       this.open = false;
       this.reset();
     },
@@ -403,4 +405,7 @@ export default {
   vertical-align: text-top;
 }
 
+.feed-dialog ::v-deep .el-dialog__body {
+  padding: 0 20px 10px 20px;
+}
 </style>

+ 15 - 4
src/views/task/task.vue

@@ -138,7 +138,7 @@
 
 
     <!-- 添加或修改任务配置对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="490px" append-to-body :close-on-click-modal="false">
+    <el-dialog :title="title" :visible.sync="open" width="680px" class="add-dialog" append-to-body @close="cancel">
       <el-form ref="form" :model="form" :rules="rules" size="mini" label-width="110px">
         <el-form-item label="任务名称" prop="taskName">
           <el-input v-model="form.taskName" placeholder="请输入任务名称"/>
@@ -169,7 +169,9 @@
           <file-upload @getFileUrl="getFileUrl" @removeFile="removeFile"></file-upload>
         </el-form-item>
         <el-form-item label="任务描述" prop="description">
-          <el-input v-model="form.description" type="textarea" placeholder="请输入内容"></el-input>
+
+          <!--          <el-input v-model="form.description" type="textarea" placeholder="请输入内容"></el-input>-->
+          <rich-text-editor ref="rtEditor" @getHtml="(val)=>form.description=val"></rich-text-editor>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -284,6 +286,7 @@ import FileUpload from "@/components/FileUpload"
 import Project from "@/views/task/components/project";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import RichTextEditor from '@/components/RichTextEditor'
 
 const statusMap = {
   '0': {name: '待查看', type: 'info'},
@@ -295,7 +298,7 @@ const statusMap = {
 }
 export default {
   name: "Task",
-  components: {Project, TaskDetail, DeptUserTree, FileUpload, Treeselect},
+  components: {Project, TaskDetail, DeptUserTree, FileUpload, Treeselect, RichTextEditor},
   dicts: ['task_status'],
   data() {
     return {
@@ -399,8 +402,11 @@ export default {
     },
     // 取消按钮
     cancel() {
-      this.open = false;
+      this.$refs.dut2.clearText()
+      this.$refs.dut3.clearText()
+      this.$refs.rtEditor.clear()
       this.reset()
+      this.open = false;
     },
     reset() {
       this.form = {
@@ -695,4 +701,9 @@ export default {
   display: flex;
   justify-content: space-between
 }
+
+.add-dialog ::v-deep .el-dialog__body {
+  padding: 0 20px 10px 20px;
+}
+
 </style>

+ 85 - 37
src/views/task/view.vue

@@ -97,7 +97,7 @@
               <el-table-column label="反馈备注">
                 <template slot-scope="scope">
                   <div>
-                    <span>{{ scope.row.description }}</span>
+                    <span v-html="scope.row.description"></span>
                     <span v-for="(file,index) in scope.row.fileList">
                                 <a :href="file.url" style="color: darkgreen">
                                   <span v-html="file.fileName"></span>
@@ -119,40 +119,60 @@
       </el-table-column>
     </el-table>
 
-    <el-dialog title="反馈任务" :visible.sync="open" width="680px" append-to-body :close-on-click-modal="false">
+    <el-dialog title="反馈任务" :visible.sync="open" width="680px" class="feed-dialog" append-to-body @close="cancel">
       <el-form ref="form" :model="form" :rules="rules" size="mini" label-width="100px">
         <el-form-item label="任务名称">
           <div>{{ form.taskName }}</div>
         </el-form-item>
-        <el-form-item label="所属项目">
-          <div>{{ form.projectName }}</div>
-        </el-form-item>
-        <el-form-item label="反馈时间">
-          <div>{{ form.feedbackDate }}</div>
-        </el-form-item>
-        <el-form-item label="反馈类型" prop="feedbackType">
-          <el-radio-group v-model="form.feedbackType" @input="feedbackTypeChange">
-            <el-radio
-              v-for="dict in dict.type.feedback_type"
-              :key="dict.value"
-              :label="dict.value"
-              v-if="dict.value<5"
-            >{{ dict.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="工时" prop="hours">
-          <el-input v-model="form.hours" style="width: 130px"></el-input>
-          <span style="margin-left: 5px">小时</span>
-        </el-form-item>
-        <el-form-item label="进度" prop="value">
-          <el-input-number v-model="form.value" :min="1" :max="100"></el-input-number>
-        </el-form-item>
-        <el-form-item label="附件" prop="fileUrl">
-          <file-upload @getFileUrl="getFileUrl" @removeFile="removeFile"></file-upload>
-        </el-form-item>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="所属项目">
+              <div>{{ form.projectName }}</div>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="反馈时间">
+              <div>{{ form.feedbackDate }}</div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="反馈类型" prop="feedbackType">
+              <el-radio-group v-model="form.feedbackType" @input="feedbackTypeChange">
+                <el-radio
+                  v-for="dict in dict.type.feedback_type"
+                  :key="dict.value"
+                  :label="dict.value"
+                  v-if="dict.value<3"
+                >{{ dict.label }}
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="工时" prop="hours">
+              <el-input v-model="form.hours" style="width: 130px"></el-input>
+              <span style="margin-left: 5px">小时</span>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="进度" prop="value">
+              <el-input-number v-model="form.value" :min="1" :max="100"></el-input-number>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="附件" prop="fileUrl">
+              <file-upload @getFileUrl="getFileUrl" @removeFile="removeFile"></file-upload>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
         <el-form-item label="反馈描述" prop="description">
-          <el-input v-model="form.description" type="textarea" autosize/>
+          <!--          <el-input v-model="form.description" type="textarea" autosize/>-->
+          <rich-text-editor ref="rtEditor" @getHtml="(val)=>form.description=val"></rich-text-editor>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -170,10 +190,10 @@
 
 <script>
 import {getTask, listView, addTaskFeedback, getFeedbackList, confirmComment} from "@/api/task/task";
-import {getProjectList, getProjectTree} from "@/api/task/project";
 import DateUtil from "@/utils/date"
 import TaskDetail from "./components/taskDetail"
 import FileUpload from "@/components/FileUpload"
+import RichTextEditor from '@/components/RichTextEditor'
 
 import {mapGetters} from 'vuex'
 
@@ -187,21 +207,41 @@ const statusMap = {
 }
 
 export default {
-  components: {TaskDetail, FileUpload},
+  components: {TaskDetail, FileUpload, RichTextEditor},
   dicts: ['task_status', 'feedback_type'],
   computed: {
     ...mapGetters(['userId'])
   },
   data() {
     let validateValue = (rule, value, callback) => {
-      if (this.form.feedbackType != '1' && this.form.feedbackType != '2') {
-        return callback();
+      if (!Number.isInteger(value) || value < 0 || value > 100) {
+        return callback(new Error('进度值必须为0到100的整数'));
       }
       if (!value) {
         return callback(new Error('进度不能为空'));
       }
       return callback();
     };
+    let validateHours = (rule, value, callback) => {
+      const regex = /^(?:[0-1]?\d|2[0-4])(\.5)?$/;
+      if (!regex.test(value) || value < 0 || value > 24) {
+        return callback(new Error('工时必须为0到24的数,最小维度为0.5小时'));
+      }
+      if (!value) {
+        return callback(new Error('工时不能为空'));
+      }
+      return callback();
+    };
+    let validateDescription = (rule, value, callback) => {
+      let text = value.replace('<p>', '').replace('</p>', '').replace('<br>', '').replace('&nbsp;', '')
+      if (text === '') {
+        return callback(new Error('反馈描述不能为空'));
+      }
+      if (text.length < 5 || text.length > 900) {
+        return callback(new Error('反馈描述字符数需在5到500之间'));
+      }
+      return callback();
+    };
 
     return {
       queryParams: {
@@ -222,11 +262,13 @@ export default {
           {required: true, message: "反馈类型不能为空", trigger: "change"}
         ],
         value: [
-          {validator: validateValue, trigger: 'blur'}
+          {required: true, validator: validateValue, trigger: 'blur'}
+        ],
+        hours: [
+          {required: true, validator: validateHours, trigger: 'blur'}
         ],
         description: [
-          {required: true, message: "反馈描述不能为空", trigger: "blur"},
-          {min: 3, max: 500, message: '长度在 3 到 500 个字符', trigger: 'blur'}
+          {required: true, validator: validateDescription, trigger: "blur"},
         ]
       },
       openDetail: false,
@@ -351,6 +393,7 @@ export default {
     },
     // 取消按钮
     cancel() {
+      this.$refs.rtEditor.clear();
       this.open = false;
       this.reset();
     },
@@ -444,4 +487,9 @@ export default {
   vertical-align: text-top;
 }
 
+.feed-dialog ::v-deep .el-dialog__body {
+  padding: 0 20px 10px 20px;
+}
+
+
 </style>