add.html 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  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. .selectInput {
  14. position: relative;
  15. width: 100%;
  16. min-width: 100px;
  17. }
  18. .selectInput .flavorSelect {
  19. position: absolute;
  20. width: 100%;
  21. padding: 0 10px;
  22. border-radius: 3px;
  23. border: solid 1px #FF903D;
  24. line-height: 30px;
  25. text-align: center;
  26. background: #fff;
  27. top: 50px;
  28. z-index: 99;
  29. }
  30. .selectInput .flavorSelect .items {
  31. cursor: pointer;
  32. display: inline-block;
  33. width: 100%;
  34. line-height: 35px;
  35. border-bottom: solid 1px #f4f4f4;
  36. color: #666;
  37. }
  38. .selectInput .flavorSelect .none {
  39. font-size: 14px;
  40. }
  41. #food-add-app .uploadImg .el-form-item__label::before{
  42. content: '*';
  43. color: #F56C6C;
  44. margin-right: 4px;
  45. }
  46. </style>
  47. </head>
  48. <body>
  49. <div class="addBrand-container" id="food-add-app">
  50. <div class="container">
  51. <el-form
  52. ref="ruleForm"
  53. :model="ruleForm"
  54. :rules="rules"
  55. :inline="true"
  56. label-width="180px"
  57. class="demo-ruleForm"
  58. >
  59. <div>
  60. <el-form-item
  61. label="菜品名称:"
  62. prop="name"
  63. >
  64. <el-input
  65. v-model="ruleForm.name"
  66. placeholder="请填写菜品名称"
  67. maxlength="20"
  68. />
  69. </el-form-item>
  70. <el-form-item
  71. label="菜品分类:"
  72. prop="categoryId"
  73. >
  74. <el-select
  75. v-model="ruleForm.categoryId"
  76. placeholder="请选择菜品分类"
  77. >
  78. <el-option v-for="(item,index) in dishList" :key="index" :label="item.name" :value="item.id" />
  79. </el-select>
  80. </el-form-item>
  81. </div>
  82. <div>
  83. <el-form-item
  84. label="菜品价格:"
  85. prop="price"
  86. >
  87. <el-input
  88. v-model="ruleForm.price"
  89. placeholder="请设置菜品价格"
  90. />
  91. </el-form-item>
  92. </div>
  93. <el-form-item label="口味做法配置:">
  94. <el-form-item>
  95. <div class="flavorBox">
  96. <span
  97. v-if="dishFlavors.length == 0"
  98. class="addBut"
  99. @click="addFlavore"
  100. > + 添加口味</span>
  101. <div
  102. v-if="dishFlavors.length != 0"
  103. class="flavor"
  104. >
  105. <div class="title">
  106. <span>口味名(3个字内)</span><span>口味标签(输入标签回车添加)</span>
  107. </div>
  108. <div class="cont">
  109. <div
  110. v-for="(item, index) in dishFlavors"
  111. :key="index"
  112. class="items"
  113. >
  114. <div class="itTit">
  115. <!-- <SelectInput
  116. :dish-flavors-data="dishFlavorsData"
  117. :index="index"
  118. :value="item.name"
  119. @select="selectHandle"
  120. /> -->
  121. <div class="selectInput">
  122. <div>
  123. <el-input
  124. v-model="item.name"
  125. type="text"
  126. style="width: 100%"
  127. placeholder="请输入口味"
  128. @focus="selectFlavor(true,index)"
  129. @blur="outSelect(false,index)"
  130. @input="inputHandle(index)"
  131. />
  132. </div>
  133. <div v-show="item.showOption" class="flavorSelect">
  134. <span
  135. v-for="(it, ind) in dishFlavorsData"
  136. :key="ind"
  137. class="items"
  138. @click="checkOption(it,ind,index)"
  139. >{{ it.name }}</span>
  140. <span
  141. v-if="dishFlavorsData == []"
  142. class="none"
  143. >无数据</span>
  144. </div>
  145. </div>
  146. </div>
  147. <div
  148. class="labItems"
  149. style="display: flex"
  150. >
  151. <span
  152. v-for="(it, ind) in item.value"
  153. :key="ind"
  154. >{{ it }} <i @click="delFlavorLabel(index, ind)">X</i></span>
  155. <div
  156. class="inputBox"
  157. :style="inputStyle"
  158. contenteditable="true"
  159. @focus="flavorPosition(index)"
  160. @keydown.enter="(val)=>keyDownHandle(val,index)"
  161. ></div>
  162. </div>
  163. <span
  164. class="delFlavor delBut non"
  165. @click="delFlavor(index)"
  166. >删除</span>
  167. </div>
  168. </div>
  169. <div
  170. class="addBut"
  171. @click="addFlavore"
  172. >
  173. 添加口味
  174. </div>
  175. </div>
  176. </div>
  177. </el-form-item>
  178. </el-form-item>
  179. <div>
  180. </div>
  181. <div>
  182. <el-form-item
  183. label="菜品图片:"
  184. prop="region"
  185. class="uploadImg"
  186. >
  187. <el-upload
  188. class="avatar-uploader"
  189. action="/common/upload"
  190. :show-file-list="false"
  191. :on-success="handleAvatarSuccess"
  192. :on-change="onChange"
  193. ref="upload"
  194. >
  195. <img
  196. v-if="imageUrl"
  197. :src="imageUrl"
  198. class="avatar"
  199. ></img>
  200. <i
  201. v-else
  202. class="el-icon-plus avatar-uploader-icon"
  203. ></i>
  204. </el-upload>
  205. </el-form-item>
  206. </div>
  207. <div class="address">
  208. <el-form-item
  209. label="菜品描述:"
  210. prop="region"
  211. >
  212. <el-input
  213. v-model="ruleForm.description"
  214. type="textarea"
  215. :rows="3"
  216. placeholder="菜品描述,最长200字"
  217. maxlength="200"
  218. />
  219. </el-form-item>
  220. </div>
  221. <div class="subBox address">
  222. <el-form-item>
  223. <el-button @click="goBack()">
  224. 取消
  225. </el-button>
  226. <el-button
  227. type="primary"
  228. @click="submitForm('ruleForm')"
  229. >
  230. 保存
  231. </el-button>
  232. <el-button
  233. v-if="actionType == 'add'"
  234. type="primary"
  235. class="continue"
  236. @click="submitForm('ruleForm','goAnd')"
  237. >
  238. 保存并继续添加菜品
  239. </el-button>
  240. </el-form-item>
  241. </div>
  242. </el-form>
  243. </div>
  244. </div>
  245. <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  246. <script src="../../plugins/vue/vue.js"></script>
  247. <!-- 引入组件库 -->
  248. <script src="../../plugins/element-ui/index.js"></script>
  249. <!-- 引入axios -->
  250. <script src="../../plugins/axios/axios.min.js"></script>
  251. <script src="../../js/request.js"></script>
  252. <script src="../../js/validate.js"></script>
  253. <script src="../../js/index.js"></script>
  254. <script src="../../api/food.js"></script>
  255. <script>
  256. new Vue({
  257. el: '#food-add-app',
  258. data() {
  259. return {
  260. id: '',
  261. restKey: 0,
  262. textarea: '',
  263. value: '',
  264. imageUrl: '',
  265. actionType: '',
  266. dishList: [],
  267. dishFlavorsData: [],
  268. dishFlavors: [],
  269. vueRest : '1',
  270. index : 0,
  271. inputStyle : {'flex':1},
  272. ruleForm : {
  273. 'name': '',
  274. 'id': '',
  275. 'price': '',
  276. 'code': '',
  277. 'image': '',
  278. 'description': '',
  279. 'dishFlavors': [],
  280. 'status': true,
  281. categoryId: ''
  282. },
  283. mak: false
  284. }
  285. },
  286. computed: {
  287. rules () {
  288. return {
  289. 'name': [
  290. {'required': true, 'message': '请填写菜品名称', 'trigger': 'blur'}
  291. ],
  292. 'categoryId': [
  293. {'required': true, 'message': '请选择菜品分类', 'trigger': 'change'}
  294. ],
  295. 'price': [
  296. {
  297. 'required': true,
  298. // 'message': '请填写菜品价格',
  299. validator: (rules, value, callback) => {
  300. if (!value) {
  301. callback(new Error('请填写菜品价格'))
  302. } else {
  303. const reg = /^\d+(\.\d{0,2})?$/
  304. if (reg.test(value)) {
  305. if(value < 10000){
  306. callback()
  307. }else{
  308. callback(new Error('菜品价格小于10000'))
  309. }
  310. } else {
  311. callback(new Error('菜品价格格式只能为数字,且最多保留两位小数'))
  312. }
  313. }
  314. },
  315. 'trigger': 'blur'
  316. }
  317. ],
  318. }
  319. }
  320. },
  321. created() {
  322. this.getDishList()
  323. // 口味临时数据
  324. this.getFlavorListHand()
  325. this.id = requestUrlParam('id')
  326. this.actionType = this.id ? 'edit' : 'add'
  327. if (this.id) {
  328. this.init()
  329. }
  330. },
  331. mounted() {
  332. },
  333. methods: {
  334. async init () {
  335. queryDishById(this.id).then(res => {
  336. console.log(res)
  337. if (String(res.code) === '1') {
  338. this.ruleForm = { ...res.data }
  339. this.ruleForm.price = String(res.data.price/100)
  340. this.ruleForm.status = res.data.status == '1'
  341. this.dishFlavors = res.data.flavors && res.data.flavors.map(obj => ({ ...obj, value: JSON.parse(obj.value),showOption: false }))
  342. console.log('this.dishFlavors',this.dishFlavors)
  343. // this.ruleForm.id = res.data.data.categoryId
  344. // this.imageUrl = res.data.data.image
  345. this.imageUrl = `/common/download?name=${res.data.image}`
  346. } else {
  347. this.$message.error(res.msg || '操作失败')
  348. }
  349. })
  350. },
  351. // 按钮 - 添加口味
  352. addFlavore () {
  353. this.dishFlavors.push({'name': '', 'value': [], showOption: false}) // JSON.parse(JSON.stringify(this.dishFlavorsData))
  354. },
  355. // 按钮 - 删除口味
  356. delFlavor (ind) {
  357. this.dishFlavors.splice(ind, 1)
  358. },
  359. // 按钮 - 删除口味标签
  360. delFlavorLabel (index, ind) {
  361. this.dishFlavors[index].value.splice(ind, 1)
  362. },
  363. //口味位置记录
  364. flavorPosition (index) {
  365. this.index = index
  366. },
  367. // 添加口味标签
  368. keyDownHandle (val,index) {
  369. console.log('keyDownHandle----val',val)
  370. console.log('keyDownHandle----index',index)
  371. console.log('keyDownHandle----this.dishFlavors',this.dishFlavors)
  372. if (event) {
  373. event.cancelBubble = true
  374. event.preventDefault()
  375. event.stopPropagation()
  376. }
  377. if (val.target.innerText.trim() != '') {
  378. this.dishFlavors[index].value.push(val.target.innerText)
  379. val.target.innerText = ''
  380. }
  381. },
  382. // 获取菜品分类
  383. getDishList () {
  384. getCategoryList({ 'type': 1 }).then(res => {
  385. if (res.code === 1) {
  386. this.dishList = res.data
  387. } else {
  388. this.$message.error(res.msg || '操作失败')
  389. }
  390. })
  391. },
  392. // 获取口味列表
  393. getFlavorListHand () {
  394. // flavor flavorData
  395. this.dishFlavorsData = [
  396. {'name':'甜味','value':['无糖','少糖','半糖','多糖','全糖']},
  397. {'name':'温度','value':['热饮','常温','去冰','少冰','多冰']},
  398. {'name':'忌口','value':['不要葱','不要蒜','不要香菜','不要辣']},
  399. {'name':'辣度','value':['不辣','微辣','中辣','重辣']}
  400. ]
  401. },
  402. selectFlavor(st,index){
  403. console.log('st',st)
  404. console.log('index',index)
  405. console.log('this.dishFlavors',this.dishFlavors)
  406. const obj = JSON.parse(JSON.stringify(this.dishFlavors[index]))
  407. obj.showOption = st
  408. this.dishFlavors.splice(index,1,obj)
  409. // this.dishFlavors[index].showOption = st
  410. },
  411. outSelect(st,index){
  412. const _this = this
  413. setTimeout(()=> {
  414. const obj = JSON.parse(JSON.stringify(_this.dishFlavors[index]))
  415. obj.showOption = st
  416. _this.dishFlavors.splice(index,1,obj)
  417. }, 200)
  418. },
  419. inputHandle(val,index){
  420. // this.selectFlavor(false,index)
  421. },
  422. checkOption(val, ind, index){
  423. this.selectHandle(val.name, index, ind)
  424. this.dishFlavors[index].name = val.name
  425. },
  426. selectHandle(val, key, ind){
  427. const arrDate = [...this.dishFlavors]
  428. arrDate[key] = JSON.parse(JSON.stringify(this.dishFlavorsData[ind]))
  429. this.dishFlavors = arrDate
  430. },
  431. submitForm(formName, st) {
  432. this.$refs[formName].validate((valid) => {
  433. if (valid) {
  434. let params = {...this.ruleForm}
  435. // params.flavors = this.dishFlavors
  436. params.status = this.ruleForm ? 1 : 0
  437. params.price *= 100
  438. params.categoryId = this.ruleForm.categoryId
  439. params.flavors = this.dishFlavors.map(obj => ({ ...obj, value: JSON.stringify(obj.value) }))
  440. delete params.dishFlavors
  441. if(!this.imageUrl){
  442. this.$message.error('请上传菜品图片')
  443. return
  444. }
  445. if (this.actionType == 'add') {
  446. delete params.id
  447. addDish(params).then(res => {
  448. if (res.code === 1) {
  449. this.$message.success('菜品添加成功!')
  450. if (!st) {
  451. this.goBack()
  452. } else {
  453. this.dishFlavors = []
  454. // this.dishFlavorsData = []
  455. this.imageUrl = ''
  456. this.ruleForm = {
  457. 'name': '',
  458. 'id': '',
  459. 'price': '',
  460. 'code': '',
  461. 'image': '',
  462. 'description': '',
  463. 'dishFlavors': [],
  464. 'status': true,
  465. categoryId: ''
  466. }
  467. }
  468. } else {
  469. this.$message.error(res.msg || '操作失败')
  470. }
  471. }).catch(err => {
  472. this.$message.error('请求出错了:' + err)
  473. })
  474. } else {
  475. delete params.updateTime
  476. editDish(params).then(res => {
  477. if (res.code === 1) {
  478. this.$message.success('菜品修改成功!')
  479. this.goBack()
  480. } else {
  481. this.$message.error(res.msg || '操作失败')
  482. }
  483. }).catch(err => {
  484. this.$message.error('请求出错了:' + err)
  485. })
  486. }
  487. } else {
  488. return false
  489. }
  490. })
  491. },
  492. handleAvatarSuccess (response, file, fileList) {
  493. // 拼接down接口预览
  494. if(response.code === 0 && response.msg === '未登录'){
  495. window.top.location.href = '/backend/page/login/login.html'
  496. }else{
  497. this.imageUrl = `/common/download?name=${response.data}`
  498. this.ruleForm.image = response.data
  499. }
  500. },
  501. onChange (file) {
  502. if(file){
  503. const suffix = file.name.split('.')[1]
  504. const size = file.size / 1024 / 1024 < 2
  505. if(['png','jpeg','jpg'].indexOf(suffix) < 0){
  506. this.$message.error('上传图片只支持 png、jpeg、jpg 格式!')
  507. this.$refs.upload.clearFiles()
  508. return false
  509. }
  510. if(!size){
  511. this.$message.error('上传文件大小不能超过 2MB!')
  512. return false
  513. }
  514. return file
  515. }
  516. },
  517. goBack(){
  518. window.parent.menuHandle({
  519. id: '4',
  520. url: '/backend/page/food/list.html',
  521. name: '菜品管理'
  522. },false)
  523. }
  524. }
  525. })
  526. </script>
  527. </body>
  528. </html>