index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. <template>
  2. <div class="mainContentBox">
  3. <avue-crud
  4. ref="crudRef"
  5. :option="option"
  6. v-model:page="page"
  7. v-model:search="search"
  8. v-model="form"
  9. :table-loading="loading"
  10. :permission="permission"
  11. @search-change="handleQuery"
  12. @search-reset="resetQuery"
  13. @size-change="handleQuery"
  14. @current-change="handleQuery"
  15. @row-save="rowSave"
  16. @row-update="rowUpdate"
  17. @row-del="rowDel"
  18. :data="pageData"
  19. >
  20. <template #menu-right="{}">
  21. <el-dropdown split-button v-hasPerm="['plan:order:import']"
  22. >导入
  23. <template #dropdown>
  24. <el-dropdown-menu>
  25. <el-dropdown-item @click="downloadTemplate">
  26. <i-ep-download />下载模板
  27. </el-dropdown-item>
  28. <el-dropdown-item @click="openDialog('obj-import')">
  29. <i-ep-top />导入数据
  30. </el-dropdown-item>
  31. </el-dropdown-menu>
  32. </template>
  33. </el-dropdown>
  34. <el-button
  35. class="ml-3"
  36. v-hasPerm="['plan:order:export']"
  37. @click="handleExport"
  38. >
  39. <template #icon> <i-ep-download /> </template>导出
  40. </el-button>
  41. </template>
  42. <template #menu="{size,row,index}">
  43. <el-button
  44. v-hasPerm="[buttonPermission.PLAN.BTNS.order_edit]"
  45. v-if="row.orderState === '0' || row.orderState === '1' || row.orderState === '2'"
  46. type="primary"
  47. link
  48. size="small"
  49. @click="handleEdit(row,0)"
  50. ><i-ep-edit />编辑
  51. </el-button>
  52. <el-button
  53. v-if="row.nameplated === 1"
  54. type="info"
  55. link
  56. size="small"
  57. @click="handleNameplated(row)"
  58. ><i-ep-edit />铭牌
  59. </el-button>
  60. <el-button
  61. v-hasPerm="[buttonPermission.PLAN.BTNS.order_del]"
  62. v-if="row.orderState === '0' || row.orderState === '1' || row.orderState === '2'"
  63. type="danger"
  64. link
  65. size="small"
  66. @click="rowDel(row,0)"
  67. ><i-ep-edit />删除
  68. </el-button>
  69. </template>
  70. </avue-crud>
  71. <el-dialog
  72. v-model="dialog1.visible"
  73. :title="dialog1.title"
  74. width="950px"
  75. @close="dialog1.visible = false"
  76. >
  77. <choice-item-page @materialInfo="materialInfo"/>
  78. </el-dialog>
  79. <el-dialog
  80. v-model="dialog.visible"
  81. :title="dialog.title"
  82. width="500px"
  83. @close="closeDialog"
  84. >
  85. <el-form
  86. v-if="dialog.type === 'obj-import'"
  87. :model="importData"
  88. label-width="100px"
  89. >
  90. <el-form-item label="Excel文件">
  91. <el-upload
  92. ref="uploadRef"
  93. action=""
  94. drag
  95. accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
  96. :limit="1"
  97. :auto-upload="false"
  98. :file-list="importData.fileList"
  99. :on-change="handleFileChange"
  100. :on-exceed="handleFileExceed"
  101. >
  102. <el-icon class="el-icon--upload">
  103. <i-ep-upload-filled />
  104. </el-icon>
  105. <div class="el-upload__text">
  106. 将文件拖到此处,或
  107. <em>点击上传</em>
  108. </div>
  109. <template #tip>
  110. <div style="color: red">文件类型: xls/xlsx</div>
  111. </template>
  112. </el-upload>
  113. </el-form-item>
  114. </el-form>
  115. <!-- 弹窗底部操作按钮 -->
  116. <template #footer>
  117. <div class="dialog-footer">
  118. <el-button type="primary" @click="handleSubmit">确 定</el-button>
  119. <el-button @click="closeDialog">取 消</el-button>
  120. </div>
  121. </template>
  122. </el-dialog>
  123. </div>
  124. </template>
  125. <script setup lang="ts">
  126. import { checkPerm } from "@/directive/permission";
  127. import type { UploadInstance } from "element-plus";
  128. import { genFileId } from "element-plus";
  129. import dictDataUtil from "@/common/configs/dictDataUtil";
  130. import buttonPermission from "@/common/configs/buttonPermission";
  131. import {
  132. addOrder,
  133. deleteOrders,
  134. downloadTemplateApi,
  135. exportOrder,
  136. getOrderPage,
  137. importOrder,
  138. updateOrder,
  139. getExpandAlias,
  140. } from "@/api/order";
  141. import {ref} from "vue";
  142. import ChoiceItemPage from "@/views/base/materials/components/choice-item-page.vue";
  143. // 弹窗对象
  144. const dialog = reactive({
  145. visible: false,
  146. type: "order-form",
  147. width: 800,
  148. title: "",
  149. });
  150. const search = ref({});
  151. const option = ref({});
  152. const pageData = ref([]);
  153. const form = ref({});
  154. const page = ref({ total: 0, currentPage: 1, pageSize: 10 });
  155. const loading = ref(false);
  156. const uploadRef = ref<UploadInstance>(); // 上传组件
  157. // 导入数据
  158. const importData = reactive({
  159. file: undefined,
  160. fileList: [],
  161. });
  162. const materialInfo = (value) => {
  163. form.value.materialCode = value.materialCode
  164. form.value.materialName = value.materialName
  165. form.value.materialModel = value.spec
  166. dialog1.visible = false
  167. }
  168. const dialog1 = reactive({
  169. title: "物料选择",
  170. visible: false,
  171. });
  172. const permission = reactive({
  173. delBtn: checkPerm(buttonPermission.PLAN.BTNS.order_del),
  174. addBtn: checkPerm(buttonPermission.PLAN.BTNS.order_add),
  175. editBtn: checkPerm(buttonPermission.PLAN.BTNS.order_edit),
  176. menu: true,
  177. });
  178. const crudRef = ref(null); //crudRef.value 获取avue-crud对象
  179. option.value = {
  180. border: true,
  181. searchIndex: 3,
  182. searchIcon: true,
  183. editBtn: false,
  184. delBtn: false,
  185. searchMenuSpan: 8,
  186. align: "center",
  187. menuAlign: "center",
  188. search: true,
  189. refreshBtn: false,
  190. from: {
  191. width: "300",
  192. },
  193. column: [
  194. {
  195. label: "订单编号",
  196. prop: "orderCode",
  197. search: true,
  198. width: 130,
  199. overHidden: true,
  200. display: false,
  201. },
  202. {
  203. label: "订单名称",
  204. prop: "orderName",
  205. search: true,
  206. width: 150,
  207. overHidden: true,
  208. rules: [
  209. {
  210. required: true,
  211. message: "订单名称不能为空",
  212. trigger: "trigger",
  213. },
  214. ],
  215. },
  216. {
  217. label: "ERP号",
  218. prop: "erpCode",
  219. search: true,
  220. width: 130,
  221. overHidden: true,
  222. rules: [
  223. {
  224. required: true,
  225. message: "订单编号不能为空",
  226. trigger: "trigger",
  227. },
  228. ],
  229. },
  230. {
  231. label: "产品编码",
  232. prop: "materialCode",
  233. search: true,
  234. width: 130,
  235. overHidden: true,
  236. rules: [
  237. {
  238. required: true,
  239. message: "订单编号不能为空",
  240. trigger: "trigger",
  241. },
  242. ],
  243. click: ({ value, column }) => {
  244. if(column.boxType){
  245. dialog1.visible = true
  246. }
  247. },
  248. },
  249. {
  250. label: "产品名称",
  251. prop: "materialName",
  252. search: true,
  253. width: 130,
  254. overHidden: true,
  255. rules: [
  256. {
  257. required: true,
  258. message: "产品名称不能为空",
  259. trigger: "trigger",
  260. },
  261. ],
  262. disabled: true,
  263. },
  264. {
  265. label: "产品规格",
  266. width: 130,
  267. overHidden: true,
  268. disabled: true,
  269. prop: "materialModel",
  270. },
  271. {
  272. label: "订单状态",
  273. prop: "orderState",
  274. display: false,
  275. width: 100,
  276. overHidden: true,
  277. type: "select", //类型为下拉选择框
  278. dicUrl:
  279. dictDataUtil.request_url + dictDataUtil.TYPE_CODE.plan_order_state,
  280. props: {
  281. label: "dictLabel",
  282. value: "dictValue",
  283. },
  284. searchClearable: false, //可清空的输入框,默认为true
  285. filterable: true, //添加filterable属性即可启用搜索功能
  286. },
  287. {
  288. label: "订单类型",
  289. prop: "orderType",
  290. type: "select", //类型为下拉选择框
  291. width: 100,
  292. overHidden: true,
  293. dicUrl: dictDataUtil.request_url + dictDataUtil.TYPE_CODE.plan_order_type,
  294. props: {
  295. label: "dictLabel",
  296. value: "dictValue",
  297. },
  298. searchClearable: false, //可清空的输入框,默认为true
  299. filterable: true, //添加filterable属性即可启用搜索功能
  300. rules: [
  301. {
  302. required: true,
  303. message: "订单类型不能为空",
  304. trigger: "trigger",
  305. },
  306. ],
  307. },
  308. {
  309. label: "订单数量",
  310. prop: "orderNum",
  311. type: "number",
  312. width: 100,
  313. overHidden: true,
  314. min: 1,
  315. max: 99999,
  316. rules: [
  317. {
  318. required: true,
  319. message: "订单数量不能为空",
  320. trigger: "trigger",
  321. },
  322. ],
  323. },
  324. {
  325. label: "排产数量",
  326. prop: "scheduledNum",
  327. width: 100,
  328. overHidden: true,
  329. display: false,
  330. },
  331. {
  332. label: "优先级",
  333. prop: "priority",
  334. width: 100,
  335. overHidden: true,
  336. type: "select", //类型为下拉选择框
  337. dicUrl:
  338. dictDataUtil.request_url + dictDataUtil.TYPE_CODE.plan_order_priority,
  339. props: {
  340. label: "dictLabel",
  341. value: "dictValue",
  342. },
  343. searchClearable: false, //可清空的输入框,默认为true
  344. filterable: true, //添加filterable属性即可启用搜索功能
  345. rules: [
  346. {
  347. required: true,
  348. message: "订单类型不能为空",
  349. trigger: "trigger",
  350. },
  351. ],
  352. },
  353. {
  354. label: "交付日期",
  355. prop: "deliverTime",
  356. type: "date",
  357. width: 100,
  358. overHidden: true,
  359. format: "YYYY-MM-DD", //前端展示格式
  360. valueFormat: "YYYY-MM-DD", //设置后端接收的日期格式
  361. rules: [
  362. {
  363. required: true,
  364. message: "请选择交付日期",
  365. trigger: "trigger",
  366. },
  367. ],
  368. },
  369. {
  370. label: "所属公司",
  371. prop: "companyId",
  372. width: 100,
  373. overHidden: true,
  374. type: "select", //类型为下拉选择框
  375. dicUrl: import.meta.env.VITE_APP_BASE_API + "/api/v1/sys/dept/orgList",
  376. props: {
  377. label: "deptName",
  378. value: "id",
  379. },
  380. rules: [
  381. {
  382. required: true,
  383. message: "请选择所属公司",
  384. trigger: "trigger",
  385. },
  386. ],
  387. },
  388. {
  389. label: "项目号",
  390. width: 100,
  391. overHidden: true,
  392. prop: "projectCode",
  393. },
  394. {
  395. label: "绑定铭牌",
  396. prop: "nameplated",
  397. width: "100",
  398. type: "radio", //类型为单选框
  399. dicData: [
  400. {
  401. label: "否",
  402. value: 0,
  403. },
  404. {
  405. label: "是",
  406. value: 1,
  407. },
  408. ],
  409. value: 0,
  410. },
  411. {
  412. label: "备注",
  413. prop: "remark",
  414. width: 100,
  415. overHidden: true,
  416. minRows: 2, //最小行/最小值
  417. type: "textarea", //类型为多行文本域框
  418. maxlength: 512, //最大输入长度
  419. },
  420. {
  421. label: "创建时间",
  422. prop: "created",
  423. width: "140",
  424. overHidden: true,
  425. display: false,
  426. type: "datetime",
  427. valueFormat: "yyyy-MM-dd HH:mm:ss",
  428. },
  429. {
  430. label: "创建人",
  431. prop: "creator",
  432. display: false,
  433. width: 80,
  434. overHidden: true,
  435. },
  436. ],
  437. };
  438. const queryExpandAlias = () => {
  439. getExpandAlias(dictDataUtil.EXPAND_FIELD_TABLE.plan_order_info).then(
  440. (data: any) => {
  441. if (data.data) {
  442. data.data.forEach((item: any) => {
  443. option.value.column.push({
  444. label: item.label,
  445. prop: item.field,
  446. width: 100,
  447. overHidden: true,
  448. });
  449. });
  450. }
  451. }
  452. );
  453. };
  454. const handleQuery = (params, done) => {
  455. console.log(JSON.stringify(option.value.column));
  456. loading.value = true;
  457. const querySearch = {
  458. pageSize: page.value.pageSize,
  459. pageNo: page.value.currentPage,
  460. ...params,
  461. };
  462. getOrderPage(querySearch)
  463. .then(({ data }) => {
  464. pageData.value = data.records;
  465. page.value.total = data.totalCount;
  466. page.value.currentPage = data.pageNo;
  467. page.value.pageSize = data.pageSize;
  468. })
  469. .finally(() => {
  470. loading.value = false;
  471. if (done) {
  472. done();
  473. }
  474. });
  475. };
  476. const resetQuery = () => {};
  477. const rowSave = (form, done, loading) => {
  478. loading();
  479. addOrder(form).then((data: any) => {
  480. ElMessage({
  481. message: data.msg,
  482. type: "success",
  483. });
  484. done();
  485. handleQuery(null, null);
  486. });
  487. };
  488. const rowUpdate = (form, index, done, loading) => {
  489. loading();
  490. updateOrder(form).then((data: any) => {
  491. ElMessage({
  492. message: data.msg,
  493. type: "success",
  494. });
  495. done();
  496. handleQuery(null, null);
  497. });
  498. };
  499. const handleNameplated = (row) =>{
  500. ElMessage.warning("功能开发中")
  501. }
  502. const rowDel = (form: any, index) => {
  503. ElMessageBox.confirm("当前操作会删除数据,你确认要继续吗?")
  504. .then(() => {
  505. deleteOrders([form.id])
  506. .then((data: any) => {
  507. ElMessage({
  508. message: data.msg,
  509. type: "success",
  510. });
  511. handleQuery(null, null);
  512. })
  513. .finally(() => {});
  514. })
  515. .catch(() => {
  516. // catch error
  517. });
  518. };
  519. const openDialog = (type) => {
  520. dialog.visible = true;
  521. dialog.type = type;
  522. if (dialog.type === "obj-import") {
  523. // 导入弹窗
  524. dialog.title = "数据导入";
  525. dialog.width = 600;
  526. }
  527. };
  528. const closeDialog = () => {
  529. dialog.visible = false;
  530. if (dialog.type === "obj-import") {
  531. importData.file = undefined;
  532. importData.fileList = [];
  533. }
  534. };
  535. const downloadTemplate = () => {
  536. downloadTemplateApi().then((response) => {
  537. downFile(response);
  538. });
  539. };
  540. const handleEdit = (row, index) =>{
  541. crudRef.value && crudRef.value.rowEdit(row, index);
  542. }
  543. /** 弹窗提交 */
  544. const handleSubmit = () => {
  545. importOrder(importData).then((data: any) => {
  546. ElMessage({
  547. message: data.msg,
  548. type: "success",
  549. });
  550. dialog.visible = false;
  551. handleQuery(null, null);
  552. });
  553. };
  554. /** Excel文件 Change */
  555. const handleFileChange = (file) => {
  556. importData.file = file.raw;
  557. };
  558. /** 文件下载 */
  559. const downFile = (response: any) => {
  560. const fileData = response.data;
  561. const fileName = decodeURI(
  562. response.headers["content-disposition"].split(";")[1].split("=")[1]
  563. );
  564. const fileType =
  565. "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
  566. const blob = new Blob([fileData], { type: fileType });
  567. const downloadUrl = window.URL.createObjectURL(blob);
  568. const downloadLink = document.createElement("a");
  569. downloadLink.href = downloadUrl;
  570. downloadLink.download = fileName;
  571. document.body.appendChild(downloadLink);
  572. downloadLink.click();
  573. document.body.removeChild(downloadLink);
  574. window.URL.revokeObjectURL(downloadUrl);
  575. };
  576. /** Excel文件 Exceed */
  577. const handleFileExceed = (files) => {
  578. uploadRef.value!.clearFiles();
  579. const file = files[0];
  580. file.uid = genFileId();
  581. uploadRef.value!.handleStart(file);
  582. importData.file = file;
  583. };
  584. /** 导出 */
  585. const handleExport = () => {
  586. exportOrder(search.value).then((response: any) => {
  587. downFile(response);
  588. });
  589. };
  590. onMounted?.(() => {
  591. queryExpandAlias();
  592. handleQuery(null, null);
  593. });
  594. </script>