budgetReview.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. <template>
  2. <section>
  3. <div class="budgetReviewHeader">
  4. <div class="budgetReviewHeader_Form">
  5. <!-- 日期 -->
  6. <div class="budgetReviewHeader_FormItem">
  7. <el-date-picker size="small" v-model="screeningConditionForm.dateRange" :editable="false"
  8. format="yyyy-MM-dd" value-format="yyyy-MM-dd" :clearable="false" :range-separator="'至'"
  9. type="daterange" :start-placeholder="'开始日期'" :end-placeholder="'结束日期'" style="width: 260px"
  10. @change="getList"></el-date-picker>
  11. </div>
  12. <!-- 项目 -->
  13. <div class="budgetReviewHeader_FormItem">
  14. <div class="budgetReviewHeader_FormItemText">项目:</div>
  15. <el-select v-model="screeningConditionForm.projectId" filterable placeholder="请选择项目" clearable
  16. size="small" @change="getList">
  17. <el-option v-for="item in projectList" :key="item.id"
  18. :label="item.projectName + '\u3000' + item.projectCode" :value="item.id">
  19. <span class="selectProRight">{{ item.projectCode }}</span>
  20. <span class="selectProleft">{{ item.projectName }}</span>
  21. </el-option>
  22. </el-select>
  23. </div>
  24. <!-- 审核人 -->
  25. <div class="budgetReviewHeader_FormItem">
  26. <div class="budgetReviewHeader_FormItemText">审核人:</div>
  27. <el-select v-model="screeningConditionForm.checkUserId" filterable placeholder="请选择审核人" clearable
  28. size="small" v-if="user.userNameNeedTranslate != 1" style="width: 130px;" @change="getList">
  29. <el-option v-for="item in usersList" :key="item.id" :label="item.name + '\u3000' + item.jobNumber"
  30. :value="item.id">
  31. <span class="selectProRight">{{ item.jobNumber }}</span>
  32. <span class="selectProleft">{{ item.name }}</span>
  33. </el-option>
  34. </el-select>
  35. <selectCat :size="'small'" :subject="usersList" :subjectId="screeningConditionForm.checkUserId"
  36. :clearable="true" :filterable="true" :searchBoxTop="1" stinction="'1'" @selectCal="selectCal"
  37. v-if="user.userNameNeedTranslate == 1" :widthStr="'130'"></selectCat>
  38. </div>
  39. <!-- 审核状态 -->
  40. <div class="budgetReviewHeader_FormItem">
  41. <div class="budgetReviewHeader_FormItemText">审核状态:</div>
  42. <el-select v-model="screeningConditionForm.status" filterable placeholder="请选择状态" clearable size="small"
  43. style="width: 120px;" @change="getList">
  44. <el-option v-for="item in auditStatus" :key="item.id" :label="item.label" :value="item.id">
  45. </el-option>
  46. </el-select>
  47. </div>
  48. </div>
  49. <div class="budgetReviewHeader_btn">
  50. <el-button type="primary" size="small" @click="exportReport" :loading="exporListLoading">导出</el-button>
  51. </div>
  52. </div>
  53. <!--列表-->
  54. <el-table :data="list" ref="multipleTable" highlight-current-row v-loading="listLoading" :height="tableHeight"
  55. style="width: 100%;">
  56. <el-table-column prop="projectName" :label="'项目名称'" sortable min-width="200px">
  57. <template slot-scope="scope">
  58. <div>
  59. <span>
  60. {{ scope.row.projectName }}
  61. </span>
  62. </div>
  63. </template>
  64. </el-table-column>
  65. <el-table-column prop="groupName" :label="'分组名称'" sortable min-width="180px">
  66. <template slot-scope="scope">
  67. <div>
  68. <span>
  69. {{ scope.row.groupName }}
  70. </span>
  71. </div>
  72. </template>
  73. </el-table-column>
  74. <el-table-column prop="creator" :label="'提交人'" sortable min-width="120px">
  75. <template slot-scope="scope">
  76. <div>
  77. <span v-if="user.userNameNeedTranslate == '1'">
  78. <TranslationOpenDataText type='userName' :openid='scope.row.creator'></TranslationOpenDataText>
  79. </span>
  80. <span v-else>
  81. {{ scope.row.creator }}
  82. </span>
  83. </div>
  84. </template>
  85. </el-table-column>
  86. <el-table-column prop="createTime" :label="'提交时间'" sortable min-width="120px">
  87. <template slot-scope="scope">
  88. <div>
  89. <span>
  90. {{ scope.row.createTime }}
  91. </span>
  92. </div>
  93. </template>
  94. </el-table-column>
  95. <el-table-column prop="oldManDay" :label="'变更前预估工时'" sortable min-width="150px">
  96. <template slot-scope="scope">
  97. <div>
  98. <span>
  99. {{ scope.row.oldManDay }}人天 / {{ scope.row.oldEstimatedWorkTime }}小时
  100. </span>
  101. </div>
  102. </template>
  103. </el-table-column>
  104. <el-table-column prop="changeManDay" :label="'预估工时变更'" sortable min-width="150px">
  105. <template slot-scope="scope">
  106. <div>
  107. <span>
  108. {{ scope.row.changeManDay }}人天 / {{ scope.row.changeEstimatedWorkTime }}小时
  109. </span>
  110. </div>
  111. </template>
  112. </el-table-column>
  113. <el-table-column prop="nowManDay" :label="'变更后预估工时'" sortable min-width="150px">
  114. <template slot-scope="scope">
  115. <div>
  116. <span>
  117. {{ scope.row.nowManDay }}人天 / {{ scope.row.nowEstimatedWorkTime }}小时
  118. </span>
  119. </div>
  120. </template>
  121. </el-table-column>
  122. <el-table-column prop="remark" :label="'变更理由'" sortable width="200px">
  123. <template slot-scope="scope">
  124. <div>
  125. <div v-if="scope.row.remark && scope.row.remark.length > 11">
  126. <el-tooltip class="remarkClassItem" effect="dark" :content="scope.row.remark" placement="top">
  127. <div class="remarkClass">{{ scope.row.remark }}</div>
  128. </el-tooltip>
  129. </div>
  130. <div v-else>
  131. {{ scope.row.remark }}
  132. </div>
  133. </div>
  134. </template>
  135. </el-table-column>
  136. <el-table-column prop="rejectReason" :label="'驳回理由'" sortable width="200px">
  137. <template slot-scope="scope">
  138. <div>
  139. <div v-if="scope.row.rejectReason && scope.row.rejectReason.length > 11">
  140. <el-tooltip class="remarkClassItem" effect="dark" :content="scope.row.rejectReason" placement="top">
  141. <div class="remarkClass">{{ scope.row.rejectReason }}</div>
  142. </el-tooltip>
  143. </div>
  144. <div v-else>
  145. {{ scope.row.rejectReason}}
  146. </div>
  147. </div>
  148. </template>
  149. </el-table-column>
  150. <el-table-column prop="status" :label="$t('state.states')" sortable>
  151. <template slot-scope="scope">
  152. <span v-if="scope.row.status == 0" style="color:#DAA520;">{{ '待审核' }}</span>
  153. <span v-else-if="scope.row.status == 1" style="color:#32CD32;">{{ $t('state.alreadyPassed') }}</span>
  154. <span v-else-if="scope.row.status == 2" style="color:#FF0000;">{{ $t('state.rejected') }}</span>
  155. </template>
  156. </el-table-column>
  157. <el-table-column :label="$t('operation')" width="220" fixed="right">
  158. <template slot-scope="scope">
  159. <el-button v-if="scope.row.status == 0" type="primary" :loading="logining" size="small"
  160. @click="review(scope.row.id, 1)">{{ $t('btn.through') }}</el-button>
  161. <el-button v-if="scope.row.status == 0" type="danger" :loading="logining" size="small"
  162. @click="review(scope.row.id, 2)">{{ $t('btn.rejected') }}</el-button>
  163. </template>
  164. </el-table-column>
  165. </el-table>
  166. </section>
  167. </template>
  168. <script>
  169. // 引入自定义组件
  170. import selectCat from "@/components/select.vue"
  171. export default {
  172. components: {
  173. selectCat,
  174. },
  175. data() {
  176. return {
  177. list: [],
  178. tableHeight: 0,
  179. listLoading: false,
  180. defaultExpandAllFlg: false,
  181. exporListLoading: false,
  182. user: JSON.parse(sessionStorage.getItem("user")),
  183. usersList: [],
  184. searchUsersList: [],
  185. projectList: [],
  186. auditStatus: [
  187. { id: 1, label: '待审核' },
  188. { id: 2, label: '审核通过' },
  189. { id: 3, label: '已驳回' }
  190. ],
  191. screeningConditionForm: {
  192. projectId: '',
  193. dateRange: '',
  194. checkUserId: '',
  195. status: ''
  196. }
  197. };
  198. },
  199. filters: {
  200. manHourText(value) {
  201. return value == 0 ? 0 : value + 'h';
  202. }
  203. },
  204. methods: {
  205. review(id,checkType){
  206. if(checkType==2){
  207. this.$prompt('请输入驳回理由', '提示', {
  208. confirmButtonText: '确定',
  209. cancelButtonText: '取消',
  210. }).then(({ value }) => {
  211. this.http.post("/group-budget-review/check", {id:id,checkType:checkType,rejectReason:value},
  212. res => {
  213. if (res.code == "ok") {
  214. this.$message({
  215. message:"操作成功",
  216. type: "success"
  217. });
  218. this.getList();
  219. } else {
  220. this.$message({
  221. message: res.msg,
  222. type: "error"
  223. });
  224. }
  225. },
  226. error => {
  227. this.$message({
  228. message: error,
  229. type: "error"
  230. });
  231. });
  232. }).catch(() => {
  233. this.$message({
  234. type: 'info',
  235. message: '取消驳回'
  236. });
  237. });
  238. }else{
  239. this.http.post("/group-budget-review/check", {id:id,checkType:checkType,rejectReason:""},
  240. res => {
  241. if (res.code == "ok") {
  242. this.$message({
  243. message:"操作成功",
  244. type: "success"
  245. });
  246. this.getList();
  247. } else {
  248. this.$message({
  249. message: res.msg,
  250. type: "error"
  251. });
  252. }
  253. },
  254. error => {
  255. this.$message({
  256. message: error,
  257. type: "error"
  258. });
  259. });
  260. }
  261. },
  262. //获取待审核的数据列表
  263. getList() {
  264. this.listLoading = true;
  265. const { projectId, dateRange, checkUserId, status } = this.screeningConditionForm;
  266. const params = {
  267. ...(projectId && { projectId }),
  268. ...(dateRange && { startDate: dateRange[0], endDate: dateRange[1] }),
  269. ...(checkUserId && { checkUserId }),
  270. ...(status && { status }),
  271. };
  272. this.http.post("/group-budget-review/list", {
  273. ...params
  274. },
  275. res => {
  276. this.listLoading = false;
  277. if (res.code == "ok") {
  278. this.list = res.data;
  279. } else {
  280. this.$message({
  281. message: res.msg,
  282. type: "error"
  283. });
  284. }
  285. },
  286. error => {
  287. this.listLoading = false;
  288. this.$message({
  289. message: error,
  290. type: "error"
  291. });
  292. });
  293. },
  294. //获取项目列表
  295. getProjectList() {
  296. this.http.post(this.port.project.list, {},
  297. res => {
  298. if (res.code == "ok") {
  299. this.projectList = res.data;
  300. } else {
  301. this.$message({
  302. message: res.msg,
  303. type: "error"
  304. });
  305. }
  306. },
  307. error => {
  308. this.$message({
  309. message: error,
  310. type: "error"
  311. });
  312. });
  313. },
  314. // 获取所有人员
  315. getUsers() {
  316. this.http.post('/user/getSimpleActiveUserList', {},
  317. res => {
  318. if (res.code == "ok") {
  319. this.usersList = res.data;
  320. this.searchUsersList = this.usersList
  321. } else {
  322. this.$message({
  323. message: res.msg,
  324. type: "error"
  325. });
  326. }
  327. },
  328. error => {
  329. this.$message({
  330. message: error,
  331. type: "error"
  332. });
  333. });
  334. },
  335. selectCal(obj) {
  336. console.log(obj, '过来的数据')
  337. if (obj.distinction == 1) {
  338. this.screeningConditionForm.checkUserId = obj.id
  339. this.getList()
  340. }
  341. },
  342. // 获取当月第一天到现在的日期
  343. getNowMonth() {
  344. let date = new Date();
  345. let year = date.getFullYear();
  346. let month = date.getMonth() + 1;
  347. let day = date.getDate();
  348. let now = year + '-' + (month < 10 ? '0' + month : month) + '-' + (day < 10 ? '0' + day : day);
  349. let firstDay = year + '-' + (month < 10 ? '0' + month : month) + '-01';
  350. this.screeningConditionForm.dateRange = [firstDay, now]
  351. },
  352. // 导出
  353. exportReport() {
  354. const { projectId, dateRange, checkUserId, status } = this.screeningConditionForm;
  355. const params = {
  356. ...(projectId && { projectId }),
  357. ...(dateRange && { startDate: dateRange[0], endDate: dateRange[1] }),
  358. ...(checkUserId && { checkUserId }),
  359. ...(status && { status }),
  360. };
  361. this.exporListLoading = true;
  362. this.http.post('/group-budget-review/export', {
  363. ...params
  364. },
  365. res => {
  366. this.exporListLoading = false
  367. if (res.code == "ok") {
  368. var filePath = res.data;
  369. const a = document.createElement('a'); // 创建a标签
  370. a.setAttribute('download', '预估工时审核');// download属性
  371. a.setAttribute('href', filePath);// href链接
  372. a.click(); //自执行点击事件
  373. a.remove();
  374. } else {
  375. this.$message({
  376. message: res.msg,
  377. type: "error"
  378. });
  379. }
  380. },
  381. error => {
  382. this.exporListLoading = false
  383. this.$message({
  384. message: error,
  385. type: "error"
  386. });
  387. });
  388. }
  389. },
  390. created() {
  391. let height = window.innerHeight;
  392. this.tableHeight = height - 125;
  393. const that = this;
  394. window.onresize = function temp() {
  395. that.tableHeight = window.innerHeight - 125;
  396. };
  397. },
  398. mounted() {
  399. this.getNowMonth()
  400. this.getUsers();
  401. this.getProjectList()
  402. this.getList();
  403. }
  404. };
  405. </script>
  406. <style lang="scss" scoped>
  407. .propsbtn {
  408. display: inline-block;
  409. padding-left: 20px;
  410. }
  411. .remarkClass {
  412. overflow: hidden;
  413. text-overflow: ellipsis;
  414. white-space: nowrap;
  415. }
  416. .selectProRight {
  417. float: right;
  418. color: #8492a6;
  419. font-size: 13px;
  420. margin-left: 10px;
  421. }
  422. .selectProleft {
  423. float: left;
  424. }
  425. .budgetReviewHeader {
  426. padding: 10px 20px;
  427. background: #F2F2F2;
  428. display: flex;
  429. justify-content: space-between;
  430. flex-wrap: wrap;
  431. }
  432. .budgetReviewHeader_Form {
  433. display: flex;
  434. .budgetReviewHeader_FormItem {
  435. display: flex;
  436. align-items: center;
  437. margin-right: 20px;
  438. .budgetReviewHeader_FormItemText {
  439. margin-right: 10px;
  440. font-size: 14px;
  441. color: #333;
  442. }
  443. }
  444. }
  445. </style>