doSugar.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. <template>
  2. <div class="sugar-maker">
  3. <s-header :name="$t('device.remoteSugarMaking')" :noback="false" />
  4. <!-- 设备信息卡片 -->
  5. <div class="device-card">
  6. <div class="device-header">
  7. <div class="header-indicator"></div>
  8. <h3 class="device-name">
  9. {{ $t("device.equipmentName") }}:{{ deviceDetal?.name || "-" }}
  10. </h3>
  11. </div>
  12. </div>
  13. <!-- 主操作区 -->
  14. <div class="operation-card">
  15. <!-- 动态选择器 -->
  16. <div v-if="[null, '0', '1'].includes(machineType)" class="selector-card">
  17. <van-field
  18. v-model="fieldValue"
  19. is-link
  20. readonly
  21. :label="
  22. machineType === '1'
  23. ? $t('device.clickToSelectTaste')
  24. : $t('device.clickToSelectPattern')
  25. "
  26. :placeholder="
  27. machineType === '1'
  28. ? $t('device.pleaseSelectTaste')
  29. : $t('device.pleaseSelectAPattern')
  30. "
  31. @click="show = true"
  32. class="smart-field"
  33. />
  34. <van-popup v-model:show="show" round position="bottom">
  35. <van-cascader
  36. v-model="cascaderValue"
  37. :title="
  38. machineType === '1'
  39. ? $t('device.pleaseSelectTaste')
  40. : $t('device.pleaseSelectAPattern')
  41. "
  42. :options="options"
  43. @close="show = false"
  44. @finish="onFinish"
  45. >
  46. <template #option="{ option }">
  47. <div class="cascader-item">
  48. <van-image
  49. :src="option.imgUrl"
  50. width="55px"
  51. height="55px"
  52. class="option-image"
  53. >
  54. <template v-if="!option.imgUrl" #error>
  55. <van-icon name="photo" size="24" />
  56. </template>
  57. </van-image>
  58. <div class="option-label">{{ option.text }}</div>
  59. </div>
  60. </template>
  61. </van-cascader>
  62. </van-popup>
  63. </div>
  64. <!-- 复合材料选择(类型2) -->
  65. <div v-if="machineType === '2'" class="material-selector">
  66. <van-collapse v-model="activeNames">
  67. <!-- 果酱选择 -->
  68. <van-collapse-item
  69. :title="$t('device.jam')"
  70. name="1"
  71. class="material-section"
  72. >
  73. <div class="grid-container">
  74. <div
  75. v-for="(item, index) in jamData"
  76. :key="`jam-${index}`"
  77. class="material-item"
  78. >
  79. <van-image
  80. :src="showPopPhoto(item)"
  81. width="50"
  82. height="50"
  83. fit="contain"
  84. />
  85. <span class="material-name">{{ item.name }}</span>
  86. <van-checkbox
  87. v-model="item.checked"
  88. shape="square"
  89. class="material-checkbox"
  90. />
  91. </div>
  92. </div>
  93. </van-collapse-item>
  94. <!-- 坚果选择 -->
  95. <van-collapse-item
  96. :title="$t('device.nuts​')"
  97. name="2"
  98. class="material-section"
  99. >
  100. <div class="grid-container">
  101. <div
  102. v-for="(item, index) in crushData"
  103. :key="`nut-${index}`"
  104. class="material-item"
  105. >
  106. <van-image
  107. :src="showPopPhoto(item)"
  108. width="50"
  109. height="50"
  110. fit="contain"
  111. />
  112. <span class="material-name">{{ item.name }}</span>
  113. <van-checkbox
  114. v-model="item.checked"
  115. shape="square"
  116. class="material-checkbox"
  117. />
  118. </div>
  119. </div>
  120. </van-collapse-item>
  121. </van-collapse>
  122. </div>
  123. <!-- 公共操作区 -->
  124. <div class="action-area">
  125. <div class="quick-link" @click="pushToDaySugarList">
  126. {{
  127. $t(
  128. machineType === "2"
  129. ? "device.todaysMakeList"
  130. : "device.todaysSugarList"
  131. )
  132. }}
  133. <van-icon name="arrow" />
  134. </div>
  135. <van-button
  136. round
  137. :type="doSugartData ? 'success' : 'primary'"
  138. class="submit-btn"
  139. :disabled="doSugartType"
  140. @click="doSugartData ? checkData() : submitDoSugar()"
  141. >
  142. <van-icon :name="doSugartData ? 'eye' : 'play-circle'" />
  143. {{
  144. $t(doSugartData ? "device.viewResults" : "device.submitToMakeSugar")
  145. }}
  146. </van-button>
  147. </div>
  148. </div>
  149. </div>
  150. </template>
  151. <script>
  152. import { onMounted, ref } from "vue";
  153. import sHeader from "@/components/SimpleHeader";
  154. import { useRoute, useRouter } from "vue-router";
  155. import {
  156. getDeviceDetal,
  157. selectProducts,
  158. remoteProduction,
  159. selectSugarStatus,
  160. } from "@/service/device";
  161. import {
  162. showConfirmDialog,
  163. showFailToast,
  164. showSuccessToast,
  165. showToast,
  166. } from "vant";
  167. import { useI18n } from "vue-i18n";
  168. import { styleUrl } from "../../common/js/utils";
  169. export default {
  170. setup() {
  171. const { t } = useI18n();
  172. const route = useRoute();
  173. const router = useRouter();
  174. const deviceId = route.query.deviceId;
  175. const machineType = route.query.machineType;
  176. const deviceDetal = ref(null);
  177. const show = ref(false);
  178. const fieldValue = ref("");
  179. const cascaderValue = ref("");
  180. const options = ref([]);
  181. const activeNames = ref(["1", "2"]);
  182. const productNo = ref("");
  183. // 果酱数据
  184. const iceName = ref();
  185. const jamData = ref([]);
  186. const crushData = ref([]);
  187. // 商品图片
  188. const showPopPhoto = (row) => {
  189. let imgId = row.no;
  190. if (imgId) {
  191. return require(`../../assets/order/spunSugar/goods/${imgId}.png`);
  192. }
  193. return imgId;
  194. };
  195. const onFinish = ({ selectedOptions }) => {
  196. console.log("onFinish", selectedOptions);
  197. show.value = false;
  198. fieldValue.value = selectedOptions[0].text;
  199. productNo.value = selectedOptions[0].value;
  200. };
  201. const doSugartData = ref(null);
  202. const doSugartType = ref(false);
  203. // 初始化页面获取列表
  204. onMounted(async () => {
  205. styleUrl("doSugar");
  206. getDeviceDetalFun();
  207. });
  208. const showSugarPhoto = (no) => {
  209. return require(`../../assets/order/spunSugar/goods/${no}.png`);
  210. };
  211. // 获取设备列表数据
  212. const getDeviceDetalFun = async () => {
  213. const { data } = await getDeviceDetal({ id: deviceId });
  214. if (data.code === "00000") {
  215. deviceDetal.value = data.data;
  216. getProduct();
  217. } else {
  218. showFailToast(data.message);
  219. }
  220. };
  221. // 获取花形下拉列表
  222. const getProduct = async () => {
  223. const { data } = await selectProducts({ equipmentId: deviceId });
  224. if (data.code) {
  225. if (machineType != "2") {
  226. options.value = data.data.map((item) => {
  227. return {
  228. text: item.productName,
  229. value: item.no,
  230. imgUrl: showSugarPhoto(item.no),
  231. };
  232. });
  233. console.log(options.value);
  234. } else {
  235. data.data.forEach((item) => {
  236. if (item.no.includes("J01")) {
  237. // 果酱1
  238. jamData.value.push({
  239. name: item.productName,
  240. no: item.no,
  241. value: 1,
  242. checked: false,
  243. });
  244. } else if (item.no.includes("J02")) {
  245. // 果酱2
  246. jamData.value.push({
  247. name: item.productName,
  248. no: item.no,
  249. value: 2,
  250. checked: false,
  251. });
  252. } else if (item.no.includes("J03")) {
  253. // 果酱3
  254. jamData.value.push({
  255. name: item.productName,
  256. no: item.no,
  257. value: 3,
  258. checked: false,
  259. });
  260. } else if (item.no.includes("C01")) {
  261. // 果碎1
  262. crushData.value.push({
  263. name: item.productName,
  264. no: item.no,
  265. value: 1,
  266. checked: false,
  267. });
  268. } else if (item.no.includes("C02")) {
  269. // 果碎2
  270. crushData.value.push({
  271. name: item.productName,
  272. no: item.no,
  273. value: 2,
  274. checked: false,
  275. });
  276. } else if (item.no.includes("I01")) {
  277. // 雪糕
  278. iceName.value = item.productName;
  279. }
  280. });
  281. }
  282. } else {
  283. showFailToast(data.message);
  284. }
  285. };
  286. const submitDoSugar = async () => {
  287. const makeCodes = ref([1, 0, 0]);
  288. doSugartData.value = null;
  289. doSugartType.value = true;
  290. if (machineType == "2") {
  291. fieldValue.value = "";
  292. let jamCount = 0;
  293. let crushCount = 0;
  294. // 如果是冰淇淋机器
  295. jamData.value.forEach((item) => {
  296. if (item.checked) {
  297. fieldValue.value += item.name + ",";
  298. makeCodes.value[1] += item.value;
  299. jamCount++;
  300. }
  301. });
  302. crushData.value.forEach((item) => {
  303. if (item.checked) {
  304. fieldValue.value += item.name + ",";
  305. makeCodes.value[2] += item.value;
  306. crushCount++;
  307. }
  308. });
  309. if (jamCount > 1) {
  310. makeCodes.value[1] += 1;
  311. }
  312. if (crushCount > 1) {
  313. makeCodes.value[2] += 1;
  314. }
  315. if (fieldValue.value === "") {
  316. fieldValue.value = iceName.value;
  317. } else {
  318. fieldValue.value = fieldValue.value.substring(
  319. 0,
  320. fieldValue.value.length - 1
  321. );
  322. fieldValue.value = iceName.value + "(" + fieldValue.value + ")";
  323. }
  324. }
  325. if (fieldValue.value === "") {
  326. showFailToast(t("device.pleaseSelectAPattern"));
  327. return;
  328. }
  329. showConfirmDialog({
  330. title: t("user.tips"),
  331. message: t("device.confirmMake") + fieldValue.value + "?",
  332. })
  333. .then(async () => {
  334. const { data } = await remoteProduction({
  335. equipmentId: deviceId,
  336. productName: fieldValue.value,
  337. makeCodes: makeCodes.value.join(","),
  338. productNo: productNo.value,
  339. });
  340. if (data.code == "00000") {
  341. doSugartData.value = data.data;
  342. setTimeout(() => {
  343. doSugartType.value = false;
  344. }, 5000);
  345. } else {
  346. showFailToast(data.message);
  347. }
  348. })
  349. .catch((error) => {
  350. console.error(error);
  351. });
  352. };
  353. const checkData = async () => {
  354. const { data } = await selectSugarStatus({ no: doSugartData.value.no });
  355. if (data.code) {
  356. if (data.data == "1") {
  357. showToast(t("device.receiveInstruction"));
  358. } else {
  359. showSuccessToast(data.message);
  360. }
  361. doSugartData.value = null;
  362. doSugartType.value = true;
  363. } else {
  364. if (data.data == "0") {
  365. showToast(t("device.notUploadData"));
  366. } else if (data.data == "2") {
  367. showToast(t("device.machineException"));
  368. } else if (data.data == "3") {
  369. showToast(t("device.netException"));
  370. } else {
  371. showToast(data.message);
  372. }
  373. }
  374. };
  375. const pushToDaySugarList = async () => {
  376. router.push({
  377. path: "toDaySugarList",
  378. query: { deviceId: deviceId, clientId: deviceDetal.value.clientId },
  379. });
  380. };
  381. return {
  382. deviceDetal,
  383. show,
  384. fieldValue,
  385. cascaderValue,
  386. options,
  387. onFinish,
  388. submitDoSugar,
  389. doSugartData,
  390. doSugartType,
  391. checkData,
  392. pushToDaySugarList,
  393. showSugarPhoto,
  394. machineType,
  395. activeNames,
  396. jamData,
  397. crushData,
  398. showPopPhoto,
  399. };
  400. },
  401. components: { sHeader },
  402. };
  403. </script>
  404. <style lang="less" scoped>
  405. @primary-color: #4d6add;
  406. @card-bg: #ffffff;
  407. @text-primary: #2d3436;
  408. @border-color: #e4e7ec;
  409. .sugar-maker {
  410. background: #f8fafb;
  411. min-height: 100vh;
  412. }
  413. .device-card {
  414. background: @card-bg;
  415. border-radius: 12px;
  416. box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
  417. margin: 10px;
  418. padding: 16px;
  419. .device-header {
  420. display: flex;
  421. align-items: center;
  422. .header-indicator {
  423. width: 3px;
  424. height: 20px;
  425. background: @primary-color;
  426. margin-right: 12px;
  427. border-radius: 2px;
  428. }
  429. .device-name {
  430. margin: 0;
  431. font-size: 15px;
  432. color: #404d74;
  433. font-weight: 550;
  434. }
  435. }
  436. }
  437. .operation-card {
  438. background: @card-bg;
  439. border-radius: 12px;
  440. box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
  441. padding: 10px;
  442. margin: 10px;
  443. .selector-card {
  444. margin-bottom: 24px;
  445. .smart-field {
  446. :deep(.van-field__label) {
  447. color: @primary-color;
  448. font-weight: 500;
  449. }
  450. }
  451. .cascader-item {
  452. padding: 5px;
  453. display: flex;
  454. align-items: center;
  455. .option-image {
  456. border-radius: 8px;
  457. margin-right: 15px;
  458. }
  459. .option-label {
  460. font-size: 14px;
  461. color: @text-primary;
  462. }
  463. }
  464. }
  465. .material-selector {
  466. .material-section {
  467. :deep(.van-collapse-item__title) {
  468. font-weight: bold;
  469. color: #404d74;
  470. }
  471. }
  472. .grid-container {
  473. display: grid;
  474. grid-template-columns: repeat(2, 1fr);
  475. gap: 12px;
  476. }
  477. .material-item {
  478. display: flex;
  479. align-items: center;
  480. padding: 8px;
  481. background: #f8fafb;
  482. border-radius: 8px;
  483. .material-name {
  484. flex: 1;
  485. margin: 0 12px;
  486. font-size: 13px;
  487. .ellipsis();
  488. }
  489. .material-checkbox {
  490. :deep(.van-checkbox__icon) {
  491. border-color: @primary-color;
  492. &.van-checkbox__icon--checked {
  493. background: @primary-color;
  494. }
  495. }
  496. }
  497. }
  498. }
  499. .action-area {
  500. margin-top: 24px;
  501. .quick-link {
  502. color: @primary-color;
  503. font-size: 13px;
  504. text-align: right;
  505. margin-bottom: 16px;
  506. display: flex;
  507. align-items: center;
  508. justify-content: flex-end;
  509. .van-icon {
  510. margin-left: 4px;
  511. }
  512. }
  513. .submit-btn {
  514. width: 100%;
  515. height: 48px;
  516. font-size: 16px;
  517. .van-icon {
  518. margin-right: 8px;
  519. }
  520. }
  521. }
  522. }
  523. .ellipsis() {
  524. overflow: hidden;
  525. text-overflow: ellipsis;
  526. white-space: nowrap;
  527. }
  528. @media (max-width: 480px) {
  529. .material-item {
  530. padding: 6px !important;
  531. .material-name {
  532. font-size: 12px !important;
  533. }
  534. }
  535. }
  536. :deep(.van-image__img) {
  537. object-fit: contain !important;
  538. }
  539. </style>