add.html 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>Document</title>
  8. <!-- 引入样式 -->
  9. <link rel="stylesheet" href="../../plugins/element-ui/index.css" />
  10. <link rel="stylesheet" href="../../styles/common.css" />
  11. <link rel="stylesheet" href="../../styles/page.css" />
  12. <style>
  13. .addDish .el-input {
  14. width: 130px;
  15. }
  16. .addDish .el-input-number__increase {
  17. border-left: solid 1px #FFE1CA;
  18. background: #fff3ea;
  19. }
  20. .addDish .el-input-number__decrease {
  21. border-right: solid 1px #FFE1CA;
  22. background: #fff3ea;
  23. }
  24. .addDish input {
  25. border: 1px solid #ffe1ca;
  26. }
  27. .addDish .table {
  28. border: solid 1px #EBEEF5;
  29. border-radius: 3px;
  30. }
  31. .addDish .table th {
  32. padding: 5px 0;
  33. }
  34. .addDish .table td {
  35. padding: 7px 0;
  36. }
  37. .addDishList .seachDish {
  38. position: absolute;
  39. top: 10px;
  40. right: 20px;
  41. }
  42. .addDishList .el-dialog__body {
  43. padding: 0;
  44. border-bottom: solid 1px #ccc;
  45. }
  46. .addDishList .el-dialog__footer {
  47. padding-top: 27px;
  48. }
  49. .addDish {
  50. width: 777px;
  51. }
  52. .addDish .addBut {
  53. background: #ffc200;
  54. display: inline-block;
  55. padding: 0px 20px;
  56. border-radius: 3px;
  57. line-height: 40px;
  58. cursor: pointer;
  59. border-radius: 4px;
  60. color: #333333;
  61. font-weight: 500;
  62. }
  63. .addDish .content {
  64. background: #fafafb;
  65. padding: 20px;
  66. border: solid 1px #ccc;
  67. border-radius: 3px;
  68. }
  69. .addDishCon {
  70. padding: 0 20px;
  71. display: flex;
  72. line-height: 40px;
  73. }
  74. .addDishCon .leftCont {
  75. display: flex;
  76. border-right: solid 2px #E4E7ED;
  77. width: 60%;
  78. padding: 15px;
  79. }
  80. .addDishCon .leftCont .tabBut {
  81. width: 110px;
  82. }
  83. .addDishCon .leftCont .tabBut span {
  84. display: block;
  85. text-align: center;
  86. border-right: solid 2px #f4f4f4;
  87. cursor: pointer;
  88. }
  89. .addDishCon .leftCont .act {
  90. border-color: #FFC200 !important;
  91. color: #FFC200 !important;
  92. }
  93. .addDishCon .leftCont .tabList {
  94. flex: 1;
  95. padding: 15px;
  96. }
  97. .addDishCon .leftCont .tabList .table {
  98. border: solid 1px #f4f4f4;
  99. border-bottom: solid 1px #f4f4f4;
  100. }
  101. .addDishCon .leftCont .tabList .table .items {
  102. border-bottom: solid 1px #f4f4f4;
  103. padding: 0 10px;
  104. display: flex;
  105. }
  106. .addDishCon .leftCont .tabList .table .items .el-checkbox, .addDishCon .leftCont .tabList .table .items .el-checkbox__label {
  107. width: 100%;
  108. }
  109. .addDishCon .leftCont .tabList .table .items .item {
  110. display: flex;
  111. padding-right: 20px;
  112. }
  113. .addDishCon .leftCont .tabList .table .items .item span {
  114. display: inline-block;
  115. text-align: center;
  116. flex: 1;
  117. }
  118. .addDishCon .ritCont {
  119. width: 40%;
  120. padding: 0 15px;
  121. }
  122. .addDishCon .ritCont .item {
  123. box-shadow: 0px 1px 4px 3px rgba(0, 0, 0, 0.03);
  124. display: flex;
  125. text-align: center;
  126. padding: 0 10px;
  127. margin-bottom: 20px;
  128. border-radius: 6px;
  129. color: #818693;
  130. }
  131. .addDishCon .ritCont .item span:first-child {
  132. text-align: left;
  133. color: #20232A;
  134. }
  135. .addDishCon .ritCont .item .price {
  136. display: inline-block;
  137. flex: 1;
  138. }
  139. .addDishCon .ritCont .item .del {
  140. cursor: pointer;
  141. }
  142. .addDishCon .ritCont .item .del img {
  143. position: relative;
  144. top: 5px;
  145. width: 20px;
  146. }
  147. .addDishCon .el-checkbox__label{
  148. width: 100%;
  149. }
  150. #combo-add-app .setmealFood .el-form-item__label::before{
  151. content: '*';
  152. color: #F56C6C;
  153. margin-right: 4px;
  154. }
  155. #combo-add-app .uploadImg .el-form-item__label::before{
  156. content: '*';
  157. color: #F56C6C;
  158. margin-right: 4px;
  159. }
  160. </style>
  161. </head>
  162. <body>
  163. <div class="addBrand-container" id="combo-add-app">
  164. <div class="container">
  165. <el-form
  166. ref="ruleForm"
  167. :model="ruleForm"
  168. :rules="rules"
  169. :inline="true"
  170. label-width="180px"
  171. class="demo-ruleForm"
  172. >
  173. <div>
  174. <el-form-item label="套餐名称:" prop="name" >
  175. <el-input v-model="ruleForm.name" placeholder="请填写套餐名称" maxlength="20"/>
  176. </el-form-item>
  177. <el-form-item label="套餐分类:" prop="idType">
  178. <el-select v-model="ruleForm.idType" placeholder="请选择套餐分类" @change="$forceUpdate()">
  179. <el-option v-for="(item, index) in setMealList" :key="index" :label="item.name" :value="item.id" />
  180. </el-select>
  181. </el-form-item>
  182. </div>
  183. <div>
  184. <el-form-item label="套餐价格:" prop="price">
  185. <el-input v-model="ruleForm.price" placeholder="请设置套餐价格" />
  186. </el-form-item>
  187. </div>
  188. <div>
  189. <el-form-item label="套餐菜品:" class="setmealFood">
  190. <el-form-item>
  191. <div class="addDish">
  192. <span v-if="dishTable.length == 0" class="addBut" @click="openAddDish"> + 添加菜品</span>
  193. <div v-if="dishTable.length != 0" class="content">
  194. <div class="addBut" style="margin-bottom: 20px" @click="openAddDish">+ 添加菜品</div>
  195. <div class="table">
  196. <el-table :data="dishTable" style="width: 100%">
  197. <el-table-column prop="name" label="名称" width="180" align="center"></el-table-column>
  198. <el-table-column prop="price" label="原价" width="180">
  199. <template slot-scope="scope"> {{ Number(scope.row.price) / 100 }} </template>
  200. </el-table-column>
  201. <el-table-column prop="address" label="份数" align="center">
  202. <template slot-scope="scope">
  203. <el-input-number
  204. v-model="scope.row.copies"
  205. size="small"
  206. :min="1"
  207. :max="99"
  208. label="描述文字"
  209. ></el-input-number>
  210. </template>
  211. </el-table-column>
  212. <el-table-column prop="address" label="操作" width="180px;" align="center">
  213. <template slot-scope="scope">
  214. <el-button type="text" size="small" @click="delDishHandle(scope.$index)"> 删除 </el-button>
  215. </template>
  216. </el-table-column>
  217. </el-table>
  218. </div>
  219. </div>
  220. </div>
  221. </el-form-item>
  222. </el-form-item>
  223. </div>
  224. <div>
  225. <el-form-item label="套餐图片:" class="uploadImg">
  226. <el-upload
  227. class="avatar-uploader"
  228. action="/common/upload"
  229. :show-file-list="false"
  230. :on-success="handleAvatarSuccess"
  231. :on-change="onChange"
  232. ref="upload"
  233. >
  234. <img v-if="imageUrl" :src="imageUrl" class="avatar"></img>
  235. <i v-else class="el-icon-plus avatar-uploader-icon"></i>
  236. </el-upload>
  237. </el-form-item>
  238. </div>
  239. <div class="address">
  240. <el-form-item label="套餐描述:">
  241. <el-input v-model="ruleForm.description" type="textarea" :rows="3" placeholder="套餐描述,最长200字" maxlength="200"/>
  242. </el-form-item>
  243. </div>
  244. <div class="subBox address">
  245. <el-form-item>
  246. <el-button @click="goBack()"> 取消 </el-button>
  247. <el-button type="primary" @click="submitForm('ruleForm', false)"> 保存 </el-button>
  248. <el-button
  249. v-if="actionType == 'add'"
  250. type="primary"
  251. class="continue"
  252. @click="submitForm('ruleForm', true)"
  253. >
  254. 保存并继续添加套餐
  255. </el-button>
  256. </el-form-item>
  257. </div>
  258. </el-form>
  259. </div>
  260. <el-dialog
  261. title="添加菜品"
  262. class="addDishList"
  263. :visible.sync="dialogVisible"
  264. width="60%"
  265. :before-close="handleClose"
  266. >
  267. <el-input
  268. v-model="value"
  269. class="seachDish"
  270. placeholder="请输入菜品名称进行搜索"
  271. style="width: 250px"
  272. size="small"
  273. clearable
  274. >
  275. <i slot="prefix" class="el-input__icon el-icon-search" style="cursor: pointer" @click="seachHandle"></i>
  276. </el-input>
  277. <!-- <AddDish ref="adddish" :check-list="checkList" :seach-key="seachKey" @checkList="getCheckList" /> -->
  278. <div class="addDishCon">
  279. <div class="leftCont">
  280. <div
  281. v-show="seachKey.trim() == ''"
  282. class="tabBut"
  283. >
  284. <span
  285. v-for="(item, index) in dishType"
  286. :key="index"
  287. :class="{act:index == keyInd}"
  288. @click="checkTypeHandle(index, item.id)"
  289. >{{ item.name }}</span>
  290. </div>
  291. <div class="tabList">
  292. <div class="table">
  293. <div v-if="dishAddList.length == 0" style="padding-left:10px">
  294. 暂无菜品!
  295. </div>
  296. <el-checkbox-group
  297. v-if="dishAddList.length > 0"
  298. v-model="checkedList"
  299. @change="checkedListHandle"
  300. >
  301. <div
  302. v-for="(item, index) in dishAddList"
  303. :key="index"
  304. class="items"
  305. >
  306. <el-checkbox
  307. :key="index"
  308. :label="item"
  309. >
  310. <div class="item">
  311. <span style="flex: 3;text-align: left">{{ item.dishName }}</span>
  312. <span>{{ item.status == 0 ? '停售' : '在售' }}</span>
  313. <span>{{ Number(item.price)/100 }}</span>
  314. </div>
  315. </el-checkbox>
  316. </div>
  317. </el-checkbox-group>
  318. </div>
  319. </div>
  320. </div>
  321. <div class="ritCont">
  322. <div class="tit">
  323. 已选菜品({{ checkedList.length }})
  324. </div>
  325. <div class="items">
  326. <div
  327. v-for="(item, ind) in checkedList"
  328. :key="ind"
  329. class="item"
  330. >
  331. <span>{{ item.dishName }}</span>
  332. <span class="price">¥ {{ Number(item.price)/100 }} </span>
  333. <span
  334. class="del"
  335. @click="delCheck(ind)"
  336. >
  337. <img
  338. src="../../images/icons/btn_clean@2x.png"
  339. alt=""
  340. >
  341. </span>
  342. </div>
  343. </div>
  344. </div>
  345. </div>
  346. <span slot="footer" class="dialog-footer">
  347. <el-button @click="handleClose">取 消</el-button>
  348. <el-button type="primary" @click="addTableList">确 定</el-button>
  349. </span>
  350. </el-dialog>
  351. </div>
  352. <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  353. <script src="../../plugins/vue/vue.js"></script>
  354. <!-- 引入组件库 -->
  355. <script src="../../plugins/element-ui/index.js"></script>
  356. <!-- 引入axios -->
  357. <script src="../../plugins/axios/axios.min.js"></script>
  358. <script src="../../js/request.js"></script>
  359. <script src="../../api/combo.js"></script>
  360. <script src="../../js/validate.js"></script>
  361. <script src="../../js/index.js"></script>
  362. <script src="../../api/food.js"></script>
  363. <script>
  364. new Vue({
  365. el: '#combo-add-app',
  366. data() {
  367. return {
  368. id: '',
  369. actionType: '',
  370. value: '',
  371. setMealList: [],
  372. seachKey: '',
  373. dishList: [],
  374. imageUrl: '',
  375. actionType: '',
  376. dishTable: [],
  377. dialogVisible: false,
  378. checkList: [],
  379. ruleForm: {
  380. name: '',
  381. categoryId: '',
  382. price: '',
  383. code: '',
  384. image: '',
  385. description: '',
  386. dishList: [],
  387. status: true,
  388. idType: '',
  389. },
  390. dishType: [],
  391. dishAddList: [],
  392. dishListCache: [],
  393. keyInd : 0,
  394. searchValue: '',
  395. checkedList: []
  396. }
  397. },
  398. computed: {
  399. rules() {
  400. return {
  401. name: {
  402. required: true,
  403. message: '请输入套餐名称',
  404. trigger: 'blur',
  405. },
  406. idType: {
  407. required: true,
  408. message: '请选择套餐分类',
  409. trigger: 'change',
  410. },
  411. price: {
  412. required: true,
  413. // 'message': '请输入套餐价格',
  414. validator: (rules, value, callback) => {
  415. if (!value) {
  416. callback(new Error('请填写菜品价格'))
  417. } else {
  418. const reg = /^\d+(\.\d{0,2})?$/
  419. if (reg.test(value)) {
  420. if(value < 10000){
  421. callback()
  422. }else{
  423. callback(new Error('菜品价格小于10000'))
  424. }
  425. } else {
  426. callback(new Error('菜品价格格式只能为数字,且最多保留两位小数'))
  427. }
  428. }
  429. },
  430. trigger: 'blur',
  431. },
  432. }
  433. },
  434. },
  435. watch:{
  436. seachKey(value){
  437. if (value.trim()){
  438. this.getDishForName(this.seachKey)
  439. }
  440. },
  441. checkList(value){
  442. this.checkedList = value
  443. }
  444. },
  445. created() {
  446. this.getDishTypeList()
  447. this.getDishType()
  448. this.id = requestUrlParam('id')
  449. this.actionType = this.id ? 'edit' : 'add'
  450. if (this.id) {
  451. this.init()
  452. }
  453. },
  454. mounted() {},
  455. methods: {
  456. async init() {
  457. querySetmealById(this.id).then((res) => {
  458. if (String(res.code) === '1') {
  459. this.ruleForm = res.data
  460. this.ruleForm.status = res.data.status === '1'
  461. this.ruleForm.price = res.data.price / 100
  462. this.imageUrl = `/common/download?name=${res.data.image}`
  463. this.checkList = res.data.setmealDishes
  464. this.dishTable = res.data.setmealDishes
  465. this.ruleForm.idType = res.data.categoryId
  466. // this.ruleForm.password = ''
  467. } else {
  468. this.$message.error(res.msg || '操作失败')
  469. }
  470. })
  471. },
  472. seachHandle() {
  473. this.seachKey = this.value
  474. },
  475. // 获取套餐分类
  476. getDishTypeList() {
  477. getCategoryList({ type: 2, page: 1, pageSize: 1000 }).then((res) => {
  478. if (res.code === 1) {
  479. this.setMealList = res.data.map((obj) => ({ ...obj, idType: obj.id }))
  480. } else {
  481. this.$message.error(res.msg || '操作失败')
  482. }
  483. })
  484. },
  485. // 删除套餐菜品
  486. delDishHandle(index) {
  487. this.dishTable.splice(index, 1)
  488. this.checkList.splice(index, 1)
  489. },
  490. // 获取添加菜品数据
  491. getCheckList(value) {
  492. this.checkList = [...value]
  493. },
  494. // 添加菜品
  495. openAddDish() {
  496. this.seachKey = ''
  497. this.dialogVisible = true
  498. //搜索条件清空,菜品重新查询,菜品类别选第一个重新查询
  499. this.value = ''
  500. this.keyInd = 0
  501. this.getDishList(this.dishType[0].id)
  502. },
  503. // 取消添加菜品
  504. handleClose(done) {
  505. // this.$refs.adddish.close()
  506. this.dialogVisible = false
  507. // this.checkList = JSON.parse(JSON.stringify(this.dishTable))
  508. // this.dialogVisible = false
  509. },
  510. // 保存添加菜品列表
  511. addTableList() {
  512. this.dishTable = JSON.parse(JSON.stringify(this.checkList))
  513. this.dishTable.forEach((n) => {
  514. n.copies = 1
  515. })
  516. this.dialogVisible = false
  517. // 添加处理逻辑清空选中list
  518. this.checkList = []
  519. },
  520. submitForm(formName, st) {
  521. this.$refs[formName].validate((valid) => {
  522. if (valid) {
  523. let prams = { ...this.ruleForm }
  524. prams.price *= 100
  525. prams.setmealDishes = this.dishTable.map((obj) => ({
  526. copies: obj.copies,
  527. dishId: obj.dishId,
  528. name: obj.name,
  529. price: obj.price,
  530. }))
  531. prams.status = this.ruleForm ? 1 : 0
  532. prams.categoryId = this.ruleForm.idType
  533. if(prams.setmealDishes.length < 1){
  534. this.$message.error('请选择菜品!')
  535. return
  536. }
  537. if(!this.imageUrl){
  538. this.$message.error('请上传套餐图片')
  539. return
  540. }
  541. // delete prams.dishList
  542. if (this.actionType == 'add') {
  543. delete prams.id
  544. addSetmeal(prams)
  545. .then((res) => {
  546. if (res.code === 1) {
  547. this.$message.success('套餐添加成功!')
  548. if (!st) {
  549. this.goBack()
  550. } else {
  551. this.$refs.ruleForm.resetFields()
  552. this.dishList = []
  553. this.dishTable = []
  554. this.ruleForm = {
  555. name: '',
  556. categoryId: '',
  557. price: '',
  558. code: '',
  559. image: '',
  560. description: '',
  561. dishList: [],
  562. status: true,
  563. id: '',
  564. idType: '',
  565. }
  566. this.imageUrl = ''
  567. }
  568. } else {
  569. this.$message.error(res.msg || '操作失败')
  570. }
  571. })
  572. .catch((err) => {
  573. this.$message.error('请求出错了:' + err)
  574. })
  575. } else {
  576. delete prams.updateTime
  577. editSetmeal(prams)
  578. .then((res) => {
  579. if (res.code === 1) {
  580. this.$message.success('套餐修改成功!')
  581. this.goBack()
  582. } else {
  583. this.$message.error(res.msg || '操作失败')
  584. }
  585. })
  586. .catch((err) => {
  587. this.$message.error('请求出错了:' + err)
  588. })
  589. }
  590. } else {
  591. return false
  592. }
  593. })
  594. },
  595. handleAvatarSuccess (response, file, fileList) {
  596. // this.imageUrl = response.data
  597. if(response.code === 0 && response.msg === '未登录'){
  598. window.top.location.href = '/backend/page/login/login.html'
  599. }else{
  600. this.imageUrl = `/common/download?name=${response.data}`
  601. this.ruleForm.image = response.data
  602. }
  603. },
  604. onChange (file) {
  605. if(file){
  606. const suffix = file.name.split('.')[1]
  607. const size = file.size / 1024 / 1024 < 2
  608. if(['png','jpeg','jpg'].indexOf(suffix) < 0){
  609. this.$message.error('上传图片只支持 png、jpeg、jpg 格式!')
  610. this.$refs.upload.clearFiles()
  611. return false
  612. }
  613. if(!size){
  614. this.$message.error('上传文件大小不能超过 2MB!')
  615. return false
  616. }
  617. return file
  618. }
  619. },
  620. goBack() {
  621. window.parent.menuHandle(
  622. {
  623. id: '5',
  624. url: '/backend/page/combo/list.html',
  625. name: '套餐管理',
  626. },
  627. false
  628. )
  629. },
  630. // 获取套餐分类
  631. getDishType () {
  632. getCategoryList({'type':1}).then(res => {
  633. if (res.code === 1) {
  634. this.dishType = res.data
  635. this.getDishList(res.data[0].id)
  636. } else {
  637. this.$message.error(res.msg)
  638. }
  639. })
  640. },
  641. // 通过套餐ID获取菜品列表分类
  642. getDishList (id) {
  643. queryDishList({categoryId: id}).then(res => {
  644. if (res.code === 1) {
  645. if (res.data.length == 0) {
  646. this.dishAddList = []
  647. return
  648. }
  649. let newArr = res.data;
  650. newArr.forEach((n) => {
  651. n.dishId = n.id
  652. n.copies = 1
  653. // n.dishCopies = 1
  654. n.dishName = n.name
  655. })
  656. this.dishAddList = newArr
  657. } else {
  658. this.$message.error(res.msg)
  659. }
  660. })
  661. },
  662. // 关键词收搜菜品列表分类
  663. getDishForName (name) {
  664. queryDishList({name}).then(res => {
  665. if (res.code === 1) {
  666. let newArr = res.data
  667. newArr.forEach((n) => {
  668. n.dishId = n.id
  669. n.dishName = n.name
  670. })
  671. this.dishAddList = newArr
  672. } else {
  673. this.$message.error(res.msg)
  674. }
  675. })
  676. },
  677. checkTypeHandle (ind,id) {
  678. this.keyInd = ind
  679. this.getDishList(id)
  680. },
  681. checkedListHandle (value) {
  682. this.getCheckList(this.checkedList)
  683. },
  684. open (done) {
  685. this.dishListCache = JSON.parse(JSON.stringify(this.checkList))
  686. },
  687. close (done) {
  688. this.checkList = this.dishListCache
  689. },
  690. // 删除
  691. delCheck (ind){
  692. this.checkedList.splice(ind, 1)
  693. }
  694. },
  695. })
  696. </script>
  697. </body>
  698. </html>