index.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. <template>
  2. <div class="body indexFlex">
  3. <van-swipe class="my-swipe" :autoplay="3000" :height="200" indicator-color="white">
  4. <van-swipe-item v-for="(item, index) in images" :key="index" class="swipe-img">
  5. <img :src="item"/>
  6. </van-swipe-item>
  7. </van-swipe>
  8. <div class="indexFlex1">
  9. <van-grid :column-num="3">
  10. <van-grid-item v-for="(item,index) in routers" :key="index" :icon="item.icon" :text="item.name"
  11. :info="(item.name=='消息记录'&&unreadNum>0)?unreadNum:''"
  12. :to="item.url" @click="pfdClick(item)">
  13. </van-grid-item>
  14. </van-grid>
  15. </div>
  16. <div v-if="isCorpWX" class="kefu" @click="tokefu"><img src="../../assets/icon/kefu.png" alt=""></div>
  17. <div class="tip" v-if="!isCorpWX">
  18. 体验报表统计等更多功能,尽在PC端<br>
  19. 网页用户访问http://worktime.ttkuaiban.com,钉钉用户直接从钉钉PC端进入工时管家
  20. </div>
  21. <Footer ref="child" :key="key"></Footer>
  22. </div>
  23. </template>
  24. <script>
  25. import Footer from "@/components/Footer";
  26. import Vue from "vue";
  27. import { ImagePreview } from "vant";
  28. Vue.use(ImagePreview);
  29. export default {
  30. data() {
  31. return {
  32. yuzhongCompId: 3385,
  33. isCorpWX:false,
  34. isWX:false,
  35. user: null,
  36. unreadNum:0,
  37. images: [
  38. // require('../../assets/img/index/banner_1.png'),
  39. require('../../assets/img/index/banner4.jpeg'),
  40. // require('../../assets/img/index/banner_3.png'),
  41. ],
  42. routers: [],
  43. key: 0,
  44. isSyncData: false,
  45. jobNumberCheckCompanyId: [936], // 定制需求,需要完善工号的公司id
  46. };
  47. },
  48. created() {
  49. if(localStorage.userInfo) {
  50. this.user = JSON.parse(localStorage.userInfo)
  51. // 是否为钉钉同步
  52. this.isSyncData = this.user.timeType.syncDingding || this.user.timeType.syncFanwei;
  53. }
  54. },
  55. mounted() {
  56. //有错误信息,优先跳转到登录页面去
  57. if(window.location.href.indexOf('errorMsg') != '-1') {
  58. this.$router.push("/login");
  59. }
  60. var ua = navigator.userAgent.toLowerCase();
  61. if (ua.indexOf("wxwork") > 0) {
  62. this.isCorpWX = true;
  63. } else if (ua.indexOf("micromessenger") > 0) {
  64. this.isWX = true;
  65. }
  66. let that = this;
  67. //企业微信或个人微信是从后台授权后跳转过来的
  68. if (this.isCorpWX || this.isWX) {
  69. //后台自动授权登录的用户
  70. if(window.location.href.indexOf('userId') != '-1') {
  71. let href = window.location.href;
  72. var loginUserId = href.substring(href.indexOf("userId=")+"userId=".length);
  73. if (loginUserId.includes('#/')) {
  74. loginUserId = loginUserId.substring(0, loginUserId.indexOf('#/'));
  75. }
  76. that.getAccountInfo(loginUserId)
  77. } else {
  78. //存在一部分用户,没有绑定企业微信,进来后跳到登录页面,登录页面输入账号密码进来后不带userId
  79. if (this.user) {
  80. that.getAccountInfo(that.user.id);
  81. } else {
  82. that.$router.push("/login");
  83. }
  84. }
  85. } else {
  86. //其他情况,刷新用户信息
  87. if (localStorage.userInfo != null && localStorage.userInfo != 'undefined') {
  88. that.user = JSON.parse(localStorage.userInfo);
  89. that.getAccountInfo(that.user.id);
  90. } else{
  91. //无用户信息,跳到登录页面去
  92. this.$router.push("/login");
  93. }
  94. }
  95. if (this.user) {
  96. let userss = this.user;
  97. if(userss.isMobFirstLogin == 1 && userss.createTime[0] > '2022' && userss.roleName == '超级管理员') {
  98. // 第一次登陆显示
  99. this.previewPicture()
  100. }
  101. }
  102. // 检查是否有工号
  103. const { companyId, jobNumber, userNameNeedTranslate, name, dingdingUserid } = this.user
  104. if(this.jobNumberCheckCompanyId.includes(companyId) && !jobNumber) {
  105. this.$router.push({
  106. path: '/editPerfect',
  107. query: {
  108. showjobNumber: 'true'
  109. }
  110. });
  111. }
  112. // 检查是否需要完成姓名
  113. if(userNameNeedTranslate == 0 && (name == dingdingUserid)) {
  114. this.$router.push({
  115. path: '/editPerfect',
  116. query: {
  117. showjobNumber: 'false'
  118. }
  119. });
  120. }
  121. if(this.user.dingdingUserid) {
  122. this.setDDOpenData()
  123. }
  124. },
  125. components: {
  126. Footer
  127. },
  128. methods: {
  129. setDDOpenData() {
  130. const ddUrl = new URL(window.location.href);
  131. const ddCorpid = ddUrl.searchParams.get("corpid") || ''
  132. let ddOpenDataInit = window.DTOpenData.init(ddCorpid)
  133. console.log(ddOpenDataInit, '<=== 钉钉执行 window.DTOpenData.init(ddCorpid) 的判断')
  134. if (ddOpenDataInit) {
  135. setTimeout(() => {
  136. console.log('<==== 执行 window.DTOpenData.update(document.querySelectorAll(dt-open-data))')
  137. window.DTOpenData.update(document.querySelectorAll('dt-open-data'));
  138. }, 300)
  139. }else {
  140. console.log('钉钉没有触发')
  141. }
  142. },
  143. pfdClick(item) {
  144. if(item.name == '使用说明') {
  145. let url = 'http://celiang.oss-cn-hangzhou.aliyuncs.com/measurement/2022-01/18/75it6phpocqYFV1642488558220118.pdf'
  146. let name = '使用说明书'
  147. // 将要传过去的值
  148. this.previewPDF(url, name)
  149. }
  150. },
  151. // 预览pdf
  152. previewPDF(url, name) {
  153. this.$router.push({
  154. path: '/pdf',
  155. query: {
  156. url: '',
  157. name: name
  158. }
  159. })
  160. },
  161. // 图片预览
  162. previewPicture() {
  163. let that = this
  164. let arr = [
  165. 'https://mobworktime.ttkuaiban.com/upload/b9cf863819924106a65255ccffae446d.png',
  166. 'https://mobworktime.ttkuaiban.com/upload/65afcaed7ad84c51a309db69c888fe6c.png',
  167. 'https://mobworktime.ttkuaiban.com/upload/3452d33a68bb4092b04147e5482fd0e9.png',
  168. 'https://mobworktime.ttkuaiban.com/upload/af5b430f48b24b2683fb48a43deab98c.png',
  169. 'https://mobworktime.ttkuaiban.com/upload/b69779d86be44ef3a1d3585816fde5f3.png'
  170. ]
  171. ImagePreview({
  172. images: arr,
  173. startPosition: 0,
  174. showIndicators: true,
  175. closeable: true,
  176. onClose() {
  177. that.previewPictureClose()
  178. },
  179. });
  180. },
  181. // 处理关闭事件
  182. previewPictureClose() {
  183. this.$axios.post("/user/mobSkipGuidance", {
  184. })
  185. .then(res => {
  186. if(res.code == "ok") {
  187. let userss = JSON.parse(localStorage.userInfo)
  188. userss.isMobFirstLogin = 0
  189. localStorage.userInfo = JSON.stringify(userss);
  190. }
  191. }).catch(err=> {this.$toast.clear();});
  192. },
  193. tokefu(){
  194. wx.invoke('openThirdAppServiceChat', {
  195. }, function(res) {
  196. console.log('invoke',res);
  197. if (res.err_msg == "openThirdAppServiceChat:ok" || res.err_msg == "openThirdAppServiceChat:cancel") {
  198. }else{
  199. this.$toast.fail('请联系管理员添加客服');
  200. }
  201. }
  202. );
  203. },
  204. // 模块
  205. getModule() {
  206. if(this.user.userNameNeedTranslate == '1'){
  207. this.agentConfig()
  208. }
  209. if (this.user.company.packageEngineering == 1) {
  210. this.routers.push(
  211. {
  212. name: '专业审核',
  213. url: '/profession_review',
  214. icon: 'todo-list-o'
  215. });
  216. }
  217. var list = this.user.moduleList
  218. let jurisdictionNameList = this.user.functionList.map(item => item.name)
  219. for (var i in list) {
  220. if(list[i].name == '工时报告') {
  221. this.routers.push({name: '查看日报',url: '/calendar',icon: 'description'})
  222. if(this.user.timeType.enableNewWeeklyfill != 1) { // 针对新版按周填报去掉填写日报
  223. this.routers.push({name: '填写日报',url: '/edit',icon: 'edit'})
  224. }
  225. if (this.user.companyId != 3092 && this.user.timeType.type != 0) {
  226. this.routers.push({name: '按周填报',url: '/weekEdit',icon: 'records'})
  227. }
  228. if(jurisdictionNameList.some(item => item == '代填日报')) {
  229. this.routers.push({name: '代填日报',url: '/edit?substitute=true',icon: 'completed'})
  230. }
  231. }
  232. if(list[i].name == '待办任务') {
  233. this.routers.push({
  234. name: '待办任务',
  235. url: '/task',
  236. icon: 'coupon-o'
  237. });
  238. }
  239. if(list[i].name == '项目报告审核') {
  240. this.routers.push({name: '项目报告审核',url: '/review',icon: 'todo-list-o'})
  241. }
  242. if(list[i].name == '项目管理') {
  243. this.routers.push({name: '项目管理',url: '/project',icon: 'label-o'})
  244. }
  245. if(list[i].name == '导入日报审核') {
  246. this.routers.push({name: '导入日报审核',url: '/audit',icon: 'completed'})
  247. }
  248. if(!this.isSyncData) {
  249. if(list[i].name == '请假管理') {
  250. this.routers.push({name: '请假管理',url: '/applyLeave',icon: 'notes-o'})
  251. // this.routers.push({name: '请假审批',url: '/exaLeave',icon: 'completed'})
  252. // this.routers.push({name: '出差管理',url: '/awayOffice',icon: 'completed'})
  253. }
  254. if(list[i].name == '出差管理') {
  255. this.routers.push({name: '出差管理',url: '/awayOffice',icon: 'logistics'})
  256. }
  257. }
  258. if(list[i].name == '费用报销') {
  259. this.routers.push({
  260. name: '费用报销',
  261. url: '/expense',
  262. icon: 'balance-list-o'
  263. });
  264. }
  265. if(list[i].name == '设备管理') {
  266. this.routers.push({
  267. name: '设备管理',
  268. url: '/useRegistration',
  269. icon: 'label-o'
  270. }, {
  271. name: '设备使用记录',
  272. url: '/usageHistory',
  273. icon: 'label-o'
  274. });
  275. }
  276. }
  277. if (this.user.manageDeptId != 0 && this.user.company.packageEngineering == 1) {
  278. this.routers.push(
  279. {
  280. name: '部门审核',
  281. url: '/department_review',
  282. icon: 'todo-list-o'
  283. });
  284. }
  285. this.routers.push({
  286. name: '消息记录',
  287. url: '/msg',
  288. icon: 'todo-list-o',
  289. info: this.unreadNum
  290. });
  291. // 针对超级管理员加使用说明
  292. if(this.user.roleName == '超级管理员') {
  293. this.routers.push(
  294. {
  295. name: '使用说明',
  296. // url: '/',
  297. icon: 'todo-list-o'
  298. });
  299. }
  300. if(this.user.companyId == 7536) {
  301. this.routers.splice(2, 0, {
  302. name: '扫码填报',
  303. url: '/edit?scanTheCode=1',
  304. icon: 'scan'
  305. })
  306. }
  307. // 设备管理
  308. // if(this.user.companyId == 10) {
  309. // this.routers.push({
  310. // name: '设备管理',
  311. // url: '/useRegistration',
  312. // icon: 'label-o'
  313. // }, {
  314. // name: '设备使用记录',
  315. // url: '/usageHistory',
  316. // icon: 'label-o'
  317. // });
  318. // }
  319. },
  320. // 获取企业微信参数
  321. agentConfig(){
  322. let curUrl = window.location.href.split('#')[0]
  323. this.$axios.post('/wxcorp/getCorpWXConfig',{
  324. url: curUrl,
  325. token: this.user.id
  326. }).then(res => {
  327. if(res.code == 'ok'){
  328. wx.config({
  329. beta: true,
  330. debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  331. appId: res.data.appid, // 必填,公众号的唯一标识
  332. timestamp: res.data.timestamp, // 必填,生成签名的时间戳
  333. nonceStr: res.data.noncestr, // 必填,生成签名的随机串
  334. signature: res.data.sign, // 必填,签名,见附录1
  335. jsApiList: ['chooseImage','previewImage','uploadImage','downloadImage','previewFile','getLocation','agentConfig']
  336. })
  337. let that = this
  338. wx.ready(function(){
  339. // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
  340. that.$axios.post('/wxcorp/getCorpWXAgentConfig', {
  341. url: curUrl,
  342. token: that.user.id
  343. }).then(res => {
  344. if(res.code == 'ok'){
  345. wx.agentConfig({
  346. corpid: res.data.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
  347. agentid: res.data.agentid, // 必填,企业微信的应用id (e.g. 1000247)
  348. timestamp: res.data.timestamp, // 必填,生成签名的时间戳
  349. nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
  350. signature: res.data.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法
  351. jsApiList: ['selectExternalContact','openThirdAppServiceChat', 'openAppManage'], //必填,传入需要使用的接口名称
  352. success: function (result) {
  353. // console.log(result, '请求微信成功')
  354. // console.log(window, 'window')
  355. // wx.agentConfig成功回调后,WWOpenData 才会注入到 window 对象上面
  356. window.WWOpenData.bind(document.querySelector('TranslationOpenDataText'))
  357. // that.kefuShow = true
  358. },
  359. fail: function (res) {
  360. // console.log('查看错误信息', res)
  361. if (res.errMsg.indexOf('function not exist') > -1) {
  362. alert('版本过低请升级')
  363. } else {
  364. // alert('agentConfig出错:'+res.errMsg);
  365. }
  366. },
  367. })
  368. }
  369. }).catch(err => {
  370. if (err.errMsg.indexOf('function not exist') > -1) {
  371. alert('版本过低请升级')
  372. }else {
  373. // alert(res.errMsg);
  374. }
  375. })
  376. });
  377. wx.error(function(res){
  378. // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
  379. // alert('wxConfig发生异常:'+JSON.stringify(res));
  380. // 企业第一次授权安装进入后会报not in reliable domain的错误,刷新后正常
  381. location.reload();
  382. });
  383. } else {
  384. // alert(''+res);
  385. }
  386. }).catch(err => {
  387. alert(err);
  388. })
  389. },
  390. //获取账户信息
  391. getAccountInfo(userId) {
  392. this.$axios.get('/user/loginByUserId', {params:{userId: userId}})
  393. .then(res => {
  394. // console.log(res);
  395. if (res.code == 'error') {
  396. localStorage.errorMsg = res.msg;
  397. //账号信息有问题,不能使用。
  398. this.$router.push("/error");
  399. } else {
  400. localStorage.userInfo = JSON.stringify(res.data);
  401. this.user = res.data;
  402. this.$refs.child.dealWith()
  403. this.key++
  404. this.getModule()
  405. this.getMessage();
  406. this.redirectIfNess();
  407. this.$forceUpdate()
  408. if (this.user.companyId == this.yuzhongCompId) {
  409. //去掉按周填报
  410. this.routers = this.routers.filter(r=>r.name != '按周填报');
  411. }
  412. // this.bindIfNessary();
  413. }
  414. }).catch(err=> {
  415. alert('err=' + err);
  416. });
  417. },
  418. redirectIfNess() {
  419. var href = window.location.href;
  420. if (href.indexOf('path') > 0) {
  421. var path = href.split('path=')[1].split('&')[0];
  422. if (path == 'expense' || path == 'task') {
  423. this.$router.push(path);
  424. }
  425. }
  426. },
  427. bindIfNessary() {
  428. let href = window.location.href;
  429. var requestUrl = "";
  430. if (this.isCorpWX && (this.user.corpwxUserid == null|| this.user.corpwxUserid == undefined || this.user.corpwxUserid == 'undefined')) {//优先检查企业微信环境
  431. requestUrl = "/wxcorp/bindCorpWeiXin";
  432. } else if (this.isWX && (this.user.wxOpenid == null || this.user.wxOpenid == undefined || this.user.wxOpenid == 'undefined')) {
  433. requestUrl = "/wechat/bindWeiXin";
  434. }
  435. if (requestUrl.length > 0) {
  436. // localStorage.openId = 'o1L3L5lOrOl3_UEJjONaoT2Rne1I';
  437. //会自动跳转到首页
  438. // let href = 'http://hq.tangusoft.com/?code=011Ptjgc2rx1eI09Irgc2Rvsgc2PtjgF&state=1#/index';
  439. if (href.includes("com/?code")) { //url包括 com/?code 证明为从微信跳转回来的
  440. var url = href; //vue自动在末尾加了 #/ 符号,截取去掉
  441. var jingPosit = url.indexOf("com/") + 4; //获取域名结束的位置
  442. // var urlLeft = url.substring(0, jingPosit);//url左侧部分
  443. var urlRight = url.substring(jingPosit, url.length); //url右侧部分
  444. // console.log('urlRight=' + urlRight);
  445. // window.location = urlLeft + "#/home" + urlRight;//拼接跳转
  446. //获取code
  447. var code = urlRight.substring('?code='.length,urlRight.indexOf('#/index'));
  448. if (code.indexOf('&state=1') > 0) {
  449. code = code.substring(0, code.indexOf('&state=1'));
  450. }
  451. //调用后台接口,注册用户
  452. // console.log('获取到code=='+code);
  453. this.$axios.get(requestUrl, {params:{code:code, userId: this.user.id}})
  454. .then(res => {
  455. // console.log(res);
  456. if (res == null) {
  457. this.$toast.fail('绑定失败');
  458. } else if(res.errcode != null) {
  459. //报错了
  460. console.log(res.errmsg);
  461. } else {
  462. //获取openId
  463. if (res.data != null && ((this.isWX && res.data.wxOpenid != undefined)
  464. || (this.isCorpWX && res.data.corpwxUserid != undefined))) {
  465. localStorage.userInfo = JSON.stringify(res.data);
  466. // console.log('绑定成功');
  467. this.user = res.data;
  468. window.location.href = '/#/my/center';
  469. }
  470. }
  471. }).catch(err=> {
  472. alert('err=' + err);
  473. });
  474. }
  475. }
  476. },
  477. //获取消息
  478. getMessage() {
  479. this.$axios.post("/information/list", {
  480. })
  481. .then(res => {
  482. if(res.code == "ok") {
  483. var list = res.data;
  484. this.unreadNum = list.filter(l=>l.checked==0).length;
  485. // console.log(this.unreadNum);
  486. }
  487. }).catch(err=> {this.$toast.clear();});
  488. },
  489. },
  490. activated(){
  491. this.getMessage()
  492. },
  493. };
  494. </script>
  495. <style lang="less" scoped>
  496. .indexFlex {
  497. display: flex;
  498. flex-direction: column;
  499. height: 100%;
  500. width: 100%;
  501. .indexFlex1 {
  502. flex: 1;
  503. overflow-y: auto;
  504. }
  505. }
  506. .swipe-img {
  507. img {
  508. width: 100%;
  509. height: 100%;
  510. }
  511. }
  512. .body {
  513. height: calc(100vh - 50px);
  514. position: relative;
  515. }
  516. .kefu{
  517. position: fixed;
  518. right: 35px;
  519. bottom: 120px;
  520. width: 36px;
  521. height: 36px;
  522. background-color: #fff;
  523. z-index: 1000;
  524. border-radius: 50%;
  525. img{
  526. margin: 4px;
  527. width: 28px;
  528. height: 28px;
  529. }
  530. }
  531. .tip {
  532. width: 100%;
  533. bottom: 5px;
  534. font-size: 14px;
  535. color: #8f8f8f;
  536. margin-top: 10px;
  537. text-align: center;
  538. line-height: 20px;
  539. }
  540. </style>