audit.vue 8.3 KB

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