Explorar o código

收文登记 部门管理 全馆值班登记 预算批复管理 预算费用管理 前端

xieyn %!s(int64=2) %!d(string=hai) anos
pai
achega
f5caae7650

+ 445 - 0
src/views/oa/BudgetCostList.vue

@@ -0,0 +1,445 @@
+<template>
+  <a-card :bordered="false">
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="部门">
+              <a-input placeholder="请输入部门" v-model="queryParam.department"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="费用资金类别">
+              <a-input placeholder="请输入费用资金类别" v-model="queryParam.costFundType"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="预算资金名称">
+              <a-input placeholder="请输入预算资金名称" v-model="queryParam.budgetFundName"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="登记人">
+              <a-input placeholder="请输入登记人" v-model="queryParam.registerPerson"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="登记部门">
+              <a-input placeholder="请输入登记部门" v-model="queryParam.registerDept"></a-input>
+            </a-form-item>
+          </a-col>
+          <template v-if="toggleSearchStatus">
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="登记日期">
+                <j-date placeholder="请选择登记日期" v-model="queryParam.registerDate"></j-date>
+              </a-form-item>
+            </a-col>
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="预算年度">
+                <a-date-picker
+                  mode="year"
+                  v-model="queryParam.budgetYear"
+                  placeholder="请输入年份"
+                  format="YYYY"
+                  :open="yearShowOne"
+                  @openChange="openChangeOne"
+                  @panelChange="panelChangeOne"/>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+              <a @click="handleToggleSearch" style="margin-left: 8px">
+                {{ toggleSearchStatus ? '收起' : '展开' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
+              </a>
+            </span>
+          </a-col>
+
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 查询区域-END -->
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('预算费用管理')">导出</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        :scroll="{x:'max-content'}"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange">
+
+        <template slot="htmlSlot" slot-scope="text">
+          <div v-html="text"></div>
+        </template>
+        <template slot="imgSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无此图片</span>
+          <img v-else :src="getImgView(text)" height="25px" alt="图片不存在" style="max-width:80px;font-size: 12px;font-style: italic;"/>
+        </template>
+        <template slot="fileSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无此文件</span>
+          <a-button
+            v-else
+            :ghost="true"
+            type="primary"
+            icon="download"
+            size="small"
+            @click="uploadFile(text)">
+            下载
+          </a-button>
+        </template>
+        <template slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </template>
+<!--        <span slot="action" slot-scope="text, record">-->
+<!--          <a @click="handleEdit(record)">编辑</a>-->
+<!--          <a-divider type="vertical" />-->
+<!--          <a-dropdown>-->
+<!--            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>-->
+<!--            <a-menu slot="overlay">-->
+<!--              <a-menu-item>-->
+<!--                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">-->
+<!--                  <a>删除</a>-->
+<!--                </a-popconfirm>-->
+<!--              </a-menu-item>-->
+<!--            </a-menu>-->
+<!--          </a-dropdown>-->
+<!--        </span>-->
+
+      </a-table>
+    </div>
+
+    <budgetCost-modal ref="modalForm" @ok="modalFormOk"></budgetCost-modal>
+  </a-card>
+</template>
+
+<script>
+
+  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+  import BudgetCostModal from './modules/BudgetCostModal'
+  import JDate from '@/components/jeecg/JDate.vue'
+  import { FormTypes } from '@/utils/JEditableTableUtil'
+  import { getAction } from '@api/manage'
+  import JYearPicker from '@/components/date/YearSelect'
+  import JEllipsis from '@/components/jeecg/JEllipsis'
+  export default {
+    name: "BudgetCostList",
+    mixins:[JeecgListMixin],
+    components: {
+      JDate,
+      BudgetCostModal,
+      JYearPicker,
+      JEllipsis
+    },
+    data () {
+      let ellipsis = (v, l = 10) => (<j-ellipsis value={v} length={l}/>)
+      return {
+        description: '预算费用管理管理页面',
+        yearShowOne: false,
+        myArray:[],
+        countnum: 0,
+        data:[],
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key:'rowIndex',
+            width:60,
+            align:"center",
+            // customRender:function (t,r,index) {
+            //   return parseInt(index)+1;
+            // }
+            customRender: (value, row, index) => {
+              const obj = {
+                children: parseInt(index)+1,
+                attrs: {},
+              };
+              obj.attrs.rowSpan = this.myArray[index];
+              return obj
+            }
+          },
+          {
+            title:'登记人',
+            align:"center",
+            dataIndex: 'registerPerson',
+            width:150,
+            customRender: (value, row, index) => {
+              const obj = {
+                children: value,
+                attrs: {},
+              };
+              obj.attrs.rowSpan = this.myArray[index];
+              return obj
+            }
+          },
+          {
+            title:'登记部门',
+            align:"center",
+            width:150,
+            dataIndex: 'registerDept',
+            customRender: (value, row, index) => {
+              const obj = {
+                children: value,
+                attrs: {},
+              };
+              obj.attrs.rowSpan = this.myArray[index];
+              return obj
+            }
+          },
+          {
+            title:'登记日期',
+            align:"center",
+            width:100,
+            dataIndex: 'registerDate',
+            customRender: (value, row, index) => {
+              const obj = {
+                children: value,
+                attrs: {},
+              };
+              obj.attrs.rowSpan = this.myArray[index];
+              return obj
+            }
+          },
+          {
+            title:'预算年度',
+            align:"center",
+            width:100,
+            dataIndex: 'budgetYear',
+            customRender: (value, row, index) => {
+              const obj = {
+                children: value,
+                attrs: {},
+              };
+              obj.attrs.rowSpan = this.myArray[index];
+              return obj
+            }
+          },
+          {
+            title: '费用资金类别',
+            align:"center",
+            width:150,
+            dataIndex: 'costFundType',
+          },
+          {
+            title: '预算资金类别',
+            align:"center",
+            width:150,
+            dataIndex: 'budgetFundType',
+          },
+          {
+            title: '预算资金名称',
+            align:"center",
+            width:150,
+            dataIndex: 'budgetFundName',
+          },
+          {
+            title: '预算资金构成',
+            align:"center",
+            width:150,
+            dataIndex: 'budgetFundPose',
+          },
+          {
+            title: '预算金额',
+            align:"center",
+            width:100,
+            dataIndex: 'budgetMoney',
+          },
+          {
+            title: '合同金额',
+            width:100,
+            align:"center",
+            dataIndex: 'contractMoney',
+          },
+          {
+            title: '已支付金额',
+            align:"center",
+            width:120,
+            dataIndex: 'paidMoney',
+          },
+          {
+            title: '待支付金额',
+            align:"center",
+            width:120,
+            dataIndex: 'toBePaidMoney',
+          },
+          {
+            title: '附件上传',
+            align:"center",
+            width:120,
+            dataIndex: 'file',
+            scopedSlots: {customRender: 'fileSlot'},
+          },
+          {
+            title:'备注',
+            align:"center",
+            width:200,
+            dataIndex: 'remark',
+            ellipsis:true,
+            customRender: (l) => ellipsis(l)
+            // customRender: (value, row, index) => {
+            //   const obj = {
+            //     children: value,
+            //     attrs: {},
+            //   };
+            //   obj.attrs.rowSpan = this.myArray[index];
+            //   return obj
+            // }
+          },
+          {
+            title: '操作',
+            dataIndex: 'action',
+            width:100,
+            align:"center",
+            customRender: (value, row, index) => {
+              const obj = {
+                children:
+                  (
+                  <span>
+                  <a id="btn"  onClick={() => this.handleEdit(row)}>编辑   </a>
+                    <a id="btn" onClick={() => this.handleDelete(row.id)}>  删除</a>
+                    </span> ),
+                attrs: {},
+              };
+              obj.attrs.rowSpan = this.myArray[index];
+              return obj
+            }
+          }
+        ],
+        url: {
+          list: "/oa/budgetCost/list",
+          delete: "/oa/budgetCost/delete",
+          deleteBatch: "/oa/budgetCost/deleteBatch",
+          exportXlsUrl: "/oa/budgetCost/exportXls",
+          importExcelUrl: "oa/budgetCost/importExcel",
+        },
+        dictOptions:{},
+      }
+    },
+    computed: {
+      importExcelUrl: function(){
+        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+      }
+    },
+    methods: {
+      initDictConfig(){
+      },
+      // 弹出日历和关闭日历的回调
+      openChangeOne(status) {
+        if (status) {
+          this.yearShowOne = true;
+        }
+      },
+      // 得到年份选择器的值
+      panelChangeOne(value) {
+        this.yearShowOne = false;
+        this.queryParam.budgetYear = value;
+      },
+      loadData(arg) {
+        if(!this.url.list){
+          this.$message.error("请设置url.list属性!")
+          return
+        }
+        //加载数据 若传入参数1则加载第一页的内容
+        if (arg === 1) {
+          this.ipagination.current = 1;
+        }
+        var params = this.getQueryParams();//查询条件
+        if(params.budgetYear){
+          params.budgetYear = this.queryParam.budgetYear.format("YYYY");
+        }
+        console.log("params",params)
+        this.loading = true;
+        getAction(this.url.list, params).then((res) => {
+          if (res.success) {
+            this.dataSource = res.result.records;
+            this.data = this.dataSource;
+            // this.changeDate(this.data,'id')
+            this.setRowSpan(this.data)
+            console.log(this.data)
+            this.ipagination.total = res.result.total;
+          }
+          if(res.code===510){
+            this.$message.warning(res.message)
+          }
+          this.loading = false;
+        })
+      },
+      // 设置每一行的rowSpan
+      setRowSpan(data){
+        //保存上一个name
+        var x = "";
+        //相同name出现的次数
+        var count = 0;
+        //该name第一次出现的位置
+        var startindex=0;
+        for(var i = 0;i<data.length;i++){
+          console.log(data[i].id);
+          //这里是合并name列,根据各自情况大家可以自己完善
+          var val = data[(i)].id;
+          if(i==0){
+            x=val;
+            count=1;
+            this.myArray[0]=1
+          }else{
+            if(val==x){
+              count++;
+              this.myArray[startindex]=count;
+              this.myArray[i]=0
+            }else{
+              count = 1;
+              x=val;
+              startindex=i;
+              this.myArray[i]=1
+            }
+          }
+        }
+        console.log(this.myArray);
+      },
+    }
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less';
+</style>

+ 258 - 0
src/views/oa/BudgetReplyList.vue

@@ -0,0 +1,258 @@
+<template>
+  <a-card :bordered="false">
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="登记人">
+              <a-input placeholder="请输入登记人" v-model="queryParam.registerPerson"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="登记部门">
+              <a-input placeholder="请输入登记部门" v-model="queryParam.registerDept"></a-input>
+            </a-form-item>
+          </a-col>
+          <template v-if="toggleSearchStatus">
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="登记日期">
+                <j-date placeholder="请选择登记日期" v-model="queryParam.registerDate"></j-date>
+              </a-form-item>
+            </a-col>
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="预算年度">
+                <a-date-picker
+                  mode="year"
+                  v-model="queryParam.budgetYear"
+                  placeholder="请输入年份"
+                  format="YYYY"
+                  :open="yearShowOne"
+                  @openChange="openChangeOne"
+                  @panelChange="panelChangeOne"/>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+              <a @click="handleToggleSearch" style="margin-left: 8px">
+                {{ toggleSearchStatus ? '收起' : '展开' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
+              </a>
+            </span>
+          </a-col>
+
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 查询区域-END -->
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('预算批复管理')">导出</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange">
+
+        <template slot="htmlSlot" slot-scope="text">
+          <div v-html="text"></div>
+        </template>
+        <template slot="imgSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无此图片</span>
+          <img v-else :src="getImgView(text)" height="25px" alt="图片不存在" style="max-width:80px;font-size: 12px;font-style: italic;"/>
+        </template>
+        <template slot="fileSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无此文件</span>
+          <a-button
+            v-else
+            :ghost="true"
+            type="primary"
+            icon="download"
+            size="small"
+            @click="uploadFile(text)">
+            下载
+          </a-button>
+        </template>
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+
+      </a-table>
+    </div>
+
+    <budgetReply-modal ref="modalForm" @ok="modalFormOk"></budgetReply-modal>
+  </a-card>
+</template>
+
+<script>
+
+  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+  import BudgetReplyModal from './modules/BudgetReplyModal'
+  import JDate from '@/components/jeecg/JDate.vue'
+  import { getAction } from '@api/manage'
+
+  export default {
+    name: "BudgetReplyList",
+    mixins:[JeecgListMixin],
+    components: {
+      JDate,
+      BudgetReplyModal
+    },
+    data () {
+      return {
+        description: '预算批复管理管理页面',
+        yearShowOne:false,
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key:'rowIndex',
+            width:60,
+            align:"center",
+            customRender:function (t,r,index) {
+              return parseInt(index)+1;
+            }
+          },
+          {
+            title:'登记人',
+            align:"center",
+            dataIndex: 'registerPerson'
+          },
+          {
+            title:'登记部门',
+            align:"center",
+            dataIndex: 'registerDept'
+          },
+          {
+            title:'登记日期',
+            align:"center",
+            dataIndex: 'registerDate',
+            customRender:function (text) {
+              return !text?"":(text.length>10?text.substr(0,10):text)
+            }
+          },
+          {
+            title:'预算年度',
+            align:"center",
+            dataIndex: 'budgetYear',
+            customRender:function (text) {
+              return !text?"":(text.length>10?text.substr(0,10):text)
+            }
+          },
+          {
+            title:'预算总额',
+            align:"center",
+            dataIndex: 'budgetTotal'
+          },
+          {
+            title: '操作',
+            dataIndex: 'action',
+            align:"center",
+            scopedSlots: { customRender: 'action' },
+          }
+        ],
+        url: {
+          list: "/oa/budgetReply/list",
+          delete: "/oa/budgetReply/delete",
+          deleteBatch: "/oa/budgetReply/deleteBatch",
+          exportXlsUrl: "/oa/budgetReply/exportXls",
+          importExcelUrl: "oa/budgetReply/importExcel",
+        },
+        dictOptions:{},
+      }
+    },
+    computed: {
+      importExcelUrl: function(){
+        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+      }
+    },
+    methods: {
+      initDictConfig(){
+      },
+      // 弹出日历和关闭日历的回调
+      openChangeOne(status) {
+        if (status) {
+          this.yearShowOne = true;
+        }
+      },
+      // 得到年份选择器的值
+      panelChangeOne(value) {
+        this.yearShowOne = false;
+        this.queryParam.budgetYear = value;
+      },
+      loadData(arg) {
+        if(!this.url.list){
+          this.$message.error("请设置url.list属性!")
+          return
+        }
+        //加载数据 若传入参数1则加载第一页的内容
+        if (arg === 1) {
+          this.ipagination.current = 1;
+        }
+        var params = this.getQueryParams();//查询条件
+        if(params.budgetYear){
+          params.budgetYear = this.queryParam.budgetYear.format("YYYY");
+        }
+        console.log("params",params)
+        this.loading = true;
+        getAction(this.url.list, params).then((res) => {
+          if (res.success) {
+            this.dataSource = res.result.records;
+            this.ipagination.total = res.result.total;
+          }
+          if(res.code===510){
+            this.$message.warning(res.message)
+          }
+          this.loading = false;
+        })
+      },
+
+    }
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less';
+</style>

+ 591 - 0
src/views/oa/DepartList.vue

@@ -0,0 +1,591 @@
+<template xmlns:background-color="http://www.w3.org/1999/xhtml">
+  <a-row :gutter="10">
+    <a-col :md="12" :sm="24">
+      <a-card :bordered="false">
+
+        <!-- 按钮操作区域 -->
+        <a-row style="margin-left: 14px">
+          <a-button @click="handleAdd(2)" type="primary">添加子部门</a-button>
+          <a-button @click="handleAdd(1)" type="primary">添加一级部门</a-button>
+          <a-button type="primary" icon="download" @click="handleExportXls('部门信息')">导出</a-button>
+          <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+            <a-button type="primary" icon="import">导入</a-button>
+          </a-upload>
+          <a-button title="删除多条数据" @click="batchDel" type="default">批量删除</a-button>
+          <!--<a-button @click="refresh" type="default" icon="reload" :loading="loading">刷新</a-button>-->
+        </a-row>
+        <div style="background: #fff;padding-left:16px;height: 100%; margin-top: 5px">
+          <a-alert type="info" :showIcon="true">
+            <div slot="message">
+              当前选择:<span v-if="this.currSelected.title">{{ getCurrSelectedTitle() }}</span>
+              <a v-if="this.currSelected.title" style="margin-left: 10px" @click="onClearSelected">取消选择</a>
+            </div>
+          </a-alert>
+          <a-input-search @search="onSearch" style="width:100%;margin-top: 10px" placeholder="请输入部门名称"/>
+          <!-- 树-->
+          <a-col :md="10" :sm="24">
+            <template>
+              <a-dropdown :trigger="[this.dropTrigger]" @visibleChange="dropStatus">
+               <span style="user-select: none">
+            <a-tree
+              checkable
+              multiple
+              @select="onSelect"
+              @check="onCheck"
+              @rightClick="rightHandle"
+              :selectedKeys="selectedKeys"
+              :checkedKeys="checkedKeys"
+              :treeData="departTree"
+              :checkStrictly="checkStrictly"
+              :expandedKeys="iExpandedKeys"
+              :autoExpandParent="autoExpandParent"
+              @expand="onExpand"/>
+                </span>
+                <!--新增右键点击事件,和增加添加和删除功能-->
+                <a-menu slot="overlay">
+                  <a-menu-item @click="handleAdd(3)" key="1">添加</a-menu-item>
+                  <a-menu-item @click="handleDelete" key="2">删除</a-menu-item>
+                  <a-menu-item @click="closeDrop" key="3">取消</a-menu-item>
+                </a-menu>
+              </a-dropdown>
+            </template>
+          </a-col>
+        </div>
+      </a-card>
+      <!---- author:os_chengtgen -- date:20190827 --  for:切换父子勾选模式 =======------>
+      <div class="drawer-bootom-button">
+        <a-dropdown :trigger="['click']" placement="topCenter">
+          <a-menu slot="overlay">
+            <a-menu-item key="1" @click="switchCheckStrictly(1)">父子关联</a-menu-item>
+            <a-menu-item key="2" @click="switchCheckStrictly(2)">取消关联</a-menu-item>
+            <a-menu-item key="3" @click="checkALL">全部勾选</a-menu-item>
+            <a-menu-item key="4" @click="cancelCheckALL">取消全选</a-menu-item>
+            <a-menu-item key="5" @click="expandAll">展开所有</a-menu-item>
+            <a-menu-item key="6" @click="closeAll">合并所有</a-menu-item>
+          </a-menu>
+          <a-button>
+            树操作 <a-icon type="up" />
+          </a-button>
+        </a-dropdown>
+      </div>
+      <!---- author:os_chengtgen -- date:20190827 --  for:切换父子勾选模式 =======------>
+    </a-col>
+    <a-col :md="12" :sm="24">
+      <a-tabs defaultActiveKey="1">
+        <a-tab-pane tab="基本信息" key="1" >
+          <a-card :bordered="false">
+            <a-form :form="form">
+              <a-form-item
+                :labelCol="labelCol"
+                :wrapperCol="wrapperCol"
+                label="机构名称">
+                <a-input placeholder="部门名称" v-decorator="['departName', validatorRules.departName ]"/>
+              </a-form-item>
+              <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="上级部门">
+                <a-tree-select
+                  style="width:100%"
+                  :dropdownStyle="{maxHeight:'200px',overflow:'auto'}"
+                  :treeData="treeData"
+                  v-decorator="['parentId', validatorRules.parentId ]"
+                  placeholder="无">
+                </a-tree-select>
+              </a-form-item>
+              <a-form-item
+                :labelCol="labelCol"
+                :wrapperCol="wrapperCol"
+                label="排序">
+                <a-input-number v-decorator="[ 'departOrder',{'initialValue':0}]"/>
+              </a-form-item>
+              <a-form-item
+                :labelCol="labelCol"
+                :wrapperCol="wrapperCol"
+                label="部门职责及人数">
+                <a-input placeholder="请输入部门职责及人数" v-decorator="['dutyNum', validatorRules.dutyNum]"/>
+              </a-form-item>
+            </a-form>
+            <div class="anty-form-btn">
+              <a-button @click="emptyCurrForm" type="default" htmlType="button" icon="sync">重置</a-button>
+              <a-button @click="submitCurrForm" type="primary" htmlType="button" icon="form">修改并保存</a-button>
+            </div>
+          </a-card>
+        </a-tab-pane>
+        <a-tab-pane tab="部门权限" key="2" forceRender>
+          <depart-auth-modal ref="departAuth"/>
+        </a-tab-pane>
+      </a-tabs>
+
+    </a-col>
+    <depart-modal ref="departModal" @ok="loadTree"></depart-modal>
+  </a-row>
+</template>
+<script>
+  import DepartModal from './modules/DepartModal'
+  import pick from 'lodash.pick'
+  import {queryDepartTreeListNotOrg,queryDepartTreeList, searchByKeywords, deleteByDepartId,queryMyDepartTreeList} from '@/api/api'
+  import {httpAction, deleteAction} from '@/api/manage'
+  import {JeecgListMixin} from '@/mixins/JeecgListMixin'
+  import DepartAuthModal from './modules/DepartAuthModal'
+  // 表头
+  const columns = [
+    {
+      title: '机构名称',
+      dataIndex: 'departName'
+    },
+    {
+      title: '机构类型',
+      align: 'center',
+      dataIndex: 'orgType'
+    },
+    {
+      title: '机构编码',
+      dataIndex: 'orgCode',
+    },
+    {
+      title: '手机号',
+      dataIndex: 'mobile'
+    },
+    {
+      title: '传真',
+      dataIndex: 'fax'
+    },
+    {
+      title: '地址',
+      dataIndex: 'address'
+    },
+    {
+      title: '排序',
+      align: 'center',
+      dataIndex: 'departOrder'
+    },
+    {
+      title: '操作',
+      align: 'center',
+      dataIndex: 'action',
+      scopedSlots: {customRender: 'action'}
+    }
+  ]
+  export default {
+    name: 'DepartList',
+    mixins: [JeecgListMixin],
+    components: {
+      DepartAuthModal,
+      DepartModal
+    },
+    data() {
+      return {
+        iExpandedKeys: [],
+        loading: false,
+        autoExpandParent: true,
+        currFlowId: '',
+        currFlowName: '',
+        disable: true,
+        treeData: [],
+        visible: false,
+        departTree: [],
+        rightClickSelectedKey: '',
+        hiding: true,
+        model: {},
+        dropTrigger: '',
+        depart: {},
+        columns: columns,
+        disableSubmit: false,
+        checkedKeys: [],
+        selectedKeys: [],
+        autoIncr: 1,
+        currSelected: {},
+
+        allTreeKeys:[],
+        checkStrictly: true,
+
+        form: this.$form.createForm(this),
+        labelCol: {
+          xs: {span: 24},
+          sm: {span: 6}
+        },
+        wrapperCol: {
+          xs: {span: 24},
+          sm: {span: 16}
+        },
+        graphDatasource: {
+          nodes: [],
+          edges: []
+        },
+        validatorRules: {
+          departName: {rules: [{required: true, message: '请输入机构/部门名称!'}]},
+          parentId: {rules: [{required: true, message: '请选择上级!'}]},
+          orgCode: {rules: [{required: true, message: '请输入机构编码!'}]},
+          orgCategory: {rules: [{required: true, message: '请输入机构类型!'}]},
+          mobile: {rules: [{validator: this.validateMobile}]},
+          dutyNum:{rules: []}
+        },
+        url: {
+          delete: '/sys/sysDepart/delete',
+          edit: '/sys/sysDepart/edit',
+          deleteBatch: '/sys/sysDepart/deleteBatch',
+          exportXlsUrl: "sys/sysDepart/exportXls",
+          importExcelUrl: "sys/sysDepart/importExcel",
+        },
+        orgCategoryDisabled:false,
+      }
+    },
+    computed: {
+      importExcelUrl: function () {
+        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+      }
+    },
+    methods: {
+      loadData() {
+        this.refresh();
+      },
+      loadTree() {
+        var that = this
+        that.treeData = []
+        that.departTree = []
+        queryMyDepartTreeList().then((res) => {
+          if (res.success) {
+            for (let i = 0; i < res.result.length; i++) {
+              let temp = res.result[i]
+              that.treeData.push(temp)
+              that.departTree.push(temp)
+              that.setThisExpandedKeys(temp)
+              that.getAllKeys(temp);
+              // console.log(temp.id)
+            }
+            this.loading = false
+          }
+        })
+      },
+      setThisExpandedKeys(node) {
+        if (node.children && node.children.length > 0) {
+          this.iExpandedKeys.push(node.key)
+          for (let a = 0; a < node.children.length; a++) {
+            this.setThisExpandedKeys(node.children[a])
+          }
+        }
+      },
+      refresh() {
+        this.loading = true
+        this.loadTree()
+      },
+      // 右键操作方法
+      rightHandle(node) {
+        this.dropTrigger = 'contextmenu'
+        console.log(node.node.eventKey)
+        this.rightClickSelectedKey = node.node.eventKey
+      },
+      onExpand(expandedKeys) {
+        console.log('onExpand', expandedKeys)
+        // if not set autoExpandParent to false, if children expanded, parent can not collapse.
+        // or, you can remove all expanded children keys.
+        this.iExpandedKeys = expandedKeys
+        this.autoExpandParent = false
+      },
+      backFlowList() {
+        this.$router.back(-1)
+      },
+      // 右键点击下拉框改变事件
+      dropStatus(visible) {
+        if (visible == false) {
+          this.dropTrigger = ''
+        }
+      },
+      // 右键店家下拉关闭下拉框
+      closeDrop() {
+        this.dropTrigger = ''
+      },
+      addRootNode() {
+        this.$refs.nodeModal.add(this.currFlowId, '')
+      },
+      batchDel: function () {
+        console.log(this.checkedKeys)
+        if (this.checkedKeys.length <= 0) {
+          this.$message.warning('请选择一条记录!')
+        } else {
+          var ids = ''
+          for (var a = 0; a < this.checkedKeys.length; a++) {
+            ids += this.checkedKeys[a] + ','
+          }
+          var that = this
+          this.$confirm({
+            title: '确认删除',
+            content: '确定要删除所选中的 ' + this.checkedKeys.length + ' 条数据,以及子节点数据吗?',
+            onOk: function () {
+              deleteAction(that.url.deleteBatch, {ids: ids}).then((res) => {
+                if (res.success) {
+                  that.$message.success(res.message)
+                  that.loadTree()
+                  that.onClearSelected()
+                } else {
+                  that.$message.warning(res.message)
+                }
+              })
+            }
+          })
+        }
+      },
+      onSearch(value) {
+        let that = this
+        if (value) {
+          searchByKeywords({keyWord: value}).then((res) => {
+            if (res.success) {
+              that.departTree = []
+              for (let i = 0; i < res.result.length; i++) {
+                let temp = res.result[i]
+                that.departTree.push(temp)
+              }
+            } else {
+              that.$message.warning(res.message)
+            }
+          })
+        } else {
+          that.loadTree()
+        }
+
+      },
+      nodeModalOk() {
+        this.loadTree()
+      },
+      nodeModalClose() {
+      },
+      hide() {
+        console.log(111)
+        this.visible = false
+      },
+      onCheck(checkedKeys, info) {
+        console.log('onCheck', checkedKeys, info)
+        this.hiding = false
+        //this.checkedKeys = checkedKeys.checked
+        // <!---- author:os_chengtgen -- date:20190827 --  for:切换父子勾选模式 =======------>
+        if(this.checkStrictly){
+          this.checkedKeys = checkedKeys.checked;
+        }else{
+          this.checkedKeys = checkedKeys
+        }
+        // <!---- author:os_chengtgen -- date:20190827 --  for:切换父子勾选模式 =======------>
+      },
+      onSelect(selectedKeys, e) {
+        console.log('selected', selectedKeys, e)
+        this.hiding = false
+        let record = e.node.dataRef
+        console.log('onSelect-record', record)
+        this.currSelected = Object.assign({}, record)
+        this.model = this.currSelected
+        this.selectedKeys = [record.key]
+        this.model.parentId = record.parentId
+        this.setValuesToForm(record)
+        console.log("record",record)
+        this.$refs.departAuth.show(record.id);
+      },
+      // 触发onSelect事件时,为部门树右侧的form表单赋值
+      setValuesToForm(record) {
+        if(record.orgCategory == '1'){
+          this.orgCategoryDisabled = true;
+        }else{
+          this.orgCategoryDisabled = false;
+        }
+        this.form.getFieldDecorator('fax', {initialValue: ''})
+        this.form.setFieldsValue(pick(record, 'departName','dutyNum','parentId','orgCategory', 'orgCode', 'departOrder', 'mobile', 'fax', 'address', 'memo','description'))
+      },
+      getCurrSelectedTitle() {
+        return !this.currSelected.title ? '' : this.currSelected.title
+      },
+      onClearSelected() {
+        this.hiding = true
+        this.checkedKeys = []
+        this.currSelected = {}
+        this.form.resetFields()
+        this.selectedKeys = []
+        this.$refs.departAuth.departId = ''
+      },
+      handleNodeTypeChange(val) {
+        this.currSelected.nodeType = val
+      },
+      notifyTriggerTypeChange(value) {
+        this.currSelected.notifyTriggerType = value
+      },
+      receiptTriggerTypeChange(value) {
+        this.currSelected.receiptTriggerType = value
+      },
+      submitCurrForm() {
+        this.form.validateFields((err, values) => {
+          if (!err) {
+            if (!this.currSelected.id) {
+              this.$message.warning('请点击选择要修改部门!')
+              return
+            }
+            let formData = Object.assign(this.currSelected, values)
+            console.log('Received values of form: ', formData)
+            httpAction(this.url.edit, formData, 'put').then((res) => {
+              if (res.success) {
+                this.$message.success('保存成功!')
+                this.loadTree()
+              } else {
+                this.$message.error(res.message)
+              }
+            })
+          }
+        })
+      },
+      emptyCurrForm() {
+        this.form.resetFields()
+      },
+      nodeSettingFormSubmit() {
+        this.form.validateFields((err, values) => {
+          if (!err) {
+            console.log('Received values of form: ', values)
+          }
+        })
+      },
+      openSelect() {
+        this.$refs.sysDirectiveModal.show()
+      },
+      handleAdd(num) {
+        if (num == 1) {
+          this.$refs.departModal.add()
+          this.$refs.departModal.title = '新增'
+        } else if (num == 2) {
+          let key = this.currSelected.key
+          if (!key) {
+            this.$message.warning('请先选中一条记录!')
+            return false
+          }
+          this.$refs.departModal.add(this.selectedKeys)
+          this.$refs.departModal.title = '新增'
+        } else {
+          this.$refs.departModal.add(this.rightClickSelectedKey)
+          this.$refs.departModal.title = '新增'
+        }
+      },
+      handleDelete() {
+        deleteByDepartId({id: this.rightClickSelectedKey}).then((resp) => {
+          if (resp.success) {
+            this.$message.success('删除成功!')
+            this.loadTree()
+          } else {
+            this.$message.warning('删除失败!')
+          }
+        })
+      },
+      selectDirectiveOk(record) {
+        console.log('选中指令数据', record)
+        this.nodeSettingForm.setFieldsValue({directiveCode: record.directiveCode})
+        this.currSelected.sysCode = record.sysCode
+      },
+      getFlowGraphData(node) {
+        this.graphDatasource.nodes.push({
+          id: node.id,
+          text: node.flowNodeName
+        })
+        if (node.children.length > 0) {
+          for (let a = 0; a < node.children.length; a++) {
+            let temp = node.children[a]
+            this.graphDatasource.edges.push({
+              source: node.id,
+              target: temp.id
+            })
+            this.getFlowGraphData(temp)
+          }
+        }
+      },
+     // <!---- author:os_chengtgen -- date:20190827 --  for:切换父子勾选模式 =======------>
+      expandAll () {
+        this.iExpandedKeys = this.allTreeKeys
+      },
+      closeAll () {
+        this.iExpandedKeys = []
+      },
+      checkALL () {
+        this.checkStriccheckStrictlytly = false
+        this.checkedKeys = this.allTreeKeys
+      },
+      cancelCheckALL () {
+        //this.checkedKeys = this.defaultCheckedKeys
+        this.checkedKeys = []
+      },
+      switchCheckStrictly (v) {
+        if(v==1){
+          this.checkStrictly = false
+        }else if(v==2){
+          this.checkStrictly = true
+        }
+      },
+      getAllKeys(node) {
+        // console.log('node',node);
+        this.allTreeKeys.push(node.key)
+        if (node.children && node.children.length > 0) {
+          for (let a = 0; a < node.children.length; a++) {
+            this.getAllKeys(node.children[a])
+          }
+        }
+      }
+      // <!---- author:os_chengtgen -- date:20190827 --  for:切换父子勾选模式 =======------>
+    },
+    created() {
+      this.currFlowId = this.$route.params.id
+      this.currFlowName = this.$route.params.name
+      // this.loadTree()
+    },
+
+  }
+</script>
+<style scoped>
+  .ant-card-body .table-operator {
+    margin: 15px;
+  }
+
+  .anty-form-btn {
+    width: 100%;
+    text-align: center;
+  }
+
+  .anty-form-btn button {
+    margin: 0 5px;
+  }
+
+  .anty-node-layout .ant-layout-header {
+    padding-right: 0
+  }
+
+  .header {
+    padding: 0 8px;
+  }
+
+  .header button {
+    margin: 0 3px
+  }
+
+  .ant-modal-cust-warp {
+    height: 100%
+  }
+
+  .ant-modal-cust-warp .ant-modal-body {
+    height: calc(100% - 110px) !important;
+    overflow-y: auto
+  }
+
+  .ant-modal-cust-warp .ant-modal-content {
+    height: 90% !important;
+    overflow-y: hidden
+  }
+
+  #app .desktop {
+    height: auto !important;
+  }
+
+  /** Button按钮间距 */
+  .ant-btn {
+    margin-left: 3px
+  }
+
+  .drawer-bootom-button {
+    /*position: absolute;*/
+    bottom: 0;
+    width: 100%;
+    border-top: 1px solid #e8e8e8;
+    padding: 10px 16px;
+    text-align: left;
+    left: 0;
+    background: #fff;
+    border-radius: 0 0 2px 2px;
+  }
+</style>

+ 256 - 0
src/views/oa/MuseumDutyList.vue

@@ -0,0 +1,256 @@
+<template>
+  <a-card :bordered="false">
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="申请人">
+              <a-input placeholder="请输入申请人" v-model="queryParam.applyPerson"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="申请部门">
+              <a-input placeholder="请输入申请部门" v-model="queryParam.applyDept"></a-input>
+            </a-form-item>
+          </a-col>
+          <template v-if="toggleSearchStatus">
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="申请日期">
+                <j-date placeholder="请选择申请日期" v-model="queryParam.applyDate"></j-date>
+              </a-form-item>
+            </a-col>
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+                <a-form-item label="值班月">
+                  <a-date-picker
+                    mode="month"
+                    v-model="queryParam.dutyMonth"
+                    placeholder="请选择班月"
+                    format="YYYY-MM"
+                    :open="monthShowOne"
+                    @openChange="openChangeOne"
+                    @panelChange="panelChangeOne"/>
+                </a-form-item>
+            </a-col>
+          </template>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+              <a @click="handleToggleSearch" style="margin-left: 8px">
+                {{ toggleSearchStatus ? '收起' : '展开' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
+              </a>
+            </span>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 查询区域-END -->
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('全馆值班登记')">导出</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange">
+
+        <template slot="htmlSlot" slot-scope="text">
+          <div v-html="text"></div>
+        </template>
+        <template slot="imgSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无此图片</span>
+          <img v-else :src="getImgView(text)" height="25px" alt="图片不存在" style="max-width:80px;font-size: 12px;font-style: italic;"/>
+        </template>
+        <template slot="fileSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无此文件</span>
+          <a-button
+            v-else
+            :ghost="true"
+            type="primary"
+            icon="download"
+            size="small"
+            @click="uploadFile(text)">
+            下载
+          </a-button>
+        </template>
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+
+      </a-table>
+    </div>
+
+    <museumDuty-modal ref="modalForm" @ok="modalFormOk"></museumDuty-modal>
+  </a-card>
+</template>
+
+<script>
+
+  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+  import MuseumDutyModal from './modules/MuseumDutyModal'
+  import JDate from '@/components/jeecg/JDate.vue'
+  import { getAction } from '@api/manage'
+
+  export default {
+    name: "MuseumDutyList",
+    mixins:[JeecgListMixin],
+    components: {
+      JDate,
+      MuseumDutyModal
+    },
+    data () {
+      return {
+        description: '全馆值班登记管理页面',
+        monthShowOne: false,
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key:'rowIndex',
+            width:60,
+            align:"center",
+            customRender:function (t,r,index) {
+              return parseInt(index)+1;
+            }
+          },
+          {
+            title:'申请人',
+            align:"center",
+            dataIndex: 'applyPerson'
+          },
+          {
+            title:'申请部门',
+            align:"center",
+            dataIndex: 'applyDept'
+          },
+          {
+            title:'申请日期',
+            align:"center",
+            dataIndex: 'applyDate',
+            customRender:function (text) {
+              return !text?"":(text.length>10?text.substr(0,10):text)
+            }
+          },
+          {
+            title:'值班月',
+            align:"center",
+            dataIndex: 'dutyMonth',
+            customRender:function (text) {
+              return !text?"":(text.length>10?text.substr(0,10):text)
+            }
+          },
+          {
+            title:'说明',
+            align:"center",
+            dataIndex: 'remark'
+          },
+          {
+            title: '操作',
+            dataIndex: 'action',
+            align:"center",
+            scopedSlots: { customRender: 'action' },
+          }
+        ],
+        url: {
+          list: "/oa/museumDuty/list",
+          delete: "/oa/museumDuty/delete",
+          deleteBatch: "/oa/museumDuty/deleteBatch",
+          exportXlsUrl: "/oa/museumDuty/exportXls",
+          importExcelUrl: "oa/museumDuty/importExcel",
+        },
+        dictOptions:{},
+      }
+    },
+    computed: {
+      importExcelUrl: function(){
+        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+      }
+    },
+    methods: {
+      initDictConfig(){
+      },
+      // 弹出日历和关闭日历的回调
+      openChangeOne(status) {
+        if (status) {
+          this.monthShowOne = true;
+        }
+      },
+      // 得到年份选择器的值
+      panelChangeOne(value) {
+        this.monthShowOne = false;
+        this.queryParam.dutyMonth = value;
+      },
+      loadData(arg) {
+        if(!this.url.list){
+          this.$message.error("请设置url.list属性!")
+          return
+        }
+        //加载数据 若传入参数1则加载第一页的内容
+        if (arg === 1) {
+          this.ipagination.current = 1;
+        }
+        var params = this.getQueryParams();//查询条件
+        if(params.dutyMonth){
+          params.dutyMonth = this.queryParam.dutyMonth.format("YYYY-MM");
+        }
+        console.log("params",params)
+        this.loading = true;
+        getAction(this.url.list, params).then((res) => {
+          if (res.success) {
+            this.dataSource = res.result.records;
+            this.ipagination.total = res.result.total;
+          }
+          if(res.code===510){
+            this.$message.warning(res.message)
+          }
+          this.loading = false;
+        })
+      },
+    }
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less';
+</style>

+ 227 - 0
src/views/oa/ReceivedMainList.vue

@@ -0,0 +1,227 @@
+<template>
+  <a-card :bordered="false">
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="来文单位">
+              <a-input placeholder="请输入来文单位" v-model="queryParam.communicationsUnit"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <a-form-item label="收文名称">
+              <a-input placeholder="请输入收文名称" v-model="queryParam.receivedName"></a-input>
+            </a-form-item>
+          </a-col>
+          <template v-if="toggleSearchStatus">
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="收文日期">
+                <j-date placeholder="请选择收文日期" v-model="queryParam.receivedDate"></j-date>
+              </a-form-item>
+            </a-col>
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="公文流转日期">
+                <j-date placeholder="请选择公文流转日期" v-model="queryParam.documentDate"></j-date>
+              </a-form-item>
+            </a-col>
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="收文份数">
+                <a-input placeholder="请输入收文份数" v-model="queryParam.receivedNum"></a-input>
+              </a-form-item>
+            </a-col>
+            <a-col :xl="6" :lg="7" :md="8" :sm="24">
+              <a-form-item label="文号">
+                <a-input placeholder="请输入文号" v-model="queryParam.documentSymbol"></a-input>
+              </a-form-item>
+            </a-col>
+          </template>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+              <a @click="handleToggleSearch" style="margin-left: 8px">
+                {{ toggleSearchStatus ? '收起' : '展开' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
+              </a>
+            </span>
+          </a-col>
+
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 查询区域-END -->
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('收文登记')">导出</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange">
+
+        <template slot="htmlSlot" slot-scope="text">
+          <div v-html="text"></div>
+        </template>
+        <template slot="imgSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无此图片</span>
+          <img v-else :src="getImgView(text)" height="25px" alt="图片不存在" style="max-width:80px;font-size: 12px;font-style: italic;"/>
+        </template>
+        <template slot="fileSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无此文件</span>
+          <a-button
+            v-else
+            :ghost="true"
+            type="primary"
+            icon="download"
+            size="small"
+            @click="uploadFile(text)">
+            下载
+          </a-button>
+        </template>
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+
+      </a-table>
+    </div>
+
+    <receivedMain-modal ref="modalForm" @ok="modalFormOk"></receivedMain-modal>
+  </a-card>
+</template>
+
+<script>
+
+  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+  import ReceivedMainModal from './modules/ReceivedMainModal'
+  import JDate from '@/components/jeecg/JDate.vue'
+
+  export default {
+    name: "ReceivedMainList",
+    mixins:[JeecgListMixin],
+    components: {
+      JDate,
+      ReceivedMainModal
+    },
+    data () {
+      return {
+        description: '收文登记管理页面',
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key:'rowIndex',
+            width:60,
+            align:"center",
+            customRender:function (t,r,index) {
+              return parseInt(index)+1;
+            }
+          },
+          {
+            title:'来文单位',
+            align:"center",
+            dataIndex: 'communicationsUnit'
+          },
+          {
+            title:'收文名称',
+            align:"center",
+            dataIndex: 'receivedName'
+          },
+          {
+            title:'收文日期',
+            align:"center",
+            dataIndex: 'receivedDate',
+            customRender:function (text) {
+              return !text?"":(text.length>10?text.substr(0,10):text)
+            }
+          },
+          {
+            title:'公文流转日期',
+            align:"center",
+            dataIndex: 'documentDate',
+            customRender:function (text) {
+              return !text?"":(text.length>10?text.substr(0,10):text)
+            }
+          },
+          {
+            title:'收文份数',
+            align:"center",
+            dataIndex: 'receivedNum'
+          },
+          {
+            title:'文号',
+            align:"center",
+            dataIndex: 'documentSymbol'
+          },
+          {
+            title: '操作',
+            dataIndex: 'action',
+            align:"center",
+            scopedSlots: { customRender: 'action' },
+          }
+        ],
+        url: {
+          list: "/received/receivedMain/list",
+          delete: "/received/receivedMain/delete",
+          deleteBatch: "/received/receivedMain/deleteBatch",
+          exportXlsUrl: "/received/receivedMain/exportXls",
+          importExcelUrl: "received/receivedMain/importExcel",
+        },
+        dictOptions:{},
+      }
+    },
+    computed: {
+      importExcelUrl: function(){
+        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
+      }
+    },
+    methods: {
+      initDictConfig(){
+      }
+
+    }
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less';
+</style>

+ 279 - 0
src/views/oa/modules/BudgetCostModal.vue

@@ -0,0 +1,279 @@
+<template>
+  <a-modal
+    :title="title"
+    :width="1200"
+    :visible="visible"
+    :maskClosable="false"
+    :confirmLoading="confirmLoading"
+    @ok="handleOk"
+    @cancel="handleCancel">
+    <a-spin :spinning="confirmLoading">
+      <!-- 主表单区域 -->
+      <a-form :form="form">
+        <a-row>
+          <a-col :span="8">
+            <a-form-item label="登记人" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <j-popup
+                v-decorator="['registerPerson', validatorRules.registerPerson]"
+                :trigger-change="true"
+                org-fields="realname,depart_name"
+                dest-fields="registerPerson,registerDept"
+                code="user_dept"
+                @callback="popupCallback"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="登记部门" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <a-input :disabled="true" v-decorator="[ 'registerDept', validatorRules.registerDept]" placeholder="请输入登记部门"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="登记日期" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <j-date placeholder="请选择登记日期" v-decorator="[ 'registerDate', validatorRules.registerDate]" :trigger-change="true" style="width: 100%"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="预算年度" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <a-date-picker
+                mode="year"
+                v-decorator="['budgetYear', validatorRules.budgetYear]"
+                placeholder="请输入年份"
+                format="YYYY"
+                style="width: 200px"
+                :open="yearShowOne"
+                @openChange="openChangeOne"
+                @panelChange="panelChangeOne"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="24">
+            <a-form-item label="备注" :labelCol="labelCol2" :wrapperCol="wrapperCol2">
+              <a-textarea v-decorator="['remark', validatorRules.remark]" rows="4" placeholder="请输入备注"/>
+            </a-form-item>
+          </a-col>
+
+        </a-row>
+      </a-form>
+
+      <!-- 子表单区域 -->
+      <a-tabs v-model="activeKey" @change="handleChangeTabs">
+        <a-tab-pane tab="预算费用管理子表" :key="refKeys[0]" :forceRender="true">
+          <j-editable-table
+            :ref="refKeys[0]"
+            :loading="budgetCostDetailTable.loading"
+            :columns="budgetCostDetailTable.columns"
+            :dataSource="budgetCostDetailTable.dataSource"
+            :maxHeight="300"
+            :rowNumber="true"
+            :rowSelection="true"
+            :actionButton="true"/>
+        </a-tab-pane>
+
+      </a-tabs>
+
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+  import moment from 'moment'
+  import pick from 'lodash.pick'
+  import { FormTypes,getRefPromise } from '@/utils/JEditableTableUtil'
+  import { JEditableTableMixin } from '@/mixins/JEditableTableMixin'
+  import { validateDuplicateValue } from '@/utils/util'
+  import JDate from '@/components/jeecg/JDate'
+  import JYearPicker from '@/components/date/YearSelect'
+  export default {
+    name: 'BudgetCostModal',
+    mixins: [JEditableTableMixin],
+    components: {
+      JDate,
+      JYearPicker
+    },
+    data() {
+      return {
+        labelCol: {
+          span: 6
+        },
+        wrapperCol: {
+          span: 16
+        },
+        labelCol2: {
+          span: 2
+        },
+        wrapperCol2: {
+          span: 20
+        },
+        // 新增时子表默认添加几行空数据
+        addDefaultRowNum: 1,
+        validatorRules: {
+          registerPerson: {rules: [
+            {required: true, message: '请输入登记人!'},
+          ]},
+          registerDept: {rules: [
+          ]},
+          registerDate: {rules: [
+            {required: true, message: '请输入登记日期!'},
+          ]},
+          budgetYear: {rules: [
+            {required: true, message: '请输入预算年度!'},
+          ]},
+          remark: {rules: [
+          ]},
+        },
+        yearShowOne: false,
+        refKeys: ['budgetCostDetail', ],
+        tableKeys:['budgetCostDetail', ],
+        activeKey: 'budgetCostDetail',
+        // 预算费用管理子表
+        budgetCostDetailTable: {
+          loading: false,
+          dataSource: [],
+          columns: [
+            {
+              title: '费用资金类别',
+              key: 'costFundType',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '预算资金类别',
+              key: 'budgetFundType',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '预算资金名称',
+              key: 'budgetFundName',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '预算资金构成',
+              key: 'budgetFundPose',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '预算金额',
+              key: 'budgetMoney',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '合同金额',
+              key: 'contractMoney',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '已支付金额',
+              key: 'paidMoney',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '待支付金额',
+              key: 'toBePaidMoney',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '附件上传',
+              key: 'file',
+              type: FormTypes.file,
+              token:true,
+              responseName:"message",
+              width:"200px",
+              placeholder: '请选择文件',
+              defaultValue: '',
+            },
+            {
+              title: '备注',
+              key: 'detailRemark',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+          ]
+        },
+        url: {
+          add: "/oa/budgetCost/add",
+          edit: "/oa/budgetCost/edit",
+          budgetCostDetail: {
+            list: '/oa/budgetCost/queryBudgetCostDetailByMainId'
+          },
+        }
+      }
+    },
+    methods: {
+      getAllTable() {
+        let values = this.tableKeys.map(key => getRefPromise(this, key))
+        return Promise.all(values)
+      },
+      /** 调用完edit()方法之后会自动调用此方法 */
+      editAfter() {
+        if(this.model.budgetYear){
+          this.model.budgetYear =  moment(this.model.budgetYear);
+        }
+        let fieldval = pick(this.model,'registerPerson','registerDept','registerDate','budgetYear','remark')
+        this.$nextTick(() => {
+          this.form.setFieldsValue(fieldval)
+        })
+        // 加载子表数据
+        if (this.model.id) {
+          let params = { id: this.model.id }
+          this.requestSubTableData(this.url.budgetCostDetail.list, params, this.budgetCostDetailTable)
+        }
+      },
+      /** 整理成formData */
+      classifyIntoFormData(allValues) {
+        let main = Object.assign(this.model, allValues.formValue)
+        return {
+          ...main, // 展开
+          budgetCostDetailList: allValues.tablesValue[0].values,
+        }
+      },
+      validateError(msg){
+        this.$message.error(msg)
+      },
+     popupCallback(row){
+       this.form.setFieldsValue(pick(row,'registerPerson','registerDept','registerDate','budgetYear','remark'))
+     },
+      // 弹出日历和关闭日历的回调
+      openChangeOne(status) {
+        if (status) {
+          this.yearShowOne = true;
+        }
+      },
+      // 得到年份选择器的值
+      panelChangeOne(value) {
+        this.yearShowOne = false;
+        this.$nextTick(() => {
+          this.form.setFieldsValue({
+            budgetYear: value,
+          });
+        });
+      },
+    }
+  }
+</script>
+
+<style scoped>
+</style>

+ 303 - 0
src/views/oa/modules/BudgetReplyModal.vue

@@ -0,0 +1,303 @@
+<template>
+  <a-modal
+    :title="title"
+    :width="1200"
+    :visible="visible"
+    :maskClosable="false"
+    :confirmLoading="confirmLoading"
+    @ok="handleOk"
+    @cancel="handleCancel">
+    <a-spin :spinning="confirmLoading">
+      <!-- 主表单区域 -->
+      <a-form :form="form">
+        <a-row>
+
+          <a-col :span="8">
+            <a-form-item label="登记人" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <j-popup
+                v-decorator="['registerPerson', validatorRules.registerPerson]"
+                :trigger-change="true"
+                org-fields="realname,depart_name"
+                dest-fields="registerPerson,registerDept"
+                code="user_dept"
+                @callback="popupCallback"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="登记部门" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <a-input  :disabled="true" v-decorator="[ 'registerDept', validatorRules.registerDept]" placeholder="请输入登记部门"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="登记日期" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <j-date placeholder="请选择登记日期" v-decorator="[ 'registerDate', validatorRules.registerDate]" :trigger-change="true" style="width: 100%"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="预算年度" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <a-date-picker
+                mode="year"
+                v-decorator="['budgetYear', validatorRules.budgetYear]"
+                placeholder="请输入年份"
+                format="YYYY"
+                style="width: 200px"
+                :open="yearShowOne"
+                @openChange="openChangeOne"
+                @panelChange="panelChangeOne"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="预算总额" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <a-input v-decorator="[ 'budgetTotal', validatorRules.budgetTotal]" placeholder="请输入预算总额"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :span="24">
+            <a-form-item label="附件" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <j-upload v-decorator="['file', validatorRules.file]" :trigger-change="true"></j-upload>
+            </a-form-item>
+          </a-col>
+
+        </a-row>
+      </a-form>
+
+      <!-- 子表单区域 -->
+      <a-tabs v-model="activeKey" @change="handleChangeTabs">
+        <a-tab-pane tab="预算批复管理子表" :key="refKeys[0]" :forceRender="true">
+          <j-editable-table
+            :ref="refKeys[0]"
+            :loading="budgetReplyDetailTable.loading"
+            :columns="budgetReplyDetailTable.columns"
+            :dataSource="budgetReplyDetailTable.dataSource"
+            :maxHeight="300"
+            :rowNumber="true"
+            :rowSelection="true"
+            :actionButton="true"/>
+        </a-tab-pane>
+
+      </a-tabs>
+
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+  import moment from 'moment'
+  import pick from 'lodash.pick'
+  import { FormTypes,getRefPromise } from '@/utils/JEditableTableUtil'
+  import { JEditableTableMixin } from '@/mixins/JEditableTableMixin'
+  import { validateDuplicateValue } from '@/utils/util'
+  import JDate from '@/components/jeecg/JDate'
+  import JUpload from '@/components/jeecg/JUpload'
+
+  export default {
+    name: 'BudgetReplyModal',
+    mixins: [JEditableTableMixin],
+    components: {
+      JDate,
+      JUpload,
+    },
+    data() {
+      return {
+        yearShowOne: false,
+        labelCol: {
+          span: 6
+        },
+        wrapperCol: {
+          span: 16
+        },
+        labelCol2: {
+          span: 3
+        },
+        wrapperCol2: {
+          span: 20
+        },
+        // 新增时子表默认添加几行空数据
+        addDefaultRowNum: 1,
+        validatorRules: {
+          registerPerson: {rules: [
+            {required: true, message: '请输入登记人!'},
+          ]},
+          registerDept: {rules: [
+          ]},
+          registerDate: {rules: [
+            {required: true, message: '请输入登记日期!'},
+          ]},
+          budgetYear: {rules: [
+            {required: true, message: '请输入预算年度!'},
+          ]},
+          budgetTotal: {rules: [
+          ]},
+          file: {rules: [
+          ]},
+        },
+        refKeys: ['budgetReplyDetail', ],
+        tableKeys:['budgetReplyDetail', ],
+        activeKey: 'budgetReplyDetail',
+        // 预算批复管理子表
+        budgetReplyDetailTable: {
+          loading: false,
+          dataSource: [],
+          columns: [
+            {
+              title: '部门',
+              key: 'department',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '费用资金类别',
+              key: 'costFundType',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '预算资金类别',
+              key: 'budgetFundType',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '预算资金名称',
+              key: 'budgetFundName',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '预算资金构成',
+              key: 'budgetFundPose',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '预算资金来源',
+              key: 'budgetFundSource',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '明细内容',
+              key: 'detailContent',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '明细金额',
+              key: 'detailMoney',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '拨付方式',
+              key: 'paymentMethod',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '采购方式',
+              key: 'purchaseMethod',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '采购编号',
+              key: 'purchaseNum',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '备注',
+              key: 'remark',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+          ]
+        },
+        url: {
+          add: "/oa/budgetReply/add",
+          edit: "/oa/budgetReply/edit",
+          budgetReplyDetail: {
+            list: '/oa/budgetReply/queryBudgetReplyDetailByMainId'
+          },
+        }
+      }
+    },
+    methods: {
+      getAllTable() {
+        let values = this.tableKeys.map(key => getRefPromise(this, key))
+        return Promise.all(values)
+      },
+      /** 调用完edit()方法之后会自动调用此方法 */
+      editAfter() {
+        if(this.model.budgetYear){
+          this.model.budgetYear =  moment(this.model.budgetYear);
+        }
+        let fieldval = pick(this.model,'registerPerson','registerDept','registerDate','budgetYear','budgetTotal','file')
+        this.$nextTick(() => {
+          this.form.setFieldsValue(fieldval)
+        })
+        // 加载子表数据
+        if (this.model.id) {
+          let params = { id: this.model.id }
+          this.requestSubTableData(this.url.budgetReplyDetail.list, params, this.budgetReplyDetailTable)
+        }
+      },
+      /** 整理成formData */
+      classifyIntoFormData(allValues) {
+        let main = Object.assign(this.model, allValues.formValue)
+
+        return {
+          ...main, // 展开
+          budgetReplyDetailList: allValues.tablesValue[0].values,
+        }
+      },
+      validateError(msg){
+        this.$message.error(msg)
+      },
+     popupCallback(row){
+       this.form.setFieldsValue(pick(row,'registerPerson','registerDept','registerDate','budgetYear','budgetTotal','file'))
+     },
+      // 弹出日历和关闭日历的回调
+      openChangeOne(status) {
+        if (status) {
+          this.yearShowOne = true;
+        }
+      },
+      // 得到年份选择器的值
+      panelChangeOne(value) {
+        this.yearShowOne = false;
+        this.$nextTick(() => {
+          this.form.setFieldsValue({
+            budgetYear: value,
+          });
+        });
+      },
+    }
+  }
+</script>
+
+<style scoped>
+</style>

+ 184 - 0
src/views/oa/modules/DepartAuthModal.vue

@@ -0,0 +1,184 @@
+<template>
+  <a-card :bordered="false">
+    <template v-if="this.departId">
+      <a-form>
+        <a-form-item label='所拥有的权限'>
+          <a-tree
+            checkable
+            @check="onCheck"
+            :checkedKeys="checkedKeys"
+            :treeData="treeData"
+            @expand="onExpand"
+            @select="onTreeNodeSelect"
+            :selectedKeys="selectedKeys"
+            :expandedKeys="expandedKeysss"
+            :checkStrictly="checkStrictly"
+            style="height:500px;overflow: auto;">
+            <span slot="hasDatarule" slot-scope="{slotTitle,ruleFlag}">
+              {{ slotTitle }}
+              <a-icon v-if="ruleFlag" type="align-left" style="margin-left:5px;color: red;"></a-icon>
+            </span>
+          </a-tree>
+        </a-form-item>
+      </a-form>
+      <div class="anty-form-btn">
+        <a-dropdown style="float: left" :trigger="['click']" placement="topCenter">
+          <a-menu slot="overlay">
+            <!-- 简化Tree逻辑,使用默认checkStrictly为false的行为,即默认父子关联
+            <a-menu-item key="1" @click="switchCheckStrictly(1)">父子关联</a-menu-item>
+            <a-menu-item key="2" @click="switchCheckStrictly(2)">取消关联</a-menu-item>
+            -->
+            <a-menu-item key="3" @click="checkALL">全部勾选</a-menu-item>
+            <a-menu-item key="4" @click="cancelCheckALL">取消全选</a-menu-item>
+            <a-menu-item key="5" @click="expandAll">展开所有</a-menu-item>
+            <a-menu-item key="6" @click="closeAll">合并所有</a-menu-item>
+          </a-menu>
+          <a-button>
+            树操作 <a-icon type="up" />
+          </a-button>
+        </a-dropdown>
+        <a-button style="float: right" @click="handleSubmit" type="primary" htmlType="button" icon="form">保存</a-button>
+      </div>
+    </template>
+    <div v-else style="height:330px;"><h3>请先选择一个部门!</h3></div>
+    <depart-datarule-modal ref="datarule"/>
+  </a-card>
+</template>
+
+<script>
+  import {queryTreeListForRole,queryDepartPermission,saveDepartPermission} from '@/api/api'
+  import DepartDataruleModal from './DepartDataruleModal'
+
+  export default {
+    name: 'DepartAuthModal',
+    components: { DepartDataruleModal },
+    data(){
+      return {
+        departId:"",
+        treeData: [],
+        defaultCheckedKeys:[],
+        checkedKeys:[],
+        halfCheckedKeys:[],
+        expandedKeysss:[],
+        allTreeKeys:[],
+        autoExpandParent: true,
+        checkStrictly: false,
+        title:"部门权限配置",
+        visible: false,
+        loading: false,
+        selectedKeys:[]
+      }
+    },
+    methods: {
+      onTreeNodeSelect(id){
+        if(id && id.length>0){
+          this.selectedKeys = id
+        }
+        this.$refs.datarule.show(this.selectedKeys[0],this.departId)
+      },
+      onCheck (checkedKeys, { halfCheckedKeys }) {
+        // 保存选中的和半选中的,后面保存的时候合并提交
+        this.checkedKeys = checkedKeys
+        this.halfCheckedKeys = halfCheckedKeys
+      },
+      show(departId){
+        this.departId=departId
+        this.loadData();
+      },
+      close () {
+        this.reset()
+        this.$emit('close');
+        this.visible = false;
+      },
+      onExpand(expandedKeys){
+        this.expandedKeysss = expandedKeys;
+        this.autoExpandParent = false
+      },
+      reset () {
+        this.expandedKeysss = []
+        this.checkedKeys = []
+        this.defaultCheckedKeys = []
+        this.loading = false
+      },
+      expandAll () {
+        this.expandedKeysss = this.allTreeKeys
+      },
+      closeAll () {
+        this.expandedKeysss = []
+      },
+      checkALL () {
+        this.checkedKeys = this.allTreeKeys
+      },
+      cancelCheckALL () {
+        this.checkedKeys = []
+      },
+      handleCancel () {
+        this.close()
+      },
+      handleSubmit() {
+        let that = this;
+        if(!that.departId){
+          this.$message.warning('请点击选择一个部门!')
+        }
+        let checkedKeys = [...that.checkedKeys, ...that.halfCheckedKeys]
+        const permissionIds = checkedKeys.join(",")
+        let params =  {
+          departId:that.departId,
+          permissionIds,
+          lastpermissionIds:that.defaultCheckedKeys.join(","),
+        };
+        that.loading = true;
+        saveDepartPermission(params).then((res)=>{
+          if(res.success){
+            that.$message.success(res.message);
+            that.loading = false;
+            that.loadData();
+          }else {
+            that.$message.error(res.message);
+            that.loading = false;
+          }
+        })
+      },
+      convertTreeListToKeyLeafPairs(treeList, keyLeafPair = []) {
+        for(const {key, isLeaf, children} of treeList) {
+          keyLeafPair.push({key, isLeaf})
+          if(children && children.length > 0) {
+            this.convertTreeListToKeyLeafPairs(children, keyLeafPair)
+          }
+        }
+        return keyLeafPair;
+      },
+      emptyCurrForm() {
+        this.form.resetFields()
+      },
+      loadData(){
+        queryTreeListForRole().then((res) => {
+          this.treeData = res.result.treeList
+          this.allTreeKeys = res.result.ids
+          const keyLeafPairs = this.convertTreeListToKeyLeafPairs(this.treeData)
+          queryDepartPermission({departId:this.departId}).then((res)=>{
+            // 过滤出 leaf node 即可,即选中的
+            // Tree组件中checkStrictly默认为false的时候,选中子节点,父节点会自动设置选中或半选中
+            // 保存 checkedKeys 以及 halfCheckedKeys 以便于未做任何操作时提交表单数据
+            const checkedKeys = [...res.result].filter(key => {
+              const keyLeafPair = keyLeafPairs.filter(item => item.key === key)[0]
+              return keyLeafPair && keyLeafPair.isLeaf
+            })
+            const halfCheckedKeys = [...res.result].filter(key => {
+              const keyLeafPair = keyLeafPairs.filter(item => item.key === key)[0]
+              return keyLeafPair && !keyLeafPair.isLeaf
+            })
+            this.checkedKeys = [...checkedKeys];
+            this.halfCheckedKeys = [...halfCheckedKeys]
+            this.defaultCheckedKeys = [...halfCheckedKeys, ...checkedKeys];
+            this.expandedKeysss = this.allTreeKeys;
+          })
+        })
+      }
+    },
+  }
+</script>
+
+<style scoped>
+
+</style>

+ 116 - 0
src/views/oa/modules/DepartDataruleModal.vue

@@ -0,0 +1,116 @@
+<template>
+  <a-drawer
+    title="数据规则/按钮权限配置"
+    width="365"
+    :closable="false"
+    @close="onClose"
+    :visible="visible"
+  >
+    <a-tabs defaultActiveKey="1">
+      <a-tab-pane tab="数据规则" key="1">
+
+        <a-checkbox-group v-model="dataruleChecked" v-if="dataruleList.length>0">
+          <a-row>
+            <a-col :span="24" v-for="(item,index) in dataruleList" :key=" 'dr'+index ">
+              <a-checkbox :value="item.id">{{ item.ruleName }}</a-checkbox>
+            </a-col>
+
+            <a-col :span="24">
+              <div style="width: 100%;margin-top: 15px">
+                <a-button @click="saveDataruleForRole" type="primary" size="small" icon="save">点击保存</a-button>
+              </div>
+            </a-col>
+          </a-row>
+        </a-checkbox-group>
+        <div v-else><h3>无配置信息!</h3></div>
+
+      </a-tab-pane>
+    </a-tabs>
+
+  </a-drawer>
+</template>
+
+<script>
+  import ARow from 'ant-design-vue/es/grid/Row'
+  import ACol from 'ant-design-vue/es/grid/Col'
+  import { getAction,postAction } from '@/api/manage'
+
+  export default {
+    name: 'DepartDataruleModal',
+    components: { ACol, ARow },
+    data(){
+      return {
+        functionId:'',
+        departId:'',
+        visible:false,
+        tabList: [{
+          key: '1',
+          tab: '数据规则',
+        }, {
+          key: '2',
+          tab: '按钮权限',
+        }],
+        activeTabKey: '1',
+        url:{
+          datarule:"/sys/sysDepartPermission/datarule",
+        },
+        dataruleList:[],
+        dataruleChecked:[]
+      }
+    },
+    methods:{
+      loadData(){
+        getAction(`${this.url.datarule}/${this.functionId}/${this.departId}`).then(res=>{
+          if(res.success){
+            this.dataruleList = res.result.datarule
+            let drChecked = res.result.drChecked
+            if(drChecked){
+              this.dataruleChecked = drChecked.split(",")
+            }
+          }
+        })
+      },
+      saveDataruleForRole(){
+        if(!this.dataruleChecked || this.dataruleChecked.length==0){
+          this.$message.warning("请注意,现未勾选任何数据权限!")
+        }
+        let params = {
+          permissionId:this.functionId,
+          departId:this.departId,
+          dataRuleIds:this.dataruleChecked.join(",")
+        }
+        postAction(this.url.datarule,params).then(res=>{
+          if(res.success){
+            this.$message.success(res.message)
+          }else{
+            this.$message.error(res.message)
+          }
+        })
+      },
+      show(functionId,departId){
+        this.onReset()
+        this.functionId = functionId
+        this.departId = departId
+        this.visible=true
+        this.loadData()
+      },
+      onClose(){
+        this.visible=false
+        this.onReset()
+      },
+      onTabChange (key) {
+        this.activeTabKey = key
+      },
+      onReset(){
+        this.functionId=''
+        this.departId=''
+        this.dataruleList=[]
+        this.dataruleChecked=[]
+      }
+    }
+  }
+</script>
+
+<style scoped>
+
+</style>

+ 223 - 0
src/views/oa/modules/DepartModal.vue

@@ -0,0 +1,223 @@
+<template>
+  <a-modal
+    :title="title"
+    :width="800"
+    :ok=false
+    :visible="visible"
+    :confirmLoading="confirmLoading"
+    :okButtonProps="{ props: {disabled: disableSubmit} }"
+    @ok="handleOk"
+    @cancel="handleCancel"
+    cancelText="关闭">
+
+    <a-spin :spinning="confirmLoading">
+      <a-form :form="form">
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="机构名称"
+          :hidden="false"
+          hasFeedback >
+          <a-input id="departName" placeholder="请输入机构/部门名称" v-decorator="['departName', validatorRules.departName ]"/>
+        </a-form-item>
+        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" :hidden="seen" label="上级部门" hasFeedback>
+        <a-tree-select
+          style="width:100%"
+          :dropdownStyle="{maxHeight:'200px',overflow:'auto'}"
+          :treeData="departTree"
+          v-model="model.parentId"
+          placeholder="请选择上级部门"
+          :disabled="condition">
+        </a-tree-select>
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="机构类型">
+          <template v-if="seen">
+          <a-radio-group v-decorator="['orgCategory',validatorRules.orgCategory]" placeholder="请选择机构类型">
+            <a-radio value="1">
+              公司
+            </a-radio>
+          </a-radio-group>
+          </template>
+          <template v-else>
+            <a-radio-group v-decorator="['orgCategory',validatorRules.orgCategory]" placeholder="请选择机构类型">
+              <a-radio value="2">
+                部门
+              </a-radio>
+              <a-radio value="3">
+                岗位
+              </a-radio>
+            </a-radio-group>
+          </template>
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="电话">
+          <a-input placeholder="请输入电话" v-decorator="['mobile',validatorRules.mobile]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="传真">
+          <a-input placeholder="请输入传真" v-decorator="['fax', {}]"  />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="地址">
+          <a-input placeholder="请输入地址" v-decorator="['address', {}]"  />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="排序">
+          <a-input-number v-decorator="[ 'departOrder',{'initialValue':0}]" />
+        </a-form-item>
+        <a-form-item
+          :labelCol="labelCol"
+          :wrapperCol="wrapperCol"
+          label="备注">
+          <a-textarea placeholder="请输入备注" v-decorator="['memo', {}]"  />
+        </a-form-item>
+
+      </a-form>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+  import { httpAction } from '@/api/manage'
+  import { queryIdTree } from '@/api/api'
+  import pick from 'lodash.pick'
+  import ATextarea from 'ant-design-vue/es/input/TextArea'
+  export default {
+    name: "SysDepartModal",
+    components: { ATextarea },
+    data () {
+      return {
+        departTree:[],
+        orgTypeData:[],
+        phoneWarning:'',
+        departName:"",
+        title:"操作",
+        seen:false,
+        visible: false,
+        condition:true,
+        disableSubmit:false,
+        model: {},
+        menuhidden:false,
+        menuusing:true,
+        labelCol: {
+          xs: { span: 24 },
+          sm: { span: 5 },
+        },
+        wrapperCol: {
+          xs: { span: 24 },
+          sm: { span: 16 },
+        },
+
+        confirmLoading: false,
+        form: this.$form.createForm(this),
+        validatorRules:{
+        departName:{rules: [{ required: true, message: '请输入机构/部门名称!' }]},
+        orgCode:{rules: [{ required: true, message: '请输入机构编码!' }]},
+         mobile:{rules: [{validator:this.validateMobile}]}
+        },
+        url: {
+          add: "/sys/sysDepart/add",
+        },
+        dictDisabled:true,
+      }
+    },
+    created () {
+    },
+    methods: {
+      loadTreeData(){
+        var that = this;
+        queryIdTree().then((res)=>{
+          if(res.success){
+            that.departTree = [];
+            for (let i = 0; i < res.result.length; i++) {
+              let temp = res.result[i];
+              that.departTree.push(temp);
+            }
+          }
+
+        })
+      },
+      add (depart) {
+        if(depart){
+          this.seen = false;
+          this.dictDisabled = false;
+        }else{
+          this.seen = true;
+          this.dictDisabled = true;
+        }
+        this.edit(depart);
+      },
+      edit (record) {
+          this.form.resetFields();
+          this.model = Object.assign({}, {});
+          this.visible = true;
+          this.loadTreeData();
+          this.model.parentId = record!=null?record.toString():null;
+          if(this.seen){
+            this.model.orgCategory = '1';
+          }else{
+            this.model.orgCategory = '2';
+          }
+          this.$nextTick(() => {
+            this.form.setFieldsValue(pick(this.model,'orgCategory','departName','departNameEn','departNameAbbr','departOrder','description','orgType','orgCode','mobile','fax','address','memo','status','delFlag'))
+          });
+      },
+      close () {
+        this.$emit('close');
+        this.disableSubmit = false;
+        this.visible = false;
+      },
+      handleOk () {
+        const that = this;
+        // 触发表单验证
+        this.form.validateFields((err, values) => {
+          if (!err) {
+            that.confirmLoading = true;
+            let formData = Object.assign(this.model, values);
+            //时间格式化
+            console.log(formData)
+            httpAction(this.url.add,formData,"post").then((res)=>{
+              if(res.success){
+                that.$message.success(res.message);
+                that.loadTreeData();
+                that.$emit('ok');
+              }else{
+                that.$message.warning(res.message);
+              }
+            }).finally(() => {
+              that.confirmLoading = false;
+              that.close();
+            })
+
+          }
+        })
+      },
+      handleCancel () {
+        this.close()
+      },
+      validateMobile(rule,value,callback){
+        if (!value || new RegExp(/^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/).test(value)){
+          callback();
+        }else{
+          callback("您的手机号码格式不正确!");
+        }
+
+      }
+    }
+  }
+</script>
+
+<style scoped>
+
+</style>

+ 252 - 0
src/views/oa/modules/MuseumDutyModal.vue

@@ -0,0 +1,252 @@
+<template>
+  <a-modal
+    :title="title"
+    :width="1200"
+    :visible="visible"
+    :maskClosable="false"
+    :confirmLoading="confirmLoading"
+    @ok="handleOk"
+    @cancel="handleCancel">
+    <a-spin :spinning="confirmLoading">
+      <!-- 主表单区域 -->
+      <a-form :form="form">
+        <a-row>
+
+          <a-col :span="8">
+            <a-form-item label="申请人" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <j-popup
+                v-decorator="['applyPerson', validatorRules.applyPerson]"
+                :trigger-change="true"
+                org-fields="realname,depart_name"
+                dest-fields="applyPerson,applyDept"
+                code="user_dept"
+                @callback="popupCallback"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="申请部门" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <a-input v-decorator="[ 'applyDept', validatorRules.applyDept]" :disabled="true" placeholder="请输入申请部门"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="申请日期" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <j-date placeholder="请选择申请日期"  v-decorator="[ 'applyDate', validatorRules.applyDate]" :trigger-change="true" style="width: 100%"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="值班月" :labelCol="labelCol" :wrapperCol="wrapperCol">
+                <a-date-picker
+                  mode="month"
+                  v-decorator="[ 'dutyMonth', validatorRules.dutyMonth]"
+                  placeholder="请选择值班月"
+                  format="YYYY-MM"
+                  :open="monthShowOne"
+                  @openChange="openChangeOne"
+                  @panelChange="panelChangeOne"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="24">
+            <a-form-item label="说明" :labelCol="labelCol2" :wrapperCol="wrapperCol2">
+              <a-textarea v-decorator="['remark', validatorRules.remark]" rows="4" placeholder="请输入说明"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="24">
+            <a-form-item label="附件" :labelCol="labelCol2" :wrapperCol="wrapperCol2">
+              <j-upload v-decorator="['file', validatorRules.file]" :trigger-change="true"></j-upload>
+            </a-form-item>
+          </a-col>
+
+        </a-row>
+      </a-form>
+
+      <!-- 子表单区域 -->
+      <a-tabs v-model="activeKey" @change="handleChangeTabs">
+        <a-tab-pane tab="全馆值班登记子表" :key="refKeys[0]" :forceRender="true">
+          <j-editable-table
+            :ref="refKeys[0]"
+            :loading="museumDutyDetailTable.loading"
+            :columns="museumDutyDetailTable.columns"
+            :dataSource="museumDutyDetailTable.dataSource"
+            :maxHeight="300"
+            :rowNumber="true"
+            :rowSelection="true"
+            :actionButton="true">
+              <span slot="action" slot-scope="text, record">
+              <a @click="handleEdit(record)">编辑</a>
+
+              <a-divider type="vertical" />
+              <a-dropdown>
+                <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
+                <a-menu slot="overlay">
+                  <a-menu-item>
+                    <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                      <a>删除</a>
+                    </a-popconfirm>
+                  </a-menu-item>
+                </a-menu>
+              </a-dropdown>
+            </span>
+          </j-editable-table>
+        </a-tab-pane>
+      </a-tabs>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+
+  import pick from 'lodash.pick'
+  import { FormTypes,getRefPromise } from '@/utils/JEditableTableUtil'
+  import { JEditableTableMixin } from '@/mixins/JEditableTableMixin'
+  import { validateDuplicateValue } from '@/utils/util'
+  import JDate from '@/components/jeecg/JDate'
+  import JUpload from '@/components/jeecg/JUpload'
+  import moment from 'moment'
+
+  export default {
+    name: 'MuseumDutyModal',
+    mixins: [JEditableTableMixin],
+    components: {
+      JDate,
+      JUpload,
+    },
+    data() {
+      return {
+        labelCol: {
+          span: 6
+        },
+        wrapperCol: {
+          span: 18
+        },
+        labelCol2: {
+          span: 2
+        },
+        wrapperCol2: {
+          span: 22
+        },
+        monthShowOne:false,
+        // 新增时子表默认添加几行空数据
+        addDefaultRowNum: 1,
+        validatorRules: {
+          applyPerson: {rules: [
+            {required: true, message: '请输入申请人!'},
+          ]},
+          applyDept: {rules: [
+          ]},
+          applyDate: {rules: [
+            {required: true, message: '请输入申请日期!'},
+          ]},
+          dutyMonth: {rules: [
+            {required: true, message: '请输入值班月!'},
+          ]},
+          remark: {rules: [
+          ]},
+          file: {rules: [
+          ]},
+        },
+        refKeys: ['museumDutyDetail', ],
+        tableKeys:['museumDutyDetail', ],
+        activeKey: 'museumDutyDetail',
+        // 全馆值班登记子表
+        museumDutyDetailTable: {
+          loading: false,
+          dataSource: [],
+          columns: [
+            {
+              title: '值班日期',
+              key: 'dutyDate',
+              type: FormTypes.date,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '值班人',
+              key: 'dutyPerson',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '值班岗位',
+              key: 'dutyPost',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '备注',
+              key: 'remark',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+          ]
+        },
+        url: {
+          add: "/oa/museumDuty/add",
+          edit: "/oa/museumDuty/edit",
+          museumDutyDetail: {
+            list: '/oa/museumDuty/queryMuseumDutyDetailByMainId'
+          },
+        }
+      }
+    },
+    methods: {
+      getAllTable() {
+        let values = this.tableKeys.map(key => getRefPromise(this, key))
+        return Promise.all(values)
+      },
+      /** 调用完edit()方法之后会自动调用此方法 */
+      editAfter() {
+        if(this.model.dutyMonth){
+          this.model.dutyMonth =  moment(this.model.dutyMonth);
+        }
+        let fieldval = pick(this.model,'applyPerson','applyDept','applyDate','dutyMonth','remark','file')
+        this.$nextTick(() => {
+          this.form.setFieldsValue(fieldval)
+        })
+        // 加载子表数据
+        if (this.model.id) {
+          let params = { id: this.model.id }
+          this.requestSubTableData(this.url.museumDutyDetail.list, params, this.museumDutyDetailTable)
+        }
+      },
+      /** 整理成formData */
+      classifyIntoFormData(allValues) {
+        let main = Object.assign(this.model, allValues.formValue)
+        return {
+          ...main, // 展开
+          museumDutyDetailList: allValues.tablesValue[0].values,
+        }
+      },
+      validateError(msg){
+        this.$message.error(msg)
+      },
+     popupCallback(row){
+       this.form.setFieldsValue(pick(row,'applyPerson','applyDept','applyDate','dutyMonth','remark','file'))
+     },
+      // 弹出日历和关闭日历的回调
+      openChangeOne(status) {
+        if (status) {
+          this.monthShowOne = true;
+        }
+      },
+      // 得到年份选择器的值
+      panelChangeOne(value) {
+        this.monthShowOne = false;
+        this.$nextTick(() => {
+          this.form.setFieldsValue({
+            dutyMonth: value,
+          });
+        });
+      },
+    }
+  }
+</script>
+
+<style scoped>
+</style>

+ 257 - 0
src/views/oa/modules/ReceivedMainModal.vue

@@ -0,0 +1,257 @@
+<template>
+  <a-modal
+    :title="title"
+    :width="1200"
+    :visible="visible"
+    :maskClosable="false"
+    :confirmLoading="confirmLoading"
+    @ok="handleOk"
+    @cancel="handleCancel">
+    <a-spin :spinning="confirmLoading">
+      <!-- 主表单区域 -->
+      <a-form :form="form">
+        <a-row>
+          <a-col :span="8">
+            <a-form-item label="来文单位" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <a-input v-decorator="[ 'communicationsUnit', validatorRules.communicationsUnit]" placeholder="请输入来文单位"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="收文名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <a-input v-decorator="[ 'receivedName', validatorRules.receivedName]" placeholder="请输入收文名称"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="收文日期" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <j-date placeholder="请选择收文日期" v-decorator="[ 'receivedDate', validatorRules.receivedDate]" :trigger-change="true" style="width: 100%"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="公文流转日期" :labelCol="{span:8}" :wrapperCol="{span:16}">
+              <j-date placeholder="请选择公文流转日期" v-decorator="[ 'documentDate', validatorRules.documentDate]" :trigger-change="true" style="width: 100%"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="收文份数" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <a-input-number v-decorator="[ 'receivedNum', validatorRules.receivedNum]" placeholder="请输入收文份数" style="width: 100%"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="8">
+            <a-form-item label="文号" :labelCol="labelCol" :wrapperCol="wrapperCol">
+              <a-input v-decorator="[ 'documentSymbol', validatorRules.documentSymbol]" placeholder="请输入文号"></a-input>
+            </a-form-item>
+          </a-col>
+          <a-col :span="24">
+            <a-form-item label="备注" :labelCol="labelCol2" :wrapperCol="wrapperCol2">
+              <a-textarea v-decorator="['remark', validatorRules.remark]" rows="4" placeholder="请输入备注"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="24">
+            <a-form-item label="附件" :labelCol="labelCol2" :wrapperCol="wrapperCol2">
+              <j-upload v-decorator="['file', validatorRules.file]" :trigger-change="true"></j-upload>
+            </a-form-item>
+          </a-col>
+
+        </a-row>
+      </a-form>
+
+      <!-- 子表单区域 -->
+      <a-tabs v-model="activeKey" @change="handleChangeTabs">
+        <a-tab-pane tab="收文登记子表" :key="refKeys[0]" :forceRender="true">
+          <j-editable-table
+            :ref="refKeys[0]"
+            :loading="receivedDetailTable.loading"
+            :columns="receivedDetailTable.columns"
+            :dataSource="receivedDetailTable.dataSource"
+            :maxHeight="300"
+            :rowNumber="true"
+            :rowSelection="true"
+            :actionButton="true">
+            <template v-slot:departHead="props">
+              <j-select-user-by-dep  @change="headChange(props)" v-model="props.text" :trigger-change="true"></j-select-user-by-dep>
+            </template>
+
+            <template v-slot:depart="props">
+              <j-select-depart  @change="departChange(props)" v-model="props.text" :trigger-change="true"></j-select-depart>
+            </template>
+          </j-editable-table>
+        </a-tab-pane>
+      </a-tabs>
+    </a-spin>
+  </a-modal>
+</template>
+
+<script>
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+  import pick from 'lodash.pick'
+  import { FormTypes,getRefPromise } from '@/utils/JEditableTableUtil'
+  import { JEditableTableMixin } from '@/mixins/JEditableTableMixin'
+  import { validateDuplicateValue } from '@/utils/util'
+  import JDate from '@/components/jeecg/JDate'
+  import JUpload from '@/components/jeecg/JUpload'
+  import JSelectUserByDep from '@/components/jeecgbiz/JSelectUserByDep'
+  import JSelectDepart from '@/components/jeecgbiz/JSelectDepart'
+
+  export default {
+    name: 'ReceivedMainModal',
+    mixins: [JEditableTableMixin],
+    components: {
+      JDate,
+      JUpload,
+      JeecgListMixin,
+      JSelectUserByDep,
+      JSelectDepart
+    },
+    data() {
+      return {
+        labelCol: {
+          span: 6
+        },
+        wrapperCol: {
+          span: 16
+        },
+        labelCol2: {
+          span: 2
+        },
+        wrapperCol2: {
+          span: 22
+        },
+        // 新增时子表默认添加几行空数据
+        addDefaultRowNum: 1,
+        validatorRules: {
+          communicationsUnit: {rules: [
+            {required: true, message: '请输入来文单位!'},
+          ]},
+          receivedName: {rules: [
+            {required: true, message: '请输入收文名称!'},
+          ]},
+          receivedDate: {rules: [
+            {required: true, message: '请输入收文日期!'},
+          ]},
+          documentDate: {rules: [
+            {required: true, message: '请输入公文流转日期!'},
+          ]},
+          receivedNum: {rules: [
+            {required: true, message: '请输入收文份数!'},
+          ]},
+          documentSymbol: {rules: [
+          ]},
+          remark: {rules: [
+          ]},
+          file: {rules: [
+          ]},
+        },
+        refKeys: ['receivedDetail', ],
+        tableKeys:['receivedDetail', ],
+        activeKey: 'receivedDetail',
+        // 收文登记子表
+        receivedDetailTable: {
+          loading: false,
+          dataSource: [],
+          columns: [
+            {
+              title: '公文流转部门',
+              key: 'documentDept',
+              type: FormTypes.slot,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+              slotName: 'depart',
+            },
+            {
+              title: '部门负责人姓名',
+              key: 'deptHeadName',
+              type: FormTypes.slot,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+              slotName: 'departHead',
+            },
+            {
+              title: '审阅日期',
+              key: 'reviewDate',
+              type: FormTypes.date,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+            {
+              title: '备注',
+              key: 'remark',
+              type: FormTypes.input,
+              width:"200px",
+              placeholder: '请输入${title}',
+              defaultValue: '',
+            },
+          ]
+        },
+        url: {
+          add: "/received/receivedMain/add",
+          edit: "/received/receivedMain/edit",
+          receivedDetail: {
+            list: '/received/receivedMain/queryReceivedDetailByMainId'
+          },
+        }
+      }
+    },
+    methods: {
+      getAllTable() {
+        let values = this.tableKeys.map(key => getRefPromise(this, key))
+        return Promise.all(values)
+      },
+      /** 调用完edit()方法之后会自动调用此方法 */
+      editAfter() {
+        let fieldval = pick(this.model,'communicationsUnit','receivedName','receivedDate','documentDate','receivedNum','documentSymbol','remark','file')
+        this.$nextTick(() => {
+          this.form.setFieldsValue(fieldval)
+        })
+        // 加载子表数据
+        if (this.model.id) {
+          let params = { id: this.model.id }
+          this.requestSubTableData(this.url.receivedDetail.list, params, this.receivedDetailTable)
+        }
+      },
+      /** 整理成formData */
+      classifyIntoFormData(allValues) {
+        let main = Object.assign(this.model, allValues.formValue)
+        return {
+          ...main, // 展开
+          receivedDetailList: allValues.tablesValue[0].values,
+        }
+      },
+      validateError(msg){
+        this.$message.error(msg)
+      },
+     popupCallback(row){
+       this.form.setFieldsValue(pick(row,'communicationsUnit','receivedName','receivedDate','documentDate','receivedNum','documentSymbol','remark','file'))
+     },
+      //部门负责人插槽更改数据
+      headChange(props) {
+        let values = [
+          {
+            rowKey: props.rowId,
+            values: {
+              'deptHeadName': props.text,
+            },
+          },
+        ]
+        this.$refs.receivedDetail.setValues(values)
+      },
+      //部门插槽更改数据
+      departChange(props) {
+        let values = [
+          {
+            rowKey: props.rowId,
+            values: {
+              'documentDept': props.text,
+            },
+          },
+        ]
+        this.$refs.receivedDetail.setValues(values)
+      }
+    }
+  }
+</script>
+
+<style scoped>
+</style>