daily.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  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"
  8. @change="changeMonth()" :clearable="false" type="month" placeholder="选择月份"></el-date-picker>
  9. </el-form-item>
  10. <el-form-item style="float:right;">
  11. <el-link type="primary" :underline="false" v-if="user.role != 0" @click="exportReport">导出日报</el-link>
  12. </el-form-item>
  13. <el-form-item style="float:right;">
  14. <el-link type="primary" :underline="false" @click="fillInReport">填写日报</el-link>
  15. </el-form-item>
  16. </el-form>
  17. </el-col>
  18. <!--列表-->
  19. <div>
  20. <el-card class="box-card daily" shadow="never" :style="'height:'+tableHeight +'px'">
  21. <div slot="header" class="clearfix">
  22. <span>日期:</span>
  23. <span v-for="(item,index) in allDate" :id="'day'+index" :class="index==choseDay?'chooseDate date_item':'date_item'"
  24. @click="choseDate(index)" :key="index">{{item}}</span>
  25. </div>
  26. <div class="allDaily">
  27. <div class="one_daily" v-for="(item1,index1) in reportList" :key="index1">
  28. <i class="fa fa-circle"></i>{{item1.name}}
  29. <span style="margin-left:30px;">
  30. <span style="margin-right:20px;">
  31. <i v-if="parseFloat(item1.reportTime)>parseFloat(item1.calculateTime)+0.5" style="color:red;margin-right:8px;" class="fa fa-exclamation-triangle"></i>
  32. 总填报:
  33. <span :style="parseFloat(item1.reportTime)>parseFloat(item1.calculateTime)+0.5?'color:red':''">{{item1.reportTime}}h</span>
  34. </span>
  35. <el-link v-if="user.role != 0" type="primary" :underline="false" @click="junpToDeskTop(item1.id)">系统智能统计:{{item1.calculateTime}}h</el-link>
  36. <span v-else>系统智能统计:{{item1.calculateTime}}h</span>
  37. </span>
  38. <div class="checkbtn">
  39. <el-button v-if="user.role != 0 && item1.state == 0" type="primary" :loading="logining" size="small" @click="approve(item1.id)">通过</el-button>
  40. <el-button v-if="user.role != 0 && item1.state == 0" type="danger" :loading="logining" size="small" @click="deny(item1.id,0)">驳回</el-button>
  41. <el-button v-if="user.role != 0 && item1.state == 1" type="danger" :loading="logining" size="small" @click="deny(item1.id,1)">撤销</el-button>
  42. </div>
  43. <div class="one_daily_body">
  44. <el-timeline>
  45. <el-timeline-item v-for="(item2,index2) in item1.data" :key="index2">
  46. <el-card shadow="never">
  47. <p>项目:<b>{{item2.project}}</b></p>
  48. <p>时长:{{item2.time}}h</p>
  49. <p>事项:<span v-html="item2.content"></span></p>
  50. </el-card>
  51. </el-timeline-item>
  52. </el-timeline>
  53. </div>
  54. </div>
  55. <!-- 简陋的无报告提示 -->
  56. <span v-if="reportList.length==0">本日暂无报告</span>
  57. </div>
  58. </el-card>
  59. </div>
  60. <!-- 项目管理的dialog -->
  61. <el-dialog title="填写日报" :visible.sync="dialogVisible" width="60%">
  62. <el-form ref="workForm" :model="workForm" :rules="workRules" label-width="100px">
  63. <el-form-item label="工作日期" prop="createDate">
  64. <el-date-picker v-model="workForm.createDate" :editable="false" format="yyyy-MM-dd" value-format="yyyy-MM-dd"
  65. @change="changeMonth()" :clearable="false" type="date" placeholder="选择工作日期"></el-date-picker>
  66. </el-form-item>
  67. <el-form-item label="待分配时长" prop="name">
  68. <span>{{report.time}}h</span>
  69. <el-link type="primary" :underline="false" @click="addDomain" style="margin-left:40px">添加项目</el-link>
  70. </el-form-item>
  71. <div v-for="(domain, index) in workForm.domains" :key="domain.id">
  72. <el-form-item label="投入项目" :prop="'domains.' + index + '.projectId'"
  73. :rules="{ required: true, message: '请选择投入项目', trigger: ['change','blur'] }">
  74. <el-select v-model="domain.projectId" placeholder="请选择" style="width:200px;"
  75. :disabled="workForm.domains.length==0?true:(workForm.domains[0].state==2?false:true)">
  76. <el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id"></el-option>
  77. </el-select>
  78. <el-link v-if="index >= 1" type="primary" :underline="false" @click="delDomain(index)" style="float:right;margin-right:10px;"
  79. :disabled="workForm.domains.length==0?true:(workForm.domains[0].state==2?false:true)">
  80. <i class="fa fa-trash" style="color: red;;font-size:18px;"></i>
  81. </el-link>
  82. </el-form-item>
  83. <el-form-item label="投入时长" :prop="'domains.' + index + '.workingTime'"
  84. :rules="{ required: true, message: '请输入投入时长', trigger: 'blur' }">
  85. <el-input v-model.number="domain.workingTime" placeholder="请输入投入时长" type='number' clearable style="width:200px;"
  86. :disabled="workForm.domains.length==0?true:(workForm.domains[0].state==2?false:true)"></el-input>
  87. </el-form-item>
  88. <el-form-item label="工作事项" :prop="'domains.' + index + '.content'" :rules="{ required: true, message: '请输入工作事项', trigger: 'blur' }">
  89. <el-input v-model="domain.content" type="textarea" :rows="4" placeholder="请输入投入时长" clearable
  90. :disabled="workForm.domains.length==0?true:(workForm.domains[0].state==2?false:true)"></el-input>
  91. </el-form-item>
  92. <el-divider v-if="workForm.domains.length>1"></el-divider>
  93. </div>
  94. </el-form>
  95. <span slot="footer" class="dialog-footer">
  96. <el-button @click="dialogVisible = false">取消</el-button>
  97. <el-button type="primary" @click="submitDepartment"
  98. :disabled="workForm.domains.length==0?true:(workForm.domains[0].state==2?false:true)" >提交</el-button>
  99. </span>
  100. </el-dialog>
  101. </section>
  102. </template>
  103. <script>
  104. import util from "../../common/js/util";
  105. export default {
  106. data() {
  107. return {
  108. user: JSON.parse(sessionStorage.getItem("user")),
  109. allDate: [],
  110. date: util.formatDate.format(new Date(new Date()), "yyyy-MM"),
  111. choseDay: 0,
  112. tableHeight: 0,
  113. listLoading: false,
  114. projectList: [], //项目列表
  115. reportList: [], //日报列表
  116. dialogVisible: false, //项目弹窗
  117. report: '',
  118. workForm: {
  119. createDate: util.formatDate.format(new Date(new Date()), "yyyy-MM-dd"),
  120. domains: [{
  121. id: null,
  122. projectId: "",
  123. workingTime: "",
  124. content: "",
  125. state: 2,
  126. }],
  127. },
  128. workRules: {
  129. createDate: [{ required: true, message: "请选择工作日期", trigger: "change" }],
  130. },
  131. logining: false,
  132. };
  133. },
  134. methods: {
  135. // 改变月份
  136. changeMonth() {
  137. this.getAllDate();
  138. this.getReportList();
  139. },
  140. // 选择日期
  141. choseDate(i) {
  142. this.choseDay = i;
  143. this.getReportList();
  144. },
  145. // 获取日期列表
  146. getAllDate() {
  147. var dayArry = [];
  148. var day = this.getCountDays();
  149. for (var k = 1; k <= day; k++) {
  150. var str = new Date(this.date.replace(/-/g, "/")).getMonth() + 1 + "月" + k + "日";
  151. if ( new Date(this.date.replace(/-/g, "/")).getFullYear() == new Date(new Date()).getFullYear() &&
  152. new Date(this.date.replace(/-/g, "/")).getMonth() == new Date(new Date()).getMonth()) {
  153. if (new Date().getDate() == k) {
  154. this.choseDay = k - 1;
  155. }
  156. } else {
  157. this.choseDay = 0;
  158. }
  159. dayArry.push(str);
  160. }
  161. this.allDate = dayArry;
  162. },
  163. getCountDays() {
  164. var newstr = this.date.replace(/-/g, "/");
  165. var curDate = new Date(newstr);
  166. var curMonth = curDate.getMonth();
  167. curDate.setMonth(curMonth + 1);
  168. curDate.setDate(0);
  169. return curDate.getDate();
  170. },
  171. //获取日报列表
  172. getReportList() {
  173. this.listLoading = true;
  174. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  175. this.http.post( this.port.report.list, { date: this.date + day },
  176. res => {
  177. this.listLoading = false;
  178. if (res.code == "ok") {
  179. this.reportList = res.data;
  180. document.querySelector("#day"+this.choseDay).scrollIntoView(true);
  181. } else {
  182. this.$message({
  183. message: res.msg,
  184. type: "error"
  185. });
  186. }
  187. },
  188. error => {
  189. this.listLoading = false;
  190. this.$message({
  191. message: error,
  192. type: "error"
  193. });
  194. });
  195. },
  196. //导出日报
  197. exportReport() {
  198. if (this.reportList.length > 0) {
  199. this.listLoading = true;
  200. //首先处理日期
  201. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  202. this.http.post( this.port.report.export, { date: this.date + day },
  203. res => {
  204. this.listLoading = false;
  205. if (res.code == "ok") {
  206. location.href = res.data;
  207. } else {
  208. this.$message({
  209. message: res.msg,
  210. type: "error"
  211. });
  212. }
  213. },
  214. error => {
  215. this.listLoading = false;
  216. this.$message({
  217. message: error,
  218. type: "error"
  219. });
  220. });
  221. } else {
  222. this.$message({
  223. message: "当天没有报告 无法导出",
  224. type: "info"
  225. });
  226. }
  227. },
  228. //获取项目列表
  229. getProjectList() {
  230. this.listLoading = true;
  231. this.http.post( this.port.project.list, {},
  232. res => {
  233. this.listLoading = false;
  234. if (res.code == "ok") {
  235. this.projectList = res.data;
  236. } else {
  237. this.$message({
  238. message: res.msg,
  239. type: "error"
  240. });
  241. }
  242. },
  243. error => {
  244. this.listLoading = false;
  245. this.$message({
  246. message: error,
  247. type: "error"
  248. });
  249. });
  250. },
  251. // 获取个人某天的日报
  252. getReport() {
  253. this.http.post( this.port.report.getPort, {
  254. date: this.workForm.createDate
  255. },
  256. res => {
  257. if (res.code == "ok") {
  258. var list = res.data;
  259. this.report = list;
  260. if(list.report.length != 0) {
  261. var arr = [];
  262. for(var i in list.report) {
  263. arr.push({
  264. id: list.report[i].id,
  265. projectId: list.report[i].projectId,
  266. workingTime: list.report[i].workingTime,
  267. content: list.report[i].content,
  268. state: list.report[i].state
  269. })
  270. }
  271. this.workForm = {
  272. createDate: this.workForm.createDate,
  273. domains: arr,
  274. }
  275. } else {
  276. this.workForm = {
  277. createDate: this.workForm.createDate,
  278. domains: [{
  279. id: null,
  280. projectId: "",
  281. workingTime: "",
  282. content: "",
  283. state: 2,
  284. }],
  285. }
  286. }
  287. console.log(this.workForm)
  288. } else {
  289. this.$message({
  290. message: res.msg,
  291. type: "error"
  292. });
  293. }
  294. },
  295. error => {
  296. this.$message({
  297. message: error,
  298. type: "error"
  299. });
  300. });
  301. },
  302. // 打开日报填写
  303. fillInReport() {
  304. this.getReport();
  305. this.dialogVisible = true;
  306. },
  307. // 添加模块
  308. addDomain() {
  309. this.workForm.domains.push({
  310. projectId: "",
  311. workingTime: "",
  312. content: ""
  313. });
  314. },
  315. // 移除模块
  316. delDomain(i) {
  317. this.workForm.domains.splice(i,1)
  318. },
  319. // 改变月份
  320. changeMonth() {
  321. this.getReport()
  322. },
  323. // 保存日报
  324. submitDepartment() {
  325. this.$refs.workForm.validate(valid => {
  326. if (valid) {
  327. this.listLoading = true;
  328. let formData = new FormData();
  329. for(var i in this.workForm.domains) {
  330. if (this.workForm.domains[i].id != null) {
  331. formData.append("id", this.workForm.domains[i].id);
  332. } else {
  333. formData.append("id", -1);
  334. }
  335. formData.append("projectId", this.workForm.domains[i].projectId);
  336. formData.append("workingTime", this.workForm.domains[i].workingTime);
  337. formData.append("content", this.workForm.domains[i].content);
  338. formData.append("createDate", this.workForm.createDate);
  339. }
  340. this.http.uploadFile( this.port.report.editPort, formData,
  341. res => {
  342. this.listLoading = false;
  343. if (res.code == "ok") {
  344. this.$message({
  345. message: "填报成功",
  346. type: "success"
  347. });
  348. this.dialogVisible = false;
  349. this.getReportList();
  350. } else {
  351. this.$message({
  352. message: res.msg,
  353. type: "error"
  354. });
  355. }
  356. },
  357. error => {
  358. this.listLoading = false;
  359. this.$message({
  360. message: error,
  361. type: "error"
  362. });
  363. });
  364. }
  365. });
  366. },
  367. // 跳转
  368. junpToDeskTop(id) {
  369. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  370. this.$router.push("/desktop/" + id + "/" + this.date +day);
  371. },
  372. // 通过日报
  373. approve(id) {
  374. this.logining = true;
  375. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  376. this.http.post( this.port.report.approve, {id: id , date: this.date +day},
  377. res => {
  378. this.logining = false;
  379. if (res.code == "ok") {
  380. this.$message({
  381. message: "审核成功",
  382. type: "success"
  383. });
  384. this.getReportList();
  385. } else {
  386. this.$message({
  387. message: res.msg,
  388. type: "error"
  389. });
  390. }
  391. },
  392. error => {
  393. this.logining = false;
  394. this.$message({
  395. message: error,
  396. type: "error"
  397. });
  398. });
  399. },
  400. // 未通过日报
  401. deny(id,i) {
  402. this.logining = true;
  403. let day = this.choseDay > 9 ? "-" + (this.choseDay + 1) : "-0" + (this.choseDay + 1);
  404. this.http.post( this.port.report.deny, {id: id , date: this.date +day},
  405. res => {
  406. this.logining = false;
  407. if (res.code == "ok") {
  408. this.$message({
  409. message: i==0?"驳回成功":"撤销成功",
  410. type: "success"
  411. });
  412. this.getReportList();
  413. } else {
  414. this.$message({
  415. message: res.msg,
  416. type: "error"
  417. });
  418. }
  419. },
  420. error => {
  421. this.logining = false;
  422. this.$message({
  423. message: error,
  424. type: "error"
  425. });
  426. });
  427. }
  428. },
  429. created() {
  430. let height = window.innerHeight;
  431. this.tableHeight = height - 150;
  432. const that = this;
  433. window.onresize = function temp() {
  434. that.tableHeight = window.innerHeight - 150;
  435. };
  436. },
  437. mounted() {
  438. this.getAllDate();
  439. this.getReportList();
  440. this.getProjectList();
  441. }
  442. };
  443. </script>
  444. <style lang="scss" scoped>
  445. .clearfix {
  446. overflow-x: auto;
  447. white-space: nowrap;
  448. padding: 15px 0;
  449. .date_item {
  450. padding: 0 15px;
  451. cursor: pointer;
  452. }
  453. .chooseDate {
  454. color: #20a0ff;
  455. }
  456. }
  457. .one_daily {
  458. i {
  459. color: #9ed0ff;
  460. margin-right: 5px;
  461. }
  462. .one_daily_body {
  463. padding: 15px 0px;
  464. p {
  465. margin: 0;
  466. line-height: 30px;
  467. }
  468. }
  469. ul {
  470. padding: 0;
  471. }
  472. }
  473. .checkbtn {
  474. float: right;
  475. margin-top: -10px;
  476. }
  477. </style>
  478. <style lang="scss">
  479. .daily {
  480. .el-card__body {
  481. height: 82%;
  482. overflow-y: auto;
  483. }
  484. .el-card__header {
  485. padding: 0 20px;
  486. }
  487. }
  488. </style>
  489. <style scoped>
  490. /* 项目标签的样式 */
  491. .el-tag + .el-tag {
  492. margin-left: 10px;
  493. }
  494. .button-new-tag {
  495. margin-left: 10px;
  496. height: 32px;
  497. line-height: 30px;
  498. padding-top: 0;
  499. padding-bottom: 0;
  500. }
  501. .input-new-tag {
  502. width: 90px;
  503. margin-left: 10px;
  504. vertical-align: bottom;
  505. }
  506. </style>