audit.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <template>
  2. <view class="page">
  3. <view class="content">
  4. <uni-calendar
  5. class="uni-calendar--hook"
  6. :selected="info.selected"
  7. :showMonth="false"
  8. @change="change"
  9. />
  10. <uni-collapse ref="collapse">
  11. <uni-collapse-item
  12. v-for="collapse in collapseList"
  13. :key="collapse.name"
  14. :title="collapse.name"
  15. >
  16. <view class="content">
  17. <template v-for="(item, index) in collapse.children">
  18. <uni-card
  19. :key="index"
  20. :title="allType[item.type_id] && allType[item.type_id].name"
  21. >
  22. <view class="uni-body">
  23. <view class="detail-item">
  24. <view class="detail-label">提交人</view>
  25. <view class="detail-value">
  26. {{ item.User.CName }}
  27. </view>
  28. </view>
  29. <view class="detail-item">
  30. <view class="detail-label">审核状态</view>
  31. <view
  32. class="detail-value"
  33. :style="{ color: stateColor[item.audit_state] }"
  34. >
  35. {{ auditState[item.audit_state] }}
  36. </view>
  37. </view>
  38. <view class="detail-item" v-if="item.audit_state == 3">
  39. <view class="detail-label">拒绝原因</view>
  40. <view class="detail-value">
  41. {{ item.audit_desc }}
  42. </view>
  43. </view>
  44. <view class="detail-item">
  45. <view class="detail-label">工时</view>
  46. <view class="detail-value">
  47. {{ item.workload }}
  48. </view>
  49. </view>
  50. </view>
  51. <view
  52. v-if="item.audit_state == 1"
  53. slot="actions"
  54. class="card-actions"
  55. >
  56. <view class="card-actions-item" @click="onHandleAudit(item)">
  57. <text class="card-actions-item-text">通过</text>
  58. </view>
  59. <view class="card-actions-item" @click="onHandleReject(item)">
  60. <text class="card-actions-item-text">拒绝</text>
  61. </view>
  62. </view>
  63. </uni-card>
  64. </template>
  65. </view>
  66. </uni-collapse-item>
  67. </uni-collapse>
  68. <uni-popup ref="inputDialog" type="dialog">
  69. <uni-popup-dialog
  70. ref="inputClose"
  71. mode="input"
  72. title="拒绝原因"
  73. :value="auditDesc"
  74. @confirm="dialogInputConfirm"
  75. ></uni-popup-dialog>
  76. </uni-popup>
  77. <uni-popup ref="auditDialog" type="dialog">
  78. <uni-popup-dialog
  79. type="info"
  80. title="提示"
  81. content="是否确认通过审批"
  82. @confirm="auditConfirm"
  83. ></uni-popup-dialog>
  84. </uni-popup>
  85. </view>
  86. </view>
  87. </template>
  88. <script>
  89. import {
  90. queryAuthWorkHours,
  91. addWorkHours,
  92. queryProject,
  93. authWorkload,
  94. } from "@/services/workload";
  95. import moment from "moment";
  96. import { mapState } from "vuex";
  97. export default {
  98. data() {
  99. return {
  100. auditDesc: "",
  101. info: {
  102. lunar: true,
  103. range: true,
  104. insert: false,
  105. selected: [],
  106. },
  107. currentItem: {},
  108. projectList: [],
  109. currentList: [],
  110. stateColor: {
  111. 1: "#1890ff",
  112. 2: "#a0d911",
  113. 3: "#f5222d",
  114. },
  115. auditState: {
  116. 0: "未提审",
  117. 1: "待审核",
  118. 2: "已通过",
  119. 3: "已拒绝",
  120. },
  121. day: moment().format("YYYY-MM-DD"),
  122. };
  123. },
  124. onReady() {
  125. this.init();
  126. },
  127. computed: {
  128. ...mapState(["allType"]),
  129. collapseList() {
  130. const projectList = this.projectList;
  131. let data = {};
  132. this.currentList.forEach((item) => {
  133. let pid = item.project_id;
  134. let name = "";
  135. if (!data[pid]) {
  136. if (pid == "0") name = "其他";
  137. else {
  138. let find = projectList.find((p) => p.ID == pid);
  139. if (!find) return;
  140. name = find.Name;
  141. }
  142. data[pid] = {
  143. id: pid,
  144. name,
  145. children: [],
  146. };
  147. }
  148. data[pid].children.push(item);
  149. });
  150. let allList = Object.values(data);
  151. // 将id为0的项 放置到数组最后
  152. let index = allList.findIndex((item) => item.id == "0");
  153. if (index != -1) {
  154. var temp = allList.splice(index, 1);
  155. allList.push(temp[0]);
  156. }
  157. // allList.forEach((item) => {
  158. // // 根据type进行分类
  159. // const { list, audit } = this.getTableInfo(item.list);
  160. // item.list = list;
  161. // item.audit = audit;
  162. // });
  163. return allList;
  164. },
  165. },
  166. onNavigationBarButtonTap() {
  167. uni.reLaunch({
  168. url: "/pages/index/index",
  169. });
  170. },
  171. methods: {
  172. async init() {
  173. await this.$store.dispatch("getType");
  174. this.projectList = await queryProject();
  175. await this.queryAuthWorkHours();
  176. },
  177. change(e) {
  178. this.day = e.fulldate;
  179. this.currentList = e.extraInfo.list || [];
  180. },
  181. getProject(id) {
  182. let p = this.projectList.find((p) => p.ID == id);
  183. if (!p) return "";
  184. return p.Name;
  185. },
  186. onHandleReject(item) {
  187. this.currentItem = item;
  188. this.$refs.inputDialog.open();
  189. },
  190. onHandleAudit(item) {
  191. this.currentItem = item;
  192. this.$refs.auditDialog.open();
  193. },
  194. async dialogInputConfirm(desc) {
  195. let item = this.currentItem;
  196. let params = [
  197. {
  198. id: item.id,
  199. ts: item.ts,
  200. user_id: item.User.ID,
  201. workload: item.workload,
  202. status: 3,
  203. desc: desc || "",
  204. },
  205. ];
  206. // 保存
  207. await authWorkload(params);
  208. await this.queryAuthWorkHours();
  209. },
  210. async auditConfirm() {
  211. let item = this.currentItem;
  212. let params = [
  213. {
  214. id: item.id,
  215. status: 2,
  216. desc: "",
  217. },
  218. ];
  219. await authWorkload(params);
  220. this.queryAuthWorkHours();
  221. this.$refs.auditDialog.close();
  222. },
  223. async queryAuthWorkHours() {
  224. const user = uni.getStorageSync("user");
  225. const data = await queryAuthWorkHours({
  226. user_id: user.ID,
  227. audit_state: 1,
  228. });
  229. let selected = [];
  230. Object.keys(data).map((day) => {
  231. let list = data[day];
  232. let total = 0;
  233. let canEdit = false;
  234. list.forEach((item) => {
  235. if (item.audit_state == 1) {
  236. total += item.workload;
  237. canEdit = true;
  238. }
  239. });
  240. selected.push({
  241. date: day,
  242. info: total > 0 ? `${total} 小时` : "",
  243. list: list,
  244. color: canEdit ? "#e43d33" : "",
  245. });
  246. if (this.day == day) {
  247. this.currentList = list;
  248. }
  249. });
  250. this.info.selected = selected;
  251. },
  252. async onSubmit(values) {
  253. let params = [
  254. {
  255. type_id: Number(values.subTypeId),
  256. comment: "",
  257. data: [
  258. {
  259. project_id: Number(values.projectId),
  260. workload: 0,
  261. day: this.day,
  262. },
  263. ],
  264. },
  265. ];
  266. // 新增
  267. await addWorkHours(params);
  268. this.queryAuthWorkHours();
  269. },
  270. showModal() {
  271. this.$refs.addModal.open();
  272. },
  273. getTableInfo(list) {
  274. let data = {},
  275. audit = [];
  276. const allType = this.allType;
  277. list.forEach((item) => {
  278. let pid = allType[item.type_id].parent_id;
  279. if (!pid) return;
  280. if (!data[pid]) data[pid] = [];
  281. data[pid].push(item);
  282. // 判断是否处于待审批状态
  283. if (item.audit_state == 1) {
  284. // 保存可审批的项
  285. audit.push(item);
  286. }
  287. });
  288. let newList = Object.keys(data).map((pid) => ({
  289. zIndex: 0,
  290. id: pid,
  291. type_id: allType[pid].id,
  292. children: data[pid],
  293. }));
  294. return {
  295. list: newList,
  296. audit,
  297. };
  298. },
  299. },
  300. };
  301. </script>
  302. <style lang="scss" scoped>
  303. .content {
  304. padding: 30rpx;
  305. padding-top: 0;
  306. }
  307. .button {
  308. margin-right: 20rpx;
  309. }
  310. .card-actions {
  311. display: flex;
  312. flex-direction: row;
  313. justify-content: space-around;
  314. align-items: center;
  315. height: 45px;
  316. border-top: 1px #eee solid;
  317. }
  318. .detail-item {
  319. margin: 12rpx 0;
  320. display: flex;
  321. justify-content: space-between;
  322. align-items: flex-start;
  323. .detail-value {
  324. max-width: 60%;
  325. text-align: right;
  326. }
  327. }
  328. ::v-deep {
  329. .uni-calendar-item__weeks-box-item {
  330. width: 90rpx;
  331. }
  332. }
  333. </style>