weeklyCustomization.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. <template>
  2. <div class='weeklyCustomization'>
  3. <div class="title">
  4. <el-button @click="getCurrentWeek(-7)" size="small">&lt;&lt;</el-button>
  5. <el-button @click="getCurrentWeek(0)" size="small">本周</el-button>
  6. <el-button @click="getCurrentWeek(7)" size="small">&gt;&gt;</el-button>
  7. </div>
  8. <div class="weekcen flexColumn" v-loading="submitLoading">
  9. <div class="flexColumnAuto flex1">
  10. <el-table :data="weekTableData" border style="width: 100%;" height="0" :span-method="arraySpanMethod">
  11. <el-table-column prop="dateTime" label="日期" width="180">
  12. <template slot-scope="scope">
  13. <span>{{ scope.row.dateTime }}</span>
  14. (<span>{{ scope.row.weekDayTxt }}</span>)
  15. </template>
  16. </el-table-column>
  17. <el-table-column label="项目" width="220">
  18. <template slot-scope="scope">
  19. <el-select v-model="scope.row.projectId" size="small" placeholder="请选择项目" clearable
  20. @change="changeProject(scope.row.projectId, scope.$index)" :disabled="scope.row.state == 1">
  21. <el-option v-for="item in projectList" :key="item.id" :label="item.projectName"
  22. :value="item.id">
  23. </el-option>
  24. </el-select>
  25. </template>
  26. </el-table-column>
  27. <el-table-column label="分类" width="180">
  28. <template slot-scope="scope">
  29. <el-select v-model="scope.row.groupId" size="small" placeholder="请选择分类"
  30. @change="changeGroup(scope.row.groupId, scope.row.taskGroups, scope.$index)"
  31. :disabled="scope.row.state == 1">
  32. <el-option v-for="item in scope.row.taskGroups" :key="item.id" :label="item.name"
  33. :value="item.id">
  34. </el-option>
  35. </el-select>
  36. </template>
  37. </el-table-column>
  38. <el-table-column prop="content" label="工作内容" width="300">
  39. <template slot-scope="scope">
  40. <el-input size="small" type="textarea" :rows="1" v-model="scope.row.content"
  41. :disabled="scope.row.state == 1"></el-input>
  42. </template>
  43. </el-table-column>
  44. <el-table-column prop="workingTime" label="时间(小时)" width="160">
  45. <template slot-scope="scope">
  46. <el-input-number size="small" v-model="scope.row.workingTime" :min="0" :max="12" :step="0.5"
  47. :disabled="scope.row.state == 1"></el-input-number>
  48. </template>
  49. </el-table-column>
  50. <el-table-column prop="projectAuditorId" label="审批人" width="160">
  51. <template slot-scope="scope">
  52. <!-- <span v-if="user.userNameNeedTranslate != '1'">{{ scope.row.projectAuditorName }}</span>
  53. <span v-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName'
  54. :openid='scope.row.projectAuditorName'></ww-open-data></span> -->
  55. <span v-if="user.userNameNeedTranslate != '1'">{{ auditorNameFun(scope.row) }}</span>
  56. <span v-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName'
  57. :openid='scope.row.projectAuditorName'></ww-open-data></span>
  58. </template>
  59. </el-table-column>
  60. <el-table-column prop="state" label="状态" width="140" fixed="right">
  61. <template slot-scope="scope">
  62. <div class="controls">
  63. <el-tag v-if="scope.row.state == 0" type="warning">待审</el-tag>
  64. <el-tag v-if="scope.row.state == 1" type="success">通过</el-tag>
  65. <el-tag v-if="scope.row.state == 2" type="danger">拒绝</el-tag>
  66. <span v-if="scope.row.state != 1">
  67. <el-link type="primary" :underline="false" class="el-icon-circle-plus-outline"
  68. @click="insertRow(scope.$index)"></el-link>
  69. <el-link type="primary" :underline="false" class="el-icon-delete"
  70. @click="deleteRow(scope.$index)"></el-link>
  71. </span>
  72. </div>
  73. </template>
  74. </el-table-column>
  75. </el-table>
  76. </div>
  77. <div class="weeklyCustomization_btn">
  78. <el-button @click="handleClose()">取消</el-button>
  79. <el-button @click="submitWeekData(1)">暂存</el-button>
  80. <el-button type="primary" @click="submitWeekData(0)">确定</el-button>
  81. </div>
  82. </div>
  83. </div>
  84. </template>
  85. <script>
  86. import cloneDeep from 'lodash/cloneDeep'; // 深拷贝
  87. export default {
  88. name: '',
  89. components: {},
  90. props: {
  91. weekParentData: {
  92. type: Object,
  93. default: () => {
  94. return {}
  95. }
  96. },
  97. },
  98. data() {
  99. return {
  100. weekTableData: [],
  101. projectList: [],
  102. nowTime: this.dayjs().format('YYYY-MM-DD'),
  103. submitLoading: false,
  104. permissions: JSON.parse(sessionStorage.getItem("permissions")),
  105. user: JSON.parse(sessionStorage.getItem("user")),
  106. }
  107. },
  108. computed: {},
  109. watch: {},
  110. created() { },
  111. mounted() {
  112. this.$set(this, 'weekTableData', [])
  113. this.getCurrentWeek(0)
  114. this.getProjectList()
  115. },
  116. methods: {
  117. // 提交与暂存
  118. submitWeekData(draft) { // draft 暂存(1)提交(0)
  119. const newWeekData = cloneDeep(this.weekTableData)
  120. let strArr = this.judgmentData(newWeekData)
  121. console.log(strArr, '<===== strArr')
  122. if (strArr.length > 0) {
  123. this.$message({
  124. message: `【${strArr.join('、')}】日期填写工作时长小于系统设置的每日工作时长`,
  125. type: "error"
  126. });
  127. return
  128. }
  129. let formData = new FormData();
  130. formData.append("draft", draft);
  131. let fixation = {
  132. id: -1,
  133. projectId: '',
  134. subProjectId: 0,
  135. taskId: 0,
  136. reportTimeType: 1,
  137. workingTime: 0,
  138. multiWorktime: 0,
  139. content: '',
  140. isOvertime: 0,
  141. // professionProgress: [],
  142. groupId: '',
  143. stage: '',
  144. createDate: '',
  145. projectAuditorId: '',
  146. basecostId: 0,
  147. degreeId: -1,
  148. customData: 0,
  149. customText: '-',
  150. }
  151. const arr = newWeekData
  152. .filter(data => data.projectId)
  153. .map(data => ({
  154. ...fixation,
  155. projectId: data.projectId,
  156. createDate: data.dateTime,
  157. content: data.content,
  158. projectAuditorId: data.projectAuditorId,
  159. workingTime: data.workingTime,
  160. groupId: data.groupId,
  161. id: data.id || -1,
  162. }));
  163. arr.forEach(item => {
  164. Object.entries(item).forEach(([key, value]) => {
  165. formData.append(key, value);
  166. });
  167. });
  168. this.submitLoading = true
  169. this.http.uploadFile(this.port.report.editPort, formData,
  170. res => {
  171. this.submitLoading = false
  172. if (res.code == "ok") {
  173. this.$message({
  174. message: `${draft ? '暂存成功:' : '提交成功:'}`,
  175. type: "success"
  176. });
  177. this.$emit('weekClose')
  178. this.$emit('weekSubmit')
  179. } else {
  180. this.$message({
  181. message: `${draft ? '暂存失败:' : '提交失败:'}` + res.msg,
  182. type: "error"
  183. });
  184. }
  185. },
  186. error => {
  187. this.submitLoading = false
  188. this.$message({
  189. message: error,
  190. type: "error"
  191. });
  192. });
  193. },
  194. // 判断是否小于系统设置的每日工作时间
  195. judgmentData(data) {
  196. const { allday } = this.user.timeType // 系统设置的每日工作时间
  197. const result = [];
  198. data.forEach((item) => {
  199. const date = item.dateTime;
  200. const index = result.findIndex((arr) => arr[0].dateTime === date);
  201. if (index === -1) {
  202. result.push([item]);
  203. } else {
  204. result[index].push(item);
  205. }
  206. });
  207. const strArr = result
  208. .filter((arr) => arr[0].projectId)
  209. .filter(
  210. (arr) => arr.reduce((sum, item) => sum + (+item.workingTime || 0), 0) < allday
  211. )
  212. .map((arr) => arr[0].dateTime);
  213. return strArr
  214. },
  215. // 项目切换事件
  216. changeProject(projectId, index) {
  217. this.$set(this.weekTableData[index], 'projectAuditorId', '')
  218. this.$set(this.weekTableData[index], 'projectAuditorName', '')
  219. this.$set(this.weekTableData[index], 'groupId', '')
  220. if (projectId) {
  221. this.getProjectGroup(projectId, index)
  222. }
  223. },
  224. // 分组切换事件
  225. changeGroup(groupId, groupList, index) {
  226. let newArr = groupList.filter(item => item.id == groupId)
  227. if (!newArr[0].inchargerId) {
  228. this.$message({
  229. message: `【${newArr[0].name}】分类未设置审批人,请联系该项目管理人员`,
  230. type: "error"
  231. });
  232. return
  233. }
  234. this.$set(this.weekTableData[index], 'projectAuditorId', newArr[0].inchargerId)
  235. this.$set(this.weekTableData[index], 'projectAuditorName', newArr[0].inchargerName)
  236. },
  237. // 获取周数据
  238. async getCurrentWeek(time) {
  239. if (!time) {
  240. this.nowTime = this.dayjs().format('YYYY-MM-DD')
  241. } else {
  242. this.nowTime = this.dayjs(this.nowTime).add(time, 'day').format('YYYY-MM-DD')
  243. }
  244. let { data } = await this.getData('/report/getWeeklyFillReportData', { targetDate: this.nowTime })
  245. const { dateList, projectList, sumTimeList, cardTimeList } = data;
  246. const weekTableData = dateList.flatMap(date => {
  247. const { weekDayTxt, date: dateTime, reportList } = date;
  248. const reports = reportList.map(report => ({ ...report, weekDayTxt, dateTime }));
  249. return reports.length > 0 ? reports : [{ weekDayTxt, dateTime }];
  250. });
  251. this.weekTableData = weekTableData;
  252. },
  253. // 获取项目列表
  254. async getProjectList() {
  255. let { data } = await this.getData('/project/getProjectList')
  256. this.projectList = data
  257. },
  258. // 获取项目下的分组
  259. async getProjectGroup(projectId, index) {
  260. const { isSubstitude } = this.weekParentData;
  261. let { data } = await this.getData('/task-group/listProjectGroupAndAuditor', { projectId, isSubstitude: isSubstitude ? 1 : 0 })
  262. if (data.length == 0) {
  263. this.$message({
  264. message: '分类未设置,请联系该项目管理人员',
  265. type: "error"
  266. });
  267. } else if (data.length == 1) {
  268. this.$set(this.weekTableData[index], 'groupId', data[0].id)
  269. this.$set(this.weekTableData[index], 'projectAuditorId', data[0].inchargerId)
  270. this.$set(this.weekTableData[index], 'projectAuditorName', data[0].inchargerName)
  271. if (!data[0].inchargerId) {
  272. this.$message({
  273. message: `【${newArr[0].name}】分类未设置审批人,请联系该项目管理人员`,
  274. type: "error"
  275. });
  276. }
  277. }
  278. this.$set(this.weekTableData[index], 'taskGroups', data)
  279. },
  280. // 插入一行
  281. insertRow(index) {
  282. this.weekTableData.splice(index + 1, 0, {
  283. dateTime: this.weekTableData[index].dateTime,
  284. weekDayTxt: this.weekTableData[index].weekDayTxt,
  285. content: '',
  286. workingTime: 0,
  287. projectId: '',
  288. projectAuditorId: '',
  289. projectAuditorName: '',
  290. groupId: '',
  291. groupList: [],
  292. approverList: [],
  293. })
  294. },
  295. // 删除一行
  296. deleteRow(index) {
  297. this.weekTableData.splice(index, 1)
  298. },
  299. // 合并单元格
  300. arraySpanMethod({ row, column, rowIndex, columnIndex }) {
  301. let spanOneArr = [], concatOne = 0;
  302. this.weekTableData.map((item, index) => {
  303. if (index === 0) {
  304. spanOneArr.push(1);
  305. } else {
  306. if (item.dateTime === this.weekTableData[index - 1].dateTime) {
  307. spanOneArr[concatOne] += 1;
  308. spanOneArr.push(0);
  309. } else {
  310. spanOneArr.push(1);
  311. concatOne = index;
  312. };
  313. }
  314. });
  315. if (columnIndex === 0) {
  316. const _row = spanOneArr[rowIndex];
  317. const _col = _row > 0 ? 1 : 0;
  318. return {
  319. rowspan: _row,
  320. colspan: _col
  321. }
  322. }
  323. },
  324. // 回显审批人名字
  325. auditorNameFun(item) {
  326. const { groupId, taskGroups } = item;
  327. if (groupId) {
  328. const newArr = taskGroups.filter(v => v.id === groupId);
  329. return newArr.length > 0 ? newArr[0].inchargerName : '';
  330. }
  331. return '';
  332. },
  333. // post 方法请求二次封装
  334. async getData(url, param) {
  335. return new Promise((resolve, reject) => {
  336. this.http.post(url, param,
  337. res => {
  338. resolve(res)
  339. },
  340. error => {
  341. this.$message({
  342. message: error,
  343. type: "error"
  344. });
  345. reject(error)
  346. }
  347. )
  348. });
  349. },
  350. // 关闭弹窗
  351. handleClose() {
  352. this.$emit('weekClose')
  353. },
  354. },
  355. }
  356. </script>
  357. <style scoped lang='scss'>
  358. .flexColumn {
  359. display: flex;
  360. flex-direction: column;
  361. }
  362. .flexColumnAuto {
  363. display: flex;
  364. flex-direction: column;
  365. overflow: auto;
  366. }
  367. .flex1 {
  368. flex: 1;
  369. overflow-y: auto;
  370. }
  371. .weeklyCustomization {
  372. width: 100%;
  373. height: 100%;
  374. .title {
  375. position: absolute;
  376. top: 16px;
  377. left: 140px;
  378. }
  379. .weekcen {
  380. width: 100%;
  381. height: 100%;
  382. }
  383. .weeklyCustomization_btn {
  384. display: flex;
  385. justify-content: flex-end;
  386. padding-top: 10px;
  387. }
  388. .controls {
  389. display: flex;
  390. justify-content: space-between;
  391. align-items: center;
  392. width: 100%;
  393. .el-link {
  394. font-size: 18px;
  395. margin-right: 5px;
  396. }
  397. }
  398. }
  399. </style>