daily.vue 98 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041
  1. <template>
  2. <section>
  3. <!--列表-->
  4. <div>
  5. <el-card class="box-card daily" shadow="never">
  6. <div slot="header" class="clearfix" id="clearfix" style="padding-left: 255px;">
  7. <div class="jjk" style="display:inline-block;position:fixed;top:70px;background:#fff;left:250px;">
  8. <el-date-picker size="small" v-model="date" :editable="false" format="yyyy-MM" value-format="yyyy-MM"
  9. style="width:190px;"
  10. @change="changeMonthOut" :clearable="false" type="month" placeholder="选择月份"></el-date-picker>
  11. <el-button style="margin-left:10px;" icon="iconfont firerock-icongongshitongji" size="mini" @click="showMonthWorkTime"></el-button>
  12. </div>
  13. <span v-for="(item,index) in allDate" :id="'day'+index" :class="index==choseDay?'chooseDate date_item':'date_item'"
  14. @click="choseDate(index, item)" :key="index" >
  15. <div :style="'display:inline-block;'+(item.state == null?'padding:0px 6px;':'')" >
  16. <div><span>{{item.showDate}}</span>
  17. <span style="font-size:10px;text-align:center;color:#999;">{{item.weekDay}}</span>
  18. </div>
  19. </div>
  20. <i v-if="item.state != null" class="iconfont firerock-icondot" :class="statusStyle[item.state]"></i>
  21. </span>
  22. </div>
  23. <div style="display:flex;">
  24. <div v-if="user.role > 0 || user.manageDeptId != 0" >
  25. <div style="width:190px;">
  26. <el-select v-model="selectState" size="small" @change="stateChange" >
  27. <el-option value="-1" label="全部状态" >全部状态</el-option>
  28. <el-option value="-2" label="未填报">未填报</el-option>
  29. <el-option value="1" label="已通过">已通过</el-option>
  30. <el-option value="0" label="待审核">待审核</el-option>
  31. <el-option value="2" label="不通过">不通过</el-option>
  32. <el-option value="3" label="已撤回">已撤回</el-option>
  33. </el-select></div>
  34. <div>
  35. <el-tree :data="data" @node-click="handleNodeClick" >
  36. <span class="custom-tree-node" slot-scope="{ node, data}">
  37. <span>{{ node.label }}</span>
  38. <span v-if="data.membCount != null && data.isUser == null">({{data.membCount}})</span>
  39. <div style="width:0%;float:right;">
  40. <span v-if="data.isUser == 1 && data.state == null" style="color:red;">
  41. 未填报
  42. </span>
  43. <span v-if="data.isUser == 1 && data.state == 0" style="color:orange;">
  44. 待审核
  45. </span>
  46. <span v-if="data.isUser == 1 && data.state == 1" style="color:green;">
  47. 已通过
  48. </span>
  49. <span v-if="data.isUser == 1 && data.state == 2" style="color:red;">
  50. 未通过
  51. </span>
  52. <span v-if="data.isUser == 1 && data.state == 3" style="color:red;">
  53. 已撤回
  54. </span>
  55. </div>
  56. </span>
  57. </el-tree>
  58. </div>
  59. </div>
  60. <div :style="'height:'+tableHeight+'px;width:0.5px;background:#eee;margin-right:10px;margin-left:10px;'" ></div>
  61. <div class="allDaily" style="float:left;flex-grow:1">
  62. <!--系统管理员和部门负责人 -->
  63. <div class="report_title" v-if="user.role == 1 || user.role == 2 || user.manageDeptId > 0">
  64. <span>工作日报 | {{depData != null ?depData.label:""}}</span>
  65. <span v-if="targetUid == null">
  66. - 已填写
  67. <el-link :underline="false" @click="showMembList(1)"><span style="margin-left:5px;margin-right:5px;color:green;">{{reportList.length}}</span></el-link>人,
  68. 未填写<el-link :underline="false" @click="showMembList(0)"><span style="margin-left:5px;margin-right:5px;color:red;">{{(depData == null?data[0].membCount:(depData.isUser == 1?1:depData.membCount))-reportList.length}}</span></el-link>人
  69. </span>
  70. <span style="float:right;">
  71. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReport(-1,0)">填写日报</el-link>
  72. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=true; fillInReport(-1,0)">代填日报</el-link>
  73. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReport(-1,1)">批量填报</el-link>
  74. <!-- <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=true; fillInReport(-1,1)">批量代填</el-link> -->
  75. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="showExportDialog">导出日报</el-link>
  76. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="batchApprove" >批量审核</el-link>
  77. </span>
  78. </div>
  79. <!--普通员工,含项目经理 -->
  80. <div class="report_title" v-if="(user.role==0||user.role==5) && user.manageDeptId == 0"><span>日报列表</span>
  81. <span style="float:right;" v-if="(user.role==0||user.role==5) && user.manageDeptId == 0">
  82. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReport(-1,0)">填写日报</el-link>
  83. <el-link type="primary" v-if="user.leader" style="margin-right:10px;" :underline="false" @click="isSubstitude=true; fillInReport(-1,0)">代填日报</el-link>
  84. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReport(-1,1)">批量填报</el-link>
  85. <!-- <el-link type="primary" v-if="user.leader" style="margin-right:10px;" :underline="false" @click="isSubstitude=true; fillInReport(-1,1)">批量代填</el-link> -->
  86. <el-link type="primary" v-if="user.leader" style="margin-right:10px;" :underline="false" @click="batchApprove">批量审核</el-link>
  87. </span>
  88. </div>
  89. <div :style="'height:'+(tableHeight-50)+'px;overflow:scroll;padding-top:10px;'">
  90. <div class="one_daily" v-for="(item1,index1) in reportList" :key="index1">
  91. <i class="fa fa-circle"></i>{{item1.name}}
  92. <span style="margin-left:30px;">
  93. <span style="margin-right:20px;">
  94. <!-- <i v-if="parseFloat(item1.reportTime)>parseFloat(item1.calculateTime)+0.5" style="color:red;margin-right:8px;" class="fa fa-exclamation-triangle"></i> -->
  95. 工作总时长:
  96. <!-- <span :style="parseFloat(item1.reportTime)>parseFloat(item1.calculateTime)+0.5?'color:red':''">{{item1.reportTime}}h</span> -->
  97. <span >{{item1.reportTime}}</span>h
  98. <span v-if="user.role >=1 && user.role <=3"><span style="margin-left:10px;">成本:</span>
  99. <span >{{item1.cost}}</span>元</span>
  100. </span>
  101. </span>
  102. <div class="checkbtn">
  103. <el-button v-if="(user.role == 1 || user.role == 2 || user.id == item1.data[0].inchargerId) && item1.state == 0" type="primary" :loading="logining" size="small" @click="approve(item1.id, item1)">通过</el-button>
  104. <el-button v-if="(user.role == 1 || user.role == 2 || user.id == item1.data[0].inchargerId) && item1.state == 0" type="danger" :loading="logining" size="small" @click="deny(item1.id,0, item1)">驳回</el-button>
  105. <!--自己可以撤回待审核状态的报告 -->
  106. <el-button v-if="(user.id == item1.id) && item1.state == 0" type="normal" :loading="logining" size="small" @click="cancel(item1)">撤回</el-button>
  107. <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>
  108. <el-button v-if="item1.state >= 2 && user.id == item1.id" type="primary" size="small" @click="isSubstitude=false; fillInReport(index1,0)">编辑日报</el-button>
  109. </div>
  110. <div class="one_daily_body">
  111. <el-timeline>
  112. <el-timeline-item v-for="(item2,index2) in item1.data" :key="index2">
  113. <el-card shadow="never">
  114. <p>项目:<b>{{item2.project}}</b><span v-if="item2.subProjectName != null"> / {{item2.subProjectName}}</span>
  115. <span v-if="user.company.packageEngineering == 0">
  116. <span style="margin-left:15px;color:#DAA520;" v-if="item2.state == 0">[ 待审核 ]</span>
  117. <span style="margin-left:15px;color:#32CD32;" v-else-if="item2.state == 1">[ 已通过 ]</span>
  118. <span style="margin-left:15px;color:#FF0000;" v-else-if="item2.state == 2">[ 已驳回 ]</span>
  119. <span style="margin-left:15px;color:#FF0000;" v-else-if="item2.state == 3">[ 已撤回 ]</span>
  120. </span>
  121. <span v-if="user.company.packageEngineering == 1">
  122. <span style="margin-left:15px;color:#DAA520;" v-if="item2.state == 0 && item2.departmentAuditState == -1">[ 待专业审核 ]</span>
  123. <span style="margin-left:15px;color:#DAA520;" v-if="item2.state == 0 && item2.departmentAuditState == 0">[ 待部门审核 ]</span>
  124. <span style="margin-left:15px;color:#DAA520;" v-if="item2.state == 0 && item2.departmentAuditState == 1">[ 待项目经理审核 ]</span>
  125. <span style="margin-left:15px;color:#32CD32;" v-else-if="item2.state == 1">[ 已通过 ]</span>
  126. <span style="margin-left:15px;color:#FF0000;" v-else-if="item2.state == 2">[ 已驳回 ]</span>
  127. <span style="margin-left:15px;color:#FF0000;" v-else-if="item2.state == 3">[ 已撤回 ]</span>
  128. </span>
  129. </p>
  130. <p v-if="user.company.packageEngineering == 1">
  131. 专业进度:
  132. <span style="margin-right:10px;" v-for="progressItem in item2.professionProgress" :key="progressItem.id">{{progressItem.professionName}}({{progressItem.progress}}%)
  133. <el-tooltip v-if="progressItem.auditState == 0" content="待审核" effect="light" placement="top">
  134. <i class="iconfont firerock-icondaibandengdaishenhe"></i>
  135. </el-tooltip>
  136. <el-tooltip v-if="progressItem.auditState == 1" content="已通过" effect="light" placement="top">
  137. <i class="iconfont firerock-iconshenhetongguo"></i>
  138. </el-tooltip>
  139. <el-tooltip v-if="progressItem.auditState == 2" content="不通过" effect="light" placement="top">
  140. <i class="iconfont firerock-iconshenhebohui"></i>
  141. </el-tooltip>
  142. </span>
  143. </p>
  144. <p v-if="item2.taskId != null">任务:{{item2.taskName}}
  145. </p>
  146. <p style="display: inline-block;">时长:
  147. <span v-if="item2.reportTimeType == 0" style="margin-right:10px;">{{typeList[item2.timeType]}}</span>
  148. <span v-if="item2.reportTimeType == 2" style="margin-right:10px;">{{item2.startTime+'-'+item2.endTime}}</span>
  149. {{item2.time.toFixed(1)}}h
  150. <el-tag type="danger" size="mini" style="margin-left: 65px" v-if="item2.isOvertime === 1">加班</el-tag>
  151. </p>
  152. <p>事项:<span v-html="item2.content"></span></p>
  153. </el-card>
  154. </el-timeline-item>
  155. </el-timeline>
  156. </div>
  157. </div>
  158. <!-- 简陋的无报告提示 -->
  159. <div v-if="reportList.length==0" style="width:100%;font-size:17px;text-align:center;color:#aaa;">{{curDate}}暂无报告</div>
  160. </div>
  161. </div>
  162. </div>
  163. </el-card>
  164. </div>
  165. <!-- 填写日报的dialog -->
  166. <el-dialog :title="isBatch==0?'填写日报':'批量填报'" :visible.sync="dialogVisible" width="60%" :close-on-click-modal="false">
  167. <el-form ref="workForm" :model="workForm" :rules="workRules" label-width="100px">
  168. <el-form-item label="选择人员" prop="userNames" v-if="isSubstitude"
  169. :rules="{ required: true, message: '请选择代填人员', trigger: 'change' }">
  170. <el-input @focus="showChooseMembTree" v-model="workForm.userNames"
  171. placeholder="请选择代填人员" ></el-input>
  172. </el-form-item>
  173. <el-form-item label="工作日期" prop="createDate">
  174. <el-date-picker v-model="workForm.createDate" :editable="false" format="yyyy-MM-dd" value-format="yyyy-MM-dd"
  175. :style="'width:'+(isBatch==0?'200':'280')+'px;'" :type="isBatch==0?'date':'daterange'"
  176. @change="changeMonth()" :clearable="false" placeholder="选择工作日期" :disabled="isDisable"></el-date-picker>
  177. <span v-if="reportTimeType.type == 3" style="margin-left:30px;">{{isBatch==0?'总':'每日'}}时长:</span>
  178. <el-input-number :disabled="!canEdit" v-if="reportTimeType.type == 3" style="margin-left:10px;" @change="changeAllTime"
  179. v-model="reportTimeType.allday" :precision="1" :step="0.5" :max="12" :min="0.5"></el-input-number>
  180. <span v-if="reportTimeType.type == 3">小时</span>
  181. </el-form-item>
  182. <div v-for="(domain, index) in workForm.domains" :key="domain.id">
  183. <el-form-item v-if="reportTimeType.type != 3" label="工作时长" :prop="'domains.' + index + '.'+timeFields[reportTimeType.type]"
  184. :rules="{ required: true, message: '请选择工作时长', trigger: 'blur' }">
  185. <el-select v-model="domain.timeType" style="width:200px;"
  186. v-if="reportTimeType.type == 0"
  187. placeholder="请选择工作时长"
  188. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
  189. @change="onTimeTypeChange(domain.timeType)">
  190. <el-option
  191. v-for="item in timeType"
  192. :key="item.value"
  193. :label="item.label"
  194. :value="item.value">
  195. </el-option>
  196. </el-select>
  197. <!-- 数字时长选择 -->
  198. <el-select v-model="domain.workingTime" style="width:200px;"
  199. v-if="reportTimeType.type == 1"
  200. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
  201. placeholder="请选择工作时长" >
  202. <el-option v-for="item in timeRange" :key="item" :value="item.toFixed(1)">{{item.toFixed(1)}}</el-option>
  203. </el-select>
  204. <span v-if="reportTimeType.type == 1">小时</span>
  205. <span v-if="reportTimeType.type == 2">
  206. <!--时间范围选择 -->
  207. <el-time-picker
  208. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
  209. v-model="domain.startTime"
  210. placeholder="起始时间"
  211. style="width:120px;"
  212. format="HH:mm"
  213. value-format="HH:mm"
  214. :picker-options="{
  215. start: '08:00',
  216. end: '23:30'
  217. }">
  218. </el-time-picker> - <el-time-picker
  219. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
  220. v-model="domain.endTime"
  221. placeholder="结束时间"
  222. style="width:120px;"
  223. format="HH:mm"
  224. value-format="HH:mm"
  225. :picker-options="{
  226. start: '08:00',
  227. end: '23:30',
  228. minTime: domain.startTime
  229. }">
  230. </el-time-picker>
  231. </span>
  232. <div class="overtime"><el-checkbox :disabled="!canEdit" v-model="domain.isOvertime">加班</el-checkbox></div>
  233. </el-form-item>
  234. <el-form-item label="投入项目" :prop="'domains.' + index + '.projectId'"
  235. :rules="{ required: true, message: '请选择投入项目', trigger: ['change','blur'] }">
  236. <el-select v-model="domain.projectId" placeholder="请选择" style="width:200px;" clearable="true" filterable="true"
  237. @change="selectProject(domain, index)"
  238. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)">
  239. <el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id"></el-option>
  240. </el-select>
  241. <!--子项目 -->
  242. <el-select v-model="domain.subProjectId" placeholder="请选择" style="width:200px;" clearable="true" v-if="domain.subProjectList != null && domain.subProjectList.length> 0"
  243. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)">
  244. <el-option v-for="item in domain.subProjectList" :key="item.id" :label="item.name" :value="item.id"></el-option>
  245. </el-select>
  246. <el-link v-if="index >= 1" type="primary" :underline="false" @click="delDomain(index)" style="float:right;margin-right:10px;"
  247. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)">
  248. <i class="fa fa-trash" style="color: red;;font-size:18px;"></i>
  249. </el-link>
  250. </el-form-item>
  251. <el-form-item v-if="reportTimeType.type == 3" label="用时占比" :prop="'domains.' + index + '.'+timeFields[reportTimeType.type]"
  252. :rules="{ required: true, message: '请选择工作时长', trigger: 'blur' }">
  253. <div style="width:300px;">
  254. <el-col span="14"><el-slider :disabled="!canEdit" v-model="domain.progress" :min="10" :show-tooltip="false" :step="10" style="width:180px;" @change="domain.workingTime = (reportTimeType.allday*domain.progress/100).toFixed(1)"></el-slider></el-col>
  255. <el-col span="10"><span style="margin-left:10px;float:right;"><span style="margin-right:10px;">{{domain.progress}}%</span>{{domain.workingTime}}小时</span></el-col>
  256. </div>
  257. <div class="overtime"><el-checkbox :disabled="!canEdit" v-model="domain.isOvertime">加班</el-checkbox></div>
  258. </el-form-item>
  259. <!--工程专业版本模式下, 各个专业的进度填报 -->
  260. <el-form-item label="专业进度" :prop="'domains.' + index + '.professionProgress'" v-if="user.company.packageEngineering==1">
  261. <span v-for="item in domain.professionProgress" :key="item.professionId" style="margin-right:10px;">
  262. <span>{{item.professionName}}</span> / 进度:
  263. <el-input size="mini" style="width:60px;" v-model="item.progress"
  264. @keyup.native="onProgressChange"
  265. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"></el-input>%
  266. </span>
  267. </el-form-item>
  268. <!--项目管理专业版模式下,项目下的近期执行的任务 -->
  269. <el-form-item label="相关任务" :prop="'domains.' + index + '.taskId'" v-if="user.company.packageProject==1" >
  270. <el-select v-model="domain.taskId" placeholder="请选择" style="width:100%;" filterable="true"
  271. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)">
  272. <el-option v-for="item in domain.taskList" :key="item.taskId" :label="item.taskName" :value="item.taskId"></el-option>
  273. </el-select>
  274. </el-form-item>
  275. <el-form-item label="工作事项" :prop="'domains.' + index + '.content'" >
  276. <el-input v-model="domain.content" type="textarea" :rows="4" placeholder="请填写工作事项" clearable
  277. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"></el-input>
  278. </el-form-item>
  279. <el-divider v-if="workForm.domains.length>1" style="margin-bottom:10px;"></el-divider>
  280. </div>
  281. <el-link v-if="showAddMore" :disabled="!canEdit" type="primary" :underline="false" @click="addDomain" style="margin-left:40px">添加更多</el-link>
  282. </el-form>
  283. <span slot="footer" class="dialog-footer">
  284. <el-button @click="deleteReport" v-if="workForm.domains[0].id != null">删除</el-button>
  285. <el-button @click="dialogVisible = false">取消</el-button>
  286. <el-button type="primary" @click="submitDepartment"
  287. :disabled="workForm.domains.length==0?true:(canEdit?false:true)" >提交</el-button>
  288. </span>
  289. </el-dialog>
  290. <!-- 批量日报审核 -->
  291. <el-dialog title="批量日报审核" :visible.sync="approveDialogVisible" width="500px" >
  292. <el-checkbox v-model="isAllSelect" label="全选" style="margin-left:24px;" @change="selectAll" v-if="reportNames.length > 0"></el-checkbox>
  293. <el-tree ref="approveTree" node-key="id" :data="reportNames" show-checkbox="true" @check-change="handleCheckChange" >
  294. </el-tree>
  295. <span slot="footer" class="dialog-footer">
  296. <el-button @click="approveDialogVisible = false">取消</el-button>
  297. <el-button type="primary" @click="submitBatchApprove" :disabled="batchShowData.length == 0">审核通过</el-button>
  298. </span>
  299. </el-dialog>
  300. <!--导出报表条件选择 -->
  301. <el-dialog title="日报导出" v-if="exportDialog" :visible.sync="exportDialog" customClass="customWidth" width="500px">
  302. <el-form ref="form3" :model="exportParam" >
  303. <el-form-item prop="projectId" label="选择项目">
  304. <el-select v-model="exportParam.projectId" placeholder="全部项目" clearable style="width:350px;">
  305. <el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id"></el-option>
  306. </el-select>
  307. </el-form-item>
  308. <el-form-item prop="projectId" label="日期范围">
  309. <el-date-picker
  310. v-model="exportParam.dateRange" :editable="false"
  311. format="yyyy-MM-dd" value-format="yyyy-MM-dd"
  312. :clearable="true"
  313. range-separator="至"
  314. type="daterange"
  315. start-placeholder="开始日期"
  316. end-placeholder="结束日期"
  317. ></el-date-picker>
  318. </el-form-item>
  319. </el-form>
  320. <div slot="footer" class="dialog-footer">
  321. <el-button type="primary" @click="exportReport" style="width:100%;" >导出</el-button>
  322. </div>
  323. </el-dialog>
  324. <!--人员列表 -->
  325. <el-dialog :title="(isFill?'已填':'未填')+'人员列表'" v-if="membListVisible" :visible.sync="membListVisible" width="500px">
  326. <el-table :show-header="false" :data="fillMembList" highlight-current-row :height="400" style="width: 100%;">
  327. <el-table-column type="index" width="60">
  328. <template slot-scope="scope" >
  329. {{scope.$index+1}}
  330. </template>
  331. </el-table-column>
  332. <el-table-column prop="label" label="姓名" ></el-table-column>
  333. <el-table-column prop="deptName" label="部门" >
  334. </el-table-column>
  335. </el-table>
  336. <div slot="footer" class="dialog-footer">
  337. <el-button type="primary" @click="weixinNotify" v-if="!isFill" :disabled="fillMembList == 0">微信催填</el-button>
  338. <el-button type="default" @click="exportMemb" :disabled="fillMembList == 0">导出</el-button>
  339. </div>
  340. </el-dialog>
  341. <!-- 按部门选择人员 -->
  342. <el-dialog title="选择需要代填报的人员" v-if="chooseParticipVisible" :visible.sync="chooseParticipVisible" :close-on-click-modal="false" customClass="customWidth" width="500px">
  343. <!-- <el-input style="width:100%" v-model="filterName" placeholder="请输入姓名搜索" @change="findUserInTree"></el-input> -->
  344. <div class="tree" style="height:400px">
  345. <el-scrollbar style="height:100%">
  346. <el-tree :data="deptMembData" show-checkbox :props="defaultProps" node-key="id"
  347. ref="chooseMembTree" @check-change="onTreeItemChange" :default-checked-keys="workForm.userId"
  348. highlight-current ></el-tree>
  349. </el-scrollbar>
  350. </div>
  351. <div>已选中&nbsp;{{chosenMembCount}}&nbsp;人</div>
  352. <div slot="footer" class="dialog-footer">
  353. <el-button @click="chooseParticipVisible = false" >取消</el-button>
  354. <el-button type="primary" @click="chooseParticip()" >确定</el-button>
  355. </div>
  356. </el-dialog>
  357. <el-dialog title="员工每日填报工时数" v-if="monthWorkTimeDialog" :visible.sync="monthWorkTimeDialog" :close-on-click-modal="false" customClass="customWidth" width="90%">
  358. <!-- <el-input style="width:100%" v-model="filterName" placeholder="请输入姓名搜索" @change="findUserInTree"></el-input> -->
  359. <el-table :data="monthWorkData" border :height="500" highlight-current-row style="width: 100%;">
  360. <el-table-column width="60" type="index" fixed="left" label="序号">
  361. <template slot-scope="scope" >
  362. {{scope.$index+1}}
  363. </template>
  364. </el-table-column>
  365. <el-table-column width="100" prop="name" fixed="left" label="姓名">
  366. </el-table-column>
  367. <el-table-column width="90" v-for="(item,index) in allDate" :key="index" :label="item.showDate+'/'+item.weekDay" align="center">
  368. <template slot-scope="scope">
  369. <div style="color:red;"
  370. v-if="scope.row.worktimeList.filter(w=>w.createDate.split('-')[2] == item.date.split('月')[1].replace('日','')
  371. || w.createDate.split('-')[2] == '0'+item.date.split('月')[1].replace('日','') ).length > 0 && scope.row.worktimeList.filter(w=>w.createDate.split('-')[2] == item.date.split('月')[1].replace('日','')
  372. || w.createDate.split('-')[2] == '0'+item.date.split('月')[1].replace('日','') )[0].workingTime < reportTimeType.allday">
  373. {{scope.row.worktimeList.filter(w=>w.createDate.split('-')[2] == item.date.split('月')[1].replace('日','')
  374. || w.createDate.split('-')[2] == '0'+item.date.split('月')[1].replace('日','') )[0].workingTime
  375. }}</div>
  376. <div style="color:#20a0ff;"
  377. v-if="scope.row.worktimeList.filter(w=>w.createDate.split('-')[2] == item.date.split('月')[1].replace('日','')
  378. || w.createDate.split('-')[2] == '0'+item.date.split('月')[1].replace('日','') ).length > 0 && scope.row.worktimeList.filter(w=>w.createDate.split('-')[2] == item.date.split('月')[1].replace('日','')
  379. || w.createDate.split('-')[2] == '0'+item.date.split('月')[1].replace('日','') )[0].workingTime > reportTimeType.allday">
  380. {{scope.row.worktimeList.filter(w=>w.createDate.split('-')[2] == item.date.split('月')[1].replace('日','')
  381. || w.createDate.split('-')[2] == '0'+item.date.split('月')[1].replace('日','') )[0].workingTime
  382. }}</div>
  383. <div v-if="scope.row.worktimeList.filter(w=>w.createDate.split('-')[2] == item.date.split('月')[1].replace('日','')
  384. || w.createDate.split('-')[2] == '0'+item.date.split('月')[1].replace('日','') ).length > 0 && scope.row.worktimeList.filter(w=>w.createDate.split('-')[2] == item.date.split('月')[1].replace('日','')
  385. || w.createDate.split('-')[2] == '0'+item.date.split('月')[1].replace('日','') )[0].workingTime == reportTimeType.allday">
  386. {{scope.row.worktimeList.filter(w=>w.createDate.split('-')[2] == item.date.split('月')[1].replace('日','')
  387. || w.createDate.split('-')[2] == '0'+item.date.split('月')[1].replace('日','') )[0].workingTime
  388. }}</div>
  389. <div v-if="scope.row.worktimeList.filter(w=>w.createDate.split('-')[2] == item.date.split('月')[1].replace('日','')
  390. || w.createDate.split('-')[2] == '0'+item.date.split('月')[1].replace('日','') ).length == 0">
  391. 0
  392. </div>
  393. </template>
  394. </el-table-column>
  395. </el-table>
  396. <div slot="title" class="dialog-title">
  397. <label style="font-size:16px;">员工每日填报工时数</label>
  398. <el-link type="primary" style="float:right;margin-right:60px;" @click="exportMembWorkHours()" >导出数据</el-link>
  399. <!-- <el-button >导出</el-button> -->
  400. </div>
  401. </el-dialog>
  402. </section>
  403. </template>
  404. <script>
  405. import util from "../../common/js/util";
  406. export default {
  407. data() {
  408. return {
  409. monthWorkTimeDialog: false,
  410. isSubstitude:false,
  411. isFill:false,
  412. unFillList:[],
  413. fillList:[],
  414. fillMembList:[],
  415. membListVisible: false,
  416. isBatch:0,//是否是批量填报
  417. weekDay : ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
  418. statusStyle:["waiting", "filledReportStyle", "RejectStyle", ""],
  419. fillStatusList: [],
  420. exportParam:{projectId: null, dateRange:[]},
  421. exportDialog:false,
  422. timeFields:['timeType', 'workingTime', 'startTime', 'progress'],
  423. subProjectList:[],
  424. canEdit: true,
  425. timeRange:[0.5,1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5,7.0,7.5,8.0,8.5,9.0,9.5,10.0,10.5,11.0,11.5,12.0,12.5,13.0,13.5,14.0,14.5,15.0],
  426. selectTime:null,
  427. reportTimeType:{},
  428. curDate:'',
  429. isAllSelect: false,
  430. approveDialogVisible:false,
  431. deptId:null,
  432. targetUid: null,
  433. membCount:0,
  434. selectState:"-1",
  435. user: JSON.parse(sessionStorage.getItem("user")),
  436. showAddMore:false,
  437. allDate: [],
  438. typeList:['全天','上午','下午'],
  439. date: sessionStorage.msg?sessionStorage.msg.split('-')[0]+"-"+sessionStorage.msg.split('-')[1]:util.formatDate.format(new Date(new Date()), "yyyy-MM"),
  440. choseDay: 0,
  441. tableHeight: 0,
  442. listLoading: false,
  443. projectList: [], //项目列表
  444. reportList: [], //日报列表
  445. reportNames:[], //批量审批列表
  446. dialogVisible: false, //项目弹窗
  447. report: '',
  448. workForm: {
  449. createDate: sessionStorage.msg?sessionStorage.msg:util.formatDate.format(new Date(new Date()), "yyyy-MM-dd"),
  450. domains: [{
  451. id: null,
  452. projectId: "",
  453. workingTime: "",
  454. timeType:0,
  455. content: "",
  456. state: 2,
  457. }],
  458. },
  459. workRules: {
  460. createDate: [{ required: true, message: "请选择工作日期", trigger: "change" }],
  461. },
  462. chooseParticipVisible: false,
  463. logining: false,
  464. isDisable: false,
  465. timeType:[],
  466. deptMembData: [
  467. ],
  468. //部门人员树状结构
  469. data: [
  470. {
  471. id: -1,
  472. label: '全部人员',
  473. membCount:0
  474. },
  475. {
  476. id: 0,
  477. label: '未分配',
  478. }
  479. ],
  480. allData:{},
  481. batchShowData:{},
  482. option: [],
  483. depData: {
  484. id: -1,
  485. label: '全部人员',
  486. },
  487. defaultProps: {
  488. children: 'children',
  489. label: 'label'
  490. },
  491. isNew: false,
  492. selected: false,
  493. valuet: new Date(),
  494. domObj: null,
  495. participator:[],
  496. chosenMembCount:0,
  497. };
  498. },
  499. methods: {
  500. //导出员工每日填报工时数
  501. exportMembWorkHours() {
  502. this.http.post('/report/exportUserDailyWorkTime',{
  503. month: this.date
  504. },
  505. res => {
  506. if (res.code == "ok") {
  507. var url = '/upload/'+res.data;
  508. this.downloadByA("人员每日工时统计.xlxs", url);
  509. }
  510. },
  511. error => {
  512. this.$message({
  513. message: error,
  514. type: "error"
  515. });
  516. }
  517. );
  518. },
  519. downloadByA(name, url) {
  520. const a = document.createElement('a'); // 创建a标签
  521. a.setAttribute('download', name);// download属性
  522. a.setAttribute('href', url);// href链接
  523. a.click();// 自执行点击事件
  524. a.remove();
  525. },
  526. showMonthWorkTime() {
  527. this.monthWorkTimeDialog = true;
  528. this.http.post('/report/getUserDailyWorkTime',{
  529. month: this.date
  530. },
  531. res => {
  532. if (res.code == "ok") {
  533. this.monthWorkData = res.data.list;
  534. console.log('获取到数据:'+this.monthWorkData[0].name+', daytime='+this.reportTimeType.allday);
  535. this.$forceUpdate();
  536. }
  537. },
  538. error => {
  539. this.$message({
  540. message: error,
  541. type: "error"
  542. });
  543. }
  544. );
  545. },
  546. onProgressChange() {
  547. this.$forceUpdate();
  548. },
  549. showChooseMembTree() {
  550. this.chosenMembCount = this.participator.length;
  551. this.chooseParticipVisible = true;
  552. },
  553. onTreeItemChange() {
  554. var chosenList = this.$refs.chooseMembTree.getCheckedNodes();
  555. var list = chosenList.filter(item=>item.isUser == 1);
  556. this.chosenMembCount = list.length;
  557. },
  558. findUserInTree() {
  559. if (this.filterName == '') {
  560. this.deptMembData = this.allMembData;
  561. } else {
  562. var list = this.findRecursively(this.filterName, this.allMembData);
  563. this.deptMembData = list;
  564. }
  565. },
  566. findRecursively(username, list) {
  567. var filterList = [];
  568. for (var i=0;i<list.length; i++) {
  569. if (list[i].isUser == 1) {
  570. if (list[i].label.indexOf(username) >= 0) {
  571. //匹配上了
  572. filterList.push(list[i]);
  573. }
  574. } else if (list[i].children != null && list[i].children.length > 0) {
  575. var subList = this.findRecursively(username, list[i].children);
  576. if (subList.length > 0) {
  577. subList.forEach(s=>filterList.push(s));
  578. }
  579. }
  580. }
  581. return filterList;
  582. },
  583. //确定选择参与人
  584. chooseParticip() {
  585. this.chooseParticipVisible = false;
  586. var chosenList = this.$refs.chooseMembTree.getCheckedNodes();
  587. this.chosenMembList = chosenList.filter(item=>item.isUser == 1);
  588. this.workForm.userNames = '';
  589. this.workForm.userId = [];
  590. this.participator = [];
  591. for (var i=0;i<this.chosenMembList.length; i++) {
  592. this.workForm.userId.push(this.chosenMembList[i].id);
  593. this.workForm.userNames += this.chosenMembList[i].label+',';
  594. var item = {id:this.chosenMembList[i].id, name:this.chosenMembList[i].label};
  595. this.participator.push(item);
  596. }
  597. if (this.workForm.userNames.length > 0) {
  598. this.workForm.userNames = this.workForm.userNames.substring(0, this.workForm.userNames.length-1);
  599. }
  600. },
  601. //微信通知人员填写
  602. weixinNotify() {
  603. if (this.fillMembList.length == 0) return;
  604. var ids = '';
  605. this.fillMembList.forEach(f=>{
  606. ids += f.id+',';
  607. })
  608. this.http.post('/user/pushFillReport',{
  609. ids: ids, date: this.curDate
  610. },
  611. res => {
  612. if (res.code == "ok") {
  613. this.$message({
  614. message: '已发送成功',
  615. type: "success"
  616. });
  617. }
  618. },
  619. error => {
  620. this.$message({
  621. message: error,
  622. type: "error"
  623. });
  624. }
  625. );
  626. },
  627. //导出人员列表
  628. exportMemb() {
  629. if (this.fillMembList.length == 0) return;
  630. var ids = '';
  631. this.fillMembList.forEach(f=>{
  632. ids += f.id+',';
  633. })
  634. this.http.post('/user/exportMembList',{
  635. ids: ids,isFill: this.isFill, date: this.curDate
  636. },
  637. res => {
  638. if (res.code == "ok") {
  639. var aTag = document.createElement('a');
  640. aTag.download = this.curDate+(this.isFill?"已填":"未填")+"人员列表.xls";
  641. aTag.href = res.data;
  642. aTag.click();
  643. }
  644. },
  645. error => {
  646. this.$message({
  647. message: error,
  648. type: "error"
  649. });
  650. }
  651. );
  652. },
  653. showMembList(fill) {
  654. this.membListVisible = true;
  655. if (fill == 0) {
  656. this.fillMembList = this.unFillList;
  657. this.isFill = false;
  658. } else {
  659. this.fillMembList = this.fillList;
  660. this.isFill = true;
  661. }
  662. },
  663. //获取自己填写的日报状态
  664. getReportFillStatus() {
  665. this.http.post('/report/getReportFillStatus',{
  666. startDate: this.date+"-01", endDate: this.date+"-31", userId: this.user.id
  667. },
  668. res => {
  669. if (res.code == "ok") {
  670. this.fillStatusList = res.data;
  671. this.allDate.forEach(d=>{
  672. var fillInfo = null;
  673. d.state = null;
  674. this.fillStatusList.forEach(s=>{
  675. var d1 = s.createDate.split('-')[2];
  676. var d2 = d.date.split('月')[1].split('日')[0];
  677. if (d1.indexOf('0') == 0) {
  678. d1 = d1.substring(1,d1.length);
  679. }
  680. if (d1 == d2) {
  681. d.state = s.state;
  682. }
  683. })
  684. })
  685. this.$forceUpdate();
  686. }
  687. },
  688. error => {
  689. this.$message({
  690. message: error,
  691. type: "error"
  692. });
  693. }
  694. );
  695. },
  696. scrollFunction () {
  697. this.domObj = document.getElementById('clearfix') // 通过id获取要设置的div
  698. if (this.domObj.attachEvent) { // IE
  699. this.domObj.attachEvent('onmousewheel', this.mouseScroll)
  700. } else if (this.domObj.addEventListener) {
  701. this.domObj.addEventListener('DOMMouseScroll', this.mouseScroll, false)
  702. }
  703. this.domObj.onmousewheel = this.domObj.onmousewheel = this.mouseScroll
  704. },
  705. mouseScroll(event) { // google 浏览器下
  706. let detail = event.wheelDelta || event.detail
  707. let moveForwardStep = -1
  708. let moveBackStep = 1
  709. let step = 0
  710. step = detail > 0 ? moveForwardStep * 100 : moveBackStep * 100
  711. event.preventDefault() // 阻止浏览器默认事件
  712. this.domObj.scrollLeft = this.domObj.scrollLeft + step
  713. },
  714. // //左右滚动
  715. // wheel(e){
  716. // var a = document.getElementById("dateScroll");
  717. // var scroll_width = 80; //滚动一下的距离
  718. // var e = e || window.event, v;
  719. // e.wheelDelta ? v=e.wheelDelta : v=e.detail;
  720. // if(v>3||-v>3) v=-v;
  721. // v>0 ? a.scrollLeft+=scroll_width : a.scrollLeft-=scroll_width;
  722. // e.preventDefault(); //阻止浏览器的默认滚动
  723. // },
  724. showExportDialog() {
  725. this.exportDialog = true;
  726. },
  727. changeAllTime() {
  728. //总时长发生改变,自动按比例计算
  729. this.workForm.domains.forEach(d=>{
  730. d.workingTime = (d.progress*this.reportTimeType.allday/100).toFixed(1);
  731. });
  732. },
  733. // 是否加班的单机事件
  734. check() {
  735. this.selected = !this.selected
  736. this.isNew = this.selected
  737. },
  738. //项目选中了, 加载子项目
  739. selectProject(domain, index) {
  740. this.http.post('/sub-project/list',{
  741. projectId: domain.projectId
  742. },
  743. res => {
  744. if (res.code == "ok") {
  745. this.workForm.domains[index].subProjectList = res.data;
  746. this.$forceUpdate();
  747. }
  748. },
  749. error => {
  750. this.$message({
  751. message: error,
  752. type: "error"
  753. });
  754. }
  755. );
  756. //项目相关的近期任务
  757. if (this.user.company.packageProject == 1) {
  758. this.http.post('/task/getRecentTask',{
  759. projectId: domain.projectId
  760. },
  761. res => {
  762. if (res.code == "ok") {
  763. this.workForm.domains[index].taskList = res.data;
  764. this.$forceUpdate();
  765. }
  766. },
  767. error => {
  768. this.$message({
  769. message: error,
  770. type: "error"
  771. });
  772. }
  773. );
  774. }
  775. //获取项目相关专业
  776. if (this.user.company.packageEngineering == 1) {
  777. this.getProjectProfessions(domain, index);
  778. }
  779. },
  780. getProjectProfessions(domain, index) {
  781. this.http.post("/project-profession/getMyProfession", {projectId: domain.projectId},
  782. res => {
  783. if (res.code == "ok") {
  784. this.workForm.domains[index].professionProgress = res.data;
  785. this.$forceUpdate();
  786. }
  787. },
  788. error => {
  789. this.$message({
  790. message: error,
  791. type: "error"
  792. });
  793. });
  794. },
  795. //删除自己的日报
  796. deleteReport() {
  797. this.$confirm("确定要删除该日报吗?","提示", {
  798. confirmButtonText: "确定",
  799. cancelButtonText: "取消",
  800. type: "warning"
  801. })
  802. .then(() => {
  803. this.listLoading = true;
  804. this.http.post('/report/delete',{
  805. userId: this.user.id,
  806. date: this.workForm.createDate
  807. },
  808. res => {
  809. this.listLoading = false;
  810. if (res.code == "ok") {
  811. this.$message({
  812. message: "删除成功",
  813. type: "success"
  814. });
  815. this.getReportList();
  816. this.getDepartment();
  817. this.dialogVisible = false;
  818. } else {
  819. this.$message({
  820. message: res.msg,
  821. type: "error"
  822. });
  823. }
  824. },
  825. error => {
  826. this.listLoading = false;
  827. this.$message({
  828. message: error,
  829. type: "error"
  830. });
  831. }
  832. );
  833. })
  834. .catch(() => {});
  835. },
  836. //提交批量审核数据
  837. submitBatchApprove() {
  838. var data = this.$refs.approveTree.getCheckedNodes();
  839. var ids = '';
  840. if (data.length == 0) {
  841. this.$message({
  842. message: '请选择要审核的人员',
  843. type: "error"
  844. });
  845. return;
  846. }
  847. for (var i=0;i<data.length; i++) {
  848. ids += data[i].id;
  849. if (i < data.length-1) {
  850. ids += ',';
  851. }
  852. }
  853. let day = (this.choseDay+1) > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  854. this.http.post("/report/batchApproveReport", {ids:ids, date:this.date + day},
  855. res => {
  856. if (res.code == "ok") {
  857. this.$message({
  858. message: '审核成功',
  859. type: "success"
  860. });
  861. this.getReportList();
  862. this.getDepartment();
  863. this.approveDialogVisible = false;
  864. } else {
  865. this.$message({
  866. message: res.msg,
  867. type: "error"
  868. });
  869. }
  870. },
  871. error => {
  872. this.$message({
  873. message: error,
  874. type: "error"
  875. });
  876. });
  877. },
  878. selectAll() {
  879. if (this.isAllSelect) {
  880. var keys = [];
  881. this.reportNames.forEach(b=>{
  882. keys.push(b.id);
  883. })
  884. this.$refs.approveTree.setCheckedKeys(keys);
  885. } else {
  886. this.$refs.approveTree.setCheckedKeys([]);
  887. }
  888. },
  889. //批量审核
  890. batchApprove() {
  891. this.approveDialogVisible = true;
  892. this.reportNames = [];
  893. for (var i=0;i<this.reportList.length; i++) {
  894. var report = this.reportList[i];
  895. var hasUnChecked =false;
  896. var id = '';
  897. for (var j=0;j<report.data.length; j++) {
  898. if (report.data[j].state == 0) {
  899. hasUnChecked = true;
  900. id += report.data[j].id+',';
  901. }
  902. }
  903. if (hasUnChecked) {
  904. this.reportNames.push({id:id, label: report.name});
  905. }
  906. }
  907. },
  908. removeEmptyNode(list) {
  909. for (var i=0;i<list.length;i++) {
  910. var cnt = 0;
  911. if (list[i].membCount == 0) {
  912. list.splice(i, 1);
  913. i--;
  914. } else if (list[i].children != null) {
  915. this.removeEmptyNode(list[i].children);
  916. }
  917. }
  918. },
  919. calculateMembCount(list) {
  920. for (var i in list) {
  921. var cnt = 0;
  922. if (list[i].children != null) {
  923. this.calculateMembCount(list[i].children);
  924. for (var m in list[i].children) {
  925. cnt += list[i].children[m].membCount;
  926. }
  927. }
  928. if (list[i].isUser == 1) {
  929. cnt++;
  930. this.membCount++;
  931. }
  932. list[i].membCount = cnt;
  933. }
  934. },
  935. stateChange() {
  936. this.membCount = 0;
  937. if (this.selectState == -1) {
  938. //全部状态
  939. this.data = this.allData;
  940. } else {
  941. //未填报
  942. var newData = JSON.parse(JSON.stringify(this.allData));
  943. this.filterState(this.selectState, newData);
  944. this.data = newData;
  945. }
  946. this.calculateMembCount(this.data);
  947. this.data[0].membCount = this.membCount;//总人数
  948. },
  949. //按状态过滤部门人员
  950. filterState(state, list) {
  951. for (var i =0;i<list.length; i++) {
  952. var obj = list[i];
  953. if (obj.isUser == 1) {
  954. var match = false;
  955. if (state == -2) {
  956. if (obj.state == null) {
  957. match = true;
  958. }
  959. } else {
  960. if (obj.state == state) {
  961. match = true;
  962. }
  963. }
  964. if (!match) {
  965. list.splice(i, 1);
  966. i--;
  967. } else {
  968. }
  969. } else {
  970. if (obj.children != null) {
  971. this.filterState(state, obj.children);
  972. }
  973. }
  974. }
  975. },
  976. // 部门列表点击
  977. handleNodeClick(data) {
  978. this.depData = data;
  979. var list = [];
  980. if (data.id == -1) {
  981. this.deptId = null;
  982. this.targetUid = null;
  983. list = this.data;
  984. } else if (data.isUser == 1) {
  985. this.deptId = null;
  986. this.targetUid = data.id;
  987. } else {
  988. this.deptId = data.id;
  989. this.targetUid = null;
  990. list.push(data);
  991. }
  992. this.getReportList();
  993. if (list.length > 0) {
  994. this.unFillList = this.getUserMembListFromDeptList(list, 0);
  995. this.fillList = this.getUserMembListFromDeptList(list, 1);
  996. }
  997. },
  998. //获取可以选择的代填的人员列表
  999. getSubstitudeUserDeptList() {
  1000. if (this.deptMembData.length == 0) {
  1001. this.http.post("/department/listMyMembs", {},
  1002. res => {
  1003. if (res.code == "ok") {
  1004. let noAllData = JSON.parse(JSON.stringify(res.data));
  1005. if (noAllData.length > 0) {
  1006. if (noAllData[0].label == '全部人员') {
  1007. noAllData.splice(0,1);
  1008. }
  1009. }
  1010. this.setUserToDept(noAllData);
  1011. this.deptMembData = noAllData;
  1012. } else {
  1013. this.$message({
  1014. message: res.msg,
  1015. type: "error"
  1016. });
  1017. }
  1018. },
  1019. error => {
  1020. this.$message({
  1021. message: error,
  1022. type: "error"
  1023. });
  1024. });
  1025. }
  1026. },
  1027. // 获取部门列表
  1028. getDepartment() {
  1029. let day = (this.choseDay+1) > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  1030. var param = {date:this.date + day};
  1031. if (this.user.manageDeptId != 0) {
  1032. param.manageDeptId = this.user.manageDeptId;
  1033. }
  1034. this.http.post("/report/getMembList", param,
  1035. res => {
  1036. if (res.code == "ok") {
  1037. var list = res.data , list1 = JSON.parse(JSON.stringify(res.data));
  1038. // let noAllData = JSON.parse(JSON.stringify(res.data));
  1039. if (this.user.role > 0) {
  1040. list.splice(0,0,{
  1041. id: -1,
  1042. label: '全部人员',
  1043. })
  1044. }
  1045. this.membCount = 0;
  1046. //设置员工到部门下面
  1047. this.setUserToDept(list);
  1048. this.data = list;
  1049. this.allData = list;
  1050. // if (noAllData.length > 0) {
  1051. // if (noAllData[0].label == '全部人员') {
  1052. // noAllData.splice(0,1);
  1053. // }
  1054. // }
  1055. // this.setUserToDept(noAllData);
  1056. // this.deptMembData = noAllData;
  1057. this.option = this.changeArr(list1);
  1058. list[0].membCount = this.membCount;
  1059. if (this.depData.id == -1) {
  1060. this.depData.membCount = this.membCount;
  1061. this.unFillList = this.getUserMembListFromDeptList(this.data, 0);
  1062. this.fillList = this.getUserMembListFromDeptList(this.data, 1);
  1063. } else {
  1064. if (this.depData.isUser == null) {
  1065. var dep = this.findTargetDept(this.data, this.depData.id);
  1066. var membDeptList = [];
  1067. membDeptList.push(dep);
  1068. this.unFillList = this.getUserMembListFromDeptList(membDeptList, 0);
  1069. this.fillList = this.getUserMembListFromDeptList(membDeptList, 1);
  1070. }
  1071. }
  1072. if (this.depData.isUser == null) {
  1073. if (this.isFill) {
  1074. this.fillMembList = this.fillList;
  1075. } else {
  1076. this.fillMembList = this.unFillList;
  1077. }
  1078. }
  1079. } else {
  1080. this.$message({
  1081. message: res.msg,
  1082. type: "error"
  1083. });
  1084. }
  1085. },
  1086. error => {
  1087. this.$message({
  1088. message: error,
  1089. type: "error"
  1090. });
  1091. });
  1092. this.getReportFillStatus();
  1093. },
  1094. findTargetDept(list, deptId) {
  1095. var t = null;
  1096. for (var i=0;i<list.length; i++) {
  1097. if (list[i].isUser == null && list[i].id == deptId) {
  1098. t = list[i];
  1099. break;
  1100. }
  1101. }
  1102. if (t == null) {
  1103. for (var i=0;i<list.length; i++) {
  1104. if (list[i].children != null && list[i].children.length > 0) {
  1105. t = this.findTargetDept(list[i].children, deptId);
  1106. if (t != null) {
  1107. break;
  1108. }
  1109. }
  1110. }
  1111. }
  1112. return t;
  1113. },
  1114. getUserMembListFromDeptList(list, isFill) {
  1115. var membList = [];
  1116. for (var i in list) {
  1117. var deptName = list[i].label;
  1118. if (list[i].userList != null) {
  1119. list[i].userList.forEach(element => {
  1120. if (isFill == 0) {
  1121. //获取未填的
  1122. if (element.state == null) {
  1123. var obj = {id: element.id, label:element.name, deptId:element.departmentId, deptName: deptName};
  1124. membList.push(obj);
  1125. }
  1126. } else {
  1127. if (element.state != null) {
  1128. var obj = {id: element.id, label:element.name, deptId:element.departmentId, deptName: deptName};
  1129. membList.push(obj);
  1130. }
  1131. }
  1132. });
  1133. }
  1134. if (list[i].children != null) {
  1135. membList = membList.concat(this.getUserMembListFromDeptList(list[i].children, isFill));
  1136. }
  1137. }
  1138. return membList;
  1139. },
  1140. setUserToDept(list) {
  1141. for (var i in list) {
  1142. var cnt = 0;
  1143. if (list[i].children != null) {
  1144. this.setUserToDept(list[i].children);
  1145. for (var m in list[i].children) {
  1146. cnt += list[i].children[m].membCount;
  1147. }
  1148. }
  1149. if (list[i].userList != null) {
  1150. if (list[i].children == null) {
  1151. list[i].children = [];
  1152. }
  1153. list[i].userList.forEach(element => {
  1154. var obj = {id: element.id, label:element.name, state:element.state, parentId:element.departmentId, isUser:1};
  1155. list[i].children.push(obj);
  1156. this.membCount++;
  1157. cnt++;
  1158. });
  1159. }
  1160. list[i].membCount = cnt;
  1161. }
  1162. },
  1163. // 修改数组
  1164. changeArr(arr) {
  1165. for (var i = 0; i < arr.length; i++) {
  1166. if(arr[i].id != -1 && arr[i].id != 0) {
  1167. if (arr[i].children != null && arr[i].children.length>0) {
  1168. arr[i].children = this.changeArr(arr[i].children);
  1169. }
  1170. arr[i].id && (arr[i].value = arr[i].id);
  1171. delete arr[i].id;
  1172. }
  1173. }
  1174. for(var i in arr) {
  1175. if(arr[i].id == -1 || arr[i].id == 0) {
  1176. arr.splice(i,1)
  1177. }
  1178. }
  1179. return arr;
  1180. },
  1181. //时间段范围设置改动,监听
  1182. onTimeTypeChange(timeType) {
  1183. this.showAddMore = true;
  1184. for(var i in this.workForm.domains) {
  1185. if (this.workForm.domains[i].timeType == 0) {
  1186. this.showAddMore = false;
  1187. break;
  1188. }
  1189. }
  1190. if (this.showAddMore) {
  1191. //检测数量
  1192. if (this.workForm.domains.length == 2) {
  1193. this.showAddMore = false;
  1194. } else {
  1195. this.showAddMore = true;
  1196. }
  1197. }
  1198. },
  1199. getTimeType() {
  1200. this.http.post('/time-type/getCompanyTimeSetting', { companyId: this.user.companyId},
  1201. res => {
  1202. if (res.code == "ok") {
  1203. var t = res.data;
  1204. this.reportTimeType = t;
  1205. if (this.reportTimeType.type > 0) {
  1206. this.showAddMore = true;
  1207. }
  1208. //转化时间格式
  1209. if (t.allday != null) {
  1210. this.timeType.push({value:0, label:'全天 - '+t.allday+'小时', hours:t.allday});
  1211. }
  1212. if (t.am != null) {
  1213. this.timeType.push({value:1, label:'上午 - '+t.am+'小时', hours: t.am});
  1214. }
  1215. if (t.pm != null) {
  1216. this.timeType.push({value:2, label:'下午 - '+t.pm+'小时', hours: t.pm});
  1217. }
  1218. } else {
  1219. this.$message({
  1220. message: res.msg,
  1221. type: "error"
  1222. });
  1223. }
  1224. },
  1225. error => {
  1226. this.listLoading = false;
  1227. this.$message({
  1228. message: error,
  1229. type: "error"
  1230. });
  1231. });
  1232. },
  1233. // 改变月份
  1234. changeMonthOut() {
  1235. this.getAllDate();
  1236. this.getReportList();
  1237. this.getDepartment();
  1238. },
  1239. // 选择日期
  1240. choseDate(i, item) {
  1241. this.choseDay = i;
  1242. let day = (this.choseDay +1)> 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  1243. sessionStorage.msg = this.date + day,
  1244. this.getReportList();
  1245. this.getDepartment();
  1246. this.curDate = item.date;
  1247. },
  1248. // 获取日期列表
  1249. getAllDate() {
  1250. var dayArry = [];
  1251. var day = this.getCountDays();
  1252. let curMonthDay = null;
  1253. for (var k = 1; k <= day; k++) {
  1254. var str = new Date(this.date.replace(/-/g, "/")+'/01').getMonth() + 1 + "月" + k+'日';
  1255. var showStr = new Date(this.date.replace(/-/g, "/")+'/01').getMonth() + 1+'.'+k;
  1256. if ( new Date(this.date.replace(/-/g, "/")+'/01').getFullYear() == new Date(new Date()).getFullYear() &&
  1257. new Date(this.date.replace(/-/g, "/")+'/01').getMonth() == new Date(new Date()).getMonth()) {
  1258. if(sessionStorage.msg) {
  1259. if(parseInt(sessionStorage.msg.split("-")[2]) == k) {
  1260. this.choseDay = k - 1;
  1261. curMonthDay = str;
  1262. }
  1263. } else {
  1264. if (new Date().getDate() == k) {
  1265. this.choseDay = k - 1;
  1266. }
  1267. }
  1268. } else {
  1269. this.choseDay = 0;
  1270. }
  1271. var curDateStr = (this.date +'-'+ (k<10?('0'+k):k));
  1272. var curDateTime = util.formatDate.parse(curDateStr, 'yyyy-MM-dd');
  1273. dayArry.push({date:str, weekDay:this.weekDay[curDateTime.getDay()], showDate:showStr});
  1274. }
  1275. this.allDate = dayArry;
  1276. //不能超过最大日期
  1277. if (this.choseDay > day-1) {
  1278. this.choseDay = day-1;
  1279. }
  1280. //从消息点击跳转过来的,直接加载指定日期
  1281. if (sessionStorage.from == 1 && sessionStorage.msg) {
  1282. this.curDate = sessionStorage.msg;
  1283. sessionStorage.from = 0;
  1284. } else {
  1285. if (curMonthDay != null) {
  1286. this.curDate = curMonthDay;
  1287. } else {
  1288. var d = new Date(this.date.replace(/-/g, "/")+'/01')
  1289. this.curDate = (d.getMonth()+1)+'月'+d.getDate()+'日';
  1290. }
  1291. }
  1292. this.getReportFillStatus();
  1293. },
  1294. getCountDays() {
  1295. var newstr = this.date.replace(/-/g, "/");
  1296. var curDate = new Date(newstr+'/01');
  1297. var curMonth = curDate.getMonth();
  1298. curDate.setMonth(curMonth + 1);
  1299. curDate.setDate(0);
  1300. return curDate.getDate();
  1301. },
  1302. //获取日报列表
  1303. getReportList() {
  1304. this.listLoading = true;
  1305. let day = (this.choseDay + 1) > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  1306. let param = {date: this.date + day};
  1307. if (this.deptId != null) {
  1308. param.deptId = this.deptId;
  1309. }
  1310. if (this.targetUid != null) {
  1311. param.userId = this.targetUid;
  1312. }
  1313. this.http.post( this.port.report.list, param,
  1314. res => {
  1315. this.listLoading = false;
  1316. if (res.code == "ok") {
  1317. this.reportList = res.data;
  1318. document.querySelector("#day"+this.choseDay).scrollIntoView(true);
  1319. } else {
  1320. this.$message({
  1321. message: res.msg,
  1322. type: "error"
  1323. });
  1324. }
  1325. },
  1326. error => {
  1327. this.listLoading = false;
  1328. this.$message({
  1329. message: error,
  1330. type: "error"
  1331. });
  1332. });
  1333. },
  1334. //导出日报
  1335. exportReport() {
  1336. this.listLoading = true;
  1337. var param = {};
  1338. if (this.exportParam.dateRange != null) {
  1339. param = {startDate:this.exportParam.dateRange[0], endDate: this.exportParam.dateRange[1]};
  1340. }
  1341. if (this.exportParam.projectId != null) {
  1342. param.projectId = this.exportParam.projectId;
  1343. }
  1344. this.http.post( this.port.report.export, param,
  1345. res => {
  1346. this.listLoading = false;
  1347. if (res.code == "ok") {
  1348. location.href = res.data;
  1349. this.exportDialog = false;
  1350. } else {
  1351. this.$message({
  1352. message: res.msg,
  1353. type: "error"
  1354. });
  1355. }
  1356. },
  1357. error => {
  1358. this.listLoading = false;
  1359. this.$message({
  1360. message: error,
  1361. type: "error"
  1362. });
  1363. });
  1364. },
  1365. //获取项目列表
  1366. getProjectList() {
  1367. this.listLoading = true;
  1368. this.http.post( this.port.project.list, {},
  1369. res => {
  1370. this.listLoading = false;
  1371. if (res.code == "ok") {
  1372. this.projectList = res.data;
  1373. } else {
  1374. this.$message({
  1375. message: res.msg,
  1376. type: "error"
  1377. });
  1378. }
  1379. },
  1380. error => {
  1381. this.listLoading = false;
  1382. this.$message({
  1383. message: error,
  1384. type: "error"
  1385. });
  1386. });
  1387. },
  1388. // 获取个人某天的日报
  1389. getReport() {
  1390. this.http.post( this.port.report.getPort, {
  1391. date: this.workForm.createDate
  1392. },
  1393. res => {
  1394. if (res.code == "ok") {
  1395. var list = res.data;
  1396. this.report = list;
  1397. if(list.report.length != 0) {
  1398. var arr = [];
  1399. this.canEdit = false;
  1400. for(var i in list.report) {
  1401. var flg = null
  1402. list.report[i].isOvertime == 1 ? flg = true : flg = false
  1403. arr.push({
  1404. id: list.report[i].id,
  1405. projectId: list.report[i].projectId,
  1406. workingTime: list.report[i].workingTime,
  1407. content: list.report[i].content,
  1408. state: list.report[i].state,
  1409. timeType: list.report[i].timeType,
  1410. subProjectList: list.report[i].subProjectList,
  1411. taskList: list.report[i].taskList,
  1412. subProjectId: list.report[i].subProjectId,
  1413. taskId: list.report[i].taskId,
  1414. // startTime: `Fri May 16 2021 ${list.report[i].startTime}:12 GMT+0800 (中国标准时间)`,
  1415. startTime: list.report[i].startTime,
  1416. // endTime: `Fri May 16 2021 ${list.report[i].endTime}:12 GMT+0800 (中国标准时间)`,
  1417. endTime: list.report[i].endTime,
  1418. isOvertime: flg,
  1419. progress:list.report[i].progress,
  1420. professionProgress: list.report[i].professionProgressList
  1421. })
  1422. if (list.report[i].state >= 2) {
  1423. this.canEdit = true;
  1424. }
  1425. }
  1426. this.workForm = {
  1427. createDate: this.workForm.createDate,
  1428. domains: arr,
  1429. userNames:null,
  1430. userId:null,
  1431. }
  1432. } else {
  1433. this.workForm = {
  1434. createDate: this.workForm.createDate,
  1435. domains: [{
  1436. id: null,
  1437. projectId: "",
  1438. workingTime: this.reportTimeType.type==3?(this.reportTimeType.allday).toFixed(1):"",
  1439. content: "",
  1440. progress:100,
  1441. state: 2,
  1442. timeType:0,
  1443. }],
  1444. userId:null,
  1445. userNames:null,
  1446. }
  1447. this.canEdit = true;
  1448. }
  1449. } else {
  1450. this.$message({
  1451. message: res.msg,
  1452. type: "error"
  1453. });
  1454. }
  1455. },
  1456. error => {
  1457. this.$message({
  1458. message: error,
  1459. type: "error"
  1460. });
  1461. });
  1462. },
  1463. // 打开日报填写
  1464. fillInReport(i, isBatch) {
  1465. if (this.isSubstitude) {
  1466. this.getSubstitudeUserDeptList();
  1467. }
  1468. if(i == -1) {
  1469. this.isDisable = false;
  1470. } else {
  1471. this.isDisable = true;
  1472. }
  1473. let day = (this.choseDay + 1) > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  1474. this.isBatch = isBatch;
  1475. if (this.isBatch == 0) {
  1476. this.workForm.createDate = this.date + day; // 获取个人某天的日报
  1477. this.getReport(i);
  1478. } else {
  1479. this.workForm = {
  1480. createDate: null,//批量填报没有日期
  1481. domains: [{
  1482. id: null,
  1483. projectId: "",
  1484. workingTime: this.reportTimeType.type==3?(this.reportTimeType.allday).toFixed(1):"",
  1485. content: "",
  1486. progress:100,
  1487. state: 2,
  1488. timeType:0,
  1489. }],
  1490. }
  1491. this.canEdit = true;
  1492. }
  1493. this.dialogVisible = true;
  1494. },
  1495. // 添加模块
  1496. addDomain() {
  1497. var leftProgress = 10;
  1498. if (this.reportTimeType.type == 3) {
  1499. //计算已经待分配工时比例
  1500. let array = this.workForm.domains;
  1501. let totalProgress = 0;
  1502. for (var i=0;i<array.length; i++) {
  1503. totalProgress += array[i].progress;
  1504. }
  1505. if (totalProgress < 100) {
  1506. leftProgress = 100 - totalProgress;
  1507. }
  1508. }
  1509. this.workForm.domains.push({
  1510. projectId: "",
  1511. workingTime: this.reportTimeType.type == 3?(leftProgress*this.reportTimeType.allday/100).toFixed(1):"",
  1512. content: "",
  1513. progress:leftProgress,
  1514. state:2,//2-表示待提交
  1515. });
  1516. if (this.reportTimeType.type == 0) {
  1517. //全天上下午模式下,检测时间段数量,达到2个,不能再加了
  1518. var length = this.workForm.domains.length;
  1519. if (length == 2) {
  1520. this.showAddMore = false;
  1521. }
  1522. }
  1523. },
  1524. // 移除模块
  1525. delDomain(i) {
  1526. this.workForm.domains.splice(i,1)
  1527. //检测当前剩下的一个,时间类型是否是全天
  1528. if (this.reportTimeType.type == 0) {
  1529. if (this.workForm.domains[0].timeType == 0) {
  1530. this.showAddMore = false;
  1531. } else {
  1532. this.showAddMore = true;
  1533. }
  1534. }
  1535. },
  1536. // 改变月份
  1537. changeMonth() {
  1538. if (this.isBatch == 0) {
  1539. //只有按天填报才能获取当天的日报
  1540. this.getReport()
  1541. }
  1542. },
  1543. // 保存日报
  1544. submitDepartment() {
  1545. this.$refs.workForm.validate(valid => {
  1546. if (valid) {
  1547. //检查时间,全天和上下午不能同时存在
  1548. if (this.reportTimeType.type == 0) {
  1549. var alldayNum = 0;
  1550. var amNum = 0;
  1551. var pmNum = 0;
  1552. for(var i in this.workForm.domains) {
  1553. if (this.workForm.domains[i].timeType == 0) {
  1554. alldayNum ++;
  1555. } else if (this.workForm.domains[i].timeType == 1) {
  1556. amNum++;
  1557. } else if (this.workForm.domains[i].timeType == 2) {
  1558. pmNum++;
  1559. }
  1560. }
  1561. if (alldayNum > 1) {
  1562. this.$message({
  1563. message: "工作时间-全天,只能选择一次",
  1564. type: "error"
  1565. });
  1566. return;
  1567. }
  1568. if (amNum > 1) {
  1569. this.$message({
  1570. message: "工作时间-上午,只能选择一次",
  1571. type: "error"
  1572. });
  1573. return;
  1574. }
  1575. if (pmNum > 1) {
  1576. this.$message({
  1577. message: "工作时间-下午,只能选择一次",
  1578. type: "error"
  1579. });
  1580. return;
  1581. }
  1582. if (alldayNum == 1 && (amNum > 0 || pmNum > 0)) {
  1583. this.$message({
  1584. message: "工作时间-全天,不能和上下午同时存在",
  1585. type: "error"
  1586. });
  1587. return;
  1588. }
  1589. } else if (this.reportTimeType.type == 3) {
  1590. //总百分比不能超过100%
  1591. let total = 0;
  1592. this.workForm.domains.forEach(w=>{total += w.progress});
  1593. if (total > 100) {
  1594. this.$message({
  1595. message: "用时比例之和不能超过100%",
  1596. type: "error"
  1597. });
  1598. return;
  1599. } else if (total < 100) {
  1600. this.$message({
  1601. message: "工时尚未完全分配,无法提交",
  1602. type: "error"
  1603. });
  1604. return;
  1605. }
  1606. }
  1607. this.listLoading = true;
  1608. let formData = new FormData();
  1609. for(var i in this.workForm.domains) {
  1610. if (this.workForm.domains[i].id != null) {
  1611. formData.append("id", this.workForm.domains[i].id);
  1612. } else {
  1613. formData.append("id", -1);
  1614. }
  1615. formData.append("projectId", this.workForm.domains[i].projectId);
  1616. if (this.workForm.domains[i].subProjectId != null) {
  1617. formData.append("subProjectId", this.workForm.domains[i].subProjectId);
  1618. } else {
  1619. formData.append("subProjectId", 0);
  1620. }
  1621. if (this.workForm.domains[i].taskId != null) {
  1622. formData.append("taskId", this.workForm.domains[i].taskId);
  1623. } else {
  1624. formData.append("taskId", 0);
  1625. }
  1626. formData.append("reportTimeType", this.reportTimeType.type);
  1627. if (this.reportTimeType.type == 0) {
  1628. formData.append("timeType", this.workForm.domains[i].timeType);
  1629. var workingTime = this.timeType.filter(t=>t.value == this.workForm.domains[i].timeType)[0].hours;
  1630. formData.append("workingTime", workingTime);
  1631. } else if (this.reportTimeType.type == 1){
  1632. formData.append("workingTime", this.workForm.domains[i].workingTime);
  1633. } else if (this.reportTimeType.type == 2) {
  1634. formData.append("endTime", this.workForm.domains[i].endTime);
  1635. formData.append("startTime", this.workForm.domains[i].startTime);
  1636. } else if (this.reportTimeType.type == 3) {
  1637. //按比例分配
  1638. formData.append("progress", this.workForm.domains[i].progress);
  1639. formData.append("workingTime", this.workForm.domains[i].workingTime);
  1640. }
  1641. if (this.workForm.domains[i].content == null || this.workForm.domains[i].content == '') {
  1642. formData.append("content", '-');
  1643. } else {
  1644. formData.append("content", this.workForm.domains[i].content);
  1645. }
  1646. if (this.isBatch == 0) {
  1647. formData.append("createDate", this.workForm.createDate);
  1648. } else {
  1649. //批量填报,时间范围
  1650. formData.append("createDate", this.workForm.createDate[0]+'@'+this.workForm.createDate[1]);
  1651. }
  1652. if(this.workForm.domains[i].isOvertime == undefined ) {
  1653. this.workForm.domains[i].isOvertime = '0'
  1654. formData.append("isOvertime", this.workForm.domains[i].isOvertime);
  1655. } else if (this.workForm.domains[i].isOvertime == false){
  1656. this.workForm.domains[i].isOvertime = '0'
  1657. formData.append("isOvertime", this.workForm.domains[i].isOvertime);
  1658. } else {
  1659. this.workForm.domains[i].isOvertime = '1'
  1660. formData.append("isOvertime", this.workForm.domains[i].isOvertime);
  1661. }
  1662. if (this.workForm.userId != null) {
  1663. var targetUids = '';
  1664. this.workForm.userId.forEach(u=>{
  1665. targetUids += u + '@';
  1666. });
  1667. if (targetUids.length > 0) {
  1668. targetUids = targetUids.substring(0, targetUids.length -1);
  1669. formData.append("targetUids", targetUids);
  1670. }
  1671. }
  1672. //项目专业进度
  1673. if (this.workForm.domains[i].professionProgress != null) {
  1674. var m = JSON.stringify(this.workForm.domains[i].professionProgress);
  1675. m = m.replace(/,/g,"@");//replaceAll(',','@');企业微信不兼容replaceAll
  1676. formData.append("professionProgress", m);
  1677. } else {
  1678. formData.append("professionProgress", "[]");
  1679. }
  1680. }
  1681. this.http.uploadFile( this.port.report.editPort, formData,
  1682. res => {
  1683. this.listLoading = false;
  1684. if (res.code == "ok") {
  1685. this.$message({
  1686. message: "填报成功",
  1687. type: "success"
  1688. });
  1689. this.dialogVisible = false;
  1690. this.getReportList();
  1691. this.getDepartment();
  1692. } else {
  1693. this.$message({
  1694. message: res.msg,
  1695. type: "error"
  1696. });
  1697. }
  1698. },
  1699. error => {
  1700. this.listLoading = false;
  1701. this.$message({
  1702. message: error,
  1703. type: "error"
  1704. });
  1705. });
  1706. }
  1707. });
  1708. },
  1709. cli() {
  1710. },
  1711. // 跳转
  1712. junpToDeskTop(id) {
  1713. let day = (this.choseDay + 1) > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  1714. this.$router.push("/desktop/" + id + "/" + this.date +day);
  1715. },
  1716. // 通过日报
  1717. approve(id, item) {
  1718. this.logining = true;
  1719. let day = (this.choseDay + 1) > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  1720. var ids = '';
  1721. var data = item.data;
  1722. data.forEach(element => {
  1723. ids +=(element.id+',');
  1724. });
  1725. this.http.post( this.port.report.approve, {id: id , date: this.date +day, reportIds: ids},
  1726. res => {
  1727. this.logining = false;
  1728. if (res.code == "ok") {
  1729. this.$message({
  1730. message: "审核成功",
  1731. type: "success"
  1732. });
  1733. this.getReportList();
  1734. this.getDepartment();
  1735. } else {
  1736. this.$message({
  1737. message: res.msg,
  1738. type: "error"
  1739. });
  1740. }
  1741. },
  1742. error => {
  1743. this.logining = false;
  1744. this.$message({
  1745. message: error,
  1746. type: "error"
  1747. });
  1748. });
  1749. },
  1750. //撤回日报
  1751. cancel(item) {
  1752. this.logining = true;
  1753. var ids = '';
  1754. var data = item.data;
  1755. data.forEach(element => {
  1756. ids +=(element.id+',');
  1757. });
  1758. this.http.post(this.port.report.cancelReport, {userId: this.user.id, reportIds: ids},
  1759. res => {
  1760. this.logining = false;
  1761. if (res.code == "ok") {
  1762. this.$message({
  1763. message:"撤回成功",
  1764. type: "success"
  1765. });
  1766. this.getReportList();
  1767. this.getDepartment();
  1768. } else {
  1769. this.$message({
  1770. message: res.msg,
  1771. type: "error"
  1772. });
  1773. }
  1774. },
  1775. error => {
  1776. this.logining = false;
  1777. this.$message({
  1778. message: error,
  1779. type: "error"
  1780. });
  1781. });
  1782. },
  1783. // 未通过日报
  1784. deny(id,i, item) {
  1785. this.logining = true;
  1786. let day = (this.choseDay+1) > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  1787. var ids = '';
  1788. var data = item.data;
  1789. data.forEach(element => {
  1790. ids +=(element.id+',');
  1791. });
  1792. this.http.post( this.port.report.deny, {id: id , date: this.date +day, reportIds: ids},
  1793. res => {
  1794. this.logining = false;
  1795. if (res.code == "ok") {
  1796. this.$message({
  1797. message: i==0?"驳回成功":"撤销成功",
  1798. type: "success"
  1799. });
  1800. this.getReportList();
  1801. this.getDepartment();
  1802. } else {
  1803. this.$message({
  1804. message: res.msg,
  1805. type: "error"
  1806. });
  1807. }
  1808. },
  1809. error => {
  1810. this.logining = false;
  1811. this.$message({
  1812. message: error,
  1813. type: "error"
  1814. });
  1815. });
  1816. }
  1817. },
  1818. created() {
  1819. let height = window.innerHeight;
  1820. this.tableHeight = height - 178;
  1821. const that = this;
  1822. window.onresize = function temp() {
  1823. that.tableHeight = window.innerHeight - 178;
  1824. };
  1825. },
  1826. mounted() {
  1827. var now = new Date();
  1828. var t = util.formatDate.format(now, 'yyyy-MM-dd');
  1829. var startStr = util.formatDate.format(new Date(), 'yyyy-MM') + "-01";
  1830. this.exportParam.dateRange = [startStr,t];
  1831. this.getAllDate();
  1832. this.getReportList();
  1833. this.getProjectList();
  1834. this.getTimeType();
  1835. this.getDepartment();
  1836. this.scrollFunction()
  1837. }
  1838. };
  1839. </script>
  1840. <style lang="scss" scoped>
  1841. .waiting {
  1842. color:orange;
  1843. }
  1844. .filledReportStyle {
  1845. color:#32CD32;
  1846. }
  1847. .RejectStyle {
  1848. color:red;
  1849. }
  1850. .allDaily {
  1851. width:82%;
  1852. }
  1853. .report_title {
  1854. padding:10px 0;
  1855. color:#666;
  1856. }
  1857. .clearfix {
  1858. overflow-x: auto;
  1859. white-space: nowrap;
  1860. padding: 15px 0;
  1861. // overflow-y: hidden;
  1862. .date_item {
  1863. padding: 0 3px;
  1864. cursor: pointer;
  1865. }
  1866. .chooseDate {
  1867. color: #20a0ff;
  1868. }
  1869. }
  1870. .one_daily {
  1871. i {
  1872. color: #9ed0ff;
  1873. margin-right: 5px;
  1874. }
  1875. .one_daily_body {
  1876. padding: 15px 0px;
  1877. p {
  1878. margin: 0;
  1879. line-height: 30px;
  1880. }
  1881. }
  1882. ul {
  1883. padding: 0;
  1884. }
  1885. }
  1886. .checkbtn {
  1887. float: right;
  1888. margin-top: -10px;
  1889. }
  1890. </style>
  1891. <style lang="scss">
  1892. .daily {
  1893. .el-card__body {
  1894. height: 80%;
  1895. overflow-y: auto;
  1896. }
  1897. .el-card__header {
  1898. padding: 0 20px;
  1899. }
  1900. }
  1901. </style>
  1902. <style scoped>
  1903. /* 项目标签的样式 */
  1904. .el-tag + .el-tag {
  1905. margin-left: 10px;
  1906. }
  1907. .button-new-tag {
  1908. margin-left: 10px;
  1909. height: 32px;
  1910. line-height: 30px;
  1911. padding-top: 0;
  1912. padding-bottom: 0;
  1913. }
  1914. .input-new-tag {
  1915. width: 90px;
  1916. margin-left: 10px;
  1917. vertical-align: bottom;
  1918. }
  1919. </style>
  1920. <style lang="scss" scoped>
  1921. // 加班样式
  1922. .overtime {
  1923. display: inline-block;
  1924. margin-left: 20px;
  1925. input {
  1926. display: inline-block;
  1927. margin-top: 5px;
  1928. }
  1929. }
  1930. .plus {
  1931. display: inline-block;
  1932. }
  1933. // .tages {
  1934. // float: right;
  1935. // }
  1936. .overtime {
  1937. display: inline-block;
  1938. margin-left: 30px;
  1939. }
  1940. </style>