index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <template>
  2. <el-drawer
  3. v-model="drawerVisible"
  4. :close-on-click-modal="false"
  5. :show-close="false"
  6. destroy-on-close
  7. direction="rtl"
  8. size="972px"
  9. >
  10. <template #header>
  11. <div class="drawerTitle">报工</div>
  12. </template>
  13. <template #default>
  14. <el-scrollbar>
  15. <div id="drawContent">
  16. <el-form
  17. :model="formData"
  18. ref="formRef"
  19. :disabled="formDisabled"
  20. label-position="left"
  21. label-width="auto"
  22. size="large"
  23. >
  24. <el-row :gutter="20">
  25. <el-col :span="10">
  26. <el-select
  27. v-model="selectedSign"
  28. :filterable="true"
  29. placeholder="请选择签章名称"
  30. style="margin-bottom: 20px"
  31. >
  32. <el-option v-for="item in signNameList" :key="item.id" :label="item.signatureName" :value="item.id" />
  33. </el-select>
  34. </el-col>
  35. </el-row>
  36. <el-row>
  37. <el-col :span="24">
  38. <el-form-item
  39. prop="operateCondition"
  40. style="margin-bottom: 20px"
  41. :rules="[{ required: true, message: '请输入实时工艺条件', trigger: 'blur' }]"
  42. >
  43. <el-input v-model="formData.operateCondition" placeholder="请输入实时工艺条件" type="textarea" />
  44. </el-form-item>
  45. </el-col>
  46. </el-row>
  47. <el-row v-for="(per, index) in persons" :key="per.userName" :gutter="20" style="width: 100%">
  48. <el-col :span="10">
  49. <el-form-item label="" prop="userName">
  50. <el-tree-select
  51. v-model="per.userName"
  52. :data="userList"
  53. placeholder="请选择人员"
  54. :default-expand-all="false"
  55. filterable
  56. clearable
  57. />
  58. </el-form-item>
  59. </el-col>
  60. <el-col :span="10" v-if="false">
  61. <el-form-item label="" prop="workingHoursRate">
  62. <el-select v-model="per.workingHoursRate" placeholder="请选择工时比例" value-key="value">
  63. <el-option v-for="item in rateArray" :key="item.value" :label="item.label" :value="item.value" />
  64. </el-select>
  65. </el-form-item>
  66. </el-col>
  67. <el-col :span="10">
  68. <el-form-item label="" prop="selectedProcess">
  69. <el-select
  70. v-model="per.selectedProcess"
  71. :filterable="true"
  72. multiple
  73. placeholder="请选择流转卡号,可以输入或者扫码筛选"
  74. @remove-tag="removeSeq"
  75. @visible-change="visibleSeq"
  76. @focus="getUserName(index)"
  77. >
  78. <template #prefix><img src="@/assets/icons/shaoma.svg" /></template>
  79. <template #header>
  80. <div class="guanhao-header">
  81. <el-checkbox v-model="per.checkAll" @change="handleCheckAll(per)"> 全选 </el-checkbox>
  82. <el-input v-model="toSelectCount" placeholder="请输入选中前面数量">
  83. <template #append
  84. ><el-button type="primary" @click="startToSelectAheads(per)">选择</el-button></template
  85. >
  86. </el-input>
  87. </div>
  88. </template>
  89. <el-option v-for="item in process" :key="item" :label="item" :value="item" />
  90. </el-select>
  91. </el-form-item>
  92. </el-col>
  93. <el-col :span="4">
  94. <div v-if="!formDisabled" class="right-btns">
  95. <CirclePlus
  96. class="icon-btn"
  97. @click="
  98. persons.push({
  99. userName: null,
  100. workingHoursRate: 100,
  101. selectedProcess: [],
  102. checkAll: false,
  103. })
  104. "
  105. />
  106. <Remove v-if="index !== 0" class="icon-btn" @click="persons.splice(index, 1)" />
  107. </div>
  108. </el-col>
  109. </el-row>
  110. </el-form>
  111. </div>
  112. </el-scrollbar>
  113. </template>
  114. <template #footer>
  115. <div class="bottom-btns">
  116. <el-button class="cancelBtn el-button-big" @click="cancelClick">取消 </el-button>
  117. <el-button v-if="!formDisabled" class="sureBtn el-button-big" type="primary" @click="confirmClick"
  118. >报工
  119. </el-button>
  120. </div>
  121. </template>
  122. </el-drawer>
  123. </template>
  124. <script lang="ts" setup>
  125. import { useProcessStore } from "@/store/modules/processView";
  126. import { useDictionaryStore } from "@/store/modules/dictionary";
  127. import { getProcessInfo, getunProcessedList } from "@/api/prosteps";
  128. import { emitter, EventsNames } from "@/utils/common";
  129. import { CirclePlus, Remove } from "@element-plus/icons-vue";
  130. import { useUserStore } from "@/store/modules/user";
  131. import { reportWork, signList } from "@/api/process/reportBreak";
  132. import { getUserTree } from "@/api/user";
  133. const processStore = useProcessStore();
  134. const dictStroe = useDictionaryStore();
  135. const userStore = useUserStore();
  136. const router = useRouter();
  137. const drawerVisible = ref(false);
  138. const formDisabled = ref(true);
  139. const signNameList = ref<any[]>([]);
  140. const selectedSign = ref<any[]>([]);
  141. const formData = reactive({
  142. operateCondition: "",
  143. });
  144. const checkAll = ref(false);
  145. const x = () => {};
  146. const process = ref([]);
  147. const visibleSeq = (val) => {
  148. if (val) {
  149. process.value = processList.value;
  150. if (persons.value && persons.value.length > 0) {
  151. let i = 0;
  152. for (let element of persons.value) {
  153. if (element.selectedProcess && element.selectedProcess.length > 0) {
  154. //排除当前行的值
  155. if (currentUser.value && currentUser.value != i) {
  156. for (let e of element.selectedProcess) {
  157. process.value = process.value.filter((item) => item !== e);
  158. }
  159. }
  160. }
  161. i++;
  162. }
  163. }
  164. }
  165. };
  166. const currentUser = ref(null);
  167. const getUserName = (index) => {
  168. currentUser.value = index;
  169. };
  170. const handleCheckAll = (person) => {
  171. console.log("handleCheckAll", person);
  172. person.selectedProcess = [];
  173. if (person.checkAll) {
  174. person.selectedProcess = process.value;
  175. } else {
  176. person.selectedProcess = [];
  177. }
  178. };
  179. const formRef = ref<InstanceType<typeof ElForm>>();
  180. const persons = ref<
  181. {
  182. userName: string | null;
  183. workingHoursRate: number | null;
  184. selectedProcess: any;
  185. checkAll: boolean;
  186. }[]
  187. >([
  188. {
  189. userName: userStore.user.username ?? "",
  190. workingHoursRate: 100,
  191. selectedProcess: [],
  192. checkAll: false,
  193. },
  194. ]);
  195. const removeSeq = (item) => {
  196. console.log();
  197. selectedProcess.value = selectedProcess.value.filter((e) => e !== item);
  198. };
  199. const openReportWorkDrawer = () => {
  200. // 初始化数据
  201. selectedSign.value = [];
  202. formData.operateCondition = "";
  203. persons.value = [
  204. {
  205. userName: userStore.user.username ?? "",
  206. workingHoursRate: 100,
  207. selectedProcess: [],
  208. checkAll: false,
  209. },
  210. ];
  211. processList.value = [];
  212. getProcessInfo(processStore.scanInfo.id).then((res) => {
  213. processStore.scanInfo.currentState = res.data.currentState;
  214. if (res.data.currentState !== "start") {
  215. ElMessage.warning("当前工单状态不允许报工");
  216. formDisabled.value = true;
  217. // reportWorkList(processStore.scanInfo.id).then((res) => {
  218. // persons.value = res.data || [];
  219. // });
  220. } else {
  221. drawerVisible.value = true;
  222. formDisabled.value = false;
  223. }
  224. });
  225. getunProcessedList(processStore.scanInfo.id).then((res: any) => {
  226. processList.value = res.data ?? [];
  227. });
  228. signList({ signatureType: "3" }).then((res) => {
  229. signNameList.value = res.data ?? [];
  230. });
  231. };
  232. const cancelClick = () => {
  233. drawerVisible.value = false;
  234. };
  235. const confirmClick = async () => {
  236. let validataStatus = await formRef.value?.validate();
  237. if (!validataStatus) return;
  238. let total = 0;
  239. persons.value.forEach((item) => {
  240. total += item.workingHoursRate ?? 0;
  241. });
  242. /* if (total > 100) {
  243. ElMessage.error("总占比不能超过100%");
  244. return;
  245. }*/
  246. let params = {
  247. processId: processStore.scanInfo.id,
  248. processUserReportList: persons.value,
  249. seqList: selectedProcess.value,
  250. signatureId: Array.isArray(selectedSign.value) && selectedSign.value.length === 0 ? null : selectedSign.value,
  251. operateCondition: formData.operateCondition,
  252. };
  253. reportWork(params).then((res: any) => {
  254. if (res.code === "200") {
  255. ElMessage.success("报工成功");
  256. emitter.emit(EventsNames.PROCESS_REDER);
  257. router.replace("/process");
  258. drawerVisible.value = false;
  259. } else {
  260. ElMessage.error("报工失败");
  261. }
  262. });
  263. };
  264. defineExpose({
  265. openReportWorkDrawer,
  266. });
  267. const rateArray: { label: string; value: number }[] = [
  268. { label: "10%", value: 10 },
  269. { label: "20%", value: 20 },
  270. { label: "30%", value: 30 },
  271. { label: "40%", value: 40 },
  272. { label: "50%", value: 50 },
  273. { label: "60%", value: 60 },
  274. { label: "70%", value: 70 },
  275. { label: "80%", value: 80 },
  276. { label: "90%", value: 90 },
  277. { label: "100%", value: 100 },
  278. ];
  279. // ================= 选择工序相关
  280. const selectedProcess = ref<any[]>([]);
  281. const processList = ref<any[]>([]);
  282. // ================= 人员树结构
  283. const userList = ref([]);
  284. const queryUserList = () => {
  285. getUserTree().then((data) => {
  286. userList.value = data.data;
  287. });
  288. };
  289. onMounted(async () => queryUserList());
  290. const toSelectCount = ref(null);
  291. const startToSelectAheads = (per) => {
  292. if (Number(toSelectCount.value) && toSelectCount.value < process.value.length + 1) {
  293. per.selectedProcess = process.value.slice(0, toSelectCount.value);
  294. } else {
  295. ElMessage.error("请输入小于管号数量的整数");
  296. }
  297. };
  298. </script>
  299. <style lang="scss" scoped>
  300. #drawContent {
  301. width: 100%;
  302. }
  303. .right-btns {
  304. display: flex;
  305. justify-content: space-evenly;
  306. align-items: center;
  307. padding-top: 7px;
  308. margin-bottom: 15px;
  309. .icon-btn {
  310. width: 30px;
  311. height: 30px;
  312. }
  313. }
  314. .bottom-btns {
  315. display: flex;
  316. justify-content: center;
  317. //margin-top: 20px;
  318. //margin-bottom: 20px;
  319. .button {
  320. margin-right: 20px;
  321. }
  322. .cancelBtn {
  323. width: 292px;
  324. height: 80px;
  325. background: rgba(0, 0, 0, 0.06);
  326. border-radius: 76px 76px 76px 76px;
  327. }
  328. .sureBtn {
  329. width: 292px;
  330. height: 80px;
  331. background: #0a59f7;
  332. border-radius: 76px 76px 76px 76px;
  333. }
  334. }
  335. .guanhao-header {
  336. display: flex;
  337. justify-content: space-between;
  338. align-items: center;
  339. padding: 0 20px;
  340. gap: 20px;
  341. }
  342. </style>