daily.vue 103 KB

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