index.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. <template>
  2. <div class="user">
  3. <div class="content">
  4. <byTable :source="sourceList.data" :pagination="sourceList.pagination" :config="config" :loading="loading" highlight-current-row
  5. :selectConfig="selectConfig" :action-list="[
  6. ]" @get-list="getList">
  7. <template #code="{ item }">
  8. <div style="width: 100%" class="el-click" @click="lookDetails(item)">
  9. {{item.code}}
  10. </div>
  11. </template>
  12. <template #isOverdue="{item}">
  13. <div style="width: 100%">
  14. <span class="red" v-if="item.isOverdue=='1'"> 逾期 </span>
  15. </div>
  16. </template>
  17. <template #prodTag="{ item }">
  18. <div style="width: 100%">
  19. <el-popover placement="top-start" :width="300" trigger="hover">
  20. <div>
  21. 备注:{{item.prodRemark}}
  22. </div>
  23. <template #reference>
  24. <div style="width:100%;display:inline-block">
  25. <el-tag style="margin-right: 8px" type="success" v-for="(tag, index) in item.prodTags" :key="index">
  26. {{ dictKeyValue(tag, contractTag) }}
  27. </el-tag>
  28. </div>
  29. </template>
  30. </el-popover>
  31. </div>
  32. </template>
  33. <template #list="{ item }">
  34. <div style="width:100%">
  35. <span v-for="(product ,index) in item.produceOrderDetailList" style="margin-right:15px">
  36. <el-popover placement="top-start" :width="400" trigger="hover">
  37. <div>
  38. <div>产品编码:{{product.productCode}}</div>
  39. <div>产品名称:{{product.productName}}</div>
  40. <div>产品尺寸:{{product.productLength}}cm*{{product.productWidth}}cm*{{product.productHeight}}cm</div>
  41. <div>产品颜色:{{product.productColor}}</div>
  42. <div>产品数量:{{product.quantity}}</div>
  43. </div>
  44. <template #reference>
  45. <el-progress type="circle" :percentage="(Number(product.finishQuantity) / Number(product.quantity))*100" width="60"
  46. :status="(Number(product.finishQuantity) / Number(product.quantity))*100 == 100 ? 'success' : ''" />
  47. </template>
  48. </el-popover>
  49. </span>
  50. </div>
  51. </template>
  52. </byTable>
  53. </div>
  54. <div class="schedule-right">
  55. <div class="schedule-top">
  56. <el-row>
  57. <!-- <el-col :span="10" style="text-align: left">
  58. <el-select v-model="status" style="width: 110px">
  59. <el-option v-for="item in tableStatus" :key="item.value" :label="item.label" :value="item.value" />
  60. </el-select>
  61. <el-button type="info" style="margin-left: 8px" @click="clickToday()" plain>今日</el-button>
  62. </el-col> -->
  63. <el-col :span="24" style="text-align: center; height: 32px; line-height: 32px">
  64. <div style="display: flex; justify-content: space-between">
  65. <el-button @click="clickToday()" plain>今日</el-button>
  66. <el-button :icon="ArrowLeftBold" @click="prevMonth()" />
  67. <span style="font-weight: 700">{{ month }}</span>
  68. <el-button :icon="ArrowRightBold" @click="nextMonth()" />
  69. </div>
  70. </el-col>
  71. <!-- <el-col :span="10" style="text-align: right">
  72. <el-button type="primary" @click="newSchedule()">新建日程</el-button>
  73. </el-col> -->
  74. </el-row>
  75. </div>
  76. <div class="schedule-bottom">
  77. <el-calendar v-model="today" ref="calendar">
  78. <template #date-cell="{ data }">
  79. <div style="text-align:center;height: 100%;">
  80. <div>
  81. {{ data.day.substr(8, 10) }}
  82. </div>
  83. <el-popover placement="left" :width="400" style="height" trigger="hover" @show="onShow(data.day)">
  84. <template #reference>
  85. <div v-if="isShow(data.day)">
  86. <div style="height:5px;margin-bottom:5px;border-radius:2px" v-for="(item,index) in judgeDay(data.day)" :key="index"
  87. :style="{ background: colorData[item]}">
  88. </div>
  89. </div>
  90. </template>
  91. <div style="height:500px;overflow:auto">
  92. <div v-for="item in showData" :key="item" style="margin-bottom:20px">
  93. <div style="display:flex">
  94. <div>颜色:</div>
  95. <div :style="{ background: colorData[item]}" style="width:20px;height:20px;border-radius:10px"></div>
  96. </div>
  97. <div>
  98. 订单号:<span v-if="rightDataObj[item]">{{rightDataObj[item]['code']}}</span>
  99. </div>
  100. <div>
  101. 产品:<span v-if="rightDataObj[item]">{{rightDataObj[item]['productName']}}</span>
  102. </div>
  103. </div>
  104. </div>
  105. </el-popover>
  106. </div>
  107. </template>
  108. </el-calendar>
  109. </div>
  110. </div>
  111. <el-dialog :title="modalType == 'add' ? '添加店铺' : '编辑店铺'" v-model="dialogVisible" width="500px" destroy-on-close>
  112. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="formDom" v-loading="submitLoading">
  113. </byForm>
  114. <template #footer>
  115. <el-button @click="dialogVisible = false" size="defualt">取 消</el-button>
  116. <el-button type="primary" @click="submitForm()" size="defualt" :loading="submitLoading">
  117. 确 定
  118. </el-button>
  119. </template>
  120. </el-dialog>
  121. <el-dialog :title="'投产'" v-model="productionDialog" width="500px" destroy-on-close>
  122. <byForm :formConfig="productionFormConfig" :formOption="formOption" v-model="formData.data" :rules="productionRules" ref="productionFormDom"
  123. v-loading="formLoading">
  124. </byForm>
  125. <template #footer>
  126. <el-button @click="productionDialog =false" size="default" v-debounce>取 消</el-button>
  127. <el-button @click="submitProduction" type="primary" size="default" v-debounce>提 交</el-button>
  128. </template>
  129. </el-dialog>
  130. <el-dialog :title="'确认交期'" v-model="confirmDialog" width="500px" destroy-on-close>
  131. <byForm :formConfig="confirmFormConfig" :formOption="confirmFormOption" v-model="formData.dataOne" :rules="confirmRules" ref="confirmDom"
  132. v-loading="formLoading">
  133. </byForm>
  134. <template #footer>
  135. <el-button @click="confirmDialog =false" size="default" v-debounce>取 消</el-button>
  136. <el-button @click="submitConfirm(true)" type="danger" size="default" v-debounce>驳 回</el-button>
  137. <el-button @click="submitConfirm(false)" type="primary" size="default" v-debounce>提 交</el-button>
  138. </template>
  139. </el-dialog>
  140. <el-dialog :title="'订单详情'" v-model="dialogVisible" width="90%" destroy-on-close>
  141. <byForm :formConfig="formConfig" :formOption="formOptionOne" v-model="formData.orderData" ref="formDom">
  142. <template #commodity>
  143. <div style="width: 100%">
  144. <el-table :data="formData.orderData.contractProductList" style="width: 100%; ">
  145. <el-table-column type="expand" width="50" align="center">
  146. <template #default="scope">
  147. <div style="padding-left:50px">
  148. <div style="margin-bottom:10px;">
  149. <TitleInfo content='BOM单:'></TitleInfo>
  150. </div>
  151. <el-table :data="scope.row.contractProductBomList" style="width: 100%;" border class="bom-table">
  152. <el-table-column label="图片" width="80">
  153. <template #default="{ row }">
  154. <div v-if="row.fileUrl">
  155. <img :src="row.fileUrl" class="pic" @click="onPicture(row.fileUrl)" />
  156. </div>
  157. <div v-else></div>
  158. </template>
  159. </el-table-column>
  160. <el-table-column prop="productCode" label="物料编码" width="190" />
  161. <el-table-column prop="productName" label="物料名称" min-width="200" />
  162. <el-table-column label="尺寸 (cm)" width="150">
  163. <template #default="{ row, $index }">
  164. <div style="width: 100%">
  165. {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
  166. </div>
  167. </template>
  168. </el-table-column>
  169. <el-table-column prop="quantity" label="数量" width="110" />
  170. <el-table-column prop="remark" label="备注" width="180" />
  171. </el-table>
  172. </div>
  173. </template>
  174. </el-table-column>
  175. <el-table-column label="商品图片" width="80">
  176. <template #default="{ row }">
  177. <div v-if="row.fileUrl">
  178. <img :src="row.fileUrl" class="pic" @click="onPicture(row.fileUrl)" />
  179. </div>
  180. <div v-else></div>
  181. </template>
  182. </el-table-column>
  183. <el-table-column prop="productCnName" label="商品名称" min-width="130" />
  184. <el-table-column prop="productCode" label="商品编码" width="130" />
  185. <el-table-column label="尺寸 (cm)" width="150">
  186. <template #default="{ row, $index }">
  187. <div style="width: 100%">
  188. {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
  189. </div>
  190. </template>
  191. </el-table-column>
  192. <el-table-column prop="productColor" label="颜色" width="100" />
  193. <el-table-column label="设计图稿" width="80">
  194. <template #default="{ row, $index }">
  195. <div style="width: 100%">
  196. <el-upload :action="uploadUrl" accept=".gif, .jpeg, .jpg, .png" :show-file-list="false" :data="uploadData"
  197. :before-upload="(file)=>handleBeforeUpload(file,$index)" :on-success="()=>handleSuccess($index)">
  198. <div v-loading="row.imgLoading">
  199. <img v-if="row.imageUrl" :src="row.imageUrl" class="pic" />
  200. <!-- <el-icon v-else class="avatar-uploader-icon">
  201. <Plus />
  202. </el-icon> -->
  203. </div>
  204. </el-upload>
  205. </div>
  206. </template>
  207. </el-table-column>
  208. <el-table-column label="生产源文件" width="140">
  209. <template #default="{ row, $index }">
  210. <div style="width:100%">
  211. <div v-if="row.isShowProductFile &&row.fileListOne && row.fileListOne.length > 0">
  212. <span class="el-click" @click="onPicture(row.fileListOne[0].fileUrl)">{{row.fileListOne[0].fileName}}</span>
  213. </div>
  214. <div v-else>
  215. <div v-if="row.prodFileList && row.prodFileList.length > 0">
  216. <span class="el-click" @click="onPicture(row.prodFileList[0].fileUrl)">{{row.prodFileList[0].fileName}} (定制)</span>
  217. </div>
  218. </div>
  219. </div>
  220. </template>
  221. </el-table-column>
  222. <el-table-column label="数量" width="150" prop="quantity" />
  223. <el-table-column label="备注" min-width="200" prop="remark" />
  224. </el-table>
  225. </div>
  226. </template>
  227. </byForm>
  228. <template #footer>
  229. <el-button @click="dialogVisible = false" size="defualt">取 消</el-button>
  230. </template>
  231. </el-dialog>
  232. </div>
  233. </template>
  234. <script setup>
  235. import byTable from "@/components/byTable/index";
  236. import byForm from "@/components/byForm/index";
  237. import moment from "moment";
  238. import * as date from "@/utils/date.js";
  239. import { ArrowLeftBold, ArrowRightBold } from "@element-plus/icons-vue";
  240. const { proxy } = getCurrentInstance();
  241. const contractTag = computed(
  242. () => proxy.useUserStore().allDict["contract_prod_tag"]
  243. );
  244. const companyData = ref([]);
  245. const loading = ref(false);
  246. const submitLoading = ref(false);
  247. const sourceList = ref({
  248. data: [],
  249. pagination: {
  250. total: 3,
  251. pageNum: 1,
  252. pageSize: 10,
  253. keyword: "",
  254. produceStatus: "",
  255. staDeliveryPeriod: "",
  256. endDeliveryPeriod: "",
  257. beginTime: "",
  258. endTime: "",
  259. companyId: "",
  260. isOverdue: "",
  261. },
  262. });
  263. const treeData = ref([]);
  264. const dialogVisible = ref(false);
  265. const modalType = ref("add");
  266. const status = ref("0");
  267. const today = ref(moment().format("yyyy-MM-DD"));
  268. const dateList = ref({});
  269. const month = ref(moment().format("yyyy年MM月"));
  270. const monthOne = ref(moment().format("yyyy-MM"));
  271. const calendar = ref(null);
  272. const statusData = ref([
  273. {
  274. label: "未开始",
  275. value: "0",
  276. },
  277. {
  278. label: "进行中",
  279. value: "1",
  280. },
  281. {
  282. label: "已完成",
  283. value: "2",
  284. },
  285. ]);
  286. const isOverdueData = ref([
  287. {
  288. label: "是",
  289. value: "1",
  290. },
  291. {
  292. label: "否",
  293. value: "0",
  294. },
  295. ]);
  296. const selectConfig = computed(() => [
  297. // {
  298. // label: "生产公司",
  299. // prop: "companyId",
  300. // data: companyData.value,
  301. // fn: () => {
  302. // getRightData();
  303. // },
  304. // },
  305. {
  306. label: "生产状态",
  307. prop: "produceStatus",
  308. data: statusData.value,
  309. },
  310. {
  311. label: "是否逾期",
  312. prop: "isOverdue",
  313. data: isOverdueData.value,
  314. },
  315. {
  316. type: "time",
  317. label: "交期",
  318. placeholder: "开始日期",
  319. prop: "staDeliveryPeriod",
  320. placeholderOne: "结束日期",
  321. propOne: "endDeliveryPeriod",
  322. },
  323. {
  324. type: "time",
  325. label: "下单日期",
  326. placeholder: "开始日期",
  327. prop: "beginTime",
  328. placeholderOne: "结束日期",
  329. propOne: "endTime",
  330. },
  331. ]);
  332. const config = computed(() => {
  333. return [
  334. {
  335. attrs: {
  336. label: "生产公司",
  337. prop: "companyName",
  338. width: 130,
  339. },
  340. },
  341. {
  342. attrs: {
  343. label: "订单号",
  344. slot: "code",
  345. width: 150,
  346. },
  347. },
  348. {
  349. attrs: {
  350. label: "下单时间",
  351. prop: "createTime",
  352. width: 160,
  353. },
  354. },
  355. {
  356. attrs: {
  357. label: "生产状态",
  358. prop: "produceStatus",
  359. width: 120,
  360. },
  361. render(val) {
  362. return proxy.dictValueLabel(val, statusData.value);
  363. },
  364. },
  365. {
  366. attrs: {
  367. label: "交期",
  368. prop: "deliveryPeriod",
  369. width: 160,
  370. },
  371. },
  372. {
  373. attrs: {
  374. label: "投产时间",
  375. prop: "produceTime",
  376. width: 160,
  377. },
  378. },
  379. {
  380. attrs: {
  381. label: "完工时间",
  382. prop: "finishTime",
  383. width: 160,
  384. },
  385. },
  386. {
  387. attrs: {
  388. label: "是否逾期",
  389. slot: "isOverdue",
  390. width: 80,
  391. },
  392. },
  393. {
  394. attrs: {
  395. label: "生产指示",
  396. slot: "prodTag",
  397. "min-width": 220,
  398. },
  399. },
  400. {
  401. attrs: {
  402. slot: "list",
  403. label: "产品生产进度",
  404. // prop: "name",
  405. "min-width": 300,
  406. },
  407. },
  408. {
  409. attrs: {
  410. label: "操作",
  411. width: "100",
  412. align: "center",
  413. fixed: "right",
  414. },
  415. renderHTML(row) {
  416. return [
  417. row.produceTime || !proxy.isCurrentCompanyData(row.companyId)
  418. ? {}
  419. : {
  420. attrs: {
  421. label: "投产",
  422. type: "primary",
  423. text: true,
  424. },
  425. el: "button",
  426. click() {
  427. clickDistributeProduction(row);
  428. },
  429. },
  430. row.produceTime || !proxy.isCurrentCompanyData(row.companyId)
  431. ? {}
  432. : {
  433. attrs: {
  434. label: "确认交期",
  435. type: "primary",
  436. text: true,
  437. },
  438. el: "button",
  439. click() {
  440. confirmDeliveryTime(row);
  441. },
  442. },
  443. ];
  444. },
  445. },
  446. ];
  447. });
  448. const formData = reactive({
  449. data: {},
  450. orderData: {},
  451. dataOne: {},
  452. });
  453. const formOption = reactive({
  454. inline: true,
  455. labelWidth: 100,
  456. itemWidth: 100,
  457. });
  458. const formOptionOne = reactive({
  459. inline: true,
  460. labelWidth: 100,
  461. itemWidth: 100,
  462. disabled: true,
  463. });
  464. const formDom = ref(null);
  465. const formConfig = computed(() => {
  466. return [
  467. {
  468. type: "title1",
  469. title: "基本信息",
  470. },
  471. {
  472. type: "text",
  473. prop: "code",
  474. label: "合同号:",
  475. disabled: true,
  476. isShow: formData.orderData.code ? true : false,
  477. },
  478. {
  479. type: "title1",
  480. title: "商品信息",
  481. haveLine: true,
  482. },
  483. {
  484. type: "slot",
  485. slotName: "commodity",
  486. label: "",
  487. },
  488. ];
  489. });
  490. const rules = ref({
  491. deptId: [{ required: true, message: "请选择负责部门", trigger: "change" }],
  492. name: [{ required: true, message: "请输入店铺名称", trigger: "blur" }],
  493. code: [{ required: true, message: "请输入店铺编号", trigger: "blur" }],
  494. });
  495. const getList = async (req) => {
  496. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  497. loading.value = true;
  498. proxy.post("/produceOrder/page", sourceList.value.pagination).then((res) => {
  499. res.rows.forEach((x) => {
  500. if (x.prodTag) {
  501. x.prodTags = x.prodTag.split(",");
  502. } else {
  503. x.prodTags = [];
  504. }
  505. });
  506. sourceList.value.data = res.rows;
  507. sourceList.value.pagination.total = res.total;
  508. setTimeout(() => {
  509. loading.value = false;
  510. }, 200);
  511. });
  512. };
  513. const openModal = () => {
  514. dialogVisible.value = true;
  515. modalType.value = "add";
  516. formData.data = {
  517. definition: "2",
  518. fileList: [],
  519. };
  520. if (currencyData.value && currencyData.value.length > 0) {
  521. formData.data.currency = currencyData.value[0].dictKey;
  522. formData.data.costCurrency = currencyData.value[0].dictKey;
  523. }
  524. };
  525. const submitForm = () => {
  526. formDom.value.handleSubmit((valid) => {
  527. submitLoading.value = true;
  528. proxy.post("/shopInfo/" + modalType.value, formData.data).then(
  529. (res) => {
  530. proxy.msgTip("操作成功", 1);
  531. dialogVisible.value = false;
  532. submitLoading.value = false;
  533. getList();
  534. },
  535. (err) => {
  536. submitLoading.value = false;
  537. }
  538. );
  539. });
  540. };
  541. const getDtl = (row) => {
  542. modalType.value = "edit";
  543. proxy.post("/shopInfo/detail", { id: row.id }).then((res) => {
  544. formData.data = res;
  545. dialogVisible.value = true;
  546. });
  547. };
  548. getList();
  549. const productionFormDom = ref(null);
  550. const productionDialog = ref(false);
  551. const formLoading = ref(false);
  552. const productionFormConfig = computed(() => [
  553. {
  554. type: "date",
  555. itemType: "datetime",
  556. label: "投产时间",
  557. prop: "produceTime",
  558. // placeholder: "合同开始时间",
  559. itemWidth: 100,
  560. clearable: true,
  561. disabledFn: (date) => {
  562. return moment(date).isBefore(moment());
  563. },
  564. },
  565. ]);
  566. const productionRules = ref({
  567. produceTime: [
  568. { required: true, message: "请选择投产时间", trigger: "change" },
  569. ],
  570. });
  571. const clickDistributeProduction = (row) => {
  572. formData.data = {
  573. id: row.id,
  574. produceTime: moment().format("yyyy-MM-DD HH:mm:ss"),
  575. };
  576. productionDialog.value = true;
  577. // proxy
  578. // .msgConfirm()
  579. // .then((res) => {
  580. // proxy.post("/produceOrder/putProduction", formData.data).then((res) => {
  581. // proxy.msgTip("操作成功");
  582. // formLoading.value = false;
  583. // productionDialog.value = false;
  584. // getList();
  585. // getRightData();
  586. // });
  587. // })
  588. // .catch((err) => {});
  589. };
  590. const submitProduction = () => {
  591. productionFormDom.value.handleSubmit(() => {
  592. formLoading.value = true;
  593. proxy.post("/produceOrder/putProduction", formData.data).then((res) => {
  594. proxy.msgTip("操作成功");
  595. formLoading.value = false;
  596. productionDialog.value = false;
  597. getList();
  598. getRightData();
  599. });
  600. });
  601. };
  602. const rightData = ref([]);
  603. const rightDataObj = ref({});
  604. const colorData = ref({});
  605. let colorList = [
  606. "#BBFF00",
  607. "#FFFF00",
  608. "#FFBB00",
  609. "#FF3333",
  610. "#D28EFF",
  611. "#CCEEFF",
  612. "#FFC8B4",
  613. "#CCDDFF",
  614. "#007799",
  615. "#550088",
  616. "#AAFFEE",
  617. "#FFB3FF",
  618. "#FFFF33",
  619. ];
  620. const getRightData = () => {
  621. proxy
  622. .post("/produceOrder/schedulingList", {
  623. beginDate: monthOne.value,
  624. companyId: sourceList.value.pagination.companyId,
  625. })
  626. .then(
  627. (res) => {
  628. rightDataObj.value = {};
  629. rightData.value = res.map((x, index) => ({
  630. ...x,
  631. produceTimeOne: x.produceTime,
  632. produceTime: x.produceTime.substr(0, 10),
  633. deliveryPeriod: x.deliveryPeriod.substr(0, 10),
  634. }));
  635. for (let i = 0; i < res.length; i++) {
  636. const ele = res[i];
  637. rightDataObj.value[ele.id] = ele;
  638. if (i <= 12) {
  639. colorData.value[ele.id] = colorList[i];
  640. } else {
  641. let index = Math.floor(i % 12);
  642. colorData.value[ele.id] = colorList[index];
  643. }
  644. }
  645. },
  646. (err) => {
  647. loading.value = false;
  648. }
  649. );
  650. };
  651. getRightData();
  652. const getBackGround = (id) => {
  653. return { background: colorData.value[id] };
  654. };
  655. const prodTagClose = (index, row) => {
  656. row.prodTags.splice(index, 1);
  657. proxy
  658. .post("/contract/updateProductionTag", {
  659. id: row.contractId,
  660. prodTag: row.prodTags.join(","),
  661. })
  662. .then((res) => {
  663. getList();
  664. });
  665. };
  666. const getDict = () => {
  667. proxy
  668. .get("/tenantDept/list", {
  669. pageNum: 1,
  670. pageSize: 9999,
  671. keyword: "",
  672. tenantId: proxy.useUserStore().user.tenantId,
  673. type: 0,
  674. })
  675. .then((res) => {
  676. companyData.value = res.data.map((x) => ({
  677. ...x,
  678. label: x.deptName,
  679. value: x.deptId,
  680. }));
  681. // treeData.value = proxy.handleTree(res.data, "deptId");
  682. });
  683. };
  684. getDict();
  685. const clickToday = () => {
  686. today.value = moment().format("yyyy-MM-DD");
  687. month.value = moment().format("yyyy年MM月");
  688. monthOne.value = moment().format("yyyy-MM");
  689. getRightData();
  690. };
  691. const isShow = (day) => {
  692. let nowDay = new Date(day + " 23:59:59").getTime();
  693. let flag = false;
  694. for (let i = 0; i < rightData.value.length; i++) {
  695. const e = rightData.value[i];
  696. let startDay = new Date(e.produceTime).getTime();
  697. let endDay = new Date(e.deliveryPeriod + " 23:59:59").getTime();
  698. if (nowDay >= startDay && nowDay <= endDay) {
  699. flag = true;
  700. break;
  701. }
  702. }
  703. return flag;
  704. };
  705. const judgeDay = (day) => {
  706. // return dateList.value[day] && dateList.value[day].length > 0;
  707. let nowDay = new Date(day + " 23:59:59").getTime();
  708. let rows = [];
  709. for (let i = 0; i < rightData.value.length; i++) {
  710. const e = rightData.value[i];
  711. let startDay = new Date(e.produceTime).getTime();
  712. let endDay = new Date(e.deliveryPeriod + " 23:59:59").getTime();
  713. if (nowDay >= startDay && nowDay <= endDay) {
  714. rows.push(e.id);
  715. }
  716. }
  717. return rows;
  718. };
  719. const showData = ref([]);
  720. const onShow = (day) => {
  721. let rows = judgeDay(day);
  722. showData.value = rows;
  723. };
  724. const getData = (id, att) => {
  725. const current = rightData.value.find((x) => x.id == id);
  726. if (current && current[att]) {
  727. return current[att];
  728. }
  729. };
  730. const selectDate = (val) => {
  731. calendar.value.selectDate(val);
  732. };
  733. const prevMonth = () => {
  734. month.value = moment(
  735. moment(month.value, "yyyy年MM月").add(-1, "month").calendar()
  736. ).format("yyyy年MM月");
  737. monthOne.value = moment(moment(month.value, "yyyy年MM月")).format("yyyy-MM");
  738. selectDate("prev-month");
  739. getRightData();
  740. };
  741. const nextMonth = () => {
  742. month.value = moment(
  743. moment(month.value, "yyyy年MM月").add(+1, "month").calendar()
  744. ).format("yyyy年MM月");
  745. monthOne.value = moment(moment(month.value, "yyyy年MM月")).format("yyyy-MM");
  746. selectDate("next-month");
  747. getRightData();
  748. };
  749. watch(
  750. () => today.value,
  751. (newValue) => {
  752. if (month.value !== moment(newValue).format("yyyy年MM月")) {
  753. month.value = moment(newValue).format("yyyy年MM月");
  754. monthOne.value = moment(moment(month.value, "yyyy年MM月")).format(
  755. "yyyy-MM"
  756. );
  757. getRightData();
  758. }
  759. }
  760. );
  761. const getFileData = () => {
  762. let ids = [];
  763. formData.orderData.contractProductList.map((x) => {
  764. // ids.push(x.productId);
  765. x.contractProductBomList.map((y) => {
  766. ids.push(y.materialId);
  767. });
  768. });
  769. ids = Array.from(new Set(ids));
  770. proxy
  771. .post("/fileInfo/getList", {
  772. businessIdList: ids,
  773. })
  774. .then((fileObj) => {
  775. formData.orderData.contractProductList.map((x) => {
  776. // if (fileObj[x.productId] && fileObj[x.productId].length > 0) {
  777. // x.fileUrl = fileObj[x.productId][0].fileUrl;
  778. // }
  779. x.contractProductBomList.map((y) => {
  780. y.fileList = fileObj[y.materialId] || [];
  781. if (y.fileList && y.fileList.length > 0) {
  782. y.fileUrl = y.fileList[0].fileUrl;
  783. }
  784. });
  785. });
  786. });
  787. };
  788. const lookDetails = (item) => {
  789. proxy.post("/contract/detail", { id: item.contractId }).then((res) => {
  790. formData.orderData = res;
  791. dialogVisible.value = true;
  792. if (
  793. formData.orderData.contractProductList &&
  794. formData.orderData.contractProductList.length > 0
  795. ) {
  796. getFileData();
  797. let ids = formData.orderData.contractProductList.map((x) => x.id);
  798. let productIds = formData.orderData.contractProductList.map(
  799. (x) => x.productId
  800. );
  801. proxy.getFileData({
  802. businessIdList: productIds,
  803. data: formData.orderData.contractProductList,
  804. att: "productId",
  805. businessType: "0",
  806. fileAtt: "productFile",
  807. filePathAtt: "fileUrl",
  808. });
  809. proxy
  810. .getFileData({
  811. businessIdList: ids,
  812. getAll: true,
  813. })
  814. .then((fileObj) => {
  815. for (
  816. let i = 0;
  817. i < formData.orderData.contractProductList.length;
  818. i++
  819. ) {
  820. const ele = formData.orderData.contractProductList[i];
  821. for (const key in fileObj) {
  822. if (
  823. ele.id == key &&
  824. fileObj[ele.id] &&
  825. fileObj[ele.id].length > 0
  826. ) {
  827. ele.fileListOne = fileObj[ele.id].filter(
  828. (x) => x.businessType == "0"
  829. );
  830. if (ele.fileListOne && ele.fileListOne.length > 0) {
  831. ele.imageUrl = ele.fileListOne[0].fileUrl;
  832. }
  833. ele.prodFileList = fileObj[ele.id]
  834. .filter((x) => x.businessType == "1")
  835. .map((x) => ({ ...x, name: x.fileName, url: x.fileUrl }));
  836. if (ele.prodFileList && ele.prodFileList.length > 0) {
  837. ele.isShowProductFile = false;
  838. } else {
  839. ele.isShowProductFile = true;
  840. }
  841. }
  842. }
  843. }
  844. });
  845. }
  846. });
  847. };
  848. const handleClickUpload = async (att, flag, index) => {
  849. let res = null;
  850. let path = "";
  851. if (flag) {
  852. proxy.msgTip("请稍后", 2);
  853. res = await proxy.post("/fileService/createTempFolder");
  854. if (res && res.path) {
  855. formData.data.contractProductList[index][att] = res.path;
  856. path = res.path;
  857. }
  858. } else {
  859. path = formData.data.contractProductList[index][att];
  860. }
  861. let a = document.createElement("a");
  862. a.href = "printer://" + "ftp://121.37.194.75/" + path + "/";
  863. a.style.display = "none";
  864. document.body.appendChild(a);
  865. a.click();
  866. document.body.removeChild(a);
  867. };
  868. const onPicture = (path) => {
  869. window.open(path, "_blank");
  870. };
  871. const confirmFormDom = ref(null);
  872. const confirmDialog = ref(false);
  873. const confirmFormOption = reactive({
  874. inline: true,
  875. labelWidth: 100,
  876. itemWidth: 100,
  877. disabled: false,
  878. });
  879. const confirmFormConfig = computed(() => [
  880. {
  881. type: "input",
  882. itemType: "textarea",
  883. label: "退回原因",
  884. prop: "aa",
  885. // placeholder: "合同开始时间",
  886. itemWidth: 100,
  887. // clearable: true,
  888. // disabledFn: (date) => {
  889. // return moment(date).isBefore(moment());
  890. // },
  891. },
  892. ]);
  893. const confirmRules = ref({});
  894. const confirmDeliveryTime = (row) => {
  895. formData.dataOne = {
  896. id: row.id,
  897. aa: "",
  898. };
  899. confirmDialog.value = true;
  900. };
  901. const submitConfirm = () => {
  902. confirmFormDom.value.handleSubmit(() => {
  903. if (!formData.dataOne.aa) {
  904. return proxy.msgTip("请填写退回原因", 2);
  905. }
  906. formLoading.value = true;
  907. proxy.post("/produceOrder/putProduction", formData.data).then((res) => {
  908. proxy.msgTip("操作成功");
  909. formLoading.value = false;
  910. confirmDialog.value = false;
  911. getList();
  912. getRightData();
  913. });
  914. });
  915. };
  916. </script>
  917. <style lang="scss" scoped>
  918. ::v-deep(.el-progress__text) {
  919. font-size: 14px !important;
  920. }
  921. .user {
  922. padding: 10px;
  923. display: flex;
  924. justify-content: space-between;
  925. .schedule-right {
  926. width: 400px;
  927. .schedule-top {
  928. width: 100%;
  929. background: #fff;
  930. padding: 20px;
  931. }
  932. .schedule-bottom {
  933. width: 100%;
  934. background: #fff;
  935. height: calc(100vh - 100px - 20px - 83px);
  936. padding: 20px;
  937. margin-top: 10px;
  938. overflow-y: auto;
  939. &::-webkit-scrollbar {
  940. width: 0px;
  941. }
  942. .line-class {
  943. height: 18px;
  944. line-height: 18px;
  945. overflow: hidden;
  946. white-space: nowrap;
  947. text-overflow: ellipsis;
  948. -o-text-overflow: ellipsis;
  949. margin: 1px 0;
  950. }
  951. }
  952. }
  953. .content {
  954. width: calc(100% - 410px);
  955. }
  956. }
  957. ::v-deep(.el-calendar__header) {
  958. display: none;
  959. }
  960. ::v-deep(.el-calendar__body) {
  961. padding: 0;
  962. }
  963. ::v-deep(.el-calendar-table .el-calendar-day) {
  964. // padding: 0;
  965. min-height: 50px;
  966. height: calc((100vh - 100px - 20px - 83px - 95px) / 5);
  967. overflow-y: hidden;
  968. }
  969. .el-icon.avatar-uploader-icon {
  970. font-size: 20px;
  971. color: #8c939d;
  972. width: 50px;
  973. height: 50px;
  974. text-align: center;
  975. border: 1px dashed var(--el-border-color);
  976. }
  977. .red {
  978. background: red;
  979. border-radius: 2px;
  980. padding: 4px;
  981. color: #fff;
  982. }
  983. </style>