Explorar el Código

增加企业微信,批量填报,项目导入功能

seyason hace 3 años
padre
commit
bcae91e07e
Se han modificado 42 ficheros con 1510 adiciones y 461 borrados
  1. BIN
      fhKeeper/formulahousekeeper/inva_4_tivo/images/favicon.png
  2. 4 4
      fhKeeper/formulahousekeeper/inva_4_tivo/index.html
  3. 8 0
      fhKeeper/formulahousekeeper/inva_4_tivo/mobile.html
  4. 2 2
      fhKeeper/formulahousekeeper/timesheet/config/index.js
  5. BIN
      fhKeeper/formulahousekeeper/timesheet/favicon.ico
  6. 62 49
      fhKeeper/formulahousekeeper/timesheet/package-lock.json
  7. 1 0
      fhKeeper/formulahousekeeper/timesheet/package.json
  8. 233 3
      fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/demo_index.html
  9. 43 3
      fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.css
  10. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.js
  11. 70 0
      fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.json
  12. BIN
      fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.ttf
  13. BIN
      fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.woff
  14. BIN
      fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.woff2
  15. 9 29
      fhKeeper/formulahousekeeper/timesheet/src/main.js
  16. 18 5
      fhKeeper/formulahousekeeper/timesheet/src/routes.js
  17. 74 0
      fhKeeper/formulahousekeeper/timesheet/src/views/Login.vue
  18. 83 8
      fhKeeper/formulahousekeeper/timesheet/src/views/Register.vue
  19. 77 30
      fhKeeper/formulahousekeeper/timesheet/src/views/expense/expense.vue
  20. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/views/market/list.vue
  21. 193 18
      fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue
  22. 5 4
      fhKeeper/formulahousekeeper/timesheet/src/views/project/earning.vue
  23. 22 8
      fhKeeper/formulahousekeeper/timesheet/src/views/project/info.vue
  24. 51 0
      fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue
  25. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/views/project/projectInside.vue
  26. 72 7
      fhKeeper/formulahousekeeper/timesheet/src/views/team/index.vue
  27. 118 57
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue
  28. 6 4
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/list.vue
  29. 15 3
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/timer.vue
  30. 218 205
      fhKeeper/formulahousekeeper/timesheet_h5/package-lock.json
  31. 1 0
      fhKeeper/formulahousekeeper/timesheet_h5/package.json
  32. BIN
      fhKeeper/formulahousekeeper/timesheet_h5/public/favicon.ico
  33. 2 2
      fhKeeper/formulahousekeeper/timesheet_h5/public/index.html
  34. 2 2
      fhKeeper/formulahousekeeper/timesheet_h5/src/main.js
  35. 7 0
      fhKeeper/formulahousekeeper/timesheet_h5/src/router/index.js
  36. 2 2
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/index.vue
  37. 5 5
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/index/index.vue
  38. 40 2
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/login/index.vue
  39. 5 1
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/project/index.vue
  40. 53 3
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/register/index.vue
  41. 1 1
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/review/index.vue
  42. 5 1
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/view/index.vue

BIN
fhKeeper/formulahousekeeper/inva_4_tivo/images/favicon.png


+ 4 - 4
fhKeeper/formulahousekeeper/inva_4_tivo/index.html

@@ -257,7 +257,7 @@
                         </div>
                         <div class="card-body">
                             <h4 class="card-title">工时日报</h4>
-                            <p>员工填写工时日报<br>项目经理在线审批<br>支持微信方便快捷</p>
+                            <p>员工填写工时日报<br>项目经理在线审批<br>支持微信和钉钉方便快捷</p>
                         </div>
                     </div>
                     <div class="card">
@@ -371,7 +371,7 @@
                 <div id="common" class="common simple">
                     <div class="upper">
                         <p>简易版</p>
-                        <p>¥100/人/年</p>
+                        <p>¥50/人/年</p>
                         <span> <a href="http://worktime.ttkuaiban.com/#/login" target="_blank">立即注册</a></span>
                     </div>
                     <div class="middle">
@@ -390,7 +390,7 @@
                 <div id="common" class="common basics">
                     <div class="upper">
                         <p class="sale">基础版</p>
-                        <p>¥250/人/年</p>
+                        <p>¥150/人/年</p>
                         <span><a href="http://worktime.ttkuaiban.com/#/login" target="_blank">立即注册</a></span>
                     </div>
                     <div class="middle">
@@ -412,7 +412,7 @@
                 <div id="common" class="common specialty">
                     <div class="upper">
                         <p>专业版</p>
-                        <p>¥350/人/年</p>
+                        <p>¥200/人/年</p>
                         <span><a href="http://worktime.ttkuaiban.com/#/login" target="_blank">立即注册</a></span>
                     </div>
                     <div class="middle">

+ 8 - 0
fhKeeper/formulahousekeeper/inva_4_tivo/mobile.html

@@ -85,8 +85,16 @@
                         </div>
                         <div class="card-body">
                             <h4 class="card-title" id="mobTxt">关注公众号,长按上方图片保存到手机,微信打开识别二维码</h4>
+                            
+                        </div>
+                        <div class="card-image">
+                            <img class="img-fluid" src="images/qr_dingding.png" alt="wechat">
+                        </div>
+                        <div class="card-body">
+                            <h4 class="card-title" id="dingdingTxt">钉钉扫码,一键同步组织架构,方便快捷。</h4>
                             <a id="mobLink" class="btn-solid-lg page-scroll" href="http://mobworktime.ttkuaiban.com" >直接访问</a>
                         </div>
+                        
                     </div>
                 </div>
             </div>

+ 2 - 2
fhKeeper/formulahousekeeper/timesheet/config/index.js

@@ -1,9 +1,9 @@
 var path = require('path')
 
- //var ip = '127.0.0.1'
+ var ip = '127.0.0.1'
 
  
-var ip = '47.100.37.243'
+// var ip = '47.100.37.243'
 
 // var os = require('os'), ip = '', ifaces = os.networkInterfaces() // 获取本机ip
 // for (var i in ifaces) {

BIN
fhKeeper/formulahousekeeper/timesheet/favicon.ico


+ 62 - 49
fhKeeper/formulahousekeeper/timesheet/package-lock.json

@@ -90,7 +90,7 @@
     },
     "amdefine": {
       "version": "1.0.1",
-      "resolved": "https://registry.npm.taobao.org/amdefine/download/amdefine-1.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
       "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
       "dev": true
     },
@@ -446,7 +446,7 @@
     },
     "array-find-index": {
       "version": "1.0.2",
-      "resolved": "https://registry.npm.taobao.org/array-find-index/download/array-find-index-1.0.2.tgz",
+      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
       "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
       "dev": true
     },
@@ -526,7 +526,7 @@
     },
     "assert-plus": {
       "version": "1.0.0",
-      "resolved": "https://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
       "dev": true
     },
@@ -553,7 +553,7 @@
     },
     "async-foreach": {
       "version": "0.1.3",
-      "resolved": "https://registry.npm.taobao.org/async-foreach/download/async-foreach-0.1.3.tgz",
+      "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
       "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
       "dev": true
     },
@@ -573,7 +573,7 @@
     },
     "asynckit": {
       "version": "0.4.0",
-      "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
       "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
       "dev": true
     },
@@ -599,7 +599,7 @@
     },
     "aws-sign2": {
       "version": "0.7.0",
-      "resolved": "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
       "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
       "dev": true
     },
@@ -1531,7 +1531,7 @@
     },
     "bcrypt-pbkdf": {
       "version": "1.0.2",
-      "resolved": "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
       "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
       "dev": true,
       "requires": {
@@ -1563,7 +1563,7 @@
     },
     "block-stream": {
       "version": "0.0.9",
-      "resolved": "https://registry.npm.taobao.org/block-stream/download/block-stream-0.0.9.tgz",
+      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
       "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
       "dev": true,
       "requires": {
@@ -1807,13 +1807,13 @@
     },
     "camelcase": {
       "version": "2.1.1",
-      "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-2.1.1.tgz?cache=0&sync_timestamp=1603921884289&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-2.1.1.tgz",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
       "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
       "dev": true
     },
     "camelcase-keys": {
       "version": "2.1.0",
-      "resolved": "https://registry.npm.taobao.org/camelcase-keys/download/camelcase-keys-2.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
       "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
       "dev": true,
       "requires": {
@@ -1847,7 +1847,7 @@
     },
     "caseless": {
       "version": "0.12.0",
-      "resolved": "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
       "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
       "dev": true
     },
@@ -2342,7 +2342,7 @@
     },
     "console-control-strings": {
       "version": "1.1.0",
-      "resolved": "https://registry.npm.taobao.org/console-control-strings/download/console-control-strings-1.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
       "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
       "dev": true
     },
@@ -2569,7 +2569,7 @@
     },
     "cross-spawn": {
       "version": "3.0.1",
-      "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-3.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcross-spawn%2Fdownload%2Fcross-spawn-3.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
       "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
       "dev": true,
       "requires": {
@@ -2756,7 +2756,7 @@
     },
     "currently-unhandled": {
       "version": "0.4.1",
-      "resolved": "https://registry.npm.taobao.org/currently-unhandled/download/currently-unhandled-0.4.1.tgz",
+      "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
       "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
       "dev": true,
       "requires": {
@@ -2771,7 +2771,7 @@
     },
     "dashdash": {
       "version": "1.14.1",
-      "resolved": "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz?cache=0&sync_timestamp=1601073602368&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdashdash%2Fdownload%2Fdashdash-1.14.1.tgz",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
       "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
       "dev": true,
       "requires": {
@@ -2886,7 +2886,7 @@
     },
     "delayed-stream": {
       "version": "1.0.0",
-      "resolved": "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
       "dev": true
     },
@@ -2897,7 +2897,7 @@
     },
     "delegates": {
       "version": "1.0.0",
-      "resolved": "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
       "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
       "dev": true
     },
@@ -2943,6 +2943,14 @@
         "randombytes": "^2.0.0"
       }
     },
+    "dingtalk-jsapi": {
+      "version": "2.13.42",
+      "resolved": "https://registry.nlark.com/dingtalk-jsapi/download/dingtalk-jsapi-2.13.42.tgz?cache=0&sync_timestamp=1624277670244&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdingtalk-jsapi%2Fdownload%2Fdingtalk-jsapi-2.13.42.tgz",
+      "integrity": "sha1-CsEBEIRty6MwQ3L51XlJfxrB4rg=",
+      "requires": {
+        "promise-polyfill": "^7.1.0"
+      }
+    },
     "dir-glob": {
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
@@ -3022,7 +3030,7 @@
     },
     "ecc-jsbn": {
       "version": "0.1.2",
-      "resolved": "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
       "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
       "dev": true,
       "requires": {
@@ -3381,7 +3389,7 @@
     },
     "extsprintf": {
       "version": "1.3.0",
-      "resolved": "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz",
+      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
       "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
       "dev": true
     },
@@ -3557,7 +3565,7 @@
     },
     "forever-agent": {
       "version": "0.6.1",
-      "resolved": "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
       "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
       "dev": true
     },
@@ -4200,7 +4208,7 @@
     },
     "gauge": {
       "version": "2.7.4",
-      "resolved": "https://registry.npm.taobao.org/gauge/download/gauge-2.7.4.tgz",
+      "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
       "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
       "dev": true,
       "requires": {
@@ -4216,7 +4224,7 @@
       "dependencies": {
         "is-fullwidth-code-point": {
           "version": "1.0.0",
-          "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
           "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
           "dev": true,
           "requires": {
@@ -4225,7 +4233,7 @@
         },
         "string-width": {
           "version": "1.0.2",
-          "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz?cache=0&sync_timestamp=1618558821529&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-1.0.2.tgz",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
           "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
           "dev": true,
           "requires": {
@@ -4253,7 +4261,7 @@
     },
     "get-stdin": {
       "version": "4.0.1",
-      "resolved": "https://registry.npm.taobao.org/get-stdin/download/get-stdin-4.0.1.tgz?cache=0&sync_timestamp=1618557606273&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fget-stdin%2Fdownload%2Fget-stdin-4.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
       "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
       "dev": true
     },
@@ -4265,7 +4273,7 @@
     },
     "getpass": {
       "version": "0.1.7",
-      "resolved": "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
       "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
       "dev": true,
       "requires": {
@@ -4396,7 +4404,7 @@
     },
     "har-schema": {
       "version": "2.0.0",
-      "resolved": "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
       "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
       "dev": true
     },
@@ -4462,7 +4470,7 @@
     },
     "has-unicode": {
       "version": "2.0.1",
-      "resolved": "https://registry.npm.taobao.org/has-unicode/download/has-unicode-2.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
       "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
       "dev": true
     },
@@ -4710,7 +4718,7 @@
     },
     "http-signature": {
       "version": "1.2.0",
-      "resolved": "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz?cache=0&sync_timestamp=1600868441269&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-signature%2Fdownload%2Fhttp-signature-1.2.0.tgz",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
       "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
       "dev": true,
       "requires": {
@@ -4772,7 +4780,7 @@
     },
     "indent-string": {
       "version": "2.1.0",
-      "resolved": "https://registry.nlark.com/indent-string/download/indent-string-2.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
       "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
       "dev": true,
       "requires": {
@@ -5010,7 +5018,7 @@
     },
     "is-typedarray": {
       "version": "1.0.0",
-      "resolved": "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
       "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
       "dev": true
     },
@@ -5034,7 +5042,7 @@
     },
     "isexe": {
       "version": "2.0.0",
-      "resolved": "https://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
       "dev": true
     },
@@ -5049,7 +5057,7 @@
     },
     "isstream": {
       "version": "0.1.2",
-      "resolved": "https://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
       "dev": true
     },
@@ -5107,7 +5115,7 @@
     },
     "jsbn": {
       "version": "0.1.1",
-      "resolved": "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
       "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
       "dev": true
     },
@@ -5125,7 +5133,7 @@
     },
     "json-schema": {
       "version": "0.2.3",
-      "resolved": "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz?cache=0&sync_timestamp=1609553686459&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema%2Fdownload%2Fjson-schema-0.2.3.tgz",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
       "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
       "dev": true
     },
@@ -5146,7 +5154,7 @@
     },
     "json-stringify-safe": {
       "version": "5.0.1",
-      "resolved": "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz?cache=0&sync_timestamp=1573614722142&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-stringify-safe%2Fdownload%2Fjson-stringify-safe-5.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
       "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
       "dev": true
     },
@@ -5164,7 +5172,7 @@
     },
     "jsprim": {
       "version": "1.4.1",
-      "resolved": "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
       "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
       "dev": true,
       "requires": {
@@ -5348,7 +5356,7 @@
     },
     "loud-rejection": {
       "version": "1.6.0",
-      "resolved": "https://registry.npm.taobao.org/loud-rejection/download/loud-rejection-1.6.0.tgz",
+      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
       "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
       "dev": true,
       "requires": {
@@ -5389,7 +5397,7 @@
     },
     "map-obj": {
       "version": "1.0.1",
-      "resolved": "https://registry.nlark.com/map-obj/download/map-obj-1.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
       "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
       "dev": true
     },
@@ -5443,7 +5451,7 @@
     },
     "meow": {
       "version": "3.7.0",
-      "resolved": "https://registry.nlark.com/meow/download/meow-3.7.0.tgz?cache=0&sync_timestamp=1620227947636&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmeow%2Fdownload%2Fmeow-3.7.0.tgz",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
       "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
       "dev": true,
       "requires": {
@@ -5835,7 +5843,7 @@
     },
     "nopt": {
       "version": "3.0.6",
-      "resolved": "https://registry.npm.taobao.org/nopt/download/nopt-3.0.6.tgz?cache=0&sync_timestamp=1597649942437&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnopt%2Fdownload%2Fnopt-3.0.6.tgz",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
       "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
       "dev": true,
       "requires": {
@@ -6340,7 +6348,7 @@
     },
     "performance-now": {
       "version": "2.1.0",
-      "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
       "dev": true
     },
@@ -7008,6 +7016,11 @@
       "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
       "dev": true
     },
+    "promise-polyfill": {
+      "version": "7.1.2",
+      "resolved": "https://registry.npm.taobao.org/promise-polyfill/download/promise-polyfill-7.1.2.tgz",
+      "integrity": "sha1-qwUwHYwoU2MBYi1pInYyJppwyjs="
+    },
     "proto-list": {
       "version": "1.2.4",
       "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
@@ -7646,7 +7659,7 @@
     },
     "redent": {
       "version": "1.0.0",
-      "resolved": "https://registry.nlark.com/redent/download/redent-1.0.0.tgz?cache=0&sync_timestamp=1620070119923&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fredent%2Fdownload%2Fredent-1.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
       "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
       "dev": true,
       "requires": {
@@ -8041,7 +8054,7 @@
     },
     "scss-tokenizer": {
       "version": "0.2.3",
-      "resolved": "https://registry.npm.taobao.org/scss-tokenizer/download/scss-tokenizer-0.2.3.tgz",
+      "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
       "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
       "dev": true,
       "requires": {
@@ -8051,7 +8064,7 @@
       "dependencies": {
         "source-map": {
           "version": "0.4.4",
-          "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.4.4.tgz",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
           "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
           "dev": true,
           "requires": {
@@ -8595,7 +8608,7 @@
     },
     "strip-indent": {
       "version": "1.0.1",
-      "resolved": "https://registry.nlark.com/strip-indent/download/strip-indent-1.0.1.tgz?cache=0&sync_timestamp=1620053263051&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fstrip-indent%2Fdownload%2Fstrip-indent-1.0.1.tgz",
+      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
       "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
       "dev": true,
       "requires": {
@@ -8761,7 +8774,7 @@
     },
     "trim-newlines": {
       "version": "1.0.0",
-      "resolved": "https://registry.nlark.com/trim-newlines/download/trim-newlines-1.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
       "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
       "dev": true
     },
@@ -8794,7 +8807,7 @@
     },
     "tunnel-agent": {
       "version": "0.6.0",
-      "resolved": "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
       "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
       "dev": true,
       "requires": {
@@ -8803,7 +8816,7 @@
     },
     "tweetnacl": {
       "version": "0.14.5",
-      "resolved": "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz?cache=0&sync_timestamp=1581365004105&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftweetnacl%2Fdownload%2Ftweetnacl-0.14.5.tgz",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
       "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
       "dev": true
     },
@@ -9119,7 +9132,7 @@
     },
     "verror": {
       "version": "1.10.0",
-      "resolved": "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz",
+      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
       "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
       "dev": true,
       "requires": {

+ 1 - 0
fhKeeper/formulahousekeeper/timesheet/package.json

@@ -13,6 +13,7 @@
     "@tinymce/tinymce-vue": "^4.0.0",
     "axios": "^0.15.3",
     "dayjs": "^1.10.4",
+    "dingtalk-jsapi": "^2.13.42",
     "echarts": "^3.8.5",
     "element-ui": "^2.13.0",
     "font-awesome": "^4.7.0",

+ 233 - 3
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/demo_index.html

@@ -54,6 +54,66 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xe611;</span>
+                <div class="name">密 码</div>
+                <div class="code-name">&amp;#xe611;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe608;</span>
+                <div class="name">密 码</div>
+                <div class="code-name">&amp;#xe608;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe60d;</span>
+                <div class="name">验证码</div>
+                <div class="code-name">&amp;#xe60d;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe60b;</span>
+                <div class="name">dot</div>
+                <div class="code-name">&amp;#xe60b;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe607;</span>
+                <div class="name">dot</div>
+                <div class="code-name">&amp;#xe607;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe636;</span>
+                <div class="name">报表管理</div>
+                <div class="code-name">&amp;#xe636;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe698;</span>
+                <div class="name">组织架构</div>
+                <div class="code-name">&amp;#xe698;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe60a;</span>
+                <div class="name">填报</div>
+                <div class="code-name">&amp;#xe60a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe606;</span>
+                <div class="name">组织架构</div>
+                <div class="code-name">&amp;#xe606;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe670;</span>
+                <div class="name">组织结构</div>
+                <div class="code-name">&amp;#xe670;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe663;</span>
                 <div class="name">权限</div>
@@ -282,9 +342,9 @@
 <pre><code class="language-css"
 >@font-face {
   font-family: 'iconfont';
-  src: url('iconfont.woff2?t=1622768216453') format('woff2'),
-       url('iconfont.woff?t=1622768216453') format('woff'),
-       url('iconfont.ttf?t=1622768216453') format('truetype');
+  src: url('iconfont.woff2?t=1624604148407') format('woff2'),
+       url('iconfont.woff?t=1624604148407') format('woff'),
+       url('iconfont.ttf?t=1624604148407') format('truetype');
 }
 </code></pre>
           <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -310,6 +370,96 @@
       <div class="content font-class">
         <ul class="icon_lists dib-box">
           
+          <li class="dib">
+            <span class="icon iconfont firerock-iconmima"></span>
+            <div class="name">
+              密 码
+            </div>
+            <div class="code-name">.firerock-iconmima
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconmima1"></span>
+            <div class="name">
+              密 码
+            </div>
+            <div class="code-name">.firerock-iconmima1
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconyanzhengma"></span>
+            <div class="name">
+              验证码
+            </div>
+            <div class="code-name">.firerock-iconyanzhengma
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-icondot"></span>
+            <div class="name">
+              dot
+            </div>
+            <div class="code-name">.firerock-icondot
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-icondot2"></span>
+            <div class="name">
+              dot
+            </div>
+            <div class="code-name">.firerock-icondot2
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconbaobiao"></span>
+            <div class="name">
+              报表管理
+            </div>
+            <div class="code-name">.firerock-iconbaobiao
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconzuzhijiagou1"></span>
+            <div class="name">
+              组织架构
+            </div>
+            <div class="code-name">.firerock-iconzuzhijiagou1
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-icontianbao1"></span>
+            <div class="name">
+              填报
+            </div>
+            <div class="code-name">.firerock-icontianbao1
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconzuzhijiagou"></span>
+            <div class="name">
+              组织架构
+            </div>
+            <div class="code-name">.firerock-iconzuzhijiagou
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconzuzhijiegou"></span>
+            <div class="name">
+              组织结构
+            </div>
+            <div class="code-name">.firerock-iconzuzhijiegou
+            </div>
+          </li>
+          
           <li class="dib">
             <span class="icon iconfont firerock-iconquanxian"></span>
             <div class="name">
@@ -652,6 +802,86 @@
       <div class="content symbol">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconmima"></use>
+                </svg>
+                <div class="name">密 码</div>
+                <div class="code-name">#firerock-iconmima</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconmima1"></use>
+                </svg>
+                <div class="name">密 码</div>
+                <div class="code-name">#firerock-iconmima1</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconyanzhengma"></use>
+                </svg>
+                <div class="name">验证码</div>
+                <div class="code-name">#firerock-iconyanzhengma</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-icondot"></use>
+                </svg>
+                <div class="name">dot</div>
+                <div class="code-name">#firerock-icondot</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-icondot2"></use>
+                </svg>
+                <div class="name">dot</div>
+                <div class="code-name">#firerock-icondot2</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconbaobiao"></use>
+                </svg>
+                <div class="name">报表管理</div>
+                <div class="code-name">#firerock-iconbaobiao</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconzuzhijiagou1"></use>
+                </svg>
+                <div class="name">组织架构</div>
+                <div class="code-name">#firerock-iconzuzhijiagou1</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-icontianbao1"></use>
+                </svg>
+                <div class="name">填报</div>
+                <div class="code-name">#firerock-icontianbao1</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconzuzhijiagou"></use>
+                </svg>
+                <div class="name">组织架构</div>
+                <div class="code-name">#firerock-iconzuzhijiagou</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconzuzhijiegou"></use>
+                </svg>
+                <div class="name">组织结构</div>
+                <div class="code-name">#firerock-iconzuzhijiegou</div>
+            </li>
+          
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
                   <use xlink:href="#firerock-iconquanxian"></use>

+ 43 - 3
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 2390497 */
-  src: url('iconfont.woff2?t=1622768216453') format('woff2'),
-       url('iconfont.woff?t=1622768216453') format('woff'),
-       url('iconfont.ttf?t=1622768216453') format('truetype');
+  src: url('iconfont.woff2?t=1624604148407') format('woff2'),
+       url('iconfont.woff?t=1624604148407') format('woff'),
+       url('iconfont.ttf?t=1624604148407') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,46 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.firerock-iconmima:before {
+  content: "\e611";
+}
+
+.firerock-iconmima1:before {
+  content: "\e608";
+}
+
+.firerock-iconyanzhengma:before {
+  content: "\e60d";
+}
+
+.firerock-icondot:before {
+  content: "\e60b";
+}
+
+.firerock-icondot2:before {
+  content: "\e607";
+}
+
+.firerock-iconbaobiao:before {
+  content: "\e636";
+}
+
+.firerock-iconzuzhijiagou1:before {
+  content: "\e698";
+}
+
+.firerock-icontianbao1:before {
+  content: "\e60a";
+}
+
+.firerock-iconzuzhijiagou:before {
+  content: "\e606";
+}
+
+.firerock-iconzuzhijiegou:before {
+  content: "\e670";
+}
+
 .firerock-iconquanxian:before {
   content: "\e663";
 }

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.js


+ 70 - 0
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.json

@@ -5,6 +5,76 @@
   "css_prefix_text": "firerock-icon",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "19410111",
+      "name": "密 码",
+      "font_class": "mima",
+      "unicode": "e611",
+      "unicode_decimal": 58897
+    },
+    {
+      "icon_id": "16842350",
+      "name": "密 码",
+      "font_class": "mima1",
+      "unicode": "e608",
+      "unicode_decimal": 58888
+    },
+    {
+      "icon_id": "20915138",
+      "name": "验证码",
+      "font_class": "yanzhengma",
+      "unicode": "e60d",
+      "unicode_decimal": 58893
+    },
+    {
+      "icon_id": "11640993",
+      "name": "dot",
+      "font_class": "dot",
+      "unicode": "e60b",
+      "unicode_decimal": 58891
+    },
+    {
+      "icon_id": "9382963",
+      "name": "dot",
+      "font_class": "dot2",
+      "unicode": "e607",
+      "unicode_decimal": 58887
+    },
+    {
+      "icon_id": "7171606",
+      "name": "报表管理",
+      "font_class": "baobiao",
+      "unicode": "e636",
+      "unicode_decimal": 58934
+    },
+    {
+      "icon_id": "4426098",
+      "name": "组织架构",
+      "font_class": "zuzhijiagou1",
+      "unicode": "e698",
+      "unicode_decimal": 59032
+    },
+    {
+      "icon_id": "13100227",
+      "name": "填报",
+      "font_class": "tianbao1",
+      "unicode": "e60a",
+      "unicode_decimal": 58890
+    },
+    {
+      "icon_id": "4469651",
+      "name": "组织架构",
+      "font_class": "zuzhijiagou",
+      "unicode": "e606",
+      "unicode_decimal": 58886
+    },
+    {
+      "icon_id": "4231111",
+      "name": "组织结构",
+      "font_class": "zuzhijiegou",
+      "unicode": "e670",
+      "unicode_decimal": 58992
+    },
     {
       "icon_id": "12860884",
       "name": "权限",

BIN
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.ttf


BIN
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.woff


BIN
fhKeeper/formulahousekeeper/timesheet/src/assets/myfont/iconfont.woff2


+ 9 - 29
fhKeeper/formulahousekeeper/timesheet/src/main.js

@@ -46,7 +46,7 @@ import 'nprogress/nprogress.css'
 var addRouFlag = false;
 //角色权限对应关系
 var userModules = [{role:0, modules:["工时报告","自动计时","项目管理"]},
-            {role:3, modules:["成本统计","财务核算成本","项目管理"]},
+            {role:3, modules:["工时成本统计","项目报表服务","费用报销","财务核算成本","项目管理"]},
             {role:4, modules:["组织架构"]},
             {role:5, modules:["工时报告","自动计时","项目管理"]},];
 router.beforeEach((to, from, next) => {
@@ -72,15 +72,19 @@ router.beforeEach((to, from, next) => {
             if(user != null) {
                 addRouFlag = true;
                 var getRoutes = null;
+                var filterRouter = allRouters;
                 if (user.company.packageExpense == 0) {
-                    allRoutes = allRouters.filter(r=>r.name != '费用报销');
+                    filterRouter = allRouters.filter(r=>{return r.name != '费用报销' && r.name != '项目报表服务'});
                 }
+
                 if (user.role == 1 || user.role == 2) {
-                    getRoutes = allRouters;
+                    getRoutes = filterRouter;
                 } else {
                     var modules = userModules.filter(u=>u.role == user.role)[0].modules;
-                    
-                    getRoutes = allRouters.filter(r=>{
+                    if (user.role == 0 && user.leader) {
+                        modules.push(2, "报告审核");
+                    }
+                    getRoutes = filterRouter.filter(r=>{
                         return modules.filter(m=>m == r.name).length > 0;
                     });
                 }
@@ -89,30 +93,6 @@ router.beforeEach((to, from, next) => {
                 router.options.routes = fixedRouter.concat(getRoutes);
                 router.push({ path: to.path })
                 
-                // if(user.role == 0) {
-                //     var getRoutes = baseRoleGetRouters(user.leader?leaderRouter:staffRouter, user);
-                //     if (user.company.packageProject == 1 && !user.leader) {
-                //         getRoutes = getRoutes.concat(projectManageRouter);
-                //     }
-                //     if (user.company.packageExpense == 1) {
-                //         getRoutes = getRoutes.concat(expenseRouter);
-                //     }
-                //     global.antRouter = fixedRouter.concat(getRoutes);
-                //     router.addRoutes(fixedRouter.concat(getRoutes));
-                //     router.options.routes = fixedRouter.concat(getRoutes);
-                //     router.push({ path: to.path })
-                // } else {
-                //     var getRoutes = baseRoleGetRouters(manageRouter, user);
-                //     if (user.company.packageExpense == 1) {
-                //         getRoutes = getRoutes.concat(expenseRouter);
-                //     }
-                //     getRoutes = getRoutes.concat(sysManageRouter);
-                    
-                //     global.antRouter = fixedRouter.concat(getRoutes);
-                //     router.addRoutes(fixedRouter.concat(getRoutes));
-                //     router.options.routes = fixedRouter.concat(getRoutes);
-                //     router.push({ path: to.path })
-                // }
             }
         }
         next()

+ 18 - 5
fhKeeper/formulahousekeeper/timesheet/src/routes.js

@@ -38,7 +38,9 @@ import Market from './views/market/list';
 import PdfView from './views/pdf/pdfview';
 
 // 费用报销
-import expense from './views/expense/expense'
+import expense from './views/expense/expense';
+//企业报表
+import corpReport from './views/corpreport/list';
 
 
 // 权限管理
@@ -95,7 +97,7 @@ export const allRouters = [//组织架构
         path: '/',
         component: Home,
         name: '工时报告',
-        iconCls: 'fa fa-sticky-note',
+        iconCls: 'iconfont firerock-icontianbao1',
         leaf: true,
         children: [
             { path: '/daily', component: daily, name: '工时报告' },
@@ -127,15 +129,16 @@ export const allRouters = [//组织架构
     {
         path: '/',
         component: Home,
-        name: '成本统计',
+        name: '工时成本统计',
         iconCls: 'iconfont firerock-icontongji',
         leaf: true,
         children: [
-            { path: '/cost', component: cost, name: '成本统计' },
+            { path: '/cost', component: cost, name: '工时成本统计' },
             { path: '/cost/:id/:name', component: proDetail, name: '成本详情', hidden: true },
             { path: '/costDep/:id/:name', component: depDetail, name: '成本详情', hidden: true },
         ]
     },
+    
     //每月财务成本
     {
         path: '/',
@@ -158,6 +161,16 @@ export const allRouters = [//组织架构
             { path: '/list', component: list, name: '项目管理' },
         ]
     },
+    {
+        path: '/',
+        component: Home,
+        name: '项目报表服务',
+        iconCls: 'iconfont firerock-iconbaobiao',
+        leaf: true,
+        children: [
+            { path: '/corpreport', component: corpReport, name: '项目报表服务' }
+        ]
+    },
     // 费用报销模块
     {
         path: '/',
@@ -173,7 +186,7 @@ export const allRouters = [//组织架构
         path: '/',
         component: Home,
         name: '组织架构',
-        iconCls: 'fa fa-users',
+        iconCls: 'iconfont firerock-iconzuzhijiagou1',
         leaf: true,//只有一个节点
         children: [
             { path: '/team', component: team, name: '组织架构' },

+ 74 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/Login.vue

@@ -43,6 +43,7 @@
 </template>
 
 <script>
+    import * as dd from 'dingtalk-jsapi';
     export default {
         data() {
             return {
@@ -59,7 +60,80 @@
                 }
             };
         },
+        created() {
+            if (localStorage.userInfo != null) {
+                var user = JSON.parse(localStorage.userInfo);
+                if (user.role == 3) {
+                    //公司高层
+                    this.$router.push({ path: '/cost' });
+                } else if (user.role == 4) {
+                    //人事管理员
+                    this.$router.push({ path: '/team' });
+                } else {
+                    this.$router.push({ path: '/daily' });
+                }
+            }
+        },
+        mounted() {
+            if (localStorage.userInfo != null) {
+                var user = JSON.parse(localStorage.userInfo);
+                if (user.role == 3) {
+                    //公司高层
+                    this.$router.push({ path: '/cost' });
+                } else if (user.role == 4) {
+                    //人事管理员
+                    this.$router.push({ path: '/team' });
+                } else {
+                    this.$router.push({ path: '/daily' });
+                }
+            } else {
+                //检查环境,如果是钉钉有$CORPID$
+                var key = '?corpid=';
+                var url = location.href;
+                var that = this;
+                if (url.indexOf(key) > 0) {
+                    var corpId = url.substring(url.indexOf(key)+key.length,url.indexOf('#'));
+                    dd.ready(function() {
+                        dd.runtime.permission.requestAuthCode({
+                            corpId: corpId, // 企业id
+                            onSuccess: function (info) {
+                                var code = info.code // 通过该免登授权码可以获取用户身份
+                                that.loginByCode(code, corpId);
+                            }});
+                    });
+                } 
+            }
+        },
         methods: {
+            loginByCode(code, corpId) {
+                this.http.post("/dingding/getUserByCode", {code:code, corpid:corpId} , res => {
+                            if (res.code == "ok") {
+                                var user = res.data;
+                                localStorage.user = JSON.stringify(res.data);
+                                sessionStorage.setItem('user', JSON.stringify(res.data));
+                                if (user.role == 3) {
+                                    //公司高层
+                                    this.$router.push({ path: '/cost' });
+                                } else if (user.role == 4) {
+                                    //人事管理员
+                                    this.$router.push({ path: '/team' });
+                                } else {
+                                    this.$router.push({ path: '/daily' });
+                                }
+                            } else {
+                                this.$message({
+                                    message: res.msg,
+                                    type: 'error'
+                                });
+                            }
+                        }, error => {
+                            this.$message({
+                                message: error,
+                                type: 'error'
+                            });
+                        })
+            },
+
             handleReset2() {
                 this.$refs.ruleForm.resetFields();
             },

+ 83 - 8
fhKeeper/formulahousekeeper/timesheet/src/views/Register.vue

@@ -15,8 +15,21 @@
                 <el-form-item class="login-input" prop="phone">
                     <el-input type="text" v-model="ruleForm.phone" autocomplete="off" placeholder="手机号" clearable prefix-icon="el-icon-mobile-phone"></el-input>
                 </el-form-item>
-                <div style="color:#aaa;margin:15px 0 20px 0;">初始密码:000000</div>
-                <div class="login-button" style="width:100%;margin-top:0;">
+                <el-form-item class="login-input" prop="vcode">
+                    <el-input type="text" v-model="ruleForm.vcode" autocomplete="off" placeholder="验证码" clearable prefix-icon="iconfont firerock-iconyanzhengma">
+                        <el-button slot="append" @click="sendVcode" :disabled="ruleForm.phone=='' || showTimer">发送验证码<span v-if="showTimer">({{countNum}})</span></el-button>
+                    </el-input>
+                </el-form-item>
+                <el-form-item class="login-input" prop="password">
+                    <el-input type="password" v-model="ruleForm.password" autocomplete="off" placeholder="设置密码,长度不低于6位" clearable prefix-icon="iconfont firerock-iconmima">
+                    </el-input>
+                </el-form-item>
+                <el-form-item class="login-input" prop="repwd">
+                    <el-input type="password" v-model="ruleForm.repwd" autocomplete="off" placeholder="重复密码" clearable prefix-icon="iconfont firerock-iconmima">
+                    </el-input>
+                </el-form-item>
+                <div style="color:#aaa;margin:55px 0 20px 0;"></div>
+                <div class="login-button" style="width:100%;margin-top:10px;">
                     <el-button type="primary" style="width:100%;" @click.native.prevent="handleSubmit" :loading="logining">注册</el-button>
                 </div>
             </el-form>
@@ -29,20 +42,67 @@
         data() {
             return {
                 logining: false,
+                showTimer: false,
+                countNum: 60,
                 // 登录信息
                 ruleForm: {
                     companyName: '',
                     name: '',
-                    phone: ''
+                    phone: '',
+
                 },
                 rules: {
                     companyName: [{ required: true, message: '请输入公司名', trigger: 'blur' },],
                     name: [{ required: true, message: '请输入姓名', trigger: 'blur' },],
-                    phone: [{ required: true, message: '请输入手机号', trigger: 'blur' },]
+                    phone: [{ required: true, message: '请输入手机号', trigger: 'blur' },],
+                    vcode: [{ required: true, message: '请输入验证码', trigger: 'blur' },],
+                    password: [{ required: true, message: '请设置密码,长度不低于6位', trigger: 'blur' },],
+                    repwd: [{ required: true, message: '请重复输入密码', trigger: 'blur' },]
                 }
             };
         },
         methods: {
+            //开始倒计时
+            countDown() {
+                if (this.countNum > 0) {
+                    this.countNum--;
+                } else {
+                    clearInterval(this.timer);
+                    this.showTimer = false;
+                }
+            },
+            sendVcode() {
+                if (this.ruleForm.phone.length != 11) {
+                    this.$message({
+                                    message: '手机号码格式不正确',
+                                    type: 'error'
+                                });
+                } else {
+                    this.http.post('/user/sendVcode', {mobile: this.ruleForm.phone} , res => {
+                            this.logining = false;
+                            if (res.code == "ok") {
+                                this.$message({
+                                    message: '发送成功',
+                                    type: 'success'
+                                });
+                                this.showTimer = true;
+                                this.countNum = 60;
+                                this.timer = setInterval(this.countDown, 1000);
+                            } else {
+                                this.$message({
+                                    message: res.msg,
+                                    type: 'error'
+                                });
+                            }
+                        }, error => {
+                            this.logining = false;
+                            this.$message({
+                                message: error,
+                                type: 'error'
+                            });
+                        })
+                }
+            },
             handleReset2() {
                 this.$refs.ruleForm.resetFields();
             },
@@ -50,6 +110,21 @@
             handleSubmit(ev) {
                 this.$refs.ruleForm.validate((valid) => {
                     if (valid) {
+                        if (this.ruleForm.password.length < 6) {
+                            this.$message({
+                                    message: '密码长度不能少于6位',
+                                    type: 'error'
+                                });
+                            return;
+                        }
+                        //检查两次密码是否一致
+                        if (this.ruleForm.password != this.ruleForm.repwd) {
+                            this.$message({
+                                    message: '两次输入的密码不一致',
+                                    type: 'error'
+                                });
+                            return;
+                        }
                         var _this = this;
                         this.logining = true;
                         this.http.post(this.port.manage.register, this.ruleForm , res => {
@@ -101,7 +176,7 @@
                 -moz-border-radius: 5px;
                 background-clip: padding-box;
                 width: 450px;
-                height: 365px;
+                height: 385px;
                 padding: 25px 35px 25px 35px;
                 background: #fff;
                 border: 1px solid #eaeaea;
@@ -110,7 +185,7 @@
                 margin:auto;
                 .title {
                     font-size: 20px;
-                    margin: 0px auto 40px auto;
+                    margin: 0px auto 30px auto;
                     text-align: center;
                     color: #505458;
                 }
@@ -118,10 +193,10 @@
                     margin: 0px 0px 35px 0px;
                 }
                 .login-input {
-                    margin: 30px 0 0 0;
+                    margin: 15px 0 0 0;
                 }
                 .login-button {
-                    margin: 30px 0 0 0;
+                    margin: 50px 0 0 0;
                 }
                 .login-button .el-button {
                     padding: 14px;

+ 77 - 30
fhKeeper/formulahousekeeper/timesheet/src/views/expense/expense.vue

@@ -21,13 +21,13 @@
               <el-menu-item index="1-2"><p @click="ssl(1)">差旅费用填报</p></el-menu-item>
               <el-menu-item index="1-3"><p @click="ssl(2)">外包费用填报</p></el-menu-item>
             </el-submenu>
-            <!-- <el-menu-item index="2" @select="bills">
-              <i class="el-icon-setting"></i>
-              <span slot="title">我的报销单据</span>
-            </el-menu-item> -->
+            <el-menu-item index="2" @select="bills" @click="bills">
+              <i class="iconfont firerock-iconbaoxiaodan"></i>
+              <span slot="title">报销单据列表</span>
+            </el-menu-item>
           </el-menu>
-           <el-menu
-          default-active="1-1"
+           <!-- <el-menu
+          default-active="2"
           class="el-menu-vertical-demo"
           @select="bills"
           background-color="#ffffff"
@@ -38,7 +38,7 @@
               <i class="iconfont firerock-iconbaoxiaodan"></i>
               <span slot="title">报销单据列表</span>
             </el-menu-item>
-          </el-menu>
+          </el-menu> -->
       </el-col>
     </div>
      <!-- 侧边栏点击事件 -->
@@ -58,9 +58,9 @@
         <div class="public">
           <el-form :model="addForm" label-width="80px">
             <!-- <el-form :model="form" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"> -->
-            <!-- 报人 -->
-            <el-form-item label="报人">
-              <el-select v-model="addForm.ownerId" placeholder="请选择报人" style="width: 150px">
+            <!-- 报人 -->
+            <el-form-item label="报人">
+              <el-select v-model="addForm.ownerId" placeholder="请选择报人" style="width: 150px">
                 <span v-for="(item, index) in users" :key="index">
                   <el-option :label="item.name" :value="item.id"></el-option>
                 </span>
@@ -129,9 +129,16 @@
                 </el-select>
               </template>
             </el-table-column>
+            <el-table-column label="费用类型" width="155px">
+              <template slot-scope="scope">
+                <el-select size="small" v-model="scope.row.expenseType" placeholder="费用类型" style="width: 150px" >
+                  <el-option v-for="(item, index) in expenseTypeList" :key="index" :label="item.typeName" :value="item.typeName" ></el-option>
+                </el-select>
+              </template>
+            </el-table-column>
             <el-table-column label="费用金额" width="135px">
               <template slot-scope="scope">
-                <el-input size="small" v-enter-number v-model.number="scope.row.amount" @change="shiqu(scope.row.amount)"></el-input>
+                <el-input size="small"  v-model="scope.row.amount" @change="shiqu(scope.row.amount)"></el-input>
               </template>
             </el-table-column>
             <el-table-column prop="invoiceNo" label="发票号" width="135px">
@@ -141,17 +148,17 @@
             </el-table-column>
             <el-table-column label="税率%" width="135px">
               <template slot-scope="scope">
-                <el-input size="small" v-enter-number v-model.number="scope.row.taxPercent"></el-input>
+                <el-input size="small"  v-model="scope.row.taxPercent"></el-input>
               </template>
             </el-table-column>
             <el-table-column label="税额" width="135px">
               <template slot-scope="scope">
-                <el-input size="small" v-enter-number v-model.number="scope.row.taxValue"></el-input>
+                <el-input size="small" v-model="scope.row.taxValue"></el-input>
               </template>
             </el-table-column>
             <el-table-column label="备注" width="135px">
               <template slot-scope="scope">
-                <el-input size="small" v-model.number="scope.row.remark"></el-input>
+                <el-input size="small" v-model="scope.row.remark"></el-input>
               </template>
             </el-table-column>
             <el-table-column fixed="right"
@@ -199,7 +206,7 @@
           <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
               <el-table-column prop="code" label="票据编号"></el-table-column>
               <el-table-column prop="totalAmount" label="金额(元)" ></el-table-column>
-              <el-table-column prop="ownerName" label="报人" ></el-table-column>
+              <el-table-column prop="ownerName" label="报人" ></el-table-column>
               <el-table-column prop="createDate" label="填报日期" ></el-table-column>
               <el-table-column prop="ticketNum" label="发票张数" ></el-table-column>
               <el-table-column prop="type" label="票据类型" >
@@ -240,15 +247,15 @@
     <!-- 我的单据报销展示 -->
       <el-dialog title="报销单据详情" :visible.sync="dialog" width="1000px">
         <!-- 内容主体 -->
-        <div class="informant"><!--  报人 -->
+        <div class="informant"><!--  报人 -->
           <el-form :model="ParticularsList" label-width="80px">
-            <el-form-item label="报人">
-              <el-input v-model="ParticularsList.ownerName" :disabled="flg"></el-input>
-              <!-- <el-select v-model="ParticularsList.ownerId" placeholder="请选择报人" style="width: 150px" :disabled="flg">
+            <el-form-item label="报人">
+              <el-input v-show="flg" v-model="ParticularsList.ownerName" disabled ></el-input>
+              <el-select v-show="!flg" v-model="ParticularsList.ownerId" placeholder="请选择报人" style="width: 150px" :disabled="flg">
                 <span v-for="(item, index) in users" :key="index">
                   <el-option :label="item.name" :value="item.id"></el-option>
                 </span>
-              </el-select> -->
+              </el-select>
             </el-form-item>
             <el-form-item label="填报日期">
               <!-- <el-input v-model="ParticularsList.createDate" :disabled="flg"></el-input> -->
@@ -301,9 +308,17 @@
                 <span v-else>{{typeInvoic[scope.row.invoiceType]}}</span>
               </template>
             </el-table-column>
+            <el-table-column prop="invoiceType" label="费用类型" width="172">
+              <template slot-scope="scope">
+                <el-select v-if="!flg" size="small" v-model="scope.row.expenseType" placeholder="请选择费用类型" 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="费用金额(元)" width="172">
               <template slot-scope="scope">
-                <el-input size="small" v-enter-number v-if="!flg" v-model.number="scope.row.amount" @change="kan"></el-input>
+                <el-input size="small"  v-if="!flg" v-model="scope.row.amount" @change="kan"></el-input>
                 <span v-else>¥{{scope.row.amount}}</span>
               </template>
             </el-table-column>
@@ -315,19 +330,19 @@
             </el-table-column>
             <el-table-column prop="taxPercent" label="税率%" width="172">
               <template slot-scope="scope">
-                <el-input size="small" v-enter-number v-if="!flg" v-model.number="scope.row.taxPercent"></el-input>
+                <el-input size="small"  v-if="!flg" v-model="scope.row.taxPercent"></el-input>
                 <span v-else>{{scope.row.taxPercent}}</span>
               </template>
             </el-table-column>
             <el-table-column prop="taxValue" label="税额(元)" width="172">
               <template slot-scope="scope">
-                <el-input size="small" v-enter-number v-if="!flg" v-model.number="scope.row.taxValue"></el-input>
+                <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="备注" width="300">
               <template slot-scope="scope">
-                <el-input size="small" v-if="!flg" v-model.number="scope.row.remark"></el-input>
+                <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>
@@ -358,6 +373,8 @@ export default {
   props: {},
   data() {
     return {
+      allExpList:[],
+      expenseTypeList:[],
       tian:{a: null,b: null,c: null,d: null,e: null,f: null,g: null,h: null,},
       feeType:["一般费用","差旅费用","外包费用"],
       typeInvoic: ['增值税专用发票', '增值税普通发票'],
@@ -407,13 +424,16 @@ export default {
   },
 
   mounted() {
+    this.getNextCode();
     this.getUsers() // 获取人员信息
     this.getList() // 获取单据列表
-    this.getProjectList()
+    this.getProjectList();
+    this.getExpList();
   },
   filters: {
       numberToCurrency(value) {
           if (!value) return '0.00'
+          console.log('v=='+value);
           value = value.toFixed(2)
           const intPart = Math.trunc(value)
           const intPartFormat = intPart.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
@@ -427,11 +447,33 @@ export default {
       }
   },
   methods: {
+    getExpList() {
+      this.http.post('/expense-type/getList', {
+        },
+        res => {
+            if (res.code == "ok") {
+                this.allExpList = res.data;
+                this.expenseTypeList = this.allExpList.filter(a=>a.mainType == 0);
+            } else {
+                this.$message({
+                message: res.msg,
+                type: "error"
+                });
+            }
+        },
+        error => {
+            this.$message({
+                message: error,
+                type: "error"
+            });
+        });
+    },
     // 单据查看
     downloadByA(val) {
       this.dialog = true
       this.flg = true;
-      this.getParticulars(val.id)
+      this.getParticulars(val.id);
+      this.expenseTypeList = this.allExpList.filter(a=>a.mainType == val.type);
     },
     // 单据编辑
     showEditName(val) {
@@ -439,6 +481,7 @@ export default {
       this.flg = false,
       delete val.invoiceList
       this.getParticulars(val.id)
+      this.expenseTypeList = this.allExpList.filter(a=>a.mainType == val.type);
     },
     staffs() { // 控制员工费用报表
       this.displayTable = false;
@@ -460,6 +503,7 @@ export default {
      adds() {
       // happenDate
       this.ParticularsList.items = JSON.stringify(this.ParticularsList.invoiceList)//这里要传发票列表的json转string
+      
       delete this.ParticularsList.invoiceList
         this.http.post('/expense-sheet/add', this.ParticularsList,
         res => {
@@ -516,7 +560,7 @@ export default {
     },
     // 点击新增
     addxz() {
-      this.getNextCode()
+      
       this.form = {happenDate: null,invoiceType:null,amount:null,invoiceNo:null,taxPercent:null,taxValue:null,remark:null},
       this.invoiceList.push(this.form)
     },
@@ -595,6 +639,7 @@ export default {
     add() {
       // happenDate
       this.addForm.items = JSON.stringify(this.invoiceList)//这里要传发票列表的json转string
+      
         this.http.post('/expense-sheet/add', this.addForm,
         res => {
             if (res.code == "ok") {
@@ -715,7 +760,9 @@ export default {
     ssl(index) {
       this.z = index
       this.addForm.type = index
-      this.ins = index
+      this.ins = index;
+      this.expenseTypeList = this.allExpList.filter(a=>a.mainType == this.ins);
+      this.getNextCode();
     },
     
     // 点击侧边栏事件
@@ -743,12 +790,12 @@ export default {
     // 费用金额失去焦点时触发
     shiqu(){
       this.addForm.totalAmount = this.invoiceList.reduce((prev, next) => {
-        return prev + next.amount;
+        return prev + Number(next.amount);
       }, 0)
     },
     kan(){
       this.ParticularsList.totalAmount = this.ParticularsList.invoiceList.reduce((prev, next) => {
-        return prev + next.amount
+        return prev + Number(next.amount)
       }, 0)
     }
   },

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/market/list.vue

@@ -17,7 +17,7 @@
                     </template>
             </el-table-column>
             <el-table-column prop="companyName" label="公司名称"  ></el-table-column>
-            <el-table-column prop="ctime" label="注册时间"  ></el-table-column>
+            <el-table-column prop="cTime" label="注册时间"  ></el-table-column>
             <el-table-column prop="name" label="联系人" ></el-table-column>
             <el-table-column prop="phone" label="联系方式"  width="150"></el-table-column>
             <el-table-column prop="contacted" label="是否联系" >

+ 193 - 18
fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue

@@ -18,17 +18,22 @@
                 <el-radio-button label="人员"></el-radio-button>
             </el-radio-group>
         </el-col>
-        <div id="container" :style="'height:'+containerHeight+'px'"></div>
+        <div id="container" :style="'height:'+containerHeight+'px;'"></div>
         <div style="position:fixed;top:120px;right:150px;"><el-button @click="showExportDialog">报表导出</el-button></div>
 
         <!--导出报表条件选择 -->
         <el-dialog title="工时报表导出" v-if="exportDialog" :visible.sync="exportDialog" :close-on-click-modal="false" customClass="customWidth" width="500px">
             <el-form ref="form3" :model="exportParam" >
-                <el-form-item prop="projectId" label="选择项目">
+                <el-form-item prop="projectId" label="选择项目" v-if="radio != '人员'">
                     <el-select v-model="exportParam.projectId" placeholder="全部项目"  clearable style="width:350px;">
                         <el-option v-for="item in projectList"  :key="item.id" :label="item.projectName" :value="item.id"></el-option>
                     </el-select>
                 </el-form-item>
+                <el-form-item prop="userIds" label="选择人员" v-if="radio == '人员'">
+                    <el-select v-model="exportParam.userIds" placeholder="全部人员" multiple="true"  clearable style="width:350px;">
+                        <el-option v-for="item in hasReportUserList"  :key="item.id" :label="item.name" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
                 <el-form-item prop="projectId" label="日期范围">
                     <el-date-picker
                         v-model="exportParam.dateRange" :editable="false" 
@@ -54,8 +59,9 @@
     export default {
         data() {
             return {
+                hasReportUserList:[],
                 projectList:[],
-                exportParam:{projectId:null,datRange:[]},
+                exportParam:{projectId:null,dateRange:[]},
                 exportDialog:false,
                 dateRange:[],
                 user: JSON.parse(sessionStorage.getItem("user")),
@@ -69,6 +75,9 @@
             showExportDialog() {
                 this.exportDialog = true;
                 this.exportParam.dateRange = this.dateRange;
+                if (this.radio == '人员') {
+                    // this.exportParam.userIds = [];
+                }
             },
             //获取我的项目列表
             getMyProjectList() {
@@ -93,19 +102,35 @@
             },
             exportProjectData() {
                  var param = {};
-                if (this.exportParam.dateRange != null) {
-                    param = {startDate:this.dateRange[0], endDate: this.dateRange[1]};
-                }
+                 if (this.exportParam.dateRange != null) {
+                    param = {startDate:this.exportParam.dateRange[0], endDate: this.exportParam.dateRange[1]};
+                 }
+                 var url = "/project/exportTimeCost";
+                 var fileName = '项目工时成本统计.xls';
+                 if (this.radio == '人员' ) {
+                     console.log(this.exportParam.userIds);
+                     fileName = '人员工时成本统计.xls';
+                     url = '/department/exportUserStatistic';
+                     if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
+                         var ids = '';
+                        this.exportParam.userIds.forEach(u=>{
+                            ids += u+',';
+                        })
+                        param.userIds = ids;
+                     }
+                 } 
+                
                 if (this.exportParam.projectId != null) {
                     param.projectId = this.exportParam.projectId;
                 }
 
-                this.http.post("/project/exportTimeCost", param,
+                this.http.post(url, param,
                     res => {
                         this.listLoading = false;
                         if (res.code == "ok") {
+                            this.exportDialog = false;
                             var aTag = document.createElement('a');
-                            aTag.download = "项目工时成本统计.xls";
+                            aTag.download = fileName;
                             aTag.href = res.data;
                             aTag.click();
                         } else {
@@ -123,10 +148,166 @@
                         });
                     });
             },
+            //获取人员成本统计列表
+            getUserCostList() {
+                this.listLoading = true;
+                this.http.post(this.port.project.userCost, {
+                    startDate:this.dateRange[0], endDate: this.dateRange[1]
+                },
+                res => {
+                    this.listLoading = false;
+                    var _this = this;
+                    this.hasReportUserList = [];
+                    if (res.code == "ok") {
+                        //工时总成本
+                        this.hasReportUserList = res.data.userList;
+                        var xList = [] , yList = [] , list = res.data.list, array = [] , series = [];
+                        var totalMoneyCost = res.data.totalCostMoney;
+                        if (list.length > 0) {
+                            var num = list.length==0?0:list[0].project.length;
+                            for(var i in list) {
+                                xList.push(list[i].name);
+                                var pro = list[i].project;
+                                for(var j in pro) {
+                                    if(array.indexOf(pro[j].project) == -1) {
+                                        array.push(pro[j].project)
+                                    }
+                                }
+                            }
+
+                            for(var i in array) {
+                                yList.push(array[i]);
+                                var dataList = [];
+                                for(var j in list) {
+                                    var project = list[j].project , num = 0;
+                                    if(project.length != 0) {
+                                        for(var k in project) {
+                                            if(project[k].project == array[i]) {
+                                                dataList.push({
+                                                    "value": project[k].money,
+                                                    "cost": project[k].time,
+                                                })
+                                            } else {
+                                                num++;
+                                            }
+                                            if(k == project.length-1 && num != project.length-1) {
+                                                dataList.push({
+                                                    "value": 0,
+                                                    "cost": 0,
+                                                })
+                                            }
+                                        }
+                                    } else {
+                                        dataList.push({
+                                            "value": 0,
+                                            "cost": 0,
+                                        })
+                                    }
+                                }
+                                series.push({
+                                    name: array[i],
+                                    type: 'bar',
+                                    stack:'1',
+                                    barMaxWidth: 30,
+                                    data: dataList,
+                                })
+                            }
+                        } 
+                            
+                            
+                            var myChart = echarts.init(document.getElementById("container"));
+                            _this.myChart = myChart;
+                            var option = {
+                                //总成本
+                                title: {
+                                    text: '工时成本总计' + totalMoneyCost.toFixed(2) + '元',
+                                    left:'left',
+                                },
+                                
+                                // 工具箱
+                                legend: {
+                                    x: 80,
+                                    y: 10,
+                                    data: yList,
+                                    show: true,
+                               top:"5%",//与上方的距离 可百分比% 可像素px
+                                },
+                                grid : {
+                                    top : 80,    //距离容器上边界40像素
+                                    bottom: 35   //距离容器下边界30像素
+                                },
+                                toolbox: {
+                                    show: true,
+                                    feature:{
+                                        saveAsImage:{
+                                            show:true
+                                        },
+                                        restore:{
+                                            show:true
+                                        },
+                                        // dataView:{
+                                        //     show:true
+                                        // },
+                                        // dataZoom:{
+                                        //     show:true
+                                        // },
+                                        magicType:{
+                                            type:['line','bar']
+                                        }
+                                    }
+                                },
+                                tooltip:{
+                                    trigger:'axis',
+                                    formatter: function (params,ticket,callback) {
+                                        var totalTime = 0;
+                                        var totalCost = 0;
+                                        var res = "";
+                                        for(var i in params) {
+                                            if (params[i].data.value > 0) {
+                                                res += "<div style='margin-top:3px;font-size:12px;'><font color='#ddd'>项目名称:" + params[i].seriesName 
+                                                    + "</font><br/>工作成本 : " + params[i].data.value
+                                                    + "元 <br/>工作时长"+" : " + params[i].data.cost + "小时</br></div>";
+                                                totalTime += Number(params[i].data.cost);
+                                                totalCost += Number(params[i].data.value);
+                                            }
+                                        }
+                                        res = res +'<br/>'+ params[0].name+ '<br/>总计: ' + totalTime.toFixed(1)+'小时 '+totalCost.toFixed(2) + "元<br/>";
+                                        return res;
+                                    }
+                                },
+                                xAxis: {
+                                    data: xList,
+                                    axisLabel: {
+                                        interval:0,rotate:20
+                                    }
+                                },
+                                yAxis: [{
+                                    type : 'value',
+                                    axisLabel: {
+                                        formatter:'{value} (元)'
+                                    }
+                                }],
+                                series: series,
+                            };
+                            myChart.setOption(option,{notMerge:true});
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
             getEchart(){
                 sessionStorage.radio = this.radio;
                 var _this = this;
-                console.log(this.dateRange);
                 var param = {};
                 if (this.dateRange != null) {
                     param = {startDate:this.dateRange[0], endDate: this.dateRange[1]};
@@ -137,7 +318,8 @@
                 } else if (this.radio=='部门') {
                     url = this.port.project.depCost;
                 } else if (this.radio=='人员') {
-                    url = '/project/getAllMembCost';
+                    this.getUserCostList();
+                    return;
                 }
                 this.http.post(url, param,
                 res => {
@@ -220,14 +402,7 @@
                                 data: yList,
                             }]
                         };
-                        myChart.setOption(option);
-                        // myChart.on('click', function(params) {
-                        //     if(_this.radio=='项目') {
-                        //         _this.$router.push("/cost/" + params.data.id + "/" + params.name);
-                        //     } else {
-                        //         _this.$router.push("/costDep/" + params.data.id + "/" + params.name);
-                        //     }
-                        // });
+                        myChart.setOption(option,{notMerge: true});
                         myChart.getZr().on('click', params => {
                             const pointInPixel = [params.offsetX, params.offsetY];
                             if (myChart.containPixel('grid', pointInPixel)) {

+ 5 - 4
fhKeeper/formulahousekeeper/timesheet/src/views/project/earning.vue

@@ -13,7 +13,7 @@
                         <el-table-column prop="profitA"  >
                             <template slot="header">
                                <span>利润率A</span>
-                               <el-popover placement="top" width="250" trigger="hover" content="利润率A = (项目金额 - 总成本)/项目金额">
+                               <el-popover placement="top" width="250" trigger="hover" content="利润率A = (合同金额 - 总成本)/合同金额">
                                    <i class="el-icon-question" slot="reference" />
                                </el-popover>
                             </template>
@@ -24,7 +24,7 @@
                         <el-table-column prop="profitB" label="利润率B"  >
                             <template slot="header">
                                <span>利润率B</span>
-                               <el-popover placement="top" width="350" trigger="hover" content="利润率B = (项目金额 - 总成本 - 预留金额1)/项目金额">
+                               <el-popover placement="top" width="350" trigger="hover" content="利润率B = (合同金额 - 总成本 - 预留金额1)/合同金额">
                                    <i class="el-icon-question" slot="reference" />
                                </el-popover>
                             </template>
@@ -35,7 +35,7 @@
                         <el-table-column prop="profitC" label="利润率C"  >
                             <template slot="header">
                                <span>利润率C</span>
-                               <el-popover placement="top" width="430" trigger="hover" content="利润率C = (项目金额 - 总成本 - 预留金额1 - 预留金额2)/项目金额">
+                               <el-popover placement="top" width="430" trigger="hover" content="利润率C = (合同金额 - 总成本 - 预留金额1 - 预留金额2)/合同金额">
                                    <i class="el-icon-question" slot="reference" />
                                </el-popover>
                             </template>
@@ -43,7 +43,7 @@
                                 {{scope.row.profitC}}%
                             </template>
                         </el-table-column>
-                        <el-table-column prop="contractAmount" label="项目金额" width="110" >
+                        <el-table-column prop="contractAmount" label="合同金额" width="110" >
                             <template slot-scope="scope">
                                <span style="font-size: 10px">¥{{scope.row.contractAmount | numberToCurrency}}</span>
                             </template>
@@ -148,6 +148,7 @@
         },
         filters: {
             numberToCurrency(value) {
+                console.log('earning numberToCurrency='+value);
                 if (!value) return '0.00'
                 value = value.toFixed(2)
                 const intPart = Math.trunc(value)

+ 22 - 8
fhKeeper/formulahousekeeper/timesheet/src/views/project/info.vue

@@ -14,8 +14,8 @@
                             <el-progress :percentage="project.progress"></el-progress></span></el-col>
                     </el-row>
                     <el-row :gutter="10">
-                        <el-col :span="5" ><span class="gray_label">项目编码: </span></el-col><el-col :span="7" ><span >{{project.projectCode}}</span></el-col>
-                        <el-col :span="5" ><span class="gray_label">项目金额:</span></el-col><el-col :span="7" >
+                        <el-col :span="5" ><span class="gray_label">项目编码: </span></el-col><el-col :span="7" ><span >{{project.projectCode}}&nbsp;</span></el-col>
+                        <el-col :span="5" ><span class="gray_label">合同金额:</span></el-col><el-col :span="7" >
                         <span >{{project.contractAmount == null?'-':project.contractAmount | numberToCurrency}} 元</span></el-col>
                     </el-row>
                     <el-row :gutter="10">
@@ -33,7 +33,18 @@
                             {{project.finishDate==null?'-':project.finishDate}}</span></el-col>
                     </el-row>
                 </div>
-                
+                <div class="box" style="margin-top:10px;">
+                    <div><label>相关人员</label>
+                    <el-link v-if="user.id == project.creatorId || user.id == project.inchargerId" @click="showEditPar" style="float:right;"><i class="el-icon-edit"  ></i></el-link>
+                    </div>
+                    <div style="margin-top:10px;color:#999;">负责人</div>
+                    <div><el-link style="margin:10px" @click="showUser(project.inchargerId)">{{project.inchargerName}}</el-link></div>
+                    <div style="color:#999;">参与人</div>
+                    <div>
+                        <el-link v-for="item in project.participationList" :key="item.id" style="margin:10px;" @click="showUser(item.id)">{{item.name}}</el-link>
+                        <el-button class="el-icon-plus" @click="addMembVisible=true" size="mini"></el-button>
+                    </div>
+                </div>
                 <div class="box info" style="margin-top:10px;">
                     <div><label>成本基线<el-link v-if="user.id == project.creatorId || user.id == project.inchargerId" @click="showEditBase" style="float:right;"><i class="el-icon-edit"  ></i></el-link></label>
                     <el-row :gutter="10">
@@ -107,8 +118,9 @@
         <el-dialog title="查看详情" v-if="userDetailVisible" :visible.sync="userDetailVisible" :close-on-click-modal="false" customClass="customWidth" width="400px">
             <div class="line"><span>姓名</span><span>{{userDetail.name}}</span></div>
             <div class="line"><span>手机号码</span><span>{{userDetail.phone}}</span></div>
+            <div class="line"><span>角色</span><span>{{roleArray[userDetail.role]}}</span></div>
             <div class="line"><span>部门</span><span>{{userDetail.departmentName}}</span></div>
-            <div class="line" v-if="user.role==1||user.role==2"><span>成本</span><span>{{userDetail.cost}}元/小时</span></div>
+            <div class="line" v-if="user.role>0&&user.role<=3"><span>成本</span><span>{{userDetail.cost}}元/小时</span></div>
             <div slot="footer" class="dialog-footer">
                 <el-button type="primary" @click="userDetailVisible = false" >确定</el-button>
             </div>
@@ -128,7 +140,7 @@
                     <el-select v-model="addForm.level"  placeholder="请选择级别" style="width:32%;" >
                         <el-option v-for="item in importanceList" :key="item.id" :label="item.label" :value="item.id"></el-option>
                     </el-select>
-                    <span style="margin-left:50px;margin-right:10px;">项目金额</span>
+                    <span style="margin-left:50px;margin-right:10px;">合同金额</span>
                     <el-input v-model="addForm.contractAmount"    style="width:32%;"
                     placeholder="整数" clearable @keyup.native="number"></el-input><span style="margin-left:10px;">元</span>
                 </el-form-item>
@@ -249,6 +261,7 @@
     export default {
         data() {
             return {
+                roleArray:["普通员工","超级管理员", "系统管理员", "公司高层","人事管理员", "项目管理员"],
                 addBaseFormVisible:false,
                 addMembVisible:false,
                 addMembForm:{},
@@ -260,9 +273,9 @@
                 addFormVisible:false,
                 userDetail:{},
                 userDetailVisible: false,
-                importanceList:[{id:1,label:'一般'},{id:2,label:'紧急'},{id:3,label:'重要'},{id:4,label:'重要且紧急'}],
+                importanceList:[{id:1,label:'正常'},{id:2,label:'紧急'},{id:3,label:'重要'},{id:4,label:'重要且紧急'}],
                 //1-一般,2-紧急,3-重要,4-重要且紧急
-                levelTxt:["全部","一般","紧急","重要","重要且紧急"],
+                levelTxt:["全部","正常","紧急","重要","重要且紧急"],
                 //1-进行中,2-已完成,3-已撤销
                 statusTxt: ["全部","进行中","已完成","已撤销"],
                 mileStoneList:[],
@@ -283,7 +296,8 @@
         },
         filters: {
             numberToCurrency(value) {
-                if (!value) return '0.00'
+                console.log('info numberToCurrency='+value);
+                if (!value || value=='-') return '0.00'
                 value = value.toFixed(2)
                 const intPart = Math.trunc(value)
                 const intPartFormat = intPart.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')

+ 51 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue

@@ -27,6 +27,14 @@
                             <el-option label="已撤销" value=3 ></el-option>
                         </el-select>
                 </el-form-item>
+                <el-form-item style="float:right;" v-if="user.role == 1||user.role == 2||user.role == 5">
+                    <el-link type="primary" style="margin-left:5px;" :underline="false" href="./upload/项目导入模板.xlsx" download="项目导入模板.xlsx">模板下载</el-link>
+                </el-form-item>
+                <el-form-item style="float:right;" v-if="user.role == 1||user.role == 2||user.role == 5">
+                    <el-upload ref="upload" style="margin-left:5px;" action="#" :limit="1" :http-request="importProject" :show-file-list="false">
+                        <el-link type="primary" :underline="false" >导入项目</el-link>
+                    </el-upload>
+                </el-form-item> 
                 <el-form-item style="float:right;" v-if="user.role == 1||user.role == 2||user.role == 5">
                     <el-link type="primary" :underline="false" @click="handleAdd(-1,null)">新增项目</el-link>
                 </el-form-item>
@@ -200,6 +208,7 @@
         <el-dialog title="查看详情" v-if="userDetailVisible" :visible.sync="userDetailVisible" :close-on-click-modal="false" customClass="customWidth" width="400px">
             <div class="line"><span>姓名</span><span>{{userDetail.name}}</span></div>
             <div class="line"><span>手机号码</span><span>{{userDetail.phone}}</span></div>
+            <div class="line"><span>角色</span><span>{{roleArray[userDetail.role]}}</span></div>
             <div class="line"><span>部门</span><span>{{userDetail.departmentName}}</span></div>
             <div class="line" v-if="user.role>0&&user.role<=3"><span>成本</span><span>{{userDetail.cost}}元/小时</span></div>
             <div slot="footer" class="dialog-footer">
@@ -263,6 +272,7 @@
     export default {
         data() {
             return {
+                roleArray:["普通员工","超级管理员", "系统管理员", "公司高层","人事管理员", "项目管理员"],
                 status:null,
                 statusTxt:["-","进行中","已完成","已撤销"],
                 importanceList:[{id:1,label:'正常'},{id:2,label:'紧急'},{id:3,label:'重要'},{id:4,label:'重要且紧急'}],
@@ -320,6 +330,47 @@
             }
         },
         methods: {
+            importProject(item) {
+                //首先判断文件类型
+                let str = item.file.name.split(".");
+                let format = str[str.length - 1];
+                if (format != "xls" && format != "xlsx") {
+                    this.$message({
+                        message: "请选择.xls或.xlsx文件",
+                        type: "error"
+                    });
+                } else {
+                    this.listLoading = true;
+                    let formData = new FormData();
+                    formData.append("file", item.file);
+                    formData.append("userId", this.user.id);
+                    this.http.uploadFile('/project/importData', formData,
+                    res => {
+                        this.$refs.upload.clearFiles();
+                        this.listLoading = false;
+                        if (res.code == "ok") {
+                            this.$message({
+                                message: "导入成功",
+                                type: "success"
+                            });
+                            this.getList();
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
+                    },
+                    error => {
+                        this.$refs.upload.clearFiles();
+                        this.listLoading = false;
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+                }
+            },
             number(){  
         //      this.addForm.budget = this.addForm.budget.replace(/[^\.\d]/g,'');
         //         this.addForm.budget = this.addForm.budget.replace('.','');

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/project/projectInside.vue

@@ -207,7 +207,7 @@
                             <!-- <el-table-column prop="endDate" label="截止时间" width="100" ></el-table-column> -->
                             <el-table-column prop="endDate" label="截止时间" width="100" >
                                 <template slot-scope="scope">
-                                    <p v-if="scope.row.endDate >= times">{{scope.row.endDate}}</p>
+                                    <p v-if="scope.row.endDate >= times || scope.row.taskStatus != 0">{{scope.row.endDate}}</p>
                                     <p style="border-radius: 3px; text-align: center;background: #e62412; color: #fff;" v-else><span>{{scope.row.endDate}}</span></p>
                                 </template>
                             </el-table-column>

+ 72 - 7
fhKeeper/formulahousekeeper/timesheet/src/views/team/index.vue

@@ -2,7 +2,7 @@
     <section>
         <el-col :span="4" class="left" :style="'height:'+ (tableHeight + 113) + 'px'">
             <div class="department">
-                <span>部门</span>
+                <span><i class="iconfont firerock-iconzuzhijiegou" style="font-size:10px;" ></i>&nbsp;部门</span>
                 <div v-on:click="createDepartment(-1)">
                     <i class="fa fa-plus-circle"></i>
                     创建
@@ -33,6 +33,9 @@
                     <el-form-item>
                         <div style="color:#999;font-size:13px;">共{{total}}人</div>
                     </el-form-item>
+                    <el-form-item style="float:right;">
+                        <el-link type="primary" :underline="false" @click="showExportDialog">导出人员</el-link>
+                    </el-form-item>
                     <el-form-item style="float:right;">
                         <el-link type="primary" :underline="false" @click="openInsertDialog(null)">添加人员</el-link>
                     </el-form-item>
@@ -142,7 +145,10 @@
                     <el-link :underline="false" style="color:blue;font-size:12px;margin-left:7px;" href="#/timetype">修改工作时长</el-link>
                 </el-form-item>
                 <el-form-item label="时薪" prop="cost">
-                    <el-input v-model.number="insertForm.cost" :disabled="insertForm.salaryType == 0" placeholder="请输入成本 单位:元/小时" clearable></el-input>
+                    <el-input v-model.number="insertForm.cost" :disabled="insertForm.salaryType == 0" style="width:120px;"
+                     placeholder="请输入成本 单位:元/小时" clearable></el-input>
+                    <span style="margin-left:25px;">生效日期</span>
+                    <el-date-picker v-model="insertForm.costApplyDate" value-format="yyyy-MM-dd"></el-date-picker>
                 </el-form-item>
                 <el-form-item label="部门" prop="departmentId">
                     <el-cascader v-model="insertForm.departmentId" placeholder="请选择部门" style="width: 100%"
@@ -161,7 +167,7 @@
                         <el-option label="公司高层" :value="3"></el-option>
                         <el-option label="人事管理员" :value="4"></el-option>
                         <el-option label="项目管理员" :value="5"></el-option> -->
-                        <el-option v-for="item in roleDescArray" :label="item.label" :value="item.value" :key="item.name">
+                        <el-option v-for="item in roleDescArray" :label="item.label" :disabled="item.value==2&&user.role != 1" :value="item.value" :key="item.name">
                             <span style="float: left">{{item.label}}</span>
                             <span style="float: right; color: #8492a6; font-size: 13px">{{item.desc}}</span>
                         </el-option>
@@ -188,7 +194,10 @@
                     <el-link :underline="false" style="color:blue;font-size:12px;margin-left:7px;" href="#/timetype">修改工作时长</el-link>
                 </el-form-item>
                 <el-form-item label="时薪" prop="cost">
-                    <el-input v-model.number="insertForm.cost" :disabled="insertForm.salaryType == 0" placeholder="请输入成本 单位:元/小时" clearable></el-input>
+                    <el-input v-model.number="insertForm.cost" :disabled="insertForm.salaryType == 0" style="width:120px;"
+                     placeholder="请输入成本 单位:元/小时" clearable></el-input>
+                    <span style="margin-left:25px;">生效日期</span>
+                    <el-date-picker v-model="insertForm.costApplyDate"  value-format="yyyy-MM-dd"></el-date-picker>
                 </el-form-item>
                 <el-form-item label="部门" prop="departmentId">
                     <el-cascader v-model="insertForm.departmentId" 
@@ -228,13 +237,30 @@
                 
             </el-table>
         </el-dialog>
+        <!--导出人员 -->
+        <el-dialog title="导出人员列表" :visible.sync="exportDialogVisible" width="550px" >
+            <el-form  label-width="100px">
+                <el-form-item label="导出" >
+                    <el-radio-group v-model="containInvalid" >
+                    <el-radio  :label="1" >全部人员</el-radio>
+                    <el-radio  :label="0" >仅活跃人员</el-radio>
+                    </el-radio-group>
+                </el-form-item>
+            </el-form>
+            <span slot="footer" class="dialog-footer">
+                <el-button type="primary" @click="exportUsers">导出</el-button>
+            </span>
+        </el-dialog>
     </section>
 </template>
 
 <script>
+    import util from "../../common/js/util";
     export default {
         data() {
             return {
+                containInvalid:1,
+                exportDialogVisible: false,
                 roleArray:["普通员工","超级管理员", "系统管理员", "公司高层","人事管理员", "项目管理员"],
                 roleDescArray:[{label:"普通员工",value:0, desc:"填报日报,参与项目协作"},
                 {label:"系统管理员",value:2, desc:"具有除了创建系统管理员之外的全部功能"},
@@ -284,10 +310,11 @@
                     cost: null,
                     departmentId: null,
                     salaryType:0,
+                    costApplyDate: '2021-04-09'
                 },
                 rules: {
                     name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
-                    phone: [{ required: true, message: "请输入电话", trigger: "blur" }],
+                    // phone: [{ required: true, message: "请输入电话", trigger: "blur" }],
                     role: [{ required: true, message: "请选择角色", trigger: "blur" }],
                     cost: [{ required: true, message: "请输入成本", trigger: "blur" }]
                 },
@@ -309,6 +336,35 @@
             };
         },
         methods: {
+            showExportDialog() {
+                this.exportDialogVisible = true;
+            },
+            exportUsers() {
+                
+                this.http.post('/user/exportUsers', {
+                    containInvalid: this.containInvalid
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.exportDialogVisible = false;
+                        var aTag = document.createElement('a');
+                        aTag.download = "全部员工列表.xls";
+                        aTag.href = res.data;
+                        aTag.click();
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
             showSalaryList(item) {
                 this.userSalaryListDialog = true;
                 this.userSalaryList = [];
@@ -532,7 +588,9 @@
                         monthCost:list.monthCost,
                         cost: list.cost,
                         departmentId: array.reverse(),
-                        salaryType: list.salaryType
+                        salaryType: list.salaryType,
+                        costApplyDate: list.costApplyDate,
+                        
                     };
                     this.title = "编辑人员"
                 } else {
@@ -545,6 +603,7 @@
                         cost: null,
                         departmentId: null,
                         salaryType:0,
+                        costApplyDate: util.formatDate.format(new Date(), 'yyyy-MM-dd'),
                     };
                     this.title = "新增人员"
                 }
@@ -561,11 +620,14 @@
                             role: this.insertForm.role,
                             monthCost: this.insertForm.monthCost,
                             cost: this.insertForm.cost,
-                            salaryType: this.insertForm.salaryType
+                            salaryType: this.insertForm.salaryType,
                         };
                         if (this.insertForm.id != null) {
                             form.id = this.insertForm.id;
                         }
+                        if (this.insertForm.costApplyDate != null) {
+                            form.costApplyDate = this.insertForm.costApplyDate;
+                        }
                         if (this.insertForm.departmentId != null) {
                             form.departmentId = this.insertForm.departmentId[this.insertForm.departmentId.length-1];
                         }
@@ -706,6 +768,9 @@
                         if (this.insertForm.departmentId != null) {
                             form.departmentId = this.insertForm.departmentId[this.insertForm.departmentId.length-1];
                         }
+                        if (this.insertForm.costApplyDate != null) {
+                            form.costApplyDate = this.insertForm.costApplyDate;
+                        }
                         this.http.post( this.port.manage.insert, form,
                         res => {
                             this.listLoading = false;

+ 118 - 57
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -17,21 +17,16 @@
                     <div class="jjk" style="display:inline-block;position:fixed;top:70px;background:#fff;left:250px;">
                         <el-date-picker size="small" v-model="date" :editable="false" format="yyyy-MM" value-format="yyyy-MM" style="width:190px;"
                          @change="changeMonthOut" :clearable="false" type="month" placeholder="选择月份"></el-date-picker>
-                        <!-- <span>日期:</span> -->
                     </div>
                         <span v-for="(item,index) in allDate" :id="'day'+index" :class="index==choseDay?'chooseDate date_item':'date_item'" 
-                        @click="choseDate(index, item)" :key="index">{{item}}</span>
-
-            <!-- <el-card class="box-card daily" shadow="never" >
-                <div slot="header" class="clearfix" @mousewheel="wheel" id="dateScroll">
-                    <el-date-picker size="small" v-model="date" :editable="false" format="yyyy-MM" style="width:187px;"
-                    value-format="yyyy-MM" @change="changeMonthOut" :clearable="false" type="month" placeholder="选择月份"></el-date-picker>
-                    <span >
-                    <span style="color:#999;">日期:</span>
-                    <span v-for="(item,index) in allDate" :id="'day'+index" :class="index==choseDay?'chooseDate date_item':'date_item'" 
-                        @click="choseDate(index, item)" :key="index">{{item}}</span>
-                    </span> -->
-
+                        @click="choseDate(index, item)" :key="index" >
+                        <div :style="'display:inline-block;'+(item.state == null?'padding:0px 6px;':'')" >
+                            <div><span>{{item.showDate}}</span>
+                            <span style="font-size:10px;text-align:center;color:#999;">{{item.weekDay}}</span>
+                            </div>
+                        </div>
+                        <i v-if="item.state != null" class="iconfont firerock-icondot" :class="statusStyle[item.state]"></i>
+                        </span>
                 </div>
                 <div style="display:flex;">
                 <div v-if="user.role > 0 || user.manageDeptId != 0" >
@@ -78,7 +73,8 @@
                         <span>工作日报 | {{depData.label}}</span> - 已填写<span style="margin-left:5px;margin-right:5px;color:green;">{{reportList.length}}</span>人,
                     未填写<span style="margin-left:5px;margin-right:5px;color:red;">{{(depData == null?data[0].membCount:(depData.isUser == 1?1:depData.membCount))-reportList.length}}</span>人
                         <span style="float:right;">
-                            <el-link type="primary" style="margin-right:10px;" :underline="false" @click="fillInReport(-1)">填写日报</el-link>
+                            <el-link type="primary" style="margin-right:10px;" :underline="false" @click="fillInReport(-1,0)">填写日报</el-link>
+                            <el-link type="primary" style="margin-right:10px;" :underline="false" @click="fillInReport(-1,1)">批量填报</el-link>
                             <el-link type="primary" style="margin-right:10px;" :underline="false" @click="showExportDialog">导出日报</el-link>
                             <el-link type="primary" style="margin-right:10px;" :underline="false" @click="batchApprove" >批量审核</el-link>
                         </span>
@@ -86,7 +82,8 @@
                     <!--普通员工,含项目经理 -->
                     <div class="report_title" v-if="(user.role==0||user.role==5) && user.manageDeptId == 0"><span>日报列表</span>
                     <span style="float:right;" v-if="(user.role==0||user.role==5) && user.manageDeptId == 0">
-                            <el-link type="primary" style="margin-right:10px;" :underline="false" @click="fillInReport(-1)">填写日报</el-link>
+                            <el-link type="primary" style="margin-right:10px;" :underline="false" @click="fillInReport(-1,0)">填写日报</el-link>
+                            <el-link type="primary" style="margin-right:10px;" :underline="false" @click="fillInReport(-1,1)">批量填报</el-link>
                             <el-link type="primary" v-if="user.leader" style="margin-right:10px;" :underline="false" @click="batchApprove">批量审核</el-link>
                     </span>
                     </div>
@@ -109,7 +106,7 @@
                                 <!--自己可以撤回待审核状态的报告 -->
                                 <el-button v-if="(user.id == item1.id) && item1.state == 0" type="normal" :loading="logining" size="small" @click="cancel(item1)">撤回</el-button>
                                 <el-button v-if="(user.role == 1 || user.role == 2 || user.id == item1.data[0].inchargerId) && item1.state == 1" type="normal" :loading="logining" size="small" @click="deny(item1.id,1, item1)">撤销</el-button>
-                                <el-button v-if="item1.state >= 2 && user.id == item1.id" type="primary" size="small" @click="fillInReport(index1)">编辑日报</el-button>
+                                <el-button v-if="item1.state >= 2 && user.id == item1.id" type="primary" size="small" @click="fillInReport(index1,0)">编辑日报</el-button>
                             </div>
                             <div class="one_daily_body">
                                 <el-timeline>
@@ -146,22 +143,22 @@
         </div>
 
         <!-- 填写日报的dialog -->
-        <el-dialog title="填写日报" :visible.sync="dialogVisible" width="60%" :close-on-click-modal="false">
+        <el-dialog :title="isBatch==0?'填写日报':'批量填报'" :visible.sync="dialogVisible" width="60%" :close-on-click-modal="false">
             <el-form ref="workForm" :model="workForm" :rules="workRules" label-width="100px">
                 <el-form-item label="工作日期" prop="createDate">
                     <el-date-picker v-model="workForm.createDate" :editable="false" format="yyyy-MM-dd" value-format="yyyy-MM-dd" 
-                    @change="changeMonth()" :clearable="false" type="date" placeholder="选择工作日期" :disabled="isDisable"></el-date-picker>
+                    :style="'width:'+(isBatch==0?'200':'280')+'px;'" :type="isBatch==0?'date':'daterange'"
+                    @change="changeMonth()" :clearable="false" placeholder="选择工作日期" :disabled="isDisable"></el-date-picker>
                     <span v-if="reportTimeType.type == 3" style="margin-left:30px;">总时长:</span>
                     <el-input-number :disabled="!canEdit" v-if="reportTimeType.type == 3" style="margin-left:10px;" @change="changeAllTime"
                         v-model="reportTimeType.allday" :precision="1" :step="0.5" :max="12" :min="0.5"></el-input-number>
                     <span v-if="reportTimeType.type == 3">小时</span>
-                    <!-- <span v-if="reportTimeType.type == 3" style="margin-left:30px;" >总时长: {{reportTimeType.allday.toFixed(1)}}小时</span> -->
                 </el-form-item>
                 
                 <div v-for="(domain, index) in workForm.domains" :key="domain.id">
                     <el-form-item v-if="reportTimeType.type != 3" label="工作时长" :prop="'domains.' + index + '.'+timeFields[reportTimeType.type]"
                         :rules="{ required: true, message: '请选择工作时长', trigger: 'blur' }">
-                        <el-select v-model="domain.timeType" 
+                        <el-select v-model="domain.timeType" style="width:200px;"
                             v-if="reportTimeType.type == 0"
                             placeholder="请选择工作时长" 
                             :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
@@ -174,7 +171,7 @@
                             </el-option>
                         </el-select>
                         <!-- 数字时长选择 -->
-                        <el-select v-model="domain.workingTime" 
+                        <el-select v-model="domain.workingTime" style="width:200px;"
                         v-if="reportTimeType.type == 1"
                         :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
                         placeholder="请选择工作时长" >
@@ -305,6 +302,10 @@
     export default {
         data() {
             return {
+                isBatch:0,//是否是批量填报
+                weekDay : ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
+                statusStyle:["waiting", "filledReportStyle", "RejectStyle", ""],
+                fillStatusList: [],
                 exportParam:{projectId: null, dateRange:[]},
                 exportDialog:false,
                 timeFields:['timeType', 'workingTime', 'startTime', 'progress'],
@@ -380,11 +381,44 @@
                 isNew: false,
                 selected: false,
                 valuet: new Date(),
-                domObj: null
+                domObj: null,
             };
         },
         methods: {
-
+            //获取自己填写的日报状态
+            getReportFillStatus() {
+                this.http.post('/report/getReportFillStatus',{ 
+                        startDate: this.date+"-01", endDate: this.date+"-31", userId: this.user.id
+                    },
+                    res => {
+                        if (res.code == "ok") {
+                            this.fillStatusList = res.data;
+                            this.allDate.forEach(d=>{
+                                var fillInfo = null;
+                                d.state = null;
+                                this.fillStatusList.forEach(s=>{
+                                    var d1 = s.createDate.split('-')[2];
+                                    var d2 = d.date.split('月')[1].split('日')[0];
+                                    if (d1.indexOf('0') == 0) {
+                                        d1 = d1.substring(1,d1.length);
+                                    }
+                                    
+                                    if (d1 == d2) {
+                                        d.state = s.state;
+                                    }
+                                })
+                            })
+                            this.$forceUpdate();
+                        } 
+                    },
+                    error => {
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                        }
+                    );
+            },
             scrollFunction () {
                 this.domObj = document.getElementById('clearfix') // 通过id获取要设置的div
                 if (this.domObj.attachEvent) { // IE
@@ -441,8 +475,6 @@
                 res => {
                     if (res.code == "ok") {
                         this.workForm.domains[index].subProjectList = res.data;
-                        // domain.subProjectList = res.data;
-                        // console.log(domain.subProjectList);
                         this.$forceUpdate();
                     } 
                 },
@@ -518,7 +550,6 @@
            },
             //提交批量审核数据
             submitBatchApprove() {
-                console.log(this.$refs.approveTree.getCheckedNodes());
                 var data = this.$refs.approveTree.getCheckedNodes();
                 var ids = '';
                 if (data.length == 0) {
@@ -535,7 +566,7 @@
                     }
                 }
                 let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
-                console.log('ids==='+ids);
+                
                 this.http.post("/report/batchApproveReport", {ids:ids, date:this.date + day},
                 res => {
                     if (res.code == "ok") {
@@ -574,7 +605,7 @@
             //批量审核
             batchApprove() {
                 this.approveDialogVisible = true;
-                console.log(this.allData);
+                
                 this.reportNames = [];
                 for (var i=0;i<this.reportList.length; i++) {
                     var report = this.reportList[i];
@@ -649,11 +680,9 @@
                             }
                         }
                         if (!match) {
-                            console.log("不匹配,删除="+obj.label+', state='+obj.state);
                             list.splice(i, 1);
                             i--;
                         } else {
-                            console.log("匹配"+obj.label);
                         }
                     } else {
                         if (obj.children != null) {
@@ -664,7 +693,6 @@
             },
             // 部门列表点击
             handleNodeClick(data) {
-                console.log(data);
                 // if(this.depData == null || data.id != this.depData.id) {
                 //     this.depData = data;
                 //     //this.getUser();
@@ -700,10 +728,6 @@
                                 id: -1,
                                 label: '全部人员',
                             })
-                            list.push({
-                                id: 0,
-                                label: '未分配',
-                            })
                         }
                        
                         this.membCount = 0;
@@ -729,6 +753,8 @@
                         type: "error"
                     });
                 });
+
+                this.getReportFillStatus();
             },
 
             setUserToDept(list) {
@@ -777,7 +803,6 @@
             //时间段范围设置改动,监听
             onTimeTypeChange(timeType) {
                 this.showAddMore = true;
-                console.log("======" + timeType);
                 for(var i in this.workForm.domains) {
                     if (this.workForm.domains[i].timeType == 0) {
                         this.showAddMore = false;
@@ -829,11 +854,10 @@
             },
             // 改变月份
             changeMonthOut() {
-                console.log(sessionStorage.msg)
-
                 this.getAllDate();
                 this.getReportList();
                 this.getDepartment();
+                
             },
 
             // 选择日期
@@ -843,7 +867,7 @@
                 sessionStorage.msg = this.date + day,
                 this.getReportList();
                 this.getDepartment();
-                this.curDate = item;
+                this.curDate = item.date;
             },
 
             // 获取日期列表
@@ -852,9 +876,10 @@
                 var day = this.getCountDays();
                 let curMonthDay = null;
                 for (var k = 1; k <= day; k++) {
-                    var str = new Date(this.date.replace(/-/g, "/")).getMonth() + 1 + "月" + k + "日";
-                    if ( new Date(this.date.replace(/-/g, "/")).getFullYear() == new Date(new Date()).getFullYear() &&
-                    new Date(this.date.replace(/-/g, "/")).getMonth() == new Date(new Date()).getMonth()) {
+                    var str = new Date(this.date.replace(/-/g, "/")+'/01').getMonth() + 1 + "月" + k+'日';
+                    var showStr = new Date(this.date.replace(/-/g, "/")+'/01').getMonth() + 1+'.'+k;
+                    if ( new Date(this.date.replace(/-/g, "/")+'/01').getFullYear() == new Date(new Date()).getFullYear() &&
+                    new Date(this.date.replace(/-/g, "/")+'/01').getMonth() == new Date(new Date()).getMonth()) {
                         if(sessionStorage.msg) {
                             if(parseInt(sessionStorage.msg.split("-")[2]) == k) {
                                 this.choseDay = k - 1;
@@ -865,11 +890,12 @@
                                 this.choseDay = k - 1;
                             }   
                         }
-                         
                     } else {
                         this.choseDay = 0;
                     }
-                    dayArry.push(str);
+                    var curDateStr = (this.date +'-'+ (k<10?('0'+k):k));
+                    var curDateTime = util.formatDate.parse(curDateStr, 'yyyy-MM-dd');
+                    dayArry.push({date:str, weekDay:this.weekDay[curDateTime.getDay()], showDate:showStr});
                 }
                 this.allDate = dayArry;
                 //不能超过最大日期
@@ -878,22 +904,22 @@
                 }
                 //从消息点击跳转过来的,直接加载指定日期
                 if (sessionStorage.from == 1 && sessionStorage.msg) {
-                    console.log('sssss');
                     this.curDate = sessionStorage.msg;
                     sessionStorage.from = 0;
                 } else {
                     if (curMonthDay != null) {
                         this.curDate = curMonthDay;
                     } else {
-                        var d = new Date(this.date.replace(/-/g, "/"))
+                        var d = new Date(this.date.replace(/-/g, "/")+'/01')
                         this.curDate = (d.getMonth()+1)+'月'+d.getDate()+'日';  
                     }
                 }
+                this.getReportFillStatus();
             },
 
             getCountDays() {
                 var newstr = this.date.replace(/-/g, "/");
-                var curDate = new Date(newstr);
+                var curDate = new Date(newstr+'/01');
                 var curMonth = curDate.getMonth();
                 curDate.setMonth(curMonth + 1);
                 curDate.setDate(0);
@@ -915,7 +941,6 @@
                 res => {
                     this.listLoading = false;
                     if (res.code == "ok") {
-                        console.log(res);
                         this.reportList = res.data;
                         document.querySelector("#day"+this.choseDay).scrollIntoView(true);
                     } else {
@@ -991,7 +1016,7 @@
             },
 
             // 获取个人某天的日报
-            getReport(i) {
+            getReport() {
                 this.http.post( this.port.report.getPort, {
                     date: this.workForm.createDate
                 },
@@ -1037,7 +1062,7 @@
                                 domains: [{
                                     id: null,
                                     projectId: "",
-                                    workingTime: this.reportTimeType.type==3?(10*this.reportTimeType.allday/100).toFixed(1):"",
+                                    workingTime: this.reportTimeType.type==3?(this.reportTimeType.allday).toFixed(1):"",
                                     content: "",
                                     progress:100,
                                     state: 2,
@@ -1062,16 +1087,35 @@
             },
 
             // 打开日报填写
-            fillInReport(i) {
+            fillInReport(i, isBatch) {
                 if(i == -1) {
                     this.isDisable = false;
                 } else {
                     this.isDisable = true;
                 }
                 let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
-                this.workForm.createDate = this.date + day; // 获取个人某天的日报
-                this.getReport(i);
+                this.isBatch = isBatch;
+                if (this.isBatch == 0) {
+                    this.workForm.createDate = this.date + day; // 获取个人某天的日报
+                    this.getReport(i);
+                } else {
+                    this.workForm = {
+                                createDate: null,//批量填报没有日期
+                                domains: [{
+                                    id: null,
+                                    projectId: "",
+                                    workingTime: this.reportTimeType.type==3?(this.reportTimeType.allday).toFixed(1):"",
+                                    content: "",
+                                    progress:100,
+                                    state: 2,
+                                    timeType:0,
+                                }],
+                            }
+                    this.canEdit = true;
+                }
+                
                 this.dialogVisible = true;
+                
             },
 
             // 添加模块
@@ -1122,7 +1166,10 @@
 
             // 改变月份
             changeMonth() {
-                this.getReport()
+                if (this.isBatch == 0) {
+                    //只有按天填报才能获取当天的日报
+                    this.getReport()
+                }
             },
 
             // 保存日报
@@ -1232,8 +1279,13 @@
                             } else {
                                 formData.append("content", this.workForm.domains[i].content);
                             }
+                            if (this.isBatch == 0) {
+                                formData.append("createDate", this.workForm.createDate);
+                            } else {
+                                //批量填报,时间范围
+                                formData.append("createDate", this.workForm.createDate[0]+'@'+this.workForm.createDate[1]);
+                            }
                             
-                            formData.append("createDate", this.workForm.createDate);
                             if(this.workForm.domains[i].isOvertime == undefined ) {
                                 this.workForm.domains[i].isOvertime = '0'
                                 formData.append("isOvertime", this.workForm.domains[i].isOvertime);
@@ -1391,7 +1443,6 @@
         },
         created() {
             let height = window.innerHeight;
-            console.log('window inner height=='+height)
             this.tableHeight = height - 178;
             const that = this;
             window.onresize = function temp() {
@@ -1415,6 +1466,16 @@
 </script>
 
 <style lang="scss" scoped>
+.waiting {
+    color:orange;
+}
+.filledReportStyle {
+    color:#32CD32;
+
+}
+.RejectStyle {
+    color:red;
+}
     .allDaily {
         width:82%;
     }
@@ -1428,7 +1489,7 @@
         padding: 15px 0;
         // overflow-y: hidden;
         .date_item {
-            padding: 0 15px;
+            padding: 0 3px;
             cursor: pointer;
         }
         .chooseDate {

+ 6 - 4
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/list.vue

@@ -34,9 +34,11 @@
                     <el-timeline>
                         <el-timeline-item v-for="(item,index) in props.row.data" :key="index">
                             <el-card shadow="never">
-                                <p>项目:<b>{{item.project}}</b></p>
-                                <p>时长:{{item.time}}h <span class="propsbtn" v-if="item.isOvertime === 1"><el-tag type="danger" size="mini" style="margin-left: 65px">加班</el-tag></span></p>
-                                <p>成本:{{item.cost}}元</p>
+                                <p>项目:<b>{{item.project}}<span v-if="item.subProjectName != null"> / {{item.subProjectName}}</span></b></p>
+                                <p v-if="item.taskId != null">任务:{{item.taskName}}</p>
+                                <p>时长:{{item.time}}h <span class="propsbtn" v-if="item.isOvertime === 1">
+                                    <el-tag type="danger" size="mini" style="margin-left: 65px">加班</el-tag></span></p>
+                                <p v-if="user.role>=1&&user.role<=3">成本:{{item.cost}}元</p>
                                 <p>事项:<span v-html="item.content"></span></p>
                             </el-card>
                         </el-timeline-item>
@@ -45,7 +47,7 @@
             </el-table-column>
             
             <el-table-column prop="name" label="姓名" sortable></el-table-column>
-            <el-table-column prop="date" label="日期" sortable>
+            <el-table-column prop="dateStr" label="日期" sortable>
             </el-table-column>
             <el-table-column prop="reportTime" label="工作时长(h)" >
             </el-table-column>

+ 15 - 3
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/timer.vue

@@ -165,12 +165,18 @@
                     this.listLoading = true;
                     this.http.post('/project-timer/endTimer',{id: id},
                     res => {
+                        this.listLoading = false;
                         if (res.code == "ok") {
                             this.getList();
-                        } 
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
                     },
                     error => {
-                        this.listLoading = false;
+                        
                         this.$message({
                             message: error,
                             type: "error"
@@ -190,9 +196,15 @@
                     this.listLoading = true;
                     this.http.post('/project-timer/deleteTimer',{id: id},
                     res => {
+                        this.listLoading = false;
                         if (res.code == "ok") {
                             this.getList();
-                        } 
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
                     },
                     error => {
                         this.listLoading = false;

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 218 - 205
fhKeeper/formulahousekeeper/timesheet_h5/package-lock.json


+ 1 - 0
fhKeeper/formulahousekeeper/timesheet_h5/package.json

@@ -15,6 +15,7 @@
     "babel-plugin-import": "^1.13.3",
     "core-js": "^2.6.12",
     "css-loader": "^3.6.0",
+    "dingtalk-jsapi": "^2.13.42",
     "echarts": "^4.9.0",
     "style-loader": "^1.3.0",
     "vue": "^2.6.12",

BIN
fhKeeper/formulahousekeeper/timesheet_h5/public/favicon.ico


+ 2 - 2
fhKeeper/formulahousekeeper/timesheet_h5/public/index.html

@@ -7,11 +7,11 @@
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
     <title>工时管家</title>
-    <link rel="stylesheet" href="http://at.alicdn.com/t/font_1456778_1mgn5degp7t.css">
+    <link rel="stylesheet" href="https://at.alicdn.com/t/font_1456778_1mgn5degp7t.css">
     <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
 
     <meta name="wpk-bid" content="dta_2_71020"> <script>    !(function(c,i,e,b){var h=i.createElement("script");var f=i.getElementsByTagName("script")[0];h.type="text/javascript";h.crossorigin=true;h.onload=function(){c[b]||(c[b]=new c.wpkReporter({bid:"dta_2_71020"}));c[b].installAll()};f.parentNode.insertBefore(h,f);h.src=e})(window,document,"https://g.alicdn.com/woodpeckerx/jssdk??wpkReporter.js","__wpk");</script>
-    
+    <meta name="wpk-bid" content="dta_2_71020"> <script>    !(function(c,i,e,b){var h=i.createElement("script");var f=i.getElementsByTagName("script")[0];h.type="text/javascript";h.crossorigin=true;h.onload=function(){c[b]||(c[b]=new c.wpkReporter({bid:"dta_2_71020"}));c[b].installAll()};f.parentNode.insertBefore(h,f);h.src=e})(window,document,"https://g.alicdn.com/woodpeckerx/jssdk??wpkReporter.js","__wpk");</script>
 </head>
 
 <body>

+ 2 - 2
fhKeeper/formulahousekeeper/timesheet_h5/src/main.js

@@ -13,12 +13,12 @@ import "@/components/Vant";
 
 import { Form , Toast , Grid, GridItem , DatetimePicker ,
 Picker , Dialog , NumberKeyboard , Sticky , Skeleton ,
-Panel , Divider , List , pullRefresh , SwipeCell, Checkbox, Search, Slider,Stepper,Tag } from 'vant';
+Panel , Divider , List , pullRefresh , SwipeCell, Checkbox, Search, Slider,Stepper,Tag, Calendar } from 'vant';
 
 Vue.use(Form).use(Toast).use(Grid).use(GridItem).use(DatetimePicker)
 .use(Picker).use(Dialog).use(NumberKeyboard).use(Sticky).use(Skeleton)
 .use(Panel).use(Divider).use(List).use(pullRefresh).use(SwipeCell)
-.use(Checkbox).use(Search).use(Slider).use(Stepper).use(Tag);
+.use(Checkbox).use(Search).use(Slider).use(Stepper).use(Tag).use(Calendar);
 
 // rem
 import "amfe-flexible";

+ 7 - 0
fhKeeper/formulahousekeeper/timesheet_h5/src/router/index.js

@@ -39,6 +39,13 @@ const router = new Router({
         },
         component: () => import("@/views/view/index")
     },
+    {
+        path: "/calendar",
+        meta: {
+            title: "查看日报"
+        },
+        component: () => import("@/views/view/calendar")
+    },
     {
         path: "/edit",
         meta: {

+ 2 - 2
fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/index.vue

@@ -338,7 +338,7 @@
                         // }
                     } else {
                         toast.clear();
-                        this.$toast.fail('获取失败');
+                        this.$toast.fail('获取失败:'+res.msg);
                     }
                 }).catch(err=> {toast.clear();});
             },
@@ -428,7 +428,7 @@
                         }
                     } else {
                         toast.clear();
-                        this.$toast.fail('获取失败');
+                        this.$toast.fail('获取失败:'+res.msg);
                     }
                 }).catch(err=> {toast.clear();});
             },

+ 5 - 5
fhKeeper/formulahousekeeper/timesheet_h5/src/views/index/index.vue

@@ -12,8 +12,8 @@
             </van-grid-item>
         </van-grid>
         <div class="tip">
-            新注册用户请登录PC版,完善组织结构信息<br>
-            http://worktime.ttkuaiban.com
+            体验报表统计等更多功能,尽在PC端<br>
+            网页用户访问http://worktime.ttkuaiban.com,钉钉用户直接从钉钉PC端进入工时管家
         </div>
         <Footer page="index"></Footer>
     </div>
@@ -34,8 +34,8 @@
                 ],
                 routers: [
                     {
-                        name: '查看日报',
-                        url: '/view',
+                        name: '我的日报',
+                        url: '/calendar',
                         icon: 'description'
                     },
                     {
@@ -194,6 +194,6 @@
         color: #8f8f8f;
         margin-top: 20px;
         text-align: center;
-        line-height: 30px;
+        line-height: 20px;
     }
 </style>

+ 40 - 2
fhKeeper/formulahousekeeper/timesheet_h5/src/views/login/index.vue

@@ -17,6 +17,7 @@
 
 <script>
     import { constants } from "crypto";
+    import * as dd from 'dingtalk-jsapi'; 
     export default {
         data() {
             return {
@@ -52,19 +53,56 @@
                         window.location.reload();
                     } else {
                         toast.clear();
-                        this.$toast.success('登录失败');
+                        this.$toast.fail(res.msg);
                     }
                 }).catch(err=> {toast.clear();});
             },
             
             jumpTo() {
                 this.$router.push("/register");
+            },
+
+            loginByCode(code, corpId) {
+                this.$axios.post("/dingding/getUserByCode", {code:code, corpid:corpId})
+                            .then(res => {
+                                if(res.code == "ok") {
+                                    let user = res.data;
+                                    this.$store.commit("updateLogin", true);
+                                    localStorage.userInfo = JSON.stringify(user);
+                                    
+                                    this.$router.push("/index");
+                                    //强制刷新,避免index页面中的mounted不执行
+                                    // window.location.reload();
+                                } else {
+                                    this.$toast.fail(res.msg);
+                                }
+                            }).catch(err=> {toast.clear();});
+            },
+        },
+        created() {
+            if (localStorage.userInfo != null) {
+                this.$router.push("/index");
             }
         },
         mounted() {
-            //自动检测账号,登录进入系统
             if (localStorage.userInfo != null) {
                 this.$router.push("/index");
+            } else {
+                //检查环境,如果是钉钉有$CORPID$
+                var key = '?corpid=';
+                var url = location.href;
+                var that = this;
+                if (url.indexOf(key) > 0) {
+                    var corpId = url.substring(url.indexOf(key)+key.length,url.indexOf('#'));
+                    dd.ready(function() {
+                        dd.runtime.permission.requestAuthCode({
+                            corpId: corpId, // 企业id
+                            onSuccess: function (info) {
+                                var code = info.code // 通过该免登授权码可以获取用户身份
+                                that.loginByCode(code, corpId);
+                            }});
+                    });
+                } 
             }
         }
     };

+ 5 - 1
fhKeeper/formulahousekeeper/timesheet_h5/src/views/project/index.vue

@@ -146,13 +146,17 @@
                 .then(res => {
                     if(res.code == "ok") {
                         this.loading = false;
+                        if (this.list.length == 0) {
+                            this.finished = true;
+                        }
+                        
                         for(var i in res.data.records) {
                             this.list.push(res.data.records[i])
                         }
                         this.total = res.data.total;
                         this.page++;
                     } else {
-                        this.$toast.fail('获取失败');
+                        this.$toast.fail('获取失败:'+res.msg);
                     }
                 }).catch(err=> {toast.clear();});
             },

+ 53 - 3
fhKeeper/formulahousekeeper/timesheet_h5/src/views/register/index.vue

@@ -6,7 +6,14 @@
             <van-field class="form_input" v-model="form.companyName" name="companyName" label="公司名称" placeholder="请输入公司名称" :rules="rules.companyName" />
             <van-field class="form_input" v-model="form.name" name="name" label="姓名" placeholder="请输入姓名" :rules="rules.name" />
             <van-field class="form_input" v-model="form.phone" name="phone" label="手机号" placeholder="请输入手机号" :rules="rules.phone" />
-            <div class="form_tip">手机号为负责人登录账号,默认密码:<span>000000</span></div>
+            <van-field class="form_input" v-model="form.vcode" name="vcode" label="验证码" placeholder="请输入验证码" :rules="rules.vcode" >
+                <template #button>
+                    <van-button size="small" type="primary" @click="sendVcode" :disabled="form.phone=='' || showTimer">发送验证码<span v-if="showTimer">({{countNum}})</span></van-button>
+                </template>
+            </van-field>
+            <van-field class="form_input" v-model="form.password" name="password" label="设置密码" placeholder="请设置密码,不低于6位" :rules="rules.password" />
+            <van-field class="form_input" v-model="form.repwd" name="repwd" label="重复密码" placeholder="请重复输入密码" :rules="rules.repwd" />
+            <div class="form_tip">手机号为企业负责人登录账号</div>
             <div class="form_btn" style="margin: 16px;">
                 <van-button round block type="info" native-type="submit"> 注册 </van-button>
             </div>
@@ -19,6 +26,8 @@
     export default {
         data() {
             return {
+                showTimer: false,
+                countNum: 60,
                 form: {
                     companyName: '',
                     name: '',
@@ -30,20 +39,61 @@
                     phone: [
                         { required: true, message: '请输入手机号' },
                         { validator: this.phoneValidator, message: '手机号格式错误' },
-                    ]
+                    ],
+                    vcode: [{ required: true, message: '请输入验证码'},],
+                    password: [{ required: true, message: '请设置密码,长度不低于6位' },],
+                    repwd: [{ required: true, message: '请重复输入密码'},]
                 }
             };
         },
         methods: {
+            //开始倒计时
+            countDown() {
+                if (this.countNum > 0) {
+                    this.countNum--;
+                } else {
+                    clearInterval(this.timer);
+                    this.showTimer = false;
+                }
+            },
+            sendVcode() {
+                if (this.form.phone.length != 11) {
+                    this.$toast.fail( '手机号码格式不正确');
+                } else {
+                    this.$axios.post("/user/sendVcode", {mobile: this.form.phone})
+                    .then(res => {
+                        if(res.code == "ok") {
+                            this.$toast.success('发送成功');
+                            this.showTimer = true;
+                            this.countNum = 60;
+                            this.timer = setInterval(this.countDown, 1000);
+                        } else {
+                            this.$toast.fail(res.msg);
+                        }
+                    }).catch(err=> {});
+                    
+                }
+            },
             phoneValidator(val) {
                 return /1\d{10}/.test(val);
             },
 
             register() {
+                //检查密码是否一致
+                if (this.form.password.length < 6) {
+                    this.$toast.fail('密码不能低于6位');
+                    return;
+                }
+                if (this.form.password != this.form.repwd) {
+                    this.$toast.fail('两次输入的密码不一致');
+                    return;
+                }
+                
                 const toast = this.$toast.loading({
                     forbidClick: true,
                     duration: 0
                 });
+                
                 this.$axios.post("/user/insertCompany", this.form)
                 .then(res => {
                     if(res.code == "ok") {
@@ -52,7 +102,7 @@
                         this.$router.push("/login");
                     } else {
                         toast.clear();
-                        this.$toast.fail('注册失败');
+                        this.$toast.fail(res.msg);
                     }
                 }).catch(err=> {toast.clear();});
             },

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet_h5/src/views/review/index.vue

@@ -102,7 +102,7 @@
                         this.report = res.data;
                     } else {
                         toast.clear();
-                        this.$toast.fail('获取失败');
+                        this.$toast.fail('获取失败:'+res.msg);
                     }
                 }).catch(err=> {toast.clear();});
             },

+ 5 - 1
fhKeeper/formulahousekeeper/timesheet_h5/src/views/view/index.vue

@@ -115,13 +115,17 @@
                         }
                     } else {
                         toast.clear();
-                        this.$toast.fail('获取失败');
+                        this.$toast.fail('获取失败:'+res.msg);
                     }
                 }).catch(err=> {toast.clear();});
             },
         },
 
         mounted() {
+            if (sessionStorage.targetDate != null) {
+                this.nowTime = sessionStorage.targetDate;
+                sessionStorage.removeItem('targetDate');
+            }
             this.getReport();
         }
     };