daily.vue 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262
  1. <template>
  2. <section>
  3. <!--工具条-->
  4. <!-- <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
  5. <el-form :inline="true">
  6. <el-form-item>
  7. <el-date-picker v-model="date" :editable="false" format="yyyy-MM" value-format="yyyy-MM" @change="changeMonthOut" :clearable="false" type="month" placeholder="选择月份"></el-date-picker>
  8. </el-form-item>
  9. </el-form>
  10. </el-col> -->
  11. <!--列表-->
  12. <div>
  13. <el-card class="box-card daily" shadow="never" >
  14. <div slot="header" class="clearfix">
  15. <el-date-picker size="small" v-model="date" :editable="false" format="yyyy-MM" value-format="yyyy-MM" @change="changeMonthOut" :clearable="false" type="month" placeholder="选择月份"></el-date-picker>
  16. <span >
  17. <span>日期:</span>
  18. <span v-for="(item,index) in allDate" :id="'day'+index" :class="index==choseDay?'chooseDate date_item':'date_item'"
  19. @click="choseDate(index, item)" :key="index">{{item}}</span>
  20. </span>
  21. </div>
  22. <div style="display:flex;">
  23. <div v-if="user.role > 0">
  24. <div>
  25. <el-select v-model="selectState" size="small" @change="stateChange">
  26. <el-option value="-1" label="全部状态" >全部状态</el-option>
  27. <el-option value="-2" label="未填报">未填报</el-option>
  28. <el-option value="1" label="已通过">已通过</el-option>
  29. <el-option value="0" label="待审核">待审核</el-option>
  30. <el-option value="2" label="不通过">不通过</el-option>
  31. <el-option value="3" label="已撤回">已撤回</el-option>
  32. </el-select></div>
  33. <div>
  34. <el-tree :data="data" @node-click="handleNodeClick" >
  35. <span class="custom-tree-node" slot-scope="{ node, data}">
  36. <span>{{ node.label }}</span>
  37. <span v-if="data.membCount != null && data.isUser == null">({{data.membCount}})</span>
  38. <div style="width:0%;float:right;">
  39. <span v-if="data.isUser == 1 && data.state == null" style="color:red;">
  40. 未填报
  41. </span>
  42. <span v-if="data.isUser == 1 && data.state == 0" style="color:orange;">
  43. 待审核
  44. </span>
  45. <span v-if="data.isUser == 1 && data.state == 1" style="color:green;">
  46. 已通过
  47. </span>
  48. <span v-if="data.isUser == 1 && data.state == 2" style="color:red;">
  49. 未通过
  50. </span>
  51. <span v-if="data.isUser == 1 && data.state == 3" style="color:red;">
  52. 已撤回
  53. </span>
  54. </div>
  55. </span>
  56. </el-tree>
  57. </div>
  58. </div>
  59. <div :style="'height:'+tableHeight+'px;width:0.5px;background:#eee;margin-right:10px;margin-left:10px;'" ></div>
  60. <div class="allDaily" style="float:left;flex-grow:1">
  61. <!--系统管理员 -->
  62. <div class="report_title" v-if="user.role > 0">
  63. <span>工作日报 | {{depData.label}}</span> - 已填写<span style="margin-left:5px;margin-right:5px;color:green;">{{reportList.length}}</span>人,
  64. 未填写<span style="margin-left:5px;margin-right:5px;color:red;">{{(depData == null?data[0].membCount:(depData.isUser == 1?1:depData.membCount))-reportList.length}}</span>人
  65. <span style="float:right;">
  66. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="fillInReport(-1)">填写日报</el-link>
  67. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="exportReport">导出日报</el-link>
  68. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="batchApprove">批量审核</el-link>
  69. </span>
  70. </div>
  71. <!--普通员工,含项目经理 -->
  72. <div class="report_title" v-if="user.role==0"><span>日报列表</span>
  73. <span style="float:right;" v-if="user.role==0">
  74. <el-link type="primary" style="margin-right:10px;" :underline="false" @click="fillInReport(-1)">填写日报</el-link>
  75. <el-link type="primary" v-if="user.leader" style="margin-right:10px;" :underline="false" @click="batchApprove">批量审核</el-link>
  76. </span>
  77. </div>
  78. <div :style="'height:'+(tableHeight-50)+'px;overflow:scroll;padding-top:10px;'">
  79. <div class="one_daily" v-for="(item1,index1) in reportList" :key="index1">
  80. <i class="fa fa-circle"></i>{{item1.name}}
  81. <span style="margin-left:30px;">
  82. <span style="margin-right:20px;">
  83. <!-- <i v-if="parseFloat(item1.reportTime)>parseFloat(item1.calculateTime)+0.5" style="color:red;margin-right:8px;" class="fa fa-exclamation-triangle"></i> -->
  84. 工作总时长:
  85. <!-- <span :style="parseFloat(item1.reportTime)>parseFloat(item1.calculateTime)+0.5?'color:red':''">{{item1.reportTime}}h</span> -->
  86. <span >{{item1.reportTime}}</span>h
  87. <span style="margin-left:10px;">成本:</span>
  88. <span >{{item1.cost}}</span>元
  89. </span>
  90. </span>
  91. <div class="checkbtn">
  92. <el-button v-if="(user.role != 0 || user.id == item1.data[0].inchargerId) && item1.state == 0" type="primary" :loading="logining" size="small" @click="approve(item1.id, item1)">通过</el-button>
  93. <el-button v-if="(user.role != 0 || user.id == item1.data[0].inchargerId) && item1.state == 0" type="danger" :loading="logining" size="small" @click="deny(item1.id,0, item1)">驳回</el-button>
  94. <!--自己可以撤回待审核状态的报告 -->
  95. <el-button v-if="(user.id == item1.id) && item1.state == 0" type="normal" :loading="logining" size="small" @click="cancel(item1)">撤回</el-button>
  96. <el-button v-if="(user.role != 0 || user.id == item1.data[0].inchargerId) && item1.state == 1" type="normal" :loading="logining" size="small" @click="deny(item1.id,1, item1)">撤销</el-button>
  97. <el-button v-if="item1.state >= 2 && user.id == item1.id" type="primary" size="small" @click="fillInReport(index1)">编辑日报</el-button>
  98. </div>
  99. <div class="one_daily_body">
  100. <el-timeline>
  101. <el-timeline-item v-for="(item2,index2) in item1.data" :key="index2">
  102. <el-card shadow="never">
  103. <p>项目:<b>{{item2.project}}</b><span v-if="item2.subProjectName != null"> / {{item2.subProjectName}}</span>
  104. <span style="margin-left:15px;color:#DAA520;" v-if="item2.state == 0">[ 待审核 ]</span>
  105. <span style="margin-left:15px;color:#32CD32;" v-else-if="item2.state == 1">[ 已通过 ]</span>
  106. <span style="margin-left:15px;color:#FF0000;" v-else-if="item2.state == 2">[ 已驳回 ]</span>
  107. <span style="margin-left:15px;color:#FF0000;" v-else-if="item2.state == 3">[ 已撤回 ]</span>
  108. </p>
  109. <p>时长:
  110. <span v-if="item2.reportTimeType == 0" style="margin-right:10px;">{{typeList[item2.timeType]}}</span>
  111. <span v-if="item2.reportTimeType == 2" style="margin-right:10px;">{{item2.startTime+'-'+item2.endTime}}</span>
  112. {{item2.time.toFixed(1)}}h
  113. </p>
  114. <p>事项:<span v-html="item2.content"></span></p>
  115. </el-card>
  116. </el-timeline-item>
  117. </el-timeline>
  118. </div>
  119. </div>
  120. <!-- 简陋的无报告提示 -->
  121. <div v-if="reportList.length==0" style="width:100%;font-size:17px;text-align:center;color:#aaa;">{{curDate}}暂无报告</div>
  122. </div>
  123. </div>
  124. </div>
  125. </el-card>
  126. </div>
  127. <!-- 填写日报的dialog -->
  128. <el-dialog title="填写日报" :visible.sync="dialogVisible" width="60%">
  129. <el-form ref="workForm" :model="workForm" :rules="workRules" label-width="100px">
  130. <el-form-item label="工作日期" prop="createDate">
  131. <el-date-picker v-model="workForm.createDate" :editable="false" format="yyyy-MM-dd" value-format="yyyy-MM-dd"
  132. @change="changeMonth()" :clearable="false" type="date" placeholder="选择工作日期" :disabled="isDisable"></el-date-picker>
  133. </el-form-item>
  134. <!-- <el-form-item label="待分配时长" prop="name">
  135. <span>{{report.time}}h</span>
  136. <el-link type="primary" :underline="false" @click="addDomain" style="margin-left:40px">添加项目</el-link>
  137. </el-form-item> -->
  138. <div v-for="(domain, index) in workForm.domains" :key="domain.id">
  139. <el-form-item label="工作时长" :prop="'domains.' + index + '.timeType'"
  140. :rules="{ required: true, message: '请选择工作时长', trigger: 'blur' }">
  141. <!-- <el-input v-model.number="domain.workingTime" placeholder="请输入投入时长" type='number' clearable style="width:200px;"
  142. :disabled="workForm.domains.length==0?true:(workForm.domains[0].state==2?false:true)"></el-input> -->
  143. <!-- 全天/上下午 -->
  144. <el-select v-model="domain.timeType"
  145. v-if="reportTimeType.type == 0"
  146. placeholder="请选择工作时长"
  147. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
  148. @change="onTimeTypeChange(domain.timeType)">
  149. <el-option
  150. v-for="item in timeType"
  151. :key="item.value"
  152. :label="item.label"
  153. :value="item.value">
  154. </el-option>
  155. </el-select>
  156. <!-- 数字时长选择 -->
  157. <el-select v-model="domain.workingTime"
  158. v-if="reportTimeType.type == 1"
  159. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
  160. placeholder="请选择工作时长" >
  161. <el-option v-for="item in timeRange" :key="item" :value="item.toFixed(1)">{{item.toFixed(1)}}</el-option>
  162. </el-select>
  163. <span v-if="reportTimeType.type == 1">小时</span>
  164. <span v-if="reportTimeType.type == 2">
  165. <!--时间范围选择 -->
  166. <el-time-select
  167. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
  168. placeholder="起始时间"
  169. style="width:120px;"
  170. v-model="domain.startTime"
  171. :picker-options="{
  172. start: '08:00',
  173. step: '00:30',
  174. end: '23:30'
  175. }">
  176. </el-time-select> - <el-time-select
  177. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
  178. placeholder="结束时间"
  179. style="width:120px;"
  180. v-model="domain.endTime"
  181. :picker-options="{
  182. start: '08:00',
  183. step: '00:30',
  184. end: '23:30',
  185. minTime: domain.startTime
  186. }">
  187. </el-time-select>
  188. </span>
  189. </el-form-item>
  190. <el-form-item label="投入项目" :prop="'domains.' + index + '.projectId'"
  191. :rules="{ required: true, message: '请选择投入项目', trigger: ['change','blur'] }">
  192. <el-select v-model="domain.projectId" placeholder="请选择" style="width:200px;" clearable="true" @change="selectProject(domain, index)"
  193. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)">
  194. <el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id"></el-option>
  195. </el-select>
  196. <!--子项目 -->
  197. <el-select v-model="domain.subProjectId" placeholder="请选择" style="width:200px;" clearable="true" v-if="domain.subProjectList != null && domain.subProjectList.length> 0"
  198. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)">
  199. <el-option v-for="item in domain.subProjectList" :key="item.id" :label="item.name" :value="item.id"></el-option>
  200. </el-select>
  201. <el-link v-if="index >= 1" type="primary" :underline="false" @click="delDomain(index)" style="float:right;margin-right:10px;"
  202. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)">
  203. <i class="fa fa-trash" style="color: red;;font-size:18px;"></i>
  204. </el-link>
  205. </el-form-item>
  206. <el-form-item label="工作事项" :prop="'domains.' + index + '.content'" >
  207. <el-input v-model="domain.content" type="textarea" :rows="4" placeholder="请填写工作事项" clearable
  208. :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"></el-input>
  209. </el-form-item>
  210. <el-divider v-if="workForm.domains.length>1"></el-divider>
  211. </div>
  212. <el-link v-if="showAddMore" type="primary" :underline="false" @click="addDomain" style="margin-left:40px">添加更多</el-link>
  213. </el-form>
  214. <span slot="footer" class="dialog-footer">
  215. <el-button @click="deleteReport" v-if="workForm.domains[0].id != null">删除</el-button>
  216. <el-button @click="dialogVisible = false">取消</el-button>
  217. <el-button type="primary" @click="submitDepartment"
  218. :disabled="workForm.domains.length==0?true:(canEdit?false:true)" >提交</el-button>
  219. </span>
  220. </el-dialog>
  221. <!-- 批量日报审核 -->
  222. <el-dialog title="批量日报审核" :visible.sync="approveDialogVisible" width="500px">
  223. <el-checkbox v-model="isAllSelect" label="全选" style="margin-left:24px;" @change="selectAll" v-if="reportNames.length > 0"></el-checkbox>
  224. <el-tree ref="approveTree" node-key="id" :data="reportNames" show-checkbox="true" @check-change="handleCheckChange" >
  225. </el-tree>
  226. <span slot="footer" class="dialog-footer">
  227. <el-button @click="approveDialogVisible = false">取消</el-button>
  228. <el-button type="primary" @click="submitBatchApprove" :disabled="batchShowData.length == 0">审核通过</el-button>
  229. </span>
  230. </el-dialog>
  231. </section>
  232. </template>
  233. <script>
  234. import util from "../../common/js/util";
  235. export default {
  236. data() {
  237. return {
  238. subProjectList:[],
  239. canEdit: true,
  240. 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.5,13.0,13.5,14.0,14.5,15.0],
  241. selectTime:null,
  242. reportTimeType:{},
  243. curDate:'',
  244. isAllSelect: false,
  245. approveDialogVisible:false,
  246. deptId:null,
  247. targetUid: null,
  248. membCount:0,
  249. selectState:"-1",
  250. user: JSON.parse(sessionStorage.getItem("user")),
  251. showAddMore:false,
  252. allDate: [],
  253. typeList:['全天','上午','下午'],
  254. date: sessionStorage.msg?sessionStorage.msg.split('-')[0]+"-"+sessionStorage.msg.split('-')[1]:util.formatDate.format(new Date(new Date()), "yyyy-MM"),
  255. choseDay: 0,
  256. tableHeight: 0,
  257. listLoading: false,
  258. projectList: [], //项目列表
  259. reportList: [], //日报列表
  260. reportNames:[], //批量审批列表
  261. dialogVisible: false, //项目弹窗
  262. report: '',
  263. workForm: {
  264. createDate: sessionStorage.msg?sessionStorage.msg:util.formatDate.format(new Date(new Date()), "yyyy-MM-dd"),
  265. domains: [{
  266. id: null,
  267. projectId: "",
  268. workingTime: "",
  269. timeType:0,
  270. content: "",
  271. state: 2,
  272. }],
  273. },
  274. workRules: {
  275. createDate: [{ required: true, message: "请选择工作日期", trigger: "change" }],
  276. },
  277. logining: false,
  278. isDisable: false,
  279. timeType:[],
  280. //部门人员树状结构
  281. data: [
  282. {
  283. id: -1,
  284. label: '全部人员',
  285. membCount:0
  286. },
  287. {
  288. id: 0,
  289. label: '未分配',
  290. }
  291. ],
  292. allData:{},
  293. batchShowData:{},
  294. option: [],
  295. depData: {
  296. id: -1,
  297. label: '全部人员',
  298. },
  299. defaultProps: {
  300. children: 'children',
  301. label: 'label'
  302. },
  303. };
  304. },
  305. methods: {
  306. //项目选中了, 加载子项目
  307. selectProject(domain, index) {
  308. this.http.post('/sub-project/list',{
  309. projectId: domain.projectId
  310. },
  311. res => {
  312. if (res.code == "ok") {
  313. this.workForm.domains[index].subProjectList = res.data;
  314. // domain.subProjectList = res.data;
  315. // console.log(domain.subProjectList);
  316. this.$forceUpdate();
  317. }
  318. },
  319. error => {
  320. this.listLoading = false;
  321. this.$message({
  322. message: error,
  323. type: "error"
  324. });
  325. }
  326. );
  327. },
  328. //删除自己的日报
  329. deleteReport() {
  330. this.$confirm("确定要删除该日报吗?","提示", {
  331. confirmButtonText: "确定",
  332. cancelButtonText: "取消",
  333. type: "warning"
  334. })
  335. .then(() => {
  336. this.listLoading = true;
  337. this.http.post('/report/delete',{
  338. userId: this.user.id,
  339. date: this.workForm.createDate
  340. },
  341. res => {
  342. this.listLoading = false;
  343. if (res.code == "ok") {
  344. this.$message({
  345. message: "删除成功",
  346. type: "success"
  347. });
  348. this.getReportList();
  349. this.getDepartment();
  350. this.dialogVisible = false;
  351. } else {
  352. this.$message({
  353. message: res.msg,
  354. type: "error"
  355. });
  356. }
  357. },
  358. error => {
  359. this.listLoading = false;
  360. this.$message({
  361. message: error,
  362. type: "error"
  363. });
  364. }
  365. );
  366. })
  367. .catch(() => {});
  368. },
  369. //提交批量审核数据
  370. submitBatchApprove() {
  371. console.log(this.$refs.approveTree.getCheckedNodes());
  372. var data = this.$refs.approveTree.getCheckedNodes();
  373. var ids = '';
  374. if (data.length == 0) {
  375. this.$message({
  376. message: '请选择要审核的人员',
  377. type: "error"
  378. });
  379. return;
  380. }
  381. for (var i=0;i<data.length; i++) {
  382. ids += data[i].id;
  383. if (i < data.length-1) {
  384. ids += ',';
  385. }
  386. }
  387. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  388. console.log('ids==='+ids);
  389. this.http.post("/report/batchApproveReport", {ids:ids, date:this.date + day},
  390. res => {
  391. if (res.code == "ok") {
  392. this.$message({
  393. message: '审核成功',
  394. type: "success"
  395. });
  396. this.getReportList();
  397. this.getDepartment();
  398. this.approveDialogVisible = false;
  399. } else {
  400. this.$message({
  401. message: res.msg,
  402. type: "error"
  403. });
  404. }
  405. },
  406. error => {
  407. this.$message({
  408. message: error,
  409. type: "error"
  410. });
  411. });
  412. },
  413. selectAll() {
  414. if (this.isAllSelect) {
  415. var keys = [];
  416. this.reportNames.forEach(b=>{
  417. keys.push(b.id);
  418. })
  419. this.$refs.approveTree.setCheckedKeys(keys);
  420. } else {
  421. this.$refs.approveTree.setCheckedKeys([]);
  422. }
  423. },
  424. //批量审核
  425. batchApprove() {
  426. this.approveDialogVisible = true;
  427. console.log(this.allData);
  428. this.reportNames = [];
  429. for (var i=0;i<this.reportList.length; i++) {
  430. var report = this.reportList[i];
  431. var hasUnChecked =false;
  432. var id = '';
  433. for (var j=0;j<report.data.length; j++) {
  434. if (report.data[j].state == 0) {
  435. hasUnChecked = true;
  436. id += report.data[j].id+',';
  437. }
  438. }
  439. if (hasUnChecked) {
  440. this.reportNames.push({id:id, label: report.name});
  441. }
  442. }
  443. },
  444. removeEmptyNode(list) {
  445. for (var i=0;i<list.length;i++) {
  446. var cnt = 0;
  447. if (list[i].membCount == 0) {
  448. list.splice(i, 1);
  449. i--;
  450. } else if (list[i].children != null) {
  451. this.removeEmptyNode(list[i].children);
  452. }
  453. }
  454. },
  455. calculateMembCount(list) {
  456. for (var i in list) {
  457. var cnt = 0;
  458. if (list[i].children != null) {
  459. this.calculateMembCount(list[i].children);
  460. for (var m in list[i].children) {
  461. cnt += list[i].children[m].membCount;
  462. }
  463. }
  464. if (list[i].isUser == 1) {
  465. cnt++;
  466. this.membCount++;
  467. }
  468. list[i].membCount = cnt;
  469. }
  470. },
  471. stateChange() {
  472. this.membCount = 0;
  473. if (this.selectState == -1) {
  474. //全部状态
  475. this.data = this.allData;
  476. } else {
  477. //未填报
  478. var newData = JSON.parse(JSON.stringify(this.allData));
  479. this.filterState(this.selectState, newData);
  480. this.data = newData;
  481. }
  482. this.calculateMembCount(this.data);
  483. this.data[0].membCount = this.membCount;//总人数
  484. },
  485. //按状态过滤部门人员
  486. filterState(state, list) {
  487. for (var i =0;i<list.length; i++) {
  488. var obj = list[i];
  489. if (obj.isUser == 1) {
  490. var match = false;
  491. if (state == -2) {
  492. if (obj.state == null) {
  493. match = true;
  494. }
  495. } else {
  496. if (obj.state == state) {
  497. match = true;
  498. }
  499. }
  500. if (!match) {
  501. console.log("不匹配,删除="+obj.label+', state='+obj.state);
  502. list.splice(i, 1);
  503. i--;
  504. } else {
  505. console.log("匹配"+obj.label);
  506. }
  507. } else {
  508. if (obj.children != null) {
  509. this.filterState(state, obj.children);
  510. }
  511. }
  512. }
  513. },
  514. // 部门列表点击
  515. handleNodeClick(data) {
  516. console.log(data);
  517. // if(this.depData == null || data.id != this.depData.id) {
  518. // this.depData = data;
  519. // //this.getUser();
  520. // }
  521. this.depData = data;
  522. if (data.id == -1) {
  523. this.deptId = null;
  524. this.targetUid = null;
  525. } else if (data.isUser == 1) {
  526. this.deptId = null;
  527. this.targetUid = data.id;
  528. } else {
  529. this.deptId = data.id;
  530. this.targetUid = null;
  531. }
  532. this.getReportList();
  533. },
  534. // 获取部门列表
  535. getDepartment() {
  536. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  537. this.http.post("/report/getMembList", {date:this.date + day},
  538. res => {
  539. if (res.code == "ok") {
  540. var list = res.data , list1 = JSON.parse(JSON.stringify(res.data));
  541. list.splice(0,0,{
  542. id: -1,
  543. label: '全部人员',
  544. })
  545. list.push({
  546. id: 0,
  547. label: '未分配',
  548. })
  549. this.membCount = 0;
  550. //设置员工到部门下面
  551. this.setUserToDept(list);
  552. this.data = list;
  553. this.allData = list;
  554. this.option = this.changeArr(list1);
  555. list[0].membCount = this.membCount;
  556. if (this.depData.id == -1) {
  557. this.depData.membCount = this.membCount;
  558. }
  559. } else {
  560. this.$message({
  561. message: res.msg,
  562. type: "error"
  563. });
  564. }
  565. },
  566. error => {
  567. this.$message({
  568. message: error,
  569. type: "error"
  570. });
  571. });
  572. },
  573. setUserToDept(list) {
  574. for (var i in list) {
  575. var cnt = 0;
  576. if (list[i].children != null) {
  577. this.setUserToDept(list[i].children);
  578. for (var m in list[i].children) {
  579. cnt += list[i].children[m].membCount;
  580. }
  581. }
  582. if (list[i].userList != null) {
  583. if (list[i].children == null) {
  584. list[i].children = [];
  585. }
  586. list[i].userList.forEach(element => {
  587. var obj = {id: element.id, label:element.name, state:element.state, parentId:element.departmentId, isUser:1};
  588. list[i].children.push(obj);
  589. this.membCount++;
  590. cnt++;
  591. });
  592. }
  593. list[i].membCount = cnt;
  594. }
  595. },
  596. // 修改数组
  597. changeArr(arr) {
  598. for (var i = 0; i < arr.length; i++) {
  599. if(arr[i].id != -1 && arr[i].id != 0) {
  600. if (arr[i].children != null && arr[i].children.length>0) {
  601. arr[i].children = this.changeArr(arr[i].children);
  602. }
  603. arr[i].id && (arr[i].value = arr[i].id);
  604. delete arr[i].id;
  605. }
  606. }
  607. for(var i in arr) {
  608. if(arr[i].id == -1 || arr[i].id == 0) {
  609. arr.splice(i,1)
  610. }
  611. }
  612. return arr;
  613. },
  614. //时间段范围设置改动,监听
  615. onTimeTypeChange(timeType) {
  616. this.showAddMore = true;
  617. console.log("======" + timeType);
  618. for(var i in this.workForm.domains) {
  619. if (this.workForm.domains[i].timeType == 0) {
  620. this.showAddMore = false;
  621. break;
  622. }
  623. }
  624. if (this.showAddMore) {
  625. //检测数量
  626. if (this.workForm.domains.length == 2) {
  627. this.showAddMore = false;
  628. } else {
  629. this.showAddMore = true;
  630. }
  631. }
  632. },
  633. getTimeType() {
  634. this.http.post('/time-type/getCompanyTimeSetting', { companyId: this.user.companyId},
  635. res => {
  636. if (res.code == "ok") {
  637. var t = res.data;
  638. this.reportTimeType = t;
  639. if (this.reportTimeType.type > 0) {
  640. this.showAddMore = true;
  641. }
  642. //转化时间格式
  643. if (t.allday != null) {
  644. this.timeType.push({value:0, label:'全天 - '+t.allday+'小时', hours:t.allday});
  645. }
  646. if (t.am != null) {
  647. this.timeType.push({value:1, label:'上午 - '+t.am+'小时', hours: t.am});
  648. }
  649. if (t.pm != null) {
  650. this.timeType.push({value:2, label:'下午 - '+t.pm+'小时', hours: t.pm});
  651. }
  652. } else {
  653. this.$message({
  654. message: res.msg,
  655. type: "error"
  656. });
  657. }
  658. },
  659. error => {
  660. this.listLoading = false;
  661. this.$message({
  662. message: error,
  663. type: "error"
  664. });
  665. });
  666. },
  667. // 改变月份
  668. changeMonthOut() {
  669. console.log(sessionStorage.msg)
  670. this.getAllDate();
  671. this.getReportList();
  672. this.getDepartment();
  673. },
  674. // 选择日期
  675. choseDate(i, item) {
  676. this.choseDay = i;
  677. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  678. sessionStorage.msg = this.date + day,
  679. this.getReportList();
  680. this.getDepartment();
  681. this.curDate = item;
  682. },
  683. // 获取日期列表
  684. getAllDate() {
  685. var dayArry = [];
  686. var day = this.getCountDays();
  687. for (var k = 1; k <= day; k++) {
  688. var str = new Date(this.date.replace(/-/g, "/")).getMonth() + 1 + "月" + k + "日";
  689. if ( new Date(this.date.replace(/-/g, "/")).getFullYear() == new Date(new Date()).getFullYear() &&
  690. new Date(this.date.replace(/-/g, "/")).getMonth() == new Date(new Date()).getMonth()) {
  691. if(sessionStorage.msg) {
  692. if(parseInt(sessionStorage.msg.split("-")[2]) == k) {
  693. this.choseDay = k - 1;
  694. }
  695. } else {
  696. if (new Date().getDate() == k) {
  697. this.choseDay = k - 1;
  698. }
  699. }
  700. } else {
  701. this.choseDay = 0;
  702. }
  703. dayArry.push(str);
  704. }
  705. this.allDate = dayArry;
  706. if (sessionStorage.msg) {
  707. this.curDate = sessionStorage.msg;
  708. }
  709. },
  710. getCountDays() {
  711. var newstr = this.date.replace(/-/g, "/");
  712. var curDate = new Date(newstr);
  713. var curMonth = curDate.getMonth();
  714. curDate.setMonth(curMonth + 1);
  715. curDate.setDate(0);
  716. return curDate.getDate();
  717. },
  718. //获取日报列表
  719. getReportList() {
  720. this.listLoading = true;
  721. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  722. let param = {date: this.date + day};
  723. if (this.deptId != null) {
  724. param.deptId = this.deptId;
  725. }
  726. if (this.targetUid != null) {
  727. param.userId = this.targetUid;
  728. }
  729. this.http.post( this.port.report.list, param,
  730. res => {
  731. this.listLoading = false;
  732. if (res.code == "ok") {
  733. this.reportList = res.data;
  734. document.querySelector("#day"+this.choseDay).scrollIntoView(true);
  735. } else {
  736. this.$message({
  737. message: res.msg,
  738. type: "error"
  739. });
  740. }
  741. },
  742. error => {
  743. this.listLoading = false;
  744. this.$message({
  745. message: error,
  746. type: "error"
  747. });
  748. });
  749. },
  750. //导出日报
  751. exportReport() {
  752. if (this.reportList.length > 0) {
  753. this.listLoading = true;
  754. //首先处理日期
  755. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  756. this.http.post( this.port.report.export, { date: this.date + day },
  757. res => {
  758. this.listLoading = false;
  759. if (res.code == "ok") {
  760. location.href = res.data;
  761. } else {
  762. this.$message({
  763. message: res.msg,
  764. type: "error"
  765. });
  766. }
  767. },
  768. error => {
  769. this.listLoading = false;
  770. this.$message({
  771. message: error,
  772. type: "error"
  773. });
  774. });
  775. } else {
  776. this.$message({
  777. message: "当天没有报告 无法导出",
  778. type: "info"
  779. });
  780. }
  781. },
  782. //获取项目列表
  783. getProjectList() {
  784. this.listLoading = true;
  785. this.http.post( this.port.project.list, {},
  786. res => {
  787. this.listLoading = false;
  788. if (res.code == "ok") {
  789. this.projectList = res.data;
  790. } else {
  791. this.$message({
  792. message: res.msg,
  793. type: "error"
  794. });
  795. }
  796. },
  797. error => {
  798. this.listLoading = false;
  799. this.$message({
  800. message: error,
  801. type: "error"
  802. });
  803. });
  804. },
  805. // 获取个人某天的日报
  806. getReport(i) {
  807. this.http.post( this.port.report.getPort, {
  808. date: this.workForm.createDate
  809. },
  810. res => {
  811. if (res.code == "ok") {
  812. var list = res.data;
  813. this.report = list;
  814. if(list.report.length != 0) {
  815. var arr = [];
  816. this.canEdit = false;
  817. for(var i in list.report) {
  818. arr.push({
  819. id: list.report[i].id,
  820. projectId: list.report[i].projectId,
  821. workingTime: list.report[i].workingTime,
  822. content: list.report[i].content,
  823. state: list.report[i].state,
  824. timeType: list.report[i].timeType
  825. })
  826. if (list.report[i].state >= 2) {
  827. this.canEdit = true;
  828. }
  829. }
  830. this.workForm = {
  831. createDate: this.workForm.createDate,
  832. domains: arr,
  833. }
  834. } else {
  835. this.workForm = {
  836. createDate: this.workForm.createDate,
  837. domains: [{
  838. id: null,
  839. projectId: "",
  840. workingTime: "",
  841. content: "",
  842. state: 2,
  843. timeType:0,
  844. }],
  845. }
  846. this.canEdit = true;
  847. }
  848. } else {
  849. this.$message({
  850. message: res.msg,
  851. type: "error"
  852. });
  853. }
  854. },
  855. error => {
  856. this.$message({
  857. message: error,
  858. type: "error"
  859. });
  860. });
  861. },
  862. // 打开日报填写
  863. fillInReport(i) {
  864. if(i == -1) {
  865. this.isDisable = false;
  866. } else {
  867. this.isDisable = true;
  868. }
  869. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  870. this.workForm.createDate = this.date + day;
  871. this.getReport(i);
  872. this.dialogVisible = true;
  873. },
  874. // 添加模块
  875. addDomain() {
  876. this.workForm.domains.push({
  877. projectId: "",
  878. workingTime: "",
  879. content: "",
  880. state:2,//2-表示待提交
  881. });
  882. if (this.reportTimeType.type == 0) {
  883. //全天上下午模式下,检测时间段数量,达到2个,不能再加了
  884. var length = this.workForm.domains.length;
  885. if (length == 2) {
  886. this.showAddMore = false;
  887. }
  888. }
  889. },
  890. // 移除模块
  891. delDomain(i) {
  892. this.workForm.domains.splice(i,1)
  893. //检测当前剩下的一个,时间类型是否是全天
  894. if (this.reportTimeType.type == 0) {
  895. if (this.workForm.domains[0].timeType == 0) {
  896. this.showAddMore = false;
  897. } else {
  898. this.showAddMore = true;
  899. }
  900. }
  901. },
  902. // 改变月份
  903. changeMonth() {
  904. this.getReport()
  905. },
  906. // 保存日报
  907. submitDepartment() {
  908. this.$refs.workForm.validate(valid => {
  909. if (valid) {
  910. //检查时间,全天和上下午不能同时存在
  911. if (this.reportTimeType.type == 0) {
  912. var alldayNum = 0;
  913. var amNum = 0;
  914. var pmNum = 0;
  915. for(var i in this.workForm.domains) {
  916. if (this.workForm.domains[i].timeType == 0) {
  917. alldayNum ++;
  918. } else if (this.workForm.domains[i].timeType == 1) {
  919. amNum++;
  920. } else if (this.workForm.domains[i].timeType == 2) {
  921. pmNum++;
  922. }
  923. }
  924. if (alldayNum > 1) {
  925. this.$message({
  926. message: "工作时间-全天,只能选择一次",
  927. type: "error"
  928. });
  929. return;
  930. }
  931. if (amNum > 1) {
  932. this.$message({
  933. message: "工作时间-上午,只能选择一次",
  934. type: "error"
  935. });
  936. return;
  937. }
  938. if (pmNum > 1) {
  939. this.$message({
  940. message: "工作时间-下午,只能选择一次",
  941. type: "error"
  942. });
  943. return;
  944. }
  945. if (alldayNum == 1 && (amNum > 0 || pmNum > 0)) {
  946. this.$message({
  947. message: "工作时间-全天,不能和上下午同时存在",
  948. type: "error"
  949. });
  950. return;
  951. }
  952. }
  953. this.listLoading = true;
  954. let formData = new FormData();
  955. for(var i in this.workForm.domains) {
  956. if (this.workForm.domains[i].id != null) {
  957. formData.append("id", this.workForm.domains[i].id);
  958. } else {
  959. formData.append("id", -1);
  960. }
  961. formData.append("projectId", this.workForm.domains[i].projectId);
  962. if (this.workForm.domains[i].subProjectId != null) {
  963. formData.append("subProjectId", this.workForm.domains[i].subProjectId);
  964. } else {
  965. formData.append("subProjectId", 0);
  966. }
  967. formData.append("reportTimeType", this.reportTimeType.type);
  968. if (this.reportTimeType.type == 0) {
  969. formData.append("timeType", this.workForm.domains[i].timeType);
  970. var workingTime = this.timeType.filter(t=>t.value == this.workForm.domains[i].timeType)[0].hours;
  971. formData.append("workingTime", workingTime);
  972. } else if (this.reportTimeType.type == 1){
  973. formData.append("workingTime", this.workForm.domains[i].workingTime);
  974. } else if (this.reportTimeType.type == 2) {
  975. formData.append("startTime", this.workForm.domains[i].startTime);
  976. formData.append("endTime", this.workForm.domains[i].endTime);
  977. }
  978. if (this.workForm.domains[i].content == null || this.workForm.domains[i].content == '') {
  979. formData.append("content", '-');
  980. } else {
  981. formData.append("content", this.workForm.domains[i].content);
  982. }
  983. formData.append("createDate", this.workForm.createDate);
  984. }
  985. this.http.uploadFile( this.port.report.editPort, formData,
  986. res => {
  987. this.listLoading = false;
  988. if (res.code == "ok") {
  989. this.$message({
  990. message: "填报成功",
  991. type: "success"
  992. });
  993. this.dialogVisible = false;
  994. this.getReportList();
  995. this.getDepartment();
  996. } else {
  997. this.$message({
  998. message: res.msg,
  999. type: "error"
  1000. });
  1001. }
  1002. },
  1003. error => {
  1004. this.listLoading = false;
  1005. this.$message({
  1006. message: error,
  1007. type: "error"
  1008. });
  1009. });
  1010. }
  1011. });
  1012. },
  1013. // 跳转
  1014. junpToDeskTop(id) {
  1015. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  1016. this.$router.push("/desktop/" + id + "/" + this.date +day);
  1017. },
  1018. // 通过日报
  1019. approve(id, item) {
  1020. this.logining = true;
  1021. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  1022. var ids = '';
  1023. var data = item.data;
  1024. data.forEach(element => {
  1025. ids +=(element.id+',');
  1026. });
  1027. this.http.post( this.port.report.approve, {id: id , date: this.date +day, reportIds: ids},
  1028. res => {
  1029. this.logining = false;
  1030. if (res.code == "ok") {
  1031. this.$message({
  1032. message: "审核成功",
  1033. type: "success"
  1034. });
  1035. this.getReportList();
  1036. this.getDepartment();
  1037. } else {
  1038. this.$message({
  1039. message: res.msg,
  1040. type: "error"
  1041. });
  1042. }
  1043. },
  1044. error => {
  1045. this.logining = false;
  1046. this.$message({
  1047. message: error,
  1048. type: "error"
  1049. });
  1050. });
  1051. },
  1052. //撤回日报
  1053. cancel(item) {
  1054. this.logining = true;
  1055. var ids = '';
  1056. var data = item.data;
  1057. data.forEach(element => {
  1058. ids +=(element.id+',');
  1059. });
  1060. this.http.post(this.port.report.cancelReport, {userId: this.user.id, reportIds: ids},
  1061. res => {
  1062. this.logining = false;
  1063. if (res.code == "ok") {
  1064. this.$message({
  1065. message:"撤回成功",
  1066. type: "success"
  1067. });
  1068. this.getReportList();
  1069. this.getDepartment();
  1070. } else {
  1071. this.$message({
  1072. message: res.msg,
  1073. type: "error"
  1074. });
  1075. }
  1076. },
  1077. error => {
  1078. this.logining = false;
  1079. this.$message({
  1080. message: error,
  1081. type: "error"
  1082. });
  1083. });
  1084. },
  1085. // 未通过日报
  1086. deny(id,i, item) {
  1087. this.logining = true;
  1088. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  1089. var ids = '';
  1090. var data = item.data;
  1091. data.forEach(element => {
  1092. ids +=(element.id+',');
  1093. });
  1094. this.http.post( this.port.report.deny, {id: id , date: this.date +day, reportIds: ids},
  1095. res => {
  1096. this.logining = false;
  1097. if (res.code == "ok") {
  1098. this.$message({
  1099. message: i==0?"驳回成功":"撤销成功",
  1100. type: "success"
  1101. });
  1102. this.getReportList();
  1103. this.getDepartment();
  1104. } else {
  1105. this.$message({
  1106. message: res.msg,
  1107. type: "error"
  1108. });
  1109. }
  1110. },
  1111. error => {
  1112. this.logining = false;
  1113. this.$message({
  1114. message: error,
  1115. type: "error"
  1116. });
  1117. });
  1118. }
  1119. },
  1120. created() {
  1121. let height = window.innerHeight;
  1122. console.log('window inner height=='+height)
  1123. this.tableHeight = height - 153;
  1124. const that = this;
  1125. window.onresize = function temp() {
  1126. that.tableHeight = window.innerHeight - 153;
  1127. };
  1128. },
  1129. mounted() {
  1130. this.getAllDate();
  1131. this.getReportList();
  1132. this.getProjectList();
  1133. this.getTimeType();
  1134. this.getDepartment();
  1135. }
  1136. };
  1137. </script>
  1138. <style lang="scss" scoped>
  1139. .allDaily {
  1140. width:82%;
  1141. }
  1142. .report_title {
  1143. padding:10px 0;
  1144. }
  1145. .clearfix {
  1146. overflow-x: auto;
  1147. white-space: nowrap;
  1148. padding: 15px 0;
  1149. .date_item {
  1150. padding: 0 15px;
  1151. cursor: pointer;
  1152. }
  1153. .chooseDate {
  1154. color: #20a0ff;
  1155. }
  1156. }
  1157. .one_daily {
  1158. i {
  1159. color: #9ed0ff;
  1160. margin-right: 5px;
  1161. }
  1162. .one_daily_body {
  1163. padding: 15px 0px;
  1164. p {
  1165. margin: 0;
  1166. line-height: 30px;
  1167. }
  1168. }
  1169. ul {
  1170. padding: 0;
  1171. }
  1172. }
  1173. .checkbtn {
  1174. float: right;
  1175. margin-top: -10px;
  1176. }
  1177. </style>
  1178. <style lang="scss">
  1179. .daily {
  1180. .el-card__body {
  1181. height: 80%;
  1182. overflow-y: auto;
  1183. }
  1184. .el-card__header {
  1185. padding: 0 20px;
  1186. }
  1187. }
  1188. </style>
  1189. <style scoped>
  1190. /* 项目标签的样式 */
  1191. .el-tag + .el-tag {
  1192. margin-left: 10px;
  1193. }
  1194. .button-new-tag {
  1195. margin-left: 10px;
  1196. height: 32px;
  1197. line-height: 30px;
  1198. padding-top: 0;
  1199. padding-bottom: 0;
  1200. }
  1201. .input-new-tag {
  1202. width: 90px;
  1203. margin-left: 10px;
  1204. vertical-align: bottom;
  1205. }
  1206. </style>