Преглед изворни кода

模板管理,经费收入,经费支出,部门管理,模板部门填报后台页面

yanliming пре 1 година
родитељ
комит
295c047fd8

+ 50 - 0
src/api/base/departmentInfo.js

@@ -0,0 +1,50 @@
+import request from '@/utils/request'
+import constant from '@/constant'
+
+function pageList(formData) {
+  return request.post(constant.serverUrl + "/base/departmentInfo/pageList", formData);
+}
+
+function list() {
+  return request.post(constant.serverUrl + "/base/departmentInfo/list");
+}
+
+function create() {
+  return request.get(constant.serverUrl + "/base/departmentInfo/create");
+}
+
+function edit(id) {
+  return request.get(constant.serverUrl + "/base/departmentInfo/edit/" + id);
+}
+
+function add(formModel) {
+  return request.post(constant.serverUrl + "/base/departmentInfo/add", formModel, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+function update(formModel) {
+  return request.post(constant.serverUrl + "/base/departmentInfo/update", formModel, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+function remove(id) {
+  return request.post(constant.serverUrl + "/base/departmentInfo/delete/" + id);
+}
+
+function batchRemove(idList) {
+  return request.post(constant.serverUrl + "/base/departmentInfo/batchDelete", idList, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+export default {
+  pageList, create, edit, add, update, remove, batchRemove,list
+}

+ 51 - 0
src/api/base/expensesInfo.js

@@ -0,0 +1,51 @@
+import request from '@/utils/request'
+import constant from '@/constant'
+
+function pageList(formData) {
+  return request.post(constant.serverUrl + "/base/expensesInfo/pageList", formData);
+}
+
+function create() {
+  return request.get(constant.serverUrl + "/base/expensesInfo/create");
+}
+
+function edit(id) {
+  return request.get(constant.serverUrl + "/base/expensesInfo/edit/" + id);
+}
+
+function add(formModel) {
+  return request.post(constant.serverUrl + "/base/expensesInfo/add", formModel, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+function update(formModel) {
+  return request.post(constant.serverUrl + "/base/expensesInfo/update", formModel, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+function remove(id) {
+  return request.post(constant.serverUrl + "/base/expensesInfo/delete/" + id);
+}
+
+function batchRemove(idList) {
+  return request.post(constant.serverUrl + "/base/expensesInfo/batchDelete", idList, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+function generateData(id) {
+  return request.post(constant.serverUrl + "/base/expensesInfo/generateData/" + id);
+}
+
+
+export default {
+  pageList, create, edit, add, update, remove, batchRemove,generateData
+}

+ 51 - 0
src/api/base/fundIncomeInfo.js

@@ -0,0 +1,51 @@
+import request from '@/utils/request'
+import constant from '@/constant'
+
+function pageList(formData) {
+  return request.post(constant.serverUrl + "/base/fundIncomeInfo/pageList", formData);
+}
+
+function create() {
+  return request.get(constant.serverUrl + "/base/fundIncomeInfo/create");
+}
+
+function edit(id) {
+  return request.get(constant.serverUrl + "/base/fundIncomeInfo/edit/" + id);
+}
+
+function add(formModel) {
+  return request.post(constant.serverUrl + "/base/fundIncomeInfo/add", formModel, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+function update(formModel) {
+  return request.post(constant.serverUrl + "/base/fundIncomeInfo/update", formModel, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+function remove(id) {
+  return request.post(constant.serverUrl + "/base/fundIncomeInfo/delete/" + id);
+}
+
+function batchRemove(idList) {
+  return request.post(constant.serverUrl + "/base/fundIncomeInfo/batchDelete", idList, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+function generateData(formData) {
+  return request.post(constant.serverUrl + "/base/fundIncomeInfo/generateData", formData);
+}
+
+
+export default {
+  pageList, create, edit, add, update, remove, batchRemove,generateData
+}

+ 14 - 1
src/api/base/templateInfo.js

@@ -5,6 +5,10 @@ function pageList(formData) {
   return request.post(constant.serverUrl + "/base/templateInfo/pageList", formData);
 }
 
+function list() {
+  return request.post(constant.serverUrl + "/base/templateInfo/list");
+}
+
 function create() {
   return request.get(constant.serverUrl + "/base/templateInfo/create");
 }
@@ -33,6 +37,11 @@ function remove(id) {
   return request.post(constant.serverUrl + "/base/templateInfo/delete/" + id);
 }
 
+function checked(id) {
+  return request.post(constant.serverUrl + "/base/templateInfo/checked/" + id);
+}
+
+
 function batchRemove(idList) {
   return request.post(constant.serverUrl + "/base/templateInfo/batchDelete", idList, {
     headers: {
@@ -41,6 +50,10 @@ function batchRemove(idList) {
   });
 }
 
+function saveAttachment(formData) {
+  return request.post(constant.serverUrl + "/base/templateInfo/saveAttachment", formData);
+}
+
 export default {
-  pageList, create, edit, add, update, remove, batchRemove
+  pageList, create, edit, add, update, remove, batchRemove,list,checked,saveAttachment
 }

+ 69 - 0
src/api/base/templateOption.js

@@ -0,0 +1,69 @@
+import request from '@/utils/request'
+import constant from '@/constant'
+
+function pageList(formData) {
+  return request.post(constant.serverUrl + "/base/templateOption/pageList", formData);
+}
+
+function create() {
+  return request.get(constant.serverUrl + "/base/templateOption/create");
+}
+
+function edit(id) {
+  return request.get(constant.serverUrl + "/base/templateOption/edit/" + id);
+}
+
+
+function templateDepartmentEdit(id) {
+  return request.get(constant.serverUrl + "/base/templateOption/templateDepartmentEdit/" + id);
+}
+
+function departmentDetailEdit(id) {
+  return request.get(constant.serverUrl + "/base/templateOption/departmentDetailEdit/" + id);
+}
+
+
+
+
+function add(formModel) {
+  return request.post(constant.serverUrl + "/base/templateOption/add", formModel, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+function update(formModel) {
+  return request.post(constant.serverUrl + "/base/templateOption/update", formModel, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+function updateItem(formModel) {
+  return request.post(constant.serverUrl + "/base/templateOption/updateItem", formModel, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+
+
+function remove(id) {
+  return request.post(constant.serverUrl + "/base/templateOption/delete/" + id);
+}
+
+function batchRemove(idList) {
+  return request.post(constant.serverUrl + "/base/templateOption/batchDelete", idList, {
+    headers: {
+      "Content-Type": "application/json"
+    }
+  });
+}
+
+export default {
+  pageList, create, edit, add, update, remove, batchRemove,templateDepartmentEdit,departmentDetailEdit,
+  updateItem
+}

+ 46 - 0
src/components/PermissionDetect/index.vue

@@ -0,0 +1,46 @@
+<template>
+    <div v-if="show">
+        <slot v-if="show"></slot>
+    </div>
+  </template>
+  <script>
+  import permissionApi from "@/api/sys/permission";
+  import { mapState } from 'vuex';
+  
+  export default {
+      props: ["method","path"],
+      data() {
+          return {
+              show: false
+          }
+      },
+      computed: mapState({
+          permissions:state=>state.permission.permissions
+      }),
+      mounted() {
+          //vuex中记录method+path是否能访问
+          if(this.permissions[this.method + '_' + this.path]!=null){
+              this.show = this.permissions[this.method + '_' + this.path];
+          }
+          else{
+            
+              permissionApi.hasPermission(this.method,this.path).then((resp)=>{
+                  var jsonData = resp.data;
+                  this.show = jsonData.result;
+  
+                  this.$store.commit('permission/SET_PERMISSION', {
+                      method: this.method,
+                      path: this.path,
+                      result: this.show
+                  });
+              });
+          }
+      },
+      methods: {
+  
+      }
+  }
+  </script>
+  <style>
+  
+  </style>

+ 2 - 0
src/main.js

@@ -7,9 +7,11 @@ import './plugins/element.js'
 import AxiosPlugin from './plugins/AxiosPlugin'
 import './assets/iconfont/iconfont.css'
 import { Message } from 'element-ui'
+import PermissionDetect from "@/components/PermissionDetect";
 import { Empty } from 'vant';
 import AMap from "vue-amap"
 
+Vue.component('permission-detect', PermissionDetect);
 Vue.config.productionTip = false
 Vue.use(AxiosPlugin);
 //Vue.use(ConfirmPlugin);

+ 48 - 0
src/routers/modules/base.js

@@ -11,6 +11,54 @@ var routers = [
                         title: '模板管理'
                 }
         },
+        {
+                path: '/base/fundIncomeInfo/list',
+                name: 'baseFundIncomeInfoList',
+                // route level code-splitting
+                // this generates a separate chunk (about.[hash].js) for this route
+                // which is lazy-loaded when the route is visited.
+                component: () => import('@/views/base/fundIncomeInfo-list.vue'),
+                meta: {
+                        roles: ["admin"],
+                        title: '经费收入'
+                }
+        },
+        {
+                path: '/base/expensesInfo/list',
+                name: 'baseExpensesInfoList',
+                // route level code-splitting
+                // this generates a separate chunk (about.[hash].js) for this route
+                // which is lazy-loaded when the route is visited.
+                component: () => import('@/views/base/expensesInfo-list.vue'),
+                meta: {
+                        roles: ["admin"],
+                        title: '经费支出'
+                }
+        },
+        {
+                path: '/base/departmentInfo/list',
+                name: 'baseDepartmentInfoList',
+                // route level code-splitting
+                // this generates a separate chunk (about.[hash].js) for this route
+                // which is lazy-loaded when the route is visited.
+                component: () => import('@/views/base/departmentInfo-list.vue'),
+                meta: {
+                        roles: ["admin"],
+                        title: '部门管理'
+                }
+        },
+        {
+                path: '/base/templateDepartment/list',
+                name: 'baseTemplateDepartmentList',
+                // route level code-splitting
+                // this generates a separate chunk (about.[hash].js) for this route
+                // which is lazy-loaded when the route is visited.
+                component: () => import('@/views/base/templateDepartment-list.vue'),
+                meta: {
+                        roles: ["admin"],
+                        title: '模版部门填报'
+                }
+        },
 ]
 
 export default routers;

+ 5 - 1
src/store/modules/permission.js

@@ -38,13 +38,17 @@ export function filterAsyncRoutes(routes, roles) {
 
 const state = {
   routes: [],
-  addRoutes: []
+  addRoutes: [],
+  permissions: {}
 }
 
 const mutations = {
   SET_ROUTES: (state, routes) => {
     state.addRoutes = routes
     state.routes = constantRoutes.concat(routes)
+  },
+  SET_PERMISSION: (state, obj) => {
+    state.permissions[obj.method + '_' + obj.path] = obj.result;
   }
 }
 

+ 188 - 0
src/views/base/departmentInfo-detail.vue

@@ -0,0 +1,188 @@
+
+<template>
+    <el-dialog
+      :visible.sync="showDialog"
+      :title="title"
+      :modal-append-to-body="false"
+      style="text-align: left;"
+      @close="closeDialog"
+      :close-on-click-modal="false"
+    >
+      <div class="user-panel" v-loading="loading">
+        <el-form
+          ref="form"
+          :model="formModel"
+          :rules="ruleValidate"
+          :label-width="'100px'"
+          :inline="true"
+        >
+          <el-form-item label="部门名称" prop="name">
+            <el-input v-model="formModel.name" placeholder="请输入部门名称" style="width: 300px"></el-input>
+          </el-form-item>
+        </el-form>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="closeDialog">取 消</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="submitting"
+          >确 定</el-button
+        >
+      </span>
+    </el-dialog>
+  </template>
+  <script>
+  import Constant from "@/constant";
+  import { getToken } from "@/utils/auth"; // get token from cookie
+  import departmentInfoApi from "@/api/base/departmentInfo";
+  
+  export default {
+    props: ["businessKey", "title"],
+    data() {
+      return {
+          showPwd: true,
+          ruleValidate: {
+              title: [
+              { required: true, message: "标题不能为空", trigger: "blur" },
+              ],
+              type: [
+              { required: true, message: "模板类型不能为空", trigger: "blur" },
+              ],
+          },
+          roleList: [],
+          formModel: {},
+          showDialog: true,
+          loading: false,
+          submitting: false,
+          typeList:[
+            {
+                "name":"收入",
+                "value":"1",
+            },
+            {
+                "name":"支出",
+                "value":"2",
+            }
+          ]
+      };
+    },
+    created() {
+    },
+    methods: {
+      closeDialog() {
+        this.$emit("close", false);
+      },
+      handleSubmit() {
+        var self = this;
+  
+        this.$refs["form"].validate((valid) => {
+          if (valid) {
+            (function () {
+              var id = self.formModel.id;
+  
+              if (id == null || id.length == 0) {
+                return departmentInfoApi.add(self.formModel);
+              } else {
+                return departmentInfoApi.update(self.formModel);
+              }
+            })().then(function (response) {
+              var jsonData = response.data;
+  
+              if (jsonData.result) {
+                self.$message({
+                  message: "保存成功!",
+                  type: "success",
+                });
+  
+                self.$emit("close", true);
+              } else {
+                self.$message({
+                  message: jsonData.message + "",
+                  type: "warning",
+                });
+  
+                self.$emit("close", false);
+              }
+            });
+          }
+        });
+      },
+      handleAvatarSuccess(res, file) {
+          var self = this;
+          self.formModel.photo = res.data;
+  
+          self.fileUrl =
+            res.data + "?x-oss-process=image/resize,m_lfit,h_300,w_300";
+      },
+      beforeAvatarUpload(file) {
+          const isLt2M = file.size / 1024 / 1024 < 2;
+          if (!isLt2M) {
+              this.$message.error('上传头像图片大小不能超过 2MB!');
+          }
+          return isLt2M;
+      }
+    },
+    async mounted() {
+      var self = this;
+      self.loading = true;
+  
+      (function () {
+        if (self.businessKey != null && self.businessKey.length > 0) {
+          return departmentInfoApi.edit(self.businessKey);
+        } else {
+          return departmentInfoApi.create();
+        }
+      })()
+        .then((response) => {
+          var jsonData = response.data;
+  
+          if (jsonData.result) {
+              self.formModel = jsonData.data;
+  
+              let photo = self.formModel.photo;
+              if (photo != null) {
+                  self.fileUrl = photo 
+              }
+  
+              self.showModal = true;
+          } else {
+            self.$message.error(jsonData.message + "");
+          }
+  
+          self.loading = false;
+        })
+        .catch((error) => {
+          self.$message.error(error + "");
+          self.loading = false;
+        });
+    },
+    components: {
+    },
+  };
+  </script>
+  <style scoped>
+  .user-panel {
+    margin: 10px auto;
+  }
+  .avatar-uploader .el-upload {
+      border: 1px dashed #d9d9d9;
+      border-radius: 6px;
+      cursor: pointer;
+      position: relative;
+      overflow: hidden;
+    }
+    .avatar-uploader .el-upload:hover {
+      border-color: #409EFF;
+    }
+    .avatar-uploader-icon {
+      font-size: 28px;
+      color: #8c939d;
+      width: 178px;
+      height: 178px;
+      line-height: 178px;
+      text-align: center;
+    }
+    .avatar {
+      width: 178px;
+      height: 178px;
+      display: block;
+    }
+  </style>

+ 396 - 0
src/views/base/departmentInfo-list.vue

@@ -0,0 +1,396 @@
+<template>
+    <div>
+      <el-breadcrumb separator=">">
+        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+        <el-breadcrumb-item>
+          <a href="#">基础信息管理</a>
+        </el-breadcrumb-item>
+        <el-breadcrumb-item>
+          部门管理
+        </el-breadcrumb-item>
+      </el-breadcrumb>
+      <el-divider></el-divider>
+      <!--
+        要resetFields起作用,必须配置:model和prop
+      -->
+      <el-form ref="queryForm" :model="queryModel" inline class="demo-form-inline">
+        <el-form-item label="部门名称" prop="name">
+          <el-input type="text" size="mini" v-model="queryModel.name"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button
+            type="primary"
+            size="mini"
+            icon="ios-search"
+            @click="changePage(1)"
+            :loading="loading"
+          >查询</el-button>&nbsp;
+          <el-button
+            type="info"
+            size="mini"
+            style="margin-left: 8px"
+            @click="handleReset('queryForm')"
+          >重置</el-button>&nbsp;
+        </el-form-item>
+      </el-form>
+      <el-divider></el-divider>
+      <el-row class="button-group">
+        <el-button type="primary" size="small" plain icon="el-icon-circle-plus" @click="handleAdd">新增</el-button>
+        <el-button
+          type="primary"
+          size="small"
+          plain
+          icon="el-icon-remove"
+          :disabled="multipleSelection.length==0"
+          @click="handleBatchDelete"
+        >删除选中项</el-button>
+      </el-row>
+      <el-table
+        :data="tableData"
+        style="min-height:400px;"
+        v-loading="loading"
+        stripe
+        @sort-change="sortChange"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column  prop="name"  label="部门名称"></el-table-column>
+        <el-table-column  prop="createTime"  label="创建时间"></el-table-column>
+        <el-table-column label="操作" width="250">
+          <template slot-scope="{row}" >
+            <el-button size="mini" type="warning" @click="handleEdit(row)">编辑</el-button>
+            <el-button size="mini" type="danger" @click="handleDelete(row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination
+        :current-page.sync="pageIndex"
+        :total="totalElements"
+        :page-sizes="pageSizeList"
+        @current-change="changePage"
+        @size-change="pageSizeChange"
+        layout="total, sizes, prev, pager, next, jumper"
+      ></el-pagination>
+      <departmentInfo-detail
+        v-if="showModal"
+        ref="userDetail"
+        :businessKey="businessKey"
+        :title="modalTitle"
+        @close="onDetailModalClose"
+      ></departmentInfo-detail>
+
+    </div>
+  </template>
+  <script>
+  import Constant from "@/constant";
+  import departmentInfoApi from "@/api/base/departmentInfo";
+  import departmentInfoDetail from "./departmentInfo-detail";
+  import { getToken } from "@/utils/auth"; // get token from cookie
+  
+  export default {
+    name: 'baseDepartmentInfoInfo',
+    data() {
+      var self = this;
+  
+      return {
+        queryModel: {
+          realName: "",
+          phone:"",
+          idCard:"",
+          status:"",
+        },
+        loading: false,
+        tableData: [],
+        pageIndex: 1,
+        pageSize: 10,
+        totalPages: 0,
+        totalElements: 0,
+        field: "",
+        direction: "",
+        pageSizeList: [10, 20, 30],
+        multipleSelection: [],
+        modalTitle: "",
+        modalTitle2: "",        
+        businessKey: "",
+        showModal: false,
+        showModal2:false,
+        dialogFormVisible:false,
+        newPassword:"",
+        roleResult:[],
+        props: {
+          // 配置项(必选)
+          value: "id",
+          label: "name",
+          children: "children"
+        },
+        batchImportVisible: false,
+        xlsLoading: false,
+        batchImportFileList: [],
+        chargingStationResult:[],
+        uploadUrlXls: Constant.serverUrl + "/base/personInfo/importXls",
+        uploadXlsData: {
+            subFolder: "personInfo",
+        },
+        headers: {
+            Authorization: getToken(),
+        },
+        statusList:[
+          {
+            "id":"0",
+            "name":"未认证",
+            "value":"0"
+          },
+          {
+            "id":"1",
+            "name":"已认证",
+            "value":"1"
+          }
+        ],
+      };
+    },
+    methods: {
+      changePage(pageIndex,exportFlag) {
+        var self = this;
+  
+        console.log(pageIndex);
+  
+        self.pageIndex = pageIndex;
+        var formData = new FormData();
+  
+        formData.append("pageIndex", self.pageIndex);
+        
+        if(exportFlag!=null){
+            formData.append("exportFlag", exportFlag);
+            formData.append("pageSize", 10000);
+        }
+        else{
+            formData.append("pageSize", self.pageSize);
+        }
+        formData.append("realName", self.queryModel.realName);
+        formData.append("phone", self.queryModel.phone);
+        formData.append("idCard", self.queryModel.idCard);
+        formData.append("status", self.queryModel.status);
+  
+        self.loading = true;
+  
+        departmentInfoApi.pageList(formData).then(function(response) {
+          self.loading = false;
+            var jsonData = response.data;
+            if(jsonData.result) {
+                if(exportFlag){
+                    //导出
+                    self.$message({
+                        showClose: true,
+                        type: "success",
+                        message: `报表已生成,<a href="${jsonData.data}">请点击链接下载</a>`,
+                        dangerouslyUseHTMLString: true,
+                        duration: 30000
+                    });
+                }
+                else{
+                    //分页查看
+                    var page = jsonData.data;
+
+                    self.tableData = page.data;
+                    self.totalPages = page.totalPages;
+                    self.totalElements = page.recordsTotal;
+                }
+            }
+            else{
+                self.$message.warning(jsonData.message);
+            }
+        }).catch((error)=>{
+          self.loading = false;
+        });
+      },
+      pageSizeChange(pageSize) {
+        this.pageSize = pageSize;
+      },
+      sortChange(data) {
+        this.field = data.column.field;
+        this.direction = data.order == "ascending" ? "asc" : "desc";
+  
+        this.changePage(this.pageIndex);
+      },
+      handleSelectionChange(val) {
+        this.multipleSelection = val;
+      },
+      handleReset(name) {
+        this.$refs[name].resetFields();
+      },
+      handleAdd() {
+        var self = this;
+        
+        self.modalTitle = "新增模板";
+        self.businessKey = "";
+        self.showModal = true;
+      },
+      handleEdit(record) {
+        var self = this;
+        
+        self.modalTitle = "编辑模板";
+        self.businessKey = record.id;
+        self.showModal = true;
+      },
+      handleOption(record){
+        var self = this;
+        
+        self.modalTitle2 = "编辑项目";
+        self.businessKey = record.id;
+        self.showModal2 = true;
+      },
+      handleDelete(record) {
+        var self = this;
+  
+        this.$confirm("是否确认删除?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+            departmentInfoApi.remove(record.id).then(function(response) {
+            var jsonData = response.data;
+  
+            if (jsonData.result) {
+              // var index = self.tableData.indexOf(record);
+              // self.tableData.splice(index, 1);
+              self.changePage(self.pageIndex);
+  
+              self.$message({
+                type: "success",
+                message: "删除成功!"
+              });
+            }
+          });
+        });
+      },
+      handleBatchDelete() {
+        var self = this;
+  
+        var idList = this.multipleSelection.map(record => {
+          return record.id;
+        });
+  
+        this.$confirm("是否确认删除选中项?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+            departmentInfoApi.batchRemove(idList).then(function(response) {
+            var jsonData = response.data;
+  
+            if (jsonData.result) {
+              self.changePage(self.pageIndex);
+  
+              self.$message({
+                type: "success",
+                message: "删除成功!"
+              });
+            }
+          });
+        });
+      },
+      exportXls() {
+        this.changePage(1,true);
+      },
+        onDetailModalClose(refreshed) {
+            this.showModal = false;
+    
+            if(refreshed) {
+            this.changePage(this.pageIndex);
+            }
+        },
+        onDetailModalClose2(refreshed) {
+            this.showModal2 = false;
+    
+            if(refreshed) {
+            this.changePage(this.pageIndex);
+            }
+        },
+        beforeUpload(file, fileList) {
+            //导入前判断
+            var self = this;
+            self.xlsLoading = true;
+            return true;
+        },
+        //批量导入-上传成功
+        handleBatchImportSuccess(response, file, fileList) {
+        var self = this;
+        self.xlsLoading = false;
+
+        if (response.result) {
+            self.$message.success(response.message);
+            this.batchImportFileList = [];
+            this.changePage(1);
+
+
+        } else {
+            //this.$message.error(response.message);
+            this.batchImportFileList = [];
+            this.changePage(1);
+
+            if (response.data != null) {
+            //下载有错误信息提示的报表
+            //window.open(response.data);
+            self.$message({
+                showClose: true,
+                dangerouslyUseHTMLString: true,
+                message:
+                response.message +
+                `,<a href="${response.data}" target="_blank">点击下载未导入的数据报表</a>&nbsp;`,
+                duration: 30000,
+            });
+            }
+        }
+
+        this.batchImportVisible = false;
+        },
+        //批量导入-预览
+        handleBatchImportPreview(file) {
+        console.log(file.url);
+        },
+        //批量导入-移除
+        handleBatchImportRemove(file, fileList) {
+        console.log(file, fileList);
+        },
+        //批量导入-移除前操作
+        beforeBatchImportRemove(file, fileList) {
+        console.log(file, fileList);
+        },
+        //批量导入-文件超出个数限制时的钩子
+        handleBatchImportExceed(files, fileList) {
+        this.$message.warning(
+            `当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${
+            files.length + fileList.length
+            } 个文件`
+        );
+        },
+    },
+    mounted: function() {
+      var self = this;
+      this.changePage(1);
+    },
+    components: {
+        "departmentInfo-detail":departmentInfoDetail,
+    }
+  };
+  </script>
+  <style lang="scss" scoped>
+  .el-breadcrumb {
+    margin: 10px;
+    line-height: 20px;
+  }
+  
+  .el-divider {
+    margin: 5px 0;
+  }
+  
+  .demo-form-inline {
+    margin-left: 10px;
+    text-align: left;
+  }
+  
+  .button-group {
+    padding: 10px;
+    text-align: left;
+  }
+  </style>

+ 784 - 0
src/views/base/expensesInfo-list.vue

@@ -0,0 +1,784 @@
+<template>
+    <div class="cesiumTabRoot">
+      <el-breadcrumb separator=">">
+        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+        <el-breadcrumb-item>
+          <a href="#">基础信息管理</a>
+        </el-breadcrumb-item>
+        <el-breadcrumb-item>
+          经费支出
+        </el-breadcrumb-item>
+      </el-breadcrumb>
+      <el-divider></el-divider>
+      <!--
+        要resetFields起作用,必须配置:model和prop
+      -->
+      <el-form ref="queryForm" :model="queryModel" inline class="demo-form-inline">
+        <el-form-item label="年份" prop="yearMonth">
+          <el-date-picker
+            size="mini"
+            v-model="queryModel.yearMonth"
+            type="month"
+            placeholder="选择年月"
+            value-format="yyyy-MM"
+            format="yyyy-MM">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="项目名称" prop="name">
+          <el-input type="text" size="mini" v-model="queryModel.name" ></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button
+            type="primary"
+            size="mini"
+            icon="ios-search"
+            @click="changePage(1)"
+            :loading="loading"
+          >查询</el-button>&nbsp;
+          <el-button
+            type="info"
+            size="mini"
+            style="margin-left: 8px"
+            @click="handleReset('queryForm')"
+          >重置</el-button>&nbsp;
+        </el-form-item>
+      </el-form>
+      <el-divider></el-divider>
+      <el-row class="button-group">
+        <!-- <el-button type="primary" size="small" @click="handleAdd" plain icon="el-icon-circle-plus" >新增</el-button>
+        <el-button
+          type="primary"
+          size="small"
+          plain
+          icon="el-icon-upload"
+          @click="batchImportVisible = true"
+        >导入</el-button> -->
+        <el-button
+          type="primary"
+          size="small"
+          plain
+          icon="el-icon-upload2"
+          @click="exportXls"
+        >导出数据</el-button>
+        <span style="float: right;">
+          <permission-detect class="inline" path="/base/fundIncomeInfo/generateData" method="post">
+          <el-button type="danger"
+           size="small" 
+           style="text-align:right" 
+           icon="el-icon-s-data" 
+           @click="batchImportVisible2 = true">生成列表项目</el-button>
+          </permission-detect>
+        </span>
+        
+      </el-row>
+      
+      <el-table
+        :data="tableData"
+        style="min-height:400px;"
+        height="500"
+        v-loading="loading"
+        stripe
+        border
+        @cell-mouse-enter="handleCellEnter"
+        @cell-mouse-leave="handleCellLeave"
+        @cell-click="handleCellClick"
+      >
+        <!-- <el-table-column label="操作" fixed>
+          <template slot-scope="{row}" >
+            <i class="el-icon-plus hand-cursor" @click="handleAdd"></i>
+            <i class="el-icon-delete hand-cursor" @click="handleDelete(row)" style="margin-left:15px"></i>
+          </template>
+        </el-table-column> -->
+        <el-table-column label="保存" fixed>
+          <template slot-scope="{row}" >
+            <el-button type="primary" size="mini" @click="handleSave(row)" plain>保存</el-button>
+          </template>
+        </el-table-column>
+        <el-table-column  prop="serialNumber" fixed label="序号">
+            <!-- <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.serialNumber" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.serialNumber}}</div>
+            </div> -->
+        </el-table-column>
+        <el-table-column  prop="name" fixed label="项目名称" width="300">
+            <!-- <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.name" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.name}}</div>
+            </div> -->
+        </el-table-column>
+        <el-table-column  prop="amount"  label="金额(元)" width="200">
+                <div class="item" slot-scope="scope">
+                    <el-input-number
+                    style="width:180px"
+                    size="mini" 
+                    class="item__input" 
+                    :precision="2" :step="0.1"
+                    v-model="scope.row.amount"
+                    @blur="save(scope.row)">
+                </el-input-number>
+                <div class="item__txt">{{scope.row.amount}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="executor"  label="执行人" width="180">
+            <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.executor" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.executor}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="responsiblePerson"  label="责任人" width="200">
+            <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.responsiblePerson" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.responsiblePerson}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="completionTime"  label="完成时间" width="150">
+            <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.completionTime" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.completionTime}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="feeStartDateStr"  label="催费启动时间"  width="150">
+            <div class="item" slot-scope="scope">
+                <el-date-picker
+                  style="width:130px"
+                  size="mini"
+                  class="item__input"
+                  @blur="save(scope.row)"
+                  v-model="scope.row.feeStartDateStr"
+                  type="date"
+                  placeholder="选择日期"
+                  value-format="yyyy-MM-dd" 
+                  format="yyyy-MM-dd">
+                </el-date-picker>
+                <div class="item__txt">{{scope.row.feeStartDateStr}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="attachment"  label="附件">
+          <template slot-scope="scope">
+            <el-link type="primary" :href="scope.row.attachment" target="_blank" :underline="false">
+            <el-image
+              style="width: 35px; height: 35px"
+              v-if="scope.row.attachment"
+              :src="scope.row.attachment"
+              :fit="fit">
+            </el-image>
+            </el-link>
+          </template>
+        </el-table-column>
+        <el-table-column  prop="attachment"  label="上传">
+          <template slot-scope="scope">
+              <el-upload
+                  class="avatar-uploader"
+                  name="photoFile"
+                  :action="uploadUrl"
+                  :show-file-list="false"
+                  :headers="headers"
+                  :data="uploadData"
+                  :on-success="($event) =>{handleAvatarSuccess($event,scope.row)}"
+                  :before-upload="beforeAvatarUpload"
+                >
+              <el-link type="primary">上传</el-link>
+            </el-upload>
+          </template>
+        </el-table-column>
+        <el-table-column  prop="supervisor"  label="督办员" width="200">
+            <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.supervisor" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.supervisor}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="aboutTopic"  label="相关资料" width="180">
+            <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.aboutTopic" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.aboutTopic}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="yearMonthStr"  label="所属年月" width="120"></el-table-column>
+      </el-table>
+      <el-dialog
+      title="批量导入数据"
+      :visible.sync="batchImportVisible"
+      :modal-append-to-body="false"
+      style="text-align: left"
+      :close-on-click-modal="false"
+    >
+      <el-form label-width="150px">
+        <el-form-item label="模板下载">
+          <el-link
+            href="https://oss.xiaoxinda.com/jk-temporary-workers/person.xls"
+            type="primary"
+            target="_blank"
+            >点击下载模板</el-link
+          >
+        </el-form-item>
+        <el-form-item label="上传文件">
+          <el-upload
+            class="upload-demo"
+            accept=".xls"
+            :action="uploadUrlXls"
+            :data="uploadXlsData"
+            :headers="headers"
+            name="uploadFile"
+            :multiple="true"
+            :limit="1"
+            :file-list="batchImportFileList"
+          >
+            <el-button size="small" type="primary" :loading="xlsLoading"
+              >点击上传</el-button
+            >
+            <div slot="tip" class="el-upload__tip">
+              只能上传xls文件,且不超过500kb
+            </div>
+          </el-upload>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="batchImportVisible = false"
+          >关 闭</el-button
+        >
+      </div>
+    </el-dialog>
+
+
+    <el-dialog
+      title="选择模版"
+      :visible.sync="batchImportVisible2"
+      :modal-append-to-body="false"
+      style="text-align: left"
+      :close-on-click-modal="false"
+    >
+      <el-form label-width="150px">
+        <el-form-item label="模版" prop="userName">
+          <el-select v-model="selectTamplateId" placeholder="请选择" style="width:400px">
+            <el-option
+              v-for="item in templateList"
+              :key="item.id"
+              :label="item.title"
+              :value="item.id">
+            </el-option>
+          </el-select>
+      </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="batchImportVisible2 = false"
+          >关 闭</el-button
+        >
+        <el-button type="danger" @click="handleGenerateData(selectTamplateId)" :loading="submitting"
+          >生 成</el-button
+        >
+      </div>
+    </el-dialog>
+    </div>
+  </template>
+  <script>
+  import Constant from "@/constant";
+  import expensesInfoApi from "@/api/base/expensesInfo";
+  import templateInfoApi from "@/api/base/templateInfo";
+  import { getToken } from "@/utils/auth"; // get token from cookie
+  
+  export default {
+    name: 'baseExpensesInfoInfo',
+    data() {
+      var self = this;
+  
+      return {
+        queryModel: {
+          yearMonth: "",
+          name: "",
+        },
+        loading: false,
+        tableData: [],
+        pageIndex: 1,
+        pageSize: 10,
+        totalPages: 0,
+        totalElements: 0,
+        field: "",
+        direction: "",
+        pageSizeList: [10, 20, 30],
+        multipleSelection: [],
+        modalTitle: "",      
+        businessKey: "",
+        showModal: false,
+        dialogFormVisible:false,
+        batchImportVisible: false,
+        batchImportVisible2:false,
+        xlsLoading: false,
+        submitting:false,
+        selectTamplateId:"",
+        batchImportFileList: [],
+        chargingStationResult:[],
+        // 需要编辑的属性
+        editProp: ['amount','executor','responsiblePerson','completionTime',
+        'feeStartDateStr','supervisor','aboutTopic'],
+         // 保存进入编辑的cell
+        clickCellMap: {},
+        templateList:[],
+        uploadUrlXls: Constant.serverUrl + "/base/fundIncomeInfo/importXls",
+        uploadXlsData: {
+            subFolder: "personInfo",
+        },
+        headers: {
+            Authorization: getToken(),
+        },
+        //上传地址
+        uploadUrl: Constant.serverUrl + "/uploadPicture",
+        uploadData: {
+          subFolder: "fundIncomeInfo",
+        },
+        fileUrl: "",
+        typeList:[
+          {
+            "name":"按月",
+            "value":"1"
+          },
+          {
+            "name":"按年",
+            "value":"2"
+          },
+          {
+            "name":"按季",
+            "value":"3"
+          },
+          {
+            "name":"按学期",
+            "value":"4"
+          },
+        ],
+
+      };
+    },
+    created(){
+      var self = this;
+    
+      templateInfoApi.list().then(function (response) {
+        var jsonData = response.data;
+        if (jsonData.result) {
+          if (jsonData.data != null && jsonData.data != "") {
+            self.templateList = jsonData.data;
+          }
+        }
+      });
+
+      self.getNowTime();
+    },
+    methods: {
+      handleEditNum(event,row){
+          if(event!=0){
+            var sumNum = row.actualTotalRevenue + row.curMonthReceived;
+            row.actualTotalRevenue = sumNum;
+          }
+      },
+      getNowTime() {
+        var now = new Date();
+        var year = now.getFullYear(); //得到年份
+        var month = now.getMonth(); //得到月份
+        month = month + 1;
+        month = month.toString().padStart(2, "0");
+        var defaultDate = `${year}-${month}`;
+        this.$set(this.queryModel, "yearMonth", defaultDate);
+      },
+      changePage(pageIndex,exportFlag) {
+        var self = this;
+  
+        console.log(pageIndex);
+  
+        self.pageIndex = pageIndex;
+        var formData = new FormData();
+  
+        formData.append("name", self.queryModel.name);
+        formData.append("yearMonth", self.queryModel.yearMonth);
+
+        if(exportFlag!=null){
+            formData.append("exportFlag", exportFlag);
+        }
+
+        self.loading = true;
+  
+        expensesInfoApi.pageList(formData).then(function(response) {
+          self.loading = false;
+            var jsonData = response.data;
+            if(jsonData.result) {
+                if(exportFlag){
+                    //导出
+                    self.$message({
+                        showClose: true,
+                        type: "success",
+                        message: `报表已生成,<a href="${jsonData.data}">请点击链接下载</a>`,
+                        dangerouslyUseHTMLString: true,
+                        duration: 30000
+                    });
+                }
+                else{
+                    //分页查看
+                    var page = jsonData.data;
+
+                    self.tableData = page.data;
+                    // self.totalPages = page.totalPages;
+                    // self.totalElements = page.recordsTotal;
+                }
+            }
+            else{
+                self.$message.warning(jsonData.message);
+            }
+        }).catch((error)=>{
+          self.loading = false;
+        });
+      },
+      handleReset(name) {
+        this.$refs[name].resetFields();
+      },
+      handleDelete(record) {
+        var self = this;
+        if(record.id==null||record.id==""){
+            self.$message({
+                type: "error",
+                message: "该条记录未填写数据无需删除!"
+            });
+            return;
+        }
+  
+        this.$confirm("是否确认删除?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+            expensesInfoApi.remove(record.id).then(function(response) {
+            var jsonData = response.data;
+  
+            if (jsonData.result) {
+              // var index = self.tableData.indexOf(record);
+              // self.tableData.splice(index, 1);
+              self.changePage(self.pageIndex);
+  
+              self.$message({
+                type: "success",
+                message: "删除成功!"
+              });
+
+              var datalist = self.formModel.tableData;
+
+              datalist.splice(datalist.indexOf(record), 1);
+            }
+          });
+        });
+      },
+
+
+        /** 鼠标移入cell */
+        handleCellEnter (row, column, cell, event) {
+            const property = column.property
+            if (property === 'date' || property === 'name' || property === 'food') {
+                cell.querySelector('.item__txt').classList.add('item__txt--hover')
+            }
+        },
+        /** 鼠标移出cell */
+        handleCellLeave (row, column, cell, event) {
+            const property = column.property
+            if (this.editProp.includes(property)) {
+                cell.querySelector('.item__txt').classList.remove('item__txt--hover')
+            }
+        },
+
+        /** 点击cell */
+        handleCellClick(row, column, cell, event) {
+            const property = column.property
+            if (this.editProp.includes(property)) {
+                // 保存cell
+                this.saveCellClick(row, cell)
+                cell.querySelector('.item__txt').style.display = 'none'
+                cell.querySelector('.item__input').style.display = 'block'
+                cell.querySelector('input').focus()
+            }
+        },
+        /** 取消编辑状态 */
+        cancelEditable (cell) {
+            cell.querySelector('.item__txt').style.display = 'block'
+            cell.querySelector('.item__input').style.display = 'none'
+        },
+        /** 保存进入编辑的cell */
+        saveCellClick (row, cell) {
+            const id = row.id;
+            if (this.clickCellMap[id] !== undefined) {
+                if (!this.clickCellMap[id].includes(cell)) {
+                  this.clickCellMap[id].push(cell)
+                }
+            } else {
+                this.clickCellMap[id] = [cell]
+            }
+        },
+
+        /** 保存数据 */
+        save (row) {
+            const id = row.id;
+            if(row.incomeType!=""&&row.incomeType!=null){
+              if(row.incomeType=='1'){
+                row.incomeTypeN="按月";
+              }
+              else if(row.incomeType=='2'){
+                row.incomeTypeN="按年";
+              }
+              else if(row.incomeType=='3'){
+                row.incomeTypeN="按季";
+              }
+              else if(row.incomeType=='4'){
+                row.incomeTypeN="按学期";
+              }
+            }
+            
+            // 取消本行所有cell的编辑状态
+            this.clickCellMap[id].forEach(cell => {
+                this.cancelEditable(cell);
+            })
+            this.clickCellMap[id] = []
+        },
+
+        handleSave(row){
+          var self = this;
+          //alert(JSON.stringify(row));
+          if(self.checkEmptyInJSON(row)){
+            if(!self.checkIfNumber(row.serialNumber)){
+              self.$message({
+                message: "序号应填写数字,请重新填写!",
+                type: "error",
+              });
+              return 
+            }
+            if(!self.checkIfNumber(row.budgetRevenue)){
+              self.$message({
+                message: "预算收入应填写数字,请重新填写!",
+                type: "error",
+              });
+              return 
+            }
+            if(!self.checkIfNumber(row.curMonthReceived)){
+              self.$message({
+                message: "本月到账资金应填写数字,请重新填写!",
+                type: "error",
+              });
+              return 
+            }
+            if(!self.checkIfNumber(row.actualTotalRevenue)){
+              self.$message({
+                message: "实际总收入应填写数字,请重新填写!",
+                type: "error",
+              });
+              return 
+            }
+            if(!self.checkIfNumber(row.accumulatedArrears)){
+              self.$message({
+                message: "累计欠费应填写数字,请重新填写!",
+                type: "error",
+              });
+              return 
+            } 
+          }
+          else{
+            self.$message({
+              message: "此条数据所有数据全为空,请先填入数据再保存!",
+              type: "error",
+            });
+            return;
+          }
+
+          //alert(JSON.stringify(row))
+
+          self.handleSubmit(row);
+        },
+
+        handleAdd() {
+            this.tableData.push({
+                serialNumber:"",
+                name: "",
+                budgetRevenue:"",
+                accountName:"",
+                curMonthReceived:"",
+                actualTotalRevenue:"",
+                accumulatedArrears:"",
+                incomeTimeRange:"",
+                incomeType:"",
+                endDateStr:"",
+                incomeDepartment:"",
+                attachment:"",
+                accountingName:"",
+                bak:"",
+            });
+        },
+
+        //判断json是否全为空
+        checkEmptyInJSON(jsonObj) {
+          for (let key in jsonObj) {
+              if (jsonObj.hasOwnProperty(key)) {
+                  if (jsonObj[key] != null && jsonObj[key] != undefined && jsonObj[key] != '') {
+                    return true;
+                  }
+              }
+          }
+          return false;
+        },
+
+        //判断是否为数字
+        checkIfNumber(val) {
+          if(val!=null && val!=""){
+            return this.isNumber = /^\d+(\.\d+)?$/.test(val);
+          }
+          else{
+            return true;
+          }
+        },
+
+        handleSubmit(row) {
+          var self = this;
+
+          (function () {
+            var id = row.id;
+
+            if (id == null || id.length == 0) {
+              return expensesInfoApi.add(row);
+            } else {
+              return expensesInfoApi.update(row);
+            }
+          })().then(function (response) {
+            var jsonData = response.data;
+
+            if (jsonData.result) {
+              self.$message({
+                message: "保存成功!",
+                type: "success",
+              });
+
+              self.changePage(1,null)
+            } else {
+              self.$message({
+                message: jsonData.message + "",
+                type: "warning",
+              });
+
+              self.$emit("close", false);
+            }
+          });
+        },
+
+        exportXls() {
+          this.changePage(1,true);
+        },
+
+
+        handleRemove(file, fileList) {
+          console.log(file, fileList);
+        },
+        handlePreview(file) {
+          console.log(file);
+        },
+        handleExceed(files, fileList) {
+          this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
+        },
+        beforeRemove(file, fileList) {
+          return this.$confirm(`确定移除 ${ file.name }?`);
+        },
+
+        handleGenerateData(templateId){
+          var self = this;
+          self.$confirm("生成数据后列表原数据会被覆盖,请谨慎操作!确认生成数据?", "提示", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          }).then(() => {
+            expensesInfoApi.generateData(templateId).then(function(response) {
+              var jsonData = response.data;
+    
+              if (jsonData.result) {
+                // var index = self.tableData.indexOf(record);
+               // self.tableData.splice(index, 1);
+                self.changePage(self.pageIndex); 
+    
+                self.$message({
+                  type: "success",
+                  message: "生成数据成功!"
+                });
+
+                self.batchImportVisible2 = false
+              }
+            });
+          });
+        },
+
+        saveNum(row){
+          var sumNum = row.total + row.curMonthReceived;
+          row.actualTotalRevenue = sumNum;
+
+          row.accumulatedArrears = row.budgetRevenue-sumNum;
+        
+          this.save(row);
+        },
+        handleAvatarSuccess(res, row) {
+          row.attachment = res.data;
+        },
+        beforeAvatarUpload(file) {
+          const isLt2M = file.size / 1024 / 1024 < 2;
+    
+          if (!isLt2M) {
+            this.$message.error("上传头像图片大小不能超过 2MB!");
+          }
+          return isLt2M;
+        },
+      
+    },
+    mounted: function() {
+      var self = this;
+      self.changePage(1,null);
+    },
+    components: {
+    }
+  };
+  </script>
+  <style lang="scss" scoped>
+  .el-breadcrumb {
+    margin: 10px;
+    line-height: 20px;
+  }
+  
+  .el-divider {
+    margin: 5px 0;
+  }
+  
+  .demo-form-inline {
+    margin-left: 10px;
+    text-align: left;
+  }
+  
+  .button-group {
+    padding: 10px;
+    text-align: left;
+  }
+
+  .item{
+    .item__input{
+      display: none;
+      /* 调整elementUI中样式 如果不需要调整请忽略 */
+      .el-input__inner{
+        height: 24px!important;
+      }
+      /* 调整elementUI中样式 如果不需要调整请忽略 */
+      .el-input__suffix{
+        i{
+          font-size: 12px !important;
+          line-height: 26px !important;
+        }
+      }
+    }
+    .item__txt{
+      box-sizing: border-box;
+      border: 1px solid transparent;
+      line-height: 24px;
+      padding: 0 8px;
+    }
+    .item__txt--hover{
+      border: 1px solid #dddddd;
+      border-radius: 4px;
+      cursor: text;
+    }
+  }
+  .hand-cursor {
+  cursor: pointer; /* 将鼠标光标设置为手形 */
+}
+  </style>

+ 850 - 0
src/views/base/fundIncomeInfo-list.vue

@@ -0,0 +1,850 @@
+<template>
+    <div class="cesiumTabRoot">
+      <el-breadcrumb separator=">">
+        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+        <el-breadcrumb-item>
+          <a href="#">基础信息管理</a>
+        </el-breadcrumb-item>
+        <el-breadcrumb-item>
+          经费收入
+        </el-breadcrumb-item>
+      </el-breadcrumb>
+      <el-divider></el-divider>
+      <!--
+        要resetFields起作用,必须配置:model和prop
+      -->
+      <el-form ref="queryForm" :model="queryModel" inline class="demo-form-inline">
+        <el-form-item label="年份" prop="yearMonth">
+          <el-date-picker
+            size="mini"
+            v-model="queryModel.yearMonth"
+            type="month"
+            placeholder="选择年月"
+            value-format="yyyy-MM"
+            format="yyyy-MM">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="项目名称" prop="name">
+          <el-input type="text" size="mini" v-model="queryModel.name" ></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button
+            type="primary"
+            size="mini"
+            icon="ios-search"
+            @click="changePage(1)"
+            :loading="loading"
+          >查询</el-button>&nbsp;
+          <el-button
+            type="info"
+            size="mini"
+            style="margin-left: 8px"
+            @click="handleReset('queryForm')"
+          >重置</el-button>&nbsp;
+        </el-form-item>
+      </el-form>
+      <el-divider></el-divider>
+      <el-row class="button-group">
+        <!-- <el-button type="primary" size="small" @click="handleAdd" plain icon="el-icon-circle-plus" >新增</el-button>
+        <el-button
+          type="primary"
+          size="small"
+          plain
+          icon="el-icon-upload"
+          @click="batchImportVisible = true"
+        >导入</el-button> -->
+        <el-button
+          type="primary"
+          size="small"
+          plain
+          icon="el-icon-upload2"
+          @click="exportXls"
+        >导出数据</el-button>
+        <span style="float: right;">
+          <permission-detect class="inline" path="/base/fundIncomeInfo/generateData" method="post">
+            <el-button type="danger"
+            size="small" 
+            style="text-align:right" 
+            icon="el-icon-s-data" 
+            @click="batchImportVisible2 = true">生成列表项目</el-button>
+          </permission-detect>
+        </span>
+        
+      </el-row>
+      
+      <el-table
+        :data="tableData"
+        style="min-height:400px;"
+        height="500"
+        v-loading="loading"
+        stripe
+        border
+        @cell-click="handleCellClick"
+        :row-class-name="tableRowClassName"
+      >
+        <!-- <el-table-column label="操作" fixed>
+          <template slot-scope="{row}" >
+            <i class="el-icon-plus hand-cursor" @click="handleAdd"></i>
+            <i class="el-icon-delete hand-cursor" @click="handleDelete(row)" style="margin-left:15px"></i>
+          </template>
+        </el-table-column> -->
+        <el-table-column label="保存" fixed>
+          <template slot-scope="{row}" >
+            <el-button type="primary" size="mini" @click="handleSave(row)" plain>保存</el-button>
+          </template>
+        </el-table-column>
+        <el-table-column  prop="serialNumber" fixed label="序号">
+            <!-- <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.serialNumber" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.serialNumber}}</div>
+            </div> -->
+        </el-table-column>
+        <el-table-column  prop="name" fixed label="项目名称" width="300">
+            <!-- <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.name" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.name}}</div>
+            </div> -->
+        </el-table-column>
+        <el-table-column  prop="budgetRevenue"  label="预算收入" width="200">
+            <!-- <div class="item" slot-scope="scope">
+                <el-input-number 
+                style="width:180px"
+                size="mini" 
+                class="item__input" 
+                :precision="2" :step="0.1"
+                v-model="scope.row.budgetRevenue" 
+                @blur="save(scope.row)">
+                </el-input-number>
+                <div class="item__txt">{{scope.row.budgetRevenue}}</div>
+            </div> -->
+        </el-table-column>
+        <el-table-column  prop="accountName"  label="账户名称" width="180">
+            <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.accountName" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.accountName}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="curMonthReceived"  label="本月到账资金" width="200">
+            <div class="item" slot-scope="scope">
+                <el-input-number 
+                style="width:180px"
+                size="mini" 
+                class="item__input" 
+                :precision="2" :step="0.1"
+                v-model="scope.row.curMonthReceived" 
+                @blur="saveNum(scope.row)">
+              </el-input-number>
+                <div class="item__txt">{{scope.row.curMonthReceived}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="actualTotalRevenue"  label="实际总收入"  width="200">
+            <div class="item" slot-scope="scope">
+                <el-input-number 
+                style="width:180px"
+                 size="mini" 
+                 class="item__input" 
+                 :precision="2" :step="0.1"
+                 v-model="scope.row.actualTotalRevenue" 
+                 @blur="save(scope.row)"></el-input-number>
+                <div class="item__txt">{{scope.row.actualTotalRevenue}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="accumulatedArrears"  label="累计欠费" width="200">
+            <div class="item" slot-scope="scope">
+                <el-input-number
+                style="width:180px"
+                  size="mini" 
+                  class="item__input" 
+                  :precision="2" :step="0.1"
+                  v-model="scope.row.accumulatedArrears"
+                  @blur="save(scope.row)"></el-input-number>
+                <div class="item__txt">{{scope.row.accumulatedArrears}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="incomeTimeRange"  label="收入时间区间" width="200">
+            <!-- <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.incomeTimeRange" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.incomeTimeRange}}</div>
+            </div> -->
+        </el-table-column>
+        <el-table-column  prop="incomeType"  label="收入类型" width="120">
+            <!-- <div class="item" slot-scope="scope">
+                <el-select size="mini" v-model="scope.row.incomeType" class="item__input" placeholder="请选择" @change="save(scope.row)"  >
+                  <el-option
+                    v-for="item in typeList"
+                    :key="item.value"
+                    :label="item.name"
+                    :value="item.value">
+                  </el-option>
+                </el-select>
+                <div class="item__txt">{{scope.row.incomeTypeN}}</div>
+            </div> -->
+        </el-table-column>
+        <el-table-column  prop="endDateStr"  label="终止日" width="150">
+            <!-- <div class="item" slot-scope="scope">
+                <el-date-picker
+                  style="width:130px"
+                  size="mini"
+                  class="item__input"
+                  @blur="save(scope.row)"
+                  v-model="scope.row.endDateStr"
+                  type="date"
+                  placeholder="选择日期"
+                  value-format="yyyy-MM-dd"
+                  format="yyyy-MM-dd">
+                </el-date-picker>
+                <div class="item__txt">{{scope.row.endDateStr}}</div>
+            </div> -->
+        </el-table-column>
+        <el-table-column  prop="incomeDepartment"  label="收入实现部门"  width="200">
+            <!-- <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.incomeDepartment" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.incomeDepartment}}</div>
+            </div> -->
+        </el-table-column>
+        <el-table-column  prop="accountingName"  label="会计主体名称" width="200">
+            <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.accountingName" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.accountingName}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="bak"  label="备注" width="180">
+            <div class="item" slot-scope="scope">
+                <el-input size="mini" class="item__input" v-model="scope.row.bak" @blur="save(scope.row)"></el-input>
+                <div class="item__txt">{{scope.row.bak}}</div>
+            </div>
+        </el-table-column>
+        <el-table-column  prop="yearMonthStr"  label="所属年月" width="120"></el-table-column>
+        <el-table-column  prop="attachment"  label="附件">
+          <template slot-scope="scope">
+            <el-link type="primary" :href="scope.row.attachment" target="_blank" :underline="false">
+            <el-image
+              style="width: 35px; height: 35px"
+              v-if="scope.row.attachment"
+              :src="scope.row.attachment"
+              :fit="fit">
+            </el-image>
+            </el-link>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-dialog
+      title="批量导入数据"
+      :visible.sync="batchImportVisible"
+      :modal-append-to-body="false"
+      style="text-align: left"
+      :close-on-click-modal="false"
+    >
+      <el-form label-width="150px">
+        <el-form-item label="模板下载">
+          <el-link
+            href="https://oss.xiaoxinda.com/jk-temporary-workers/person.xls"
+            type="primary"
+            target="_blank"
+            >点击下载模板</el-link
+          >
+        </el-form-item>
+        <el-form-item label="上传文件">
+          <el-upload
+            class="upload-demo"
+            accept=".xls"
+            :action="uploadUrlXls"
+            :data="uploadXlsData"
+            :headers="headers"
+            name="uploadFile"
+            :multiple="true"
+            :limit="1"
+            :file-list="batchImportFileList"
+          >
+            <el-button size="small" type="primary" :loading="xlsLoading"
+              >点击上传</el-button
+            >
+            <div slot="tip" class="el-upload__tip">
+              只能上传xls文件,且不超过500kb
+            </div>
+          </el-upload>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="batchImportVisible = false"
+          >关 闭</el-button
+        >
+      </div>
+    </el-dialog>
+
+
+    <el-dialog
+      title="选择模版"
+      :visible.sync="batchImportVisible2"
+      :modal-append-to-body="false"
+      style="text-align: left"
+      :close-on-click-modal="false"
+    >
+      <el-form label-width="150px" >
+        <el-form-item label="年份" prop="selectYear">
+          <el-date-picker
+            v-model="selectYear"
+            type="year"
+            placeholder="选择年"
+            value-format="yyyy"
+            format="yyyy">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="模版" prop="selectTamplateId">
+          <el-select v-model="selectTamplateId" placeholder="请选择" style="width:400px">
+            <el-option
+              v-for="item in templateList"
+              :key="item.id"
+              :label="item.title"
+              :value="item.id">
+            </el-option>
+          </el-select>
+      </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="batchImportVisible2 = false"
+          >关 闭</el-button
+        >
+        <el-button type="danger" @click="handleGenerateData(selectTamplateId,selectYear)" :loading="submitting"
+          >生 成</el-button
+        >
+      </div>
+    </el-dialog>
+    </div>
+  </template>
+  <script>
+  import Constant from "@/constant";
+  import fundIncomeInfoApi from "@/api/base/fundIncomeInfo";
+  import templateInfoApi from "@/api/base/templateInfo";
+  import { getToken } from "@/utils/auth"; // get token from cookie
+  import permissionApi from "@/api/sys/permission";
+  
+  export default {
+    name: 'baseFundIncomeInfoInfo',
+    data() {
+      var self = this;
+  
+      return {
+        queryModel: {
+          yearMonth: "",
+          name: "",
+        },
+        loading: false,
+        tableData: [],
+        pageIndex: 1,
+        pageSize: 10,
+        totalPages: 0,
+        totalElements: 0,
+        field: "",
+        direction: "",
+        pageSizeList: [10, 20, 30],
+        multipleSelection: [],
+        modalTitle: "",      
+        businessKey: "",
+        showModal: false,
+        dialogFormVisible:false,
+        batchImportVisible: false,
+        batchImportVisible2:false,
+        xlsLoading: false,
+        submitting:false,
+        selectTamplateId:"",
+        selectYear:"",
+        batchImportFileList: [],
+        chargingStationResult:[],
+        fit: 'fill',
+        // 需要编辑的属性
+        editProp: ['accountName','curMonthReceived','incomeTimeRange','incomeType',
+        'endDateStr','incomeDepartment','accountingName','bak'],
+         // 保存进入编辑的cell
+        clickCellMap: {},
+        templateList:[],
+        uploadUrlXls: Constant.serverUrl + "/base/fundIncomeInfo/importXls",
+        uploadXlsData: {
+            subFolder: "personInfo",
+        },
+        headers: {
+            Authorization: getToken(),
+        },
+        //上传地址
+        uploadUrl: Constant.serverUrl + "/uploadPicture",
+        uploadData: {
+          subFolder: "fundIncomeInfo",
+        },
+        fileUrl: "",
+        typeList:[
+          {
+            "name":"按月",
+            "value":"1"
+          },
+          {
+            "name":"按年",
+            "value":"2"
+          },
+          {
+            "name":"按季",
+            "value":"3"
+          },
+          {
+            "name":"按学期",
+            "value":"4"
+          },
+        ],
+
+      };
+    },
+    created(){
+      var self = this;
+    
+      templateInfoApi.list().then(function (response) {
+        var jsonData = response.data;
+        if (jsonData.result) {
+          if (jsonData.data != null && jsonData.data != "") {
+            self.templateList = jsonData.data;
+          }
+        }
+      });
+
+      self.getNowTime();
+    },
+    methods: {
+      handleEditNum(event,row){
+          if(event!=0){
+            var sumNum = row.actualTotalRevenue + row.curMonthReceived;
+            row.actualTotalRevenue = sumNum;
+          }
+      },
+      getNowTime() {
+        var now = new Date();
+        var year = now.getFullYear(); //得到年份
+        var month = now.getMonth(); //得到月份
+        month = month + 1;
+        month = month.toString().padStart(2, "0");
+        var defaultDate = `${year}-${month}`;
+        this.$set(this.queryModel, "yearMonth", defaultDate);
+      },
+      changePage(pageIndex,exportFlag) {
+        var self = this;
+  
+        console.log(pageIndex);
+  
+        self.pageIndex = pageIndex;
+        var formData = new FormData();
+  
+        formData.append("name", self.queryModel.name);
+        formData.append("yearMonth", self.queryModel.yearMonth);
+
+        if(exportFlag!=null){
+            formData.append("exportFlag", exportFlag);
+        }
+
+        self.loading = true;
+  
+        fundIncomeInfoApi.pageList(formData).then(function(response) {
+          self.loading = false;
+            var jsonData = response.data;
+            if(jsonData.result) {
+                if(exportFlag){
+                    //导出
+                    self.$message({
+                        showClose: true,
+                        type: "success",
+                        message: `报表已生成,<a href="${jsonData.data}">请点击链接下载</a>`,
+                        dangerouslyUseHTMLString: true,
+                        duration: 30000
+                    });
+                }
+                else{
+                    //分页查看
+                    var page = jsonData.data;
+
+                    self.tableData = page.data;
+                    // self.totalPages = page.totalPages;
+                    // self.totalElements = page.recordsTotal;
+                }
+            }
+            else{
+                self.$message.warning(jsonData.message);
+            }
+        }).catch((error)=>{
+          self.loading = false;
+        });
+      },
+      handleReset(name) {
+        this.$refs[name].resetFields();
+      },
+      handleDelete(record) {
+        var self = this;
+        if(record.id==null||record.id==""){
+            self.$message({
+                type: "error",
+                message: "该条记录未填写数据无需删除!"
+            });
+            return;
+        }
+  
+        this.$confirm("是否确认删除?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          fundIncomeInfoApi.remove(record.id).then(function(response) {
+            var jsonData = response.data;
+  
+            if (jsonData.result) {
+              // var index = self.tableData.indexOf(record);
+              // self.tableData.splice(index, 1);
+              self.changePage(self.pageIndex);
+  
+              self.$message({
+                type: "success",
+                message: "删除成功!"
+              });
+
+              var datalist = self.formModel.tableData;
+
+              datalist.splice(datalist.indexOf(record), 1);
+            }
+          });
+        });
+      },
+
+
+        // /** 鼠标移入cell */
+        // handleCellEnter (row, column, cell, event) {
+        //     const property = column.property
+        //     if (property === 'date' || property === 'name' || property === 'food') {
+        //         cell.querySelector('.item__txt').classList.add('item__txt--hover')
+        //     }
+        // },
+        // /** 鼠标移出cell */
+        // handleCellLeave (row, column, cell, event) {
+        //     const property = column.property
+        //     if (this.editProp.includes(property)) {
+        //         cell.querySelector('.item__txt').classList.remove('item__txt--hover')
+        //     }
+        // },
+
+        /** 点击cell */
+        handleCellClick(row, column, cell, event) {
+            const property = column.property
+            if (this.editProp.includes(property)) {
+                // 保存cell
+                this.saveCellClick(row, cell)
+                cell.querySelector('.item__txt').style.display = 'none'
+                cell.querySelector('.item__input').style.display = 'block'
+                cell.querySelector('input').focus()
+            }
+        },
+        /** 取消编辑状态 */
+        cancelEditable (cell) {
+            cell.querySelector('.item__txt').style.display = 'block'
+            cell.querySelector('.item__input').style.display = 'none'
+        },
+        /** 保存进入编辑的cell */
+        saveCellClick (row, cell) {
+            const id = row.id;
+            if (this.clickCellMap[id] !== undefined) {
+                if (!this.clickCellMap[id].includes(cell)) {
+                  this.clickCellMap[id].push(cell)
+                }
+            } else {
+                this.clickCellMap[id] = [cell]
+            }
+        },
+
+        /** 保存数据 */
+        save (row) {
+            const id = row.id;
+            if(row.incomeType!=""&&row.incomeType!=null){
+              if(row.incomeType=='1'){
+                row.incomeTypeN="按月";
+              }
+              else if(row.incomeType=='2'){
+                row.incomeTypeN="按年";
+              }
+              else if(row.incomeType=='3'){
+                row.incomeTypeN="按季";
+              }
+              else if(row.incomeType=='4'){
+                row.incomeTypeN="按学期";
+              }
+            }
+            
+            // 取消本行所有cell的编辑状态
+            this.clickCellMap[id].forEach(cell => {
+                this.cancelEditable(cell);
+            })
+            this.clickCellMap[id] = []
+        },
+
+        handleSave(row){
+          var self = this;
+          //alert(JSON.stringify(row));
+          if(self.checkEmptyInJSON(row)){
+            if(!self.checkIfNumber(row.serialNumber)){
+              self.$message({
+                message: "序号应填写数字,请重新填写!",
+                type: "error",
+              });
+              return 
+            }
+            if(!self.checkIfNumber(row.budgetRevenue)){
+              self.$message({
+                message: "预算收入应填写数字,请重新填写!",
+                type: "error",
+              });
+              return 
+            }
+            if(!self.checkIfNumber(row.curMonthReceived)){
+              self.$message({
+                message: "本月到账资金应填写数字,请重新填写!",
+                type: "error",
+              });
+              return 
+            }
+            if(!self.checkIfNumber(row.actualTotalRevenue)){
+              self.$message({
+                message: "实际总收入应填写数字,请重新填写!",
+                type: "error",
+              });
+              return 
+            }
+            if(!self.checkIfNumber(row.accumulatedArrears)){
+              self.$message({
+                message: "累计欠费应填写数字,请重新填写!",
+                type: "error",
+              });
+              return 
+            } 
+          }
+          else{
+            self.$message({
+              message: "此条数据所有数据全为空,请先填入数据再保存!",
+              type: "error",
+            });
+            return;
+          }
+
+          //alert(JSON.stringify(row))
+
+          self.handleSubmit(row);
+        },
+
+        handleAdd() {
+            this.tableData.push({
+                serialNumber:"",
+                name: "",
+                budgetRevenue:"",
+                accountName:"",
+                curMonthReceived:"",
+                actualTotalRevenue:"",
+                accumulatedArrears:"",
+                incomeTimeRange:"",
+                incomeType:"",
+                endDateStr:"",
+                incomeDepartment:"",
+                attachment:"",
+                accountingName:"",
+                bak:"",
+            });
+        },
+
+        //判断json是否全为空
+        checkEmptyInJSON(jsonObj) {
+          for (let key in jsonObj) {
+              if (jsonObj.hasOwnProperty(key)) {
+                  if (jsonObj[key] != null && jsonObj[key] != undefined && jsonObj[key] != '') {
+                    return true;
+                  }
+              }
+          }
+          return false;
+        },
+
+        //判断是否为数字
+        checkIfNumber(val) {
+          if(val!=null && val!=""){
+            return this.isNumber = /^\d+(\.\d+)?$/.test(val);
+          }
+          else{
+            return true;
+          }
+        },
+
+        handleSubmit(row) {
+          var self = this;
+
+          (function () {
+            var id = row.id;
+
+            if (id == null || id.length == 0) {
+              return fundIncomeInfoApi.add(row);
+            } else {
+              return fundIncomeInfoApi.update(row);
+            }
+          })().then(function (response) {
+            var jsonData = response.data;
+
+            if (jsonData.result) {
+              self.$message({
+                message: "保存成功!",
+                type: "success",
+              });
+
+              self.changePage(1,null)
+            } else {
+              self.$message({
+                message: jsonData.message + "",
+                type: "warning",
+              });
+
+              self.$emit("close", false);
+            }
+          });
+        },
+
+        exportXls() {
+          this.changePage(1,true);
+        },
+
+
+        handleRemove(file, fileList) {
+          console.log(file, fileList);
+        },
+        handlePreview(file) {
+          console.log(file);
+        },
+        handleExceed(files, fileList) {
+          this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
+        },
+        beforeRemove(file, fileList) {
+          return this.$confirm(`确定移除 ${ file.name }?`);
+        },
+
+        handleGenerateData(templateId,year){
+          var self = this;
+          self.$confirm("生成数据后列表原数据会被覆盖,请谨慎操作!确认生成数据?", "提示", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          }).then(() => {
+            var formData = new FormData();
+
+            formData.append("templateId", templateId);
+            formData.append("year", year);
+
+            fundIncomeInfoApi.generateData(formData).then(function(response) {
+                var jsonData = response.data;
+                if(jsonData.result) {
+                  self.changePage(self.pageIndex); 
+                  self.$message({
+                    type: "success",
+                    message: "生成数据成功!"
+                  });
+
+                  self.batchImportVisible2 = false
+                }
+                else{
+                    self.$message.warning(jsonData.message);
+                }
+            }).catch((error)=>{
+              self.loading = false;
+            });
+          });
+        },
+
+        saveNum(row){
+          var sumNum = row.total + row.curMonthReceived;
+          row.actualTotalRevenue = sumNum;
+
+          row.accumulatedArrears = row.budgetRevenue-sumNum;
+        
+          this.save(row);
+        },
+        handleAvatarSuccess(res, row) {
+          row.attachment = res.data;
+        },
+        beforeAvatarUpload(file) {
+          const isLt2M = file.size / 1024 / 1024 < 2;
+    
+          if (!isLt2M) {
+            this.$message.error("上传头像图片大小不能超过 2MB!");
+          }
+          return isLt2M;
+        },
+        tableRowClassName({row, rowIndex}) {
+          if (row.isSum) {
+            return 'success-row';
+          }
+          return ''; 
+        }
+      
+    },
+    mounted: function() {
+      var self = this;
+      self.changePage(1,null);
+    },
+    components: {
+    }
+  };
+  </script>
+<style>
+  .el-table .warning-row {
+    background: oldlace;
+  }
+
+  .el-table .success-row {
+    background: #f0f9eb;
+  }
+</style>
+  <style lang="scss" scoped>
+  .el-breadcrumb {
+    margin: 10px;
+    line-height: 20px;
+  }
+  
+  .el-divider {
+    margin: 5px 0;
+  }
+  
+  .demo-form-inline {
+    margin-left: 10px;
+    text-align: left;
+  }
+  
+  .button-group {
+    padding: 10px;
+    text-align: left;
+  }
+
+  .item{
+    .item__input{
+      display: none;
+      /* 调整elementUI中样式 如果不需要调整请忽略 */
+      .el-input__inner{
+        height: 24px!important;
+      }
+      /* 调整elementUI中样式 如果不需要调整请忽略 */
+      .el-input__suffix{
+        i{
+          font-size: 12px !important;
+          line-height: 26px !important;
+        }
+      }
+    }
+    .item__txt{
+      box-sizing: border-box;
+      border: 1px solid transparent;
+      line-height: 24px;
+      padding: 0 8px;
+    }
+    .item__txt--hover{
+      border: 1px solid #dddddd;
+      border-radius: 4px;
+      cursor: text;
+    }
+  }
+  .hand-cursor {
+  cursor: pointer; /* 将鼠标光标设置为手形 */
+  }
+  </style>

+ 237 - 0
src/views/base/templateDepartment-detail.vue

@@ -0,0 +1,237 @@
+
+<template>
+    <el-dialog
+      :visible.sync="showDialog"
+      :title="title"
+      :modal-append-to-body="false"
+      style="text-align: left;"
+      @close="closeDialog"
+      :close-on-click-modal="false"
+      width="1300px"
+    >
+      <div class="user-panel" v-loading="loading">
+        <el-form
+          ref="form"
+          :model="formModel"
+          :rules="ruleValidate"
+          :label-width="'100px'"
+          :inline="true"
+        >
+            <el-table 
+                class="compact-table"
+                :data="formModel.optionList" >
+                <el-table-column prop="serialNum" label="序号" ></el-table-column>
+                <el-table-column prop="name" label="名称" width="200"></el-table-column>
+                <el-table-column prop="budgetRevenue" label="预算收入"></el-table-column>
+                <el-table-column prop="incomeTimeRange" label="收入时间区间" width="180"></el-table-column>
+                <el-table-column prop="incomeTypeN" label="收入类型"></el-table-column>
+                <el-table-column prop="endDate" label="终止日"></el-table-column>
+                <el-table-column prop="departmentNames" label="部门"></el-table-column>
+                <el-table-column prop="isSum" label="是否合计">
+                    <template slot-scope="{row}" >
+                        <span v-if="row.isSum" style="color:#67C23A">是</span>
+                        <span v-else>否</span>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="index" label="排序号" ></el-table-column>
+                <el-table-column label="操作" >
+                  <template slot-scope="{row}" v-if="formModel.status=='0'">
+                    <el-button size="mini" type="warning" @click="handleEdit(row)">编辑</el-button>
+                  </template>
+                </el-table-column>
+            </el-table>
+        </el-form>
+      </div>
+      <div class="el-table__empty-block">
+    </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="closeDialog">取 消</el-button>
+      </span>
+      <templateDepartment-edit
+        v-if="showModal"
+        :businessKey2="businessKey2"
+        :title="modalTitle"
+        @close="onDetailModalClose"
+      ></templateDepartment-edit>
+    </el-dialog>
+  </template>
+  <script>
+  import Constant from "@/constant";
+  import { getToken } from "@/utils/auth"; // get token from cookie
+  import templateOptionApi from "@/api/base/templateOption";
+  import departmentInfoApi from "@/api/base/departmentInfo";
+  import templateDepartmentEdit from "./templateDepartment-edit";
+  
+  export default {
+    props: ["businessKey", "title"],
+    data() {
+      return {
+          ruleValidate: {
+              userName: [
+              { required: true, message: "用户名不能为空", trigger: "blur" },
+              ],
+              realName: [
+              { required: true, message: "真实名称不能为空", trigger: "blur" },
+              ],
+          },
+          roleList: [],
+          formModel: {
+            optionList:[],
+          },
+          showDialog: true,
+          loading: false,
+          submitting: false,
+          enterpriseList:[],
+          optionList:[],
+          departmentList:[],
+          isSumList:[
+          {
+            "label":"否",
+            "value":false
+          },
+          {
+            "label":"是",
+            "value":true
+          }],
+          showModal: false,
+      };
+    },
+    created() {
+      var self = this;
+    
+      departmentInfoApi.list().then(function (response) {
+        var jsonData = response.data;
+        if (jsonData.result) {
+          if (jsonData.data != null && jsonData.data != "") {
+            self.departmentList = jsonData.data;
+          }
+        }
+      });
+    },
+    methods: {
+      closeDialog() {
+        this.$emit("close", false);
+      },
+      handleSubmit() {
+        var self = this;
+  
+        this.$refs["form"].validate((valid) => {
+          if (valid) {
+            (function () {
+                var id = self.formModel.id;
+                self.formModel.templateOptionList = self.formModel.optionList;
+                return templateOptionApi.update(self.formModel);
+            })().then(function (response) {
+              var jsonData = response.data;
+  
+              if (jsonData.result) {
+                self.$message({
+                  message: "保存成功!",
+                  type: "success",
+                });
+  
+                self.$emit("close", true);
+              } else {
+                self.$message({
+                  message: jsonData.message + "",
+                  type: "warning",
+                });
+  
+                self.$emit("close", false);
+              }
+            });
+          }
+        });
+      },
+      handleAdd() {
+        this.formModel.optionList.push({
+            serialNumber: "",
+            name: "",
+        });
+      },
+      handleInsert(row) {
+        this.formModel.optionList.push({
+            serialNumber: "",
+            name: "",
+          });
+      },
+      handleDelete(row) {
+        var optionList = this.formModel.optionList;
+
+        optionList.splice(optionList.indexOf(row), 1);
+      },
+      handleEdit(record) {
+        var self = this;
+        
+        self.modalTitle = "编辑模板";
+        self.businessKey2 = record.id;
+        self.showModal = true;
+      },
+      onDetailModalClose(refreshed) {
+        this.showModal = false;
+        if(refreshed) {
+          this.loadDataList(this.businessKey)
+        }
+      },
+
+      loadDataList(businessKey){
+        var self = this;
+        self.loading = true;
+    
+        (function () {
+            return templateOptionApi.templateDepartmentEdit(businessKey);
+        })()
+          .then((response) => {
+            var jsonData = response.data;
+    
+            if (jsonData.result) {
+              self.formModel = jsonData.data;
+              self.formModel.optionList = jsonData.data.templateOptionList;
+            } else {
+              self.$message.error(jsonData.message + "");
+            }
+    
+            self.loading = false;
+          })
+          .catch((error) => {
+            self.$message.error(error + "");
+            self.loading = false;
+          });
+      }
+    },
+    async mounted() {
+      this.loadDataList(this.businessKey);
+    },
+    components: {
+      "templateDepartment-edit":templateDepartmentEdit
+    },
+  };
+  </script>
+  <style scoped>
+  .user-panel {
+    margin: 10px auto;
+  }
+  .avatar-uploader .el-upload {
+      border: 1px dashed #d9d9d9;
+      border-radius: 6px;
+      cursor: pointer;
+      position: relative;
+      overflow: hidden;
+    }
+    .avatar-uploader .el-upload:hover {
+      border-color: #409EFF;
+    }
+    .avatar-uploader-icon {
+      font-size: 28px;
+      color: #8c939d;
+      width: 178px;
+      height: 178px;
+      line-height: 178px;
+      text-align: center;
+    }
+    .avatar {
+      width: 178px;
+      height: 178px;
+      display: block;
+    }
+  </style>

+ 213 - 0
src/views/base/templateDepartment-edit.vue

@@ -0,0 +1,213 @@
+
+<template>
+    <el-dialog
+    :visible.sync="showModal"
+      :title="modalTitle"
+      :modal-append-to-body="true"
+      style="text-align:left;"
+      :close-on-click-modal="true"
+      @close="closeDialog"
+      :append-to-body="true"
+    >
+      <div class="user-panel" v-loading="loading">
+        <el-form
+          ref="form"
+          :model="formModel"
+          :rules="ruleValidate"
+          :label-width="'100px'"
+          :inline="true"
+        >
+          <el-form-item label="预算收入" prop="budgetRevenue">
+            <el-input-number v-model="formModel.budgetRevenue" placeholder="请输入预算收入" style="width: 300px"></el-input-number>
+          </el-form-item>
+          <el-form-item label="收入时间区间" prop="incomeTimeRangeArr">
+            <el-date-picker
+              style="width: 300px"
+              v-model="formModel.incomeTimeRangeArr"
+              type="monthrange"
+              range-separator="至"
+              start-placeholder="开始月份"
+              end-placeholder="结束月份"
+              value-format='yyyy-MM'
+              format='yyyy-MM'
+              >
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="收入类型" prop="incomeType">
+            <el-select v-model="formModel.incomeType" placeholder="请选择" style="width: 300px" >
+                <el-option
+                  v-for="item in typeList"
+                  :key="item.value"
+                  :label="item.name"
+                  :value="item.value">
+                </el-option>
+              </el-select>
+          </el-form-item>
+          <el-form-item label="终止日" prop="endDate">
+            <el-date-picker
+              style="width: 300px"
+              v-model="formModel.endDate"
+              type="date"
+              placeholder="选择日期"
+              value-format='yyyy-MM-dd'
+              format='yyyy-MM-dd'>
+            </el-date-picker>
+          </el-form-item>
+        </el-form>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="closeDialog">取 消</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="submitting"
+          >保 存</el-button
+        >
+      </span>
+    </el-dialog>
+  </template>
+  <script>
+  import Constant from "@/constant";
+  import { getToken } from "@/utils/auth"; // get token from cookie
+  import templateOptionApi from "@/api/base/templateOption";
+  
+  export default {
+    props: ["businessKey2", "modalTitle"],
+    data() {
+      return {
+          showPwd: true,
+          ruleValidate: {
+              title: [
+              { required: true, message: "标题不能为空", trigger: "blur" },
+              ],
+          },
+          roleList: [],
+          formModel: {},
+          showDialog: true,
+          loading: false,
+          submitting: false,
+          typeList:[
+            {
+              "name":"按月",
+              "value":"1"
+            },
+            {
+              "name":"按年",
+              "value":"2"
+            },
+            {
+              "name":"按季",
+              "value":"3"
+            },
+            {
+              "name":"按学期",
+              "value":"4"
+            },
+          ],
+          
+      };
+    },
+    created() {
+    },
+    methods: {
+      closeDialog() {
+        this.$emit("close", false);
+      },
+      handleSubmit() {
+        var self = this;
+  
+        this.$refs["form"].validate((valid) => {
+          if (valid) {
+            (function () {
+                var id = self.formModel.id;
+                return templateOptionApi.updateItem(self.formModel);
+            })().then(function (response) {
+              var jsonData = response.data;
+  
+              if (jsonData.result) {
+                self.$message({
+                  message: "保存成功!",
+                  type: "success",
+                });
+  
+                self.$emit("close", true);
+              } else {
+                self.$message({
+                  message: jsonData.message + "",
+                  type: "warning",
+                });
+  
+                self.$emit("close", false);
+              }
+            });
+          }
+        });
+      },
+      handleAvatarSuccess(res, file) {
+          var self = this;
+          self.formModel.photo = res.data;
+  
+          self.fileUrl =
+            res.data + "?x-oss-process=image/resize,m_lfit,h_300,w_300";
+      },
+      beforeAvatarUpload(file) {
+          const isLt2M = file.size / 1024 / 1024 < 2;
+          if (!isLt2M) {
+              this.$message.error('上传头像图片大小不能超过 2MB!');
+          }
+          return isLt2M;
+      }
+    },
+    async mounted() {
+      var self = this;
+      self.loading = true;
+  
+      (function () {
+        return templateOptionApi.departmentDetailEdit(self.businessKey2);
+      })()
+        .then((response) => {
+          var jsonData = response.data;
+  
+          if (jsonData.result) {
+              self.formModel = jsonData.data;
+              self.showModal = true;
+          } else {
+            self.$message.error(jsonData.message + "");
+          }
+  
+          self.loading = false;
+        })
+        .catch((error) => {
+          self.$message.error(error + "");
+          self.loading = false;
+        });
+    },
+    components: {
+    },
+  };
+  </script>
+  <style scoped>
+  .user-panel {
+    margin: 10px auto;
+  }
+  .avatar-uploader .el-upload {
+      border: 1px dashed #d9d9d9;
+      border-radius: 6px;
+      cursor: pointer;
+      position: relative;
+      overflow: hidden;
+    }
+    .avatar-uploader .el-upload:hover {
+      border-color: #409EFF;
+    }
+    .avatar-uploader-icon {
+      font-size: 28px;
+      color: #8c939d;
+      width: 178px;
+      height: 178px;
+      line-height: 178px;
+      text-align: center;
+    }
+    .avatar {
+      width: 178px;
+      height: 178px;
+      display: block;
+    }
+  </style>

+ 491 - 0
src/views/base/templateDepartment-list.vue

@@ -0,0 +1,491 @@
+<template>
+    <div>
+      <el-breadcrumb separator=">">
+        <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+        <el-breadcrumb-item>
+          <a href="#">基础信息管理</a>
+        </el-breadcrumb-item>
+        <el-breadcrumb-item>
+          模板管理
+        </el-breadcrumb-item>
+      </el-breadcrumb>
+      <el-divider></el-divider>
+      <!--
+        要resetFields起作用,必须配置:model和prop
+      -->
+      <el-form ref="queryForm" :model="queryModel" inline class="demo-form-inline">
+        <el-form-item label="标题" prop="title">
+          <el-input type="text" size="mini" v-model="queryModel.title"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button
+            type="primary"
+            size="mini"
+            icon="ios-search"
+            @click="changePage(1)"
+            :loading="loading"
+          >查询</el-button>&nbsp;
+          <el-button
+            type="info"
+            size="mini"
+            style="margin-left: 8px"
+            @click="handleReset('queryForm')"
+          >重置</el-button>&nbsp;
+        </el-form-item>
+      </el-form>
+      <el-divider></el-divider>
+      <el-table
+        :data="tableData"
+        style="min-height:400px;"
+        v-loading="loading"
+        stripe
+        @sort-change="sortChange"
+      >
+        <el-table-column  prop="title"  label="标题" width="300"></el-table-column>
+        <el-table-column  prop="subtitle"  label="副标题"></el-table-column>
+        <el-table-column  prop="type"  label="模板类型">
+            <template slot-scope="{row}">
+                <span v-if="row.type=='1'">收入</span>
+                <span v-else-if="row.type=='2'">支出</span>
+            </template>
+        </el-table-column>
+        <el-table-column  prop="status"  label="状态">
+          <template slot-scope="{row}">
+                <span v-if="row.status=='0'" style="color:#F56C6C">未审核</span>
+                <span v-else-if="row.status=='1'" style="color:#67C23A">已审核</span>
+            </template>
+        </el-table-column>
+        <el-table-column  prop="attachment"  label="附件">
+          <template slot-scope="scope">
+            <el-link type="primary" :href="scope.row.attachment" target="_blank" :underline="false">
+            <el-image
+              style="width: 40px; height: 40px"
+              v-if="scope.row.attachment"
+              :src="scope.row.attachment"
+              fit="fit">
+            </el-image>
+            </el-link>
+          </template>
+        </el-table-column>
+        <el-table-column  prop="attachment"  label="上传">
+          <template slot-scope="scope">
+              <el-upload
+                  class="avatar-uploader"
+                  name="photoFile"
+                  :action="uploadUrl"
+                  :show-file-list="false"
+                  :headers="headers"
+                  :data="uploadData"
+                  :on-success="($event) =>{handleAvatarSuccess($event,scope.row)}"
+                  :before-upload="beforeAvatarUpload"
+                >
+              <el-link type="primary">上传</el-link>
+            </el-upload>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="300">
+          <template slot-scope="{row}" >
+            <el-button v-if="row.attachment&&row.status=='0'" size="mini" type="warning" @click="handleSave(row)">保存附件</el-button>
+            <el-button size="mini" type="primary" @click="handleOption(row)">模板选项</el-button>
+            <el-button v-if="row.status=='0'" size="mini" type="success" @click="handleChecked(row)">审核</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination
+        :current-page.sync="pageIndex"
+        :total="totalElements"
+        :page-sizes="pageSizeList"
+        @current-change="changePage"
+        @size-change="pageSizeChange"
+        layout="total, sizes, prev, pager, next, jumper"
+      ></el-pagination>
+      <templateDepartment-detail
+        v-if="showModal2"
+        ref="userDetail"
+        :businessKey="businessKey"
+        :title="modalTitle2"
+        @close="onDetailModalClose2"
+      ></templateDepartment-detail>
+
+    </div>
+  </template>
+  <script>
+  import Constant from "@/constant";
+  import templateInfoApi from "@/api/base/templateInfo";
+  import templateDepartmentDetail from "./templateDepartment-detail";
+  import { getToken } from "@/utils/auth"; // get token from cookie
+  
+  export default {
+    name: 'baseTemplateDepartmentList',
+    data() {
+      var self = this;
+  
+      return {
+        queryModel: {
+          realName: "",
+          phone:"",
+          idCard:"",
+          status:"",
+        },
+        loading: false,
+        tableData: [],
+        pageIndex: 1,
+        pageSize: 10,
+        totalPages: 0,
+        totalElements: 0,
+        field: "",
+        direction: "",
+        pageSizeList: [10, 20, 30],
+        multipleSelection: [],
+        modalTitle: "",
+        modalTitle2: "",        
+        businessKey: "",
+        showModal: false,
+        showModal2:false,
+        dialogFormVisible:false,
+        newPassword:"",
+        roleResult:[],
+        props: {
+          // 配置项(必选)
+          value: "id",
+          label: "name",
+          children: "children"
+        },
+        batchImportVisible: false,
+        xlsLoading: false,
+        batchImportFileList: [],
+        chargingStationResult:[],
+        uploadUrlXls: Constant.serverUrl + "/base/personInfo/importXls",
+        uploadXlsData: {
+            subFolder: "personInfo",
+        },
+        headers: {
+            Authorization: getToken(),
+        },
+        //上传地址
+        uploadUrl: Constant.serverUrl + "/uploadPicture",
+        uploadData: {
+          subFolder: "fundIncomeInfo",
+        },
+        fileUrl: "",
+        statusList:[
+          {
+            "id":"0",
+            "name":"未认证",
+            "value":"0"
+          },
+          {
+            "id":"1",
+            "name":"已认证",
+            "value":"1"
+          }
+        ],
+      };
+    },
+    methods: {
+      changePage(pageIndex,exportFlag) {
+        var self = this;
+  
+        console.log(pageIndex);
+  
+        self.pageIndex = pageIndex;
+        var formData = new FormData();
+  
+        formData.append("pageIndex", self.pageIndex);
+        
+        if(exportFlag!=null){
+            formData.append("exportFlag", exportFlag);
+            formData.append("pageSize", 10000);
+        }
+        else{
+            formData.append("pageSize", self.pageSize);
+        }
+        formData.append("realName", self.queryModel.realName);
+        formData.append("phone", self.queryModel.phone);
+        formData.append("idCard", self.queryModel.idCard);
+        formData.append("status", self.queryModel.status);
+  
+        self.loading = true;
+  
+        templateInfoApi.pageList(formData).then(function(response) {
+          self.loading = false;
+            var jsonData = response.data;
+            if(jsonData.result) {
+                if(exportFlag){
+                    //导出
+                    self.$message({
+                        showClose: true,
+                        type: "success",
+                        message: `报表已生成,<a href="${jsonData.data}">请点击链接下载</a>`,
+                        dangerouslyUseHTMLString: true,
+                        duration: 30000
+                    });
+                }
+                else{
+                    //分页查看
+                    var page = jsonData.data;
+
+                    self.tableData = page.data;
+                    self.totalPages = page.totalPages;
+                    self.totalElements = page.recordsTotal;
+                }
+            }
+            else{
+                self.$message.warning(jsonData.message);
+            }
+        }).catch((error)=>{
+          self.loading = false;
+        });
+      },
+      pageSizeChange(pageSize) {
+        this.pageSize = pageSize;
+      },
+      sortChange(data) {
+        this.field = data.column.field;
+        this.direction = data.order == "ascending" ? "asc" : "desc";
+  
+        this.changePage(this.pageIndex);
+      },
+      handleSelectionChange(val) {
+        this.multipleSelection = val;
+      },
+      handleReset(name) {
+        this.$refs[name].resetFields();
+      },
+      handleAdd() {
+        var self = this;
+        
+        self.modalTitle = "新增模板";
+        self.businessKey = "";
+        self.showModal = true;
+      },
+      handleEdit(record) {
+        var self = this;
+        
+        self.modalTitle = "编辑模板";
+        self.businessKey = record.id;
+        self.showModal = true;
+      },
+      handleOption(record){
+        var self = this;
+        
+        self.modalTitle2 = "编辑项目";
+        self.businessKey = record.id;
+        self.showModal2 = true;
+      },
+      handleSave(row){
+        var self = this;
+
+        var formData = new FormData();
+
+        formData.append("id", row.id);
+        formData.append("attachment", row.attachment);
+
+        templateInfoApi.saveAttachment(formData).then(function(response) {
+          self.loading = false;
+            var jsonData = response.data;
+            if(jsonData.result) {
+              self.$message({
+                message: "保存成功!",
+                type: "success",
+              });
+              self.changePage(self.pageIndex);
+            }
+            else{
+                self.$message.warning(jsonData.message);
+            }
+        }).catch((error)=>{
+          self.loading = false;
+        });
+      },
+      handleChecked(record){
+        var self = this;
+
+        this.$confirm("审核后模板不能修改,是否确认审核?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+            templateInfoApi.checked(record.id).then(function(response) {
+            var jsonData = response.data;
+  
+            if (jsonData.result) {
+              // var index = self.tableData.indexOf(record);
+              // self.tableData.splice(index, 1);
+              self.changePage(self.pageIndex);
+  
+              self.$message({
+                type: "success",
+                message: "审核成功!"
+              });
+            }
+          });
+        });
+      },
+      handleDelete(record) {
+        var self = this;
+  
+        this.$confirm("是否确认删除?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+            templateInfoApi.remove(record.id).then(function(response) {
+            var jsonData = response.data;
+  
+            if (jsonData.result) {
+              // var index = self.tableData.indexOf(record);
+              // self.tableData.splice(index, 1);
+              self.changePage(self.pageIndex);
+  
+              self.$message({
+                type: "success",
+                message: "删除成功!"
+              });
+            }
+          });
+        });
+      },
+      handleBatchDelete() {
+        var self = this;
+  
+        var idList = this.multipleSelection.map(record => {
+          return record.id;
+        });
+  
+        this.$confirm("是否确认删除选中项?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+            templateInfoApi.batchRemove(idList).then(function(response) {
+            var jsonData = response.data;
+  
+            if (jsonData.result) {
+              self.changePage(self.pageIndex);
+  
+              self.$message({
+                type: "success",
+                message: "删除成功!"
+              });
+            }
+          });
+        });
+      },
+      exportXls() {
+        this.changePage(1,true);
+      },
+        onDetailModalClose(refreshed) {
+            this.showModal = false;
+    
+            if(refreshed) {
+            this.changePage(this.pageIndex);
+            }
+        },
+        onDetailModalClose2(refreshed) {
+            this.showModal2 = false;
+    
+            if(refreshed) {
+            this.changePage(this.pageIndex);
+            }
+        },
+        beforeUpload(file, fileList) {
+            //导入前判断
+            var self = this;
+            self.xlsLoading = true;
+            return true;
+        },
+        //批量导入-上传成功
+        handleBatchImportSuccess(response, file, fileList) {
+        var self = this;
+        self.xlsLoading = false;
+
+        if (response.result) {
+            self.$message.success(response.message);
+            this.batchImportFileList = [];
+            this.changePage(1);
+
+
+        } else {
+            //this.$message.error(response.message);
+            this.batchImportFileList = [];
+            this.changePage(1);
+
+            if (response.data != null) {
+            //下载有错误信息提示的报表
+            //window.open(response.data);
+            self.$message({
+                showClose: true,
+                dangerouslyUseHTMLString: true,
+                message:
+                response.message +
+                `,<a href="${response.data}" target="_blank">点击下载未导入的数据报表</a>&nbsp;`,
+                duration: 30000,
+            });
+            }
+        }
+
+        this.batchImportVisible = false;
+        },
+        //批量导入-预览
+        handleBatchImportPreview(file) {
+        console.log(file.url);
+        },
+        //批量导入-移除
+        handleBatchImportRemove(file, fileList) {
+        console.log(file, fileList);
+        },
+        //批量导入-移除前操作
+        beforeBatchImportRemove(file, fileList) {
+        console.log(file, fileList);
+        },
+        //批量导入-文件超出个数限制时的钩子
+        handleBatchImportExceed(files, fileList) {
+        this.$message.warning(
+            `当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${
+            files.length + fileList.length
+            } 个文件`
+        );
+        },
+
+        handleAvatarSuccess(res, row) {
+          row.attachment = res.data;
+        },
+        beforeAvatarUpload(file) {
+          const isLt2M = file.size / 1024 / 1024 < 2;
+    
+          if (!isLt2M) {
+            this.$message.error("上传头像图片大小不能超过 2MB!");
+          }
+          return isLt2M;
+        }
+    },
+    mounted: function() {
+      var self = this;
+      this.changePage(1);
+    },
+    components: {
+        "templateDepartment-detail":templateDepartmentDetail
+    }
+  };
+  </script>
+  <style lang="scss" scoped>
+  .el-breadcrumb {
+    margin: 10px;
+    line-height: 20px;
+  }
+  
+  .el-divider {
+    margin: 5px 0;
+  }
+  
+  .demo-form-inline {
+    margin-left: 10px;
+    text-align: left;
+  }
+  
+  .button-group {
+    padding: 10px;
+    text-align: left;
+  }
+  </style>

+ 2 - 2
src/views/base/templateInfo-detail.vue

@@ -68,11 +68,11 @@
           typeList:[
             {
                 "name":"收入",
-                "value":"0",
+                "value":"1",
             },
             {
                 "name":"支出",
-                "value":"1",
+                "value":"2",
             }
           ]
       };

+ 36 - 7
src/views/base/templateInfo-list.vue

@@ -17,9 +17,6 @@
         <el-form-item label="标题" prop="title">
           <el-input type="text" size="mini" v-model="queryModel.title"></el-input>
         </el-form-item>
-        <el-form-item label="联系电话" prop="phone">
-          <el-input type="text" size="mini" v-model="queryModel.phone"></el-input>
-        </el-form-item>
         <el-form-item>
           <el-button
             type="primary"
@@ -65,11 +62,18 @@
                 <span v-else-if="row.type=='2'">支出</span>
             </template>
         </el-table-column>
-        <el-table-column  prop="serialNum"  label="序号"></el-table-column>
+        <!-- <el-table-column  prop="serialNum"  label="序号"></el-table-column> -->
+        <el-table-column  prop="status"  label="状态">
+          <template slot-scope="{row}">
+                <span v-if="row.status=='0'" style="color:#F56C6C">未审核</span>
+                <span v-else-if="row.status=='1'" style="color:#67C23A">已审核</span>
+            </template>
+        </el-table-column>
         <el-table-column  prop="createTime"  label="创建时间" width="180"></el-table-column>
-        <el-table-column label="操作">
+        <el-table-column label="操作" width="250">
           <template slot-scope="{row}" >
             <el-button size="mini" type="warning" @click="handleEdit(row)">编辑</el-button>
+            <el-button size="mini" type="primary" @click="handleOption(row)">模板选项</el-button>
             <el-button size="mini" type="danger" @click="handleDelete(row)">删除</el-button>
           </template>
         </el-table-column>
@@ -89,6 +93,13 @@
         :title="modalTitle"
         @close="onDetailModalClose"
       ></templateInfo-detail>
+      <templateInfo-option-list
+        v-if="showModal2"
+        ref="userDetail"
+        :businessKey="businessKey"
+        :title="modalTitle2"
+        @close="onDetailModalClose2"
+      ></templateInfo-option-list>
 
     </div>
   </template>
@@ -96,6 +107,7 @@
   import Constant from "@/constant";
   import templateInfoApi from "@/api/base/templateInfo";
   import templateInfoDetail from "./templateInfo-detail";
+  import templateInfoOptionList from "./templateInfo-option-list";
   import { getToken } from "@/utils/auth"; // get token from cookie
   
   export default {
@@ -120,9 +132,11 @@
         direction: "",
         pageSizeList: [10, 20, 30],
         multipleSelection: [],
-        modalTitle: "",      
+        modalTitle: "",
+        modalTitle2: "",        
         businessKey: "",
         showModal: false,
+        showModal2:false,
         dialogFormVisible:false,
         newPassword:"",
         roleResult:[],
@@ -241,6 +255,13 @@
         self.businessKey = record.id;
         self.showModal = true;
       },
+      handleOption(record){
+        var self = this;
+        
+        self.modalTitle2 = "编辑项目";
+        self.businessKey = record.id;
+        self.showModal2 = true;
+      },
       handleDelete(record) {
         var self = this;
   
@@ -301,6 +322,13 @@
             this.changePage(this.pageIndex);
             }
         },
+        onDetailModalClose2(refreshed) {
+            this.showModal2 = false;
+    
+            if(refreshed) {
+            this.changePage(this.pageIndex);
+            }
+        },
         beforeUpload(file, fileList) {
             //导入前判断
             var self = this;
@@ -365,7 +393,8 @@
       this.changePage(1);
     },
     components: {
-        "templateInfo-detail":templateInfoDetail
+        "templateInfo-detail":templateInfoDetail,
+        "templateInfo-option-list":templateInfoOptionList
     }
   };
   </script>

+ 288 - 0
src/views/base/templateInfo-option-list.vue

@@ -0,0 +1,288 @@
+
+<template>
+    <el-dialog
+      :visible.sync="showDialog"
+      :title="title"
+      :modal-append-to-body="false"
+      style="text-align: left;"
+      @close="closeDialog"
+      :close-on-click-modal="false"
+      width="1200px"
+    >
+      <div class="user-panel" v-loading="loading">
+        <el-form
+          ref="form"
+          :model="formModel"
+          :rules="ruleValidate"
+          :label-width="'100px'"
+          :inline="true"
+        >
+            <el-table 
+                class="compact-table"
+                :data="formModel.optionList" >
+                <el-table-column prop="serialNum" label="序号" width="150">
+                    <template slot-scope="scope">
+                        <el-form-item
+                        :prop="'optionList.' + scope.$index + '.serialNum'"
+                        :rules="ruleValidate['serialNum']"
+                        >
+                        <el-input placeholder="序号"  v-model="scope.row.serialNum"  size="mini"> 
+                        </el-input>
+                        </el-form-item>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="name" label="名称" width="250">
+                    <template slot-scope="scope">
+                        <el-form-item
+                        :prop="'optionList.' + scope.$index + '.name'"
+                        :rules="ruleValidate['name']"
+                        >
+                        <el-input placeholder="名称"  v-model="scope.row.name"  size="mini" style="width:200px"> 
+                        </el-input>
+                        </el-form-item>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="budgetRevenue" label="预算收入" width="180">
+                    <template slot-scope="scope">
+                        <el-form-item
+                        :prop="'optionList.' + scope.$index + '.budgetRevenue'"
+                        :rules="ruleValidate['budgetRevenue']"
+                        >
+                        <el-input-number placeholder="预算收入"  v-model="scope.row.budgetRevenue"  size="mini" style="width:150px"> 
+                        </el-input-number>
+                        </el-form-item>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="departmentIdArr" label="部门" width="180">
+                    <template slot-scope="scope">
+                        <el-form-item
+                        :prop="'optionList.' + scope.$index + '.departmentIdArr'"
+                        :rules="ruleValidate['departmentIdArr']"
+                        >
+                        <el-select v-model="scope.row.departmentIdArr" placeholder="请选择" multiple size="mini" style="width:150px">
+                          <el-option
+                            v-for="item in departmentList"
+                            :key="item.id"
+                            :label="item.name"
+                            :value="item.id">
+                          </el-option>
+                        </el-select>
+                        </el-form-item>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="isSum" label="是否合计" width="150">
+                    <template slot-scope="scope">
+                        <el-form-item
+                        :prop="'optionList.' + scope.$index + '.isSum'"
+                        :rules="ruleValidate['isSum']"
+                        >
+                        <el-select v-model="scope.row.isSum" placeholder="请选择" size="mini" style="width:130px">
+                          <el-option
+                            v-for="item in isSumList"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value">
+                          </el-option>
+                        </el-select>
+                        </el-form-item>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="index" label="排序号" width="120">
+                    <template slot-scope="scope">
+                        <el-form-item
+                        :prop="'optionList.' + scope.$index + '.index'"
+                        :rules="ruleValidate['index']"
+                        >
+                        <el-input placeholder="排序号"  v-model="scope.row.index"  size="mini" style="width:100px"> 
+                        </el-input>
+                        </el-form-item>
+                    </template>
+                </el-table-column>
+                <el-table-column label="操作" width="100" fixed="right">
+                <template slot-scope="{row}">
+                    <el-form-item>
+                    <i class="el-icon-delete my-font" @click="handleDelete(row)"></i>
+                    <i class="el-icon-document-add my-font" @click="handleInsert(row)"></i>
+                    </el-form-item>
+                </template>
+                </el-table-column>
+            </el-table>
+        </el-form>
+      </div>
+      <div class="el-table__empty-block">
+    <el-button icon="el-icon-circle-plus-outline" @click="handleAdd()">新增</el-button>
+    </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="closeDialog">取 消</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="submitting"
+          >确 定</el-button
+        >
+      </span>
+    </el-dialog>
+  </template>
+  <script>
+  import Constant from "@/constant";
+  import { getToken } from "@/utils/auth"; // get token from cookie
+  import templateOptionApi from "@/api/base/templateOption";
+  import departmentInfoApi from "@/api/base/departmentInfo";
+  
+  export default {
+    props: ["businessKey", "title"],
+    data() {
+      return {
+          ruleValidate: {
+              userName: [
+              { required: true, message: "用户名不能为空", trigger: "blur" },
+              ],
+              realName: [
+              { required: true, message: "真实名称不能为空", trigger: "blur" },
+              ],
+          },
+          roleList: [],
+          formModel: {
+            optionList:[],
+          },
+          showDialog: true,
+          loading: false,
+          submitting: false,
+          enterpriseList:[],
+          optionList:[],
+          departmentList:[],
+          isSumList:[
+            {
+              "label":"否",
+              "value":false
+            },
+            {
+              "label":"是",
+              "value":true
+            }]
+      };
+    },
+    created() {
+      var self = this;
+    
+      departmentInfoApi.list().then(function (response) {
+        var jsonData = response.data;
+        if (jsonData.result) {
+          if (jsonData.data != null && jsonData.data != "") {
+            self.departmentList = jsonData.data;
+          }
+        }
+      });
+    },
+    methods: {
+      closeDialog() {
+        this.$emit("close", false);
+      },
+      handleSubmit() {
+        var self = this;
+  
+        this.$refs["form"].validate((valid) => {
+          if (valid) {
+            (function () {
+                var id = self.formModel.id;
+                self.formModel.templateOptionList = self.formModel.optionList;
+                return templateOptionApi.update(self.formModel);
+            })().then(function (response) {
+              var jsonData = response.data;
+  
+              if (jsonData.result) {
+                self.$message({
+                  message: "保存成功!",
+                  type: "success",
+                });
+  
+                self.$emit("close", true);
+              } else {
+                self.$message({
+                  message: jsonData.message + "",
+                  type: "warning",
+                });
+  
+                self.$emit("close", false);
+              }
+            });
+          }
+        });
+      },
+      handleAdd() {
+        this.formModel.optionList.push({
+            serialNumber: "",
+            name: "",
+        });
+      },
+      handleInsert(row) {
+        this.formModel.optionList.push({
+            serialNumber: "",
+            name: "",
+          });
+      },
+      handleDelete(row) {
+        var optionList = this.formModel.optionList;
+
+        optionList.splice(optionList.indexOf(row), 1);
+      },
+    },
+    async mounted() {
+      var self = this;
+      self.loading = true;
+  
+      (function () {
+        if (self.businessKey != null && self.businessKey.length > 0) {
+          return templateOptionApi.edit(self.businessKey);
+        } else {
+          return templateOptionApi.create();
+        }
+      })()
+        .then((response) => {
+          var jsonData = response.data;
+  
+          if (jsonData.result) {
+            self.formModel.templateId = jsonData.data.templateId;
+            self.formModel.optionList = jsonData.data.templateOptionList;
+  
+              self.showModal = true;
+          } else {
+            self.$message.error(jsonData.message + "");
+          }
+  
+          self.loading = false;
+        })
+        .catch((error) => {
+          self.$message.error(error + "");
+          self.loading = false;
+        });
+    },
+    components: {
+    },
+  };
+  </script>
+  <style scoped>
+  .user-panel {
+    margin: 10px auto;
+  }
+  .avatar-uploader .el-upload {
+      border: 1px dashed #d9d9d9;
+      border-radius: 6px;
+      cursor: pointer;
+      position: relative;
+      overflow: hidden;
+    }
+    .avatar-uploader .el-upload:hover {
+      border-color: #409EFF;
+    }
+    .avatar-uploader-icon {
+      font-size: 28px;
+      color: #8c939d;
+      width: 178px;
+      height: 178px;
+      line-height: 178px;
+      text-align: center;
+    }
+    .avatar {
+      width: 178px;
+      height: 178px;
+      display: block;
+    }
+  </style>

+ 0 - 2
src/views/layout/index.vue

@@ -2,9 +2,7 @@
   <el-container class="outter-container">
     <el-header>
       <h3>
-        <sidebar-collpase-btn>
           <img src="../../assets/logo.png" height="50" width="350" />
-        </sidebar-collpase-btn>
       </h3>
       <div class="user-info">
         <el-dropdown @command="handleCommand">

+ 1 - 1
src/views/sys/role-permission.vue

@@ -1,7 +1,7 @@
 <template>
       <el-dialog
         title="分配接口权限"
-        width="800px"
+        width="900px"
         :visible="showDialog"
         :modal-append-to-body="false"
         style="text-align:left;"

+ 24 - 11
src/views/sys/user-detail.vue

@@ -45,14 +45,6 @@
             style="width: 300px"
           ></el-input>
         </el-form-item>
-        <!-- <el-form-item label="所属企业" prop="companyId">
-          <el-select-tree
-            :props="companyProps"
-            :options="companyResult"
-            v-model="formModel.companyId"
-            size="mediumn"
-          ></el-select-tree>
-        </el-form-item> -->
         <el-form-item label="分配角色" prop="roles">
           <el-select
             v-model="formModel.roles"
@@ -71,6 +63,16 @@
           <!-- <el-transfer v-model="formModel.roles" :data="roleList" 
           :props="{key: 'id',label: 'description'}" :titles="['所有角色','已分配角色']"></el-transfer>-->
         </el-form-item>
+        <el-form-item label="所属部门" prop="departmentId">
+          <el-select v-model="formModel.departmentId" placeholder="请选择" style="width: 300px">
+            <el-option
+              v-for="item in departmentList"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
       </el-form>
     </div>
     <span slot="footer" class="dialog-footer">
@@ -86,6 +88,7 @@ import Constant from "@/constant";
 import userApi from "@/api/sys/user";
 import roleApi from "@/api/sys/role";
 import SelectTree from "@/components/SelectTree";
+import departmentInfoApi from "@/api/base/departmentInfo";
 
 export default {
   props: ["businessKey", "title","companyResult"],
@@ -99,9 +102,6 @@ export default {
         realName: [
           { required: true, message: "真实名称不能为空", trigger: "blur" },
         ],
-        companyId: [
-          { required: true, message: "单位不能为空", trigger: "blur" },
-        ],
         password: [
           { required: true, message: "密码不能为空", trigger: "blur" },
         ],
@@ -118,8 +118,21 @@ export default {
         value: "id",
         label: "name",
       },
+      departmentList:[],
     };
   },
+  created(){
+    var self = this;
+    
+    departmentInfoApi.list().then(function (response) {
+      var jsonData = response.data;
+      if (jsonData.result) {
+        if (jsonData.data != null && jsonData.data != "") {
+          self.departmentList = jsonData.data;
+        }
+      }
+    });
+  },
   methods: {
     closeDialog() {
       this.$emit("close", false);