Home.vue 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  1. <template>
  2. <el-row class="container">
  3. <v-tour name="myTour" :steps="steps" :options="myOptions" :callbacks="myCallbacks" v-if="tourFlg"></v-tour>
  4. <el-col :span="24" class="header">
  5. <div class="contentMask" v-if="vTourFlg"></div>
  6. <el-col :span="10" class="logo" :class="collapsed?'logo-collapse-width':'logo-width'" :style="collapsed?'padding:0':''">
  7. <img v-if="collapsed" class="headImg" src="../assets/image/head_logo.png" />
  8. <div v-else class="logo-sys">
  9. <img class="headImg" src="../assets/image/head_logo.png" />
  10. <span>{{appName}}</span>
  11. </div>
  12. </el-col>
  13. <el-col :span="6">
  14. <div class="tools" style="position: relative;">
  15. <i class="fa fa-align-justify" @click.prevent="collapse" style="position: relative;z-index: 10;"></i>
  16. <div class="gongshimingz">
  17. {{user.companyName}}
  18. <i v-if="user.roleName == '超级管理员'" class="el-icon-edit" @click="editCompanyNamedialog=true,companyForm.name = user.companyName" style="position: relative;z-index: 15; margin-left: 5px;"></i>
  19. </div>
  20. </div>
  21. </el-col>
  22. <el-col :span="12" class="userinfo" style="display: flex;align-items: center;justify-content: flex-end;">
  23. <!-- 中英文切换入口 -->
  24. <!-- <el-dropdown trigger="click" @command="langChange" style="margin-right:30px;">
  25. <span class="el-dropdown-link userinfo-inner">
  26. {{language}} <i class="el-icon-caret-bottom"></i>
  27. </span>
  28. <el-dropdown-menu slot="dropdown">
  29. <el-dropdown-item divided command="zh">中文</el-dropdown-item>
  30. <el-dropdown-item divided command="en">English</el-dropdown-item>
  31. </el-dropdown-menu>
  32. </el-dropdown> -->
  33. <el-dropdown trigger="hover" style="margin-right:30px;">
  34. <span class="el-dropdown-link userinfo-inner">
  35. <i class="el-icon-user" style="font-size:18px" ></i>
  36. <!-- {{$t('other.customerService')}} -->
  37. 帮助中心
  38. </span>
  39. <el-dropdown-menu slot="dropdown">
  40. <el-dropdown-item >
  41. <div v-if="!isCorpWX">
  42. <!-- <div>{{$t('other.sweepWeChatYards')}}</div> -->
  43. <!-- <div>扫码添加企业微信客服</div> -->
  44. <div>{{ $t('ke-fu-wei-xin') }}</div>
  45. <img
  46. style="width: 120px; height: 120px"
  47. src="../assets/image/code.jpg" />
  48. </div>
  49. <div v-if="isCorpWX">
  50. <div>扫码添加企业微信客服</div>
  51. <img
  52. style="width: 153px; height: 153px"
  53. src="../assets/image/qwcode.png" />
  54. </div>
  55. <div>
  56. <div>
  57. <el-link type="primary" :underline="false" href="https://www.ttkuaiban.com/download/%E5%B7%A5%E6%97%B6%E7%AE%A1%E5%AE%B6%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%E4%B9%A6.pdf">点击查看操作手册</el-link>
  58. </div>
  59. </div>
  60. </el-dropdown-item>
  61. </el-dropdown-menu>
  62. </el-dropdown>
  63. {{$t('time.dueDate')}}:{{remainingTime}}
  64. <el-badge class="itemNew" :value="num" :hidden="num == 0">
  65. <i class="el-icon-message-solid" style="font-size:24px" v-popover:popover1 @click="drawer = true"></i>
  66. </el-badge>
  67. <el-drawer :title="$t('other.messageCenter')" :visible.sync="drawer" direction="rtl" :with-header="false" size="35%">
  68. <el-table :data="popoverData" :height="tableHeight" size="small">
  69. <el-table-column property="type" :label="$t('other.messageContent')" align="left">
  70. <template slot-scope="scope">
  71. <el-link type="primary" :underline="false" @click="locationHerf(scope.row.id,scope.row.content, scope.row.type)">
  72. <span style="font-size:13px;">
  73. <span v-if="scope.row.msg == null">
  74. {{msgTypeTxt[scope.row.type]}}
  75. </span>
  76. <span v-else>
  77. <span v-if="user.userNameNeedTranslate != 1">
  78. {{scope.row.msg}}
  79. </span>
  80. <span v-if="user.userNameNeedTranslate == 1">
  81. {{scope.row.omg.textOne}}
  82. <ww-open-data type='userName' :openid='scope.row.omg.textTwo'></ww-open-data>
  83. {{scope.row.omg.textThree}}
  84. </span>
  85. </span>
  86. <!-- {{scope.row.msg==null?msgTypeTxt[scope.row.type]:scope.row.msg}} -->
  87. </span>
  88. </el-link>
  89. </template>
  90. </el-table-column>
  91. <el-table-column property="type" :label="$t('state.states')" align="center" width="60">
  92. <template slot-scope="scope">
  93. <span v-if="scope.row.checked == 0" style="color:red">{{$t('other.unread')}}</span>
  94. <span v-else style="color:green">{{$t('other.read')}}</span>
  95. </template>
  96. </el-table-column>
  97. <el-table-column property="time" :label="$t('time.times')" align="center" width="120"></el-table-column>
  98. </el-table>
  99. </el-drawer>
  100. <el-dropdown trigger="hover" style="margin-left:10px;">
  101. <span class="el-dropdown-link userinfo-inner">
  102. <img src="../assets/image/userHead.png" />
  103. <span v-if="user.userNameNeedTranslate == 1">
  104. <ww-open-data type='userName' :openid='sysUserName'></ww-open-data>
  105. </span>
  106. <span v-if="user.userNameNeedTranslate != 1">
  107. {{sysUserName}}
  108. </span>
  109. <!-- {{sysUserName}} -->
  110. </span>
  111. <el-dropdown-menu slot="dropdown">
  112. <!-- <el-dropdown-item disabled ><span style="font-size:12px;"><i class="el-icon-view" ></i>{{roleArray[user.role]}}</span></el-dropdown-item> -->
  113. <el-dropdown-item disabled ><span style="font-size:12px;"><i class="el-icon-view" ></i>{{user.roleName}}</span></el-dropdown-item>
  114. <el-dropdown-item disabled ><span style="font-size:12px;"><i class="el-icon-medal" v-if="user.jobNumber"></i>{{user.jobNumber}}</span></el-dropdown-item>
  115. <el-dropdown-item @click.native="reset" v-if="user.userNameNeedTranslate != 1">{{$t('other.changeThePassword')}}</el-dropdown-item>
  116. <!-- <el-dropdown-item @click.native="editInfoOpen">修改信息</el-dropdown-item> -->
  117. <el-dropdown-item divided @click.native="logout" v-if="!isCorpWX" >{{$t('other.launchTheLogin')}}</el-dropdown-item>
  118. </el-dropdown-menu>
  119. </el-dropdown>
  120. </el-col>
  121. </el-col>
  122. <el-col :span="24" class="main">
  123. <aside :class="collapsed?'menu-collapsed':'menu-expanded'">
  124. <el-scrollbar style="height:100%">
  125. <!--导航菜单-->
  126. <el-menu :default-active="$route.path" class="el-menu-vertical-demo" unique-opened router v-if="!collapsed" default-openeds="zhan">
  127. <template v-for="(item, index) in $router.options.routes" v-if="!item.hidden">
  128. <div v-if="item.name =='产品管理'">
  129. <el-submenu :index="'zhan'" >
  130. <template slot="title">
  131. <i :class="item.iconCls"></i>
  132. <span class="itemName bosx" v-if="item.name.length < 16">{{item.name}}</span>
  133. <el-tooltip class="itemName bosx" v-if="item.name.length > 16" effect="dark" :content="item.name" placement="top">
  134. <span>{{item.name}}</span>
  135. </el-tooltip>
  136. </template>
  137. <!-- 根据后台配置的产品分类来渲染产品管理的子菜单 -->
  138. <el-menu-item v-for="child in user.prodSubMenuList" :index="child.path" :key="child.path" v-if="!child.hidden" :data-v-step="child.path"><i :class="child.iconCls"></i>
  139. <span class="bosx" v-if="child.name.length < 16">{{child.name}}</span>
  140. <el-tooltip class="bosx" v-if="child.name.length > 16" effect="dark" :content="child.name" placement="top">
  141. <span>{{child.name}}</span>
  142. </el-tooltip>
  143. </el-menu-item>
  144. </el-submenu>
  145. </div>
  146. <div v-else>
  147. <el-submenu :index="'zhan'" v-if="!item.leaf">
  148. <template slot="title">
  149. <i :class="item.iconCls"></i>
  150. <span class="itemName bosx" v-if="item.name.length < 16">{{item.name}}</span>
  151. <el-tooltip class="itemName bosx" v-if="item.name.length > 16" effect="dark" :content="item.name" placement="top">
  152. <span>{{item.name}}</span>
  153. </el-tooltip>
  154. </template>
  155. <el-menu-item v-for="child in item.children" :index="child.path" :key="child.path" v-if="!child.hidden" :data-v-step="child.path"><i :class="child.iconCls"></i>
  156. <!-- {{child.name}} -->
  157. <span class="bosx" v-if="child.name.length < 16">{{child.name}}</span>
  158. <el-tooltip class="bosx" v-if="child.name.length > 16" effect="dark" :content="child.name" placement="top">
  159. <span>{{child.name}}</span>
  160. </el-tooltip>
  161. </el-menu-item>
  162. </el-submenu>
  163. <el-menu-item v-if="item.leaf && item.children.length > 0" :index="item.children[0].path" :data-v-step="item.children[0].path">
  164. <i :class="item.iconCls"></i>
  165. <!-- {{item.children[0].name}} -->
  166. <span class="bosx" v-if="item.name.length < 16">{{item.name}}</span>
  167. <el-tooltip class="itemName bosx" v-if="item.name.length > 16" effect="dark" :content="item.name" placement="top">
  168. <span>{{item.name}}</span>
  169. </el-tooltip>
  170. </el-menu-item>
  171. </div>
  172. </template>
  173. </el-menu>
  174. <!--导航菜单-折叠后-->
  175. <ul class="el-menu el-menu-vertical-demo collapsed" v-if="collapsed" ref="menuCollapsed">
  176. <li v-for="(item,index) in $router.options.routes" v-if="!item.hidden" class="el-submenu item" :style="{overflow:!item.leaf?'':'hidden'}">
  177. <div v-if="item.name == '产品管理'">
  178. <template>
  179. <div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
  180. <i :class="item.iconCls"></i>
  181. </div>
  182. <ul class="el-menu submenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
  183. <li v-for="child in user.prodSubMenuList" :key="child.path" class="el-menu-item" style="padding-left: 40px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.path)">
  184. {{child.name}}
  185. </li>
  186. </ul>
  187. </template>
  188. </div>
  189. <div v-else>
  190. <template v-if="!item.leaf">
  191. <div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
  192. <i :class="item.iconCls"></i>
  193. </div>
  194. <ul class="el-menu submenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
  195. <li v-for="child in item.children" v-if="!child.hidden" :key="child.path" class="el-menu-item" style="padding-left: 40px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.path)">
  196. {{child.name}}
  197. </li>
  198. </ul>
  199. </template>
  200. <template v-else>
  201. <li class="el-submenu">
  202. <div class="el-submenu__title el-menu-item" :class="$route.path==item.children[0].path?'is-active':''" @click="$router.push(item.children[0].path)"
  203. style="padding-left: 20px;height: 56px;line-height: 56px;padding: 0 20px;">
  204. <i :class="item.iconCls"></i>
  205. </div>
  206. </li>
  207. </template>
  208. </div>
  209. <!-- <template v-if="!item.leaf">
  210. <div class="el-submenu__title" style="padding-left: 20px;" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
  211. <i :class="item.iconCls"></i>
  212. </div>
  213. <ul class="el-menu submenu" :class="'submenu-hook-'+index" @mouseover="showMenu(index,true)" @mouseout="showMenu(index,false)">
  214. <li v-for="child in item.children" v-if="!child.hidden" :key="child.path" class="el-menu-item" style="padding-left: 40px;" :class="$route.path==child.path?'is-active':''" @click="$router.push(child.path)">
  215. {{child.name}}
  216. </li>
  217. </ul>
  218. </template>
  219. <template v-else>
  220. <li class="el-submenu">
  221. <div class="el-submenu__title el-menu-item" :class="$route.path==item.children[0].path?'is-active':''" @click="$router.push(item.children[0].path)"
  222. style="padding-left: 20px;height: 56px;line-height: 56px;padding: 0 20px;">
  223. <i :class="item.iconCls"></i>
  224. </div>
  225. </li>
  226. </template> -->
  227. </li>
  228. </ul>
  229. </el-scrollbar>
  230. </aside>
  231. <section class="content-container">
  232. <div class="contentMask" v-if="vTourFlg"></div>
  233. <div class="grid-content bg-purple-light">
  234. <el-col :span="24" class="content-wrapper">
  235. <transition name="fade" mode="out-in">
  236. <router-view></router-view>
  237. </transition>
  238. </el-col>
  239. </div>
  240. <!--修改密码-->
  241. <el-dialog :title="$t('other.changeThePassword')" width='450px' v-if="editPassWord" :visible.sync="editPassWord" :close-on-click-modal="false" customClass="customWidth">
  242. <el-form :model="addForm" label-width="auto" :rules="passRule" ref="addForm">
  243. <el-form-item :label="$t('lable.originalPassword')" prop="originPassword">
  244. <el-input v-model="addForm.originPassword" autocomplete="off" :placeholder="$t('defaultText.pleaseEnterTheOldPassword')" show-password></el-input>
  245. </el-form-item>
  246. <el-form-item :label="$t('lable.newPassword')" prop="newPassword">
  247. <el-input v-model="addForm.newPassword" autocomplete="off" :placeholder="$t('defaultText.pleaseEnterTheNewPassword')" show-password></el-input>
  248. </el-form-item>
  249. </el-form>
  250. <div slot="footer" class="dialog-footer">
  251. <el-button @click.native="editPassWord = false">{{$t('btn.cancel')}}</el-button>
  252. <el-button type="primary" @click.native="resetPwd" :loading="editLoading">{{$t('btn.submit')}}</el-button>
  253. </div>
  254. </el-dialog>
  255. <!--修改信息-->
  256. <el-dialog :title="$t('title.modifyTheInformation')" width='450px' v-if="editInformation" :visible.sync="editInformation" :close-on-click-modal="false" customClass="customWidth">
  257. <el-form :model="editInfoForm" label-width="auto" :rules="passRule" ref="editInfoForm">
  258. <el-form-item :label="$t('lable.name')" prop="username">
  259. <el-input v-model="editInfoForm.username" autocomplete="off" :placeholder="$t('defaultText.PleaseEnterYourName')"></el-input>
  260. </el-form-item>
  261. </el-form>
  262. <el-form :model="editInfoForm" label-width="auto" :rules="passRule" ref="editInfoForm">
  263. <el-form-item :label="$t('lable.phone')" prop="mobile">
  264. <el-input v-model="editInfoForm.mobile" autocomplete="off" :placeholder="$t('defaultText.PleaseEnterYourPhone')" :disabled="true"></el-input>
  265. </el-form-item>
  266. </el-form>
  267. <div slot="footer" class="dialog-footer">
  268. <el-button @click.native="editInformation = false">{{$t('btn.cancel')}}</el-button>
  269. <el-button type="primary" @click.native="editInfo" :loading="editLoading2">{{$t('btn.submit')}}</el-button>
  270. </div>
  271. </el-dialog>
  272. <el-dialog
  273. title="修改公司名称"
  274. :visible.sync="editCompanyNamedialog"
  275. width="30%">
  276. <el-form :model="companyForm" :rules="rules" ref="companyForm" label-width="100px" class="demo-ruleForm">
  277. <el-form-item label="公司名称" prop="name">
  278. <el-input v-model.trim="companyForm.name"></el-input>
  279. </el-form-item>
  280. </el-form>
  281. <span slot="footer" class="dialog-footer">
  282. <el-button @click="editCompanyNamedialog = false">取 消</el-button>
  283. <el-button type="primary" @click="editCompanyName('companyForm')">确 定</el-button>
  284. </span>
  285. </el-dialog>
  286. </section>
  287. </el-col>
  288. </el-row>
  289. </template>
  290. <script>
  291. import util from "../common/js/util";
  292. export default {
  293. // 引用 app.vue reloads 方法
  294. inject:['reloads'],
  295. data() {
  296. return {
  297. appName: localStorage.appName,
  298. companyForm:{
  299. name: '',
  300. },
  301. rules: {
  302. name: [
  303. { required: true, message: '请输入公司名称', trigger: 'blur' },
  304. { min: 1, max: 20, message: '长度为1-20个字符', trigger: 'blur' }
  305. ]
  306. },
  307. tourFlg: false,
  308. editCompanyNamedialog:false,
  309. firstTourFalse: localStorage.getItem('firstTourFalse') | true, // 是否需要新手指导
  310. steps: [
  311. {
  312. target: '[data-v-step="/timetype"]',
  313. content: `第一步,查看基础设置,按照企业情况进行调整`,
  314. params: {
  315. placement: 'right',
  316. highlight: true
  317. }
  318. },{
  319. target: '[data-v-step="/list"]',
  320. content: `第二步,创建项目和任务`,
  321. params: {
  322. placement: 'right',
  323. highlight: true
  324. }
  325. },{
  326. target: '[data-v-step="/report"]',
  327. content: `第三步,填写每日工时报告`,
  328. params: {
  329. placement: 'right',
  330. highlight: true
  331. }
  332. },{
  333. target: '[data-v-step="/review"]',
  334. content: `第四步,项目报告审核`,
  335. params: {
  336. placement: 'right',
  337. highlight: true
  338. }
  339. },{
  340. target: '[data-v-step="/cost"]',
  341. content: `第五步,查看工时成本统计结果`,
  342. params: {
  343. placement: 'right',
  344. highlight: true
  345. }
  346. },{
  347. target: '[data-v-step="/finance"]',
  348. content: `第六步,导入薪资,校准成本并生成财务报表`,
  349. params: {
  350. placement: 'right',
  351. highlight: true
  352. }
  353. }
  354. ],
  355. myOptions:{
  356. useKeyboardNavigation: false, //不使用←、→和ESC键来导航tour
  357. startTimeout: 1000, //1秒后执行
  358. highlight: true,
  359. labels: {
  360. buttonSkip: '跳过',
  361. buttonPrevious: '上一步',
  362. buttonNext: '下一步',
  363. buttonStop: '关闭'
  364. }
  365. },
  366. myCallbacks: {
  367. onSkip: this.onSkip, //在data中定义两个回调
  368. onFinish: this.onFinish
  369. },
  370. isCorpWX: false,
  371. // roleArray:["普通员工","超级管理员", "系统管理员", "公司高层","财务管理员", "项目管理员","公司领导"],
  372. roleArray:[this.$t('role.ordinaryEmployees'),this.$t('role.superAdministrator'),this.$t('role.systemAdministrator'),this.$t('role.companyTop'),this.$t('role.financialAdministrator'),this.$t('role.projectManager'),this.$t('role.companyLeadership')],
  373. helpImg: '../assets/image/userHead.png',
  374. user: sessionStorage.getItem("user"),
  375. collapsed: sessionStorage.collapsed!=null?(sessionStorage.collapsed=='true'?true:false):false,
  376. sysUserName: "",
  377. menu: [],
  378. // msgTypeTxt:["审批未通过","有新任务啦","任务有新进展","项目日报审核通过"],
  379. msgTypeTxt:[this.$t('state.notApproved'),this.$t('state.ThereIsAnewTask'),this.$t('state.TheresBeen'),this.$t('state.approvedProject')],
  380. editInformation: false,
  381. editPassWord: false,
  382. editLoading: false,
  383. editLoading2: false,
  384. addForm: {
  385. id: "",
  386. originPassword: "",
  387. newPassword: ""
  388. },
  389. editInfoForm: {
  390. id: "",
  391. username: "",
  392. mobile: "",
  393. companyName: ""
  394. },
  395. passRule: {
  396. originPassword: [{ required: true, message: this.$t('defaultText.pleaseEnterTheOldPassword'), trigger: "blur" }],
  397. newPassword: [{ required: true, message: this.$t('defaultText.pleaseEnterTheNewPassword'), trigger: "blur" }],
  398. username: [{ required: true, message: this.$t('defaultText.PleaseEnterYourName'), trigger: "blur" }]
  399. },
  400. //时间
  401. activeDate: new Date(),
  402. timer: null,
  403. remainingTime: '',
  404. drawer: false,
  405. tableHeight: 0,
  406. popoverData: [],
  407. num: 0,
  408. language: '',
  409. setTimeLoad: null,
  410. // 遮罩
  411. vTourFlg: false
  412. };
  413. },
  414. created() {
  415. this.firstTourFalse = localStorage.getItem('firstTourFalse') || true
  416. console.log(this.firstTourFalse, '数据书数据')
  417. console.log(localStorage.getItem('firstTourFalse'))
  418. },
  419. methods: {
  420. getSkipGuidance() {
  421. this.http.post('/user/skipGuidance', {},
  422. res => {
  423. if (res.code == "ok") {
  424. let users = JSON.parse(sessionStorage.getItem("user"))
  425. users.isFirstLogin == 0
  426. sessionStorage.setItem("user", JSON.stringify(users))
  427. }
  428. },
  429. error => {
  430. });
  431. },
  432. onSkip(currentStep) {
  433. console.log('看看')
  434. this.vTourFlg = false
  435. this.firstTourFalse = false
  436. localStorage.setItem('firstTourFalse', false)
  437. console.log(this.user, '用户信息')
  438. if(this.user.corpwxUserid != null) {
  439. this.getSkipGuidance()
  440. }
  441. },
  442. onFinish(currentStep) {
  443. console.log('数据')
  444. this.vTourFlg = false
  445. this.firstTourFalse = false
  446. localStorage.setItem('firstTourFalse', false)
  447. this.getSkipGuidance()
  448. if(this.user.corpwxUserid != null) {
  449. this.getSkipGuidance()
  450. }
  451. },
  452. // 中英文切换
  453. langChange(command) {
  454. let flg = this.language
  455. this.$i18n.locale = command
  456. localStorage.setItem("lang", command)
  457. if(command == 'en') {
  458. this.language = 'English'
  459. } else if (command == 'zh') {
  460. this.language = '中文'
  461. }
  462. if(flg != this.language) {
  463. this.reloads()
  464. }
  465. },
  466. //退出登录
  467. logout: function() {
  468. var _this = this;
  469. this.$confirm(this.$t('other.confirmExit') + '?', this.$t('other.prompts'), {
  470. //type: 'warning'
  471. confirmButtonText: this.$t('btn.submit'),
  472. cancelButtonText: this.$t('btn.cancel'),
  473. }).then(() => {
  474. sessionStorage.removeItem("user");
  475. location.reload();
  476. _this.$router.push("/login");
  477. });
  478. },
  479. //折叠导航栏
  480. collapse: function() {
  481. this.collapsed = !this.collapsed;
  482. sessionStorage.collapsed = this.collapsed;
  483. },
  484. showMenu(i, status) {
  485. this.$refs.menuCollapsed.getElementsByClassName(
  486. "submenu-hook-" + i
  487. )[0].style.display = status ? "block" : "none";
  488. },
  489. //打开编辑信息界面
  490. editInfoOpen() {
  491. this.editInformation = true;
  492. this.editInfoForm.id = JSON.parse(sessionStorage.getItem("user")).id;
  493. this.editInfoForm.username = JSON.parse(
  494. sessionStorage.getItem("user")
  495. ).username;
  496. this.editInfoForm.mobile = JSON.parse(
  497. sessionStorage.getItem("user")
  498. ).account;
  499. this.editInfoForm.companyName = JSON.parse(
  500. sessionStorage.getItem("user")
  501. ).companyName;
  502. },
  503. //编辑信息
  504. editInfo() {
  505. this.$refs.editInfoForm.validate(valid => {
  506. if (valid) {
  507. this.editLoading2 = true;
  508. this.http.post(
  509. this.port.pwd.resetPwd,
  510. { id: this.editInfoForm.id, username: this.editInfoForm.username },
  511. res => {
  512. this.editLoading2 = false;
  513. this.editInformation = false;
  514. if (res.code == "ok") {
  515. this.$message({
  516. message: this.$t('message.modifyTheSuccess'),
  517. type: "success"
  518. });
  519. //读取并覆盖session storage
  520. var userObject = JSON.parse(sessionStorage.getItem("user"));
  521. userObject.username = this.editInfoForm.username;
  522. sessionStorage.setItem("user", JSON.stringify(userObject));
  523. this.sysUserName = this.editInfoForm.username;
  524. } else {
  525. this.$message({
  526. message: res.msg,
  527. type: "error"
  528. });
  529. }
  530. },
  531. error => {
  532. this.editLoading2 = false;
  533. this.editInformation = false;
  534. this.$message({
  535. message: error,
  536. type: "error"
  537. });
  538. }
  539. );
  540. }
  541. });
  542. },
  543. //编辑公司名称
  544. editCompanyName(companyForm){
  545. this.$refs[companyForm].validate((valid) => {
  546. if (valid) {
  547. this.http.post("/company/editCompanyName", {name:this.companyForm.name},
  548. res => {
  549. if (res.code == "ok") {
  550. this.editCompanyNamedialog = false;
  551. let list = JSON.parse(sessionStorage.getItem("user") || '[]')
  552. sessionStorage.removeItem('user')
  553. this.user.companyName = this.companyForm.name
  554. list.companyName = this.companyForm.name
  555. sessionStorage.setItem("user",JSON.stringify(list))
  556. this.$message({
  557. message: res.msg,
  558. type: "success"
  559. });
  560. } else {
  561. this.$message({
  562. message: res.msg,
  563. type: "error"
  564. });
  565. }
  566. },
  567. error => {
  568. this.$message({
  569. message: error,
  570. type: "error"
  571. });
  572. });
  573. } else {
  574. return false;
  575. }
  576. });
  577. },
  578. reset() {
  579. this.editPassWord = true;
  580. this.addForm.id = JSON.parse(sessionStorage.getItem("user")).id;
  581. this.addForm.account = JSON.parse(sessionStorage.getItem("user")).account;
  582. },
  583. resetPwd() {
  584. this.$refs.addForm.validate(valid => {
  585. if (valid) {
  586. this.editLoading = true;
  587. this.http.post( this.port.manage.editPassword, this.addForm,
  588. res => {
  589. this.editLoading = false;
  590. this.editPassWord = false;
  591. if (res.code == "ok") {
  592. this.$message({
  593. // message: "修改成功,请重新登录",
  594. message: this.$t('message.logAganin'),
  595. type: "success"
  596. });
  597. this.$router.push("/login");
  598. } else {
  599. this.$message({
  600. message: res.msg,
  601. type: "error"
  602. });
  603. }
  604. },
  605. error => {
  606. this.editLoading = false;
  607. this.editPassWord = false;
  608. this.$message({
  609. message: error,
  610. type: "error"
  611. });
  612. });
  613. }
  614. });
  615. },
  616. setTime() {
  617. var d = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 'd');
  618. var h = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 'h');
  619. var m = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 'm');
  620. var s = util.formatDate.cdTime(new Date(new Date().getTime() + this.user.remainingTime), new Date(), 's');
  621. this.remainingTime = d+'天'+h+'时'+m+'分'+s+'秒';
  622. },
  623. // 加载消息
  624. loadNotice() {
  625. this.http.post( this.port.manage.msgList, {},
  626. res => {
  627. if (res.code == "ok") {
  628. var list = res.data;
  629. if(this.user.userNameNeedTranslate == 1) {
  630. let msgArr = res.data
  631. for(var i in msgArr) {
  632. if(msgArr[i].msg) {
  633. let caozuo = JSON.parse(JSON.stringify(msgArr[i].msg))
  634. if(caozuo.indexOf('$userName=') != '-1') {
  635. let textOne = caozuo.split('$userName=')[0]
  636. let textTwo = caozuo.split('$userName=')[1].split('$')[0]
  637. let textThree = caozuo.split('$userName=')[1].split('$')[1]
  638. msgArr[i].omg = {
  639. textOne: textOne,
  640. textTwo: textTwo,
  641. textThree: textThree
  642. }
  643. } else {
  644. msgArr[i].omg = {
  645. textOne: msgArr[i].msg,
  646. textTwo: '',
  647. textThree: ''
  648. }
  649. }
  650. } else {
  651. msgArr[i].omg = {
  652. textOne: '',
  653. textTwo: '',
  654. textThree: ''
  655. }
  656. }
  657. }
  658. }
  659. this.popoverData = res.data;
  660. var num = 0;
  661. for(var i in list) {
  662. if(list[i].checked != 1) {
  663. num ++;
  664. }
  665. }
  666. this.num = num;
  667. } else {
  668. this.$message({
  669. message: res.msg,
  670. type: "error"
  671. });
  672. }
  673. },
  674. error => {
  675. this.$message({
  676. message: error,
  677. type: "error"
  678. });
  679. });
  680. },
  681. //点击消息的跳转
  682. locationHerf(id, date, type) {
  683. this.http.post( this.port.manage.check, { id: id },
  684. res => {
  685. if (res.code == "ok") {
  686. this.loadNotice();
  687. if (type == 0) {
  688. //审批未通过的消息, 也包括审批通过的通知
  689. sessionStorage.msg = date;
  690. sessionStorage.from = 1;
  691. //本页面再点的话强制转移一下
  692. var currentRoute = this.$route.path.split("/");
  693. if (currentRoute[1] == "daily") {
  694. this.$router.go(0);
  695. this.drawer = false;
  696. return false;
  697. }
  698. this.$router.push("/daily");
  699. this.drawer = false;
  700. } else if (type == 1) {
  701. //1- 有新任务待执行
  702. this.$router.push("/projectInside/"+date);
  703. this.drawer = false;
  704. } else if (type == 2) {
  705. //2- 任务有新进展
  706. this.$router.push("/projectInside/"+date);
  707. this.drawer = false;
  708. } else if (type == 3) {
  709. //3- 费用报销
  710. this.$router.push("/expense");
  711. this.drawer = false;
  712. } else if (type == 4) {
  713. //4- 请假消息
  714. this.$router.push("/leave");
  715. this.drawer = false;
  716. } else if (type == 5) {
  717. //5- 出差消息
  718. this.$router.push("/awayOffice");
  719. this.drawer = false;
  720. } else if (type == 6 || type == 7 || type == 8) {
  721. // 6、7 合同通过、驳回
  722. this.$router.push("/contract");
  723. this.drawer = false;
  724. }
  725. } else {
  726. this.$message({
  727. message: res.msg,
  728. type: "error"
  729. });
  730. }
  731. },
  732. error => {
  733. this.$message({
  734. message: error,
  735. type: "error"
  736. });
  737. });
  738. },
  739. // 获取企业微信的参数
  740. agentConfig() {
  741. var isCorpWX = true
  742. var ua = navigator.userAgent.toLowerCase();
  743. if (ua.indexOf("wxwork") > 0) {
  744. isCorpWX = false;
  745. }
  746. var curUrl = location.href.split("#")[0];
  747. this.http.post("/wxcorp/getCorpWXConfig", {url: curUrl, token: this.user.id}, (res) => {
  748. if (res.code == "ok") {
  749. wx.config({
  750. beta: true,
  751. debug: isCorpWX, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  752. appId: res.data.appid, // 必填,公众号的唯一标识
  753. timestamp: res.data.timestamp, // 必填,生成签名的时间戳
  754. nonceStr: res.data.noncestr, // 必填,生成签名的随机串
  755. signature: res.data.sign, // 必填,签名,见附录1
  756. jsApiList: ['chooseImage','previewImage','uploadImage','downloadImage','previewFile','getLocation','agentConfig', 'getLocalImgData']
  757. });
  758. var that = this;
  759. wx.ready(function(){
  760. // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
  761. that.http.post("/wxcorp/getCorpWXAgentConfig", {url: curUrl, token: that.user.id}, (res) => {
  762. if (res.code == "ok") {
  763. console.log()
  764. wx.agentConfig({
  765. corpid: res.data.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
  766. agentid: res.data.agentid, // 必填,企业微信的应用id (e.g. 1000247)
  767. timestamp: res.data.timestamp, // 必填,生成签名的时间戳
  768. nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
  769. signature: res.data.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法
  770. jsApiList: ['selectExternalContact', 'selectEnterpriseContact', 'openAppManage'], //必填,传入需要使用的接口名称
  771. success: function (result) {
  772. console.log(result, '请求微信成功')
  773. console.log(window, 'window')
  774. // wx.agentConfig成功回调后,WWOpenData 才会注入到 window 对象上面
  775. if(window.WWOpenData) {
  776. window.WWOpenData.bind(document.querySelector('ww-open-data'))
  777. if (WWOpenData.initCanvas) {
  778. WWOpenData.initCanvas()
  779. console.log('我企业微信 canvas 应该执行了吧')
  780. }
  781. }
  782. },
  783. fail: function (res) {
  784. console.log('查看错误信息', res)
  785. if (res.errMsg.indexOf('function not exist') > -1) {
  786. alert('版本过低请升级')
  787. }
  788. },
  789. })
  790. }
  791. }, (error) => {
  792. console.log('查看错误信息' + res)
  793. if (error.errMsg.indexOf('function not exist') > -1) {
  794. alert('版本过低请升级')
  795. }
  796. })
  797. });
  798. }
  799. }, (error) => {
  800. console.log(error, '哦耶')
  801. })
  802. },
  803. },
  804. mounted() {
  805. var ua = navigator.userAgent.toLowerCase();
  806. if (ua.indexOf("wxwork") > 0) {
  807. this.isCorpWX = true;
  808. }
  809. let langse = localStorage.getItem("lang") || 'zh'
  810. if(langse == 'en') {
  811. this.language = 'English'
  812. } else if (langse == 'zh') {
  813. this.language = '中文'
  814. }
  815. let height = window.innerHeight;
  816. this.tableHeight = height - 15;
  817. const that = this;
  818. window.onresize = function temp() {
  819. that.tableHeight = window.innerHeight - 15;
  820. };
  821. if (this.user) {
  822. var user = JSON.parse(this.user);
  823. this.user = user;
  824. this.sysUserName = user.name || "";
  825. this.loadNotice();
  826. if(this.user.remainingTime != "" && this.user.remainingTime != 0) {
  827. this.remainingTime = util.formatDate.format(new Date(new Date().getTime() + this.user.remainingTime), "yyyy-MM-dd")
  828. } else {
  829. this.remainingTime = this.$t('other.expired');
  830. clearInterval(this.timer);
  831. }
  832. } else {
  833. this.$router.push("/login");
  834. }
  835. // console.log('啊,我被触发了呀')
  836. // 获取企业微信参数
  837. if(this.user.userNameNeedTranslate == '1') {
  838. this.agentConfig()
  839. }
  840. // 判断是否为新用户
  841. // console.log(this.firstTourFalse, '数据书数据123', 'true' == true)
  842. // if(this.firstTourFalse != 'false') {
  843. if(this.user.isFirstLogin == 1 && this.user.roleName == '超级管理员' && this.firstTourFalse != 'false' && this.user.createTime[0] > '2022') {
  844. var thats = this
  845. this.tourFlg = true
  846. setTimeout(() => {
  847. thats.$tours['myTour'].start()
  848. setTimeout(() => {
  849. thats.vTourFlg = true
  850. }, 1000)
  851. }, 200)
  852. }
  853. },
  854. };
  855. </script>
  856. <style scoped lang="scss">
  857. .contentMask {
  858. width: 100%;
  859. height: 100%;
  860. position: absolute;
  861. top: 0;
  862. left: 0;
  863. background: #000;
  864. opacity: .4;
  865. z-index: 99;
  866. // box-shadow: 0 0 0 99999px rgba(0,0,0,.4) !important;
  867. }
  868. .gongshimingz {
  869. width: 100%;
  870. position: absolute;
  871. left: 0px;
  872. display: inline-block;
  873. overflow: hidden;
  874. white-space: nowrap;
  875. text-overflow: ellipsis;
  876. box-sizing: border-box;
  877. padding-left: 60px;
  878. }
  879. .el-menu-vertical-demo i {
  880. margin-right: 10px;
  881. }
  882. .container {
  883. position: absolute;
  884. top: 0px;
  885. bottom: 0px;
  886. width: 100%;
  887. .header {
  888. height: 60px;
  889. line-height: 60px;
  890. background: #20a0ff;
  891. color: #fff;
  892. position: relative;
  893. .userinfo {
  894. text-align: right;
  895. padding-right: 35px;
  896. float: right;
  897. .userinfo-inner {
  898. cursor: pointer;
  899. color: #fff;
  900. img {
  901. width: 40px;
  902. height: 40px;
  903. border-radius: 20px;
  904. margin: 10px 10px 10px 10px;
  905. float: left;
  906. }
  907. }
  908. .itemNew {
  909. height: 25px;
  910. margin: 0 0 0 10px;
  911. i {
  912. vertical-align: top;
  913. }
  914. }
  915. }
  916. .logo {
  917. height: 60px;
  918. font-size: 21px;
  919. padding-left: 20px;
  920. padding-right: 20px;
  921. border-color: rgba(238, 241, 146, 0.3);
  922. border-right-width: 1px;
  923. border-right-style: solid;
  924. img {
  925. width: 40px;
  926. float: left;
  927. margin: 10px 10px 10px 18px;
  928. }
  929. img.headImg {
  930. margin: 0;
  931. width: 40px;
  932. height: 40px;
  933. margin: 10px 0 0 10px;
  934. }
  935. .logo-sys {
  936. height: 100%;
  937. line-height: 100%;
  938. img.headImg {
  939. width: 40px;
  940. height: 40px;
  941. margin: 7.5px 0 0 10px;
  942. vertical-align: middle;
  943. }
  944. span {
  945. display: inline-block;
  946. height: 100%;
  947. line-height: 60px;
  948. margin-left: 15px;
  949. font-size: 16px;
  950. // margin: 20px 0 0 15px;
  951. vertical-align: middle;
  952. }
  953. }
  954. .txt {
  955. color: #fff;
  956. }
  957. }
  958. .logo-width {
  959. width: 200px;
  960. }
  961. .logo-collapse-width {
  962. width: 60px;
  963. }
  964. .tools {
  965. padding: 0px 23px;
  966. // width: 14px;
  967. height: 60px;
  968. line-height: 60px;
  969. cursor: pointer;
  970. }
  971. }
  972. .main {
  973. display: flex;
  974. position: absolute;
  975. top: 60px;
  976. bottom: 0px;
  977. overflow: hidden;
  978. aside {
  979. flex: 0 0 230px;
  980. width: 230px;
  981. .el-menu {
  982. height: 100%;
  983. }
  984. .collapsed {
  985. width: 60px;
  986. .item {
  987. position: relative;
  988. }
  989. .submenu {
  990. position: absolute;
  991. top: 0px;
  992. left: 60px;
  993. z-index: 99999;
  994. height: auto;
  995. display: none;
  996. box-shadow: 5px 5px 10px #ddd;
  997. }
  998. }
  999. }
  1000. .menu-collapsed {
  1001. flex: 0 0 60px;
  1002. width: 60px;
  1003. }
  1004. .menu-expanded {
  1005. flex: 0 0 200px;
  1006. width: 200px;
  1007. }
  1008. .content-container {
  1009. flex: 1;
  1010. width: 80%;
  1011. overflow-y: auto;
  1012. overflow-x: hidden;
  1013. // position: relative;
  1014. .breadcrumb-container {
  1015. .title {
  1016. width: 200px;
  1017. float: left;
  1018. color: #475669;
  1019. }
  1020. .breadcrumb-inner {
  1021. float: right;
  1022. }
  1023. }
  1024. .content-wrapper {
  1025. background-color: #fff;
  1026. box-sizing: border-box;
  1027. // position: relative;
  1028. }
  1029. }
  1030. }
  1031. }
  1032. .popover-item {
  1033. padding: 10px;
  1034. border-bottom: 1px #eee solid;
  1035. }
  1036. .popover-item > div > p {
  1037. margin: 0;
  1038. line-height: 18px;
  1039. }
  1040. .popover-title {
  1041. color: #409eff;
  1042. padding-bottom: 8px;
  1043. }
  1044. .popover-type {
  1045. color: #aaa;
  1046. font-size: 8px;
  1047. float: right;
  1048. }
  1049. .popover-button {
  1050. font-weight: 900;
  1051. padding: 10px;
  1052. text-align: center;
  1053. cursor: pointer;
  1054. }
  1055. .isRead {
  1056. color: #999 !important;
  1057. }
  1058. .bosx {
  1059. width: 110px;
  1060. display: inline-block;
  1061. overflow: hidden;
  1062. white-space: nowrap;
  1063. text-overflow: ellipsis;
  1064. }
  1065. </style>