Browse Source

调整样式,费用报销加打印功能

Lijy 1 year ago
parent
commit
cba8e8dc11

File diff suppressed because it is too large
+ 6025 - 6872
fhKeeper/formulahousekeeper/timesheet/package-lock.json


+ 135 - 0
fhKeeper/formulahousekeeper/timesheet/src/assets/js/print.js

@@ -0,0 +1,135 @@
+// 打印类属性、方法定义
+/* eslint-disable */
+const Print = function (dom, options) {
+  if (!(this instanceof Print)) return new Print(dom, options);
+ 
+  this.options = this.extend({
+    'noPrint': '.no-print'
+  }, options);
+ 
+  if ((typeof dom) === "string") {
+    this.dom = document.querySelector(dom);
+  } else {
+    this.isDOM(dom)
+    this.dom = this.isDOM(dom) ? dom : dom.$el;
+  }
+ 
+  this.init();
+};
+Print.prototype = {
+  init: function () {
+    var content = this.getStyle() + this.getHtml();
+    this.writeIframe(content);
+  },
+  extend: function (obj, obj2) {
+    for (var k in obj2) {
+      obj[k] = obj2[k];
+    }
+    return obj;
+  },
+ 
+  getStyle: function () {
+    var str = "",
+      styles = document.querySelectorAll('style,link');
+    for (var i = 0; i < styles.length; i++) {
+      str += styles[i].outerHTML;
+    }
+    str += "<style>" + (this.options.noPrint ? this.options.noPrint : '.no-print') + "{display:none;}</style>";
+ 
+    return str;
+  },
+ 
+  getHtml: function () {
+    var inputs = document.querySelectorAll('input');
+    var textareas = document.querySelectorAll('textarea');
+    var selects = document.querySelectorAll('select');
+ 
+    for (var k = 0; k < inputs.length; k++) {
+      if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
+        if (inputs[k].checked == true) {
+          inputs[k].setAttribute('checked', "checked")
+        } else {
+          inputs[k].removeAttribute('checked')
+        }
+      } else if (inputs[k].type == "text") {
+        inputs[k].setAttribute('value', inputs[k].value)
+      } else {
+        inputs[k].setAttribute('value', inputs[k].value)
+      }
+    }
+ 
+    for (var k2 = 0; k2 < textareas.length; k2++) {
+      if (textareas[k2].type == 'textarea') {
+        textareas[k2].innerHTML = textareas[k2].value
+      }
+    }
+ 
+    for (var k3 = 0; k3 < selects.length; k3++) {
+      if (selects[k3].type == 'select-one') {
+        var child = selects[k3].children;
+        for (var i in child) {
+          if (child[i].tagName == 'OPTION') {
+            if (child[i].selected == true) {
+              child[i].setAttribute('selected', "selected")
+            } else {
+              child[i].removeAttribute('selected')
+            }
+          }
+        }
+      }
+    }
+ 
+    return this.dom.outerHTML;
+  },
+ 
+  writeIframe: function (content) {
+    var w, doc, iframe = document.createElement('iframe'),
+      f = document.body.appendChild(iframe);
+    iframe.id = "myIframe";
+    //iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
+    iframe.setAttribute('style', 'position:absolute;width:0;height:0;top:-10px;left:-10px;');
+    w = f.contentWindow || f.contentDocument;
+    doc = f.contentDocument || f.contentWindow.document;
+    doc.open();
+    doc.write(content);
+    doc.close();
+    var _this = this
+    iframe.onload = function(){
+      _this.toPrint(w);
+      setTimeout(function () {
+        document.body.removeChild(iframe)
+      }, 100)
+    }
+  },
+ 
+  toPrint: function (frameWindow) {
+    try {
+      setTimeout(function () {
+        frameWindow.focus();
+        try {
+          if (!frameWindow.document.execCommand('print', false, null)) {
+            frameWindow.print();
+          }
+        } catch (e) {
+          frameWindow.print();
+        }
+        frameWindow.close();
+      }, 10);
+    } catch (err) {
+      console.log('err', err);
+    }
+  },
+  isDOM: (typeof HTMLElement === 'object') ?
+    function (obj) {
+      return obj instanceof HTMLElement;
+    } :
+    function (obj) {
+      return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string';
+    }
+};
+const MyPlugin = {}
+MyPlugin.install = function (Vue, options) {
+  // 4. 添加实例方法
+  Vue.prototype.$print = Print
+}
+export default MyPlugin

+ 4 - 0
fhKeeper/formulahousekeeper/timesheet/src/main.js

@@ -70,6 +70,10 @@ import VueTour from 'vue-tour'
 require('vue-tour/dist/vue-tour.css')
 Vue.use(VueTour)
 
+// 打印js
+import Print from './assets/js/print.js'
+Vue.use(Print)
+
 var addRouFlag = false; 
 //角色权限对应关系
 var userModules = [{role:0, modules:["工时报告","专业审核","部门审核","自动计时","费用报销","待办任务", "项目管理", "请假管理", "审批流设置"]},

+ 247 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/expense/expense.vue

@@ -492,6 +492,7 @@
         </viewer> -->
         <!-- 取消和确定 -->
         <span slot="footer" class="dialog-footer">
+          <!-- <el-button @click="print()">打印</el-button> -->
           <el-button @click="dialog = false">{{ $t('btn.cancel') }}</el-button>
           <el-button v-if="!flg" type="primary" @click="present()">{{ $t('btn.determine') }}</el-button>
           <el-button v-else type="primary" @click="dialog = false">{{ $t('btn.determine') }}</el-button>
@@ -616,6 +617,186 @@
                 <el-button type="primary" @click="deny()" >{{ $t('btn.determine') }}</el-button>
             </div>
         </el-dialog>
+
+        <!-- 详情查看弹出框 -->
+        <el-dialog title="报销凭证详情" :visible.sync="detailDialog" width="1000px" :before-close="handleClose">
+          <div ref="printContent" class="printContent">
+            <div class="printContent-detail">
+              <div class="detail-item">
+                <span class="detail-item-title"> <span class="printBox">报销人</span> </span>
+                <span class="detail-item-content">{{ParticularsList.ownerName}}</span>
+              </div>
+              <div class="detail-item">
+                <span class="detail-item-title"><span class="printBox">填报时间</span></span>
+                <span class="detail-item-content">{{ParticularsList.createDate}}</span>
+              </div>
+              <div class="detail-item">
+                <span class="detail-item-title"><span class="printBox">发票张数</span></span>
+                <span class="detail-item-content">{{ParticularsList.ticketNum}} 张</span>
+              </div>
+              <div class="detail-item">
+                <span class="detail-item-title"><span class="printBox">费用类型:</span></span>
+                <span class="detail-item-content">{{detaExpenseMainTypeName}}</span>
+              </div>
+              <div class="detail-item">
+                <span class="detail-item-title"><span class="printBox">总费用</span></span>
+                <span class="detail-item-content">¥ {{ParticularsList.totalAmount | numberToCurrency}}</span>
+              </div>
+              <div class="detail-item" style="width: 100%">
+                <span class="detail-item-title"><span class="printBox">备注</span></span>
+                <span class="detail-item-content">{{ParticularsList.remark}}</span>
+              </div>
+            </div>
+            <el-table :data="ParticularsList.invoiceList" border style="width: 100%">
+            <el-table-column prop="projectId" :label="$t('other.project')" width="155">
+                <template slot-scope="scope">
+                  <el-select size="small" v-if="!flg" v-model="scope.row.projectId" :placeholder="$t('other.project')" style="width: 130px">
+                    <el-option v-for="(item, index) in projectList" :key="index" :label="item.projectName + item.projectCode" :value="item.id" @click="ok(item)">
+                      <span style="float: left;color: #8492a6; font-size: 13px">{{ item.projectCode }}</span>
+                      <span style="float: right;margin-left: 20px">{{ item.projectName }}</span>
+                    </el-option>
+                  </el-select>
+                  <!-- <span v-else>{{projectIdName[scope.$index].projectName}}</span> -->
+                  <div v-else>
+                    <div v-for="(item, index) in projectIdName" :key="index">
+                      <span v-if="item.id == scope.row.projectId">{{item.projectName}}</span>
+                    </div>
+                  </div>
+                </template>
+            </el-table-column>
+            <el-table-column prop="happenDate" :label="$t('forthedate')" width="172">
+              <template slot-scope="scope">
+                <el-date-picker size="small" v-if="!flg" v-model="scope.row.happenDate" type="date" style=" width: 145px" value-format="yyyy-MM-dd" :placeholder="$t('optiondate')">
+                </el-date-picker>
+                <span v-else>{{scope.row.happenDate}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="invoiceType" :label="$t('invoices')" width="172" v-if="this.user.timeType.easyExpense==0">
+              <template slot-scope="scope">
+                <el-select size="small" v-if="!flg" v-model="scope.row.invoiceType" :placeholder="$t('pleaseselectthetypeoffee')" style="width: 150px;">
+                  <el-option :label="$t('vATspecialinvoice')" :value="0"></el-option>
+                  <el-option :label="$t('vATgeneralinvoice')" :value="1"></el-option>
+                </el-select>
+                <span v-else>{{typeInvoic[scope.row.invoiceType]}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="invoiceType" :label="$t('costtype')" width="172">
+              <template slot-scope="scope">
+                <el-select v-if="!flg" size="small" v-model="scope.row.expenseType" :placeholder="$t('pleaseselectthetypeoffee')" style="width: 150px" >
+                  <el-option v-for="(item, index) in expenseTypeList" :key="index" :label="item.typeName" :value="item.typeName" ></el-option>
+                </el-select>
+                <span v-else>{{scope.row.expenseType}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="amount" :label="this.user.timeType.easyExpense==0?$t('amountoffees'):'费用金额'" width="172">
+              <template slot-scope="scope">
+                <el-input size="small"  v-if="!flg" :id="'am'+scope.$index" v-model="scope.row.amount" @input="zhiNum(scope.$index, scope)" @change="kan" @keyup.native="restrictNumber('am'+scope.$index)"></el-input>
+                <span v-else>¥{{scope.row.amount}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="invoiceNo" :label="$t('invoiceno')" width="172" v-if="this.user.timeType.easyExpense==0">
+              <template slot-scope="scope">
+                <el-input size="small" v-if="!flg" v-model.number="scope.row.invoiceNo"></el-input>
+                <span v-else>{{scope.row.invoiceNo}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="taxPercent" :label="$t('shui-shuai')" width="172" v-if="this.user.timeType.easyExpense==0">
+              <template slot-scope="scope">
+                <el-input size="small"  v-if="!flg" v-model="scope.row.taxPercent" @input="zhiNum(scope.$index, scope)"></el-input>
+                <span v-else>{{scope.row.taxPercent}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="taxValue" :label="$t('taxs')+'('+$t('yuan')+')'" width="172" v-if="this.user.timeType.easyExpense==0">
+              <template slot-scope="scope">
+                <el-input size="small"  v-if="!flg" v-model="scope.row.taxValue"></el-input>
+                <span v-else>¥{{scope.row.taxValue}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="remark" :label="$t('bei-zhu')" width="300">
+              <template slot-scope="scope"> 
+                <el-input size="small" v-if="!flg" v-model="scope.row.remark"></el-input>
+                <span v-else>{{scope.row.remark}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="pic" :label="$t('expensereimbursementvoucher')" width="300">
+              <template slot-scope="scope">
+                <div v-if="!flg">
+                  <div @click="abl(scope.$index)" style="height: 35px;overflow: hidden;">
+                    <el-upload :class="!scope.row.pic ? 'upload-demo' : 'upload-demo icl'" :file-list="scope.row.pic" :before-remove="beforeRemoves" :http-request="fileonLoads" limit="1" name="multipartFile">
+                      <el-button size="small" type="primary" v-if="!scope.row.pic">{{ $t('clickupload') }}</el-button>
+                    </el-upload>
+                  </div>
+                </div>
+                <div v-else>
+                  <span v-if="scope.row.pic">
+                    <div class="tups">
+                      <viewer :images="scope.row.pic">
+                        <img ref="imgsa" v-for="src in scope.row.pic" :src="src.url" :key="src.title">
+                    </viewer>
+                    </div>
+                  </span>
+                  <span v-else>{{ $t('nodocuments') }}</span>    
+                </div>
+              </template>
+            </el-table-column>
+            <!-- 删除 -->
+            <el-table-column fixed="right"
+              :label="$t('operation')" v-if="!flg">
+              <template slot-scope="scope">
+                <el-button  type="default" size="mini" style="display: inline-block;margin-left:0;margin-top: 3px" @click="delec(scope.$index)">{{ $t('btn.delete') }}</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+            <!-- <div class="conter-box">
+              <div class="conter-border" v-for="item, index in ParticularsList.invoiceList" :key="index">
+                <div class="detail-item">
+                  <span class="detail-item-title"> <span class="printBox">项目</span> </span>
+                  <span class="detail-item-content">{{item.ownerName}}</span>
+                </div>
+                <div class="detail-item">
+                  <span class="detail-item-title"> <span class="printBox">费用日期</span> </span>
+                  <span class="detail-item-content">{{ParticularsList.ownerName}}</span>
+                </div>
+                <div class="detail-item">
+                  <span class="detail-item-title"> <span class="printBox">发票种类</span> </span>
+                  <span class="detail-item-content">{{ParticularsList.ownerName}}</span>
+                </div>
+                <div class="detail-item">
+                  <span class="detail-item-title"> <span class="printBox">费用类型</span> </span>
+                  <span class="detail-item-content">{{ParticularsList.ownerName}}</span>
+                </div>
+                <div class="detail-item">
+                  <span class="detail-item-title"> <span class="printBox">费用金额(含税)</span> </span>
+                  <span class="detail-item-content">{{ParticularsList.ownerName}}</span>
+                </div>
+                <div class="detail-item">
+                  <span class="detail-item-title"> <span class="printBox">发票号</span> </span>
+                  <span class="detail-item-content">{{ParticularsList.ownerName}}</span>
+                </div>
+                <div class="detail-item">
+                  <span class="detail-item-title"> <span class="printBox">税率%</span> </span>
+                  <span class="detail-item-content">{{ParticularsList.ownerName}}</span>
+                </div>
+                <div class="detail-item">
+                  <span class="detail-item-title"> <span class="printBox">税额</span> </span>
+                  <span class="detail-item-content">{{ParticularsList.ownerName}}</span>
+                </div>
+                <div class="detail-item">
+                  <span class="detail-item-title"> <span class="printBox">备注</span> </span>
+                  <span class="detail-item-content">{{ParticularsList.ownerName}}</span>
+                </div>
+                <div class="detail-item">
+                  <span class="detail-item-title"> <span class="printBox">报销凭证</span> </span>
+                  <span class="detail-item-content">{{ParticularsList.ownerName}}</span>
+                </div>
+              </div>
+            </div> -->
+          </div>
+          <span slot="footer" class="dialog-footer">
+            <el-button @click="print()">打 印</el-button>
+            <el-button @click="detailDialog = false">关 闭</el-button>
+          </span>
+        </el-dialog>
   </section>
 </template>
 
@@ -715,6 +896,9 @@ export default {
       editExpenseTypeDataRules:{
         name: [{ required: true, message: this.$t('pleaseentercustomfeetypename'), trigger: "blur" }],
       },
+      // 详情弹出框
+      detailDialog: false,
+      detaExpenseMainTypeName: '',
     };
   },
   computed: {
@@ -1126,7 +1310,13 @@ export default {
     },
     // 单据查看
     downloadByA(val) {
-      this.dialog = true
+      if(val.status == 0) {
+        this.detailDialog = true
+      } else {
+        this.dialog = true
+      }
+      console.log(val, '看看数据来源')
+      this.detaExpenseMainTypeName = val.expenseMainTypeName
       this.flg = true;
       this.getParticulars(val.id);
       this.expenseTypeList = this.allExpList.filter(a=>a.mainType == val.type);
@@ -1795,11 +1985,25 @@ export default {
                 type: "error"
             });
         });
+      },
+      // 打印
+      print() {
+        // let printContent = this.$refs.printContent;
+        // let newWindow = window.open('', '_blank');
+        // newWindow.document.write(printContent.innerHTML);
+        // newWindow.document.close();
+        // newWindow.focus();
+        // newWindow.print();
+        // newWindow.close();
+        this.$print(this.$refs.printContent)
       }
   },
+  beforeDestroy() {
+    
+  }
 };
 </script>
-<style scoped>
+<style scoped lang="scss">
 .tups {
   width: 100%;
   height: 25px;
@@ -2000,4 +2204,45 @@ export default {
 .newInvoice:hover{
   color: #7bbcff;
 }
+
+/* 新增打印的费用报销类型 */
+.printContent {
+  .printContent-detail {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  .detail-item {
+    width: 33%;
+    font-size: 16px;
+    margin-bottom: 10px;
+    color: #000;
+    .detail-item-title {
+      color: #999;
+    }
+    .printBox {
+      display: inline-block;
+      width: 125px;
+      text-align-last: justify;
+      box-sizing: border-box;
+      padding-right: 10px;
+    }
+  }
+  .conter-box {
+    .conter-border {
+      width: 100%;
+      box-sizing: border-box;
+      padding: 15px;
+      border: 1px solid #ddd;
+      border-radius: 4px;
+      display: flex;
+      flex-wrap: wrap;
+      margin-top: 20px;
+      .detail-item {
+        width: 50%;
+        margin-top: 10px;
+      }
+    }
+  }
+}
+
 </style>

+ 23 - 17
fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue

@@ -230,21 +230,24 @@
                                 <span v-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.label'></ww-open-data></span>
                             </el-tag>
                         </div>
+
+                        <div style="width:100%;margin-top: 10px;">
+                            <span style="color: #606266;margin-right: 5px">审核提醒时间</span>
+                            <el-time-picker 
+                                    v-model="timeType.waitCheckAlertTime"
+                                    :placeholder="$t('checkRemindertime')"
+                                    style="width:150px;"
+                                    format="HH:mm"
+                                    value-format="HH:mm"
+                                    :picker-options="{
+                                    start: '08:00',
+                                    end: '23:30'
+                                    }">
+                                </el-time-picker>
+                        </div>
+
                     </div>
-                    <div style="width:100%">
-                        <span style="color: #606266;margin-right: 5px">审核提醒时间</span>
-                        <el-time-picker 
-                                v-model="timeType.waitCheckAlertTime"
-                                :placeholder="$t('checkRemindertime')"
-                                style="width:150px;"
-                                format="HH:mm"
-                                value-format="HH:mm"
-                                :picker-options="{
-                                start: '08:00',
-                                end: '23:30'
-                                }">
-                            </el-time-picker>
-                    </div>
+                    
                 </div>
             </el-col>
         </el-row>
@@ -1481,11 +1484,13 @@
 
 <style lang="scss" scoped>
 .panel {
-    padding:15px;height:300px;box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
+    padding:15px;
+    // height:300px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
 }
 .underpanel{
     width: 900px;
-    height: 140px;
+    // height: 140px;
     border-top: 1px solid #eee;
     position: relative;
     top: -12px;
@@ -1497,7 +1502,8 @@
 .underpanel .whiteList_content{
     margin: 10px 10px 0 10px;
     border: 1px solid #eee;
-    height: 90px;
+    padding-bottom: 10px;
+    // height: 90px;
 }
 .sample {
     margin-top:22px;