index.vue 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. <template>
  2. <div class="processApproval">
  3. <div class="left-card">
  4. <div class="top">
  5. <div class="commons-title title">
  6. <span>
  7. {{
  8. queryData.query.flowName
  9. ? queryData.query.flowName + (queryData.query.processType ? typeName[queryData.query.processType] : "(发起)")
  10. : keyName[queryData.query.flowKey] + "(审批)"
  11. }}
  12. </span>
  13. <el-button type="primary" size="small" @click="clickRecords()" v-preReClick>审批记录</el-button>
  14. <el-button
  15. type="primary"
  16. size="small"
  17. @click="clickViewPackaging()"
  18. v-if="queryData.query.processType && ['10', '20'].includes(queryData.query.processType) && queryData.query.flowKey == 'order'"
  19. v-preReClick>
  20. 包装配置
  21. </el-button>
  22. <el-button
  23. type="primary"
  24. size="small"
  25. @click="clickOrderLog()"
  26. v-if="queryData.query.processType && ['10', '20'].includes(queryData.query.processType) && queryData.query.flowKey == 'order'"
  27. v-preReClick>
  28. 订单操作日志
  29. </el-button>
  30. </div>
  31. <div class="line"></div>
  32. <Subscribe :queryData="detailsData.data" v-if="queryData.query.flowKey == 'apply_buy'" ref="makeDom"></Subscribe>
  33. <Purchase :queryData="detailsData.data" v-else-if="queryData.query.flowKey == 'purchase'" ref="makeDom"></Purchase>
  34. <Order :queryData="detailsData.data" v-else-if="queryData.query.flowKey == 'order'" ref="makeDom"></Order>
  35. <ReturnGoods :queryData="detailsData.data" v-else-if="queryData.query.flowKey == 'purchase_return'" ref="makeDom"></ReturnGoods>
  36. <OrderDelete :queryData="detailsData.data" :recordList="recordList" v-else-if="queryData.query.flowKey == 'order_delete'" ref="makeDom"></OrderDelete>
  37. </div>
  38. <div class="bottom" v-if="route.query.processType != 20">
  39. <div class="commons-title title">处理意见</div>
  40. <el-form :model="flowForm" :rules="flowRules" ref="flowFormDom">
  41. <el-form-item prop="remark" label-width="0px" label="">
  42. <el-input type="textarea" placeholder="请输入" v-model="flowForm.remark"> </el-input>
  43. </el-form-item>
  44. <el-form-item>
  45. <el-button
  46. type="primary"
  47. v-if="(!queryData.query.processType || ['30', '40'].includes(queryData.query.processType)) && queryData.query.flowKey != 'purchase_return'"
  48. @click="handleSaveDraft"
  49. v-preReClick>
  50. 保存草稿
  51. </el-button>
  52. <el-button
  53. type="primary"
  54. v-if="(!queryData.query.processType || ['30', '40'].includes(queryData.query.processType)) && queryData.query.flowKey == 'order'"
  55. @click="handlePackagingConfiguration"
  56. v-preReClick>
  57. 包装配置
  58. </el-button>
  59. <el-button type="primary" v-if="approvalRecordData.buttonInfoList.length == 0" @click="handleSubmit" v-preReClick>提交</el-button>
  60. <el-button type="primary" v-else v-for="i in approvalRecordData.buttonInfoList" :key="i.type" @click="handleSubmit(i.type)" v-preReClick>
  61. {{ i.name }}
  62. </el-button>
  63. </el-form-item>
  64. </el-form>
  65. </div>
  66. </div>
  67. <el-dialog title="下一处理人" width="400" v-model="dialogVisible">
  68. <el-form :model="flowForm">
  69. <el-form-item prop="remark" label="处理人">
  70. <el-select v-model="flowForm.handleUserId" placeholder="请选择" filterable style="width: 100%">
  71. <el-option v-for="item in nextHandleUser" :label="item.name" :value="item.id"> </el-option>
  72. </el-select>
  73. </el-form-item>
  74. <el-form-item>
  75. <div style="width: 100%; text-align: center">
  76. <el-button type="primary" @click="handleSelectUser" v-preReClick>提交</el-button>
  77. </div>
  78. </el-form-item>
  79. </el-form>
  80. </el-dialog>
  81. <el-drawer v-model="drawer" :direction="'rtl'">
  82. <div class="right-card">
  83. <el-tabs v-model="activeName" class="demo-tabs">
  84. <el-tab-pane label="审批记录" name="first">
  85. <ul class="flow-chart">
  86. <li
  87. v-for="(item, index) in recordList"
  88. :key="item.id"
  89. :class="
  90. !queryData.query.flowId
  91. ? index === 0
  92. ? 'flow-orange'
  93. : 'flow-grey'
  94. : item.status == 2
  95. ? 'flow-orange'
  96. : item.status == 3 && !queryData.query.flowId
  97. ? 'flow-orange'
  98. : item.status == 3 && queryData.query.flowId
  99. ? 'flow-grey'
  100. : ''
  101. ">
  102. <div class="left-icon">
  103. <i class="iconfont icon-iconm_daick"></i>
  104. <i class="iconfont icon-icomx_quertj1 right-btm-status"></i>
  105. </div>
  106. <div class="right-conetnt">
  107. <div class="name">{{ item.nodeName }}</div>
  108. <div class="remark">
  109. <div class="label">
  110. <span v-if="item.status != 3">办理人:</span>{{ item.processedUser }}<span class="time">{{ item.processedDate }}</span>
  111. </div>
  112. {{ item.remark }}
  113. <div v-for="j in fileObj[item.flowExampleDetailId]" v-if="fileObj[item.flowExampleDetailId]">
  114. <a :href="j.fileUrl" style="color: #409eff; line-height: 30px">{{ j.fileName }}</a>
  115. </div>
  116. </div>
  117. </div>
  118. <div class="line"></div>
  119. </li>
  120. </ul>
  121. </el-tab-pane>
  122. </el-tabs>
  123. </div>
  124. </el-drawer>
  125. <el-dialog title="包装配置" v-if="openShippingPackage" v-model="openShippingPackage" width="80%">
  126. <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden">
  127. <el-form :model="formShippingPackage.data" :rules="rulesShippingPackage" ref="shippingPackage">
  128. <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
  129. <div style="margin-bottom: 10px">
  130. <el-button type="primary" size="small" @click="clickSelectAssembly()">选择常用组合</el-button>
  131. <el-button type="primary" size="small" @click="clickExpressPacking()">选择快递物流包材</el-button>
  132. </div>
  133. <el-table :data="formShippingPackage.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
  134. <el-table-column label="品号" prop="code" width="160" />
  135. <el-table-column label="品名" prop="name" min-width="220" />
  136. <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
  137. <el-table-column label="成本单价" prop="costPrice" width="100" />
  138. <el-table-column label="数量" width="120">
  139. <template #default="{ row, $index }">
  140. <div class="shippingPackage">
  141. <el-form-item
  142. :prop="'orderPackageBomList.' + $index + '.quantity'"
  143. :rules="rulesShippingPackage.quantity"
  144. :inline-message="true"
  145. style="width: 100%">
  146. <el-input-number
  147. onmousewheel="return false;"
  148. v-model="row.quantity"
  149. placeholder="修正数量"
  150. style="width: 100%"
  151. :controls="false"
  152. :min="0"
  153. :precision="0" />
  154. </el-form-item>
  155. </div>
  156. </template>
  157. </el-table-column>
  158. <el-table-column label="销售小计" width="120">
  159. <template #default="{ row }">
  160. {{ moneyFormat(computeMoney(row, "internalSellingPrice"), 2) }}
  161. </template>
  162. </el-table-column>
  163. <el-table-column label="成本小计" width="120">
  164. <template #default="{ row }">
  165. {{ moneyFormat(computeMoney(row, "costPrice"), 2) }}
  166. </template>
  167. </el-table-column>
  168. <el-table-column label="操作" align="center" fixed="right" width="80">
  169. <template #default="{ $index }">
  170. <el-button type="danger" @click="clickDelete($index)" text>删除</el-button>
  171. </template>
  172. </el-table-column>
  173. </el-table>
  174. <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
  175. <div style="display: flex; width: 100%">
  176. <div style="width: 80px; line-height: 32px">不干胶图片:</div>
  177. <div style="width: calc(100% - 80px)">
  178. <el-image
  179. fit="scale-down"
  180. style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
  181. v-if="formShippingPackage.data.outerBoxSelfAdhesiveStickerFile && formShippingPackage.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
  182. :src="formShippingPackage.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
  183. @click="openFile(formShippingPackage.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
  184. <div style="display: flex">
  185. <el-upload
  186. :show-file-list="false"
  187. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  188. :data="uploadAdhesiveData"
  189. :before-upload="uploadAdhesiveFile"
  190. :on-success="
  191. (response, uploadFile) => {
  192. return handleAdhesiveSuccess(uploadFile);
  193. }
  194. "
  195. style="width: 100%">
  196. <el-button type="primary" text>上传文件</el-button>
  197. </el-upload>
  198. </div>
  199. </div>
  200. </div>
  201. </el-form>
  202. </div>
  203. <template #footer>
  204. <el-button type="primary" @click="clickSaveAssembly" v-preReClick>保存常用组合</el-button>
  205. <el-button @click="openShippingPackage = false">取 消</el-button>
  206. <el-button type="primary" @click="clickSaveShippingPackage" v-preReClick>保 存</el-button>
  207. </template>
  208. </el-dialog>
  209. <el-dialog title="选择快递包装" v-if="openExpressPacking" v-model="openExpressPacking" width="90%">
  210. <SelectBOM :selectStatus="true" :expressStatus="true" @selectBOM="selectExpressPacking"></SelectBOM>
  211. <template #footer>
  212. <el-button @click="openExpressPacking = false">关 闭</el-button>
  213. </template>
  214. </el-dialog>
  215. <el-dialog title="保存常用组合" v-if="openAssembly" v-model="openAssembly" width="500">
  216. <el-form :model="formShippingPackage.data" :rules="rulesAssembly" ref="assembly">
  217. <el-form-item label="组合名称" prop="assemblyName">
  218. <el-input v-model="formShippingPackage.data.assemblyName" placeholder="请输入组合名称" />
  219. </el-form-item>
  220. </el-form>
  221. <template #footer>
  222. <el-button @click="openAssembly = false">关 闭</el-button>
  223. <el-button type="primary" @click="submitAssembly" v-preReClick>保 存</el-button>
  224. </template>
  225. </el-dialog>
  226. <el-dialog title="选择常用组合" v-if="openSelectAssembly" v-model="openSelectAssembly" width="700">
  227. <SelectAssembly @selectAssembly="selectAssembly"></SelectAssembly>
  228. <template #footer>
  229. <el-button @click="openSelectAssembly = false">关 闭</el-button>
  230. </template>
  231. </el-dialog>
  232. <el-dialog title="包装配置" v-if="openViewPackaging" v-model="openViewPackaging" width="80%">
  233. <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden">
  234. <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
  235. <el-table :data="viewPackaging.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
  236. <el-table-column label="品号" prop="code" width="160" />
  237. <el-table-column label="品名" prop="name" min-width="220" />
  238. <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
  239. <el-table-column label="成本单价" prop="costPrice" width="100" />
  240. <el-table-column label="数量" prop="quantity" width="120" />
  241. <el-table-column label="销售小计" width="120">
  242. <template #default="{ row }">
  243. {{ moneyFormat(computeMoney(row, "internalSellingPrice"), 2) }}
  244. </template>
  245. </el-table-column>
  246. <el-table-column label="成本小计" width="120">
  247. <template #default="{ row }">
  248. {{ moneyFormat(computeMoney(row, "costPrice"), 2) }}
  249. </template>
  250. </el-table-column>
  251. </el-table>
  252. <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
  253. <div style="display: flex; width: 100%">
  254. <div style="width: 80px; line-height: 32px">不干胶图片:</div>
  255. <div style="width: calc(100% - 80px)">
  256. <el-image
  257. fit="scale-down"
  258. style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
  259. v-if="viewPackaging.data.outerBoxSelfAdhesiveStickerFile && viewPackaging.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
  260. :src="viewPackaging.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
  261. @click="openFile(viewPackaging.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
  262. </div>
  263. </div>
  264. </div>
  265. <template #footer>
  266. <el-button @click="openViewPackaging = false">关 闭</el-button>
  267. </template>
  268. </el-dialog>
  269. <el-drawer v-model="drawerOrderLog" :direction="'rtl'">
  270. <byTable :hidePagination="true" :source="logsList.data" :pagination="logsList.pagination" :config="configLogs"> </byTable>
  271. </el-drawer>
  272. </div>
  273. </template>
  274. <script setup>
  275. import byTable from "/src/components/byTable/index";
  276. import useTagsViewStore from "/src/store/modules/tagsView.js";
  277. import { useRouter, useRoute } from "vue-router";
  278. import { ElMessage, ElMessageBox } from "element-plus";
  279. // 申购单
  280. import Subscribe from "/src/components/process/subscribe";
  281. // 采购合同
  282. import Purchase from "/src/components/process/purchase";
  283. // 新建订单
  284. import Order from "/src/components/process/order";
  285. import refreshStore from "/src/store/modules/refresh";
  286. import SelectBOM from "/src/views/group/BOM/management/index";
  287. import SelectAssembly from "/src/components/selectAssembly/index";
  288. import ReturnGoods from "/src/components/process/returnGoods.vue";
  289. // 删除订单
  290. import OrderDelete from "/src/components/process/order-delete";
  291. const typeName = ref({
  292. 10: "(审批)",
  293. 20: "(详情)",
  294. 30: "(发起)",
  295. 40: "(发起)",
  296. });
  297. const keyName = ref({
  298. apply_buy: "申购流程",
  299. purchase: "采购流程",
  300. order: "新建订单流程",
  301. purchase_return: "采购退货流程",
  302. order_delete: "订单删除流程",
  303. });
  304. const flowKeyCollect = reactive({
  305. apply_buy: {
  306. backPath: "/group/oa/subscribe",
  307. edit: "/applyBuy/edit",
  308. add: "/applyBuy/add",
  309. detail: "/applyBuy/detail",
  310. },
  311. purchase: {
  312. backPath: "/group/purchase/purchase-contract",
  313. edit: "/purchase/edit",
  314. add: "/purchase/add",
  315. detail: "/purchase/detail",
  316. },
  317. order: {
  318. backPath: "/subsidiary/order/subsidiary-order-management",
  319. edit: "/orderInfo/edit",
  320. add: "/orderInfo/add",
  321. detail: "/orderInfo/detail",
  322. },
  323. purchase_return: {
  324. backPath: "/group/purchase/return-goods",
  325. detail: "/purchaseReturn/detail",
  326. },
  327. order_delete: {
  328. backPath: "/subsidiary/order/subsidiary-order-management",
  329. edit: "/orderInfo/edit",
  330. add: "/orderInfo/add",
  331. detail: "/orderInfo/detail",
  332. },
  333. });
  334. const detailsData = reactive({
  335. data: {},
  336. });
  337. const router = useRouter();
  338. const route = useRoute();
  339. // tab切换逻辑
  340. const activeName = ref("first");
  341. // 意见表单
  342. const flowForm = reactive({
  343. flowKey: "",
  344. tenantType: "",
  345. handleUserId: "",
  346. remark: "",
  347. data: {},
  348. });
  349. const flowRules = reactive({
  350. // remark: [{ required: true, message: "请输入处理意见", trigger: "blur" }],
  351. });
  352. //组件实例
  353. const { proxy } = getCurrentInstance();
  354. const flowFormDom = ref(null);
  355. let dialogVisible = ref(false);
  356. const nextHandleUser = ref([]);
  357. const handleSelectUser = () => {
  358. if (!flowForm.handleUserId) {
  359. return ElMessage({
  360. message: "请选择下一节点处理人!",
  361. type: "info",
  362. });
  363. }
  364. handleSubmit();
  365. };
  366. const handleResult = (res) => {
  367. if (res !== null && res.success) {
  368. skipPage();
  369. } else {
  370. dialogVisible.value = true;
  371. nextHandleUser.value = res.userList;
  372. }
  373. };
  374. // 提交逻辑
  375. const handleSubmit = async (_type) => {
  376. try {
  377. // 调用发起组件的提交事件
  378. const flag = await proxy.$refs.makeDom.handleSubmit();
  379. if (flag) {
  380. flowFormDom.value.validate((valid) => {
  381. if (valid) {
  382. if (queryData.query.flowKey == "order") {
  383. ElMessageBox.confirm("请确认包装配置", "提示", {
  384. confirmButtonText: "确定",
  385. cancelButtonText: "取消",
  386. type: "warning",
  387. })
  388. .then(() => {
  389. processSubmit(_type);
  390. })
  391. .catch(() => {});
  392. } else {
  393. processSubmit(_type);
  394. }
  395. }
  396. });
  397. }
  398. } catch (err) {
  399. console.log("数据未填完整!", err);
  400. }
  401. };
  402. const processSubmit = (_type) => {
  403. const data = { ...proxy.$refs.makeDom.getFormData() };
  404. if (queryData.query.processType == "10" || queryData.query.processType == "30") {
  405. proxy
  406. .post("/flowProcess/jump", {
  407. ...flowForm,
  408. data,
  409. handleType: _type,
  410. version: queryData.query.version,
  411. flowId: queryData.query.flowId,
  412. })
  413. .then((res) => {
  414. handleResult(res);
  415. });
  416. return;
  417. } else {
  418. proxy
  419. .post("/flowProcess/initiate", {
  420. ...flowForm,
  421. data,
  422. })
  423. .then((res) => {
  424. handleResult(res);
  425. });
  426. }
  427. };
  428. // 页面跳转
  429. const skipPage = () => {
  430. const useTagsStore = useTagsViewStore();
  431. useTagsStore.delVisitedView(router.currentRoute.value);
  432. if (queryData.query.processType && queryData.query.processType != "40") {
  433. router.replace({
  434. path: "/oa/1/dealWith",
  435. });
  436. } else {
  437. ElMessage({ message: "操作成功!", type: "success" });
  438. if (queryData.query.flowKey == "order") {
  439. refreshStore().setRefresh("order");
  440. }
  441. router.replace({
  442. path: flowKeyCollect[queryData.query.flowKey].backPath,
  443. });
  444. }
  445. };
  446. const queryData = reactive({
  447. query: {},
  448. data: {},
  449. });
  450. // 记录
  451. const recordList = ref([]);
  452. const fileIds = ref([]);
  453. const fileObj = ref({});
  454. const approvalRecordData = ref({
  455. buttonInfoList: [],
  456. });
  457. const getRecords = (_id) => {
  458. if (_id) {
  459. proxy
  460. .post("/flowExample/getApprovalRecord", {
  461. id: _id,
  462. })
  463. .then((res) => {
  464. recordList.value = res.recordList;
  465. queryData.data.recordList = res.recordList;
  466. approvalRecordData.value = res;
  467. fileIds.value = res.recordList.map((item) => {
  468. return item.flowExampleDetailId;
  469. });
  470. proxy.post("fileInfo/getList", { businessIdList: fileIds.value }).then((res2) => {
  471. fileObj.value = res2;
  472. });
  473. });
  474. } else {
  475. proxy
  476. .post("/flowExample/getFlowNode", {
  477. flowKey: queryData.query.flowKey,
  478. })
  479. .then((res) => {
  480. recordList.value = res;
  481. });
  482. }
  483. };
  484. const handleSaveDraft = async () => {
  485. const flag = await proxy.$refs.makeDom.handleSubmit();
  486. if (flag) {
  487. let data = proxy.$refs.makeDom.getFormData();
  488. if (queryData.query.flowKey == "order") {
  489. data.status = "0";
  490. }
  491. if (data.id) {
  492. proxy.post(flowKeyCollect[queryData.query.flowKey].edit, data).then(() => {
  493. skipPage();
  494. });
  495. } else {
  496. proxy.post(flowKeyCollect[queryData.query.flowKey].add, data).then(() => {
  497. skipPage();
  498. });
  499. }
  500. }
  501. };
  502. onMounted(() => {
  503. if (route.query) {
  504. queryData.query = route.query;
  505. }
  506. //processType 10 为审批 20为查看 30回退发起 40为草稿修改
  507. flowForm.flowKey = queryData.query.flowKey;
  508. flowForm.tenantType = queryData.query.tenantType;
  509. if (queryData.query.random) {
  510. useTagsViewStore().visitedViews = useTagsViewStore().visitedViews.map((item) => {
  511. if (item.query && item.query.random === queryData.query.random) {
  512. return {
  513. ...item,
  514. name: queryData.query.flowName,
  515. title: queryData.query.flowName,
  516. };
  517. } else {
  518. return {
  519. ...item,
  520. };
  521. }
  522. });
  523. }
  524. if (queryData.query.id) {
  525. proxy.post(flowKeyCollect[queryData.query.flowKey].detail, { id: queryData.query.id }).then((res) => {
  526. detailsData.data = { ...res };
  527. });
  528. }
  529. getRecords(queryData.query.flowId);
  530. });
  531. const drawer = ref(false);
  532. const clickRecords = () => {
  533. drawer.value = true;
  534. };
  535. const formShippingPackage = reactive({
  536. data: {
  537. assemblyName: "",
  538. orderPackageBomList: [],
  539. outerBoxSelfAdhesiveStickerFile: {},
  540. },
  541. });
  542. const rulesShippingPackage = ref({
  543. quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
  544. });
  545. const openShippingPackage = ref(false);
  546. const handlePackagingConfiguration = () => {
  547. let orderData = proxy.$refs.makeDom.getFormData();
  548. if (orderData.orderPackageBomList && orderData.orderPackageBomList.length > 0) {
  549. formShippingPackage.data.orderPackageBomList = orderData.orderPackageBomList;
  550. } else {
  551. formShippingPackage.data.orderPackageBomList = [];
  552. }
  553. if (orderData.outerBoxSelfAdhesiveStickerFile) {
  554. formShippingPackage.data.outerBoxSelfAdhesiveStickerFile = orderData.outerBoxSelfAdhesiveStickerFile;
  555. } else {
  556. formShippingPackage.data.outerBoxSelfAdhesiveStickerFile = {};
  557. }
  558. openShippingPackage.value = true;
  559. };
  560. const openExpressPacking = ref(false);
  561. const clickExpressPacking = () => {
  562. openExpressPacking.value = true;
  563. };
  564. const selectExpressPacking = (data) => {
  565. if (formShippingPackage.data.orderPackageBomList && formShippingPackage.data.orderPackageBomList.length > 0) {
  566. let list = formShippingPackage.data.orderPackageBomList.filter((item) => item.bomSpecId === data.id);
  567. if (list && list.length > 0) {
  568. return ElMessage("快递物流包材已添加");
  569. }
  570. formShippingPackage.data.orderPackageBomList.push({
  571. bomSpecId: data.id,
  572. code: data.code,
  573. name: data.name,
  574. costPrice: data.costPrice,
  575. internalSellingPrice: data.internalSellingPrice,
  576. quantity: undefined,
  577. });
  578. } else {
  579. formShippingPackage.data.orderPackageBomList = [
  580. {
  581. bomSpecId: data.id,
  582. code: data.code,
  583. name: data.name,
  584. costPrice: data.costPrice,
  585. internalSellingPrice: data.internalSellingPrice,
  586. quantity: undefined,
  587. },
  588. ];
  589. }
  590. ElMessage({ message: "添加成功", type: "success" });
  591. };
  592. const computeMoney = (item, label) => {
  593. let money = 0;
  594. if (item.quantity && item[label]) {
  595. money = Number(Math.round(item.quantity * item[label] * 100) / 100);
  596. }
  597. return money;
  598. };
  599. const clickDelete = (index) => {
  600. formShippingPackage.data.orderPackageBomList.splice(index, 1);
  601. };
  602. const uploadAdhesiveData = ref({});
  603. const uploadAdhesiveFile = async (file) => {
  604. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  605. uploadAdhesiveData.value = res.uploadBody;
  606. file.id = res.id;
  607. file.fileName = res.fileName;
  608. file.fileUrl = res.fileUrl;
  609. return true;
  610. };
  611. const handleAdhesiveSuccess = (UploadFile) => {
  612. formShippingPackage.data.outerBoxSelfAdhesiveStickerFile = {
  613. id: UploadFile.raw.id,
  614. fileName: UploadFile.raw.fileName,
  615. fileUrl: UploadFile.raw.fileUrl,
  616. };
  617. };
  618. const openFile = (path) => {
  619. window.open(path);
  620. };
  621. const openAssembly = ref(false);
  622. const rulesAssembly = ref({
  623. assemblyName: [{ required: true, message: "请输入组合名称", trigger: "blur" }],
  624. });
  625. const clickSaveAssembly = () => {
  626. if (formShippingPackage.data.orderPackageBomList && formShippingPackage.data.orderPackageBomList.length > 0) {
  627. formShippingPackage.data.assemblyName = "";
  628. openAssembly.value = true;
  629. } else {
  630. return ElMessage("请添加快递物流包材");
  631. }
  632. };
  633. const submitAssembly = () => {
  634. proxy.$refs.assembly.validate((valid) => {
  635. if (valid) {
  636. proxy
  637. .post("/packagingAssembly/add", { name: formShippingPackage.data.assemblyName, packagingAssemblyBomList: formShippingPackage.data.orderPackageBomList })
  638. .then(() => {
  639. ElMessage({ message: "保存成功!", type: "success" });
  640. openAssembly.value = false;
  641. });
  642. }
  643. });
  644. };
  645. const openSelectAssembly = ref(false);
  646. const clickSelectAssembly = () => {
  647. openSelectAssembly.value = true;
  648. };
  649. const selectAssembly = (item) => {
  650. if (item.id) {
  651. proxy.post("/packagingAssembly/getPackagingBomList", { id: item.id }).then((res) => {
  652. if (res && res.length > 0) {
  653. formShippingPackage.data.orderPackageBomList = res.map((resItem) => {
  654. return {
  655. bomSpecId: resItem.id,
  656. code: resItem.code,
  657. name: resItem.name,
  658. costPrice: resItem.costPrice,
  659. internalSellingPrice: resItem.internalSellingPrice,
  660. quantity: undefined,
  661. };
  662. });
  663. }
  664. ElMessage({ message: "选择完成", type: "success" });
  665. openSelectAssembly.value = false;
  666. });
  667. } else {
  668. return ElMessage("选择失败,请重新选择");
  669. }
  670. };
  671. const clickSaveShippingPackage = () => {
  672. proxy.$refs.shippingPackage.validate((valid) => {
  673. if (valid) {
  674. proxy.$refs.makeDom.saveShippingPackage(formShippingPackage.data);
  675. ElMessage({ message: "保存完成", type: "success" });
  676. openShippingPackage.value = false;
  677. }
  678. });
  679. };
  680. const viewPackaging = reactive({
  681. data: {
  682. orderPackageBomList: [],
  683. outerBoxSelfAdhesiveStickerFile: {},
  684. },
  685. });
  686. const openViewPackaging = ref(false);
  687. const clickViewPackaging = () => {
  688. let orderData = proxy.$refs.makeDom.getFormData();
  689. if (orderData.orderPackageBomList && orderData.orderPackageBomList.length > 0) {
  690. viewPackaging.data.orderPackageBomList = orderData.orderPackageBomList;
  691. } else {
  692. viewPackaging.data.orderPackageBomList = [];
  693. }
  694. if (orderData.outerBoxSelfAdhesiveStickerFile) {
  695. viewPackaging.data.outerBoxSelfAdhesiveStickerFile = orderData.outerBoxSelfAdhesiveStickerFile;
  696. } else {
  697. viewPackaging.data.outerBoxSelfAdhesiveStickerFile = {};
  698. }
  699. openViewPackaging.value = true;
  700. };
  701. const logsList = ref({
  702. data: [],
  703. pagination: {
  704. pageNum: 1,
  705. pageSize: 999,
  706. id: route.query.id,
  707. },
  708. });
  709. const drawerOrderLog = ref(false);
  710. const logType = ref([
  711. { dictKey: "10", dictValue: "新增订单" },
  712. { dictKey: "20", dictValue: "图稿上传" },
  713. { dictKey: "21", dictValue: "修改税率" },
  714. { dictKey: "30", dictValue: "删除订单" },
  715. ]);
  716. const configLogs = computed(() => {
  717. return [
  718. {
  719. attrs: {
  720. label: "操作时间",
  721. prop: "createTime",
  722. width: 160,
  723. align: "center",
  724. },
  725. },
  726. {
  727. attrs: {
  728. label: "操作人",
  729. prop: "userName",
  730. align: "center",
  731. },
  732. },
  733. {
  734. attrs: {
  735. label: "行为",
  736. prop: "type",
  737. width: 100,
  738. align: "center",
  739. },
  740. render(val) {
  741. return proxy.dictKeyValue(val, logType.value);
  742. },
  743. },
  744. ];
  745. });
  746. const clickOrderLog = () => {
  747. if (route.query.id) {
  748. proxy.post("/orderOperatingLog/page", logsList.value.pagination).then((res) => {
  749. logsList.value.data = res.rows;
  750. });
  751. }
  752. drawerOrderLog.value = true;
  753. };
  754. </script>
  755. <style lang="scss" scoped>
  756. .processApproval {
  757. display: flex;
  758. justify-content: space-between;
  759. height: calc(100vh - 120px);
  760. .left-card {
  761. border-radius: 4px;
  762. width: 100%;
  763. display: flex;
  764. flex-direction: column;
  765. .top {
  766. flex: 1;
  767. overflow-y: auto;
  768. overflow-x: hidden;
  769. background: #fff;
  770. padding: 20px;
  771. .line {
  772. border-bottom: 1px solid #ddd;
  773. margin-bottom: 10px;
  774. }
  775. }
  776. .bottom {
  777. margin-top: 10px;
  778. height: 190px;
  779. background: #fff;
  780. padding: 20px;
  781. overflow-y: auto;
  782. overflow-x: hidden;
  783. }
  784. }
  785. }
  786. .right-card {
  787. background: #fff;
  788. border-radius: 4px;
  789. padding: 0 20px 20px;
  790. width: 100%;
  791. box-sizing: border-box;
  792. .flow-chart {
  793. overflow-y: auto;
  794. overflow-x: hidden;
  795. height: calc(100vh - 200px);
  796. padding: 0;
  797. margin: 0;
  798. li {
  799. margin: 0;
  800. padding: 0 0 20px;
  801. list-style: none;
  802. display: flex;
  803. justify-content: space-between;
  804. position: relative;
  805. .right-conetnt {
  806. flex: 1;
  807. .name {
  808. font-size: 12px;
  809. color: #39c55a;
  810. margin-bottom: 10px;
  811. span {
  812. color: #999;
  813. }
  814. }
  815. .time {
  816. float: right;
  817. }
  818. .remark {
  819. padding: 10px;
  820. color: #666666;
  821. font-size: 12px;
  822. background: #f1f1f1;
  823. border-radius: 2px;
  824. .label {
  825. color: #999;
  826. margin-bottom: 10px;
  827. }
  828. }
  829. }
  830. .left-icon {
  831. width: 40px;
  832. height: 40px;
  833. text-align: center;
  834. line-height: 40px;
  835. background: #0084ff;
  836. border-radius: 10px;
  837. color: #fff;
  838. font-size: 20px;
  839. position: relative;
  840. margin-right: 27px;
  841. z-index: 2;
  842. .right-btm-status {
  843. position: absolute;
  844. bottom: 0px;
  845. right: -10px;
  846. height: 20px;
  847. width: 20px;
  848. line-height: 16px;
  849. border-radius: 10px;
  850. background: #39c55a;
  851. border: 2px solid #fff;
  852. font-size: 12px;
  853. box-sizing: border-box;
  854. }
  855. }
  856. }
  857. li::before {
  858. content: "";
  859. position: absolute;
  860. top: 0;
  861. left: 20px;
  862. width: 2px;
  863. height: 100%;
  864. background: #ddd;
  865. z-index: 1;
  866. }
  867. li:last-child::before {
  868. display: none;
  869. }
  870. .flow-orange {
  871. .right-btm-status {
  872. background: #ff9a00 !important;
  873. }
  874. .name {
  875. color: #ff9a00 !important;
  876. }
  877. .left-icon {
  878. background: #ff9a00 !important;
  879. }
  880. }
  881. .flow-grey {
  882. .right-btm-status {
  883. background: #999 !important;
  884. }
  885. .name {
  886. color: #999 !important;
  887. }
  888. .left-icon {
  889. background: #999 !important;
  890. }
  891. }
  892. .flow-red {
  893. .right-btm-status {
  894. background: #ff4d4f !important;
  895. }
  896. .name {
  897. color: #ff4d4f !important;
  898. }
  899. .left-icon {
  900. background: #ff4d4f !important;
  901. }
  902. }
  903. }
  904. }
  905. ::v-deep(.el-drawer) {
  906. width: 400px !important;
  907. }
  908. :deep(.el-dialog) {
  909. margin-top: 10px !important;
  910. margin-bottom: 10px !important;
  911. }
  912. ::v-deep(.el-input-number .el-input__inner) {
  913. text-align: left;
  914. }
  915. .shippingPackage {
  916. .el-form-item {
  917. margin-bottom: 0;
  918. }
  919. }
  920. </style>