edit.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. <template>
  2. <view>
  3. <view class="card-wrapper" v-if="showEdit()">
  4. <uni-card title="操作">
  5. <view class="editBtns" slot="actions">
  6. <view class="edit" v-if="!isDetail" @click="onClickProject">
  7. 项目详情
  8. </view>
  9. <view class="edit" v-if="canEdit(0)" @click="onEdit">编辑</view>
  10. <view class="edit" v-if="canEdit(0)" @click="onDelete">删除</view>
  11. <view class="edit" v-if="canEdit(0)" @click="onSubmitAuth">
  12. 提交审核
  13. </view>
  14. <view class="edit" v-if="canEdit(1)" @click="onMember">
  15. 成员管理
  16. </view>
  17. <view class="edit" v-if="canEdit(2)" @click="onExecute">
  18. 转执行
  19. </view>
  20. <view class="edit" v-if="canEdit(3)" @click="onWarranty">
  21. 转质保
  22. </view>
  23. <view class="edit" v-if="canEdit(3)" @click="onOperate">
  24. 转运营
  25. </view>
  26. <view class="edit" v-if="canAuth()" @click="onHandleAudit(1)">
  27. 审核通过
  28. </view>
  29. <view class="edit" v-if="canAuth()" @click="onHandleAudit(0)">
  30. 审核拒绝
  31. </view>
  32. </view>
  33. </uni-card>
  34. </view>
  35. <uni-popup ref="exePopup" type="dialog">
  36. <uni-popup-dialog
  37. title="转执行"
  38. type="info"
  39. @confirm="submitExecute"
  40. @close="onCancel"
  41. before-close
  42. >
  43. <uni-forms
  44. ref="exe"
  45. :modelValue="formData"
  46. label-position="left"
  47. :rules="exeRules"
  48. >
  49. <uni-forms-item required label="执行经理:" name="manager">
  50. <uni-data-picker
  51. class="depSelect"
  52. placeholder="请选择执行经理"
  53. :localdata="depUserTree"
  54. @change="changeManager"
  55. />
  56. </uni-forms-item>
  57. <uni-forms-item required label="合同状态:" name="contract">
  58. <picker
  59. @change="changeContract"
  60. :range="contracts"
  61. :value="formData.contract"
  62. >
  63. <view class="select">{{ contracts[formData.contract] }}</view>
  64. </picker>
  65. </uni-forms-item>
  66. </uni-forms>
  67. </uni-popup-dialog>
  68. </uni-popup>
  69. <uni-popup ref="wtyPopup" type="dialog">
  70. <uni-popup-dialog
  71. title="转质保"
  72. type="info"
  73. @confirm="submitWarranty"
  74. @close="onCancel"
  75. before-close
  76. >
  77. <uni-forms
  78. ref="wty"
  79. :modelValue="formData"
  80. label-position="left"
  81. :rules="wtyRules"
  82. >
  83. <uni-forms-item required label="质保经理:" name="manager">
  84. <uni-data-picker
  85. class="depSelect"
  86. placeholder="请选择质保经理"
  87. :localdata="depUserTree"
  88. @change="changeManager"
  89. />
  90. </uni-forms-item>
  91. </uni-forms>
  92. </uni-popup-dialog>
  93. </uni-popup>
  94. <uni-popup ref="optPopup" type="dialog">
  95. <uni-popup-dialog
  96. title="转运营"
  97. type="info"
  98. @confirm="submitOperate"
  99. @close="onCancel"
  100. before-close
  101. >
  102. <uni-forms
  103. ref="opt"
  104. :modelValue="formData"
  105. label-position="left"
  106. :rules="optRules"
  107. >
  108. <uni-forms-item required label="运营经理:" name="manager">
  109. <uni-data-picker
  110. class="depSelect"
  111. placeholder="请选择运营经理"
  112. :localdata="depUserTree"
  113. @change="changeManager"
  114. />
  115. </uni-forms-item>
  116. </uni-forms>
  117. </uni-popup-dialog>
  118. </uni-popup>
  119. </view>
  120. </template>
  121. <script>
  122. import { mapState } from "vuex";
  123. import {
  124. deleteApproval,
  125. submitAudit,
  126. startExecution,
  127. startWarranty,
  128. startOperate,
  129. authApproval,
  130. } from "@/services/project";
  131. export default {
  132. props: ["project", "user", "auth", "flowList", "depRole", "isDetail"],
  133. computed: {
  134. ...mapState(["depUserTree", "showSearch"]),
  135. },
  136. data() {
  137. return {
  138. contracts: ["无合同", "有合同"],
  139. formData: {
  140. manager: "",
  141. contract: null,
  142. },
  143. exeRules: {
  144. manager: {
  145. rules: [{ required: true, errorMessage: "请选择质保经理" }],
  146. },
  147. contract: {
  148. rules: [{ required: true, errorMessage: "请选择合同状态" }],
  149. },
  150. },
  151. wtyRules: {
  152. manager: {
  153. rules: [{ required: true, errorMessage: "请选择质保经理" }],
  154. },
  155. },
  156. optRules: {
  157. manager: {
  158. rules: [{ required: true, errorMessage: "请选择运营经理" }],
  159. },
  160. },
  161. };
  162. },
  163. methods: {
  164. showEdit() {
  165. let toRet =
  166. !this.isDetail ||
  167. this.canEdit(0) ||
  168. this.canEdit(1) ||
  169. this.canEdit(2) ||
  170. this.canEdit(3) ||
  171. this.canAuth();
  172. this.$emit("canEdit", toRet);
  173. return toRet;
  174. },
  175. hideHelper() {
  176. setTimeout(() => {
  177. uni.hideToast();
  178. if (this.isDetail) uni.navigateBack();
  179. else location.reload();
  180. }, 1800);
  181. },
  182. async onClickProject() {
  183. await this.$store.commit("setCurrentProject", this.project);
  184. uni.navigateTo({
  185. url: `./detail?id=${this.project.id}${this.auth ? "&auth=true" : ""}`,
  186. });
  187. },
  188. canEdit(index) {
  189. if (this.auth) return false;
  190. let {
  191. audit_status,
  192. project_status,
  193. author,
  194. LeaderId,
  195. opt_manager_id,
  196. wty_manager_id,
  197. } = this.project;
  198. //audit_status: 0未提审1审核中2审核拒绝3审核通过
  199. //project_status: 0售前1执行2转运营3转质保
  200. switch (index) {
  201. //编辑删除提审
  202. case 0:
  203. //售前阶段,未提审/审核被拒,创建人/管理员
  204. return (
  205. project_status == 0 &&
  206. (audit_status == 0 || audit_status == 2) &&
  207. (this.user.ID == author || this.user.IsSuper)
  208. );
  209. //成员管理
  210. case 1:
  211. //售前/执行/运营/质保,审核通过,项目经理/管理员
  212. let manager;
  213. switch (project_status) {
  214. case 0:
  215. manager = this.user.ID == author;
  216. break;
  217. case 1:
  218. manager = this.user.ID == LeaderId;
  219. break;
  220. case 2:
  221. manager =
  222. this.user.ID == LeaderId || this.user.ID == opt_manager_id;
  223. break;
  224. case 3:
  225. manager =
  226. this.user.ID == LeaderId || this.user.ID == wty_manager_id;
  227. break;
  228. }
  229. return audit_status == 3 && (manager || this.user.IsSuper);
  230. //转执行
  231. case 2:
  232. //售前,审核通过,售前经理/管理员
  233. return (
  234. project_status == 0 &&
  235. audit_status == 3 &&
  236. (this.user.ID == author || this.user.IsSuper)
  237. );
  238. //转质保运营
  239. case 3:
  240. //执行,审核通过,执行经理/管理员
  241. return (
  242. project_status == 1 &&
  243. audit_status == 3 &&
  244. (this.user.ID == LeaderId || this.user.IsSuper)
  245. );
  246. }
  247. },
  248. async onEdit() {
  249. await this.$store.commit("setCurrentProject", this.project);
  250. uni.navigateTo({
  251. url: `./add?project_id=${this.project.id}`,
  252. });
  253. },
  254. onDelete() {
  255. uni.showModal({
  256. title: "删除项目",
  257. content: "是否确认删除该项目",
  258. confirmText: "删除",
  259. confirmColor: "#ff7875",
  260. success: async (res) => {
  261. if (res.confirm) {
  262. await deleteApproval(this.project);
  263. uni.showToast({
  264. title: "删除成功",
  265. });
  266. this.hideHelper();
  267. }
  268. },
  269. });
  270. },
  271. onSubmitAuth() {
  272. uni.showModal({
  273. title: "提交审核",
  274. content: "是否确认提交审核",
  275. confirmText: "提审",
  276. success: async (res) => {
  277. if (res.confirm) {
  278. let payload = {
  279. id: this.project.id,
  280. flow_id: this.project.flow_id,
  281. node_id: this.project.node_id,
  282. };
  283. await submitAudit(payload);
  284. uni.showToast({
  285. title: "提审成功",
  286. });
  287. this.hideHelper();
  288. }
  289. },
  290. });
  291. },
  292. async onMember() {
  293. await this.$store.commit("setCurrentProject", this.project);
  294. uni.navigateTo({
  295. url: "./member",
  296. });
  297. },
  298. async submitHelper(payload = {}, type) {
  299. const [dep_id, manager_id] = this.formData.manager.split("-");
  300. payload = {
  301. ...payload,
  302. project_code_id: this.project.id,
  303. dep_id: Number(dep_id),
  304. };
  305. switch (type) {
  306. case "exe":
  307. await startExecution(payload);
  308. this.$refs.exePopup.close();
  309. uni.showToast({
  310. title: "转执行送审成功",
  311. });
  312. break;
  313. case "wty":
  314. await startWarranty(payload);
  315. this.$refs.wtyPopup.close();
  316. uni.showToast({
  317. title: "转质保送审成功",
  318. });
  319. break;
  320. case "opt":
  321. await startOperate(payload);
  322. this.$refs.optPopup.close();
  323. uni.showToast({
  324. title: "转运营送审成功",
  325. });
  326. break;
  327. }
  328. this.hideHelper();
  329. },
  330. changeManager(e) {
  331. if (e.detail.value.length > 0)
  332. this.formData.manager = e.detail.value[e.detail.value.length - 1].value;
  333. else this.formData.manager = "";
  334. },
  335. async onExecute() {
  336. await this.$store.commit("setShowSearch", false);
  337. this.$refs.exePopup.open();
  338. },
  339. changeContract(e) {
  340. this.formData.contract = e.detail.value;
  341. },
  342. submitExecute() {
  343. this.$refs.exe.validate((err) => {
  344. if (!err) {
  345. const [dep_id, manager_id] = this.formData.manager.split("-");
  346. let payload = {
  347. with_contract: Number(this.formData.contract),
  348. exe_manager_id: Number(manager_id),
  349. };
  350. this.submitHelper(payload, "exe");
  351. }
  352. });
  353. },
  354. async onWarranty() {
  355. await this.$store.commit("setShowSearch", false);
  356. this.$refs.wtyPopup.open();
  357. },
  358. submitWarranty() {
  359. this.$refs.wty.validate((err) => {
  360. if (!err) {
  361. const [dep_id, manager_id] = this.formData.manager.split("-");
  362. let payload = {
  363. wty_manager_id: Number(manager_id),
  364. };
  365. this.submitHelper(payload, "wty");
  366. }
  367. });
  368. },
  369. async onOperate() {
  370. await this.$store.commit("setShowSearch", false);
  371. this.$refs.optPopup.open();
  372. },
  373. submitOperate() {
  374. this.$refs.opt.validate((err) => {
  375. if (!err) {
  376. const [dep_id, manager_id] = this.formData.manager.split("-");
  377. let payload = {
  378. opt_manager_id: Number(manager_id),
  379. };
  380. this.submitHelper(payload, "opt");
  381. }
  382. });
  383. },
  384. async onCancel() {
  385. await this.$store.commit("setShowSearch", true);
  386. this.$refs.exePopup.close();
  387. this.$refs.wtyPopup.close();
  388. this.$refs.optPopup.close();
  389. this.formData = {
  390. manager: "",
  391. contract: null,
  392. };
  393. },
  394. canAuth() {
  395. if (!this.auth) return false;
  396. let { NodeInfo, audit_status, project_status } = this.project;
  397. if (!NodeInfo || this.flowList.length == 0 || this.depRole.length == 0)
  398. return false;
  399. if (audit_status != 1) return false;
  400. if (project_status == 2)
  401. return this.project.opt_manager_id == this.user.ID;
  402. if (project_status == 3)
  403. return this.project.wty_manager_id == this.user.ID;
  404. let flow = this.flowList.find((item) => item.id == NodeInfo.flow_id);
  405. if (!flow) return false;
  406. let { NodeAudits } = flow.Nodes.find((item) => item.id == NodeInfo.id);
  407. const role = this.depRole.find((item) =>
  408. NodeAudits.find((audit) => audit.audit_role == item.ID)
  409. );
  410. return Boolean(role);
  411. },
  412. onHandleAudit(value) {
  413. if (value) {
  414. uni.showModal({
  415. title: "审批通过",
  416. content: "是否确认通过审批",
  417. confirmText: "通过",
  418. success: async (res) => {
  419. if (res.confirm) {
  420. let payload = {
  421. id: this.project.id,
  422. project_full_code: this.project.project_full_code,
  423. flow_id: this.project.flow_id,
  424. node_id: this.project.node_id,
  425. audit_status: 3,
  426. audit_comment: "",
  427. };
  428. await authApproval(payload);
  429. uni.showToast({
  430. title: "审核成功",
  431. });
  432. this.hideHelper();
  433. }
  434. },
  435. });
  436. } else {
  437. uni.showModal({
  438. title: "是否确认拒绝",
  439. content: "拒绝理由",
  440. editable: true,
  441. success: async (res) => {
  442. if (res.confirm) {
  443. let payload = {
  444. id: this.project.id,
  445. project_full_code: this.project.project_full_code,
  446. flow_id: this.project.flow_id,
  447. node_id: this.project.node_id,
  448. audit_status: 2,
  449. audit_comment: res.content,
  450. };
  451. await authApproval(payload);
  452. uni.showToast({
  453. title: "已拒绝",
  454. });
  455. this.hideHelper();
  456. }
  457. },
  458. });
  459. }
  460. },
  461. },
  462. };
  463. </script>
  464. <style lang="less" scoped>
  465. .editBtns {
  466. display: flex;
  467. justify-content: space-around;
  468. flex-wrap: wrap;
  469. margin: 0 5%;
  470. .edit {
  471. width: 30%;
  472. margin-bottom: 20px;
  473. font-size: 28rpx;
  474. text-align: center;
  475. border-radius: 10rpx;
  476. box-shadow: 0 2rpx 2rpx #666;
  477. }
  478. }
  479. .card-wrapper {
  480. padding-bottom: 60rpx;
  481. }
  482. .select {
  483. width: 100%;
  484. height: 72rpx;
  485. line-height: 70rpx;
  486. border: 1px solid #666;
  487. padding-left: 20rpx;
  488. }
  489. ::v-deep {
  490. .uni-steps__column-title {
  491. font-size: 18px;
  492. line-height: 24px;
  493. }
  494. .uni-steps__column-desc {
  495. font-size: 14px;
  496. line-height: 18px;
  497. }
  498. }
  499. .depSelect {
  500. width: 200px;
  501. }
  502. </style>